]> git.proxmox.com Git - mirror_qemu.git/blob - hw/usb/dev-mtp.c
usb-mtp: Introduce write support for MTP objects
[mirror_qemu.git] / hw / usb / dev-mtp.c
1 /*
2 * Media Transfer Protocol implementation, backed by host filesystem.
3 *
4 * Copyright Red Hat, Inc 2014
5 *
6 * Author:
7 * Gerd Hoffmann <kraxel@redhat.com>
8 *
9 * This code is licensed under the GPL v2 or later.
10 */
11
12 #include "qemu/osdep.h"
13 #include "qapi/error.h"
14 #include <wchar.h>
15 #include <dirent.h>
16
17 #include <sys/statvfs.h>
18 #ifdef CONFIG_INOTIFY1
19 #include <sys/inotify.h>
20 #include "qemu/main-loop.h"
21 #endif
22
23 #include "qemu-common.h"
24 #include "qemu/iov.h"
25 #include "trace.h"
26 #include "hw/usb.h"
27 #include "hw/usb/desc.h"
28
29 /* ----------------------------------------------------------------------- */
30
31 enum mtp_container_type {
32 TYPE_COMMAND = 1,
33 TYPE_DATA = 2,
34 TYPE_RESPONSE = 3,
35 TYPE_EVENT = 4,
36 };
37
38 enum mtp_code {
39 /* command codes */
40 CMD_GET_DEVICE_INFO = 0x1001,
41 CMD_OPEN_SESSION = 0x1002,
42 CMD_CLOSE_SESSION = 0x1003,
43 CMD_GET_STORAGE_IDS = 0x1004,
44 CMD_GET_STORAGE_INFO = 0x1005,
45 CMD_GET_NUM_OBJECTS = 0x1006,
46 CMD_GET_OBJECT_HANDLES = 0x1007,
47 CMD_GET_OBJECT_INFO = 0x1008,
48 CMD_GET_OBJECT = 0x1009,
49 CMD_DELETE_OBJECT = 0x100b,
50 CMD_SEND_OBJECT = 0x100d,
51 CMD_GET_PARTIAL_OBJECT = 0x101b,
52 CMD_GET_OBJECT_PROPS_SUPPORTED = 0x9801,
53 CMD_GET_OBJECT_PROP_DESC = 0x9802,
54 CMD_GET_OBJECT_PROP_VALUE = 0x9803,
55
56 /* response codes */
57 RES_OK = 0x2001,
58 RES_GENERAL_ERROR = 0x2002,
59 RES_SESSION_NOT_OPEN = 0x2003,
60 RES_INVALID_TRANSACTION_ID = 0x2004,
61 RES_OPERATION_NOT_SUPPORTED = 0x2005,
62 RES_PARAMETER_NOT_SUPPORTED = 0x2006,
63 RES_INCOMPLETE_TRANSFER = 0x2007,
64 RES_INVALID_STORAGE_ID = 0x2008,
65 RES_INVALID_OBJECT_HANDLE = 0x2009,
66 RES_INVALID_OBJECT_FORMAT_CODE = 0x200b,
67 RES_STORE_FULL = 0x200c,
68 RES_STORE_READ_ONLY = 0x200e,
69 RES_PARTIAL_DELETE = 0x2012,
70 RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014,
71 RES_INVALID_OBJECTINFO = 0x2015,
72 RES_INVALID_PARENT_OBJECT = 0x201a,
73 RES_INVALID_PARAMETER = 0x201d,
74 RES_SESSION_ALREADY_OPEN = 0x201e,
75 RES_INVALID_OBJECT_PROP_CODE = 0xA801,
76
77 /* format codes */
78 FMT_UNDEFINED_OBJECT = 0x3000,
79 FMT_ASSOCIATION = 0x3001,
80
81 /* event codes */
82 EVT_OBJ_ADDED = 0x4002,
83 EVT_OBJ_REMOVED = 0x4003,
84 EVT_OBJ_INFO_CHANGED = 0x4007,
85
86 /* object properties */
87 PROP_STORAGE_ID = 0xDC01,
88 PROP_OBJECT_FORMAT = 0xDC02,
89 PROP_OBJECT_COMPRESSED_SIZE = 0xDC04,
90 PROP_PARENT_OBJECT = 0xDC0B,
91 PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER = 0xDC41,
92 PROP_NAME = 0xDC44,
93 };
94
95 enum mtp_data_type {
96 DATA_TYPE_UINT16 = 0x0004,
97 DATA_TYPE_UINT32 = 0x0006,
98 DATA_TYPE_UINT64 = 0x0008,
99 DATA_TYPE_UINT128 = 0x000a,
100 DATA_TYPE_STRING = 0xffff,
101 };
102
103 typedef struct {
104 uint32_t length;
105 uint16_t type;
106 uint16_t code;
107 uint32_t trans;
108 } QEMU_PACKED mtp_container;
109
110 /* ----------------------------------------------------------------------- */
111
112 typedef struct MTPState MTPState;
113 typedef struct MTPControl MTPControl;
114 typedef struct MTPData MTPData;
115 typedef struct MTPObject MTPObject;
116
117 enum {
118 EP_DATA_IN = 1,
119 EP_DATA_OUT,
120 EP_EVENT,
121 };
122
123 #ifdef CONFIG_INOTIFY1
124 typedef struct MTPMonEntry MTPMonEntry;
125
126 struct MTPMonEntry {
127 uint32_t event;
128 uint32_t handle;
129
130 QTAILQ_ENTRY(MTPMonEntry) next;
131 };
132 #endif
133
134 struct MTPControl {
135 uint16_t code;
136 uint32_t trans;
137 int argc;
138 uint32_t argv[5];
139 };
140
141 struct MTPData {
142 uint16_t code;
143 uint32_t trans;
144 uint64_t offset;
145 uint64_t length;
146 uint32_t alloc;
147 uint8_t *data;
148 bool first;
149 int fd;
150 };
151
152 struct MTPObject {
153 uint32_t handle;
154 uint16_t format;
155 char *name;
156 char *path;
157 struct stat stat;
158 #ifdef CONFIG_INOTIFY1
159 /* inotify watch cookie */
160 int watchfd;
161 #endif
162 MTPObject *parent;
163 uint32_t nchildren;
164 QLIST_HEAD(, MTPObject) children;
165 QLIST_ENTRY(MTPObject) list;
166 bool have_children;
167 QTAILQ_ENTRY(MTPObject) next;
168 };
169
170 struct MTPState {
171 USBDevice dev;
172 char *root;
173 char *desc;
174 uint32_t flags;
175
176 MTPData *data_in;
177 MTPData *data_out;
178 MTPControl *result;
179 uint32_t session;
180 uint32_t next_handle;
181 bool readonly;
182
183 QTAILQ_HEAD(, MTPObject) objects;
184 #ifdef CONFIG_INOTIFY1
185 /* inotify descriptor */
186 int inotifyfd;
187 QTAILQ_HEAD(events, MTPMonEntry) events;
188 #endif
189 /* Responder is expecting a write operation */
190 bool write_pending;
191 struct {
192 uint32_t parent_handle;
193 uint16_t format;
194 uint32_t size;
195 char *filename;
196 } dataset;
197 };
198
199 #define TYPE_USB_MTP "usb-mtp"
200 #define USB_MTP(obj) OBJECT_CHECK(MTPState, (obj), TYPE_USB_MTP)
201
202 #define QEMU_STORAGE_ID 0x00010001
203
204 #define MTP_FLAG_WRITABLE 0
205
206 #define FLAG_SET(_mtp, _flag) ((_mtp)->flags & (1 << (_flag)))
207
208 /* ----------------------------------------------------------------------- */
209
210 #define MTP_MANUFACTURER "QEMU"
211 #define MTP_PRODUCT "QEMU filesharing"
212
213 enum {
214 STR_MANUFACTURER = 1,
215 STR_PRODUCT,
216 STR_SERIALNUMBER,
217 STR_MTP,
218 STR_CONFIG_FULL,
219 STR_CONFIG_HIGH,
220 STR_CONFIG_SUPER,
221 };
222
223 static const USBDescStrings desc_strings = {
224 [STR_MANUFACTURER] = MTP_MANUFACTURER,
225 [STR_PRODUCT] = MTP_PRODUCT,
226 [STR_SERIALNUMBER] = "34617",
227 [STR_MTP] = "MTP",
228 [STR_CONFIG_FULL] = "Full speed config (usb 1.1)",
229 [STR_CONFIG_HIGH] = "High speed config (usb 2.0)",
230 [STR_CONFIG_SUPER] = "Super speed config (usb 3.0)",
231 };
232
233 static const USBDescIface desc_iface_full = {
234 .bInterfaceNumber = 0,
235 .bNumEndpoints = 3,
236 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
237 .bInterfaceSubClass = 0x01,
238 .bInterfaceProtocol = 0x01,
239 .iInterface = STR_MTP,
240 .eps = (USBDescEndpoint[]) {
241 {
242 .bEndpointAddress = USB_DIR_IN | EP_DATA_IN,
243 .bmAttributes = USB_ENDPOINT_XFER_BULK,
244 .wMaxPacketSize = 64,
245 },{
246 .bEndpointAddress = USB_DIR_OUT | EP_DATA_OUT,
247 .bmAttributes = USB_ENDPOINT_XFER_BULK,
248 .wMaxPacketSize = 64,
249 },{
250 .bEndpointAddress = USB_DIR_IN | EP_EVENT,
251 .bmAttributes = USB_ENDPOINT_XFER_INT,
252 .wMaxPacketSize = 64,
253 .bInterval = 0x0a,
254 },
255 }
256 };
257
258 static const USBDescDevice desc_device_full = {
259 .bcdUSB = 0x0200,
260 .bMaxPacketSize0 = 8,
261 .bNumConfigurations = 1,
262 .confs = (USBDescConfig[]) {
263 {
264 .bNumInterfaces = 1,
265 .bConfigurationValue = 1,
266 .iConfiguration = STR_CONFIG_FULL,
267 .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
268 .bMaxPower = 2,
269 .nif = 1,
270 .ifs = &desc_iface_full,
271 },
272 },
273 };
274
275 static const USBDescIface desc_iface_high = {
276 .bInterfaceNumber = 0,
277 .bNumEndpoints = 3,
278 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
279 .bInterfaceSubClass = 0x01,
280 .bInterfaceProtocol = 0x01,
281 .iInterface = STR_MTP,
282 .eps = (USBDescEndpoint[]) {
283 {
284 .bEndpointAddress = USB_DIR_IN | EP_DATA_IN,
285 .bmAttributes = USB_ENDPOINT_XFER_BULK,
286 .wMaxPacketSize = 512,
287 },{
288 .bEndpointAddress = USB_DIR_OUT | EP_DATA_OUT,
289 .bmAttributes = USB_ENDPOINT_XFER_BULK,
290 .wMaxPacketSize = 512,
291 },{
292 .bEndpointAddress = USB_DIR_IN | EP_EVENT,
293 .bmAttributes = USB_ENDPOINT_XFER_INT,
294 .wMaxPacketSize = 64,
295 .bInterval = 0x0a,
296 },
297 }
298 };
299
300 static const USBDescDevice desc_device_high = {
301 .bcdUSB = 0x0200,
302 .bMaxPacketSize0 = 64,
303 .bNumConfigurations = 1,
304 .confs = (USBDescConfig[]) {
305 {
306 .bNumInterfaces = 1,
307 .bConfigurationValue = 1,
308 .iConfiguration = STR_CONFIG_HIGH,
309 .bmAttributes = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
310 .bMaxPower = 2,
311 .nif = 1,
312 .ifs = &desc_iface_high,
313 },
314 },
315 };
316
317 static const USBDescMSOS desc_msos = {
318 .CompatibleID = "MTP",
319 .SelectiveSuspendEnabled = true,
320 };
321
322 static const USBDesc desc = {
323 .id = {
324 .idVendor = 0x46f4, /* CRC16() of "QEMU" */
325 .idProduct = 0x0004,
326 .bcdDevice = 0,
327 .iManufacturer = STR_MANUFACTURER,
328 .iProduct = STR_PRODUCT,
329 .iSerialNumber = STR_SERIALNUMBER,
330 },
331 .full = &desc_device_full,
332 .high = &desc_device_high,
333 .str = desc_strings,
334 .msos = &desc_msos,
335 };
336
337 /* ----------------------------------------------------------------------- */
338
339 static MTPObject *usb_mtp_object_alloc(MTPState *s, uint32_t handle,
340 MTPObject *parent, char *name)
341 {
342 MTPObject *o = g_new0(MTPObject, 1);
343
344 if (name[0] == '.') {
345 goto ignore;
346 }
347
348 o->handle = handle;
349 o->parent = parent;
350 o->name = g_strdup(name);
351 if (parent == NULL) {
352 o->path = g_strdup(name);
353 } else {
354 o->path = g_strdup_printf("%s/%s", parent->path, name);
355 }
356
357 if (lstat(o->path, &o->stat) != 0) {
358 goto ignore;
359 }
360 if (S_ISREG(o->stat.st_mode)) {
361 o->format = FMT_UNDEFINED_OBJECT;
362 } else if (S_ISDIR(o->stat.st_mode)) {
363 o->format = FMT_ASSOCIATION;
364 } else {
365 goto ignore;
366 }
367
368 if (access(o->path, R_OK) != 0) {
369 goto ignore;
370 }
371
372 trace_usb_mtp_object_alloc(s->dev.addr, o->handle, o->path);
373
374 QTAILQ_INSERT_TAIL(&s->objects, o, next);
375 return o;
376
377 ignore:
378 g_free(o->name);
379 g_free(o->path);
380 g_free(o);
381 return NULL;
382 }
383
384 static void usb_mtp_object_free(MTPState *s, MTPObject *o)
385 {
386 MTPObject *iter;
387
388 if (!o) {
389 return;
390 }
391
392 trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path);
393
394 QTAILQ_REMOVE(&s->objects, o, next);
395 if (o->parent) {
396 QLIST_REMOVE(o, list);
397 o->parent->nchildren--;
398 }
399
400 while (!QLIST_EMPTY(&o->children)) {
401 iter = QLIST_FIRST(&o->children);
402 usb_mtp_object_free(s, iter);
403 }
404 g_free(o->name);
405 g_free(o->path);
406 g_free(o);
407 }
408
409 static MTPObject *usb_mtp_object_lookup(MTPState *s, uint32_t handle)
410 {
411 MTPObject *o;
412
413 QTAILQ_FOREACH(o, &s->objects, next) {
414 if (o->handle == handle) {
415 return o;
416 }
417 }
418 return NULL;
419 }
420
421 static MTPObject *usb_mtp_add_child(MTPState *s, MTPObject *o,
422 char *name)
423 {
424 MTPObject *child =
425 usb_mtp_object_alloc(s, s->next_handle++, o, name);
426
427 if (child) {
428 trace_usb_mtp_add_child(s->dev.addr, child->handle, child->path);
429 QLIST_INSERT_HEAD(&o->children, child, list);
430 o->nchildren++;
431
432 if (child->format == FMT_ASSOCIATION) {
433 QLIST_INIT(&child->children);
434 }
435 }
436
437 return child;
438 }
439
440 #ifdef CONFIG_INOTIFY1
441 static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent,
442 char *name, int len)
443 {
444 MTPObject *iter;
445
446 QLIST_FOREACH(iter, &parent->children, list) {
447 if (strncmp(iter->name, name, len) == 0) {
448 return iter;
449 }
450 }
451
452 return NULL;
453 }
454
455 static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd)
456 {
457 MTPObject *iter;
458
459 QTAILQ_FOREACH(iter, &s->objects, next) {
460 if (iter->watchfd == wd) {
461 return iter;
462 }
463 }
464
465 return NULL;
466 }
467
468 static void inotify_watchfn(void *arg)
469 {
470 MTPState *s = arg;
471 ssize_t bytes;
472 /* From the man page: atleast one event can be read */
473 int pos;
474 char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
475
476 for (;;) {
477 bytes = read(s->inotifyfd, buf, sizeof(buf));
478 pos = 0;
479
480 if (bytes <= 0) {
481 /* Better luck next time */
482 return;
483 }
484
485 /*
486 * TODO: Ignore initiator initiated events.
487 * For now we are good because the store is RO
488 */
489 while (bytes > 0) {
490 char *p = buf + pos;
491 struct inotify_event *event = (struct inotify_event *)p;
492 int watchfd = 0;
493 uint32_t mask = event->mask & (IN_CREATE | IN_DELETE |
494 IN_MODIFY | IN_IGNORED);
495 MTPObject *parent = usb_mtp_object_lookup_wd(s, event->wd);
496 MTPMonEntry *entry = NULL;
497 MTPObject *o;
498
499 pos = pos + sizeof(struct inotify_event) + event->len;
500 bytes = bytes - pos;
501
502 if (!parent) {
503 continue;
504 }
505
506 switch (mask) {
507 case IN_CREATE:
508 if (usb_mtp_object_lookup_name
509 (parent, event->name, event->len)) {
510 /* Duplicate create event */
511 continue;
512 }
513 entry = g_new0(MTPMonEntry, 1);
514 entry->handle = s->next_handle;
515 entry->event = EVT_OBJ_ADDED;
516 o = usb_mtp_add_child(s, parent, event->name);
517 if (!o) {
518 g_free(entry);
519 continue;
520 }
521 o->watchfd = watchfd;
522 trace_usb_mtp_inotify_event(s->dev.addr, event->name,
523 event->mask, "Obj Added");
524 break;
525
526 case IN_DELETE:
527 /*
528 * The kernel issues a IN_IGNORED event
529 * when a dir containing a watchpoint is
530 * deleted, so we don't have to delete the
531 * watchpoint
532 */
533 o = usb_mtp_object_lookup_name(parent, event->name, event->len);
534 if (!o) {
535 continue;
536 }
537 entry = g_new0(MTPMonEntry, 1);
538 entry->handle = o->handle;
539 entry->event = EVT_OBJ_REMOVED;
540 trace_usb_mtp_inotify_event(s->dev.addr, o->path,
541 event->mask, "Obj Deleted");
542 usb_mtp_object_free(s, o);
543 break;
544
545 case IN_MODIFY:
546 o = usb_mtp_object_lookup_name(parent, event->name, event->len);
547 if (!o) {
548 continue;
549 }
550 entry = g_new0(MTPMonEntry, 1);
551 entry->handle = o->handle;
552 entry->event = EVT_OBJ_INFO_CHANGED;
553 trace_usb_mtp_inotify_event(s->dev.addr, o->path,
554 event->mask, "Obj Modified");
555 break;
556
557 case IN_IGNORED:
558 trace_usb_mtp_inotify_event(s->dev.addr, parent->path,
559 event->mask, "Obj parent dir ignored");
560 break;
561
562 default:
563 fprintf(stderr, "usb-mtp: failed to parse inotify event\n");
564 continue;
565 }
566
567 if (entry) {
568 QTAILQ_INSERT_HEAD(&s->events, entry, next);
569 }
570 }
571 }
572 }
573
574 static int usb_mtp_inotify_init(MTPState *s)
575 {
576 int fd;
577
578 fd = inotify_init1(IN_NONBLOCK);
579 if (fd == -1) {
580 return 1;
581 }
582
583 QTAILQ_INIT(&s->events);
584 s->inotifyfd = fd;
585
586 qemu_set_fd_handler(fd, inotify_watchfn, NULL, s);
587
588 return 0;
589 }
590
591 static void usb_mtp_inotify_cleanup(MTPState *s)
592 {
593 MTPMonEntry *e, *p;
594
595 if (!s->inotifyfd) {
596 return;
597 }
598
599 qemu_set_fd_handler(s->inotifyfd, NULL, NULL, s);
600 close(s->inotifyfd);
601
602 QTAILQ_FOREACH_SAFE(e, &s->events, next, p) {
603 QTAILQ_REMOVE(&s->events, e, next);
604 g_free(e);
605 }
606 }
607
608 static int usb_mtp_add_watch(int inotifyfd, char *path)
609 {
610 uint32_t mask = IN_CREATE | IN_DELETE | IN_MODIFY |
611 IN_ISDIR;
612
613 return inotify_add_watch(inotifyfd, path, mask);
614 }
615 #endif
616
617 static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
618 {
619 struct dirent *entry;
620 DIR *dir;
621
622 if (o->have_children) {
623 return;
624 }
625 o->have_children = true;
626
627 dir = opendir(o->path);
628 if (!dir) {
629 return;
630 }
631 #ifdef CONFIG_INOTIFY1
632 int watchfd = usb_mtp_add_watch(s->inotifyfd, o->path);
633 if (watchfd == -1) {
634 fprintf(stderr, "usb-mtp: failed to add watch for %s\n", o->path);
635 } else {
636 trace_usb_mtp_inotify_event(s->dev.addr, o->path,
637 0, "Watch Added");
638 o->watchfd = watchfd;
639 }
640 #endif
641 while ((entry = readdir(dir)) != NULL) {
642 usb_mtp_add_child(s, o, entry->d_name);
643 }
644 closedir(dir);
645 }
646
647 /* ----------------------------------------------------------------------- */
648
649 static MTPData *usb_mtp_data_alloc(MTPControl *c)
650 {
651 MTPData *data = g_new0(MTPData, 1);
652
653 data->code = c->code;
654 data->trans = c->trans;
655 data->fd = -1;
656 data->first = true;
657 return data;
658 }
659
660 static void usb_mtp_data_free(MTPData *data)
661 {
662 if (data == NULL) {
663 return;
664 }
665 if (data->fd != -1) {
666 close(data->fd);
667 }
668 g_free(data->data);
669 g_free(data);
670 }
671
672 static void usb_mtp_realloc(MTPData *data, uint32_t bytes)
673 {
674 if (data->length + bytes <= data->alloc) {
675 return;
676 }
677 data->alloc = (data->length + bytes + 0xff) & ~0xff;
678 data->data = g_realloc(data->data, data->alloc);
679 }
680
681 static void usb_mtp_add_u8(MTPData *data, uint8_t val)
682 {
683 usb_mtp_realloc(data, 1);
684 data->data[data->length++] = val;
685 }
686
687 static void usb_mtp_add_u16(MTPData *data, uint16_t val)
688 {
689 usb_mtp_realloc(data, 2);
690 data->data[data->length++] = (val >> 0) & 0xff;
691 data->data[data->length++] = (val >> 8) & 0xff;
692 }
693
694 static void usb_mtp_add_u32(MTPData *data, uint32_t val)
695 {
696 usb_mtp_realloc(data, 4);
697 data->data[data->length++] = (val >> 0) & 0xff;
698 data->data[data->length++] = (val >> 8) & 0xff;
699 data->data[data->length++] = (val >> 16) & 0xff;
700 data->data[data->length++] = (val >> 24) & 0xff;
701 }
702
703 static void usb_mtp_add_u64(MTPData *data, uint64_t val)
704 {
705 usb_mtp_realloc(data, 8);
706 data->data[data->length++] = (val >> 0) & 0xff;
707 data->data[data->length++] = (val >> 8) & 0xff;
708 data->data[data->length++] = (val >> 16) & 0xff;
709 data->data[data->length++] = (val >> 24) & 0xff;
710 data->data[data->length++] = (val >> 32) & 0xff;
711 data->data[data->length++] = (val >> 40) & 0xff;
712 data->data[data->length++] = (val >> 48) & 0xff;
713 data->data[data->length++] = (val >> 56) & 0xff;
714 }
715
716 static void usb_mtp_add_u16_array(MTPData *data, uint32_t len,
717 const uint16_t *vals)
718 {
719 int i;
720
721 usb_mtp_add_u32(data, len);
722 for (i = 0; i < len; i++) {
723 usb_mtp_add_u16(data, vals[i]);
724 }
725 }
726
727 static void usb_mtp_add_u32_array(MTPData *data, uint32_t len,
728 const uint32_t *vals)
729 {
730 int i;
731
732 usb_mtp_add_u32(data, len);
733 for (i = 0; i < len; i++) {
734 usb_mtp_add_u32(data, vals[i]);
735 }
736 }
737
738 static void usb_mtp_add_wstr(MTPData *data, const wchar_t *str)
739 {
740 uint32_t len = wcslen(str);
741 int i;
742
743 if (len > 0) {
744 len++; /* include terminating L'\0' */
745 }
746
747 usb_mtp_add_u8(data, len);
748 for (i = 0; i < len; i++) {
749 usb_mtp_add_u16(data, str[i]);
750 }
751 }
752
753 static void usb_mtp_add_str(MTPData *data, const char *str)
754 {
755 uint32_t len = strlen(str)+1;
756 wchar_t *wstr = g_new(wchar_t, len);
757 size_t ret;
758
759 ret = mbstowcs(wstr, str, len);
760 if (ret == -1) {
761 usb_mtp_add_wstr(data, L"Oops");
762 } else {
763 usb_mtp_add_wstr(data, wstr);
764 }
765
766 g_free(wstr);
767 }
768
769 static void usb_mtp_add_time(MTPData *data, time_t time)
770 {
771 char buf[16];
772 struct tm tm;
773
774 gmtime_r(&time, &tm);
775 strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", &tm);
776 usb_mtp_add_str(data, buf);
777 }
778
779 /* ----------------------------------------------------------------------- */
780
781 static void usb_mtp_queue_result(MTPState *s, uint16_t code, uint32_t trans,
782 int argc, uint32_t arg0, uint32_t arg1,
783 uint32_t arg2)
784 {
785 MTPControl *c = g_new0(MTPControl, 1);
786
787 c->code = code;
788 c->trans = trans;
789 c->argc = argc;
790 if (argc > 0) {
791 c->argv[0] = arg0;
792 }
793 if (argc > 1) {
794 c->argv[1] = arg1;
795 }
796 if (argc > 2) {
797 c->argv[2] = arg2;
798 }
799
800 assert(s->result == NULL);
801 s->result = c;
802 }
803
804 /* ----------------------------------------------------------------------- */
805
806 static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c)
807 {
808 static const uint16_t ops[] = {
809 CMD_GET_DEVICE_INFO,
810 CMD_OPEN_SESSION,
811 CMD_CLOSE_SESSION,
812 CMD_GET_STORAGE_IDS,
813 CMD_GET_STORAGE_INFO,
814 CMD_GET_NUM_OBJECTS,
815 CMD_GET_OBJECT_HANDLES,
816 CMD_GET_OBJECT_INFO,
817 CMD_DELETE_OBJECT,
818 CMD_SEND_OBJECT,
819 CMD_GET_OBJECT,
820 CMD_GET_PARTIAL_OBJECT,
821 CMD_GET_OBJECT_PROPS_SUPPORTED,
822 CMD_GET_OBJECT_PROP_DESC,
823 CMD_GET_OBJECT_PROP_VALUE,
824 };
825 static const uint16_t fmt[] = {
826 FMT_UNDEFINED_OBJECT,
827 FMT_ASSOCIATION,
828 };
829 MTPData *d = usb_mtp_data_alloc(c);
830
831 trace_usb_mtp_op_get_device_info(s->dev.addr);
832
833 usb_mtp_add_u16(d, 100);
834 usb_mtp_add_u32(d, 0x00000006);
835 usb_mtp_add_u16(d, 0x0064);
836 usb_mtp_add_wstr(d, L"");
837 usb_mtp_add_u16(d, 0x0000);
838
839 usb_mtp_add_u16_array(d, ARRAY_SIZE(ops), ops);
840 usb_mtp_add_u16_array(d, 0, NULL);
841 usb_mtp_add_u16_array(d, 0, NULL);
842 usb_mtp_add_u16_array(d, 0, NULL);
843 usb_mtp_add_u16_array(d, ARRAY_SIZE(fmt), fmt);
844
845 usb_mtp_add_wstr(d, L"" MTP_MANUFACTURER);
846 usb_mtp_add_wstr(d, L"" MTP_PRODUCT);
847 usb_mtp_add_wstr(d, L"0.1");
848 usb_mtp_add_wstr(d, L"0123456789abcdef0123456789abcdef");
849
850 return d;
851 }
852
853 static MTPData *usb_mtp_get_storage_ids(MTPState *s, MTPControl *c)
854 {
855 static const uint32_t ids[] = {
856 QEMU_STORAGE_ID,
857 };
858 MTPData *d = usb_mtp_data_alloc(c);
859
860 trace_usb_mtp_op_get_storage_ids(s->dev.addr);
861
862 usb_mtp_add_u32_array(d, ARRAY_SIZE(ids), ids);
863
864 return d;
865 }
866
867 static MTPData *usb_mtp_get_storage_info(MTPState *s, MTPControl *c)
868 {
869 MTPData *d = usb_mtp_data_alloc(c);
870 struct statvfs buf;
871 int rc;
872
873 trace_usb_mtp_op_get_storage_info(s->dev.addr);
874
875 if (FLAG_SET(s, MTP_FLAG_WRITABLE)) {
876 usb_mtp_add_u16(d, 0x0003);
877 usb_mtp_add_u16(d, 0x0002);
878 usb_mtp_add_u16(d, 0x0000);
879 } else {
880 usb_mtp_add_u16(d, 0x0001);
881 usb_mtp_add_u16(d, 0x0002);
882 usb_mtp_add_u16(d, 0x0001);
883 }
884
885 rc = statvfs(s->root, &buf);
886 if (rc == 0) {
887 usb_mtp_add_u64(d, (uint64_t)buf.f_frsize * buf.f_blocks);
888 usb_mtp_add_u64(d, (uint64_t)buf.f_bavail * buf.f_blocks);
889 usb_mtp_add_u32(d, buf.f_ffree);
890 } else {
891 usb_mtp_add_u64(d, 0xffffffff);
892 usb_mtp_add_u64(d, 0xffffffff);
893 usb_mtp_add_u32(d, 0xffffffff);
894 }
895
896 usb_mtp_add_str(d, s->desc);
897 usb_mtp_add_wstr(d, L"123456789abcdef");
898 return d;
899 }
900
901 static MTPData *usb_mtp_get_object_handles(MTPState *s, MTPControl *c,
902 MTPObject *o)
903 {
904 MTPData *d = usb_mtp_data_alloc(c);
905 uint32_t i = 0, handles[o->nchildren];
906 MTPObject *iter;
907
908 trace_usb_mtp_op_get_object_handles(s->dev.addr, o->handle, o->path);
909
910 QLIST_FOREACH(iter, &o->children, list) {
911 handles[i++] = iter->handle;
912 }
913 assert(i == o->nchildren);
914 usb_mtp_add_u32_array(d, o->nchildren, handles);
915
916 return d;
917 }
918
919 static MTPData *usb_mtp_get_object_info(MTPState *s, MTPControl *c,
920 MTPObject *o)
921 {
922 MTPData *d = usb_mtp_data_alloc(c);
923
924 trace_usb_mtp_op_get_object_info(s->dev.addr, o->handle, o->path);
925
926 usb_mtp_add_u32(d, QEMU_STORAGE_ID);
927 usb_mtp_add_u16(d, o->format);
928 usb_mtp_add_u16(d, 0);
929
930 if (o->stat.st_size > 0xFFFFFFFF) {
931 usb_mtp_add_u32(d, 0xFFFFFFFF);
932 } else {
933 usb_mtp_add_u32(d, o->stat.st_size);
934 }
935
936 usb_mtp_add_u16(d, 0);
937 usb_mtp_add_u32(d, 0);
938 usb_mtp_add_u32(d, 0);
939 usb_mtp_add_u32(d, 0);
940 usb_mtp_add_u32(d, 0);
941 usb_mtp_add_u32(d, 0);
942 usb_mtp_add_u32(d, 0);
943
944 if (o->parent) {
945 usb_mtp_add_u32(d, o->parent->handle);
946 } else {
947 usb_mtp_add_u32(d, 0);
948 }
949 if (o->format == FMT_ASSOCIATION) {
950 usb_mtp_add_u16(d, 0x0001);
951 usb_mtp_add_u32(d, 0x00000001);
952 usb_mtp_add_u32(d, 0);
953 } else {
954 usb_mtp_add_u16(d, 0);
955 usb_mtp_add_u32(d, 0);
956 usb_mtp_add_u32(d, 0);
957 }
958
959 usb_mtp_add_str(d, o->name);
960 usb_mtp_add_time(d, o->stat.st_ctime);
961 usb_mtp_add_time(d, o->stat.st_mtime);
962 usb_mtp_add_wstr(d, L"");
963
964 return d;
965 }
966
967 static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c,
968 MTPObject *o)
969 {
970 MTPData *d = usb_mtp_data_alloc(c);
971
972 trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path);
973
974 d->fd = open(o->path, O_RDONLY);
975 if (d->fd == -1) {
976 usb_mtp_data_free(d);
977 return NULL;
978 }
979 d->length = o->stat.st_size;
980 d->alloc = 512;
981 d->data = g_malloc(d->alloc);
982 return d;
983 }
984
985 static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c,
986 MTPObject *o)
987 {
988 MTPData *d = usb_mtp_data_alloc(c);
989 off_t offset;
990
991 trace_usb_mtp_op_get_partial_object(s->dev.addr, o->handle, o->path,
992 c->argv[1], c->argv[2]);
993
994 d->fd = open(o->path, O_RDONLY);
995 if (d->fd == -1) {
996 usb_mtp_data_free(d);
997 return NULL;
998 }
999
1000 offset = c->argv[1];
1001 if (offset > o->stat.st_size) {
1002 offset = o->stat.st_size;
1003 }
1004 if (lseek(d->fd, offset, SEEK_SET) < 0) {
1005 usb_mtp_data_free(d);
1006 return NULL;
1007 }
1008
1009 d->length = c->argv[2];
1010 if (d->length > o->stat.st_size - offset) {
1011 d->length = o->stat.st_size - offset;
1012 }
1013
1014 return d;
1015 }
1016
1017 static MTPData *usb_mtp_get_object_props_supported(MTPState *s, MTPControl *c)
1018 {
1019 static const uint16_t props[] = {
1020 PROP_STORAGE_ID,
1021 PROP_OBJECT_FORMAT,
1022 PROP_OBJECT_COMPRESSED_SIZE,
1023 PROP_PARENT_OBJECT,
1024 PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER,
1025 PROP_NAME,
1026 };
1027 MTPData *d = usb_mtp_data_alloc(c);
1028 usb_mtp_add_u16_array(d, ARRAY_SIZE(props), props);
1029
1030 return d;
1031 }
1032
1033 static MTPData *usb_mtp_get_object_prop_desc(MTPState *s, MTPControl *c)
1034 {
1035 MTPData *d = usb_mtp_data_alloc(c);
1036 switch (c->argv[0]) {
1037 case PROP_STORAGE_ID:
1038 usb_mtp_add_u16(d, PROP_STORAGE_ID);
1039 usb_mtp_add_u16(d, DATA_TYPE_UINT32);
1040 usb_mtp_add_u8(d, 0x00);
1041 usb_mtp_add_u32(d, 0x00000000);
1042 usb_mtp_add_u32(d, 0x00000000);
1043 usb_mtp_add_u8(d, 0x00);
1044 break;
1045 case PROP_OBJECT_FORMAT:
1046 usb_mtp_add_u16(d, PROP_OBJECT_FORMAT);
1047 usb_mtp_add_u16(d, DATA_TYPE_UINT16);
1048 usb_mtp_add_u8(d, 0x00);
1049 usb_mtp_add_u16(d, 0x0000);
1050 usb_mtp_add_u32(d, 0x00000000);
1051 usb_mtp_add_u8(d, 0x00);
1052 break;
1053 case PROP_OBJECT_COMPRESSED_SIZE:
1054 usb_mtp_add_u16(d, PROP_OBJECT_COMPRESSED_SIZE);
1055 usb_mtp_add_u16(d, DATA_TYPE_UINT64);
1056 usb_mtp_add_u8(d, 0x00);
1057 usb_mtp_add_u64(d, 0x0000000000000000);
1058 usb_mtp_add_u32(d, 0x00000000);
1059 usb_mtp_add_u8(d, 0x00);
1060 break;
1061 case PROP_PARENT_OBJECT:
1062 usb_mtp_add_u16(d, PROP_PARENT_OBJECT);
1063 usb_mtp_add_u16(d, DATA_TYPE_UINT32);
1064 usb_mtp_add_u8(d, 0x00);
1065 usb_mtp_add_u32(d, 0x00000000);
1066 usb_mtp_add_u32(d, 0x00000000);
1067 usb_mtp_add_u8(d, 0x00);
1068 break;
1069 case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER:
1070 usb_mtp_add_u16(d, PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER);
1071 usb_mtp_add_u16(d, DATA_TYPE_UINT128);
1072 usb_mtp_add_u8(d, 0x00);
1073 usb_mtp_add_u64(d, 0x0000000000000000);
1074 usb_mtp_add_u64(d, 0x0000000000000000);
1075 usb_mtp_add_u32(d, 0x00000000);
1076 usb_mtp_add_u8(d, 0x00);
1077 break;
1078 case PROP_NAME:
1079 usb_mtp_add_u16(d, PROP_NAME);
1080 usb_mtp_add_u16(d, DATA_TYPE_STRING);
1081 usb_mtp_add_u8(d, 0x00);
1082 usb_mtp_add_u8(d, 0x00);
1083 usb_mtp_add_u32(d, 0x00000000);
1084 usb_mtp_add_u8(d, 0x00);
1085 break;
1086 default:
1087 usb_mtp_data_free(d);
1088 return NULL;
1089 }
1090
1091 return d;
1092 }
1093
1094 static MTPData *usb_mtp_get_object_prop_value(MTPState *s, MTPControl *c,
1095 MTPObject *o)
1096 {
1097 MTPData *d = usb_mtp_data_alloc(c);
1098 switch (c->argv[1]) {
1099 case PROP_STORAGE_ID:
1100 usb_mtp_add_u32(d, QEMU_STORAGE_ID);
1101 break;
1102 case PROP_OBJECT_FORMAT:
1103 usb_mtp_add_u16(d, o->format);
1104 break;
1105 case PROP_OBJECT_COMPRESSED_SIZE:
1106 usb_mtp_add_u64(d, o->stat.st_size);
1107 break;
1108 case PROP_PARENT_OBJECT:
1109 if (o->parent == NULL) {
1110 usb_mtp_add_u32(d, 0x00000000);
1111 } else {
1112 usb_mtp_add_u32(d, o->parent->handle);
1113 }
1114 break;
1115 case PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER:
1116 /* Should be persistent between sessions,
1117 * but using our objedt ID is "good enough"
1118 * for now */
1119 usb_mtp_add_u64(d, 0x0000000000000000);
1120 usb_mtp_add_u64(d, o->handle);
1121 break;
1122 case PROP_NAME:
1123 usb_mtp_add_str(d, o->name);
1124 break;
1125 default:
1126 usb_mtp_data_free(d);
1127 return NULL;
1128 }
1129
1130 return d;
1131 }
1132
1133 /* Return correct return code for a delete event */
1134 enum {
1135 ALL_DELETE,
1136 PARTIAL_DELETE,
1137 READ_ONLY,
1138 };
1139
1140 /* Assumes that children, if any, have been already freed */
1141 static void usb_mtp_object_free_one(MTPState *s, MTPObject *o)
1142 {
1143 #ifndef CONFIG_INOTIFY1
1144 assert(o->nchildren == 0);
1145 QTAILQ_REMOVE(&s->objects, o, next);
1146 g_free(o->name);
1147 g_free(o->path);
1148 g_free(o);
1149 #endif
1150 }
1151
1152 static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans)
1153 {
1154 MTPObject *iter, *iter2;
1155 bool partial_delete = false;
1156 bool success = false;
1157
1158 /*
1159 * TODO: Add support for Protection Status
1160 */
1161
1162 QLIST_FOREACH(iter, &o->children, list) {
1163 if (iter->format == FMT_ASSOCIATION) {
1164 QLIST_FOREACH(iter2, &iter->children, list) {
1165 usb_mtp_deletefn(s, iter2, trans);
1166 }
1167 }
1168 }
1169
1170 if (o->format == FMT_UNDEFINED_OBJECT) {
1171 if (remove(o->path)) {
1172 partial_delete = true;
1173 } else {
1174 usb_mtp_object_free_one(s, o);
1175 success = true;
1176 }
1177 }
1178
1179 if (o->format == FMT_ASSOCIATION) {
1180 if (rmdir(o->path)) {
1181 partial_delete = true;
1182 } else {
1183 usb_mtp_object_free_one(s, o);
1184 success = true;
1185 }
1186 }
1187
1188 if (success && partial_delete) {
1189 return PARTIAL_DELETE;
1190 }
1191 if (!success && partial_delete) {
1192 return READ_ONLY;
1193 }
1194 return ALL_DELETE;
1195 }
1196
1197 static void usb_mtp_object_delete(MTPState *s, uint32_t handle,
1198 uint32_t format_code, uint32_t trans)
1199 {
1200 MTPObject *o;
1201 int ret;
1202
1203 /* Return error if store is read-only */
1204 if (!FLAG_SET(s, MTP_FLAG_WRITABLE)) {
1205 usb_mtp_queue_result(s, RES_STORE_READ_ONLY,
1206 trans, 0, 0, 0, 0);
1207 return;
1208 }
1209
1210 if (format_code != 0) {
1211 usb_mtp_queue_result(s, RES_SPEC_BY_FORMAT_UNSUPPORTED,
1212 trans, 0, 0, 0, 0);
1213 return;
1214 }
1215
1216 if (handle == 0xFFFFFFF) {
1217 o = QTAILQ_FIRST(&s->objects);
1218 } else {
1219 o = usb_mtp_object_lookup(s, handle);
1220 }
1221 if (o == NULL) {
1222 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
1223 trans, 0, 0, 0, 0);
1224 return;
1225 }
1226
1227 ret = usb_mtp_deletefn(s, o, trans);
1228 if (ret == PARTIAL_DELETE) {
1229 usb_mtp_queue_result(s, RES_PARTIAL_DELETE,
1230 trans, 0, 0, 0, 0);
1231 return;
1232 } else if (ret == READ_ONLY) {
1233 usb_mtp_queue_result(s, RES_STORE_READ_ONLY, trans,
1234 0, 0, 0, 0);
1235 return;
1236 } else {
1237 usb_mtp_queue_result(s, RES_OK, trans,
1238 0, 0, 0, 0);
1239 return;
1240 }
1241 }
1242
1243 static void usb_mtp_command(MTPState *s, MTPControl *c)
1244 {
1245 MTPData *data_in = NULL;
1246 MTPObject *o;
1247 uint32_t nres = 0, res0 = 0;
1248
1249 /* sanity checks */
1250 if (c->code >= CMD_CLOSE_SESSION && s->session == 0) {
1251 usb_mtp_queue_result(s, RES_SESSION_NOT_OPEN,
1252 c->trans, 0, 0, 0, 0);
1253 return;
1254 }
1255
1256 /* process commands */
1257 switch (c->code) {
1258 case CMD_GET_DEVICE_INFO:
1259 data_in = usb_mtp_get_device_info(s, c);
1260 break;
1261 case CMD_OPEN_SESSION:
1262 if (s->session) {
1263 usb_mtp_queue_result(s, RES_SESSION_ALREADY_OPEN,
1264 c->trans, 1, s->session, 0, 0);
1265 return;
1266 }
1267 if (c->argv[0] == 0) {
1268 usb_mtp_queue_result(s, RES_INVALID_PARAMETER,
1269 c->trans, 0, 0, 0, 0);
1270 return;
1271 }
1272 trace_usb_mtp_op_open_session(s->dev.addr);
1273 s->session = c->argv[0];
1274 usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root);
1275 #ifdef CONFIG_INOTIFY1
1276 if (usb_mtp_inotify_init(s)) {
1277 fprintf(stderr, "usb-mtp: file monitoring init failed\n");
1278 }
1279 #endif
1280 break;
1281 case CMD_CLOSE_SESSION:
1282 trace_usb_mtp_op_close_session(s->dev.addr);
1283 s->session = 0;
1284 s->next_handle = 0;
1285 #ifdef CONFIG_INOTIFY1
1286 usb_mtp_inotify_cleanup(s);
1287 #endif
1288 usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
1289 assert(QTAILQ_EMPTY(&s->objects));
1290 break;
1291 case CMD_GET_STORAGE_IDS:
1292 data_in = usb_mtp_get_storage_ids(s, c);
1293 break;
1294 case CMD_GET_STORAGE_INFO:
1295 if (c->argv[0] != QEMU_STORAGE_ID &&
1296 c->argv[0] != 0xffffffff) {
1297 usb_mtp_queue_result(s, RES_INVALID_STORAGE_ID,
1298 c->trans, 0, 0, 0, 0);
1299 return;
1300 }
1301 data_in = usb_mtp_get_storage_info(s, c);
1302 break;
1303 case CMD_GET_NUM_OBJECTS:
1304 case CMD_GET_OBJECT_HANDLES:
1305 if (c->argv[0] != QEMU_STORAGE_ID &&
1306 c->argv[0] != 0xffffffff) {
1307 usb_mtp_queue_result(s, RES_INVALID_STORAGE_ID,
1308 c->trans, 0, 0, 0, 0);
1309 return;
1310 }
1311 if (c->argv[1] != 0x00000000) {
1312 usb_mtp_queue_result(s, RES_SPEC_BY_FORMAT_UNSUPPORTED,
1313 c->trans, 0, 0, 0, 0);
1314 return;
1315 }
1316 if (c->argv[2] == 0x00000000 ||
1317 c->argv[2] == 0xffffffff) {
1318 o = QTAILQ_FIRST(&s->objects);
1319 } else {
1320 o = usb_mtp_object_lookup(s, c->argv[2]);
1321 }
1322 if (o == NULL) {
1323 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
1324 c->trans, 0, 0, 0, 0);
1325 return;
1326 }
1327 if (o->format != FMT_ASSOCIATION) {
1328 usb_mtp_queue_result(s, RES_INVALID_PARENT_OBJECT,
1329 c->trans, 0, 0, 0, 0);
1330 return;
1331 }
1332 usb_mtp_object_readdir(s, o);
1333 if (c->code == CMD_GET_NUM_OBJECTS) {
1334 trace_usb_mtp_op_get_num_objects(s->dev.addr, o->handle, o->path);
1335 nres = 1;
1336 res0 = o->nchildren;
1337 } else {
1338 data_in = usb_mtp_get_object_handles(s, c, o);
1339 }
1340 break;
1341 case CMD_GET_OBJECT_INFO:
1342 o = usb_mtp_object_lookup(s, c->argv[0]);
1343 if (o == NULL) {
1344 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
1345 c->trans, 0, 0, 0, 0);
1346 return;
1347 }
1348 data_in = usb_mtp_get_object_info(s, c, o);
1349 break;
1350 case CMD_GET_OBJECT:
1351 o = usb_mtp_object_lookup(s, c->argv[0]);
1352 if (o == NULL) {
1353 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
1354 c->trans, 0, 0, 0, 0);
1355 return;
1356 }
1357 if (o->format == FMT_ASSOCIATION) {
1358 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
1359 c->trans, 0, 0, 0, 0);
1360 return;
1361 }
1362 data_in = usb_mtp_get_object(s, c, o);
1363 if (data_in == NULL) {
1364 usb_mtp_queue_result(s, RES_GENERAL_ERROR,
1365 c->trans, 0, 0, 0, 0);
1366 return;
1367 }
1368 break;
1369 case CMD_DELETE_OBJECT:
1370 usb_mtp_object_delete(s, c->argv[0], c->argv[1], c->trans);
1371 return;
1372 case CMD_GET_PARTIAL_OBJECT:
1373 o = usb_mtp_object_lookup(s, c->argv[0]);
1374 if (o == NULL) {
1375 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
1376 c->trans, 0, 0, 0, 0);
1377 return;
1378 }
1379 if (o->format == FMT_ASSOCIATION) {
1380 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
1381 c->trans, 0, 0, 0, 0);
1382 return;
1383 }
1384 data_in = usb_mtp_get_partial_object(s, c, o);
1385 if (data_in == NULL) {
1386 usb_mtp_queue_result(s, RES_GENERAL_ERROR,
1387 c->trans, 0, 0, 0, 0);
1388 return;
1389 }
1390 nres = 1;
1391 res0 = data_in->length;
1392 break;
1393 case CMD_SEND_OBJECT:
1394 if (!FLAG_SET(s, MTP_FLAG_WRITABLE)) {
1395 usb_mtp_queue_result(s, RES_STORE_READ_ONLY,
1396 c->trans, 0, 0, 0, 0);
1397 return;
1398 }
1399 if (!s->write_pending) {
1400 usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO,
1401 c->trans, 0, 0, 0, 0);
1402 return;
1403 }
1404 s->data_out = usb_mtp_data_alloc(c);
1405 return;
1406 case CMD_GET_OBJECT_PROPS_SUPPORTED:
1407 if (c->argv[0] != FMT_UNDEFINED_OBJECT &&
1408 c->argv[0] != FMT_ASSOCIATION) {
1409 usb_mtp_queue_result(s, RES_INVALID_OBJECT_FORMAT_CODE,
1410 c->trans, 0, 0, 0, 0);
1411 return;
1412 }
1413 data_in = usb_mtp_get_object_props_supported(s, c);
1414 break;
1415 case CMD_GET_OBJECT_PROP_DESC:
1416 if (c->argv[1] != FMT_UNDEFINED_OBJECT &&
1417 c->argv[1] != FMT_ASSOCIATION) {
1418 usb_mtp_queue_result(s, RES_INVALID_OBJECT_FORMAT_CODE,
1419 c->trans, 0, 0, 0, 0);
1420 return;
1421 }
1422 data_in = usb_mtp_get_object_prop_desc(s, c);
1423 if (data_in == NULL) {
1424 usb_mtp_queue_result(s, RES_INVALID_OBJECT_PROP_CODE,
1425 c->trans, 0, 0, 0, 0);
1426 return;
1427 }
1428 break;
1429 case CMD_GET_OBJECT_PROP_VALUE:
1430 o = usb_mtp_object_lookup(s, c->argv[0]);
1431 if (o == NULL) {
1432 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
1433 c->trans, 0, 0, 0, 0);
1434 return;
1435 }
1436 data_in = usb_mtp_get_object_prop_value(s, c, o);
1437 if (data_in == NULL) {
1438 usb_mtp_queue_result(s, RES_INVALID_OBJECT_PROP_CODE,
1439 c->trans, 0, 0, 0, 0);
1440 return;
1441 }
1442 break;
1443 default:
1444 trace_usb_mtp_op_unknown(s->dev.addr, c->code);
1445 usb_mtp_queue_result(s, RES_OPERATION_NOT_SUPPORTED,
1446 c->trans, 0, 0, 0, 0);
1447 return;
1448 }
1449
1450 /* return results on success */
1451 if (data_in) {
1452 assert(s->data_in == NULL);
1453 s->data_in = data_in;
1454 }
1455 usb_mtp_queue_result(s, RES_OK, c->trans, nres, res0, 0, 0);
1456 }
1457
1458 /* ----------------------------------------------------------------------- */
1459
1460 static void usb_mtp_handle_reset(USBDevice *dev)
1461 {
1462 MTPState *s = USB_MTP(dev);
1463
1464 trace_usb_mtp_reset(s->dev.addr);
1465
1466 #ifdef CONFIG_INOTIFY1
1467 usb_mtp_inotify_cleanup(s);
1468 #endif
1469 usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
1470 s->session = 0;
1471 usb_mtp_data_free(s->data_in);
1472 s->data_in = NULL;
1473 usb_mtp_data_free(s->data_out);
1474 s->data_out = NULL;
1475 g_free(s->result);
1476 s->result = NULL;
1477 }
1478
1479 static void usb_mtp_handle_control(USBDevice *dev, USBPacket *p,
1480 int request, int value, int index,
1481 int length, uint8_t *data)
1482 {
1483 int ret;
1484
1485 ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
1486 if (ret >= 0) {
1487 return;
1488 }
1489
1490 trace_usb_mtp_stall(dev->addr, "unknown control request");
1491 p->status = USB_RET_STALL;
1492 }
1493
1494 static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p)
1495 {
1496 /* we don't use async packets, so this should never be called */
1497 fprintf(stderr, "%s\n", __func__);
1498 }
1499
1500 static void usb_mtp_write_data(MTPState *s)
1501 {
1502 MTPData *d = s->data_out;
1503 MTPObject *parent =
1504 usb_mtp_object_lookup(s, s->dataset.parent_handle);
1505 char *path = NULL;
1506 int rc = -1;
1507 mode_t mask = 0644;
1508
1509 assert(d != NULL);
1510
1511 if (parent == NULL || !s->write_pending) {
1512 usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, d->trans,
1513 0, 0, 0, 0);
1514 return;
1515 }
1516
1517 if (s->dataset.filename) {
1518 path = g_strdup_printf("%s/%s", parent->path, s->dataset.filename);
1519 if (s->dataset.format == FMT_ASSOCIATION) {
1520 d->fd = mkdir(path, mask);
1521 goto free;
1522 }
1523 if (s->dataset.size < d->length) {
1524 usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
1525 0, 0, 0, 0);
1526 goto done;
1527 }
1528 d->fd = open(path, O_CREAT | O_WRONLY, mask);
1529 if (d->fd == -1) {
1530 usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
1531 0, 0, 0, 0);
1532 goto done;
1533 }
1534
1535 /*
1536 * Return success if initiator sent 0 sized data
1537 */
1538 if (!s->dataset.size) {
1539 goto success;
1540 }
1541
1542 rc = write(d->fd, d->data, s->dataset.size);
1543 if (rc == -1) {
1544 usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
1545 0, 0, 0, 0);
1546 goto done;
1547 }
1548 if (rc != s->dataset.size) {
1549 usb_mtp_queue_result(s, RES_INCOMPLETE_TRANSFER, d->trans,
1550 0, 0, 0, 0);
1551 goto done;
1552 }
1553 }
1554
1555 success:
1556 usb_mtp_queue_result(s, RES_OK, d->trans,
1557 0, 0, 0, 0);
1558
1559 done:
1560 /*
1561 * The write dataset is kept around and freed only
1562 * on success or if another write request comes in
1563 */
1564 if (d->fd != -1) {
1565 close(d->fd);
1566 }
1567 free:
1568 g_free(s->dataset.filename);
1569 g_free(path);
1570 s->write_pending = false;
1571 }
1572
1573 static void usb_mtp_get_data(MTPState *s, mtp_container *container,
1574 USBPacket *p)
1575 {
1576 MTPData *d = s->data_out;
1577 uint64_t dlen;
1578 uint32_t data_len = p->iov.size;
1579
1580 if (d->first) {
1581 /* Total length of incoming data */
1582 d->length = cpu_to_le32(container->length) - sizeof(mtp_container);
1583 /* Length of data in this packet */
1584 data_len -= sizeof(mtp_container);
1585 usb_mtp_realloc(d, d->length);
1586 d->offset = 0;
1587 d->first = false;
1588 }
1589
1590 if (d->length - d->offset > data_len) {
1591 dlen = data_len;
1592 } else {
1593 dlen = d->length - d->offset;
1594 }
1595
1596 switch (d->code) {
1597 case CMD_SEND_OBJECT:
1598 usb_packet_copy(p, d->data + d->offset, dlen);
1599 d->offset += dlen;
1600 if (d->offset == d->length) {
1601 usb_mtp_write_data(s);
1602 usb_mtp_data_free(s->data_out);
1603 s->data_out = NULL;
1604 return;
1605 }
1606 break;
1607 default:
1608 p->status = USB_RET_STALL;
1609 return;
1610 }
1611 }
1612
1613 static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
1614 {
1615 MTPState *s = USB_MTP(dev);
1616 MTPControl cmd;
1617 mtp_container container;
1618 uint32_t params[5];
1619 uint16_t container_type;
1620 int i, rc;
1621
1622 switch (p->ep->nr) {
1623 case EP_DATA_IN:
1624 if (s->data_out != NULL) {
1625 /* guest bug */
1626 trace_usb_mtp_stall(s->dev.addr, "awaiting data-out");
1627 p->status = USB_RET_STALL;
1628 return;
1629 }
1630 if (p->iov.size < sizeof(container)) {
1631 trace_usb_mtp_stall(s->dev.addr, "packet too small");
1632 p->status = USB_RET_STALL;
1633 return;
1634 }
1635 if (s->data_in != NULL) {
1636 MTPData *d = s->data_in;
1637 uint64_t dlen = d->length - d->offset;
1638 if (d->first) {
1639 trace_usb_mtp_data_in(s->dev.addr, d->trans, d->length);
1640 if (d->length + sizeof(container) > 0xFFFFFFFF) {
1641 container.length = cpu_to_le32(0xFFFFFFFF);
1642 } else {
1643 container.length =
1644 cpu_to_le32(d->length + sizeof(container));
1645 }
1646 container.type = cpu_to_le16(TYPE_DATA);
1647 container.code = cpu_to_le16(d->code);
1648 container.trans = cpu_to_le32(d->trans);
1649 usb_packet_copy(p, &container, sizeof(container));
1650 d->first = false;
1651 if (dlen > p->iov.size - sizeof(container)) {
1652 dlen = p->iov.size - sizeof(container);
1653 }
1654 } else {
1655 if (dlen > p->iov.size) {
1656 dlen = p->iov.size;
1657 }
1658 }
1659 if (d->fd == -1) {
1660 usb_packet_copy(p, d->data + d->offset, dlen);
1661 } else {
1662 if (d->alloc < p->iov.size) {
1663 d->alloc = p->iov.size;
1664 d->data = g_realloc(d->data, d->alloc);
1665 }
1666 rc = read(d->fd, d->data, dlen);
1667 if (rc != dlen) {
1668 memset(d->data, 0, dlen);
1669 s->result->code = RES_INCOMPLETE_TRANSFER;
1670 }
1671 usb_packet_copy(p, d->data, dlen);
1672 }
1673 d->offset += dlen;
1674 if (d->offset == d->length) {
1675 usb_mtp_data_free(s->data_in);
1676 s->data_in = NULL;
1677 }
1678 } else if (s->result != NULL) {
1679 MTPControl *r = s->result;
1680 int length = sizeof(container) + r->argc * sizeof(uint32_t);
1681 if (r->code == RES_OK) {
1682 trace_usb_mtp_success(s->dev.addr, r->trans,
1683 (r->argc > 0) ? r->argv[0] : 0,
1684 (r->argc > 1) ? r->argv[1] : 0);
1685 } else {
1686 trace_usb_mtp_error(s->dev.addr, r->code, r->trans,
1687 (r->argc > 0) ? r->argv[0] : 0,
1688 (r->argc > 1) ? r->argv[1] : 0);
1689 }
1690 container.length = cpu_to_le32(length);
1691 container.type = cpu_to_le16(TYPE_RESPONSE);
1692 container.code = cpu_to_le16(r->code);
1693 container.trans = cpu_to_le32(r->trans);
1694 for (i = 0; i < r->argc; i++) {
1695 params[i] = cpu_to_le32(r->argv[i]);
1696 }
1697 usb_packet_copy(p, &container, sizeof(container));
1698 usb_packet_copy(p, &params, length - sizeof(container));
1699 g_free(s->result);
1700 s->result = NULL;
1701 }
1702 break;
1703 case EP_DATA_OUT:
1704 if (p->iov.size < sizeof(container)) {
1705 trace_usb_mtp_stall(s->dev.addr, "packet too small");
1706 p->status = USB_RET_STALL;
1707 return;
1708 }
1709 if (s->data_out && !s->data_out->first) {
1710 container_type = TYPE_DATA;
1711 } else {
1712 usb_packet_copy(p, &container, sizeof(container));
1713 container_type = le16_to_cpu(container.type);
1714 }
1715 switch (container_type) {
1716 case TYPE_COMMAND:
1717 if (s->data_in || s->data_out || s->result) {
1718 trace_usb_mtp_stall(s->dev.addr, "transaction inflight");
1719 p->status = USB_RET_STALL;
1720 return;
1721 }
1722 cmd.code = le16_to_cpu(container.code);
1723 cmd.argc = (le32_to_cpu(container.length) - sizeof(container))
1724 / sizeof(uint32_t);
1725 cmd.trans = le32_to_cpu(container.trans);
1726 if (cmd.argc > ARRAY_SIZE(cmd.argv)) {
1727 cmd.argc = ARRAY_SIZE(cmd.argv);
1728 }
1729 if (p->iov.size < sizeof(container) + cmd.argc * sizeof(uint32_t)) {
1730 trace_usb_mtp_stall(s->dev.addr, "packet too small");
1731 p->status = USB_RET_STALL;
1732 return;
1733 }
1734 usb_packet_copy(p, &params, cmd.argc * sizeof(uint32_t));
1735 for (i = 0; i < cmd.argc; i++) {
1736 cmd.argv[i] = le32_to_cpu(params[i]);
1737 }
1738 trace_usb_mtp_command(s->dev.addr, cmd.code, cmd.trans,
1739 (cmd.argc > 0) ? cmd.argv[0] : 0,
1740 (cmd.argc > 1) ? cmd.argv[1] : 0,
1741 (cmd.argc > 2) ? cmd.argv[2] : 0,
1742 (cmd.argc > 3) ? cmd.argv[3] : 0,
1743 (cmd.argc > 4) ? cmd.argv[4] : 0);
1744 usb_mtp_command(s, &cmd);
1745 break;
1746 case TYPE_DATA:
1747 /* One of the previous transfers has already errored but the
1748 * responder is still sending data associated with it
1749 */
1750 if (s->result != NULL) {
1751 return;
1752 }
1753 usb_mtp_get_data(s, &container, p);
1754 break;
1755 default:
1756 /* not needed as long as the mtp device is read-only */
1757 p->status = USB_RET_STALL;
1758 return;
1759 }
1760 break;
1761 case EP_EVENT:
1762 #ifdef CONFIG_INOTIFY1
1763 if (!QTAILQ_EMPTY(&s->events)) {
1764 struct MTPMonEntry *e = QTAILQ_LAST(&s->events, events);
1765 uint32_t handle;
1766 int len = sizeof(container) + sizeof(uint32_t);
1767
1768 if (p->iov.size < len) {
1769 trace_usb_mtp_stall(s->dev.addr,
1770 "packet too small to send event");
1771 p->status = USB_RET_STALL;
1772 return;
1773 }
1774
1775 QTAILQ_REMOVE(&s->events, e, next);
1776 container.length = cpu_to_le32(len);
1777 container.type = cpu_to_le32(TYPE_EVENT);
1778 container.code = cpu_to_le16(e->event);
1779 container.trans = 0; /* no trans specific events */
1780 handle = cpu_to_le32(e->handle);
1781 usb_packet_copy(p, &container, sizeof(container));
1782 usb_packet_copy(p, &handle, sizeof(uint32_t));
1783 g_free(e);
1784 return;
1785 }
1786 #endif
1787 p->status = USB_RET_NAK;
1788 return;
1789 default:
1790 trace_usb_mtp_stall(s->dev.addr, "invalid endpoint");
1791 p->status = USB_RET_STALL;
1792 return;
1793 }
1794
1795 if (p->actual_length == 0) {
1796 trace_usb_mtp_nak(s->dev.addr, p->ep->nr);
1797 p->status = USB_RET_NAK;
1798 return;
1799 } else {
1800 trace_usb_mtp_xfer(s->dev.addr, p->ep->nr, p->actual_length,
1801 p->iov.size);
1802 return;
1803 }
1804 }
1805
1806 static void usb_mtp_realize(USBDevice *dev, Error **errp)
1807 {
1808 MTPState *s = USB_MTP(dev);
1809
1810 usb_desc_create_serial(dev);
1811 usb_desc_init(dev);
1812 QTAILQ_INIT(&s->objects);
1813 if (s->desc == NULL) {
1814 if (s->root == NULL) {
1815 error_setg(errp, "usb-mtp: x-root property must be configured");
1816 return;
1817 }
1818 s->desc = strrchr(s->root, '/');
1819 /* Mark store as RW */
1820 if (!s->readonly) {
1821 s->flags |= (1 << MTP_FLAG_WRITABLE);
1822 }
1823 if (s->desc && s->desc[0]) {
1824 s->desc = g_strdup(s->desc + 1);
1825 } else {
1826 s->desc = g_strdup("none");
1827 }
1828 }
1829 }
1830
1831 static const VMStateDescription vmstate_usb_mtp = {
1832 .name = "usb-mtp",
1833 .unmigratable = 1,
1834 .version_id = 1,
1835 .minimum_version_id = 1,
1836 .fields = (VMStateField[]) {
1837 VMSTATE_USB_DEVICE(dev, MTPState),
1838 VMSTATE_END_OF_LIST()
1839 }
1840 };
1841
1842 static Property mtp_properties[] = {
1843 DEFINE_PROP_STRING("x-root", MTPState, root),
1844 DEFINE_PROP_STRING("desc", MTPState, desc),
1845 DEFINE_PROP_BOOL("readonly", MTPState, readonly, true),
1846 DEFINE_PROP_END_OF_LIST(),
1847 };
1848
1849 static void usb_mtp_class_initfn(ObjectClass *klass, void *data)
1850 {
1851 DeviceClass *dc = DEVICE_CLASS(klass);
1852 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
1853
1854 uc->realize = usb_mtp_realize;
1855 uc->product_desc = "QEMU USB MTP";
1856 uc->usb_desc = &desc;
1857 uc->cancel_packet = usb_mtp_cancel_packet;
1858 uc->handle_attach = usb_desc_attach;
1859 uc->handle_reset = usb_mtp_handle_reset;
1860 uc->handle_control = usb_mtp_handle_control;
1861 uc->handle_data = usb_mtp_handle_data;
1862 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
1863 dc->desc = "USB Media Transfer Protocol device";
1864 dc->fw_name = "mtp";
1865 dc->vmsd = &vmstate_usb_mtp;
1866 dc->props = mtp_properties;
1867 }
1868
1869 static TypeInfo mtp_info = {
1870 .name = TYPE_USB_MTP,
1871 .parent = TYPE_USB_DEVICE,
1872 .instance_size = sizeof(MTPState),
1873 .class_init = usb_mtp_class_initfn,
1874 };
1875
1876 static void usb_mtp_register_types(void)
1877 {
1878 type_register_static(&mtp_info);
1879 }
1880
1881 type_init(usb_mtp_register_types)