mirror of https://github.com/xemu-project/xemu.git
323 lines
10 KiB
C
323 lines
10 KiB
C
/*
|
|
* QEMU Chihiro USB Devices
|
|
*
|
|
* Copyright (c) 2016 espes
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#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 chihiro_an2131qc_realize(USBDevice *dev, Error **errp)
|
|
{
|
|
// ChihiroUSBState *s = DO_UPCAST(ChihiroUSBState, dev, dev);
|
|
usb_desc_init(dev);
|
|
}
|
|
|
|
static void chihiro_an2131qc_unrealize(USBDevice *dev)
|
|
{
|
|
}
|
|
|
|
static void chihiro_an2131qc_class_initfn(ObjectClass *klass, void *data)
|
|
{
|
|
// DeviceClass *dc = DEVICE_CLASS(klass);
|
|
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
|
|
|
uc->realize = chihiro_an2131qc_realize;
|
|
uc->unrealize = chihiro_an2131qc_unrealize;
|
|
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_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 void chihiro_an2131sc_realize(USBDevice *dev, Error **errp)
|
|
{
|
|
// ChihiroUSBState *s = DO_UPCAST(ChihiroUSBState, dev, dev);
|
|
usb_desc_init(dev);
|
|
}
|
|
|
|
static void chihiro_an2131sc_unrealize(USBDevice *dev)
|
|
{
|
|
}
|
|
|
|
static void chihiro_an2131sc_class_initfn(ObjectClass *klass, void *data)
|
|
{
|
|
// DeviceClass *dc = DEVICE_CLASS(klass);
|
|
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
|
|
|
uc->realize = chihiro_an2131sc_realize;
|
|
uc->unrealize = chihiro_an2131sc_unrealize;
|
|
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_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)
|