Lines Matching +full:- +full:- +full:-
14 #include "qemu/error-report.h"
25 #include "hw/qdev-properties.h"
32 /* ----------------------------------------------------------------------- */
124 /* ----------------------------------------------------------------------- */
232 uint8_t filename[0]; /* UTF-16 encoded */
239 #define TYPE_USB_MTP "usb-mtp"
246 #define FLAG_SET(_mtp, _flag) ((_mtp)->flags & (1 << (_flag)))
248 /* ----------------------------------------------------------------------- */
378 /* ----------------------------------------------------------------------- */
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()
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()
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()
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 /* ----------------------------------------------------------------------- */
832 trace_usb_mtp_op_get_device_info(s->dev.addr); in usb_mtp_get_device_info()
861 trace_usb_mtp_op_get_storage_ids(s->dev.addr); in usb_mtp_get_storage_ids()
874 trace_usb_mtp_op_get_storage_info(s->dev.addr); in usb_mtp_get_storage_info()
886 rc = statvfs(s->root, &buf); in usb_mtp_get_storage_info()
897 usb_mtp_add_str(d, s->desc); in usb_mtp_get_storage_info()
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()
926 trace_usb_mtp_op_get_object_info(s->dev.addr, o->handle, o->path); in usb_mtp_get_object_info()
929 usb_mtp_add_u16(d, o->format); in usb_mtp_get_object_info()
932 if (o->stat.st_size > 0xFFFFFFFF) { in usb_mtp_get_object_info()
935 usb_mtp_add_u32(d, o->stat.st_size); 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()
951 if (o->format == FMT_ASSOCIATION) { 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()
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()
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()
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()
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()
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()
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()
1042 switch (c->argv[0]) { in usb_mtp_get_object_prop_desc()
1104 switch (c->argv[1]) { 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()
1118 usb_mtp_add_u32(d, o->parent->handle); 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()
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()
1210 o = QTAILQ_FIRST(&s->objects); in usb_mtp_object_delete()
1247 if (c->code >= CMD_CLOSE_SESSION && s->session == 0) { in usb_mtp_command()
1249 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1254 switch (c->code) { in usb_mtp_command()
1259 if (s->session) { in usb_mtp_command()
1261 c->trans, 1, s->session, 0, 0); in usb_mtp_command()
1264 if (c->argv[0] == 0) { in usb_mtp_command()
1266 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1269 trace_usb_mtp_op_open_session(s->dev.addr); in usb_mtp_command()
1270 s->session = c->argv[0]; in usb_mtp_command()
1271 usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root); in usb_mtp_command()
1273 s->file_monitor = qemu_file_monitor_new(&err); in usb_mtp_command()
1276 "usb-mtp: file monitoring init failed: "); in usb_mtp_command()
1278 QTAILQ_INIT(&s->events); in usb_mtp_command()
1282 trace_usb_mtp_op_close_session(s->dev.addr); in usb_mtp_command()
1283 s->session = 0; in usb_mtp_command()
1284 s->next_handle = 0; in usb_mtp_command()
1286 usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects)); in usb_mtp_command()
1287 assert(QTAILQ_EMPTY(&s->objects)); in usb_mtp_command()
1293 if (c->argv[0] != QEMU_STORAGE_ID && in usb_mtp_command()
1294 c->argv[0] != 0xffffffff) { in usb_mtp_command()
1296 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1303 if (c->argv[0] != QEMU_STORAGE_ID && in usb_mtp_command()
1304 c->argv[0] != 0xffffffff) { in usb_mtp_command()
1306 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1309 if (c->argv[1] != 0x00000000) { in usb_mtp_command()
1311 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1314 if (c->argv[2] == 0x00000000 || in usb_mtp_command()
1315 c->argv[2] == 0xffffffff) { in usb_mtp_command()
1316 o = QTAILQ_FIRST(&s->objects); in usb_mtp_command()
1318 o = usb_mtp_object_lookup(s, c->argv[2]); in usb_mtp_command()
1322 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1325 if (o->format != FMT_ASSOCIATION) { in usb_mtp_command()
1327 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1331 if (c->code == CMD_GET_NUM_OBJECTS) { in usb_mtp_command()
1332 trace_usb_mtp_op_get_num_objects(s->dev.addr, o->handle, o->path); in usb_mtp_command()
1334 res0 = o->nchildren; in usb_mtp_command()
1340 o = usb_mtp_object_lookup(s, c->argv[0]); in usb_mtp_command()
1343 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1349 o = usb_mtp_object_lookup(s, c->argv[0]); in usb_mtp_command()
1352 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1355 if (o->format == FMT_ASSOCIATION) { in usb_mtp_command()
1357 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1363 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1368 usb_mtp_object_delete(s, c->argv[0], c->argv[1], c->trans); in usb_mtp_command()
1371 o = usb_mtp_object_lookup(s, c->argv[0]); in usb_mtp_command()
1374 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1377 if (o->format == FMT_ASSOCIATION) { in usb_mtp_command()
1379 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1385 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1389 res0 = data_in->length; in usb_mtp_command()
1392 /* Return error if store is read-only */ in usb_mtp_command()
1395 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1396 } else if (c->argv[0] && (c->argv[0] != QEMU_STORAGE_ID)) { in usb_mtp_command()
1398 usb_mtp_queue_result(s, RES_STORE_NOT_AVAILABLE, c->trans, in usb_mtp_command()
1400 } else if (c->argv[1] && !c->argv[0]) { in usb_mtp_command()
1402 usb_mtp_queue_result(s, RES_DESTINATION_UNSUPPORTED, c->trans, in usb_mtp_command()
1405 uint32_t handle = c->argv[1]; in usb_mtp_command()
1408 o = QTAILQ_FIRST(&s->objects); in usb_mtp_command()
1413 usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE, c->trans, in usb_mtp_command()
1415 } else if (o->format != FMT_ASSOCIATION) { in usb_mtp_command()
1416 usb_mtp_queue_result(s, RES_INVALID_PARENT_OBJECT, c->trans, in usb_mtp_command()
1421 s->dataset.parent_handle = o->handle; in usb_mtp_command()
1423 s->data_out = usb_mtp_data_alloc(c); in usb_mtp_command()
1428 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1431 if (!s->write_pending) { in usb_mtp_command()
1433 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1436 s->data_out = usb_mtp_data_alloc(c); in usb_mtp_command()
1439 if (c->argv[0] != FMT_UNDEFINED_OBJECT && in usb_mtp_command()
1440 c->argv[0] != FMT_ASSOCIATION) { in usb_mtp_command()
1442 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1448 if (c->argv[1] != FMT_UNDEFINED_OBJECT && in usb_mtp_command()
1449 c->argv[1] != FMT_ASSOCIATION) { in usb_mtp_command()
1451 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1457 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1462 o = usb_mtp_object_lookup(s, c->argv[0]); in usb_mtp_command()
1465 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1471 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1476 trace_usb_mtp_op_unknown(s->dev.addr, c->code); in usb_mtp_command()
1478 c->trans, 0, 0, 0, 0); in usb_mtp_command()
1484 assert(s->data_in == NULL); in usb_mtp_command()
1485 s->data_in = data_in; in usb_mtp_command()
1487 usb_mtp_queue_result(s, RES_OK, c->trans, nres, res0, 0, 0); in usb_mtp_command()
1490 /* ----------------------------------------------------------------------- */
1496 trace_usb_mtp_reset(s->dev.addr); in usb_mtp_handle_reset()
1499 usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects)); in usb_mtp_handle_reset()
1500 s->session = 0; in usb_mtp_handle_reset()
1501 usb_mtp_data_free(s->data_in); in usb_mtp_handle_reset()
1502 s->data_in = NULL; in usb_mtp_handle_reset()
1503 usb_mtp_data_free(s->data_out); in usb_mtp_handle_reset()
1504 s->data_out = NULL; in usb_mtp_handle_reset()
1505 g_free(s->result); in usb_mtp_handle_reset()
1506 s->result = NULL; in usb_mtp_handle_reset()
1520 g_free(s->result); in usb_mtp_handle_control()
1521 s->result = NULL; in usb_mtp_handle_control()
1522 usb_mtp_data_free(s->data_in); in usb_mtp_handle_control()
1523 s->data_in = NULL; in usb_mtp_handle_control()
1524 if (s->write_pending) { in usb_mtp_handle_control()
1525 g_free(s->dataset.filename); in usb_mtp_handle_control()
1526 s->write_pending = false; in usb_mtp_handle_control()
1527 s->dataset.size = 0; in usb_mtp_handle_control()
1529 usb_mtp_data_free(s->data_out); in usb_mtp_handle_control()
1530 s->data_out = NULL; in usb_mtp_handle_control()
1532 p->status = USB_RET_STALL; in usb_mtp_handle_control()
1543 trace_usb_mtp_stall(dev->addr, "unknown control request"); in usb_mtp_handle_control()
1594 ret = lstat(o->path, &o->stat); in usb_mtp_update_object()
1602 MTPData *d = s->data_out; in usb_mtp_write_data()
1604 usb_mtp_object_lookup(s, s->dataset.parent_handle); in usb_mtp_write_data()
1612 switch (d->write_status) { in usb_mtp_write_data()
1614 if (!parent || !s->write_pending) { in usb_mtp_write_data()
1615 usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, d->trans, in usb_mtp_write_data()
1620 if (s->dataset.filename) { in usb_mtp_write_data()
1621 path = g_strdup_printf("%s/%s", parent->path, s->dataset.filename); in usb_mtp_write_data()
1622 if (s->dataset.format == FMT_ASSOCIATION) { in usb_mtp_write_data()
1625 usb_mtp_queue_result(s, RES_OK, d->trans, 3, in usb_mtp_write_data()
1627 s->dataset.parent_handle, in usb_mtp_write_data()
1634 d->fd = open(path, O_CREAT | O_WRONLY | in usb_mtp_write_data()
1636 if (d->fd == -1) { in usb_mtp_write_data()
1642 if (!s->dataset.size) { in usb_mtp_write_data()
1645 if (d->length != MTP_WRITE_BUF_SZ && !d->pending) { in usb_mtp_write_data()
1646 d->write_status = WRITE_END; in usb_mtp_write_data()
1652 rc = write_retry(d->fd, d->data, d->data_offset, in usb_mtp_write_data()
1653 d->offset - d->data_offset); in usb_mtp_write_data()
1654 if (rc != d->data_offset) { in usb_mtp_write_data()
1658 if (d->write_status != WRITE_END) { in usb_mtp_write_data()
1667 if ((s->dataset.size != 0xFFFFFFFF && in usb_mtp_write_data()
1668 d->offset != s->dataset.size) || in usb_mtp_write_data()
1669 usb_mtp_update_object(parent, s->dataset.filename)) { in usb_mtp_write_data()
1670 usb_mtp_queue_result(s, RES_INCOMPLETE_TRANSFER, d->trans, in usb_mtp_write_data()
1679 usb_mtp_queue_result(s, RES_STORE_FULL, d->trans, in usb_mtp_write_data()
1682 usb_mtp_queue_result(s, RES_OK, d->trans, in usb_mtp_write_data()
1690 if (d->fd != -1) { in usb_mtp_write_data()
1691 close(d->fd); in usb_mtp_write_data()
1692 d->fd = -1; in usb_mtp_write_data()
1694 g_free(s->dataset.filename); in usb_mtp_write_data()
1695 s->dataset.size = 0; in usb_mtp_write_data()
1697 s->write_pending = false; in usb_mtp_write_data()
1702 MTPData *d = s->data_out; in usb_mtp_write_metadata()
1703 ObjectInfo *dataset = (ObjectInfo *)d->data; in usb_mtp_write_metadata()
1706 MTPObject *p = usb_mtp_object_lookup(s, s->dataset.parent_handle); in usb_mtp_write_metadata()
1707 uint32_t next_handle = s->next_handle; in usb_mtp_write_metadata()
1708 size_t filename_chars = dlen - offsetof(ObjectInfo, filename); in usb_mtp_write_metadata()
1711 * filename is utf-16. We're intentionally doing in usb_mtp_write_metadata()
1717 assert(!s->write_pending); in usb_mtp_write_metadata()
1720 filename = utf16_to_str(MIN(dataset->length, filename_chars), in usb_mtp_write_metadata()
1721 dataset->filename); in usb_mtp_write_metadata()
1724 usb_mtp_queue_result(s, RES_PARAMETER_NOT_SUPPORTED, d->trans, in usb_mtp_write_metadata()
1730 o = usb_mtp_object_lookup_name(p, filename, -1); in usb_mtp_write_metadata()
1732 next_handle = o->handle; in usb_mtp_write_metadata()
1735 s->dataset.filename = filename; in usb_mtp_write_metadata()
1736 s->dataset.format = dataset->format; in usb_mtp_write_metadata()
1737 s->dataset.size = dataset->size; in usb_mtp_write_metadata()
1738 s->write_pending = true; in usb_mtp_write_metadata()
1740 if (s->dataset.format == FMT_ASSOCIATION) { in usb_mtp_write_metadata()
1743 usb_mtp_queue_result(s, RES_OK, d->trans, 3, QEMU_STORAGE_ID, in usb_mtp_write_metadata()
1744 s->dataset.parent_handle, next_handle); in usb_mtp_write_metadata()
1751 MTPData *d = s->data_out; in usb_mtp_get_data()
1753 uint32_t data_len = p->iov.size; in usb_mtp_get_data()
1761 if (d->first) { in usb_mtp_get_data()
1763 total_len = cpu_to_le32(container->length) - sizeof(mtp_container); in usb_mtp_get_data()
1765 data_len -= sizeof(mtp_container); in usb_mtp_get_data()
1768 d->length += total_len; in usb_mtp_get_data()
1770 usb_mtp_realloc(d, MTP_WRITE_BUF_SZ - sizeof(mtp_container)); in usb_mtp_get_data()
1771 d->length += MTP_WRITE_BUF_SZ - sizeof(mtp_container); in usb_mtp_get_data()
1773 d->offset = 0; in usb_mtp_get_data()
1774 d->first = false; in usb_mtp_get_data()
1775 d->pending = false; in usb_mtp_get_data()
1776 d->data_offset = 0; in usb_mtp_get_data()
1777 d->write_status = WRITE_START; in usb_mtp_get_data()
1780 if (d->pending) { in usb_mtp_get_data()
1781 memset(d->data, 0, d->length); in usb_mtp_get_data()
1782 if (d->length != MTP_WRITE_BUF_SZ) { in usb_mtp_get_data()
1783 usb_mtp_realloc(d, MTP_WRITE_BUF_SZ - d->length); in usb_mtp_get_data()
1784 d->length += (MTP_WRITE_BUF_SZ - d->length); in usb_mtp_get_data()
1786 d->pending = false; in usb_mtp_get_data()
1787 d->write_status = WRITE_CONTINUE; in usb_mtp_get_data()
1788 d->data_offset = 0; in usb_mtp_get_data()
1791 if (d->length - d->data_offset > data_len) { in usb_mtp_get_data()
1794 dlen = d->length - d->data_offset; in usb_mtp_get_data()
1797 switch (d->code) { in usb_mtp_get_data()
1799 usb_packet_copy(p, d->data + d->data_offset, dlen); in usb_mtp_get_data()
1800 d->offset += dlen; in usb_mtp_get_data()
1801 d->data_offset += dlen; in usb_mtp_get_data()
1802 if (d->data_offset == d->length) { in usb_mtp_get_data()
1804 if (!s->result) { in usb_mtp_get_data()
1807 usb_mtp_data_free(s->data_out); in usb_mtp_get_data()
1808 s->data_out = NULL; in usb_mtp_get_data()
1813 usb_packet_copy(p, d->data + d->data_offset, dlen); in usb_mtp_get_data()
1814 d->offset += dlen; in usb_mtp_get_data()
1815 d->data_offset += dlen; in usb_mtp_get_data()
1816 if ((p->iov.size % 64) || !p->iov.size) { in usb_mtp_get_data()
1817 assert((s->dataset.size == 0xFFFFFFFF) || in usb_mtp_get_data()
1818 (s->dataset.size == d->offset)); in usb_mtp_get_data()
1820 if (d->length == MTP_WRITE_BUF_SZ) { in usb_mtp_get_data()
1821 d->write_status = WRITE_END; in usb_mtp_get_data()
1823 d->write_status = WRITE_START; in usb_mtp_get_data()
1826 usb_mtp_data_free(s->data_out); in usb_mtp_get_data()
1827 s->data_out = NULL; in usb_mtp_get_data()
1830 if (d->data_offset == d->length) { in usb_mtp_get_data()
1831 d->pending = true; in usb_mtp_get_data()
1836 p->status = USB_RET_STALL; in usb_mtp_get_data()
1850 switch (p->ep->nr) { in usb_mtp_handle_data()
1852 if (s->data_out != NULL) { in usb_mtp_handle_data()
1854 trace_usb_mtp_stall(s->dev.addr, "awaiting data-out"); in usb_mtp_handle_data()
1855 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1858 if (p->iov.size < sizeof(container)) { in usb_mtp_handle_data()
1859 trace_usb_mtp_stall(s->dev.addr, "packet too small"); in usb_mtp_handle_data()
1860 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1863 if (s->data_in != NULL) { in usb_mtp_handle_data()
1864 MTPData *d = s->data_in; in usb_mtp_handle_data()
1865 uint64_t dlen = d->length - d->offset; in usb_mtp_handle_data()
1866 if (d->first) { in usb_mtp_handle_data()
1867 trace_usb_mtp_data_in(s->dev.addr, d->trans, d->length); in usb_mtp_handle_data()
1868 if (d->length + sizeof(container) > 0xFFFFFFFF) { in usb_mtp_handle_data()
1872 cpu_to_le32(d->length + sizeof(container)); in usb_mtp_handle_data()
1875 container.code = cpu_to_le16(d->code); in usb_mtp_handle_data()
1876 container.trans = cpu_to_le32(d->trans); in usb_mtp_handle_data()
1878 d->first = false; in usb_mtp_handle_data()
1879 if (dlen > p->iov.size - sizeof(container)) { in usb_mtp_handle_data()
1880 dlen = p->iov.size - sizeof(container); in usb_mtp_handle_data()
1883 if (dlen > p->iov.size) { in usb_mtp_handle_data()
1884 dlen = p->iov.size; in usb_mtp_handle_data()
1887 if (d->fd == -1) { in usb_mtp_handle_data()
1888 usb_packet_copy(p, d->data + d->offset, dlen); in usb_mtp_handle_data()
1890 if (d->alloc < p->iov.size) { in usb_mtp_handle_data()
1891 d->alloc = p->iov.size; in usb_mtp_handle_data()
1892 d->data = g_realloc(d->data, d->alloc); in usb_mtp_handle_data()
1894 rc = read(d->fd, d->data, dlen); in usb_mtp_handle_data()
1896 memset(d->data, 0, dlen); in usb_mtp_handle_data()
1897 s->result->code = RES_INCOMPLETE_TRANSFER; in usb_mtp_handle_data()
1899 usb_packet_copy(p, d->data, dlen); in usb_mtp_handle_data()
1901 d->offset += dlen; in usb_mtp_handle_data()
1902 if (d->offset == d->length) { in usb_mtp_handle_data()
1903 usb_mtp_data_free(s->data_in); in usb_mtp_handle_data()
1904 s->data_in = NULL; in usb_mtp_handle_data()
1906 } else if (s->result != NULL) { in usb_mtp_handle_data()
1907 MTPControl *r = s->result; in usb_mtp_handle_data()
1908 int length = sizeof(container) + r->argc * sizeof(uint32_t); in usb_mtp_handle_data()
1909 if (r->code == RES_OK) { in usb_mtp_handle_data()
1910 trace_usb_mtp_success(s->dev.addr, r->trans, in usb_mtp_handle_data()
1911 (r->argc > 0) ? r->argv[0] : 0, in usb_mtp_handle_data()
1912 (r->argc > 1) ? r->argv[1] : 0); in usb_mtp_handle_data()
1914 trace_usb_mtp_error(s->dev.addr, r->code, r->trans, in usb_mtp_handle_data()
1915 (r->argc > 0) ? r->argv[0] : 0, in usb_mtp_handle_data()
1916 (r->argc > 1) ? r->argv[1] : 0); in usb_mtp_handle_data()
1920 container.code = cpu_to_le16(r->code); in usb_mtp_handle_data()
1921 container.trans = cpu_to_le32(r->trans); in usb_mtp_handle_data()
1922 for (i = 0; i < r->argc; i++) { in usb_mtp_handle_data()
1923 params[i] = cpu_to_le32(r->argv[i]); in usb_mtp_handle_data()
1926 usb_packet_copy(p, ¶ms, length - sizeof(container)); in usb_mtp_handle_data()
1927 g_free(s->result); in usb_mtp_handle_data()
1928 s->result = NULL; in usb_mtp_handle_data()
1932 if (p->iov.size < sizeof(container)) { in usb_mtp_handle_data()
1933 trace_usb_mtp_stall(s->dev.addr, "packet too small"); in usb_mtp_handle_data()
1934 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1937 if ((s->data_out != NULL) && !s->data_out->first) { in usb_mtp_handle_data()
1945 if (s->data_in || s->data_out || s->result) { in usb_mtp_handle_data()
1946 trace_usb_mtp_stall(s->dev.addr, "transaction inflight"); in usb_mtp_handle_data()
1947 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1951 cmd.argc = (le32_to_cpu(container.length) - sizeof(container)) in usb_mtp_handle_data()
1957 if (p->iov.size < sizeof(container) + cmd.argc * sizeof(uint32_t)) { in usb_mtp_handle_data()
1958 trace_usb_mtp_stall(s->dev.addr, "packet too small"); in usb_mtp_handle_data()
1959 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1966 trace_usb_mtp_command(s->dev.addr, cmd.code, cmd.trans, in usb_mtp_handle_data()
1978 if (s->result != NULL) { in usb_mtp_handle_data()
1984 /* not needed as long as the mtp device is read-only */ in usb_mtp_handle_data()
1985 p->status = USB_RET_STALL; in usb_mtp_handle_data()
1990 if (!QTAILQ_EMPTY(&s->events)) { in usb_mtp_handle_data()
1991 struct MTPMonEntry *e = QTAILQ_LAST(&s->events); in usb_mtp_handle_data()
1995 if (p->iov.size < len) { in usb_mtp_handle_data()
1996 trace_usb_mtp_stall(s->dev.addr, in usb_mtp_handle_data()
1998 p->status = USB_RET_STALL; in usb_mtp_handle_data()
2002 QTAILQ_REMOVE(&s->events, e, next); in usb_mtp_handle_data()
2005 container.code = cpu_to_le16(e->event); in usb_mtp_handle_data()
2007 handle = cpu_to_le32(e->handle); in usb_mtp_handle_data()
2013 p->status = USB_RET_NAK; in usb_mtp_handle_data()
2016 trace_usb_mtp_stall(s->dev.addr, "invalid endpoint"); in usb_mtp_handle_data()
2017 p->status = USB_RET_STALL; in usb_mtp_handle_data()
2021 if (p->actual_length == 0) { in usb_mtp_handle_data()
2022 trace_usb_mtp_nak(s->dev.addr, p->ep->nr); in usb_mtp_handle_data()
2023 p->status = USB_RET_NAK; in usb_mtp_handle_data()
2026 trace_usb_mtp_xfer(s->dev.addr, p->ep->nr, p->actual_length, in usb_mtp_handle_data()
2027 p->iov.size); in usb_mtp_handle_data()
2036 if ((s->root == NULL) || !g_path_is_absolute(s->root)) { in usb_mtp_realize()
2037 error_setg(errp, "usb-mtp: rootdir must be configured and be an absolute path"); in usb_mtp_realize()
2041 if (access(s->root, R_OK) != 0) { in usb_mtp_realize()
2042 error_setg(errp, "usb-mtp: rootdir does not exist/not readable"); in usb_mtp_realize()
2044 } else if (!s->readonly && access(s->root, W_OK) != 0) { in usb_mtp_realize()
2045 error_setg(errp, "usb-mtp: rootdir does not have write permissions"); in usb_mtp_realize()
2050 if (!s->readonly) { in usb_mtp_realize()
2051 s->flags |= (1 << MTP_FLAG_WRITABLE); in usb_mtp_realize()
2054 if (s->desc == NULL) { in usb_mtp_realize()
2059 s->desc = g_path_get_basename(s->root); in usb_mtp_realize()
2064 QTAILQ_INIT(&s->objects); in usb_mtp_realize()
2069 .name = "usb-mtp",
2090 uc->realize = usb_mtp_realize; in usb_mtp_class_initfn()
2091 uc->product_desc = "QEMU USB MTP"; in usb_mtp_class_initfn()
2092 uc->usb_desc = &desc; in usb_mtp_class_initfn()
2093 uc->cancel_packet = usb_mtp_cancel_packet; in usb_mtp_class_initfn()
2094 uc->handle_attach = usb_desc_attach; in usb_mtp_class_initfn()
2095 uc->handle_reset = usb_mtp_handle_reset; in usb_mtp_class_initfn()
2096 uc->handle_control = usb_mtp_handle_control; in usb_mtp_class_initfn()
2097 uc->handle_data = usb_mtp_handle_data; in usb_mtp_class_initfn()
2098 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); in usb_mtp_class_initfn()
2099 dc->desc = "USB Media Transfer Protocol device"; in usb_mtp_class_initfn()
2100 dc->fw_name = "mtp"; in usb_mtp_class_initfn()
2101 dc->vmsd = &vmstate_usb_mtp; in usb_mtp_class_initfn()