Some refactoring + started Hub device work

This commit is contained in:
ergo720 2018-06-25 11:37:33 +02:00
parent 36c60e7ca7
commit 138e103ca4
10 changed files with 582 additions and 173 deletions

View File

@ -362,7 +362,9 @@
<ClInclude Include="..\..\src\devices\SMBus.h" />
<ClInclude Include="..\..\src\devices\SMCDevice.h" />
<ClInclude Include="..\..\src\devices\SMDevice.h" />
<ClInclude Include="..\..\src\devices\usb\Hub.h" />
<ClInclude Include="..\..\src\devices\usb\OHCI.h" />
<ClInclude Include="..\..\src\devices\usb\UsbCommon.h" />
<ClInclude Include="..\..\src\devices\usb\USBDevice.h" />
<ClInclude Include="..\..\src\devices\video\nv2a.h" />
<ClInclude Include="..\..\src\devices\video\nv2a_debug.h" />
@ -734,6 +736,7 @@
<ClCompile Include="..\..\src\devices\SMBus.cpp" />
<ClCompile Include="..\..\src\devices\SMCDevice.cpp" />
<ClCompile Include="..\..\src\devices\SMDevice.cpp" />
<ClCompile Include="..\..\src\devices\usb\Hub.cpp" />
<ClCompile Include="..\..\src\devices\usb\OHCI.cpp" />
<ClCompile Include="..\..\src\devices\usb\USBDevice.cpp" />
<ClCompile Include="..\..\src\devices\video\nv2a.cpp" />

View File

@ -292,6 +292,9 @@
</ClCompile>
<ClCompile Include="..\..\src\devices\usb\USBDevice.cpp">
<Filter>Hardware\Usb</Filter>
</ClCompile>
<ClCompile Include="..\..\src\devices\usb\Hub.cpp">
<Filter>Hardware\Usb</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Cxbx\DlgXboxControllerPortMapping.cpp">
<Filter>GUI</Filter>
@ -585,6 +588,12 @@
</ClInclude>
<ClInclude Include="..\..\src\devices\usb\USBDevice.h">
<Filter>Hardware\Usb</Filter>
</ClInclude>
<ClInclude Include="..\..\src\devices\usb\Hub.h">
<Filter>Hardware\Usb</Filter>
</ClInclude>
<ClInclude Include="..\..\src\devices\usb\UsbCommon.h">
<Filter>Hardware\Usb</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Cxbx\DlgXboxControllerPortMapping.h">
<Filter>GUI</Filter>

View File

@ -70,6 +70,7 @@ namespace xboxkrnl
#include "devices\Xbox.h" // For InitXboxHardware()
#include "devices\LED.h" // For LED::Sequence
#include "EmuSha.h" // For the SHA1 functions
#include "Timer.h" // For Timer_Init
/*! thread local storage */
Xbe::TLS *CxbxKrnl_TLS = NULL;

175
src/devices/usb/Hub.cpp Normal file
View File

@ -0,0 +1,175 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->devices->usb->Hub.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * 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 recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2018 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#include "Hub.h"
USBDescIface::USBDescIface(bool bDefault)
{
std::memset(this, 0, sizeof(USBDescIface));
if (bDefault) {
bInterfaceNumber = 0;
bNumEndpoints = 1;
bInterfaceClass = USB_CLASS_HUB;
eps = new USBDescEndpoint();
eps->bEndpointAddress = USB_DIR_IN | 0x01;
eps->bmAttributes = USB_ENDPOINT_XFER_INT;
eps->wMaxPacketSize = 1 + (NUM_PORTS + 7) / 8;
eps->bInterval = 0xFF;
}
}
USBDescIface::~USBDescIface() { delete eps; }
static const USBDescIface desc_iface_hub(true);
USBDescDevice::USBDescDevice()
{
std::memset(this, 0, sizeof(USBDescDevice));
bcdUSB = 0x0110;
bDeviceClass = USB_CLASS_HUB;
bMaxPacketSize0 = 8;
bNumConfigurations = 1;
confs->bNumInterfaces = 1;
confs->bConfigurationValue = 1;
confs->bmAttributes = 0xE0;
confs->nif = 1;
confs->ifs = &desc_iface_hub;
}
static const USBDescStrings desc_strings = {
[STR_MANUFACTURER] = "Cxbx-Reloaded",
[STR_PRODUCT] = "Cxbx-Reloaded USB Hub",
[STR_SERIALNUMBER] = "314159",
};
static const USBDesc desc_hub = {
id.idVendor = 0x0409,
id.idProduct = 0x55AA,
id.bcdDevice = 0x0101,
id.iManufacturer = STR_MANUFACTURER,
id.iProduct = STR_PRODUCT,
id.iSerialNumber = STR_SERIALNUMBER,
full = &desc_device_hub,
str = desc_strings,
};
void Hub::Init()
{
ClassInitFn();
UsbEpInit();
rc = usb_claim_port(dev);
if (rc != 0) {
return rc;
}
rc = usb_device_init(dev);
if (rc != 0) {
usb_release_port(dev);
return rc;
}
if (dev->auto_attach) {
rc = usb_device_attach(dev);
if (rc != 0) {
usb_qdev_exit(qdev);
return rc;
}
}
}
void Hub::ClassInitFn()
{
//DeviceClass *dc = DEVICE_CLASS(klass);
m_pPeripheralFuncStruct = new USBDeviceClass;
m_pDeviceStruct = new XboxDevice;
m_pDeviceStruct->ProductDesc = "Cxbx-Reloaded USB Hub";
QLIST_INIT(&m_pDeviceStruct->Strings);
{
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, _1);
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->usb_desc = &desc_hub;
}
//set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
//dc->fw_name = "hub";
//dc->vmsd = &vmstate_usb_hub;
}
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()
{
int ep;
dev->EP_ctl.Num = 0;
dev->EP_ctl.Type = USB_ENDPOINT_XFER_CONTROL;
dev->EP_ctl.ifnum = 0;
dev->EP_ctl.max_packet_size = 64;
dev->EP_ctl.dev = dev;
dev->EP_ctl.pipeline = false;
for (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].max_packet_size = 0;
dev->ep_out[ep].max_packet_size = 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;
}
}

71
src/devices/usb/Hub.h Normal file
View File

@ -0,0 +1,71 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->devices->usb->Hub.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * 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 recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2018 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#include "UsbCommon.h"
/* same as Linux kernel root hubs */
typedef enum ft{
STR_MANUFACTURER = 1,
STR_PRODUCT,
STR_SERIALNUMBER,
};
/* Class which implements a usb hub */
class Hub final : public UsbPeripheral
{
public:
// initialize this peripheral
void Init() override;
private:
// initialize various member variables/functions
void ClassInitFn();
// see USBDeviceClass for comments about these functions
int UsbHub_Initfn(XboxDevice* dev);
XboxDevice* UsbHub_FindDevice(XboxDevice* dev, uint8_t addr);
void UsbHub_HandleReset(XboxDevice* dev);
void UsbHub_HandleControl(XboxDevice* dev, USBPacket* p,
int request, int value, int index, int length, uint8_t* data);
void UsbHub_HandleData(XboxDevice* dev, USBPacket* p);
void UsbHub_HandleDestroy(XboxDevice* dev);
// initialize the endpoints of this peripheral
void UsbEpInit();
//
void UsbEpReset();
};

View File

@ -9,7 +9,7 @@
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->devices->USBController->OHCI.cpp
// * Cxbx->devices->usb->OHCI.cpp
// *
// * This file is part of the Cxbx project.
// *

View File

@ -9,7 +9,7 @@
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->devices->USBController->OHCI.h
// * Cxbx->devices->usb->OHCI.h
// *
// * This file is part of the Cxbx project.
// *

View File

@ -9,7 +9,7 @@
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->devices->USBController->USBDevice.cpp
// * Cxbx->devices->usb->USBDevice.cpp
// *
// * This file is part of the Cxbx project.
// *

View File

@ -9,7 +9,7 @@
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->devices->USBController->USBDevice.h
// * Cxbx->devices->usb->USBDevice.h
// *
// * This file is part of the Cxbx project.
// *
@ -33,180 +33,13 @@
// * All rights reserved
// *
// ******************************************************************
#ifndef USBDEVICE_H_
#define USBDEVICE_H_
#include "Cxbx.h"
#include "..\PCIDevice.h"
#include "..\devices\video\queue.h"
#include "UsbCommon.h"
#define USB_MAX_ENDPOINTS 15
#define USB_MAX_INTERFACES 16
#define USB_STATE_NOTATTACHED 0
#define USB_STATE_ATTACHED 1
#define USB_STATE_DEFAULT 2
typedef enum USBPacketState {
USB_PACKET_UNDEFINED = 0,
USB_PACKET_SETUP,
USB_PACKET_QUEUED,
USB_PACKET_ASYNC,
USB_PACKET_COMPLETE,
USB_PACKET_CANCELED,
}
USBPacketState;
typedef struct _USBPacket USBPacket;
typedef struct _XboxDevice XboxDevice;
/* USB endpoint */
typedef struct _USBEndpoint
{
uint8_t Num; // endpoint number
uint8_t pid;
uint8_t Type; // the type of this endpoint
uint8_t ifnum;
int max_packet_size;
bool Pipeline;
bool Halted; // indicates that the endpoint is halted
XboxDevice* Dev; // device this endpoint belongs to
QTAILQ_HEAD(, _USBPacket) Queue; // queue of packets to this endpoint
}
USBEndpoint;
/* definition of an Xbox usb device */
typedef struct _XboxDevice
{
DeviceState qdev;
USBPort *port;
char *port_path;
char *serial;
void *opaque;
uint32_t flags;
// Actual connected speed
int speed;
// Supported speeds, not in info because it may be variable (hostdevs)
int speedmask;
uint8_t Addr; // device function address
char product_desc[32];
int auto_attach;
int Attached; // device is attached
int32_t State; // current state of device
uint8_t SetupBuffer[8]; // holds the IoVec structs copied (control transfers only?)
uint8_t data_buf[4096];
int32_t RemoteWakeup; // wakeup flag
int32_t SetupState; // result of a setup tken processing operation
int32_t SetupLength; // number of bytes to transfer as specified by a setup token
int32_t SetupIndex; // index of the parameter in a setup token?
USBEndpoint EP_ctl; // endpoints for SETUP tokens
USBEndpoint EP_in[USB_MAX_ENDPOINTS]; // endpoints for OUT tokens
USBEndpoint EP_out[USB_MAX_ENDPOINTS]; // endpoints for IN tokens
//QLIST_HEAD(, USBDescString) strings;
const USBDesc *usb_desc; // Overrides class usb_desc if not NULL
const USBDescDevice *device;
int configuration;
int ninterfaces;
int altsetting[USB_MAX_INTERFACES];
const USBDescConfig *config;
const USBDescIface *ifaces[USB_MAX_INTERFACES];
}
XboxDevice;
// ergo720: this could be merged in the OHCI or USBDevice class if possible
typedef struct USBDeviceClass
{
DeviceClass parent_class;
int(*init)(USBDev *dev);
// Walk (enabled) downstream ports, check for a matching device.
// Only hubs implement this.
USBDev *(*find_device)(USBDev *dev, uint8_t addr);
// Called when a packet is canceled.
void(*cancel_packet)(USBDev *dev, USBPacket *p);
// Called when device is destroyed.
void(*handle_destroy)(USBDev *dev);
// Attach the device
void(*handle_attach)(USBDev *dev);
// Reset the device
void(*handle_reset)(USBDev *dev);
// Process control request.
// Called from handle_packet().
// Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
// then the number of bytes transferred is stored in p->actual_length
void(*handle_control)(USBDev *dev, USBPacket *p, int request, int value,
int index, int length, uint8_t *data);
// Process data transfers (both BULK and ISOC).
// Called from handle_packet().
// Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
// then the number of bytes transferred is stored in p->actual_length
void(*handle_data)(USBDev *dev, USBPacket *p);
void(*set_interface)(USBDev *dev, int Interface,
int alt_old, int alt_new);
// Called when the hcd is done queuing packets for an endpoint, only
// necessary for devices which can return USB_RET_ADD_TO_QUEUE.
void(*flush_ep_queue)(USBDev *dev, USBEndpoint *ep);
// Called by the hcd to let the device know the queue for an endpoint
// has been unlinked / stopped. Optional may be NULL.
void(*EP_Stopped)(USBDev* Dev, USBEndpoint* EP);
const char *product_desc;
const USBDesc *usb_desc;
}
USBDeviceClass;
typedef struct _USBCombinedPacket {
_USBPacket* First;
QTAILQ_HEAD(packets_head, _USBPacket) Packets;
IOVector IoVec;
}
USBCombinedPacket;
/* Structure used to hold information about an active USB packet */
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
unsigned int Stream;
IOVector IoVec; // used to perform vectored I/O
uint64_t Parameter; // control transfers
bool ShortNotOK; // the bufferRounding mode of the TD for this packet
bool IntReq; // whether or not to generate an interrupt for this packet (DelayInterrupt of the TD is zero)
int Status; // USB_RET_* status code
int ActualLength; // before copy: offset inside IoVec structs; after copy: number of bytes actually transferred
// Internal use by the USB layer
USBPacketState State;
USBCombinedPacket* Combined;
QTAILQ_ENTRY(_USBPacket) Queue;
QTAILQ_ENTRY(_USBPacket) CombinedEntry;
};
/* Struct describing the status of a usb port */
typedef struct _USBPort {
XboxDevice* Dev; // usb device (if present)
int SpeedMask; // usb speeds supported
int HubCount; // number of hubs attached
char Path[16]; // the number of the port
int PortIndex; // internal port index
QTAILQ_ENTRY(_USBPort) Next;
}
USBPort;
// Forward declare OHCI class for USBDevice class
class OHCI;

317
src/devices/usb/UsbCommon.h Normal file
View File

@ -0,0 +1,317 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->devices->usb->UsbCommon.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * 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 recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2018 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#include "Cxbx.h"
#include "..\devices\video\queue.h"
#include <functional>
#define USB_MAX_ENDPOINTS 15
#define USB_MAX_INTERFACES 16
#define USB_STATE_NOTATTACHED 0
#define USB_STATE_ATTACHED 1
#define USB_STATE_DEFAULT 2
typedef enum USBPacketState {
USB_PACKET_UNDEFINED = 0,
USB_PACKET_SETUP,
USB_PACKET_QUEUED,
USB_PACKET_ASYNC,
USB_PACKET_COMPLETE,
USB_PACKET_CANCELED,
}
USBPacketState;
typedef struct _USBPacket USBPacket;
typedef struct _XboxDevice XboxDevice;
typedef const char* USBDescStrings[256];
typedef struct _USBDescOther {
uint8_t length;
const uint8_t *data;
}
USBDescOther;
typedef struct _USBDescEndpoint {
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
uint8_t bRefresh;
uint8_t bSynchAddress;
uint8_t is_audio; /* has bRefresh + bSynchAddress */
uint8_t *extra;
/* superspeed endpoint companion */
uint8_t bMaxBurst;
uint8_t bmAttributes_super;
uint16_t wBytesPerInterval;
}
USBDescEndpoint;
struct USBDescIface {
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
uint8_t ndesc;
USBDescOther* descs;
USBDescEndpoint* eps;
USBDescIface(bool bDefault);
~USBDescIface();
};
/* conceptually an Interface Association Descriptor, and releated interfaces */
typedef 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;
}
USBDescIfaceAssoc;
typedef struct _USBDescConfig {
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
/* grouped interfaces */
uint8_t nif_groups;
const USBDescIfaceAssoc* if_groups;
/* "normal" interfaces */
uint8_t nif;
const USBDescIface* ifs;
}
USBDescConfig;
struct USBDescDevice {
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
const USBDescConfig* confs;
USBDescDevice();
};
typedef struct _USBDescID {
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
}
USBDescID;
typedef struct _USBDesc {
USBDescID id;
const USBDescDevice* full;
const char* const* str;
}
USBDesc;
/* USB endpoint */
typedef struct _USBEndpoint
{
uint8_t Num; // endpoint number
uint8_t pid;
uint8_t Type; // the type of this endpoint
uint8_t ifnum;
int max_packet_size;
bool Pipeline;
bool Halted; // indicates that the endpoint is halted
XboxDevice* Dev; // device this endpoint belongs to
QTAILQ_HEAD(, _USBPacket) Queue; // queue of packets to this endpoint
}
USBEndpoint;
/* definition of an Xbox usb device */
typedef struct _XboxDevice
{
DeviceState qdev;
USBPort *port;
char *port_path;
char *serial;
void *opaque;
uint32_t flags;
// Actual connected speed
int speed;
// Supported speeds, not in info because it may be variable (hostdevs)
int speedmask;
uint8_t Addr; // device function address
std::string ProductDesc; // the friendly name of this device
int Attached; // device is attached
int32_t State; // current state of device
uint8_t SetupBuffer[8]; // holds the IoVec structs copied (control transfers only?)
uint8_t data_buf[4096];
int32_t RemoteWakeup; // wakeup flag
int32_t SetupState; // result of a setup tken processing operation
int32_t SetupLength; // number of bytes to transfer as specified by a setup token
int32_t SetupIndex; // index of the parameter in a setup token?
USBEndpoint EP_ctl; // endpoints for SETUP tokens
USBEndpoint EP_in[USB_MAX_ENDPOINTS]; // endpoints for OUT tokens
USBEndpoint EP_out[USB_MAX_ENDPOINTS]; // endpoints for IN tokens
QLIST_HEAD(, USBDescString) Strings;
const USBDesc *usb_desc; // Overrides class usb_desc if not NULL
const USBDescDevice *device;
int configuration;
int ninterfaces;
int altsetting[USB_MAX_INTERFACES];
const USBDescConfig *config;
const USBDescIface *ifaces[USB_MAX_INTERFACES];
}
XboxDevice;
typedef struct _USBCombinedPacket {
_USBPacket* First;
QTAILQ_HEAD(packets_head, _USBPacket) Packets;
IOVector IoVec;
}
USBCombinedPacket;
/* Structure used to hold information about an active USB packet */
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
unsigned int Stream;
IOVector IoVec; // used to perform vectored I/O
uint64_t Parameter; // control transfers
bool ShortNotOK; // the bufferRounding mode of the TD for this packet
bool IntReq; // whether or not to generate an interrupt for this packet (DelayInterrupt of the TD is zero)
int Status; // USB_RET_* status code
int ActualLength; // before copy: offset inside IoVec structs; after copy: number of bytes actually transferred
// Internal use by the USB layer
USBPacketState State;
USBCombinedPacket* Combined;
QTAILQ_ENTRY(_USBPacket) Queue;
QTAILQ_ENTRY(_USBPacket) CombinedEntry;
};
/* Struct describing the status of a usb port */
typedef struct _USBPort {
XboxDevice* Dev; // usb device (if present)
int SpeedMask; // usb speeds supported
int HubCount; // number of hubs attached
char Path[16]; // the number of the port
int PortIndex; // internal port index
QTAILQ_ENTRY(_USBPort) Next;
}
USBPort;
/* Struct which stores general functions/variables regarding the peripheral */
typedef struct _USBDeviceClass
{
std::function<int(XboxDevice* dev)> init;
// Walk (enabled) downstream ports, check for a matching device.
// Only hubs implement this.
std::function<XboxDevice*(XboxDevice* dev, uint8_t addr)> find_device;
// Called when a packet is canceled.
std::function<void(XboxDevice* dev, USBPacket* p)> cancel_packet;
// Called when device is destroyed.
std::function<void(XboxDevice* dev)> handle_destroy;
// Attach the device
std::function<void(XboxDevice* dev)> handle_attach;
// Reset the device
std::function<void(XboxDevice* dev)> handle_reset;
// Process control request.
// Called from handle_packet().
// Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
// then the number of bytes transferred is stored in p->actual_length
std::function<void(XboxDevice* dev, USBPacket* p, int request, int value,
int index, int length, uint8_t *data)> handle_control;
// Process data transfers (both BULK and ISOC).
// Called from handle_packet().
// Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
// then the number of bytes transferred is stored in p->actual_length
std::function<void(XboxDevice* dev, USBPacket* p)> handle_data;
std::function<void(XboxDevice* dev, int Interface,
int alt_old, int alt_new)> set_interface;
// Called when the hcd is done queuing packets for an endpoint, only
// necessary for devices which can return USB_RET_ADD_TO_QUEUE.
std::function<void(XboxDevice* dev, USBEndpoint* ep)> flush_ep_queue;
// Called by the hcd to let the device know the queue for an endpoint
// has been unlinked / stopped. Optional may be NULL.
std::function<void(XboxDevice* Dev, USBEndpoint* EP)> EP_Stopped;
const char* product_desc;
const USBDesc* usb_desc;
}
USBDeviceClass;
/* Abstract class representing a usb peripheral */
class UsbPeripheral
{
protected:
USBDeviceClass* m_pPeripheralFuncStruct;
XboxDevice* m_pDeviceStruct;
virtual void Init() = 0;
};