Some refactoring + started Hub device work
This commit is contained in:
parent
36c60e7ca7
commit
138e103ca4
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -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.
|
||||
// *
|
||||
|
|
|
@ -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.
|
||||
// *
|
||||
|
|
|
@ -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.
|
||||
// *
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
Loading…
Reference in New Issue