Lines Matching +full:d +full:- +full:- +full:- +full:- +full:- +full:0

14 #include "qemu/error-report.h"
25 #include "hw/qdev-properties.h"
32 /* ----------------------------------------------------------------------- */
50 CMD_GET_DEVICE_INFO = 0x1001,
51 CMD_OPEN_SESSION = 0x1002,
52 CMD_CLOSE_SESSION = 0x1003,
53 CMD_GET_STORAGE_IDS = 0x1004,
54 CMD_GET_STORAGE_INFO = 0x1005,
55 CMD_GET_NUM_OBJECTS = 0x1006,
56 CMD_GET_OBJECT_HANDLES = 0x1007,
57 CMD_GET_OBJECT_INFO = 0x1008,
58 CMD_GET_OBJECT = 0x1009,
59 CMD_DELETE_OBJECT = 0x100b,
60 CMD_SEND_OBJECT_INFO = 0x100c,
61 CMD_SEND_OBJECT = 0x100d,
62 CMD_GET_PARTIAL_OBJECT = 0x101b,
63 CMD_GET_OBJECT_PROPS_SUPPORTED = 0x9801,
64 CMD_GET_OBJECT_PROP_DESC = 0x9802,
65 CMD_GET_OBJECT_PROP_VALUE = 0x9803,
68 RES_OK = 0x2001,
69 RES_GENERAL_ERROR = 0x2002,
70 RES_SESSION_NOT_OPEN = 0x2003,
71 RES_INVALID_TRANSACTION_ID = 0x2004,
72 RES_OPERATION_NOT_SUPPORTED = 0x2005,
73 RES_PARAMETER_NOT_SUPPORTED = 0x2006,
74 RES_INCOMPLETE_TRANSFER = 0x2007,
75 RES_INVALID_STORAGE_ID = 0x2008,
76 RES_INVALID_OBJECT_HANDLE = 0x2009,
77 RES_INVALID_OBJECT_FORMAT_CODE = 0x200b,
78 RES_STORE_FULL = 0x200c,
79 RES_STORE_READ_ONLY = 0x200e,
80 RES_PARTIAL_DELETE = 0x2012,
81 RES_STORE_NOT_AVAILABLE = 0x2013,
82 RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014,
83 RES_INVALID_OBJECTINFO = 0x2015,
84 RES_DESTINATION_UNSUPPORTED = 0x2020,
85 RES_INVALID_PARENT_OBJECT = 0x201a,
86 RES_INVALID_PARAMETER = 0x201d,
87 RES_SESSION_ALREADY_OPEN = 0x201e,
88 RES_INVALID_OBJECT_PROP_CODE = 0xA801,
91 FMT_UNDEFINED_OBJECT = 0x3000,
92 FMT_ASSOCIATION = 0x3001,
95 EVT_CANCEL_TRANSACTION = 0x4001,
96 EVT_OBJ_ADDED = 0x4002,
97 EVT_OBJ_REMOVED = 0x4003,
98 EVT_OBJ_INFO_CHANGED = 0x4007,
101 PROP_STORAGE_ID = 0xDC01,
102 PROP_OBJECT_FORMAT = 0xDC02,
103 PROP_OBJECT_COMPRESSED_SIZE = 0xDC04,
104 PROP_PARENT_OBJECT = 0xDC0B,
105 PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER = 0xDC41,
106 PROP_NAME = 0xDC44,
110 DATA_TYPE_UINT16 = 0x0004,
111 DATA_TYPE_UINT32 = 0x0006,
112 DATA_TYPE_UINT64 = 0x0008,
113 DATA_TYPE_UINT128 = 0x000a,
114 DATA_TYPE_STRING = 0xffff,
124 /* ----------------------------------------------------------------------- */
232 uint8_t filename[0]; /* UTF-16 encoded */
233 char date_created[0]; /*unused*/
234 char date_modified[0]; /*unused*/
235 char keywords[0]; /*unused*/
239 #define TYPE_USB_MTP "usb-mtp"
242 #define QEMU_STORAGE_ID 0x00010001
244 #define MTP_FLAG_WRITABLE 0
246 #define FLAG_SET(_mtp, _flag) ((_mtp)->flags & (1 << (_flag)))
248 /* ----------------------------------------------------------------------- */
275 .bInterfaceNumber = 0,
278 .bInterfaceSubClass = 0x01,
279 .bInterfaceProtocol = 0x01,
294 .bInterval = 0x0a,
300 .bcdUSB = 0x0200,
317 .bInterfaceNumber = 0,
320 .bInterfaceSubClass = 0x01,
321 .bInterfaceProtocol = 0x01,
336 .bInterval = 0x0a,
342 .bcdUSB = 0x0200,
365 .idVendor = 0x46f4, /* CRC16() of "QEMU" */
366 .idProduct = 0x0004,
367 .bcdDevice = 0,
378 /* ----------------------------------------------------------------------- */
385 if (name[0] == '.') { in usb_mtp_object_alloc()
389 o->watchid = -1; in usb_mtp_object_alloc()
390 o->handle = handle; in usb_mtp_object_alloc()
391 o->parent = parent; in usb_mtp_object_alloc()
392 o->name = g_strdup(name); in usb_mtp_object_alloc()
394 o->path = g_strdup(name); in usb_mtp_object_alloc()
396 o->path = g_strdup_printf("%s/%s", parent->path, name); in usb_mtp_object_alloc()
399 if (lstat(o->path, &o->stat) != 0) { in usb_mtp_object_alloc()
402 if (S_ISREG(o->stat.st_mode)) { in usb_mtp_object_alloc()
403 o->format = FMT_UNDEFINED_OBJECT; in usb_mtp_object_alloc()
404 } else if (S_ISDIR(o->stat.st_mode)) { in usb_mtp_object_alloc()
405 o->format = FMT_ASSOCIATION; in usb_mtp_object_alloc()
410 if (access(o->path, R_OK) != 0) { in usb_mtp_object_alloc()
414 trace_usb_mtp_object_alloc(s->dev.addr, o->handle, o->path); in usb_mtp_object_alloc()
416 QTAILQ_INSERT_TAIL(&s->objects, o, next); in usb_mtp_object_alloc()
420 g_free(o->name); in usb_mtp_object_alloc()
421 g_free(o->path); in usb_mtp_object_alloc()
434 trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path); in usb_mtp_object_free()
436 if (o->watchid != -1 && s->file_monitor) { in usb_mtp_object_free()
437 qemu_file_monitor_remove_watch(s->file_monitor, o->path, o->watchid); in usb_mtp_object_free()
440 QTAILQ_REMOVE(&s->objects, o, next); in usb_mtp_object_free()
441 if (o->parent) { in usb_mtp_object_free()
443 o->parent->nchildren--; in usb_mtp_object_free()
446 while (!QLIST_EMPTY(&o->children)) { in usb_mtp_object_free()
447 iter = QLIST_FIRST(&o->children); in usb_mtp_object_free()
450 g_free(o->name); in usb_mtp_object_free()
451 g_free(o->path); in usb_mtp_object_free()
459 QTAILQ_FOREACH(o, &s->objects, next) { in usb_mtp_object_lookup()
460 if (o->handle == handle) { in usb_mtp_object_lookup()
471 usb_mtp_object_alloc(s, s->next_handle++, o, name); in usb_mtp_add_child()
474 trace_usb_mtp_add_child(s->dev.addr, child->handle, child->path); in usb_mtp_add_child()
475 QLIST_INSERT_HEAD(&o->children, child, list); in usb_mtp_add_child()
476 o->nchildren++; in usb_mtp_add_child()
478 if (child->format == FMT_ASSOCIATION) { in usb_mtp_add_child()
479 QLIST_INIT(&child->children); in usb_mtp_add_child()
491 if (len == -1) { in usb_mtp_object_lookup_name()
495 QLIST_FOREACH(iter, &parent->children, list) { in usb_mtp_object_lookup_name()
496 if (strncmp(iter->name, name, len) == 0) { in usb_mtp_object_lookup_name()
508 QTAILQ_FOREACH(iter, &s->objects, next) { in usb_mtp_object_lookup_id()
509 if (iter->watchid == id) { in usb_mtp_object_lookup_id()
533 if (usb_mtp_object_lookup_name(parent, name, -1)) { in file_monitor_event()
538 entry->handle = s->next_handle; in file_monitor_event()
539 entry->event = EVT_OBJ_ADDED; in file_monitor_event()
545 trace_usb_mtp_file_monitor_event(s->dev.addr, name, "Obj Added"); in file_monitor_event()
555 o = usb_mtp_object_lookup_name(parent, name, -1); in file_monitor_event()
560 entry->handle = o->handle; in file_monitor_event()
561 entry->event = EVT_OBJ_REMOVED; in file_monitor_event()
562 trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Obj Deleted"); in file_monitor_event()
567 o = usb_mtp_object_lookup_name(parent, name, -1); in file_monitor_event()
572 entry->handle = o->handle; in file_monitor_event()
573 entry->event = EVT_OBJ_INFO_CHANGED; in file_monitor_event()
574 trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Obj Modified"); in file_monitor_event()
578 trace_usb_mtp_file_monitor_event(s->dev.addr, parent->path, in file_monitor_event()
590 QTAILQ_INSERT_HEAD(&s->events, entry, next); in file_monitor_event()
598 QTAILQ_FOREACH_SAFE(e, &s->events, next, p) { in usb_mtp_file_monitor_cleanup()
599 QTAILQ_REMOVE(&s->events, e, next); in usb_mtp_file_monitor_cleanup()
603 qemu_file_monitor_free(s->file_monitor); in usb_mtp_file_monitor_cleanup()
604 s->file_monitor = NULL; in usb_mtp_file_monitor_cleanup()
615 if (o->have_children) { in usb_mtp_object_readdir()
618 o->have_children = true; in usb_mtp_object_readdir()
620 fd = open(o->path, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); in usb_mtp_object_readdir()
621 if (fd < 0) { in usb_mtp_object_readdir()
630 if (s->file_monitor) { in usb_mtp_object_readdir()
631 int64_t id = qemu_file_monitor_add_watch(s->file_monitor, o->path, NULL, in usb_mtp_object_readdir()
633 if (id == -1) { in usb_mtp_object_readdir()
635 "usb-mtp: failed to add watch for %s: ", in usb_mtp_object_readdir()
636 o->path); in usb_mtp_object_readdir()
638 trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, in usb_mtp_object_readdir()
640 o->watchid = id; in usb_mtp_object_readdir()
645 usb_mtp_add_child(s, o, entry->d_name); in usb_mtp_object_readdir()
650 /* ----------------------------------------------------------------------- */
656 data->code = c->code; in usb_mtp_data_alloc()
657 data->trans = c->trans; in usb_mtp_data_alloc()
658 data->fd = -1; in usb_mtp_data_alloc()
659 data->first = true; in usb_mtp_data_alloc()
668 if (data->fd != -1) { in usb_mtp_data_free()
669 close(data->fd); in usb_mtp_data_free()
671 g_free(data->data); in usb_mtp_data_free()
677 if (data->length + bytes <= data->alloc) { in usb_mtp_realloc()
680 data->alloc = (data->length + bytes + 0xff) & ~0xff; in usb_mtp_realloc()
681 data->data = g_realloc(data->data, data->alloc); in usb_mtp_realloc()
687 data->data[data->length++] = val; in usb_mtp_add_u8()
693 data->data[data->length++] = (val >> 0) & 0xff; in usb_mtp_add_u16()
694 data->data[data->length++] = (val >> 8) & 0xff; in usb_mtp_add_u16()
700 data->data[data->length++] = (val >> 0) & 0xff; in usb_mtp_add_u32()
701 data->data[data->length++] = (val >> 8) & 0xff; in usb_mtp_add_u32()
702 data->data[data->length++] = (val >> 16) & 0xff; in usb_mtp_add_u32()
703 data->data[data->length++] = (val >> 24) & 0xff; in usb_mtp_add_u32()
709 data->data[data->length++] = (val >> 0) & 0xff; in usb_mtp_add_u64()
710 data->data[data->length++] = (val >> 8) & 0xff; in usb_mtp_add_u64()
711 data->data[data->length++] = (val >> 16) & 0xff; in usb_mtp_add_u64()
712 data->data[data->length++] = (val >> 24) & 0xff; in usb_mtp_add_u64()
713 data->data[data->length++] = (val >> 32) & 0xff; in usb_mtp_add_u64()
714 data->data[data->length++] = (val >> 40) & 0xff; in usb_mtp_add_u64()
715 data->data[data->length++] = (val >> 48) & 0xff; in usb_mtp_add_u64()
716 data->data[data->length++] = (val >> 56) & 0xff; in usb_mtp_add_u64()
725 for (i = 0; i < len; i++) { in usb_mtp_add_u16_array()
736 for (i = 0; i < len; i++) { in usb_mtp_add_u32_array()
746 if (len > 0) { in usb_mtp_add_wstr()
747 len++; /* include terminating L'\0' */ in usb_mtp_add_wstr()
751 for (i = 0; i < len; i++) { in usb_mtp_add_wstr()
763 if (ret == -1) { in usb_mtp_add_str()
779 /* ----------------------------------------------------------------------- */
787 c->code = code; in usb_mtp_queue_result()
788 c->trans = trans; in usb_mtp_queue_result()
789 c->argc = argc; in usb_mtp_queue_result()
790 if (argc > 0) { in usb_mtp_queue_result()
791 c->argv[0] = arg0; in usb_mtp_queue_result()
794 c->argv[1] = arg1; in usb_mtp_queue_result()
797 c->argv[2] = arg2; in usb_mtp_queue_result()
800 assert(s->result == NULL); in usb_mtp_queue_result()
801 s->result = c; in usb_mtp_queue_result()
804 /* ----------------------------------------------------------------------- */
830 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_device_info() local
832 trace_usb_mtp_op_get_device_info(s->dev.addr); in usb_mtp_get_device_info()
834 usb_mtp_add_u16(d, 100); in usb_mtp_get_device_info()
835 usb_mtp_add_u32(d, 0x00000006); in usb_mtp_get_device_info()
836 usb_mtp_add_u16(d, 0x0064); in usb_mtp_get_device_info()
837 usb_mtp_add_wstr(d, L""); in usb_mtp_get_device_info()
838 usb_mtp_add_u16(d, 0x0000); in usb_mtp_get_device_info()
840 usb_mtp_add_u16_array(d, ARRAY_SIZE(ops), ops); in usb_mtp_get_device_info()
841 usb_mtp_add_u16_array(d, 0, NULL); in usb_mtp_get_device_info()
842 usb_mtp_add_u16_array(d, 0, NULL); in usb_mtp_get_device_info()
843 usb_mtp_add_u16_array(d, 0, NULL); in usb_mtp_get_device_info()
844 usb_mtp_add_u16_array(d, ARRAY_SIZE(fmt), fmt); in usb_mtp_get_device_info()
846 usb_mtp_add_wstr(d, L"" MTP_MANUFACTURER); in usb_mtp_get_device_info()
847 usb_mtp_add_wstr(d, L"" MTP_PRODUCT); in usb_mtp_get_device_info()
848 usb_mtp_add_wstr(d, L"0.1"); in usb_mtp_get_device_info()
849 usb_mtp_add_wstr(d, L"0123456789abcdef0123456789abcdef"); in usb_mtp_get_device_info()
851 return d; in usb_mtp_get_device_info()
859 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_storage_ids() local
861 trace_usb_mtp_op_get_storage_ids(s->dev.addr); in usb_mtp_get_storage_ids()
863 usb_mtp_add_u32_array(d, ARRAY_SIZE(ids), ids); in usb_mtp_get_storage_ids()
865 return d; in usb_mtp_get_storage_ids()
870 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_storage_info() local
874 trace_usb_mtp_op_get_storage_info(s->dev.addr); in usb_mtp_get_storage_info()
877 usb_mtp_add_u16(d, 0x0003); in usb_mtp_get_storage_info()
878 usb_mtp_add_u16(d, 0x0002); in usb_mtp_get_storage_info()
879 usb_mtp_add_u16(d, 0x0000); in usb_mtp_get_storage_info()
881 usb_mtp_add_u16(d, 0x0001); in usb_mtp_get_storage_info()
882 usb_mtp_add_u16(d, 0x0002); in usb_mtp_get_storage_info()
883 usb_mtp_add_u16(d, 0x0001); in usb_mtp_get_storage_info()
886 rc = statvfs(s->root, &buf); in usb_mtp_get_storage_info()
887 if (rc == 0) { in usb_mtp_get_storage_info()
888 usb_mtp_add_u64(d, (uint64_t)buf.f_frsize * buf.f_blocks); in usb_mtp_get_storage_info()
889 usb_mtp_add_u64(d, (uint64_t)buf.f_frsize * buf.f_bavail); in usb_mtp_get_storage_info()
890 usb_mtp_add_u32(d, buf.f_ffree); in usb_mtp_get_storage_info()
892 usb_mtp_add_u64(d, 0xffffffff); in usb_mtp_get_storage_info()
893 usb_mtp_add_u64(d, 0xffffffff); in usb_mtp_get_storage_info()
894 usb_mtp_add_u32(d, 0xffffffff); in usb_mtp_get_storage_info()
897 usb_mtp_add_str(d, s->desc); in usb_mtp_get_storage_info()
898 usb_mtp_add_wstr(d, L"123456789abcdef"); in usb_mtp_get_storage_info()
899 return d; in usb_mtp_get_storage_info()
905 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_object_handles() local
906 uint32_t i = 0; in usb_mtp_get_object_handles()
907 g_autofree uint32_t *handles = g_new(uint32_t, o->nchildren); in usb_mtp_get_object_handles()
910 trace_usb_mtp_op_get_object_handles(s->dev.addr, o->handle, o->path); in usb_mtp_get_object_handles()
912 QLIST_FOREACH(iter, &o->children, list) { in usb_mtp_get_object_handles()
913 handles[i++] = iter->handle; in usb_mtp_get_object_handles()
915 assert(i == o->nchildren); in usb_mtp_get_object_handles()
916 usb_mtp_add_u32_array(d, o->nchildren, handles); in usb_mtp_get_object_handles()
918 return d; in usb_mtp_get_object_handles()
924 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_object_info() local
926 trace_usb_mtp_op_get_object_info(s->dev.addr, o->handle, o->path); in usb_mtp_get_object_info()
928 usb_mtp_add_u32(d, QEMU_STORAGE_ID); in usb_mtp_get_object_info()
929 usb_mtp_add_u16(d, o->format); in usb_mtp_get_object_info()
930 usb_mtp_add_u16(d, 0); in usb_mtp_get_object_info()
932 if (o->stat.st_size > 0xFFFFFFFF) { in usb_mtp_get_object_info()
933 usb_mtp_add_u32(d, 0xFFFFFFFF); in usb_mtp_get_object_info()
935 usb_mtp_add_u32(d, o->stat.st_size); in usb_mtp_get_object_info()
938 usb_mtp_add_u16(d, 0); in usb_mtp_get_object_info()
939 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
940 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
941 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
942 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
943 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
944 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
946 if (o->parent) { in usb_mtp_get_object_info()
947 usb_mtp_add_u32(d, o->parent->handle); in usb_mtp_get_object_info()
949 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
951 if (o->format == FMT_ASSOCIATION) { in usb_mtp_get_object_info()
952 usb_mtp_add_u16(d, 0x0001); in usb_mtp_get_object_info()
953 usb_mtp_add_u32(d, 0x00000001); in usb_mtp_get_object_info()
954 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
956 usb_mtp_add_u16(d, 0); in usb_mtp_get_object_info()
957 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
958 usb_mtp_add_u32(d, 0); in usb_mtp_get_object_info()
961 usb_mtp_add_str(d, o->name); in usb_mtp_get_object_info()
962 usb_mtp_add_time(d, o->stat.st_ctime); in usb_mtp_get_object_info()
963 usb_mtp_add_time(d, o->stat.st_mtime); in usb_mtp_get_object_info()
964 usb_mtp_add_wstr(d, L""); in usb_mtp_get_object_info()
966 return d; in usb_mtp_get_object_info()
972 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_object() local
974 trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path); in usb_mtp_get_object()
976 d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); in usb_mtp_get_object()
977 if (d->fd == -1) { in usb_mtp_get_object()
978 usb_mtp_data_free(d); in usb_mtp_get_object()
981 d->length = o->stat.st_size; in usb_mtp_get_object()
982 d->alloc = 512; in usb_mtp_get_object()
983 d->data = g_malloc(d->alloc); in usb_mtp_get_object()
984 return d; in usb_mtp_get_object()
990 MTPData *d; in usb_mtp_get_partial_object() local
993 if (c->argc <= 2) { in usb_mtp_get_partial_object()
996 trace_usb_mtp_op_get_partial_object(s->dev.addr, o->handle, o->path, in usb_mtp_get_partial_object()
997 c->argv[1], c->argv[2]); in usb_mtp_get_partial_object()
999 d = usb_mtp_data_alloc(c); in usb_mtp_get_partial_object()
1000 d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); in usb_mtp_get_partial_object()
1001 if (d->fd == -1) { in usb_mtp_get_partial_object()
1002 usb_mtp_data_free(d); in usb_mtp_get_partial_object()
1006 offset = c->argv[1]; in usb_mtp_get_partial_object()
1007 if (offset > o->stat.st_size) { in usb_mtp_get_partial_object()
1008 offset = o->stat.st_size; in usb_mtp_get_partial_object()
1010 if (lseek(d->fd, offset, SEEK_SET) < 0) { in usb_mtp_get_partial_object()
1011 usb_mtp_data_free(d); in usb_mtp_get_partial_object()
1015 d->length = c->argv[2]; in usb_mtp_get_partial_object()
1016 if (d->length > o->stat.st_size - offset) { in usb_mtp_get_partial_object()
1017 d->length = o->stat.st_size - offset; in usb_mtp_get_partial_object()
1020 return d; in usb_mtp_get_partial_object()
1033 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_object_props_supported() local
1034 usb_mtp_add_u16_array(d, ARRAY_SIZE(props), props); in usb_mtp_get_object_props_supported()
1036 return d; in usb_mtp_get_object_props_supported()
1041 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_object_prop_desc() local
1042 switch (c->argv[0]) { in usb_mtp_get_object_prop_desc()
1044 usb_mtp_add_u16(d, PROP_STORAGE_ID); in usb_mtp_get_object_prop_desc()
1045 usb_mtp_add_u16(d, DATA_TYPE_UINT32); in usb_mtp_get_object_prop_desc()
1046 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1047 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_desc()
1048 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_desc()
1049 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1052 usb_mtp_add_u16(d, PROP_OBJECT_FORMAT); in usb_mtp_get_object_prop_desc()
1053 usb_mtp_add_u16(d, DATA_TYPE_UINT16); in usb_mtp_get_object_prop_desc()
1054 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1055 usb_mtp_add_u16(d, 0x0000); in usb_mtp_get_object_prop_desc()
1056 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_desc()
1057 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1060 usb_mtp_add_u16(d, PROP_OBJECT_COMPRESSED_SIZE); in usb_mtp_get_object_prop_desc()
1061 usb_mtp_add_u16(d, DATA_TYPE_UINT64); in usb_mtp_get_object_prop_desc()
1062 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1063 usb_mtp_add_u64(d, 0x0000000000000000); in usb_mtp_get_object_prop_desc()
1064 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_desc()
1065 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1068 usb_mtp_add_u16(d, PROP_PARENT_OBJECT); in usb_mtp_get_object_prop_desc()
1069 usb_mtp_add_u16(d, DATA_TYPE_UINT32); in usb_mtp_get_object_prop_desc()
1070 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1071 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_desc()
1072 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_desc()
1073 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1076 usb_mtp_add_u16(d, PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER); in usb_mtp_get_object_prop_desc()
1077 usb_mtp_add_u16(d, DATA_TYPE_UINT128); in usb_mtp_get_object_prop_desc()
1078 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1079 usb_mtp_add_u64(d, 0x0000000000000000); in usb_mtp_get_object_prop_desc()
1080 usb_mtp_add_u64(d, 0x0000000000000000); in usb_mtp_get_object_prop_desc()
1081 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_desc()
1082 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1085 usb_mtp_add_u16(d, PROP_NAME); in usb_mtp_get_object_prop_desc()
1086 usb_mtp_add_u16(d, DATA_TYPE_STRING); in usb_mtp_get_object_prop_desc()
1087 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1088 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1089 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_desc()
1090 usb_mtp_add_u8(d, 0x00); in usb_mtp_get_object_prop_desc()
1093 usb_mtp_data_free(d); in usb_mtp_get_object_prop_desc()
1097 return d; in usb_mtp_get_object_prop_desc()
1103 MTPData *d = usb_mtp_data_alloc(c); in usb_mtp_get_object_prop_value() local
1104 switch (c->argv[1]) { in usb_mtp_get_object_prop_value()
1106 usb_mtp_add_u32(d, QEMU_STORAGE_ID); in usb_mtp_get_object_prop_value()
1109 usb_mtp_add_u16(d, o->format); in usb_mtp_get_object_prop_value()
1112 usb_mtp_add_u64(d, o->stat.st_size); in usb_mtp_get_object_prop_value()
1115 if (o->parent == NULL) { in usb_mtp_get_object_prop_value()
1116 usb_mtp_add_u32(d, 0x00000000); in usb_mtp_get_object_prop_value()
1118 usb_mtp_add_u32(d, o->parent->handle); in usb_mtp_get_object_prop_value()
1125 usb_mtp_add_u64(d, 0x0000000000000000); in usb_mtp_get_object_prop_value()
1126 usb_mtp_add_u64(d, o->handle); in usb_mtp_get_object_prop_value()
1129 usb_mtp_add_str(d, o->name); in usb_mtp_get_object_prop_value()
1132 usb_mtp_data_free(d); in usb_mtp_get_object_prop_value()
1136 return d; in usb_mtp_get_object_prop_value()
1149 DELETE_SUCCESS = (1 << 0),
1157 int ret = 0; in usb_mtp_deletefn()
1163 QLIST_FOREACH(iter, &o->children, list) { in usb_mtp_deletefn()
1164 if (iter->format == FMT_ASSOCIATION) { in usb_mtp_deletefn()
1165 QLIST_FOREACH(iter2, &iter->children, list) { in usb_mtp_deletefn()
1171 if (o->format == FMT_UNDEFINED_OBJECT) { in usb_mtp_deletefn()
1172 if (remove(o->path)) { in usb_mtp_deletefn()
1178 } else if (o->format == FMT_ASSOCIATION) { in usb_mtp_deletefn()
1179 if (rmdir(o->path)) { in usb_mtp_deletefn()
1196 /* Return error if store is read-only */ in usb_mtp_object_delete()
1199 trans, 0, 0, 0, 0); in usb_mtp_object_delete()
1203 if (format_code != 0) { in usb_mtp_object_delete()
1205 trans, 0, 0, 0, 0); in usb_mtp_object_delete()
1209 if (handle == 0xFFFFFFF) { in usb_mtp_object_delete()
1210 o = QTAILQ_FIRST(&s->objects); in usb_mtp_object_delete()
1216 trans, 0, 0, 0, 0); in usb_mtp_object_delete()
1224 0, 0, 0, 0); in usb_mtp_object_delete()
1228 trans, 0, 0, 0, 0); in usb_mtp_object_delete()
1232 trans, 0, 0, 0, 0); in usb_mtp_object_delete()
1245 uint32_t nres = 0, res0 = 0; in usb_mtp_command()
1249 if (c->code >= CMD_CLOSE_SESSION && s->session == 0) { in usb_mtp_command()
1251 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1256 switch (c->code) { in usb_mtp_command()
1261 if (s->session) { in usb_mtp_command()
1263 c->trans, 1, s->session, 0, 0); in usb_mtp_command()
1266 if (c->argv[0] == 0) { in usb_mtp_command()
1268 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1271 trace_usb_mtp_op_open_session(s->dev.addr); in usb_mtp_command()
1272 s->session = c->argv[0]; in usb_mtp_command()
1273 usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root); in usb_mtp_command()
1275 s->file_monitor = qemu_file_monitor_new(&err); in usb_mtp_command()
1278 "usb-mtp: file monitoring init failed: "); in usb_mtp_command()
1280 QTAILQ_INIT(&s->events); in usb_mtp_command()
1284 trace_usb_mtp_op_close_session(s->dev.addr); in usb_mtp_command()
1285 s->session = 0; in usb_mtp_command()
1286 s->next_handle = 0; in usb_mtp_command()
1288 usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects)); in usb_mtp_command()
1289 assert(QTAILQ_EMPTY(&s->objects)); in usb_mtp_command()
1295 if (c->argv[0] != QEMU_STORAGE_ID && in usb_mtp_command()
1296 c->argv[0] != 0xffffffff) { in usb_mtp_command()
1298 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1305 if (c->argv[0] != QEMU_STORAGE_ID && in usb_mtp_command()
1306 c->argv[0] != 0xffffffff) { in usb_mtp_command()
1308 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1311 if (c->argv[1] != 0x00000000) { in usb_mtp_command()
1313 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1316 if (c->argv[2] == 0x00000000 || in usb_mtp_command()
1317 c->argv[2] == 0xffffffff) { in usb_mtp_command()
1318 o = QTAILQ_FIRST(&s->objects); in usb_mtp_command()
1320 o = usb_mtp_object_lookup(s, c->argv[2]); in usb_mtp_command()
1324 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1327 if (o->format != FMT_ASSOCIATION) { in usb_mtp_command()
1329 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1333 if (c->code == CMD_GET_NUM_OBJECTS) { in usb_mtp_command()
1334 trace_usb_mtp_op_get_num_objects(s->dev.addr, o->handle, o->path); in usb_mtp_command()
1336 res0 = o->nchildren; in usb_mtp_command()
1342 o = usb_mtp_object_lookup(s, c->argv[0]); in usb_mtp_command()
1345 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1351 o = usb_mtp_object_lookup(s, c->argv[0]); in usb_mtp_command()
1354 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1357 if (o->format == FMT_ASSOCIATION) { in usb_mtp_command()
1359 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1365 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1370 usb_mtp_object_delete(s, c->argv[0], c->argv[1], c->trans); in usb_mtp_command()
1373 o = usb_mtp_object_lookup(s, c->argv[0]); in usb_mtp_command()
1376 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1379 if (o->format == FMT_ASSOCIATION) { in usb_mtp_command()
1381 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1387 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1391 res0 = data_in->length; in usb_mtp_command()
1394 /* Return error if store is read-only */ in usb_mtp_command()
1397 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1398 } else if (c->argv[0] && (c->argv[0] != QEMU_STORAGE_ID)) { in usb_mtp_command()
1399 /* First parameter points to storage id or is 0 */ in usb_mtp_command()
1400 usb_mtp_queue_result(s, RES_STORE_NOT_AVAILABLE, c->trans, in usb_mtp_command()
1401 0, 0, 0, 0); in usb_mtp_command()
1402 } else if (c->argv[1] && !c->argv[0]) { in usb_mtp_command()
1404 usb_mtp_queue_result(s, RES_DESTINATION_UNSUPPORTED, c->trans, in usb_mtp_command()
1405 0, 0, 0, 0); in usb_mtp_command()
1407 uint32_t handle = c->argv[1]; in usb_mtp_command()
1408 if (handle == 0xFFFFFFFF || handle == 0) { in usb_mtp_command()
1410 o = QTAILQ_FIRST(&s->objects); in usb_mtp_command()
1415 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE, c->trans, in usb_mtp_command()
1416 0, 0, 0, 0); in usb_mtp_command()
1417 } else if (o->format != FMT_ASSOCIATION) { in usb_mtp_command()
1418 usb_mtp_queue_result(s, RES_INVALID_PARENT_OBJECT, c->trans, in usb_mtp_command()
1419 0, 0, 0, 0); in usb_mtp_command()
1423 s->dataset.parent_handle = o->handle; in usb_mtp_command()
1425 s->data_out = usb_mtp_data_alloc(c); in usb_mtp_command()
1430 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1433 if (!s->write_pending) { in usb_mtp_command()
1435 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1438 s->data_out = usb_mtp_data_alloc(c); in usb_mtp_command()
1441 if (c->argv[0] != FMT_UNDEFINED_OBJECT && in usb_mtp_command()
1442 c->argv[0] != FMT_ASSOCIATION) { in usb_mtp_command()
1444 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1450 if (c->argv[1] != FMT_UNDEFINED_OBJECT && in usb_mtp_command()
1451 c->argv[1] != FMT_ASSOCIATION) { in usb_mtp_command()
1453 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1459 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1464 o = usb_mtp_object_lookup(s, c->argv[0]); in usb_mtp_command()
1467 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1473 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1478 trace_usb_mtp_op_unknown(s->dev.addr, c->code); in usb_mtp_command()
1480 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1486 assert(s->data_in == NULL); in usb_mtp_command()
1487 s->data_in = data_in; in usb_mtp_command()
1489 usb_mtp_queue_result(s, RES_OK, c->trans, nres, res0, 0, 0); in usb_mtp_command()
1492 /* ----------------------------------------------------------------------- */
1498 trace_usb_mtp_reset(s->dev.addr); in usb_mtp_handle_reset()
1501 usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects)); in usb_mtp_handle_reset()
1502 s->session = 0; in usb_mtp_handle_reset()
1503 usb_mtp_data_free(s->data_in); in usb_mtp_handle_reset()
1504 s->data_in = NULL; in usb_mtp_handle_reset()
1505 usb_mtp_data_free(s->data_out); in usb_mtp_handle_reset()
1506 s->data_out = NULL; in usb_mtp_handle_reset()
1507 g_free(s->result); in usb_mtp_handle_reset()
1508 s->result = NULL; in usb_mtp_handle_reset()
1520 case ClassInterfaceOutRequest | 0x64: in usb_mtp_handle_control()
1522 g_free(s->result); in usb_mtp_handle_control()
1523 s->result = NULL; in usb_mtp_handle_control()
1524 usb_mtp_data_free(s->data_in); in usb_mtp_handle_control()
1525 s->data_in = NULL; in usb_mtp_handle_control()
1526 if (s->write_pending) { in usb_mtp_handle_control()
1527 g_free(s->dataset.filename); in usb_mtp_handle_control()
1528 s->write_pending = false; in usb_mtp_handle_control()
1529 s->dataset.size = 0; in usb_mtp_handle_control()
1531 usb_mtp_data_free(s->data_out); in usb_mtp_handle_control()
1532 s->data_out = NULL; in usb_mtp_handle_control()
1534 p->status = USB_RET_STALL; in usb_mtp_handle_control()
1540 if (ret >= 0) { in usb_mtp_handle_control()
1545 trace_usb_mtp_stall(dev->addr, "unknown control request"); in usb_mtp_handle_control()
1560 for (count = 0; count < len; count++) { in utf16_to_str()
1564 wstr[count] = 0; in utf16_to_str()
1566 dlen = wcstombs(NULL, wstr, 0) + 1; in utf16_to_str()
1573 /* Wrapper around write, returns 0 on failure */
1576 uint64_t ret = 0; in write_retry()
1578 if (lseek(fd, offset, SEEK_SET) < 0) { in write_retry()
1590 int ret = 0; in usb_mtp_update_object()
1596 ret = lstat(o->path, &o->stat); in usb_mtp_update_object()
1604 MTPData *d = s->data_out; in usb_mtp_write_data() local
1606 usb_mtp_object_lookup(s, s->dataset.parent_handle); in usb_mtp_write_data()
1610 int ret = 0; in usb_mtp_write_data()
1612 assert(d != NULL); in usb_mtp_write_data()
1614 switch (d->write_status) { in usb_mtp_write_data()
1616 if (!parent || !s->write_pending) { in usb_mtp_write_data()
1617 usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, d->trans, in usb_mtp_write_data()
1618 0, 0, 0, 0); in usb_mtp_write_data()
1622 if (s->dataset.filename) { in usb_mtp_write_data()
1623 path = g_strdup_printf("%s/%s", parent->path, s->dataset.filename); in usb_mtp_write_data()
1624 if (s->dataset.format == FMT_ASSOCIATION) { in usb_mtp_write_data()
1627 usb_mtp_queue_result(s, RES_OK, d->trans, 3, in usb_mtp_write_data()
1629 s->dataset.parent_handle, in usb_mtp_write_data()
1636 d->fd = open(path, O_CREAT | O_WRONLY | in usb_mtp_write_data()
1638 if (d->fd == -1) { in usb_mtp_write_data()
1643 /* Return success if initiator sent 0 sized data */ in usb_mtp_write_data()
1644 if (!s->dataset.size) { in usb_mtp_write_data()
1647 if (d->length != MTP_WRITE_BUF_SZ && !d->pending) { in usb_mtp_write_data()
1648 d->write_status = WRITE_END; in usb_mtp_write_data()
1654 rc = write_retry(d->fd, d->data, d->data_offset, in usb_mtp_write_data()
1655 d->offset - d->data_offset); in usb_mtp_write_data()
1656 if (rc != d->data_offset) { in usb_mtp_write_data()
1660 if (d->write_status != WRITE_END) { in usb_mtp_write_data()
1669 if ((s->dataset.size != 0xFFFFFFFF && in usb_mtp_write_data()
1670 d->offset != s->dataset.size) || in usb_mtp_write_data()
1671 usb_mtp_update_object(parent, s->dataset.filename)) { in usb_mtp_write_data()
1672 usb_mtp_queue_result(s, RES_INCOMPLETE_TRANSFER, d->trans, in usb_mtp_write_data()
1673 0, 0, 0, 0); in usb_mtp_write_data()
1681 usb_mtp_queue_result(s, RES_STORE_FULL, d->trans, in usb_mtp_write_data()
1682 0, 0, 0, 0); in usb_mtp_write_data()
1684 usb_mtp_queue_result(s, RES_OK, d->trans, in usb_mtp_write_data()
1685 0, 0, 0, 0); in usb_mtp_write_data()
1692 if (d->fd != -1) { in usb_mtp_write_data()
1693 close(d->fd); in usb_mtp_write_data()
1694 d->fd = -1; in usb_mtp_write_data()
1696 g_free(s->dataset.filename); in usb_mtp_write_data()
1697 s->dataset.size = 0; in usb_mtp_write_data()
1699 s->write_pending = false; in usb_mtp_write_data()
1704 MTPData *d = s->data_out; in usb_mtp_write_metadata() local
1705 ObjectInfo *dataset = (ObjectInfo *)d->data; in usb_mtp_write_metadata()
1708 MTPObject *p = usb_mtp_object_lookup(s, s->dataset.parent_handle); in usb_mtp_write_metadata()
1709 uint32_t next_handle = s->next_handle; in usb_mtp_write_metadata()
1710 size_t filename_chars = dlen - offsetof(ObjectInfo, filename); in usb_mtp_write_metadata()
1713 * filename is utf-16. We're intentionally doing in usb_mtp_write_metadata()
1719 assert(!s->write_pending); in usb_mtp_write_metadata()
1722 filename = utf16_to_str(MIN(dataset->length, filename_chars), in usb_mtp_write_metadata()
1723 dataset->filename); in usb_mtp_write_metadata()
1726 usb_mtp_queue_result(s, RES_PARAMETER_NOT_SUPPORTED, d->trans, in usb_mtp_write_metadata()
1727 0, 0, 0, 0); in usb_mtp_write_metadata()
1732 o = usb_mtp_object_lookup_name(p, filename, -1); in usb_mtp_write_metadata()
1734 next_handle = o->handle; in usb_mtp_write_metadata()
1737 s->dataset.filename = filename; in usb_mtp_write_metadata()
1738 s->dataset.format = dataset->format; in usb_mtp_write_metadata()
1739 s->dataset.size = dataset->size; in usb_mtp_write_metadata()
1740 s->write_pending = true; in usb_mtp_write_metadata()
1742 if (s->dataset.format == FMT_ASSOCIATION) { in usb_mtp_write_metadata()
1745 usb_mtp_queue_result(s, RES_OK, d->trans, 3, QEMU_STORAGE_ID, in usb_mtp_write_metadata()
1746 s->dataset.parent_handle, next_handle); in usb_mtp_write_metadata()
1753 MTPData *d = s->data_out; in usb_mtp_get_data() local
1755 uint32_t data_len = p->iov.size; in usb_mtp_get_data()
1758 if (!d) { in usb_mtp_get_data()
1759 usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, 0, in usb_mtp_get_data()
1760 0, 0, 0, 0); in usb_mtp_get_data()
1763 if (d->first) { in usb_mtp_get_data()
1765 total_len = cpu_to_le32(container->length) - sizeof(mtp_container); in usb_mtp_get_data()
1767 data_len -= sizeof(mtp_container); in usb_mtp_get_data()
1769 usb_mtp_realloc(d, total_len); in usb_mtp_get_data()
1770 d->length += total_len; in usb_mtp_get_data()
1772 usb_mtp_realloc(d, MTP_WRITE_BUF_SZ - sizeof(mtp_container)); in usb_mtp_get_data()
1773 d->length += MTP_WRITE_BUF_SZ - sizeof(mtp_container); in usb_mtp_get_data()
1775 d->offset = 0; in usb_mtp_get_data()
1776 d->first = false; in usb_mtp_get_data()
1777 d->pending = false; in usb_mtp_get_data()
1778 d->data_offset = 0; in usb_mtp_get_data()
1779 d->write_status = WRITE_START; in usb_mtp_get_data()
1782 if (d->pending) { in usb_mtp_get_data()
1783 memset(d->data, 0, d->length); in usb_mtp_get_data()
1784 if (d->length != MTP_WRITE_BUF_SZ) { in usb_mtp_get_data()
1785 usb_mtp_realloc(d, MTP_WRITE_BUF_SZ - d->length); in usb_mtp_get_data()
1786 d->length += (MTP_WRITE_BUF_SZ - d->length); in usb_mtp_get_data()
1788 d->pending = false; in usb_mtp_get_data()
1789 d->write_status = WRITE_CONTINUE; in usb_mtp_get_data()
1790 d->data_offset = 0; in usb_mtp_get_data()
1793 if (d->length - d->data_offset > data_len) { in usb_mtp_get_data()
1796 dlen = d->length - d->data_offset; in usb_mtp_get_data()
1799 switch (d->code) { in usb_mtp_get_data()
1801 usb_packet_copy(p, d->data + d->data_offset, dlen); in usb_mtp_get_data()
1802 d->offset += dlen; in usb_mtp_get_data()
1803 d->data_offset += dlen; in usb_mtp_get_data()
1804 if (d->data_offset == d->length) { in usb_mtp_get_data()
1806 if (!s->result) { in usb_mtp_get_data()
1809 usb_mtp_data_free(s->data_out); in usb_mtp_get_data()
1810 s->data_out = NULL; in usb_mtp_get_data()
1815 usb_packet_copy(p, d->data + d->data_offset, dlen); in usb_mtp_get_data()
1816 d->offset += dlen; in usb_mtp_get_data()
1817 d->data_offset += dlen; in usb_mtp_get_data()
1818 if ((p->iov.size % 64) || !p->iov.size) { in usb_mtp_get_data()
1819 assert((s->dataset.size == 0xFFFFFFFF) || in usb_mtp_get_data()
1820 (s->dataset.size == d->offset)); in usb_mtp_get_data()
1822 if (d->length == MTP_WRITE_BUF_SZ) { in usb_mtp_get_data()
1823 d->write_status = WRITE_END; in usb_mtp_get_data()
1825 d->write_status = WRITE_START; in usb_mtp_get_data()
1827 usb_mtp_write_data(s, 0); in usb_mtp_get_data()
1828 usb_mtp_data_free(s->data_out); in usb_mtp_get_data()
1829 s->data_out = NULL; in usb_mtp_get_data()
1832 if (d->data_offset == d->length) { in usb_mtp_get_data()
1833 d->pending = true; in usb_mtp_get_data()
1834 usb_mtp_write_data(s, 0); in usb_mtp_get_data()
1838 p->status = USB_RET_STALL; in usb_mtp_get_data()
1852 switch (p->ep->nr) { in usb_mtp_handle_data()
1854 if (s->data_out != NULL) { in usb_mtp_handle_data()
1856 trace_usb_mtp_stall(s->dev.addr, "awaiting data-out"); in usb_mtp_handle_data()
1857 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1860 if (p->iov.size < sizeof(container)) { in usb_mtp_handle_data()
1861 trace_usb_mtp_stall(s->dev.addr, "packet too small"); in usb_mtp_handle_data()
1862 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1865 if (s->data_in != NULL) { in usb_mtp_handle_data()
1866 MTPData *d = s->data_in; in usb_mtp_handle_data() local
1867 uint64_t dlen = d->length - d->offset; in usb_mtp_handle_data()
1868 if (d->first) { in usb_mtp_handle_data()
1869 trace_usb_mtp_data_in(s->dev.addr, d->trans, d->length); in usb_mtp_handle_data()
1870 if (d->length + sizeof(container) > 0xFFFFFFFF) { in usb_mtp_handle_data()
1871 container.length = cpu_to_le32(0xFFFFFFFF); in usb_mtp_handle_data()
1874 cpu_to_le32(d->length + sizeof(container)); in usb_mtp_handle_data()
1877 container.code = cpu_to_le16(d->code); in usb_mtp_handle_data()
1878 container.trans = cpu_to_le32(d->trans); in usb_mtp_handle_data()
1880 d->first = false; in usb_mtp_handle_data()
1881 if (dlen > p->iov.size - sizeof(container)) { in usb_mtp_handle_data()
1882 dlen = p->iov.size - sizeof(container); in usb_mtp_handle_data()
1885 if (dlen > p->iov.size) { in usb_mtp_handle_data()
1886 dlen = p->iov.size; in usb_mtp_handle_data()
1889 if (d->fd == -1) { in usb_mtp_handle_data()
1890 usb_packet_copy(p, d->data + d->offset, dlen); in usb_mtp_handle_data()
1892 if (d->alloc < p->iov.size) { in usb_mtp_handle_data()
1893 d->alloc = p->iov.size; in usb_mtp_handle_data()
1894 d->data = g_realloc(d->data, d->alloc); in usb_mtp_handle_data()
1896 rc = read(d->fd, d->data, dlen); in usb_mtp_handle_data()
1898 memset(d->data, 0, dlen); in usb_mtp_handle_data()
1899 s->result->code = RES_INCOMPLETE_TRANSFER; in usb_mtp_handle_data()
1901 usb_packet_copy(p, d->data, dlen); in usb_mtp_handle_data()
1903 d->offset += dlen; in usb_mtp_handle_data()
1904 if (d->offset == d->length) { in usb_mtp_handle_data()
1905 usb_mtp_data_free(s->data_in); in usb_mtp_handle_data()
1906 s->data_in = NULL; in usb_mtp_handle_data()
1908 } else if (s->result != NULL) { in usb_mtp_handle_data()
1909 MTPControl *r = s->result; in usb_mtp_handle_data()
1910 int length = sizeof(container) + r->argc * sizeof(uint32_t); in usb_mtp_handle_data()
1911 if (r->code == RES_OK) { in usb_mtp_handle_data()
1912 trace_usb_mtp_success(s->dev.addr, r->trans, in usb_mtp_handle_data()
1913 (r->argc > 0) ? r->argv[0] : 0, in usb_mtp_handle_data()
1914 (r->argc > 1) ? r->argv[1] : 0); in usb_mtp_handle_data()
1916 trace_usb_mtp_error(s->dev.addr, r->code, r->trans, in usb_mtp_handle_data()
1917 (r->argc > 0) ? r->argv[0] : 0, in usb_mtp_handle_data()
1918 (r->argc > 1) ? r->argv[1] : 0); in usb_mtp_handle_data()
1922 container.code = cpu_to_le16(r->code); in usb_mtp_handle_data()
1923 container.trans = cpu_to_le32(r->trans); in usb_mtp_handle_data()
1924 for (i = 0; i < r->argc; i++) { in usb_mtp_handle_data()
1925 params[i] = cpu_to_le32(r->argv[i]); in usb_mtp_handle_data()
1928 usb_packet_copy(p, &params, length - sizeof(container)); in usb_mtp_handle_data()
1929 g_free(s->result); in usb_mtp_handle_data()
1930 s->result = NULL; in usb_mtp_handle_data()
1934 if (p->iov.size < sizeof(container)) { in usb_mtp_handle_data()
1935 trace_usb_mtp_stall(s->dev.addr, "packet too small"); in usb_mtp_handle_data()
1936 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1939 if ((s->data_out != NULL) && !s->data_out->first) { in usb_mtp_handle_data()
1947 if (s->data_in || s->data_out || s->result) { in usb_mtp_handle_data()
1948 trace_usb_mtp_stall(s->dev.addr, "transaction inflight"); in usb_mtp_handle_data()
1949 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1953 cmd.argc = (le32_to_cpu(container.length) - sizeof(container)) in usb_mtp_handle_data()
1959 if (p->iov.size < sizeof(container) + cmd.argc * sizeof(uint32_t)) { in usb_mtp_handle_data()
1960 trace_usb_mtp_stall(s->dev.addr, "packet too small"); in usb_mtp_handle_data()
1961 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1965 for (i = 0; i < cmd.argc; i++) { in usb_mtp_handle_data()
1968 trace_usb_mtp_command(s->dev.addr, cmd.code, cmd.trans, in usb_mtp_handle_data()
1969 (cmd.argc > 0) ? cmd.argv[0] : 0, in usb_mtp_handle_data()
1970 (cmd.argc > 1) ? cmd.argv[1] : 0, in usb_mtp_handle_data()
1971 (cmd.argc > 2) ? cmd.argv[2] : 0, in usb_mtp_handle_data()
1972 (cmd.argc > 3) ? cmd.argv[3] : 0, in usb_mtp_handle_data()
1973 (cmd.argc > 4) ? cmd.argv[4] : 0); in usb_mtp_handle_data()
1980 if (s->result != NULL) { in usb_mtp_handle_data()
1986 /* not needed as long as the mtp device is read-only */ in usb_mtp_handle_data()
1987 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1992 if (!QTAILQ_EMPTY(&s->events)) { in usb_mtp_handle_data()
1993 struct MTPMonEntry *e = QTAILQ_LAST(&s->events); in usb_mtp_handle_data()
1997 if (p->iov.size < len) { in usb_mtp_handle_data()
1998 trace_usb_mtp_stall(s->dev.addr, in usb_mtp_handle_data()
2000 p->status = USB_RET_STALL; in usb_mtp_handle_data()
2004 QTAILQ_REMOVE(&s->events, e, next); in usb_mtp_handle_data()
2007 container.code = cpu_to_le16(e->event); in usb_mtp_handle_data()
2008 container.trans = 0; /* no trans specific events */ in usb_mtp_handle_data()
2009 handle = cpu_to_le32(e->handle); in usb_mtp_handle_data()
2015 p->status = USB_RET_NAK; in usb_mtp_handle_data()
2018 trace_usb_mtp_stall(s->dev.addr, "invalid endpoint"); in usb_mtp_handle_data()
2019 p->status = USB_RET_STALL; in usb_mtp_handle_data()
2023 if (p->actual_length == 0) { in usb_mtp_handle_data()
2024 trace_usb_mtp_nak(s->dev.addr, p->ep->nr); in usb_mtp_handle_data()
2025 p->status = USB_RET_NAK; in usb_mtp_handle_data()
2028 trace_usb_mtp_xfer(s->dev.addr, p->ep->nr, p->actual_length, in usb_mtp_handle_data()
2029 p->iov.size); in usb_mtp_handle_data()
2038 if ((s->root == NULL) || !g_path_is_absolute(s->root)) { in usb_mtp_realize()
2039 error_setg(errp, "usb-mtp: rootdir must be configured and be an absolute path"); in usb_mtp_realize()
2043 if (access(s->root, R_OK) != 0) { in usb_mtp_realize()
2044 error_setg(errp, "usb-mtp: rootdir does not exist/not readable"); in usb_mtp_realize()
2046 } else if (!s->readonly && access(s->root, W_OK) != 0) { in usb_mtp_realize()
2047 error_setg(errp, "usb-mtp: rootdir does not have write permissions"); in usb_mtp_realize()
2052 if (!s->readonly) { in usb_mtp_realize()
2053 s->flags |= (1 << MTP_FLAG_WRITABLE); in usb_mtp_realize()
2056 if (s->desc == NULL) { in usb_mtp_realize()
2061 s->desc = g_path_get_basename(s->root); in usb_mtp_realize()
2066 QTAILQ_INIT(&s->objects); in usb_mtp_realize()
2071 .name = "usb-mtp",
2093 uc->realize = usb_mtp_realize; in usb_mtp_class_initfn()
2094 uc->product_desc = "QEMU USB MTP"; in usb_mtp_class_initfn()
2095 uc->usb_desc = &desc; in usb_mtp_class_initfn()
2096 uc->cancel_packet = usb_mtp_cancel_packet; in usb_mtp_class_initfn()
2097 uc->handle_attach = usb_desc_attach; in usb_mtp_class_initfn()
2098 uc->handle_reset = usb_mtp_handle_reset; in usb_mtp_class_initfn()
2099 uc->handle_control = usb_mtp_handle_control; in usb_mtp_class_initfn()
2100 uc->handle_data = usb_mtp_handle_data; in usb_mtp_class_initfn()
2101 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); in usb_mtp_class_initfn()
2102 dc->desc = "USB Media Transfer Protocol device"; in usb_mtp_class_initfn()
2103 dc->fw_name = "mtp"; in usb_mtp_class_initfn()
2104 dc->vmsd = &vmstate_usb_mtp; in usb_mtp_class_initfn()