diff options
Diffstat (limited to 'hw/usb')
-rw-r--r-- | hw/usb/dev-mtp.c | 35 | ||||
-rw-r--r-- | hw/usb/hcd-ohci.c | 119 |
2 files changed, 134 insertions, 20 deletions
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 8b44032900..943f930404 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -50,6 +50,7 @@ enum mtp_code { RES_INVALID_TRANSACTION_ID = 0x2004, RES_OPERATION_NOT_SUPPORTED = 0x2005, RES_PARAMETER_NOT_SUPPORTED = 0x2006, + RES_INCOMPLETE_TRANSFER = 0x2007, RES_INVALID_STORAGE_ID = 0x2008, RES_INVALID_OBJECT_HANDLE = 0x2009, RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014, @@ -294,7 +295,7 @@ static MTPObject *usb_mtp_object_alloc(MTPState *s, uint32_t handle, goto ignore; } - fprintf(stderr, "%s: 0x%x %s\n", __func__, o->handle, o->path); + trace_usb_mtp_object_alloc(s->dev.addr, o->handle, o->path); QTAILQ_INSERT_TAIL(&s->objects, o, next); return o; @@ -310,7 +311,7 @@ static void usb_mtp_object_free(MTPState *s, MTPObject *o) { int i; - fprintf(stderr, "%s: 0x%x %s\n", __func__, o->handle, o->path); + trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path); QTAILQ_REMOVE(&s->objects, o, next); for (i = 0; i < o->nchildren; i++) { @@ -416,7 +417,7 @@ static void usb_mtp_add_u32(MTPData *data, uint32_t val) static void usb_mtp_add_u64(MTPData *data, uint64_t val) { - usb_mtp_realloc(data, 4); + usb_mtp_realloc(data, 8); data->data[data->length++] = (val >> 0) & 0xff; data->data[data->length++] = (val >> 8) & 0xff; data->data[data->length++] = (val >> 16) & 0xff; @@ -424,7 +425,7 @@ static void usb_mtp_add_u64(MTPData *data, uint64_t val) data->data[data->length++] = (val >> 32) & 0xff; data->data[data->length++] = (val >> 40) & 0xff; data->data[data->length++] = (val >> 48) & 0xff; - data->data[data->length++] = (val >> 54) & 0xff; + data->data[data->length++] = (val >> 56) & 0xff; } static void usb_mtp_add_u16_array(MTPData *data, uint32_t len, @@ -533,7 +534,7 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c) trace_usb_mtp_op_get_device_info(s->dev.addr); - usb_mtp_add_u16(d, 0x0100); + usb_mtp_add_u16(d, 100); usb_mtp_add_u32(d, 0xffffffff); usb_mtp_add_u16(d, 0x0101); usb_mtp_add_wstr(d, L""); @@ -548,7 +549,7 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c) usb_mtp_add_wstr(d, L"" MTP_MANUFACTURER); usb_mtp_add_wstr(d, L"" MTP_PRODUCT); usb_mtp_add_wstr(d, L"0.1"); - usb_mtp_add_wstr(d, L"123456789abcdef123456789abcdef"); + usb_mtp_add_wstr(d, L"0123456789abcdef0123456789abcdef"); return d; } @@ -669,6 +670,7 @@ static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c, d->fd = open(o->path, O_RDONLY); if (d->fd == -1) { + usb_mtp_data_free(d); return NULL; } d->length = o->stat.st_size; @@ -688,6 +690,7 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c, d->fd = open(o->path, O_RDONLY); if (d->fd == -1) { + usb_mtp_data_free(d); return NULL; } @@ -843,8 +846,7 @@ static void usb_mtp_command(MTPState *s, MTPControl *c) res0 = data_in->length; break; default: - fprintf(stderr, "%s: unknown command code 0x%04x\n", - __func__, c->code); + trace_usb_mtp_op_unknown(s->dev.addr, c->code); usb_mtp_queue_result(s, RES_OPERATION_NOT_SUPPORTED, c->trans, 0, 0, 0); return; @@ -892,6 +894,7 @@ static void usb_mtp_handle_control(USBDevice *dev, USBPacket *p, static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p) { + /* we don't use async packets, so this should never be called */ fprintf(stderr, "%s\n", __func__); } @@ -944,7 +947,8 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) } rc = read(d->fd, d->data, dlen); if (rc != dlen) { - fprintf(stderr, "%s: TODO: handle read error\n", __func__); + memset(d->data, 0, dlen); + s->result->code = RES_INCOMPLETE_TRANSFER; } usb_packet_copy(p, d->data, dlen); } @@ -996,6 +1000,14 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) cmd.argc = (le32_to_cpu(container.length) - sizeof(container)) / sizeof(uint32_t); cmd.trans = le32_to_cpu(container.trans); + if (cmd.argc > ARRAY_SIZE(cmd.argv)) { + cmd.argc = ARRAY_SIZE(cmd.argv); + } + if (p->iov.size < sizeof(container) + cmd.argc * sizeof(uint32_t)) { + trace_usb_mtp_stall(s->dev.addr, "packet too small"); + p->status = USB_RET_STALL; + return; + } usb_packet_copy(p, ¶ms, cmd.argc * sizeof(uint32_t)); for (i = 0; i < cmd.argc; i++) { cmd.argv[i] = le32_to_cpu(params[i]); @@ -1009,8 +1021,7 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) usb_mtp_command(s, &cmd); break; default: - iov_hexdump(p->iov.iov, p->iov.niov, stderr, "mtp-out", 32); - trace_usb_mtp_stall(s->dev.addr, "TODO: implement data-out"); + /* not needed as long as the mtp device is read-only */ p->status = USB_RET_STALL; return; } @@ -1044,7 +1055,7 @@ static int usb_mtp_initfn(USBDevice *dev) QTAILQ_INIT(&s->objects); if (s->desc == NULL) { s->desc = strrchr(s->root, '/'); - if (s->desc) { + if (s->desc && s->desc[0]) { s->desc = g_strdup(s->desc + 1); } else { s->desc = g_strdup("none"); diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 93f186f5e7..cd87074862 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -80,13 +80,13 @@ typedef struct { uint32_t bulk_head, bulk_cur; uint32_t per_cur; uint32_t done; - int done_count; + int32_t done_count; /* Frame counter partition */ - uint32_t fsmps:15; - uint32_t fit:1; - uint32_t fi:14; - uint32_t frt:1; + uint16_t fsmps; + uint8_t fit; + uint16_t fi; + uint8_t frt; uint16_t frame_number; uint16_t padding; uint32_t pstart; @@ -111,7 +111,7 @@ typedef struct { USBPacket usb_packet; uint8_t usb_buf[8192]; uint32_t async_td; - int async_complete; + bool async_complete; } OHCIState; @@ -693,7 +693,7 @@ static void ohci_async_complete_packet(USBPort *port, USBPacket *packet) #ifdef DEBUG_PACKET DPRINTF("Async packet complete\n"); #endif - ohci->async_complete = 1; + ohci->async_complete = true; ohci_process_lists(ohci, 1); } @@ -1058,7 +1058,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) #endif if (completion) { ohci->async_td = 0; - ohci->async_complete = 0; + ohci->async_complete = false; } else { if (ohci->async_td) { /* ??? The hardware should allow one active packet per @@ -1984,6 +1984,108 @@ static Property ohci_pci_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static const VMStateDescription vmstate_ohci_state_port = { + .name = "ohci-core/port", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT32(ctrl, OHCIPort), + VMSTATE_END_OF_LIST() + }, +}; + +static bool ohci_eof_timer_needed(void *opaque) +{ + OHCIState *ohci = opaque; + + return ohci->eof_timer != NULL; +} + +static int ohci_eof_timer_pre_load(void *opaque) +{ + OHCIState *ohci = opaque; + + ohci_bus_start(ohci); + + return 0; +} + +static const VMStateDescription vmstate_ohci_eof_timer = { + .name = "ohci-core/eof-timer", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .pre_load = ohci_eof_timer_pre_load, + .fields = (VMStateField []) { + VMSTATE_TIMER(eof_timer, OHCIState), + VMSTATE_END_OF_LIST() + }, +}; + +const VMStateDescription vmstate_ohci_state = { + .name = "ohci-core", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_INT64(sof_time, OHCIState), + VMSTATE_UINT32(ctl, OHCIState), + VMSTATE_UINT32(status, OHCIState), + VMSTATE_UINT32(intr_status, OHCIState), + VMSTATE_UINT32(intr, OHCIState), + VMSTATE_UINT32(hcca, OHCIState), + VMSTATE_UINT32(ctrl_head, OHCIState), + VMSTATE_UINT32(ctrl_cur, OHCIState), + VMSTATE_UINT32(bulk_head, OHCIState), + VMSTATE_UINT32(bulk_cur, OHCIState), + VMSTATE_UINT32(per_cur, OHCIState), + VMSTATE_UINT32(done, OHCIState), + VMSTATE_INT32(done_count, OHCIState), + VMSTATE_UINT16(fsmps, OHCIState), + VMSTATE_UINT8(fit, OHCIState), + VMSTATE_UINT16(fi, OHCIState), + VMSTATE_UINT8(frt, OHCIState), + VMSTATE_UINT16(frame_number, OHCIState), + VMSTATE_UINT16(padding, OHCIState), + VMSTATE_UINT32(pstart, OHCIState), + VMSTATE_UINT32(lst, OHCIState), + VMSTATE_UINT32(rhdesc_a, OHCIState), + VMSTATE_UINT32(rhdesc_b, OHCIState), + VMSTATE_UINT32(rhstatus, OHCIState), + VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0, + vmstate_ohci_state_port, OHCIPort), + VMSTATE_UINT32(hstatus, OHCIState), + VMSTATE_UINT32(hmask, OHCIState), + VMSTATE_UINT32(hreset, OHCIState), + VMSTATE_UINT32(htest, OHCIState), + VMSTATE_UINT32(old_ctl, OHCIState), + VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192), + VMSTATE_UINT32(async_td, OHCIState), + VMSTATE_BOOL(async_complete, OHCIState), + VMSTATE_END_OF_LIST() + }, + .subsections = (VMStateSubsection []) { + { + .vmsd = &vmstate_ohci_eof_timer, + .needed = ohci_eof_timer_needed, + } , { + /* empty */ + } + } +}; + +static const VMStateDescription vmstate_ohci = { + .name = "ohci", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(parent_obj, OHCIPCIState), + VMSTATE_STRUCT(state, OHCIPCIState, 1, vmstate_ohci_state, OHCIState), + VMSTATE_END_OF_LIST() + } +}; + static void ohci_pci_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -1997,6 +2099,7 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data) dc->desc = "Apple USB Controller"; dc->props = ohci_pci_properties; dc->hotpluggable = false; + dc->vmsd = &vmstate_ohci; } static const TypeInfo ohci_pci_info = { |