small OHCI stuff + almost done with Hub initialization
This commit is contained in:
parent
0691b8bfb4
commit
13b20e6741
|
@ -40,6 +40,20 @@
|
|||
|
||||
#define NUM_PORTS 8
|
||||
|
||||
#define PORT_STAT_CONNECTION 0x0001
|
||||
#define PORT_STAT_ENABLE 0x0002
|
||||
#define PORT_STAT_SUSPEND 0x0004
|
||||
#define PORT_STAT_OVERCURRENT 0x0008
|
||||
#define PORT_STAT_RESET 0x0010
|
||||
#define PORT_STAT_POWER 0x0100
|
||||
#define PORT_STAT_LOW_SPEED 0x0200
|
||||
|
||||
#define PORT_STAT_C_CONNECTION 0x0001
|
||||
#define PORT_STAT_C_ENABLE 0x0002
|
||||
#define PORT_STAT_C_SUSPEND 0x0004
|
||||
#define PORT_STAT_C_OVERCURRENT 0x0008
|
||||
#define PORT_STAT_C_RESET 0x0010
|
||||
|
||||
|
||||
// To avoid including Xbox.h
|
||||
extern USBDevice* g_USB0;
|
||||
|
@ -57,13 +71,13 @@ int PlayerToUsbArray[] = {
|
|||
|
||||
struct USBHubPort {
|
||||
USBPort port; // downstream port status
|
||||
uint16_t wPortStatus;
|
||||
uint16_t wPortChange;
|
||||
uint16_t wPortStatus; // Port Status Field, in accordance with the standard
|
||||
uint16_t wPortChange; // Port Change Field, in accordance with the standard
|
||||
};
|
||||
|
||||
struct USBHubState {
|
||||
XboxDeviceState dev; // hub device status
|
||||
USBEndpoint* intr;
|
||||
USBEndpoint* intr; // interrupt endpoint of the hub
|
||||
USBHubPort ports[NUM_PORTS]; // downstream ports of the hub
|
||||
};
|
||||
|
||||
|
@ -153,15 +167,13 @@ int Hub::Init(int pport)
|
|||
}
|
||||
rc = m_UsbDev->USB_DeviceInit(m_pDeviceStruct);
|
||||
if (rc != 0) {
|
||||
usb_release_port(dev);
|
||||
UsbReleasePort(m_pDeviceStruct);
|
||||
return rc;
|
||||
}
|
||||
if (dev->auto_attach) {
|
||||
rc = usb_device_attach(dev);
|
||||
if (rc != 0) {
|
||||
usb_qdev_exit(qdev);
|
||||
return rc;
|
||||
}
|
||||
rc = usb_device_attach(dev);
|
||||
if (rc != 0) {
|
||||
usb_qdev_exit(qdev);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,7 +252,6 @@ void Hub::UsbEpReset()
|
|||
|
||||
int Hub::UsbClaimPort(int pport)
|
||||
{
|
||||
USBPort* port;
|
||||
int usb_port;
|
||||
|
||||
assert(m_pDeviceStruct->Port == nullptr);
|
||||
|
@ -260,10 +271,20 @@ int Hub::UsbClaimPort(int pport)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Hub::UsbReleasePort(XboxDeviceState* dev)
|
||||
{
|
||||
USBPort* port = dev->Port;
|
||||
|
||||
assert(port != nullptr);
|
||||
|
||||
port->Dev = nullptr;
|
||||
dev->Port = nullptr;
|
||||
}
|
||||
|
||||
int Hub::UsbHub_Initfn(XboxDeviceState* dev)
|
||||
{
|
||||
USBHubState* s = container_of(dev, USBHubState, dev);
|
||||
USBHubPort *port;
|
||||
USBHubPort* port;
|
||||
int i;
|
||||
|
||||
if (dev->Port->HubCount == 5) {
|
||||
|
@ -273,18 +294,35 @@ int Hub::UsbHub_Initfn(XboxDeviceState* dev)
|
|||
|
||||
CreateSerial(dev);
|
||||
UsbDescInit(dev);
|
||||
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
|
||||
s->intr = m_UsbDev->USB_GetEP(dev, USB_TOKEN_IN, 1);
|
||||
for (i = 0; i < NUM_PORTS; i++) {
|
||||
port = &s->ports[i];
|
||||
usb_register_port(usb_bus_from_device(dev),
|
||||
&port->port, s, i, &usb_hub_port_ops,
|
||||
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
|
||||
usb_port_location(&port->port, dev->port, i + 1);
|
||||
m_UsbDev->USB_RegisterPort(&port->port, i, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
|
||||
m_UsbDev->USB_PortLocation(&port->port, dev->Port, i + 1);
|
||||
}
|
||||
usb_hub_handle_reset(dev);
|
||||
UsbHub_HandleReset(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Hub::UsbHub_HandleReset(XboxDeviceState* dev)
|
||||
{
|
||||
USBHubState* s = container_of(dev, USBHubState, dev);
|
||||
USBHubPort* port;
|
||||
|
||||
for (int i = 0; i < NUM_PORTS; i++) {
|
||||
port = s->ports + i;
|
||||
port->wPortStatus = PORT_STAT_POWER;
|
||||
port->wPortChange = 0;
|
||||
if (port->port.Dev && port->port.Dev->Attached) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* From XQEMU:
|
||||
* This function creates a serial number for a usb device.
|
||||
|
@ -406,17 +444,17 @@ int Hub::UsbDescSetInterface(XboxDeviceState* dev, int index, int value)
|
|||
int old;
|
||||
|
||||
iface = UsbDescFindInterface(dev, index, value);
|
||||
if (iface == NULL) {
|
||||
if (iface == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
old = dev->altsetting[index];
|
||||
dev->altsetting[index] = value;
|
||||
dev->ifaces[index] = iface;
|
||||
usb_desc_ep_init(dev);
|
||||
old = dev->AltSetting[index];
|
||||
dev->AltSetting[index] = value;
|
||||
dev->Ifaces[index] = iface;
|
||||
UsbDescEpInit(dev);
|
||||
|
||||
if (old != value) {
|
||||
usb_device_set_interface(dev, index, old, value);
|
||||
m_UsbDev->USB_DeviceSetInterface(dev, index, old, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -424,26 +462,46 @@ int Hub::UsbDescSetInterface(XboxDeviceState* dev, int index, int value)
|
|||
const USBDescIface* Hub::UsbDescFindInterface(XboxDeviceState* dev, int nif, int alt)
|
||||
{
|
||||
const USBDescIface* iface;
|
||||
int g, i;
|
||||
int i;
|
||||
|
||||
if (!dev->Config) { // no configuration descriptor here, nothing to search
|
||||
return nullptr;
|
||||
}
|
||||
for (g = 0; g < dev->Config->nif_groups; g++) {
|
||||
for (i = 0; i < dev->config->if_groups[g].nif; i++) {
|
||||
iface = &dev->config->if_groups[g].ifs[i];
|
||||
if (iface->bInterfaceNumber == nif &&
|
||||
iface->bAlternateSetting == alt) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < dev->config->nif; i++) {
|
||||
iface = &dev->config->ifs[i];
|
||||
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 NULL;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,26 +77,30 @@ class Hub final : public UsbPeripheral
|
|||
// TODO: perhaps these can be put in UsbPeripheral or USBDevice...
|
||||
// initialize the endpoints of this peripheral
|
||||
void UsbEpInit();
|
||||
// destroy hub
|
||||
// destroy hub resources
|
||||
void HubCleanUp();
|
||||
// reset all endpoints of this peripheral
|
||||
void UsbEpReset();
|
||||
// attach this hub to a usb port
|
||||
// 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);
|
||||
};
|
||||
|
||||
extern Hub* g_HubObjArray[4];
|
||||
|
|
|
@ -187,16 +187,27 @@
|
|||
OHCI::OHCI(int Irq, USBDevice* UsbObj)
|
||||
{
|
||||
int offset = 0;
|
||||
USBPortOps* ops;
|
||||
|
||||
m_IrqNum = Irq;
|
||||
m_UsbDevice = UsbObj;
|
||||
ops = new USBPortOps();
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
|
||||
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, _1);
|
||||
ops->wakeup = std::bind(&OHCI::OHCI_Wakeup, this, _1);
|
||||
ops->complete = std::bind(&OHCI::OHCI_AsyncCompletePacket, this, _1, _2);
|
||||
}
|
||||
|
||||
if (m_IrqNum == 9) {
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
m_UsbDevice->USB_RegisterPort(&m_Registers.RhPort[i].UsbPort, i + offset, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
|
||||
m_UsbDevice->USB_RegisterPort(&m_Registers.RhPort[i].UsbPort, i + offset, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL, ops);
|
||||
}
|
||||
OHCI_PacketInit(&m_UsbPacket);
|
||||
|
||||
|
@ -1437,6 +1448,43 @@ void OHCI::OHCI_Attach(USBPort* Port)
|
|||
}
|
||||
}
|
||||
|
||||
void OHCI::OHCI_ChildDetach(XboxDeviceState* child)
|
||||
{
|
||||
OHCI_AsyncCancelDevice(child);
|
||||
}
|
||||
|
||||
void OHCI::OHCI_Wakeup(USBPort* port1)
|
||||
{
|
||||
OHCIPort* port = &m_Registers.RhPort[port1->PortIndex];
|
||||
uint32_t intr = 0;
|
||||
if (port->HcRhPortStatus & OHCI_PORT_PSS) {
|
||||
DbgPrintf("Ohci: port %d: wakeup\n", port1->PortIndex);
|
||||
port->HcRhPortStatus |= OHCI_PORT_PSSC;
|
||||
port->HcRhPortStatus &= ~OHCI_PORT_PSS;
|
||||
intr = OHCI_INTR_RHSC;
|
||||
}
|
||||
// Note that the controller can be suspended even if this port is not
|
||||
if ((m_Registers.HcControl & OHCI_CTL_HCFS) == Suspend) {
|
||||
DbgPrintf("Ohci: remote-wakeup: SUSPEND->RESUME\n");
|
||||
// From the standard: "The only interrupts possible in the USBSUSPEND state are ResumeDetected (the
|
||||
// Host Controller will have changed the HostControllerFunctionalState to the USBRESUME state)
|
||||
// and OwnershipChange."
|
||||
m_Registers.HcControl &= ~OHCI_CTL_HCFS;
|
||||
m_Registers.HcControl |= Resume;
|
||||
intr = OHCI_INTR_RD;
|
||||
}
|
||||
OHCI_SetInterrupt(intr);
|
||||
}
|
||||
|
||||
void OHCI::OHCI_AsyncCompletePacket(USBPort* port, USBPacket* packet)
|
||||
{
|
||||
#ifdef DEBUG_PACKET
|
||||
DPRINTF("Async packet complete\n");
|
||||
#endif
|
||||
m_AsyncComplete = 1;
|
||||
OHCI_ProcessLists(1);
|
||||
}
|
||||
|
||||
void OHCI::OHCI_AsyncCancelDevice(XboxDeviceState* dev)
|
||||
{
|
||||
if (m_AsyncTD &&
|
||||
|
|
|
@ -158,10 +158,6 @@ class OHCI
|
|||
uint32_t OHCI_ReadRegister(xbaddr Addr);
|
||||
// write a register
|
||||
void OHCI_WriteRegister(xbaddr Addr, uint32_t Value);
|
||||
// update ohci registers during a device attach
|
||||
void OHCI_Attach(USBPort* Port);
|
||||
// update ohci registers during a device detach
|
||||
void OHCI_Detach(USBPort* Port);
|
||||
// update the USBPort struct with the device attached
|
||||
void OHCI_AssignUsbPortStruct(int port, XboxDeviceState* dev);
|
||||
|
||||
|
@ -263,6 +259,12 @@ class OHCI
|
|||
void OHCI_AsyncCancelDevice(XboxDeviceState* dev);
|
||||
// Process Control and Bulk lists
|
||||
void OHCI_ProcessLists(int completion);
|
||||
// see USBPortOps struct for info
|
||||
void OHCI_Attach(USBPort* Port);
|
||||
void OHCI_Detach(USBPort* Port);
|
||||
void OHCI_ChildDetach(XboxDeviceState* child);
|
||||
void OHCI_Wakeup(USBPort* port1);
|
||||
void OHCI_AsyncCompletePacket(USBPort* port, USBPacket* packet);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -86,13 +86,12 @@ void USBDevice::MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned
|
|||
m_HostController->OHCI_WriteRegister(addr, value);
|
||||
}
|
||||
|
||||
void USBDevice::USB_RegisterPort(USBPort* Port, int Index, int SpeedMask)
|
||||
void USBDevice::USB_RegisterPort(USBPort* Port, int Index, int SpeedMask, USBPortOps* Ops)
|
||||
{
|
||||
Port->PortIndex = Index;
|
||||
Port->SpeedMask = SpeedMask;
|
||||
Port->HubCount = 0;
|
||||
Port->Dev = nullptr;
|
||||
std::snprintf(Port->Path, sizeof(Port->Path), "%d", Index + 1);
|
||||
Port->Operations = Ops;
|
||||
USB_PortLocation(Port, nullptr, Index + 1);
|
||||
}
|
||||
|
||||
void USBDevice::USB_PortReset(USBPort* Port)
|
||||
|
@ -164,8 +163,8 @@ USBEndpoint* USBDevice::USB_GetEP(XboxDeviceState* Dev, int Pid, int Ep)
|
|||
if (Ep == 0) {
|
||||
return &Dev->EP_ctl; // EndpointNumber zero represents the default control endpoint
|
||||
}
|
||||
assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
|
||||
assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
|
||||
assert(Pid == USB_TOKEN_IN || Pid == USB_TOKEN_OUT);
|
||||
assert(Ep > 0 && Ep <= USB_MAX_ENDPOINTS);
|
||||
|
||||
return eps + Ep - 1;
|
||||
}
|
||||
|
@ -509,51 +508,59 @@ int USBDevice::USB_DeviceInit(XboxDeviceState* dev)
|
|||
|
||||
void USBDevice::USB_DeviceHandleControl(XboxDeviceState* dev, USBPacket* p, int request, int value, int index, int length, uint8_t* data)
|
||||
{
|
||||
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
|
||||
USBDeviceClass* klass = dev->klass;
|
||||
if (klass->handle_control) {
|
||||
klass->handle_control(dev, p, request, value, index, length, data); // TODO: usb_hub_handle_control
|
||||
klass->handle_control(dev, p, request, value, index, length, data);
|
||||
}
|
||||
}
|
||||
|
||||
void USBDevice::USB_DeviceHandleData(XboxDeviceState* dev, USBPacket* p)
|
||||
{
|
||||
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
|
||||
USBDeviceClass* klass = dev->klass;
|
||||
if (klass->handle_data) {
|
||||
klass->handle_data(dev, p); // TODO: usb_hub_handle_data
|
||||
klass->handle_data(dev, p);
|
||||
}
|
||||
}
|
||||
|
||||
void USBDevice::USB_DeviceFlushEPqueue(XboxDeviceState* dev, USBEndpoint* ep)
|
||||
{
|
||||
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
|
||||
USBDeviceClass *klass = dev->klass;
|
||||
if (klass->flush_ep_queue) {
|
||||
klass->flush_ep_queue(dev, ep); // TODO: it's nullptr in XQEMU...
|
||||
klass->flush_ep_queue(dev, ep);
|
||||
}
|
||||
}
|
||||
|
||||
void USBDevice::USB_DeviceCancelPacket(XboxDeviceState* dev, USBPacket* p)
|
||||
{
|
||||
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
|
||||
USBDeviceClass* klass = dev->klass;
|
||||
if (klass->cancel_packet) {
|
||||
klass->cancel_packet(dev, p); // TODO: it's nullptr in XQEMU...
|
||||
klass->cancel_packet(dev, p);
|
||||
}
|
||||
}
|
||||
|
||||
XboxDeviceState* USBDevice::USB_DeviceFindDevice(XboxDeviceState* Dev, uint8_t Addr)
|
||||
XboxDeviceState* USBDevice::USB_DeviceFindDevice(XboxDeviceState* dev, uint8_t Addr)
|
||||
{
|
||||
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(Dev);
|
||||
USBDeviceClass* klass = dev->klass;
|
||||
if (klass->find_device) {
|
||||
return klass->find_device(Dev, Addr); // TODO: usb_hub_find_device
|
||||
return klass->find_device(dev, Addr);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void USBDevice::USB_DeviceEPstopped(XboxDeviceState* Dev, USBEndpoint* EP)
|
||||
void USBDevice::USB_DeviceEPstopped(XboxDeviceState* dev, USBEndpoint* EP)
|
||||
{
|
||||
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(Dev);
|
||||
USBDeviceClass* klass = dev->klass;
|
||||
if (klass->ep_stopped) {
|
||||
klass->ep_stopped(Dev, EP);
|
||||
klass->ep_stopped(dev, EP);
|
||||
}
|
||||
}
|
||||
|
||||
void USBDevice::USB_DeviceSetInterface(XboxDeviceState* dev, int iface, int alt_old, int alt_new)
|
||||
{
|
||||
USBDeviceClass* klass = dev->klass;
|
||||
if (klass->set_interface) {
|
||||
klass->set_interface(dev, iface, alt_old, alt_new);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,3 +574,38 @@ void USBDevice::USB_CancelPacket(USBPacket* p)
|
|||
USB_DeviceCancelPacket(p->Endpoint->Dev, p);
|
||||
}
|
||||
}
|
||||
|
||||
void USBDevice::USB_EPsetType(XboxDeviceState* dev, int pid, int ep, uint8_t type)
|
||||
{
|
||||
USBEndpoint* uep = USB_GetEP(dev, pid, ep);
|
||||
uep->Type = type;
|
||||
}
|
||||
|
||||
uint8_t USBDevice::USB_EPsetIfnum(XboxDeviceState* dev, int pid, int ep, uint8_t ifnum)
|
||||
{
|
||||
USBEndpoint* uep = USB_GetEP(dev, pid, ep);
|
||||
uep->IfNum = ifnum;
|
||||
}
|
||||
|
||||
void USBDevice::USB_EPsetMaxPacketSize(XboxDeviceState* dev, int pid, int ep, uint16_t raw)
|
||||
{
|
||||
USBEndpoint* uep = USB_GetEP(dev, pid, ep);
|
||||
|
||||
// Dropped from XQEMU the calculation max_packet_size = size * microframes since that's only true
|
||||
// for high speed (usb 2.0) devices
|
||||
|
||||
uep->MaxPacketSize = raw & 0x7FF;
|
||||
}
|
||||
|
||||
void USBDevice::USB_PortLocation(USBPort* downstream, USBPort* upstream, int portnr)
|
||||
{
|
||||
if (upstream) {
|
||||
std::snprintf(downstream->Path, sizeof(downstream->Path), "%s.%d",
|
||||
upstream->Path, portnr);
|
||||
downstream->HubCount = upstream->HubCount + 1;
|
||||
}
|
||||
else {
|
||||
std::snprintf(downstream->Path, sizeof(downstream->Path), "%d", portnr);
|
||||
downstream->HubCount = 0;
|
||||
}
|
||||
}
|
|
@ -41,9 +41,10 @@
|
|||
#include "UsbCommon.h"
|
||||
|
||||
|
||||
// Forward declare OHCI class for USBDevice class
|
||||
// Forward declare OHCI class for m_HostController pointer
|
||||
class OHCI;
|
||||
|
||||
/* Helper class which provides various functionality to both OHCI and usb device classes */
|
||||
class USBDevice : public PCIDevice {
|
||||
public:
|
||||
// constructor
|
||||
|
@ -68,12 +69,12 @@ class USBDevice : public PCIDevice {
|
|||
const char* m_PciPath;
|
||||
|
||||
// register a port with the HC
|
||||
void USB_RegisterPort(USBPort* Port, int Index, int SpeedMask);
|
||||
void USB_RegisterPort(USBPort* Port, int Index, int SpeedMask, USBPortOps* Ops);
|
||||
//
|
||||
void USB_DeviceEPstopped(XboxDeviceState* Dev, USBEndpoint* Ep);
|
||||
// reset a usb port
|
||||
void USB_PortReset(USBPort* Port);
|
||||
// a device is attched
|
||||
// a device is attached
|
||||
void USB_Attach(USBPort* Port);
|
||||
// a device is detached
|
||||
void USB_Detach(USBPort* Port);
|
||||
|
@ -87,7 +88,7 @@ class USBDevice : public PCIDevice {
|
|||
void USB_DeviceReset(XboxDeviceState* Dev);
|
||||
// find the usb device with the supplied address
|
||||
XboxDeviceState* USB_FindDevice(USBPort* Port, uint8_t Addr);
|
||||
// ergo720: can probably be removed by calling directly usb_hub_find_device
|
||||
//
|
||||
XboxDeviceState* USB_DeviceFindDevice(XboxDeviceState* Dev, uint8_t Addr);
|
||||
// find the requested endpoint in the supplied device
|
||||
USBEndpoint* USB_GetEP(XboxDeviceState* Dev, int Pid, int Ep);
|
||||
|
@ -114,21 +115,31 @@ class USBDevice : public PCIDevice {
|
|||
void DoTokenOut(XboxDeviceState* s, USBPacket* p);
|
||||
// copy the packet data to the buffer pointed to by ptr
|
||||
void USB_PacketCopy(USBPacket* p, void* ptr, size_t bytes);
|
||||
// Cancel an active packet. The packed must have been deferred by
|
||||
// returning USB_RET_ASYNC from handle_packet, and not yet completed
|
||||
void USB_CancelPacket(USBPacket* p);
|
||||
// queue a packet to an endpoint
|
||||
void USB_QueueOne(USBPacket* p);
|
||||
// call usb class init function
|
||||
int USB_DeviceInit(XboxDeviceState* dev);
|
||||
//
|
||||
// call usb class handle_control function
|
||||
void USB_DeviceHandleControl(XboxDeviceState* dev, USBPacket* p, int request, int value, int index, int length, uint8_t* data);
|
||||
//
|
||||
// call usb class handle_data function
|
||||
void USB_DeviceHandleData(XboxDeviceState* dev, USBPacket* p);
|
||||
//
|
||||
// call usb class flush_ep_queue function
|
||||
void USB_DeviceFlushEPqueue(XboxDeviceState* dev, USBEndpoint* ep);
|
||||
//
|
||||
// call usb class cancel_packet function
|
||||
void USB_DeviceCancelPacket(XboxDeviceState* dev, USBPacket* p);
|
||||
// Cancel an active packet. The packed must have been deferred by
|
||||
// returning USB_RET_ASYNC from handle_packet, and not yet completed
|
||||
void USB_CancelPacket(USBPacket* p);
|
||||
// call usb class set_interface function
|
||||
void USB_DeviceSetInterface(XboxDeviceState* dev, int iface, int alt_old, int alt_new);
|
||||
// set the type of the endpoint
|
||||
void USB_EPsetType(XboxDeviceState* dev, int pid, int ep, uint8_t type);
|
||||
// set the interface number of the endpoint
|
||||
uint8_t USB_EPsetIfnum(XboxDeviceState* dev, int pid, int ep, uint8_t ifnum);
|
||||
// set the maximum packet size parameter of the endpoint
|
||||
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);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -102,21 +102,17 @@ struct USBDescOther {
|
|||
const uint8_t* data;
|
||||
};
|
||||
|
||||
/* Endpoint descriptor */
|
||||
struct USBDescEndpoint {
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bmAttributes;
|
||||
uint16_t wMaxPacketSize;
|
||||
uint8_t bInterval;
|
||||
uint8_t bRefresh;
|
||||
uint8_t bSynchAddress;
|
||||
uint8_t bEndpointAddress; // the address of the endpoint on the USB device described by this descriptor
|
||||
uint8_t bmAttributes; // this field describes the endpoint's attributes when it is configured using the bConfigurationValue
|
||||
uint16_t wMaxPacketSize; // maximum packet size this endpoint is capable of sending or receiving when this configuration is selected
|
||||
uint8_t bInterval; // interval for polling endpoint for data transfers, expressed in milliseconds.
|
||||
uint8_t bRefresh; // for audio devices only: the rate at which synchronization feedback is provided
|
||||
uint8_t bSynchAddress; // for audio devices only: the address of the synchronization endpoint
|
||||
|
||||
uint8_t is_audio; /* has bRefresh + bSynchAddress */
|
||||
uint8_t* extra;
|
||||
|
||||
/* superspeed endpoint companion */
|
||||
uint8_t bMaxBurst;
|
||||
uint8_t bmAttributes_super;
|
||||
uint16_t wBytesPerInterval;
|
||||
};
|
||||
|
||||
/* Interface descriptor */
|
||||
|
@ -131,23 +127,16 @@ struct USBDescIface {
|
|||
|
||||
uint8_t ndesc;
|
||||
USBDescOther* descs;
|
||||
USBDescEndpoint* eps;
|
||||
USBDescEndpoint* eps; // endpoints supported by this interface
|
||||
USBDescIface(bool bDefault);
|
||||
~USBDescIface();
|
||||
};
|
||||
|
||||
/* conceptually an Interface Association Descriptor, and releated interfaces */
|
||||
struct USBDescIfaceAssoc {
|
||||
uint8_t bFirstInterface;
|
||||
uint8_t bInterfaceCount;
|
||||
uint8_t bFunctionClass;
|
||||
uint8_t bFunctionSubClass;
|
||||
uint8_t bFunctionProtocol;
|
||||
uint8_t iFunction;
|
||||
|
||||
uint8_t nif;
|
||||
const USBDescIface* ifs;
|
||||
};
|
||||
/*
|
||||
* ergo720: I removed the Interface Association Descriptor (IAD) since, at the time of this writing (2018), the xboxdevwiki documents that all
|
||||
* known xid devices don't use them and also, according to the corresponding standard, IAD applies to usb revision 2.0 while the xbox uses
|
||||
* usb revision 1.1 so it shouldn't support them either. If this turns out to be incorrect, then IAD support will have to be added
|
||||
*/
|
||||
|
||||
/* Configuration descriptor */
|
||||
struct USBDescConfig {
|
||||
|
@ -156,14 +145,8 @@ struct USBDescConfig {
|
|||
uint8_t iConfiguration; // index of string descriptor describing this configuration
|
||||
uint8_t bmAttributes; // configuration characteristics
|
||||
uint8_t bMaxPower; // maximum power consumption of the USB device in this configuration expressed in 2mA units
|
||||
|
||||
/* grouped interfaces */
|
||||
uint8_t nif_groups;
|
||||
const USBDescIfaceAssoc* if_groups;
|
||||
|
||||
/* "normal" interfaces */
|
||||
uint8_t nif;
|
||||
const USBDescIface* ifs;
|
||||
uint8_t nif; // number of interfaces (again)
|
||||
const USBDescIface* ifs; // interfaces supported by this configuration
|
||||
};
|
||||
|
||||
/* Device descriptor part 1 */
|
||||
|
@ -174,7 +157,7 @@ struct USBDescDevice {
|
|||
uint8_t bDeviceProtocol; // protocol code (assigned by the USB)
|
||||
uint8_t bMaxPacketSize0; // maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid)
|
||||
uint8_t bNumConfigurations; // number of possible configurations
|
||||
const USBDescConfig* confs; // configuration descriptor in use
|
||||
const USBDescConfig* confs; // configurations supported by this device
|
||||
USBDescDevice(bool bDefault);
|
||||
~USBDescDevice();
|
||||
};
|
||||
|
@ -198,13 +181,12 @@ struct USBDesc {
|
|||
};
|
||||
|
||||
/* USB endpoint */
|
||||
struct USBEndpoint
|
||||
{
|
||||
struct USBEndpoint {
|
||||
uint8_t Num; // endpoint number
|
||||
uint8_t pid;
|
||||
uint8_t Type; // the type of this endpoint
|
||||
uint8_t IfNum; // interface number this endpoint belongs to
|
||||
int MaxPacketSize;
|
||||
int MaxPacketSize; // maximum packet size supported by this endpoint
|
||||
bool Pipeline;
|
||||
bool Halted; // indicates that the endpoint is halted
|
||||
XboxDeviceState* Dev; // device this endpoint belongs to
|
||||
|
@ -212,8 +194,7 @@ struct USBEndpoint
|
|||
};
|
||||
|
||||
/* definition of an Xbox usb device */
|
||||
struct XboxDeviceState
|
||||
{
|
||||
struct XboxDeviceState {
|
||||
USBPort* Port; // usb port struct of this device
|
||||
int PortPath; // port index to which this device is attached to
|
||||
char* Serial;
|
||||
|
@ -239,14 +220,14 @@ struct XboxDeviceState
|
|||
USBEndpoint EP_out[USB_MAX_ENDPOINTS]; // endpoints for IN tokens
|
||||
|
||||
QLIST_HEAD(, USBDescString) Strings; // strings of the string descriptor
|
||||
const USBDesc* UsbDesc; // Overrides class usb_desc if not NULL
|
||||
const USBDesc* UsbDesc; // Overrides class usb_desc if not nullptr
|
||||
const USBDescDevice* Device; // device descriptor part 1
|
||||
|
||||
int Configuration; // number of the selected configuration descriptor
|
||||
int NumInterfaces; // number of available interface descriptors
|
||||
int AltSetting[USB_MAX_INTERFACES]; //
|
||||
const USBDescConfig* Config; // configuration descriptor in use
|
||||
const USBDescIface* Ifaces[USB_MAX_INTERFACES];
|
||||
int Configuration; // number of the selected configuration descriptor
|
||||
int NumInterfaces; // number of available interface descriptors
|
||||
int AltSetting[USB_MAX_INTERFACES]; // alternate setting numbers for the current interface
|
||||
const USBDescConfig* Config; // configuration in use
|
||||
const USBDescIface* Ifaces[USB_MAX_INTERFACES]; // interface in use
|
||||
};
|
||||
|
||||
struct USBCombinedPacket {
|
||||
|
@ -256,8 +237,7 @@ struct USBCombinedPacket {
|
|||
};
|
||||
|
||||
/* Structure used to hold information about an active USB packet */
|
||||
struct USBPacket
|
||||
{
|
||||
struct USBPacket {
|
||||
int Pid; // Packet ID (used to identify the type of packet that is being sent)
|
||||
uint32_t Id; // Paddr of the TD for this packet
|
||||
USBEndpoint* Endpoint; // endpoint this packet is transferred to
|
||||
|
@ -275,9 +255,26 @@ struct USBPacket
|
|||
QTAILQ_ENTRY(USBPacket) CombinedEntry;
|
||||
};
|
||||
|
||||
struct USBPortOps {
|
||||
std::function<void(USBPort*port)> attach;
|
||||
std::function<void(USBPort *port)> detach;
|
||||
/*
|
||||
* This gets called when a device downstream from the device attached to
|
||||
* the port (attached through a hub) gets detached.
|
||||
*/
|
||||
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
|
||||
* the packet originated when a hub is involved.
|
||||
*/
|
||||
std::function<void(USBPort* port, USBPacket* p)> complete;
|
||||
};
|
||||
|
||||
/* Struct describing the status of a usb port */
|
||||
struct USBPort {
|
||||
XboxDeviceState* Dev; // usb device (if present)
|
||||
USBPortOps* Operations; // functions to call when a port event happens
|
||||
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
|
||||
|
@ -285,8 +282,7 @@ struct USBPort {
|
|||
};
|
||||
|
||||
/* Struct which stores general functions/variables regarding the peripheral */
|
||||
struct USBDeviceClass
|
||||
{
|
||||
struct USBDeviceClass {
|
||||
std::function<int(XboxDeviceState* dev)> init;
|
||||
|
||||
// Walk (enabled) downstream ports, check for a matching device.
|
||||
|
|
Loading…
Reference in New Issue