spice-qemu-char.c 9.4 KB

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