Implemented some hub commands + major refactoring
This commit is contained in:
parent
4e3d0b307a
commit
36038db4fa
|
|
@ -159,18 +159,18 @@ static const USBDesc desc_hub(true);
|
|||
|
||||
int Hub::Init(int pport)
|
||||
{
|
||||
ClassInitFn();
|
||||
UsbEpInit();
|
||||
int rc = UsbClaimPort(pport);
|
||||
XboxDeviceState* dev = ClassInitFn();
|
||||
m_UsbDev->UsbEpInit(dev);
|
||||
int rc = UsbHubClaimPort(dev, pport);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
rc = m_UsbDev->USB_DeviceInit(m_pDeviceStruct);
|
||||
rc = m_UsbDev->USB_DeviceInit(dev);
|
||||
if (rc != 0) {
|
||||
UsbReleasePort(m_pDeviceStruct);
|
||||
UsbHubReleasePort(dev);
|
||||
return rc;
|
||||
}
|
||||
m_UsbDev->USB_DeviceAttach(m_pDeviceStruct);
|
||||
m_UsbDev->USB_DeviceAttach(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -181,91 +181,57 @@ Hub::~Hub()
|
|||
delete m_HubState->ports[0].port.Operations;
|
||||
delete m_HubState;
|
||||
m_pPeripheralFuncStruct = nullptr;
|
||||
m_pDeviceStruct = nullptr;
|
||||
m_HubState = nullptr;
|
||||
}
|
||||
|
||||
void Hub::ClassInitFn()
|
||||
XboxDeviceState* Hub::ClassInitFn()
|
||||
{
|
||||
m_pPeripheralFuncStruct = new USBDeviceClass();
|
||||
m_HubState = new USBHubState();
|
||||
m_pDeviceStruct = &m_HubState->dev;
|
||||
|
||||
m_pDeviceStruct->ProductDesc = "Cxbx-Reloaded USB Hub";
|
||||
QLIST_INIT(&m_pDeviceStruct->Strings);
|
||||
m_pDeviceStruct->klass = m_pPeripheralFuncStruct;
|
||||
XboxDeviceState* dev = &m_HubState->dev;
|
||||
|
||||
dev->ProductDesc = "Cxbx-Reloaded USB Hub";
|
||||
QLIST_INIT(&dev->Strings);
|
||||
dev->klass = m_pPeripheralFuncStruct;
|
||||
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
|
||||
|
||||
m_pPeripheralFuncStruct->init = std::bind(&Hub::UsbHub_Initfn, this, _1);
|
||||
m_pPeripheralFuncStruct->find_device = std::bind(&Hub::UsbHub_FindDevice, this, _1, _2);
|
||||
m_pPeripheralFuncStruct->handle_reset = std::bind(&Hub::UsbHub_HandleReset, this);
|
||||
m_pPeripheralFuncStruct->handle_control = std::bind(&Hub::UsbHub_HandleControl, this, _1, _2, _3, _4, _5, _6, _7);
|
||||
m_pPeripheralFuncStruct->handle_data = std::bind(&Hub::UsbHub_HandleData, this, _1, _2);
|
||||
m_pPeripheralFuncStruct->handle_destroy = std::bind(&Hub::UsbHub_HandleDestroy, this, _1);
|
||||
m_pPeripheralFuncStruct->product_desc = m_pDeviceStruct->ProductDesc.c_str();
|
||||
m_pPeripheralFuncStruct->product_desc = dev->ProductDesc.c_str();
|
||||
m_pPeripheralFuncStruct->usb_desc = &desc_hub;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void Hub::UsbEpInit()
|
||||
{
|
||||
UsbEpReset();
|
||||
QTAILQ_INIT(&m_pDeviceStruct->EP_ctl.Queue);
|
||||
for (int ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
||||
QTAILQ_INIT(&m_pDeviceStruct->EP_in[ep].Queue);
|
||||
QTAILQ_INIT(&m_pDeviceStruct->EP_out[ep].Queue);
|
||||
}
|
||||
}
|
||||
|
||||
void Hub::UsbEpReset()
|
||||
{
|
||||
m_pDeviceStruct->EP_ctl.Num = 0;
|
||||
m_pDeviceStruct->EP_ctl.Type = USB_ENDPOINT_XFER_CONTROL;
|
||||
m_pDeviceStruct->EP_ctl.IfNum = 0;
|
||||
m_pDeviceStruct->EP_ctl.MaxPacketSize = 64;
|
||||
m_pDeviceStruct->EP_ctl.Dev = m_pDeviceStruct;
|
||||
m_pDeviceStruct->EP_ctl.Pipeline = false;
|
||||
for (int ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
||||
m_pDeviceStruct->EP_in[ep].Num = ep + 1;
|
||||
m_pDeviceStruct->EP_out[ep].Num = ep + 1;
|
||||
m_pDeviceStruct->EP_in[ep].pid = USB_TOKEN_IN;
|
||||
m_pDeviceStruct->EP_out[ep].pid = USB_TOKEN_OUT;
|
||||
m_pDeviceStruct->EP_in[ep].Type = USB_ENDPOINT_XFER_INVALID;
|
||||
m_pDeviceStruct->EP_out[ep].Type = USB_ENDPOINT_XFER_INVALID;
|
||||
m_pDeviceStruct->EP_in[ep].IfNum = USB_INTERFACE_INVALID;
|
||||
m_pDeviceStruct->EP_out[ep].IfNum = USB_INTERFACE_INVALID;
|
||||
m_pDeviceStruct->EP_in[ep].MaxPacketSize = 0;
|
||||
m_pDeviceStruct->EP_out[ep].MaxPacketSize = 0;
|
||||
m_pDeviceStruct->EP_in[ep].Dev = m_pDeviceStruct;
|
||||
m_pDeviceStruct->EP_out[ep].Dev = m_pDeviceStruct;
|
||||
m_pDeviceStruct->EP_in[ep].Pipeline = false;
|
||||
m_pDeviceStruct->EP_out[ep].Pipeline = false;
|
||||
}
|
||||
}
|
||||
|
||||
int Hub::UsbClaimPort(int pport)
|
||||
int Hub::UsbHubClaimPort(XboxDeviceState* dev, int pport)
|
||||
{
|
||||
int usb_port;
|
||||
|
||||
assert(m_pDeviceStruct->Port == nullptr);
|
||||
assert(dev->Port == nullptr);
|
||||
|
||||
if (pport > 4 || pport < 1) { return -1; };
|
||||
|
||||
usb_port = PlayerToUsbArray[pport];
|
||||
if (usb_port > 2) {
|
||||
m_UsbDev = g_USB0;
|
||||
m_UsbDev->m_HostController->OHCI_AssignUsbPortStruct(usb_port - 3, m_pDeviceStruct);
|
||||
m_UsbDev->m_HostController->OHCI_AssignUsbPortStruct(usb_port - 3, dev);
|
||||
}
|
||||
else {
|
||||
m_UsbDev = g_USB1;
|
||||
m_UsbDev->m_HostController->OHCI_AssignUsbPortStruct(usb_port - 1, m_pDeviceStruct);
|
||||
m_UsbDev->m_HostController->OHCI_AssignUsbPortStruct(usb_port - 1, dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Hub::UsbReleasePort(XboxDeviceState* dev)
|
||||
void Hub::UsbHubReleasePort(XboxDeviceState* dev)
|
||||
{
|
||||
USBPort* port = dev->Port;
|
||||
|
||||
|
|
@ -286,8 +252,8 @@ int Hub::UsbHub_Initfn(XboxDeviceState* dev)
|
|||
return -1;
|
||||
}
|
||||
|
||||
CreateSerial(dev);
|
||||
UsbDescInit(dev);
|
||||
m_UsbDev->CreateSerial(dev);
|
||||
m_UsbDev->UsbDescInit(dev);
|
||||
m_HubState->intr = m_UsbDev->USB_GetEP(dev, USB_TOKEN_IN, 1);
|
||||
|
||||
ops = new USBPortOps();
|
||||
|
|
@ -296,7 +262,7 @@ int Hub::UsbHub_Initfn(XboxDeviceState* dev)
|
|||
|
||||
ops->attach = std::bind(&Hub::UsbHub_Attach, this, _1);
|
||||
ops->detach = std::bind(&Hub::UsbHub_Detach, this, _1);
|
||||
ops->child_detach = std::bind(&Hub::UsbHub_ChildDetach, this, _1, _2);
|
||||
ops->child_detach = std::bind(&Hub::UsbHub_ChildDetach, this, _1);
|
||||
ops->wakeup = std::bind(&Hub::UsbHub_Wakeup, this, _1);
|
||||
ops->complete = std::bind(&Hub::UsbHub_Complete, this, _1, _2);
|
||||
}
|
||||
|
|
@ -310,6 +276,24 @@ int Hub::UsbHub_Initfn(XboxDeviceState* dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
XboxDeviceState* Hub::UsbHub_FindDevice(XboxDeviceState* dev, uint8_t addr)
|
||||
{
|
||||
USBHubPort* port;
|
||||
XboxDeviceState* downstream;
|
||||
|
||||
for (int i = 0; i < NUM_PORTS; i++) {
|
||||
port = &m_HubState->ports[i];
|
||||
if (!(port->wPortStatus & PORT_STAT_ENABLE)) {
|
||||
continue;
|
||||
}
|
||||
downstream = m_UsbDev->USB_FindDevice(&port->port, addr);
|
||||
if (downstream != nullptr) {
|
||||
return downstream;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Hub::UsbHub_HandleReset()
|
||||
{
|
||||
USBHubPort* port;
|
||||
|
|
@ -328,185 +312,297 @@ void Hub::UsbHub_HandleReset()
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* From XQEMU:
|
||||
* This function creates a serial number for a usb device.
|
||||
* The serial number should:
|
||||
* (a) Be unique within the emulator.
|
||||
* (b) Be constant, so you don't get a new one each
|
||||
* time the guest is started.
|
||||
* So we are using the physical location to generate a serial number
|
||||
* from it. It has three pieces: First a fixed, device-specific
|
||||
* prefix. Second the device path of the host controller (which is
|
||||
* the pci address in most cases). Third the physical port path.
|
||||
* Results in serial numbers like this: "314159-0000:00:1d.7-3".
|
||||
*/
|
||||
void Hub::CreateSerial(XboxDeviceState* dev)
|
||||
{
|
||||
const USBDesc* desc = GetUsbDeviceDesc(dev);
|
||||
int index = desc->id.iSerialNumber;
|
||||
USBDescString* s;
|
||||
char serial[64];
|
||||
char* path;
|
||||
int dst;
|
||||
|
||||
assert(index != 0 && desc->str[index] != NULL);
|
||||
dst = std::snprintf(serial, sizeof(serial), "%s", desc->str[index]);
|
||||
dst += std::snprintf(serial + dst, sizeof(serial) - dst, "-%s", m_UsbDev->m_PciPath);
|
||||
dst += std::snprintf(serial + dst, sizeof(serial) - dst, "-%s", dev->Port->Path);
|
||||
|
||||
QLIST_FOREACH(s, &dev->Strings, next) {
|
||||
if (s->index == index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == nullptr) {
|
||||
s = new USBDescString;
|
||||
s->index = index;
|
||||
QLIST_INSERT_HEAD(&dev->Strings, s, next);
|
||||
}
|
||||
|
||||
s->str = serial;
|
||||
}
|
||||
|
||||
const USBDesc* Hub::GetUsbDeviceDesc(XboxDeviceState* dev)
|
||||
{
|
||||
USBDeviceClass* klass = dev->klass;
|
||||
if (dev->UsbDesc) {
|
||||
return dev->UsbDesc;
|
||||
}
|
||||
return klass->usb_desc;
|
||||
}
|
||||
|
||||
void Hub::UsbDescInit(XboxDeviceState* dev)
|
||||
{
|
||||
const USBDesc* desc = GetUsbDeviceDesc(dev);
|
||||
|
||||
assert(desc != NULL);
|
||||
dev->Speed = USB_SPEED_FULL;
|
||||
dev->SpeedMask = 0;
|
||||
if (desc->full) {
|
||||
dev->SpeedMask |= USB_SPEED_MASK_FULL;
|
||||
}
|
||||
UsbDescSetDefaults(dev);
|
||||
}
|
||||
|
||||
void Hub::UsbDescSetDefaults(XboxDeviceState* dev)
|
||||
void Hub::UsbHub_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
||||
int request, int value, int index, int length, uint8_t* data)
|
||||
{
|
||||
const USBDesc *desc = GetUsbDeviceDesc(dev);
|
||||
USBHubState *s = (USBHubState *)dev;
|
||||
int ret;
|
||||
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (request) {
|
||||
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
|
||||
if (value == 0 && index != 0x81) { /* clear ep halt */
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
/* usb specific requests */
|
||||
case GetHubStatus:
|
||||
data[0] = 0;
|
||||
data[1] = 0;
|
||||
data[2] = 0;
|
||||
data[3] = 0;
|
||||
p->actual_length = 4;
|
||||
break;
|
||||
case GetPortStatus:
|
||||
{
|
||||
unsigned int n = index - 1;
|
||||
USBHubPort *port;
|
||||
if (n >= NUM_PORTS) {
|
||||
goto fail;
|
||||
}
|
||||
port = &s->ports[n];
|
||||
trace_usb_hub_get_port_status(s->dev.addr, index,
|
||||
port->wPortStatus,
|
||||
port->wPortChange);
|
||||
data[0] = port->wPortStatus;
|
||||
data[1] = port->wPortStatus >> 8;
|
||||
data[2] = port->wPortChange;
|
||||
data[3] = port->wPortChange >> 8;
|
||||
p->actual_length = 4;
|
||||
}
|
||||
break;
|
||||
case SetHubFeature:
|
||||
case ClearHubFeature:
|
||||
if (value != 0 && value != 1) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case SetPortFeature:
|
||||
{
|
||||
unsigned int n = index - 1;
|
||||
USBHubPort *port;
|
||||
USBDevice *dev;
|
||||
|
||||
trace_usb_hub_set_port_feature(s->dev.addr, index,
|
||||
feature_name(value));
|
||||
|
||||
if (n >= NUM_PORTS) {
|
||||
goto fail;
|
||||
}
|
||||
port = &s->ports[n];
|
||||
dev = port->port.dev;
|
||||
switch (value) {
|
||||
case PORT_SUSPEND:
|
||||
port->wPortStatus |= PORT_STAT_SUSPEND;
|
||||
break;
|
||||
case PORT_RESET:
|
||||
if (dev && dev->attached) {
|
||||
usb_device_reset(dev);
|
||||
port->wPortChange |= PORT_STAT_C_RESET;
|
||||
/* set enable bit */
|
||||
port->wPortStatus |= PORT_STAT_ENABLE;
|
||||
usb_wakeup(s->intr, 0);
|
||||
}
|
||||
break;
|
||||
case PORT_POWER:
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ClearPortFeature:
|
||||
{
|
||||
unsigned int n = index - 1;
|
||||
USBHubPort *port;
|
||||
|
||||
trace_usb_hub_clear_port_feature(s->dev.addr, index,
|
||||
feature_name(value));
|
||||
|
||||
if (n >= NUM_PORTS) {
|
||||
goto fail;
|
||||
}
|
||||
port = &s->ports[n];
|
||||
switch (value) {
|
||||
case PORT_ENABLE:
|
||||
port->wPortStatus &= ~PORT_STAT_ENABLE;
|
||||
break;
|
||||
case PORT_C_ENABLE:
|
||||
port->wPortChange &= ~PORT_STAT_C_ENABLE;
|
||||
break;
|
||||
case PORT_SUSPEND:
|
||||
port->wPortStatus &= ~PORT_STAT_SUSPEND;
|
||||
break;
|
||||
case PORT_C_SUSPEND:
|
||||
port->wPortChange &= ~PORT_STAT_C_SUSPEND;
|
||||
break;
|
||||
case PORT_C_CONNECTION:
|
||||
port->wPortChange &= ~PORT_STAT_C_CONNECTION;
|
||||
break;
|
||||
case PORT_C_OVERCURRENT:
|
||||
port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
|
||||
break;
|
||||
case PORT_C_RESET:
|
||||
port->wPortChange &= ~PORT_STAT_C_RESET;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GetHubDescriptor:
|
||||
{
|
||||
unsigned int n, limit, var_hub_size = 0;
|
||||
memcpy(data, qemu_hub_hub_descriptor,
|
||||
sizeof(qemu_hub_hub_descriptor));
|
||||
data[2] = NUM_PORTS;
|
||||
|
||||
/* fill DeviceRemovable bits */
|
||||
limit = ((NUM_PORTS + 1 + 7) / 8) + 7;
|
||||
for (n = 7; n < limit; n++) {
|
||||
data[n] = 0x00;
|
||||
var_hub_size++;
|
||||
}
|
||||
|
||||
/* fill PortPwrCtrlMask bits */
|
||||
limit = limit + ((NUM_PORTS + 7) / 8);
|
||||
for (; n < limit; n++) {
|
||||
data[n] = 0xff;
|
||||
var_hub_size++;
|
||||
}
|
||||
|
||||
p->actual_length = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
|
||||
data[0] = p->actual_length;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fail:
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Hub::UsbHub_Attach(USBPort* port1)
|
||||
{
|
||||
USBHubPort* port = &m_HubState->ports[port1->PortIndex];
|
||||
|
||||
port->wPortStatus |= PORT_STAT_CONNECTION;
|
||||
port->wPortChange |= PORT_STAT_C_CONNECTION;
|
||||
if (port->port.Dev->Speed == USB_SPEED_LOW) {
|
||||
port->wPortStatus |= PORT_STAT_LOW_SPEED;
|
||||
}
|
||||
else {
|
||||
port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
|
||||
}
|
||||
m_UsbDev->USB_Wakeup(m_HubState->intr);
|
||||
}
|
||||
|
||||
void Hub::UsbHub_Detach(USBPort* port1)
|
||||
{
|
||||
USBHubPort* port = &m_HubState->ports[port1->PortIndex];
|
||||
|
||||
m_UsbDev->USB_Wakeup(m_HubState->intr);
|
||||
|
||||
// Let upstream know the device on this port is gone
|
||||
m_HubState->dev.Port->Operations->child_detach(port1->Dev);
|
||||
|
||||
port->wPortStatus &= ~PORT_STAT_CONNECTION;
|
||||
port->wPortChange |= PORT_STAT_C_CONNECTION;
|
||||
if (port->wPortStatus & PORT_STAT_ENABLE) {
|
||||
port->wPortStatus &= ~PORT_STAT_ENABLE;
|
||||
port->wPortChange |= PORT_STAT_C_ENABLE;
|
||||
}
|
||||
m_UsbDev->USB_Wakeup(m_HubState->intr);
|
||||
}
|
||||
|
||||
void Hub::UsbHub_ChildDetach(XboxDeviceState* child)
|
||||
{
|
||||
// Pass along to upstream
|
||||
m_HubState->dev.Port->Operations->child_detach(child);
|
||||
}
|
||||
|
||||
void Hub::UsbHub_Wakeup(USBPort* port1)
|
||||
{
|
||||
USBHubPort* port = &m_HubState->ports[port1->PortIndex];
|
||||
|
||||
if (port->wPortStatus & PORT_STAT_SUSPEND) {
|
||||
port->wPortChange |= PORT_STAT_C_SUSPEND;
|
||||
m_UsbDev->USB_Wakeup(m_HubState->intr);
|
||||
}
|
||||
}
|
||||
|
||||
void Hub::UsbHub_Complete(USBPort* port, USBPacket* packet)
|
||||
{
|
||||
// Just pass it along to upstream
|
||||
m_HubState->dev.Port->Operations->complete(m_HubState->dev.Port, packet);
|
||||
}
|
||||
|
||||
int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
const USBDesc *desc = usb_device_get_usb_desc(dev);
|
||||
int ret = -1;
|
||||
|
||||
assert(desc != NULL);
|
||||
switch (dev->Speed) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL: {
|
||||
dev->Device = desc->full;
|
||||
switch (request) {
|
||||
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
|
||||
dev->addr = value;
|
||||
trace_usb_set_addr(dev->addr);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||
ret = usb_desc_get_descriptor(dev, p, value, data, length);
|
||||
break;
|
||||
|
||||
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
|
||||
/*
|
||||
* 9.4.2: 0 should be returned if the device is unconfigured, otherwise
|
||||
* the non zero value of bConfigurationValue.
|
||||
*/
|
||||
data[0] = dev->config ? dev->config->bConfigurationValue : 0;
|
||||
p->actual_length = 1;
|
||||
ret = 0;
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
|
||||
ret = usb_desc_set_config(dev, value);
|
||||
trace_usb_set_config(dev->addr, value, ret);
|
||||
break;
|
||||
|
||||
case DeviceRequest | USB_REQ_GET_STATUS: {
|
||||
const USBDescConfig *config = dev->config ?
|
||||
dev->config : &dev->device->confs[0];
|
||||
|
||||
data[0] = 0;
|
||||
/*
|
||||
* Default state: Device behavior when this request is received while
|
||||
* the device is in the Default state is not specified.
|
||||
* We return the same value that a configured device would return if
|
||||
* it used the first configuration.
|
||||
*/
|
||||
if (config->bmAttributes & 0x40) {
|
||||
data[0] |= 1 << USB_DEVICE_SELF_POWERED;
|
||||
}
|
||||
if (dev->remote_wakeup) {
|
||||
data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
|
||||
}
|
||||
data[1] = 0x00;
|
||||
p->actual_length = 2;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
|
||||
if (value == USB_DEVICE_REMOTE_WAKEUP) {
|
||||
dev->remote_wakeup = 0;
|
||||
ret = 0;
|
||||
}
|
||||
trace_usb_clear_device_feature(dev->addr, value, ret);
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_SET_FEATURE:
|
||||
if (value == USB_DEVICE_REMOTE_WAKEUP) {
|
||||
dev->remote_wakeup = 1;
|
||||
ret = 0;
|
||||
}
|
||||
trace_usb_set_device_feature(dev->addr, value, ret);
|
||||
break;
|
||||
|
||||
case InterfaceRequest | USB_REQ_GET_INTERFACE:
|
||||
if (index < 0 || index >= dev->ninterfaces) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
EmuWarning("Unknown speed parameter %d set in %s", dev->ProductDesc.c_str());
|
||||
}
|
||||
UsbDescSetConfig(dev, 0);
|
||||
}
|
||||
data[0] = dev->altsetting[index];
|
||||
p->actual_length = 1;
|
||||
ret = 0;
|
||||
break;
|
||||
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = usb_desc_set_interface(dev, index, value);
|
||||
trace_usb_set_interface(dev->addr, index, value, ret);
|
||||
break;
|
||||
|
||||
int Hub::UsbDescSetConfig(XboxDeviceState* dev, int value)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (value == 0) { // default configuration
|
||||
dev->Configuration = 0;
|
||||
dev->NumInterfaces = 0;
|
||||
dev->Config = nullptr;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < dev->Device->bNumConfigurations; i++) { // select the configuration specified
|
||||
if (dev->Device->confs[i].bConfigurationValue == value) {
|
||||
dev->Configuration = value;
|
||||
dev->NumInterfaces = dev->Device->confs[i].bNumInterfaces;
|
||||
dev->Config = dev->Device->confs + i;
|
||||
assert(dev->NumInterfaces <= USB_MAX_INTERFACES);
|
||||
}
|
||||
}
|
||||
if (i < dev->Device->bNumConfigurations) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->NumInterfaces; i++) { // setup all interfaces for the selected configuration
|
||||
UsbDescSetInterface(dev, i, 0);
|
||||
}
|
||||
for (; i < USB_MAX_INTERFACES; i++) { // null the remaining interfaces
|
||||
dev->AltSetting[i] = 0;
|
||||
dev->Ifaces[i] = nullptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Hub::UsbDescSetInterface(XboxDeviceState* dev, int index, int value)
|
||||
{
|
||||
const USBDescIface* iface;
|
||||
int old;
|
||||
|
||||
iface = UsbDescFindInterface(dev, index, value);
|
||||
if (iface == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
old = dev->AltSetting[index];
|
||||
dev->AltSetting[index] = value;
|
||||
dev->Ifaces[index] = iface;
|
||||
UsbDescEpInit(dev);
|
||||
|
||||
if (old != value) {
|
||||
m_UsbDev->USB_DeviceSetInterface(dev, index, old, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const USBDescIface* Hub::UsbDescFindInterface(XboxDeviceState* dev, int nif, int alt)
|
||||
{
|
||||
const USBDescIface* iface;
|
||||
int i;
|
||||
|
||||
if (!dev->Config) { // no configuration descriptor here, nothing to search
|
||||
return nullptr;
|
||||
}
|
||||
for (i = 0; i < dev->Config->nif; i++) { // find the desired interface
|
||||
iface = &dev->Config->ifs[i];
|
||||
if (iface->bInterfaceNumber == nif &&
|
||||
iface->bAlternateSetting == alt) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
return nullptr; // not found
|
||||
}
|
||||
|
||||
void Hub::UsbDescEpInit(XboxDeviceState* dev)
|
||||
{
|
||||
const USBDescIface *iface;
|
||||
int i, e, pid, ep;
|
||||
|
||||
UsbEpInit(); // reset endpoints (because we changed descriptors in use?)
|
||||
for (i = 0; i < dev->NumInterfaces; i++) {
|
||||
iface = dev->Ifaces[i];
|
||||
if (iface == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (e = 0; e < iface->bNumEndpoints; e++) {
|
||||
// From the standard:
|
||||
// "bEndpointAddress:
|
||||
// Bit 3...0: The endpoint number
|
||||
// Bit 6...4: Reserved, reset to zero
|
||||
// Bit 7: Direction -> 0 = OUT endpoint, 1 = IN endpoint
|
||||
// bmAttributes:
|
||||
// Bit 1..0: Transfer Type
|
||||
// 00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt. All other bits are reserved"
|
||||
pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
|
||||
ep = iface->eps[e].bEndpointAddress & 0xF;
|
||||
m_UsbDev->USB_EPsetType(dev, pid, ep, iface->eps[e].bmAttributes & 0x03);
|
||||
m_UsbDev->USB_EPsetIfnum(dev, pid, ep, iface->bInterfaceNumber);
|
||||
m_UsbDev->USB_EPsetMaxPacketSize(dev, pid, ep, iface->eps[e].wMaxPacketSize);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,23 +49,25 @@ typedef enum {
|
|||
|
||||
|
||||
/* Class which implements a usb hub */
|
||||
class Hub final : public UsbPeripheral
|
||||
class Hub
|
||||
{
|
||||
public:
|
||||
// initialize this peripheral
|
||||
int Init(int pport) override;
|
||||
int Init(int pport);
|
||||
// destructor
|
||||
~Hub();
|
||||
|
||||
|
||||
private:
|
||||
// usb device this hub is attached to
|
||||
USBDevice* m_UsbDev = nullptr;
|
||||
USBDevice* m_UsbDev;
|
||||
// hub state
|
||||
USBHubState* m_HubState = nullptr;
|
||||
USBHubState* m_HubState;
|
||||
// hub class functions
|
||||
USBDeviceClass* m_pPeripheralFuncStruct;
|
||||
|
||||
// initialize various member variables/functions
|
||||
void ClassInitFn();
|
||||
XboxDeviceState* ClassInitFn();
|
||||
// see USBDeviceClass for comments about these functions
|
||||
int UsbHub_Initfn(XboxDeviceState* dev);
|
||||
XboxDeviceState* UsbHub_FindDevice(XboxDeviceState* dev, uint8_t addr);
|
||||
|
|
@ -77,34 +79,13 @@ class Hub final : public UsbPeripheral
|
|||
// see USBPortOps struct for info
|
||||
void UsbHub_Attach(USBPort* port1);
|
||||
void UsbHub_Detach(USBPort* port1);
|
||||
void UsbHub_ChildDetach(USBPort* port1, XboxDeviceState* child);
|
||||
void UsbHub_ChildDetach(XboxDeviceState* child);
|
||||
void UsbHub_Wakeup(USBPort* port1);
|
||||
void UsbHub_Complete(USBPort* port, USBPacket* packet);
|
||||
// TODO: perhaps these can be put in UsbPeripheral or USBDevice...
|
||||
// initialize the endpoints of this peripheral
|
||||
void UsbEpInit();
|
||||
// reset all endpoints of this peripheral
|
||||
void UsbEpReset();
|
||||
// reserve a usb port for this hub
|
||||
int UsbClaimPort(int port);
|
||||
//
|
||||
void UsbReleasePort(XboxDeviceState* dev);
|
||||
// get device descriptor
|
||||
const USBDesc* GetUsbDeviceDesc(XboxDeviceState* dev);
|
||||
// create a serial number for the device
|
||||
void CreateSerial(XboxDeviceState* dev);
|
||||
// start descriptors initialization
|
||||
void UsbDescInit(XboxDeviceState* dev);
|
||||
// set the descriptors to use for this device
|
||||
void UsbDescSetDefaults(XboxDeviceState* dev);
|
||||
// set the configuration to use
|
||||
int UsbDescSetConfig(XboxDeviceState* dev, int value);
|
||||
// set the interface to use
|
||||
int UsbDescSetInterface(XboxDeviceState* dev, int index, int value);
|
||||
// find the interface to use
|
||||
const USBDescIface* UsbDescFindInterface(XboxDeviceState* dev, int nif, int alt);
|
||||
// setup endpoints and their descriptors
|
||||
void UsbDescEpInit(XboxDeviceState* dev);
|
||||
int UsbHubClaimPort(XboxDeviceState* dev, int port);
|
||||
// free the usb port used by this hub
|
||||
void UsbHubReleasePort(XboxDeviceState* dev);
|
||||
};
|
||||
|
||||
extern Hub* g_HubObjArray[4];
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ OHCI::OHCI(int Irq, USBDevice* UsbObj)
|
|||
|
||||
ops->attach = std::bind(&OHCI::OHCI_Attach, this, _1);
|
||||
ops->detach = std::bind(&OHCI::OHCI_Detach, this, _1);
|
||||
ops->child_detach = std::bind(&OHCI::OHCI_ChildDetach, this, nullptr, _2);
|
||||
ops->child_detach = std::bind(&OHCI::OHCI_ChildDetach, this, _1);
|
||||
ops->wakeup = std::bind(&OHCI::OHCI_Wakeup, this, _1);
|
||||
ops->complete = std::bind(&OHCI::OHCI_AsyncCompletePacket, this, _1, _2);
|
||||
}
|
||||
|
|
@ -1448,7 +1448,7 @@ void OHCI::OHCI_Attach(USBPort* Port)
|
|||
}
|
||||
}
|
||||
|
||||
void OHCI::OHCI_ChildDetach(USBPort* port, XboxDeviceState* child)
|
||||
void OHCI::OHCI_ChildDetach(XboxDeviceState* child)
|
||||
{
|
||||
OHCI_AsyncCancelDevice(child);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ class OHCI
|
|||
// see USBPortOps struct for info
|
||||
void OHCI_Attach(USBPort* Port);
|
||||
void OHCI_Detach(USBPort* Port);
|
||||
void OHCI_ChildDetach(USBPort* port, XboxDeviceState* child);
|
||||
void OHCI_ChildDetach(XboxDeviceState* child);
|
||||
void OHCI_Wakeup(USBPort* port1);
|
||||
void OHCI_AsyncCompletePacket(USBPort* port, USBPacket* packet);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -104,16 +104,6 @@ void USBDevice::USB_PortReset(USBPort* Port)
|
|||
USB_DeviceReset(dev);
|
||||
}
|
||||
|
||||
void USBDevice::USB_Detach(USBPort* Port)
|
||||
{
|
||||
XboxDeviceState* dev = Port->Dev;
|
||||
|
||||
assert(dev != nullptr);
|
||||
assert(dev->State != USB_STATE_NOTATTACHED);
|
||||
m_HostController->OHCI_Detach(Port);
|
||||
dev->State = USB_STATE_NOTATTACHED;
|
||||
}
|
||||
|
||||
void USBDevice::USB_Attach(USBPort* Port)
|
||||
{
|
||||
XboxDeviceState* dev = Port->Dev;
|
||||
|
|
@ -126,6 +116,25 @@ void USBDevice::USB_Attach(USBPort* Port)
|
|||
USB_DeviceHandleAttach(dev);
|
||||
}
|
||||
|
||||
void USBDevice::USB_Detach(USBPort* Port)
|
||||
{
|
||||
XboxDeviceState* dev = Port->Dev;
|
||||
|
||||
assert(dev != nullptr);
|
||||
assert(dev->State != USB_STATE_NOTATTACHED);
|
||||
m_HostController->OHCI_Detach(Port);
|
||||
dev->State = USB_STATE_NOTATTACHED;
|
||||
}
|
||||
|
||||
void USBDevice::USB_Wakeup(USBEndpoint* ep)
|
||||
{
|
||||
XboxDeviceState* dev = ep->Dev;
|
||||
|
||||
if (dev->RemoteWakeup && dev->Port && dev->Port->Operations->wakeup) {
|
||||
dev->Port->Operations->wakeup(dev->Port);
|
||||
}
|
||||
}
|
||||
|
||||
void USBDevice::USB_DeviceReset(XboxDeviceState* dev)
|
||||
{
|
||||
if (dev == nullptr || !dev->Attached) {
|
||||
|
|
@ -644,3 +653,222 @@ void USBDevice::USB_DeviceAttach(XboxDeviceState* dev)
|
|||
dev->Attached++;
|
||||
USB_Attach(port);
|
||||
}
|
||||
|
||||
void USBDevice::UsbEpInit(XboxDeviceState* dev)
|
||||
{
|
||||
UsbEpReset(dev);
|
||||
QTAILQ_INIT(&dev->EP_ctl.Queue);
|
||||
for (int ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
||||
QTAILQ_INIT(&dev->EP_in[ep].Queue);
|
||||
QTAILQ_INIT(&dev->EP_out[ep].Queue);
|
||||
}
|
||||
}
|
||||
|
||||
void USBDevice::UsbEpReset(XboxDeviceState* dev)
|
||||
{
|
||||
dev->EP_ctl.Num = 0;
|
||||
dev->EP_ctl.Type = USB_ENDPOINT_XFER_CONTROL;
|
||||
dev->EP_ctl.IfNum = 0;
|
||||
dev->EP_ctl.MaxPacketSize = 64;
|
||||
dev->EP_ctl.Dev = dev;
|
||||
dev->EP_ctl.Pipeline = false;
|
||||
for (int ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
||||
dev->EP_in[ep].Num = ep + 1;
|
||||
dev->EP_out[ep].Num = ep + 1;
|
||||
dev->EP_in[ep].pid = USB_TOKEN_IN;
|
||||
dev->EP_out[ep].pid = USB_TOKEN_OUT;
|
||||
dev->EP_in[ep].Type = USB_ENDPOINT_XFER_INVALID;
|
||||
dev->EP_out[ep].Type = USB_ENDPOINT_XFER_INVALID;
|
||||
dev->EP_in[ep].IfNum = USB_INTERFACE_INVALID;
|
||||
dev->EP_out[ep].IfNum = USB_INTERFACE_INVALID;
|
||||
dev->EP_in[ep].MaxPacketSize = 0;
|
||||
dev->EP_out[ep].MaxPacketSize = 0;
|
||||
dev->EP_in[ep].Dev = dev;
|
||||
dev->EP_out[ep].Dev = dev;
|
||||
dev->EP_in[ep].Pipeline = false;
|
||||
dev->EP_out[ep].Pipeline = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* From XQEMU:
|
||||
* This function creates a serial number for a usb device.
|
||||
* The serial number should:
|
||||
* (a) Be unique within the emulator.
|
||||
* (b) Be constant, so you don't get a new one each
|
||||
* time the guest is started.
|
||||
* So we are using the physical location to generate a serial number
|
||||
* from it. It has three pieces: First a fixed, device-specific
|
||||
* prefix. Second the device path of the host controller (which is
|
||||
* the pci address in most cases). Third the physical port path.
|
||||
* Results in serial numbers like this: "314159-0000:00:1d.7-3".
|
||||
*/
|
||||
void USBDevice::CreateSerial(XboxDeviceState* dev)
|
||||
{
|
||||
const USBDesc* desc = GetUsbDeviceDesc(dev);
|
||||
int index = desc->id.iSerialNumber;
|
||||
USBDescString* s;
|
||||
char serial[64];
|
||||
char* path;
|
||||
int dst;
|
||||
|
||||
assert(index != 0 && desc->str[index] != NULL);
|
||||
dst = std::snprintf(serial, sizeof(serial), "%s", desc->str[index]);
|
||||
dst += std::snprintf(serial + dst, sizeof(serial) - dst, "-%s", m_PciPath);
|
||||
dst += std::snprintf(serial + dst, sizeof(serial) - dst, "-%s", dev->Port->Path);
|
||||
|
||||
QLIST_FOREACH(s, &dev->Strings, next) {
|
||||
if (s->index == index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == nullptr) {
|
||||
s = new USBDescString;
|
||||
s->index = index;
|
||||
QLIST_INSERT_HEAD(&dev->Strings, s, next);
|
||||
}
|
||||
|
||||
s->str = serial;
|
||||
}
|
||||
|
||||
const USBDesc* USBDevice::GetUsbDeviceDesc(XboxDeviceState* dev)
|
||||
{
|
||||
USBDeviceClass* klass = dev->klass;
|
||||
if (dev->UsbDesc) {
|
||||
return dev->UsbDesc;
|
||||
}
|
||||
return klass->usb_desc;
|
||||
}
|
||||
|
||||
void USBDevice::UsbDescInit(XboxDeviceState* dev)
|
||||
{
|
||||
const USBDesc* desc = GetUsbDeviceDesc(dev);
|
||||
|
||||
assert(desc != NULL);
|
||||
dev->Speed = USB_SPEED_FULL;
|
||||
dev->SpeedMask = 0;
|
||||
if (desc->full) {
|
||||
dev->SpeedMask |= USB_SPEED_MASK_FULL;
|
||||
}
|
||||
UsbDescSetDefaults(dev);
|
||||
}
|
||||
|
||||
void USBDevice::UsbDescSetDefaults(XboxDeviceState* dev)
|
||||
{
|
||||
const USBDesc *desc = GetUsbDeviceDesc(dev);
|
||||
|
||||
assert(desc != NULL);
|
||||
switch (dev->Speed) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL: {
|
||||
dev->Device = desc->full;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
EmuWarning("Unknown speed parameter %d set in %s", dev->ProductDesc.c_str());
|
||||
}
|
||||
UsbDescSetConfig(dev, 0);
|
||||
}
|
||||
|
||||
int USBDevice::UsbDescSetConfig(XboxDeviceState* dev, int value)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (value == 0) { // default configuration
|
||||
dev->Configuration = 0;
|
||||
dev->NumInterfaces = 0;
|
||||
dev->Config = nullptr;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < dev->Device->bNumConfigurations; i++) { // select the configuration specified
|
||||
if (dev->Device->confs[i].bConfigurationValue == value) {
|
||||
dev->Configuration = value;
|
||||
dev->NumInterfaces = dev->Device->confs[i].bNumInterfaces;
|
||||
dev->Config = dev->Device->confs + i;
|
||||
assert(dev->NumInterfaces <= USB_MAX_INTERFACES);
|
||||
}
|
||||
}
|
||||
if (i < dev->Device->bNumConfigurations) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->NumInterfaces; i++) { // setup all interfaces for the selected configuration
|
||||
UsbDescSetInterface(dev, i, 0);
|
||||
}
|
||||
for (; i < USB_MAX_INTERFACES; i++) { // null the remaining interfaces
|
||||
dev->AltSetting[i] = 0;
|
||||
dev->Ifaces[i] = nullptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int USBDevice::UsbDescSetInterface(XboxDeviceState* dev, int index, int value)
|
||||
{
|
||||
const USBDescIface* iface;
|
||||
int old;
|
||||
|
||||
iface = UsbDescFindInterface(dev, index, value);
|
||||
if (iface == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
old = dev->AltSetting[index];
|
||||
dev->AltSetting[index] = value;
|
||||
dev->Ifaces[index] = iface;
|
||||
UsbDescEpInit(dev);
|
||||
|
||||
if (old != value) {
|
||||
USB_DeviceSetInterface(dev, index, old, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const USBDescIface* USBDevice::UsbDescFindInterface(XboxDeviceState* dev, int nif, int alt)
|
||||
{
|
||||
const USBDescIface* iface;
|
||||
int i;
|
||||
|
||||
if (!dev->Config) { // no configuration descriptor here, nothing to search
|
||||
return nullptr;
|
||||
}
|
||||
for (i = 0; i < dev->Config->nif; i++) { // find the desired interface
|
||||
iface = &dev->Config->ifs[i];
|
||||
if (iface->bInterfaceNumber == nif &&
|
||||
iface->bAlternateSetting == alt) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
return nullptr; // not found
|
||||
}
|
||||
|
||||
void USBDevice::UsbDescEpInit(XboxDeviceState* dev)
|
||||
{
|
||||
const USBDescIface *iface;
|
||||
int i, e, pid, ep;
|
||||
|
||||
UsbEpInit(dev); // reset endpoints (because we changed descriptors in use?)
|
||||
for (i = 0; i < dev->NumInterfaces; i++) {
|
||||
iface = dev->Ifaces[i];
|
||||
if (iface == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (e = 0; e < iface->bNumEndpoints; e++) {
|
||||
// From the standard:
|
||||
// "bEndpointAddress:
|
||||
// Bit 3...0: The endpoint number
|
||||
// Bit 6...4: Reserved, reset to zero
|
||||
// Bit 7: Direction -> 0 = OUT endpoint, 1 = IN endpoint
|
||||
// bmAttributes:
|
||||
// Bit 1..0: Transfer Type
|
||||
// 00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt. All other bits are reserved"
|
||||
pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
|
||||
ep = iface->eps[e].bEndpointAddress & 0xF;
|
||||
USB_EPsetType(dev, pid, ep, iface->eps[e].bmAttributes & 0x03);
|
||||
USB_EPsetIfnum(dev, pid, ep, iface->bInterfaceNumber);
|
||||
USB_EPsetMaxPacketSize(dev, pid, ep, iface->eps[e].wMaxPacketSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,14 +80,14 @@ class USBDevice : public PCIDevice {
|
|||
void USB_Detach(USBPort* Port);
|
||||
// a device downstream from the device attached to the port (attached through a hub) is detached
|
||||
void ChildDetach(USBPort* Port, XboxDeviceState* Child);
|
||||
// TODO
|
||||
void Wakeup(USBPort* Port);
|
||||
// update port status when a device is detached
|
||||
void USB_Wakeup(USBEndpoint* ep);
|
||||
// TODO
|
||||
void Complete(USBPort* Port, USBPacket *P);
|
||||
// reset a device
|
||||
void USB_DeviceReset(XboxDeviceState* Dev);
|
||||
//
|
||||
XboxDeviceState* USB_DeviceFindDevice(XboxDeviceState* Dev, uint8_t Addr);
|
||||
// find the device connected to the supplied port and address
|
||||
XboxDeviceState* USB_FindDevice(USBPort* Port, uint8_t Addr);
|
||||
// find the requested endpoint in the supplied device
|
||||
USBEndpoint* USB_GetEP(XboxDeviceState* Dev, int Pid, int Ep);
|
||||
// setup a packet for transfer
|
||||
|
|
@ -121,7 +121,7 @@ class USBDevice : public PCIDevice {
|
|||
// call usb class init function
|
||||
int USB_DeviceInit(XboxDeviceState* dev);
|
||||
// call usb class find_device function
|
||||
XboxDeviceState* USB_FindDevice(USBPort* Port, uint8_t Addr);
|
||||
XboxDeviceState* USB_DeviceFindDevice(XboxDeviceState* Dev, uint8_t Addr);
|
||||
// call usb class cancel_packet function
|
||||
void USB_DeviceCancelPacket(XboxDeviceState* dev, USBPacket* p);
|
||||
// call usb class handle_destroy function
|
||||
|
|
@ -148,6 +148,26 @@ class USBDevice : public PCIDevice {
|
|||
void USB_EPsetMaxPacketSize(XboxDeviceState* dev, int pid, int ep, uint16_t raw);
|
||||
// assign port numbers (also for hubs)
|
||||
void USB_PortLocation(USBPort* downstream, USBPort* upstream, int portnr);
|
||||
// initialize the endpoints of this peripheral
|
||||
void UsbEpInit(XboxDeviceState* dev);
|
||||
// reset all endpoints of this peripheral
|
||||
void UsbEpReset(XboxDeviceState* dev);
|
||||
// create a serial number for the device
|
||||
void CreateSerial(XboxDeviceState* dev);
|
||||
// start descriptors initialization
|
||||
void UsbDescInit(XboxDeviceState* dev);
|
||||
// get device descriptor
|
||||
const USBDesc* GetUsbDeviceDesc(XboxDeviceState* dev);
|
||||
// set the descriptors to use for this device
|
||||
void UsbDescSetDefaults(XboxDeviceState* dev);
|
||||
// set the configuration to use
|
||||
int UsbDescSetConfig(XboxDeviceState* dev, int value);
|
||||
// set the interface to use
|
||||
int UsbDescSetInterface(XboxDeviceState* dev, int index, int value);
|
||||
// find the interface to use
|
||||
const USBDescIface* UsbDescFindInterface(XboxDeviceState* dev, int nif, int alt);
|
||||
// setup endpoints and their descriptors
|
||||
void UsbDescEpInit(XboxDeviceState* dev);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -113,6 +113,9 @@ struct USBDescEndpoint {
|
|||
|
||||
uint8_t is_audio; /* has bRefresh + bSynchAddress */
|
||||
uint8_t* extra;
|
||||
|
||||
// Dropped from XQEMU the parameters bMaxBurst, bmAttributes_super and wBytesPerInterval because those are only defined for
|
||||
// superspeed (usb 3.0) devices in the superspeed endpoint companion
|
||||
};
|
||||
|
||||
/* Interface descriptor */
|
||||
|
|
@ -201,7 +204,7 @@ struct XboxDeviceState {
|
|||
uint32_t flags;
|
||||
USBDeviceClass* klass; // usb class struct of this device
|
||||
|
||||
int Speed; // actual connected speed
|
||||
int Speed; // actual speed of the connected device
|
||||
int SpeedMask; // supported speeds, not in info because it may be variable (hostdevs)
|
||||
uint8_t Addr; // device function address
|
||||
std::string ProductDesc; // the friendly name of this device
|
||||
|
|
@ -262,7 +265,7 @@ struct USBPortOps {
|
|||
* This gets called when a device downstream from the device attached to
|
||||
* the port (attached through a hub) gets detached.
|
||||
*/
|
||||
std::function<void(USBPort* port, XboxDeviceState* child)> child_detach;
|
||||
std::function<void(XboxDeviceState* child)> child_detach;
|
||||
std::function<void(USBPort* port)> wakeup;
|
||||
/*
|
||||
* Note that port->dev will be different then the device from which
|
||||
|
|
@ -278,7 +281,7 @@ struct USBPort {
|
|||
int SpeedMask; // usb speeds supported
|
||||
int HubCount; // number of hubs chained
|
||||
char Path[16]; // the number of the port + 1, used to create a serial number for this device
|
||||
int PortIndex; // internal port index against this HC
|
||||
int PortIndex; // internal port index
|
||||
};
|
||||
|
||||
/* Struct which stores general functions/variables regarding the peripheral */
|
||||
|
|
@ -329,16 +332,4 @@ struct USBDeviceClass {
|
|||
const USBDesc* usb_desc; // device descriptor
|
||||
};
|
||||
|
||||
|
||||
/* Abstract class representing a usb peripheral */
|
||||
class UsbPeripheral
|
||||
{
|
||||
protected:
|
||||
USBDeviceClass* m_pPeripheralFuncStruct;
|
||||
XboxDeviceState* m_pDeviceStruct;
|
||||
|
||||
virtual int Init(int pport) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue