2
0

spice-qemu-char.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include "config-host.h"
  2. #include "trace.h"
  3. #include "ui/qemu-spice.h"
  4. #include <spice.h>
  5. #include <spice-experimental.h>
  6. #include <spice/protocol.h>
  7. #include "osdep.h"
  8. #define dprintf(_scd, _level, _fmt, ...) \
  9. do { \
  10. static unsigned __dprintf_counter = 0; \
  11. if (_scd->debug >= _level) { \
  12. fprintf(stderr, "scd: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
  13. } \
  14. } while (0)
  15. typedef struct SpiceCharDriver {
  16. CharDriverState* chr;
  17. SpiceCharDeviceInstance sin;
  18. char *subtype;
  19. bool active;
  20. uint8_t *buffer;
  21. uint8_t *datapos;
  22. ssize_t bufsize, datalen;
  23. uint32_t debug;
  24. QLIST_ENTRY(SpiceCharDriver) next;
  25. } SpiceCharDriver;
  26. static QLIST_HEAD(, SpiceCharDriver) spice_chars =
  27. QLIST_HEAD_INITIALIZER(spice_chars);
  28. static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
  29. {
  30. SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
  31. ssize_t out = 0;
  32. ssize_t last_out;
  33. uint8_t* p = (uint8_t*)buf;
  34. while (len > 0) {
  35. last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
  36. if (last_out <= 0) {
  37. break;
  38. }
  39. qemu_chr_be_write(scd->chr, p, last_out);
  40. out += last_out;
  41. len -= last_out;
  42. p += last_out;
  43. }
  44. dprintf(scd, 3, "%s: %zu/%zd\n", __func__, out, len + out);
  45. trace_spice_vmc_write(out, len + out);
  46. return out;
  47. }
  48. static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
  49. {
  50. SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
  51. int bytes = MIN(len, scd->datalen);
  52. dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
  53. if (bytes > 0) {
  54. memcpy(buf, scd->datapos, bytes);
  55. scd->datapos += bytes;
  56. scd->datalen -= bytes;
  57. assert(scd->datalen >= 0);
  58. if (scd->datalen == 0) {
  59. scd->datapos = 0;
  60. }
  61. }
  62. trace_spice_vmc_read(bytes, len);
  63. return bytes;
  64. }
  65. #if SPICE_SERVER_VERSION >= 0x000c02
  66. static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
  67. {
  68. SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
  69. int chr_event;
  70. switch (event) {
  71. case SPICE_PORT_EVENT_BREAK:
  72. chr_event = CHR_EVENT_BREAK;
  73. break;
  74. default:
  75. dprintf(scd, 2, "%s: unknown %d\n", __func__, event);
  76. return;
  77. }
  78. dprintf(scd, 2, "%s: %d\n", __func__, event);
  79. trace_spice_vmc_event(chr_event);
  80. qemu_chr_be_event(scd->chr, chr_event);
  81. }
  82. #endif
  83. static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
  84. {
  85. SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
  86. #if SPICE_SERVER_VERSION < 0x000901
  87. /*
  88. * spice-server calls the state callback for the agent channel when the
  89. * spice client connects / disconnects. Given that not the client but
  90. * the server is doing the parsing of the messages this is wrong as the
  91. * server is still listening. Worse, this causes the parser in the server
  92. * to go out of sync, so we ignore state calls for subtype vdagent
  93. * spicevmc chardevs. For the full story see:
  94. * http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
  95. */
  96. if (strcmp(sin->subtype, "vdagent") == 0) {
  97. return;
  98. }
  99. #endif
  100. if ((scd->chr->opened && connected) ||
  101. (!scd->chr->opened && !connected)) {
  102. return;
  103. }
  104. qemu_chr_be_event(scd->chr,
  105. connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED);
  106. }
  107. static SpiceCharDeviceInterface vmc_interface = {
  108. .base.type = SPICE_INTERFACE_CHAR_DEVICE,
  109. .base.description = "spice virtual channel char device",
  110. .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
  111. .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
  112. .state = vmc_state,
  113. .write = vmc_write,
  114. .read = vmc_read,
  115. #if SPICE_SERVER_VERSION >= 0x000c02
  116. .event = vmc_event,
  117. #endif
  118. };
  119. static void vmc_register_interface(SpiceCharDriver *scd)
  120. {
  121. if (scd->active) {
  122. return;
  123. }
  124. dprintf(scd, 1, "%s\n", __func__);
  125. scd->sin.base.sif = &vmc_interface.base;
  126. qemu_spice_add_interface(&scd->sin.base);
  127. scd->active = true;
  128. trace_spice_vmc_register_interface(scd);
  129. }
  130. static void vmc_unregister_interface(SpiceCharDriver *scd)
  131. {
  132. if (!scd->active) {
  133. return;
  134. }
  135. dprintf(scd, 1, "%s\n", __func__);
  136. spice_server_remove_interface(&scd->sin.base);
  137. scd->active = false;
  138. trace_spice_vmc_unregister_interface(scd);
  139. }
  140. static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
  141. {
  142. SpiceCharDriver *s = chr->opaque;
  143. dprintf(s, 2, "%s: %d\n", __func__, len);
  144. vmc_register_interface(s);
  145. assert(s->datalen == 0);
  146. if (s->bufsize < len) {
  147. s->bufsize = len;
  148. s->buffer = g_realloc(s->buffer, s->bufsize);
  149. }
  150. memcpy(s->buffer, buf, len);
  151. s->datapos = s->buffer;
  152. s->datalen = len;
  153. spice_server_char_device_wakeup(&s->sin);
  154. return len;
  155. }
  156. static void spice_chr_close(struct CharDriverState *chr)
  157. {
  158. SpiceCharDriver *s = chr->opaque;
  159. printf("%s\n", __func__);
  160. vmc_unregister_interface(s);
  161. QLIST_REMOVE(s, next);
  162. g_free(s);
  163. }
  164. static void spice_chr_guest_open(struct CharDriverState *chr)
  165. {
  166. SpiceCharDriver *s = chr->opaque;
  167. vmc_register_interface(s);
  168. }
  169. static void spice_chr_guest_close(struct CharDriverState *chr)
  170. {
  171. SpiceCharDriver *s = chr->opaque;
  172. vmc_unregister_interface(s);
  173. }
  174. static void print_allowed_subtypes(void)
  175. {
  176. const char** psubtype;
  177. int i;
  178. fprintf(stderr, "allowed names: ");
  179. for(i=0, psubtype = spice_server_char_device_recognized_subtypes();
  180. *psubtype != NULL; ++psubtype, ++i) {
  181. if (i == 0) {
  182. fprintf(stderr, "%s", *psubtype);
  183. } else {
  184. fprintf(stderr, ", %s", *psubtype);
  185. }
  186. }
  187. fprintf(stderr, "\n");
  188. }
  189. static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
  190. {
  191. CharDriverState *chr;
  192. SpiceCharDriver *s;
  193. uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
  194. chr = g_malloc0(sizeof(CharDriverState));
  195. s = g_malloc0(sizeof(SpiceCharDriver));
  196. s->chr = chr;
  197. s->debug = debug;
  198. s->active = false;
  199. s->sin.subtype = subtype;
  200. chr->opaque = s;
  201. chr->chr_write = spice_chr_write;
  202. chr->chr_close = spice_chr_close;
  203. chr->chr_guest_open = spice_chr_guest_open;
  204. chr->chr_guest_close = spice_chr_guest_close;
  205. QLIST_INSERT_HEAD(&spice_chars, s, next);
  206. return chr;
  207. }
  208. CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
  209. {
  210. CharDriverState *chr;
  211. const char *name = qemu_opt_get(opts, "name");
  212. const char **psubtype = spice_server_char_device_recognized_subtypes();
  213. const char *subtype = NULL;
  214. if (name == NULL) {
  215. fprintf(stderr, "spice-qemu-char: missing name parameter\n");
  216. print_allowed_subtypes();
  217. return NULL;
  218. }
  219. for(;*psubtype != NULL; ++psubtype) {
  220. if (strcmp(name, *psubtype) == 0) {
  221. subtype = *psubtype;
  222. break;
  223. }
  224. }
  225. if (subtype == NULL) {
  226. fprintf(stderr, "spice-qemu-char: unsupported name: %s\n", name);
  227. print_allowed_subtypes();
  228. return NULL;
  229. }
  230. chr = chr_open(opts, subtype);
  231. #if SPICE_SERVER_VERSION < 0x000901
  232. /* See comment in vmc_state() */
  233. if (strcmp(subtype, "vdagent") == 0) {
  234. qemu_chr_generic_open(chr);
  235. }
  236. #endif
  237. return chr;
  238. }
  239. #if SPICE_SERVER_VERSION >= 0x000c02
  240. CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts)
  241. {
  242. CharDriverState *chr;
  243. SpiceCharDriver *s;
  244. const char *name = qemu_opt_get(opts, "name");
  245. if (name == NULL) {
  246. fprintf(stderr, "spice-qemu-char: missing name parameter\n");
  247. return NULL;
  248. }
  249. chr = chr_open(opts, "port");
  250. s = chr->opaque;
  251. s->sin.portname = name;
  252. return chr;
  253. }
  254. void qemu_spice_register_ports(void)
  255. {
  256. SpiceCharDriver *s;
  257. QLIST_FOREACH(s, &spice_chars, next) {
  258. if (s->sin.portname == NULL) {
  259. continue;
  260. }
  261. vmc_register_interface(s);
  262. }
  263. }
  264. #endif