More hub init + some refactoring

This commit is contained in:
ergo720 2018-07-02 01:35:24 +02:00
parent a51bde22b6
commit 0691b8bfb4
12 changed files with 250 additions and 110 deletions

View File

@ -295,7 +295,7 @@
<ClInclude Include="..\..\src\Common\Win32\AlignPrefix1.h" />
<ClInclude Include="..\..\src\Common\XDVDFS Tools\buffered_io.h" />
<ClInclude Include="..\..\src\Common\XDVDFS Tools\xdvdfs.h" />
<ClInclude Include="..\..\src\Cxbx.h" />
<ClInclude Include="..\..\src\CxbxCommon.h" />
<ClInclude Include="..\..\src\CxbxKrnl\CxbxKrnl.h" />
<ClInclude Include="..\..\src\CxbxKrnl\DbgConsole.h" />
<ClInclude Include="..\..\src\CxbxKrnl\EmuD3D8.h" />
@ -420,7 +420,7 @@
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\Common\Cxbx.cpp" />
<ClCompile Include="..\..\src\Common\CxbxCommon.cpp" />
<ClCompile Include="..\..\src\Common\Win32\InlineFunc.cpp" />
<ClCompile Include="..\..\src\Common\Win32\Threads.cpp" />
<ClCompile Include="..\..\src\Common\CxbxDebugger.cpp" />

View File

@ -284,7 +284,6 @@
<ClCompile Include="..\..\src\CxbxKrnl\Timer.cpp">
<Filter>Emulator</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Common\Cxbx.cpp" />
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\devices\usb\OHCI.cpp">
@ -295,6 +294,9 @@
</ClCompile>
<ClCompile Include="..\..\src\devices\usb\Hub.cpp">
<Filter>Hardware\Usb</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Common\CxbxCommon.cpp" />
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Cxbx\DlgXboxControllerPortMapping.cpp">
<Filter>GUI</Filter>
@ -343,9 +345,6 @@
<ClInclude Include="..\..\src\CxbxKrnl\EmuKrnlLogging.h">
<Filter>Kernel</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Cxbx.h">
<Filter>Shared</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CxbxKrnl\Emu.h">
<Filter>Shared</Filter>
</ClInclude>
@ -594,6 +593,9 @@
</ClInclude>
<ClInclude Include="..\..\src\devices\usb\UsbCommon.h">
<Filter>Hardware\Usb</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CxbxCommon.h">
<Filter>Shared</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Cxbx\DlgXboxControllerPortMapping.h">
<Filter>GUI</Filter>

View File

@ -34,7 +34,7 @@
#ifndef CXBXKRNL_H
#define CXBXKRNL_H
#include "Cxbx.h"
#include "CxbxCommon.h"
#include "Common/Xbe.h"
#undef FIELD_OFFSET // prevent macro redefinition warnings

View File

@ -36,6 +36,7 @@
#include "OHCI.h"
#include "Hub.h"
#include "..\CxbxKrnl\EmuKrnl.h" // For EmuWarning
#define NUM_PORTS 8
@ -55,15 +56,15 @@ int PlayerToUsbArray[] = {
};
struct USBHubPort {
USBPort port; // downstream ports of the hub
USBPort port; // downstream port status
uint16_t wPortStatus;
uint16_t wPortChange;
};
struct USBHubState {
XboxDeviceState dev;
XboxDeviceState dev; // hub device status
USBEndpoint* intr;
USBHubPort ports[NUM_PORTS];
USBHubPort ports[NUM_PORTS]; // downstream ports of the hub
};
USBDescIface::USBDescIface(bool bDefault)
@ -83,8 +84,12 @@ USBDescIface::USBDescIface(bool bDefault)
}
USBDescIface::~USBDescIface()
{
delete descs;
{
delete descs; // always one struct of this?
if (bNumEndpoints != 1) {
delete[] eps;
return;
}
delete eps;
}
@ -108,7 +113,14 @@ USBDescDevice::USBDescDevice(bool bDefault)
}
}
USBDescDevice::~USBDescDevice() { delete confs; }
USBDescDevice::~USBDescDevice()
{
if (bNumConfigurations != 1) {
delete[] confs;
return;
}
delete confs;
}
static const USBDescDevice desc_device_hub(true);
@ -255,12 +267,12 @@ int Hub::UsbHub_Initfn(XboxDeviceState* dev)
int i;
if (dev->Port->HubCount == 5) {
DbgPrintf("Hub: chain too deep");
DbgPrintf("Hub: chain too deep\n");
return -1;
}
usb_desc_create_serial(dev);
usb_desc_init(dev);
CreateSerial(dev);
UsbDescInit(dev);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
for (i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
@ -274,6 +286,7 @@ int Hub::UsbHub_Initfn(XboxDeviceState* dev)
}
/*
* From XQEMU:
* This function creates a serial number for a usb device.
* The serial number should:
* (a) Be unique within the emulator.
@ -287,52 +300,150 @@ int Hub::UsbHub_Initfn(XboxDeviceState* dev)
*/
void Hub::CreateSerial(XboxDeviceState* dev)
{
DeviceState *hcd = dev->qdev.parent_bus->parent;
const USBDesc* desc = GetUsbDeviceDesc(dev);
int index = desc->id.iSerialNumber;
USBDescString* s;
char serial[64];
char* path;
int dst;
if (dev->serial) {
/* 'serial' usb bus property has priority if present */
usb_desc_set_string(dev, index, dev->serial);
return;
}
assert(index != 0 && desc->str[index] != NULL);
dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]);
path = qdev_get_dev_path(hcd);
if (path) {
dst += snprintf(serial + dst, sizeof(serial) - dst, "-%s", path);
}
dst += snprintf(serial + dst, sizeof(serial) - dst, "-%s", dev->port->path);
usb_desc_set_string(dev, index, serial);
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->usb_desc) {
return dev->usb_desc;
if (dev->UsbDesc) {
return dev->UsbDesc;
}
return klass->usb_desc;
}
void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
{
USBDescString *s;
QLIST_FOREACH(s, &dev->strings, next) {
if (s->index == index) {
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)
{
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());
}
if (s == NULL) {
s = g_malloc0(sizeof(*s));
s->index = index;
QLIST_INSERT_HEAD(&dev->strings, s, next);
}
g_free(s->str);
s->str = g_strdup(str);
UsbDescSetConfig(dev, 0);
}
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 == NULL) {
return -1;
}
old = dev->altsetting[index];
dev->altsetting[index] = value;
dev->ifaces[index] = iface;
usb_desc_ep_init(dev);
if (old != value) {
usb_device_set_interface(dev, index, old, value);
}
return 0;
}
const USBDescIface* Hub::UsbDescFindInterface(XboxDeviceState* dev, int nif, int alt)
{
const USBDescIface* iface;
int g, 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];
if (iface->bInterfaceNumber == nif &&
iface->bAlternateSetting == alt) {
return iface;
}
}
return NULL;
}

View File

@ -74,7 +74,7 @@ class Hub final : public UsbPeripheral
int request, int value, int index, int length, uint8_t* data);
void UsbHub_HandleData(XboxDeviceState* dev, USBPacket* p);
void UsbHub_HandleDestroy(XboxDeviceState* dev);
// TODO: perhaps these can be put in UsbPeripheral...
// TODO: perhaps these can be put in UsbPeripheral or USBDevice...
// initialize the endpoints of this peripheral
void UsbEpInit();
// destroy hub
@ -87,6 +87,16 @@ class Hub final : public UsbPeripheral
const USBDesc* GetUsbDeviceDesc(XboxDeviceState* dev);
// create a serial number for the device
void CreateSerial(XboxDeviceState* dev);
//
void UsbDescInit(XboxDeviceState* dev);
//
void UsbDescSetDefaults(XboxDeviceState* dev);
//
int UsbDescSetConfig(XboxDeviceState* dev, int value);
//
int UsbDescSetInterface(XboxDeviceState* dev, int index, int value);
//
const USBDescIface* UsbDescFindInterface(XboxDeviceState* dev, int nif, int alt);
};
extern Hub* g_HubObjArray[4];

View File

@ -178,30 +178,25 @@
#define USB_HZ 12000000
#define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1
#define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
#define OHCI_PAGE_MASK 0xFFFFF000
#define OHCI_OFFSET_MASK 0xFFF
typedef enum _USB_SPEED
{
USB_SPEED_MASK_LOW = 1 << 0,
USB_SPEED_MASK_FULL = 1 << 1,
}
USB_SPEED;
OHCI::OHCI(int Irq, USBDevice* UsbObj)
{
int offset = 0;
m_IrqNum = Irq;
m_UsbDevice = UsbObj;
if (m_IrqNum == 9) {
offset = 2;
}
for (int i = 0; i < 2; i++) {
m_UsbDevice->USB_RegisterPort(&m_Registers.RhPort[i].UsbPort, i, 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);
}
OHCI_PacketInit(&m_UsbPacket);
@ -1423,7 +1418,7 @@ void OHCI::OHCI_Attach(USBPort* Port)
port->HcRhPortStatus |= OHCI_PORT_CCS | OHCI_PORT_CSC;
// update speed
if (port->UsbPort.Dev->speed == USB_SPEED_LOW) {
if (port->UsbPort.Dev->Speed == USB_SPEED_LOW) {
port->HcRhPortStatus |= OHCI_PORT_LSDA;
}
else {

View File

@ -142,7 +142,6 @@ struct OHCI_Registers
uint32_t HcRhDescriptorA;
uint32_t HcRhDescriptorB;
uint32_t HcRhStatus;
// For some reason, both XQEMU and OpenXbox set 4 ports per HC, for a total of 8 usb ports.
OHCIPort RhPort[2]; // 2 ports per HC, for a total of 4 USB ports
};

View File

@ -60,10 +60,12 @@ void USBDevice::Init(unsigned int address)
if (address == USB0_BASE) {
m_HostController = new OHCI(1, this);
m_PciPath = "pci.0:02.0";
return;
}
m_HostController = new OHCI(9, this);
m_PciPath = "pci.0:03.0";
}
uint32_t USBDevice::MMIORead(int barIndex, uint32_t addr, unsigned size)

View File

@ -63,7 +63,9 @@ class USBDevice : public PCIDevice {
// USBDevice-specific functions/variables
// pointer to the host controller this device refers to
OHCI* m_HostController = nullptr;
OHCI* m_HostController;
// PCI path of this usb device
const char* m_PciPath;
// register a port with the HC
void USB_RegisterPort(USBPort* Port, int Index, int SpeedMask);

View File

@ -37,7 +37,7 @@
#ifndef USBCOMMON_H_
#define USBCOMMON_H_
#include "Cxbx.h"
#include "CxbxCommon.h"
#include "..\devices\video\queue.h"
#include <functional>
@ -65,6 +65,16 @@
#define USB_TOKEN_IN 0x69 // device -> host
#define USB_TOKEN_OUT 0xE1 // host -> device
#define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1
typedef enum _USB_SPEED
{
USB_SPEED_MASK_LOW = 1 << 0,
USB_SPEED_MASK_FULL = 1 << 1,
}
USB_SPEED;
typedef enum USBPacketState {
USB_PACKET_UNDEFINED = 0,
@ -80,6 +90,13 @@ struct USBPacket;
struct XboxDeviceState;
typedef const char* USBDescStrings[256];
/* String descriptor */
struct USBDescString {
uint8_t index; // index of this string descriptor
std::string str; // the string of this string descriptor
QLIST_ENTRY(USBDescString) next;
};
struct USBDescOther {
uint8_t length;
const uint8_t* data;
@ -102,14 +119,15 @@ struct USBDescEndpoint {
uint16_t wBytesPerInterval;
};
/* Interface descriptor */
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 bInterfaceNumber; // number of interface
uint8_t bAlternateSetting; // value used to select the alternate setting for the interface identified by bInterfaceNumber
uint8_t bNumEndpoints; // number of endpoints used by this interface (excluding endpoint zero)
uint8_t bInterfaceClass; // class code (assigned by the USB)
uint8_t bInterfaceSubClass; // subclass code (assigned by the USB)
uint8_t bInterfaceProtocol; // protocol code (assigned by the USB)
uint8_t iInterface; // index of string descriptor describing this interface
uint8_t ndesc;
USBDescOther* descs;
@ -131,12 +149,13 @@ struct USBDescIfaceAssoc {
const USBDescIface* ifs;
};
/* Configuration descriptor */
struct USBDescConfig {
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
uint8_t bNumInterfaces; // number of interfaces supported by this configuration
uint8_t bConfigurationValue; // value to use as an argument to the SetConfiguration() request to select this configuration
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;
@ -147,25 +166,27 @@ struct USBDescConfig {
const USBDescIface* ifs;
};
/* Device descriptor part 1 */
struct USBDescDevice {
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
const USBDescConfig* confs;
uint16_t bcdUSB; // USB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H)
uint8_t bDeviceClass; // class code (assigned by the USB)
uint8_t bDeviceSubClass; // subclass code (assigned by the USB)
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
USBDescDevice(bool bDefault);
~USBDescDevice();
};
/* Device descriptor part 2 */
struct USBDescID {
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber; // index of string descriptor
uint16_t idVendor; // vendor ID (assigned by the USB)
uint16_t idProduct; // product ID (assigned by the manufacturer)
uint16_t bcdDevice; // device release number in binary-coded decimal
uint8_t iManufacturer; // index of string descriptor describing manufacturer
uint8_t iProduct; // index of string descriptor describing product
uint8_t iSerialNumber; // index of string descriptor describing the devices serial number
};
/* Global USB Descriptor struct */
@ -186,23 +207,21 @@ struct USBEndpoint
int MaxPacketSize;
bool Pipeline;
bool Halted; // indicates that the endpoint is halted
XboxDeviceState* Dev; // device this endpoint belongs to
QTAILQ_HEAD(, USBPacket) Queue; // queue of packets to this endpoint
XboxDeviceState* Dev; // device this endpoint belongs to
QTAILQ_HEAD(, USBPacket) Queue; // queue of packets to this endpoint
};
/* definition of an Xbox usb device */
struct XboxDeviceState
{
USBPort* Port; // usb port struct of this device
int PortPath; // port index to which this device is attached to
char* Serial;
uint32_t flags;
USBDeviceClass* klass; // usb class struct of this device
// Actual connected speed
int speed;
// Supported speeds, not in info because it may be variable (hostdevs)
int speedmask;
USBPort* Port; // usb port struct of this device
int PortPath; // port index to which this device is attached to
char* Serial;
uint32_t flags;
USBDeviceClass* klass; // usb class struct of this device
int Speed; // actual connected speed
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
int Attached; // device is attached
@ -219,15 +238,15 @@ struct XboxDeviceState
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;
QLIST_HEAD(, USBDescString) Strings; // strings of the string descriptor
const USBDesc* UsbDesc; // Overrides class usb_desc if not NULL
const USBDescDevice* Device; // device descriptor part 1
int configuration;
int ninterfaces;
int altsetting[USB_MAX_INTERFACES];
const USBDescConfig *config;
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]; //
const USBDescConfig* Config; // configuration descriptor in use
const USBDescIface* Ifaces[USB_MAX_INTERFACES];
};
struct USBCombinedPacket {
@ -260,8 +279,8 @@ struct USBPacket
struct USBPort {
XboxDeviceState* 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 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
};
@ -310,7 +329,7 @@ struct USBDeviceClass
// has been unlinked / stopped. Optional may be NULL.
std::function<void(XboxDeviceState* Dev, USBEndpoint* EP)> ep_stopped;
const char* product_desc;
const char* product_desc; // friendly name of the device
const USBDesc* usb_desc; // device descriptor
};