diff --git a/hw/xbox/Makefile.objs b/hw/xbox/Makefile.objs index 636660cd1c..d33e89902b 100644 --- a/hw/xbox/Makefile.objs +++ b/hw/xbox/Makefile.objs @@ -7,5 +7,6 @@ obj-y += swizzle.o g-lru-cache.o obj-y += mcpx_apu.o mcpx_aci.o obj-y += lpc47m157.o obj-y += xid.o +obj-y += chihiro-usb.o obj-y += dsp/ diff --git a/hw/xbox/chihiro-usb.c b/hw/xbox/chihiro-usb.c new file mode 100644 index 0000000000..4ef0635cb0 --- /dev/null +++ b/hw/xbox/chihiro-usb.c @@ -0,0 +1,331 @@ +/* + * QEMU Chihiro USB Devices + * + * Copyright (c) 2016 espes + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "hw/hw.h" +#include "ui/console.h" +#include "hw/usb.h" +#include "hw/usb/desc.h" + +#define DEBUG_CUSB +#ifdef DEBUG_CUSB +#define DPRINTF(s, ...) printf("chihiro-usb: " s, ## __VA_ARGS__) +#else +#define DPRINTF(...) +#endif + +typedef struct ChihiroUSBState { + USBDevice dev; +} ChihiroUSBState; + +enum chihiro_usb_strings { + STRING_SERIALNUMBER, + STRING_MANUFACTURER, + STRING_PRODUCT, +}; + +static const USBDescStrings chihiro_usb_stringtable = { + [STRING_SERIALNUMBER] = "\x00", + [STRING_MANUFACTURER] = "SEGA", + [STRING_PRODUCT] = "BASEBD" // different for qc? +}; + +static const USBDescIface desc_iface_chihiro_an2131qc = { + .bInterfaceNumber = 0, + .bNumEndpoints = 10, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, + .eps = (USBDescEndpoint[]) { + { + .bEndpointAddress = USB_DIR_OUT | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_OUT | 0x02, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_OUT | 0x03, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_OUT | 0x04, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_OUT | 0x05, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_IN | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_IN | 0x02, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_IN | 0x03, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_IN | 0x04, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_IN | 0x05, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + }, +}; + +static const USBDescDevice desc_device_chihiro_an2131qc = { + .bcdUSB = 0x0100, + .bMaxPacketSize0 = 0x40, + .bNumConfigurations = 1, + .confs = (USBDescConfig[]) { + { + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .bmAttributes = 0x80, + .bMaxPower = 0x96, + .nif = 1, + .ifs = &desc_iface_chihiro_an2131qc, + }, + }, +}; + +static const USBDesc desc_chihiro_an2131qc = { + .id = { + .idVendor = 0x0CA3, + .idProduct = 0x0002, + .bcdDevice = 0x0108, + .iManufacturer = STRING_MANUFACTURER, + .iProduct = STRING_PRODUCT, + .iSerialNumber = STRING_SERIALNUMBER, + }, + .full = &desc_device_chihiro_an2131qc, + .str = chihiro_usb_stringtable, +}; + + + + + +static const USBDescIface desc_iface_chihiro_an2131sc = { + .bInterfaceNumber = 0, + .bNumEndpoints = 6, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, + .eps = (USBDescEndpoint[]) { + { + .bEndpointAddress = USB_DIR_OUT | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_OUT | 0x02, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_OUT | 0x03, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_IN | 0x01, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_IN | 0x02, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + { + .bEndpointAddress = USB_DIR_IN | 0x03, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = 0x0040, + .bInterval = 0, + }, + }, +}; + +static const USBDescDevice desc_device_chihiro_an2131sc = { + .bcdUSB = 0x0100, + .bMaxPacketSize0 = 0x40, + .bNumConfigurations = 1, + .confs = (USBDescConfig[]) { + { + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .bmAttributes = 0x80, + .bMaxPower = 0x96, + .nif = 1, + .ifs = &desc_iface_chihiro_an2131sc, + }, + }, +}; + +static const USBDesc desc_chihiro_an2131sc = { + .id = { + .idVendor = 0x0CA3, + .idProduct = 0x0003, + .bcdDevice = 0x0110, + .iManufacturer = STRING_MANUFACTURER, + .iProduct = STRING_PRODUCT, + .iSerialNumber = STRING_SERIALNUMBER, + }, + .full = &desc_device_chihiro_an2131sc, + .str = chihiro_usb_stringtable, +}; + + + +static void handle_reset(USBDevice *dev) +{ + DPRINTF("usb reset\n"); +} + +static void handle_control(USBDevice *dev, USBPacket *p, + int request, int value, int index, int length, uint8_t *data) +{ + DPRINTF("handle control %d %d %d %d\n", request, value, index, length); + + int ret = usb_desc_handle_control(dev, p, request, value, index, length, data); + if (ret >= 0) { + DPRINTF("handled by usb_desc_handle_control: %d\n", ret); + return; + } +} + +static void handle_data(USBDevice *dev, USBPacket *p) +{ + DPRINTF("handle_data 0x%x %d 0x%zx\n", p->pid, p->ep->nr, p->iov.size); +} + +static void handle_destroy(USBDevice *dev) +{ + DPRINTF("usb reset\n"); +} + + +static int chihiro_an2131qc_initfn(USBDevice *dev) +{ + // ChihiroUSBState *s = DO_UPCAST(ChihiroUSBState, dev, dev); + usb_desc_init(dev); + + return 0; +} + +static void chihiro_an2131qc_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = chihiro_an2131qc_initfn; + uc->product_desc = "Chihiro an2131qc"; + uc->usb_desc = &desc_chihiro_an2131qc; + + uc->handle_reset = handle_reset; + uc->handle_control = handle_control; + uc->handle_data = handle_data; + uc->handle_destroy = handle_destroy; + uc->handle_attach = usb_desc_attach; + + //dc->vmsd = &vmstate_usb_kbd; +} + +static const TypeInfo chihiro_an2131qc_info = { + .name = "chihiro-an2131qc", + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(ChihiroUSBState), + .class_init = chihiro_an2131qc_class_initfn, +}; + + + +static int chihiro_an2131sc_initfn(USBDevice *dev) +{ + // ChihiroUSBState *s = DO_UPCAST(ChihiroUSBState, dev, dev); + usb_desc_init(dev); + + return 0; +} + +static void chihiro_an2131sc_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = chihiro_an2131sc_initfn; + uc->product_desc = "Chihiro an2131sc"; + uc->usb_desc = &desc_chihiro_an2131sc; + + uc->handle_reset = handle_reset; + uc->handle_control = handle_control; + uc->handle_data = handle_data; + uc->handle_destroy = handle_destroy; + uc->handle_attach = usb_desc_attach; + + //dc->vmsd = &vmstate_usb_kbd; +} + +static const TypeInfo chihiro_an2131sc_info = { + .name = "chihiro-an2131sc", + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(ChihiroUSBState), + .class_init = chihiro_an2131sc_class_initfn, +}; + + +static void chihiro_usb_register_types(void) +{ + type_register_static(&chihiro_an2131qc_info); + type_register_static(&chihiro_an2131sc_info); +} + +type_init(chihiro_usb_register_types)