spice.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. #include "qemu/osdep.h"
  2. #include "trace.h"
  3. #include "ui/qemu-spice.h"
  4. #include "chardev/char.h"
  5. #include "chardev/spice.h"
  6. #include "qapi/error.h"
  7. #include "qemu/error-report.h"
  8. #include "qemu/module.h"
  9. #include "qemu/option.h"
  10. #include <spice/protocol.h>
  11. typedef struct SpiceCharSource {
  12. GSource source;
  13. SpiceChardev *scd;
  14. } SpiceCharSource;
  15. static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
  16. {
  17. SpiceChardev *scd = container_of(sin, SpiceChardev, sin);
  18. Chardev *chr = CHARDEV(scd);
  19. ssize_t out = 0;
  20. ssize_t last_out;
  21. uint8_t* p = (uint8_t*)buf;
  22. while (len > 0) {
  23. int can_write = qemu_chr_be_can_write(chr);
  24. last_out = MIN(len, can_write);
  25. if (last_out <= 0) {
  26. break;
  27. }
  28. qemu_chr_be_write(chr, p, last_out);
  29. out += last_out;
  30. len -= last_out;
  31. p += last_out;
  32. }
  33. trace_spice_vmc_write(out, len + out);
  34. return out;
  35. }
  36. static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
  37. {
  38. SpiceChardev *scd = container_of(sin, SpiceChardev, sin);
  39. int bytes = MIN(len, scd->datalen);
  40. if (bytes > 0) {
  41. memcpy(buf, scd->datapos, bytes);
  42. scd->datapos += bytes;
  43. scd->datalen -= bytes;
  44. assert(scd->datalen >= 0);
  45. }
  46. if (scd->datalen == 0) {
  47. scd->datapos = 0;
  48. scd->blocked = false;
  49. }
  50. trace_spice_vmc_read(bytes, len);
  51. return bytes;
  52. }
  53. static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
  54. {
  55. SpiceChardev *scd = container_of(sin, SpiceChardev, sin);
  56. Chardev *chr = CHARDEV(scd);
  57. int chr_event;
  58. switch (event) {
  59. case SPICE_PORT_EVENT_BREAK:
  60. chr_event = CHR_EVENT_BREAK;
  61. break;
  62. default:
  63. return;
  64. }
  65. trace_spice_vmc_event(chr_event);
  66. qemu_chr_be_event(chr, chr_event);
  67. }
  68. static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
  69. {
  70. SpiceChardev *scd = container_of(sin, SpiceChardev, sin);
  71. Chardev *chr = CHARDEV(scd);
  72. if ((chr->be_open && connected) ||
  73. (!chr->be_open && !connected)) {
  74. return;
  75. }
  76. qemu_chr_be_event(chr,
  77. connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED);
  78. }
  79. static SpiceCharDeviceInterface vmc_interface = {
  80. .base.type = SPICE_INTERFACE_CHAR_DEVICE,
  81. .base.description = "spice virtual channel char device",
  82. .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
  83. .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
  84. .state = vmc_state,
  85. .write = vmc_write,
  86. .read = vmc_read,
  87. .event = vmc_event,
  88. .flags = SPICE_CHAR_DEVICE_NOTIFY_WRITABLE,
  89. };
  90. static void vmc_register_interface(SpiceChardev *scd)
  91. {
  92. if (scd->active) {
  93. return;
  94. }
  95. scd->sin.base.sif = &vmc_interface.base;
  96. qemu_spice.add_interface(&scd->sin.base);
  97. scd->active = true;
  98. trace_spice_vmc_register_interface(scd);
  99. }
  100. static void vmc_unregister_interface(SpiceChardev *scd)
  101. {
  102. if (!scd->active) {
  103. return;
  104. }
  105. spice_server_remove_interface(&scd->sin.base);
  106. scd->active = false;
  107. trace_spice_vmc_unregister_interface(scd);
  108. }
  109. static gboolean spice_char_source_prepare(GSource *source, gint *timeout)
  110. {
  111. SpiceCharSource *src = (SpiceCharSource *)source;
  112. Chardev *chr = CHARDEV(src->scd);
  113. *timeout = -1;
  114. if (!chr->be_open) {
  115. return true;
  116. }
  117. return !src->scd->blocked;
  118. }
  119. static gboolean spice_char_source_check(GSource *source)
  120. {
  121. SpiceCharSource *src = (SpiceCharSource *)source;
  122. Chardev *chr = CHARDEV(src->scd);
  123. if (!chr->be_open) {
  124. return true;
  125. }
  126. return !src->scd->blocked;
  127. }
  128. static gboolean spice_char_source_dispatch(GSource *source,
  129. GSourceFunc callback, gpointer user_data)
  130. {
  131. SpiceCharSource *src = (SpiceCharSource *)source;
  132. Chardev *chr = CHARDEV(src->scd);
  133. GIOFunc func = (GIOFunc)callback;
  134. GIOCondition cond = chr->be_open ? G_IO_OUT : G_IO_HUP;
  135. return func(NULL, cond, user_data);
  136. }
  137. static GSourceFuncs SpiceCharSourceFuncs = {
  138. .prepare = spice_char_source_prepare,
  139. .check = spice_char_source_check,
  140. .dispatch = spice_char_source_dispatch,
  141. };
  142. static GSource *spice_chr_add_watch(Chardev *chr, GIOCondition cond)
  143. {
  144. SpiceChardev *scd = SPICE_CHARDEV(chr);
  145. SpiceCharSource *src;
  146. assert(cond & G_IO_OUT);
  147. src = (SpiceCharSource *)g_source_new(&SpiceCharSourceFuncs,
  148. sizeof(SpiceCharSource));
  149. src->scd = scd;
  150. return (GSource *)src;
  151. }
  152. static int spice_chr_write(Chardev *chr, const uint8_t *buf, int len)
  153. {
  154. SpiceChardev *s = SPICE_CHARDEV(chr);
  155. int read_bytes;
  156. assert(s->datalen == 0);
  157. if (!chr->be_open) {
  158. trace_spice_chr_discard_write(len);
  159. return len;
  160. }
  161. s->datapos = buf;
  162. s->datalen = len;
  163. spice_server_char_device_wakeup(&s->sin);
  164. read_bytes = len - s->datalen;
  165. if (read_bytes != len) {
  166. /* We'll get passed in the unconsumed data with the next call */
  167. s->datalen = 0;
  168. s->datapos = NULL;
  169. s->blocked = true;
  170. }
  171. return read_bytes;
  172. }
  173. static void char_spice_finalize(Object *obj)
  174. {
  175. SpiceChardev *s = SPICE_CHARDEV(obj);
  176. vmc_unregister_interface(s);
  177. g_free((char *)s->sin.subtype);
  178. g_free((char *)s->sin.portname);
  179. }
  180. static void spice_vmc_set_fe_open(struct Chardev *chr, int fe_open)
  181. {
  182. SpiceChardev *s = SPICE_CHARDEV(chr);
  183. if (fe_open) {
  184. vmc_register_interface(s);
  185. } else {
  186. vmc_unregister_interface(s);
  187. }
  188. }
  189. static void spice_port_set_fe_open(struct Chardev *chr, int fe_open)
  190. {
  191. SpiceChardev *s = SPICE_CHARDEV(chr);
  192. if (fe_open) {
  193. spice_server_port_event(&s->sin, SPICE_PORT_EVENT_OPENED);
  194. } else {
  195. spice_server_port_event(&s->sin, SPICE_PORT_EVENT_CLOSED);
  196. }
  197. }
  198. static void spice_chr_accept_input(struct Chardev *chr)
  199. {
  200. SpiceChardev *s = SPICE_CHARDEV(chr);
  201. spice_server_char_device_wakeup(&s->sin);
  202. }
  203. static void chr_open(Chardev *chr, const char *subtype)
  204. {
  205. SpiceChardev *s = SPICE_CHARDEV(chr);
  206. s->active = false;
  207. s->sin.subtype = g_strdup(subtype);
  208. }
  209. static void qemu_chr_open_spice_vmc(Chardev *chr,
  210. ChardevBackend *backend,
  211. bool *be_opened,
  212. Error **errp)
  213. {
  214. ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data;
  215. const char *type = spicevmc->type;
  216. const char **psubtype = spice_server_char_device_recognized_subtypes();
  217. for (; *psubtype != NULL; ++psubtype) {
  218. if (strcmp(type, *psubtype) == 0) {
  219. break;
  220. }
  221. }
  222. if (*psubtype == NULL) {
  223. char *subtypes = g_strjoinv(", ",
  224. (gchar **)spice_server_char_device_recognized_subtypes());
  225. error_setg(errp, "unsupported type name: %s", type);
  226. error_append_hint(errp, "allowed spice char type names: %s\n",
  227. subtypes);
  228. g_free(subtypes);
  229. return;
  230. }
  231. *be_opened = false;
  232. #if SPICE_SERVER_VERSION < 0x000e02
  233. /* Spice < 0.14.2 doesn't explicitly open smartcard chardev */
  234. if (strcmp(type, "smartcard") == 0) {
  235. *be_opened = true;
  236. }
  237. #endif
  238. chr_open(chr, type);
  239. }
  240. static void qemu_chr_open_spice_port(Chardev *chr,
  241. ChardevBackend *backend,
  242. bool *be_opened,
  243. Error **errp)
  244. {
  245. ChardevSpicePort *spiceport = backend->u.spiceport.data;
  246. const char *name = spiceport->fqdn;
  247. SpiceChardev *s;
  248. if (name == NULL) {
  249. error_setg(errp, "missing name parameter");
  250. return;
  251. }
  252. if (!using_spice) {
  253. error_setg(errp, "spice not enabled");
  254. return;
  255. }
  256. chr_open(chr, "port");
  257. *be_opened = false;
  258. s = SPICE_CHARDEV(chr);
  259. s->sin.portname = g_strdup(name);
  260. vmc_register_interface(s);
  261. }
  262. static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend,
  263. Error **errp)
  264. {
  265. const char *name = qemu_opt_get(opts, "name");
  266. ChardevSpiceChannel *spicevmc;
  267. if (name == NULL) {
  268. error_setg(errp, "chardev: spice channel: no name given");
  269. return;
  270. }
  271. backend->type = CHARDEV_BACKEND_KIND_SPICEVMC;
  272. spicevmc = backend->u.spicevmc.data = g_new0(ChardevSpiceChannel, 1);
  273. qemu_chr_parse_common(opts, qapi_ChardevSpiceChannel_base(spicevmc));
  274. spicevmc->type = g_strdup(name);
  275. }
  276. static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
  277. Error **errp)
  278. {
  279. const char *name = qemu_opt_get(opts, "name");
  280. ChardevSpicePort *spiceport;
  281. if (name == NULL) {
  282. error_setg(errp, "chardev: spice port: no name given");
  283. return;
  284. }
  285. backend->type = CHARDEV_BACKEND_KIND_SPICEPORT;
  286. spiceport = backend->u.spiceport.data = g_new0(ChardevSpicePort, 1);
  287. qemu_chr_parse_common(opts, qapi_ChardevSpicePort_base(spiceport));
  288. spiceport->fqdn = g_strdup(name);
  289. }
  290. static void char_spice_class_init(ObjectClass *oc, void *data)
  291. {
  292. ChardevClass *cc = CHARDEV_CLASS(oc);
  293. cc->chr_write = spice_chr_write;
  294. cc->chr_add_watch = spice_chr_add_watch;
  295. cc->chr_accept_input = spice_chr_accept_input;
  296. }
  297. static const TypeInfo char_spice_type_info = {
  298. .name = TYPE_CHARDEV_SPICE,
  299. .parent = TYPE_CHARDEV,
  300. .instance_size = sizeof(SpiceChardev),
  301. .instance_finalize = char_spice_finalize,
  302. .class_init = char_spice_class_init,
  303. .abstract = true,
  304. };
  305. module_obj(TYPE_CHARDEV_SPICE);
  306. static void char_spicevmc_class_init(ObjectClass *oc, void *data)
  307. {
  308. ChardevClass *cc = CHARDEV_CLASS(oc);
  309. cc->parse = qemu_chr_parse_spice_vmc;
  310. cc->open = qemu_chr_open_spice_vmc;
  311. cc->chr_set_fe_open = spice_vmc_set_fe_open;
  312. }
  313. static const TypeInfo char_spicevmc_type_info = {
  314. .name = TYPE_CHARDEV_SPICEVMC,
  315. .parent = TYPE_CHARDEV_SPICE,
  316. .class_init = char_spicevmc_class_init,
  317. };
  318. module_obj(TYPE_CHARDEV_SPICEVMC);
  319. static void char_spiceport_class_init(ObjectClass *oc, void *data)
  320. {
  321. ChardevClass *cc = CHARDEV_CLASS(oc);
  322. cc->parse = qemu_chr_parse_spice_port;
  323. cc->open = qemu_chr_open_spice_port;
  324. cc->chr_set_fe_open = spice_port_set_fe_open;
  325. }
  326. static const TypeInfo char_spiceport_type_info = {
  327. .name = TYPE_CHARDEV_SPICEPORT,
  328. .parent = TYPE_CHARDEV_SPICE,
  329. .class_init = char_spiceport_class_init,
  330. };
  331. module_obj(TYPE_CHARDEV_SPICEPORT);
  332. static void register_types(void)
  333. {
  334. type_register_static(&char_spice_type_info);
  335. type_register_static(&char_spicevmc_type_info);
  336. type_register_static(&char_spiceport_type_info);
  337. }
  338. type_init(register_types);
  339. module_dep("ui-spice-core");