Updated some comments
This commit is contained in:
parent
ebcb6ba9a0
commit
34bbcfde32
|
@ -34,7 +34,7 @@
|
|||
// *
|
||||
// ******************************************************************
|
||||
|
||||
// Acknowledgment: some the functions present are from XQEMU (GPLv2)
|
||||
// Acknowledgment: some of the functions present are from XQEMU (GPLv2)
|
||||
// https://xqemu.com/
|
||||
|
||||
// The intent of this file is to add general functions which are not kernel specific (for those CxbxKrnl.h should be used instead)
|
||||
|
|
|
@ -2413,8 +2413,11 @@ PAddr VMManager::TranslateVAddrToPAddr(const VAddr addr)
|
|||
|
||||
Lock();
|
||||
|
||||
// ergo720: horrendous hack, this identity maps all allocations done by the VMManager to keep the LLE OHCI working
|
||||
// (see OHCI_ReadHCCA for more details). Once LLE CPU and MMU are implemented, this can be removed
|
||||
// ergo720: horrendous hack, this identity maps all allocations done by the VMManager to keep the LLE USB working.
|
||||
// The problem is that if the user buffer pointed to by the TD is allocated by the VMManager with VirtualAlloc, then
|
||||
// the physical allocation will not reside in memory.bin and if we tried to access the physical address of it, we
|
||||
// would access a random page with undefined contents.
|
||||
// NOTE: Once LLE CPU and MMU are implemented, this can be removed.
|
||||
|
||||
//if (IS_USER_ADDRESS(addr)) { Type = UserRegion; }
|
||||
//else if (IS_PHYSICAL_ADDRESS(addr)) { Type = ContiguousRegion; }
|
||||
|
|
|
@ -172,7 +172,7 @@ static const uint8_t HubDescriptor[] =
|
|||
0x0A, // u8 bDescLength; 10 bytes
|
||||
0x29, // u8 bDescriptorType; Hub-descriptor
|
||||
NUM_PORTS, // u8 bNbrPorts; 0x08
|
||||
0x0a, // u16 wHubCharacteristics; (individual port over-current protection, no power switching)
|
||||
0x0A, // u16 wHubCharacteristics; (individual port over-current protection, no power switching)
|
||||
0x00,
|
||||
0x01, // u8 bPwrOn2pwrGood; 2 ms
|
||||
0x00, // u8 bHubContrCurrent; 0 mA
|
||||
|
@ -355,8 +355,8 @@ void Hub::UsbHub_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
}
|
||||
|
||||
case GetHubStatus: {
|
||||
// From the standard: "This request returns the current hub status and the states that have changed since the previous acknowledgment.
|
||||
// The first word of data contains wHubStatus. The second word of data contains wHubChange"
|
||||
// From the USB 1.1 standard: "This request returns the current hub status and the states that have changed since the
|
||||
// previous acknowledgment. The first word of data contains wHubStatus. The second word of data contains wHubChange"
|
||||
// We always report that the local power supply is good and that currently there is no over-power condition
|
||||
data[0] = 0;
|
||||
data[1] = 0;
|
||||
|
@ -367,7 +367,7 @@ void Hub::UsbHub_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
}
|
||||
|
||||
case GetPortStatus: {
|
||||
// From the standard: "This request returns the current port status and the current value of the port status change bits.
|
||||
// From the USB 1.1 standard: "This request returns the current port status and the current value of the port status change bits.
|
||||
// The first word of data contains wPortStatus. The second word of data contains wPortChange"
|
||||
unsigned int n = index - 1;
|
||||
USBHubPort* port;
|
||||
|
@ -375,8 +375,8 @@ void Hub::UsbHub_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
goto fail;
|
||||
}
|
||||
port = &m_HubState->ports[n];
|
||||
DBG_PRINTF("%s GetPortStatus -> Address 0x%X, wIndex %d, wPortStatus %d, wPortChange %d\n",
|
||||
__func__, m_HubState->dev.Addr, index, port->wPortStatus, port->wPortChange);
|
||||
DBG_PRINTF("GetPortStatus -> Address 0x%X, wIndex %d, wPortStatus %d, wPortChange %d\n",
|
||||
m_HubState->dev.Addr, index, port->wPortStatus, port->wPortChange);
|
||||
data[0] = port->wPortStatus;
|
||||
data[1] = port->wPortStatus >> 8;
|
||||
data[2] = port->wPortChange;
|
||||
|
@ -394,14 +394,14 @@ void Hub::UsbHub_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
}
|
||||
|
||||
case SetPortFeature: {
|
||||
// From the standard: "This request sets a value reported in the port status. Features that can be set with this request are PORT_RESET,
|
||||
// PORT_SUSPEND and PORT_POWER; others features are not required to be set by this request"
|
||||
// From the USB 1.1 standard: "This request sets a value reported in the port status. Features that can be set with this request are
|
||||
// PORT_RESET, PORT_SUSPEND and PORT_POWER; others features are not required to be set by this request"
|
||||
unsigned int n = index - 1;
|
||||
USBHubPort* port;
|
||||
XboxDeviceState* dev;
|
||||
|
||||
DBG_PRINTF("%s SetPortFeature -> Address 0x%X, wIndex %d, Feature %s\n",
|
||||
__func__, m_HubState->dev.Addr, index, GetFeatureName(value).c_str());
|
||||
DBG_PRINTF("SetPortFeature -> Address 0x%X, wIndex %d, Feature %s\n",
|
||||
m_HubState->dev.Addr, index, GetFeatureName(value).c_str());
|
||||
|
||||
if (n >= NUM_PORTS) {
|
||||
goto fail;
|
||||
|
@ -434,12 +434,12 @@ void Hub::UsbHub_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
}
|
||||
|
||||
case ClearPortFeature: {
|
||||
// From the standard: "This request resets a value reported in the port status"
|
||||
// From USB 1.1 the standard: "This request resets a value reported in the port status"
|
||||
unsigned int n = index - 1;
|
||||
USBHubPort *port;
|
||||
|
||||
DBG_PRINTF("%s ClearPortFeature -> Address 0x%X, wIndex %d, Feature %s\n",
|
||||
__func__, m_HubState->dev.Addr, index, GetFeatureName(value).c_str());
|
||||
DBG_PRINTF("ClearPortFeature -> Address 0x%X, wIndex %d, Feature %s\n",
|
||||
m_HubState->dev.Addr, index, GetFeatureName(value).c_str());
|
||||
|
||||
if (n >= NUM_PORTS) {
|
||||
goto fail;
|
||||
|
@ -525,7 +525,7 @@ void Hub::UsbHub_HandleData(XboxDeviceState* dev, USBPacket* p)
|
|||
p->Status = USB_RET_BABBLE;
|
||||
return;
|
||||
}
|
||||
DBG_PRINTF("%s Address 0x%X, Status %d\n", __func__, m_HubState->dev.Addr, status);
|
||||
DBG_PRINTF("Address 0x%X, Status %d\n", m_HubState->dev.Addr, status);
|
||||
for (i = 0; i < n; i++) {
|
||||
buf[i] = status >> (8 * i);
|
||||
}
|
||||
|
|
|
@ -293,7 +293,7 @@ void OHCI::OHCI_FrameBoundaryWorker()
|
|||
|
||||
// Process all the lists at the end of the frame
|
||||
if (m_Registers.HcControl & OHCI_CTL_PLE) {
|
||||
// From the standard: "The head pointer used for a particular frame is determined by using the last 5 bits of the
|
||||
// From the OHCI standard: "The head pointer used for a particular frame is determined by using the last 5 bits of the
|
||||
// Frame Counter as an offset into the interrupt array within the HCCA."
|
||||
int n = m_Registers.HcFmNumber & 0x1F;
|
||||
OHCI_ServiceEDlist(hcca.HccaInterrruptTable[n], 0); // dropped little -> big endian conversion from XQEMU
|
||||
|
@ -316,7 +316,7 @@ void OHCI::OHCI_FrameBoundaryWorker()
|
|||
return;
|
||||
}
|
||||
|
||||
// From the standard: "This bit is loaded from the FrameIntervalToggle field of
|
||||
// From the OHCI standard: "This bit is loaded from the FrameIntervalToggle field of
|
||||
// HcFmInterval whenever FrameRemaining reaches 0."
|
||||
m_Registers.HcFmRemaining = (m_Registers.HcFmInterval & OHCI_FMI_FIT) == 0 ?
|
||||
m_Registers.HcFmRemaining & ~OHCI_FMR_FRT : m_Registers.HcFmRemaining | OHCI_FMR_FRT;
|
||||
|
@ -327,13 +327,13 @@ void OHCI::OHCI_FrameBoundaryWorker()
|
|||
|
||||
if (m_DoneCount == 0 && !(m_Registers.HcInterruptStatus & OHCI_INTR_WD)) {
|
||||
if (!m_Registers.HcDoneHead) {
|
||||
// From the standard: "This is set to zero whenever HC writes the content of this
|
||||
// From the OHCI standard: "This is set to zero whenever HC writes the content of this
|
||||
// register to HCCA. It also sets the WritebackDoneHead of HcInterruptStatus."
|
||||
CxbxKrnlCleanup("HcDoneHead is zero but WritebackDoneHead interrupt is not set!\n");
|
||||
}
|
||||
|
||||
if (m_Registers.HcInterrupt & m_Registers.HcInterruptStatus) {
|
||||
// From the standard: "The least significant bit of this entry is set to 1 to indicate whether an
|
||||
// From the OHCI standard: "The least significant bit of this entry is set to 1 to indicate whether an
|
||||
// unmasked HcInterruptStatus was set when HccaDoneHead was written." It's tecnically incorrect to
|
||||
// do this to HcDoneHead instead of HccaDoneHead however it doesn't matter since HcDoneHead is
|
||||
// zeroed below
|
||||
|
@ -371,21 +371,11 @@ void OHCI::OHCI_FatalError()
|
|||
|
||||
OHCI_SetInterrupt(OHCI_INTR_UE);
|
||||
OHCI_BusStop();
|
||||
EmuLog(LOG_LEVEL::WARNING, "an unrecoverable error occoured!\n");
|
||||
EmuLog(LOG_LEVEL::WARNING, "An unrecoverable error has occoured!\n");
|
||||
}
|
||||
|
||||
bool OHCI::OHCI_ReadHCCA(xbaddr Paddr, OHCI_HCCA* Hcca)
|
||||
{
|
||||
// ergo720: what's written below is true if we identity map only allocations served by VirtualAlloc.
|
||||
// There could be a peculiar problem if the shared memory between HCD and HC is allocated by the
|
||||
// VMManager with VirtualAlloc: the physical allocation would not reside in memory.bin and if we tried to
|
||||
// access the physical address of it, we would access an empty page. In practice, I disassembled various
|
||||
// xbe's of my games and discovered that this shared memory is allocated with MmAllocateContiguousMemory
|
||||
// which means we can access it from the contiguous region just fine (lucky)
|
||||
// ... provided that XDK revisions didn't alter this
|
||||
|
||||
// NOTE: this shared memory contains the HCCA + EDs and TDs
|
||||
|
||||
return Memory_R(reinterpret_cast<void*>(Paddr), Hcca, sizeof(OHCI_HCCA));
|
||||
}
|
||||
|
||||
|
@ -446,7 +436,7 @@ bool OHCI::OHCI_CopyTDBuffer(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsW
|
|||
return false; // no bytes left to copy
|
||||
}
|
||||
|
||||
// From the standard: "If during the data transfer the buffer address contained in the HC<48>fs working copy of
|
||||
// From the OHCI standard: "If during the data transfer the buffer address contained in the HC<48>fs working copy of
|
||||
// CurrentBufferPointer crosses a 4K boundary, the upper 20 bits of BufferEnd are copied to the
|
||||
// working value of CurrentBufferPointer causing the next buffer address to be the 0th byte in the
|
||||
// same 4K page that contains the last byte of the buffer."
|
||||
|
@ -503,7 +493,7 @@ int OHCI::OHCI_ServiceEDlist(xbaddr Head, int Completion)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// From the standard "An Endpoint Descriptor (ED) is a 16-byte, memory resident structure that must be aligned to a
|
||||
// From the OHCI standard "An Endpoint Descriptor (ED) is a 16-byte, memory resident structure that must be aligned to a
|
||||
// 16-byte boundary."
|
||||
next_ed = ed.NextED & OHCI_DPTR_MASK;
|
||||
|
||||
|
@ -585,7 +575,7 @@ int OHCI::OHCI_ServiceTD(OHCI_ED* Ed)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// From the standard: "This 2-bit field indicates the direction of data flow and the PID
|
||||
// From the OHCI standard: "This 2-bit field indicates the direction of data flow and the PID
|
||||
// to be used for the token. This field is only relevant to the HC if the D field in the ED
|
||||
// was set to 00b or 11b indicating that the PID determination is deferred to the TD."
|
||||
direction = OHCI_BM(Ed->Flags, ED_D);
|
||||
|
@ -1119,7 +1109,7 @@ void OHCI::OHCI_WriteRegister(xbaddr Addr, uint32_t Value)
|
|||
// SOC is read-only
|
||||
Value &= ~OHCI_STATUS_SOC;
|
||||
|
||||
// From the standard: "The Host Controller must ensure that bits written as 1 become set
|
||||
// From the OHCI standard: "The Host Controller must ensure that bits written as 1 become set
|
||||
// in the register while bits written as 0 remain unchanged in the register."
|
||||
m_Registers.HcCommandStatus |= Value;
|
||||
|
||||
|
@ -1510,7 +1500,7 @@ void OHCI::OHCI_Wakeup(USBPort* port1)
|
|||
// Note that the controller can be suspended even if this port is not
|
||||
if ((m_Registers.HcControl & OHCI_CTL_HCFS) == Suspend) {
|
||||
DBG_PRINTF("remote-wakeup: SUSPEND->RESUME\n");
|
||||
// From the standard: "The only interrupts possible in the USBSUSPEND state are ResumeDetected (the
|
||||
// From the OHCI 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;
|
||||
|
@ -1591,7 +1581,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion)
|
|||
|
||||
starting_frame = OHCI_BM(iso_td.Flags, TD_SF);
|
||||
frame_count = OHCI_BM(iso_td.Flags, TD_FC);
|
||||
// From the standard: "The Host Controller does an unsigned subtraction of StartingFrame from the 16 bits of
|
||||
// From the OHCI standard: "The Host Controller does an unsigned subtraction of StartingFrame from the 16 bits of
|
||||
// HcFmNumber to arrive at a signed value for a relative frame number (frame R)."
|
||||
relative_frame_number = USUB(m_Registers.HcFmNumber & 0xFFFF, starting_frame);
|
||||
|
||||
|
@ -1613,13 +1603,13 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion)
|
|||
#endif
|
||||
|
||||
if (relative_frame_number < 0) {
|
||||
// From the standard: "If the relative frame number is negative, then the current frame is earlier than the 0th frame
|
||||
// From the OHCI standard: "If the relative frame number is negative, then the current frame is earlier than the 0th frame
|
||||
// of the Isochronous TD and the Host Controller advances to the next ED."
|
||||
DBG_PRINTF("ISO_TD R=%d < 0\n", relative_frame_number);
|
||||
return 1;
|
||||
}
|
||||
else if (relative_frame_number > frame_count) {
|
||||
// From the standard: "If the relative frame number is greater than
|
||||
// From the OHCI standard: "If the relative frame number is greater than
|
||||
// FrameCount, then the Isochronous TD has expired and a error condition exists."
|
||||
DBG_PRINTF("ISO_TD R=%d > FC=%d\n", relative_frame_number, frame_count);
|
||||
OHCI_SET_BM(iso_td.Flags, TD_CC, OHCI_CC_DATAOVERRUN);
|
||||
|
@ -1638,7 +1628,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// From the standard: "If the relative frame number is between 0 and FrameCount, then the Host Controller issues
|
||||
// From the OHCI standard: "If the relative frame number is between 0 and FrameCount, then the Host Controller issues
|
||||
// a token to the endpoint and attempts a data transfer using the buffer described by the Isochronous TD."
|
||||
|
||||
dir = OHCI_BM(ed->Flags, ED_D);
|
||||
|
@ -1674,7 +1664,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion)
|
|||
start_offset = iso_td.Offset[relative_frame_number];
|
||||
next_offset = iso_td.Offset[relative_frame_number + 1];
|
||||
|
||||
// From the standard: "If the Host Controller supports checking of the Offsets, if either Offset[R] or Offset[R+1] does
|
||||
// From the OHCI standard: "If the Host Controller supports checking of the Offsets, if either Offset[R] or Offset[R+1] does
|
||||
// not have a ConditionCode of NOT ACCESSED or if the Offset[R + 1] is not greater than or equal to Offset[R], then
|
||||
// an Unrecoverable Error is indicated."
|
||||
// ergo720: I have a doubt here: according to the standard, the error condition is set if ConditionCode (bits 12-15 of
|
||||
|
@ -1694,7 +1684,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// From the standard: "Bit 12 of offset R then selects the upper 20 bits of the physical address
|
||||
// From the OHCI standard: "Bit 12 of offset R then selects the upper 20 bits of the physical address
|
||||
// as either BufferPage0 when bit 12 = 0 or the upper 20 bits of BufferEnd when bit 12 = 1."
|
||||
|
||||
if ((start_offset & 0x1000) == 0) {
|
||||
|
@ -1706,7 +1696,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion)
|
|||
(start_offset & OHCI_OFFSET_MASK);
|
||||
}
|
||||
|
||||
// From the standard: "If the data packet is not the last in an Isochronous TD (R not equal to FrameCount),
|
||||
// From the OHCI standard: "If the data packet is not the last in an Isochronous TD (R not equal to FrameCount),
|
||||
// then the ending address of the buffer is found by using Offset[R + 1] - 1. This value is then used to create a
|
||||
// physical address in the same manner as the Offset[R] was used to create the starting physical address."
|
||||
|
||||
|
@ -1722,7 +1712,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion)
|
|||
}
|
||||
}
|
||||
else {
|
||||
// From the standard: "If, however, the data packet is the last in an Isochronous TD(R = FrameCount),
|
||||
// From the OHCI standard: "If, however, the data packet is the last in an Isochronous TD(R = FrameCount),
|
||||
// then the value of BufferEnd is the address of the last byte in the buffer."
|
||||
end_addr = iso_td.BufferEnd;
|
||||
}
|
||||
|
@ -1766,7 +1756,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion)
|
|||
start_offset, end_offset, start_addr, end_addr, str, len, ret);
|
||||
#endif
|
||||
|
||||
// From the standard: "After each data packet transfer, the Rth Offset is replaced with a value that indicates the status of
|
||||
// From the OHCI standard: "After each data packet transfer, the Rth Offset is replaced with a value that indicates the status of
|
||||
// the data packet transfer.The upper 4 bits of the value are the ConditionCode for the transfer and the lower 12 bits
|
||||
// represent the size of the transfer.Together, these two fields constitute the Packet Status Word(PacketStatusWord)."
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ class OHCI
|
|||
|
||||
|
||||
private:
|
||||
// pointer to g_USB0 or g_USB1
|
||||
// pointer to g_USB0
|
||||
USBDevice* m_UsbDevice = nullptr;
|
||||
// all the registers available in the OHCI standard
|
||||
OHCI_Registers m_Registers;
|
||||
|
|
|
@ -81,7 +81,7 @@ uint32_t USBDevice::MMIORead(int barIndex, uint32_t addr, unsigned size)
|
|||
// barIndex must be zero since we created the USB devices with a zero index in Init()
|
||||
assert(barIndex == 0);
|
||||
|
||||
// read the register of the corresponding HC
|
||||
// read the register of the HC
|
||||
return m_HostController->OHCI_ReadRegister(addr);
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ void USBDevice::MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned
|
|||
// barIndex must be zero since we created the USB devices with a zero index in Init()
|
||||
assert(barIndex == 0);
|
||||
|
||||
// write the register of the corresponding HC
|
||||
// write the register of the HC
|
||||
m_HostController->OHCI_WriteRegister(addr, value);
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ void USBDevice::USB_PacketCheckState(USBPacket* p, USBPacketState expected)
|
|||
return;
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::WARNING, "packet state check failed!");
|
||||
EmuLog(LOG_LEVEL::WARNING, "Packet state check failed!");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
@ -324,7 +324,7 @@ void USBDevice::USB_DoTokenSetup(XboxDeviceState* s, USBPacket* p)
|
|||
{
|
||||
int request, value, index;
|
||||
|
||||
// From the standard "Every Setup packet has eight bytes."
|
||||
// From the USB 1.1 standard "Every Setup packet has eight bytes."
|
||||
if (p->IoVec.Size != 8) {
|
||||
p->Status = USB_RET_STALL;
|
||||
return;
|
||||
|
@ -362,7 +362,7 @@ void USBDevice::USB_DoTokenSetup(XboxDeviceState* s, USBPacket* p)
|
|||
}
|
||||
else {
|
||||
if (s->SetupLength > sizeof(s->DataBuffer)) {
|
||||
DBG_PRINTF("ctrl buffer too small (%d > %zu)\n", s->SetupLength, sizeof(s->DataBuffer));
|
||||
DBG_PRINTF("CTRL buffer too small (%d > %zu)\n", s->SetupLength, sizeof(s->DataBuffer));
|
||||
p->Status = USB_RET_STALL;
|
||||
return;
|
||||
}
|
||||
|
@ -726,7 +726,7 @@ void USBDevice::USBDesc_SetDefaults(XboxDeviceState* dev)
|
|||
break;
|
||||
}
|
||||
default:
|
||||
EmuLog(LOG_LEVEL::WARNING, "unknown speed parameter %d set in %s", dev->Speed, dev->ProductDesc.c_str());
|
||||
EmuLog(LOG_LEVEL::WARNING, "Unknown speed parameter %d set in %s", dev->Speed, dev->ProductDesc.c_str());
|
||||
}
|
||||
USBDesc_SetConfig(dev, 0);
|
||||
}
|
||||
|
@ -809,14 +809,14 @@ void USBDevice::USBDesc_EpInit(XboxDeviceState* dev)
|
|||
const USBDescIface *iface;
|
||||
int i, e, pid, ep;
|
||||
|
||||
USB_EpInit(dev); // reset endpoints (because we changed descriptors in use?)
|
||||
USB_EpInit(dev); // reset endpoints
|
||||
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:
|
||||
// From the USB 1.1 standard:
|
||||
// "bEndpointAddress:
|
||||
// Bit 3...0: The endpoint number
|
||||
// Bit 6...4: Reserved, reset to zero
|
||||
|
@ -842,16 +842,16 @@ int USBDevice::USBDesc_HandleControl(XboxDeviceState* dev, USBPacket *p,
|
|||
assert(desc != nullptr);
|
||||
switch (request) {
|
||||
case DeviceOutRequest | USB_REQ_SET_ADDRESS: {
|
||||
// From the standard: "This request sets the device address for all future device accesses.
|
||||
// From the USB 1.1 standard: "This request sets the device address for all future device accesses.
|
||||
// The wValue field specifies the device address to use for all subsequent accesses"
|
||||
dev->Addr = value;
|
||||
DBG_PRINTF("address 0x%X set for device %s\n", dev->Addr, dev->ProductDesc.c_str());
|
||||
DBG_PRINTF("Address 0x%X set for device %s\n", dev->Addr, dev->ProductDesc.c_str());
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceRequest | USB_REQ_GET_DESCRIPTOR: {
|
||||
// From the standard: "This request returns the specified descriptor if the descriptor exists.
|
||||
// From the USB 1.1 standard: "This request returns the specified descriptor if the descriptor exists.
|
||||
// The wValue field specifies the descriptor type in the high byte and the descriptor index in the low byte.
|
||||
// The wIndex field specifies the Language ID for string descriptors or is reset to zero for other descriptors"
|
||||
ret = USBDesc_HandleStandardGetDescriptor(dev, p, value, data, length);
|
||||
|
@ -859,7 +859,7 @@ int USBDevice::USBDesc_HandleControl(XboxDeviceState* dev, USBPacket *p,
|
|||
}
|
||||
|
||||
case DeviceRequest | USB_REQ_GET_CONFIGURATION: {
|
||||
// From the standard: "This request returns the current device configuration value.
|
||||
// From the USB 1.1 standard: "This request returns the current device configuration value.
|
||||
// If the returned value is zero, the device is not configured"
|
||||
data[0] = dev->Config ? dev->Config->bConfigurationValue : 0;
|
||||
p->ActualLength = 1;
|
||||
|
@ -868,16 +868,16 @@ int USBDevice::USBDesc_HandleControl(XboxDeviceState* dev, USBPacket *p,
|
|||
}
|
||||
|
||||
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: {
|
||||
// From the standard: "This request sets the device configuration. The lower byte of the wValue field specifies the desired configuration.
|
||||
// From the USB 1.1 standard: "This request sets the device configuration. The lower byte of the wValue field specifies the desired configuration.
|
||||
// This configuration value must be zero or match a configuration value from a configuration descriptor"
|
||||
ret = USBDesc_SetConfig(dev, value);
|
||||
DBG_PRINTF("received standard SetConfiguration() request for device at address 0x%X. Configuration selected is %d and returned %d\n",
|
||||
DBG_PRINTF("Received standard SetConfiguration() request for device at address 0x%X. Configuration selected is %d and returned %d\n",
|
||||
dev->Addr, value, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceRequest | USB_REQ_GET_STATUS: {
|
||||
// From the standard: "This request returns the status for the specified recipient. The Recipient bits of the bmRequestType field
|
||||
// From the USB 1.1 standard: "This request returns the status for the specified recipient. The Recipient bits of the bmRequestType field
|
||||
// specify the desired recipient. The data returned is the current status of the specified recipient."
|
||||
// From XQEMU:
|
||||
/* Default state: Device behavior when this request is received while
|
||||
|
@ -899,31 +899,31 @@ int USBDevice::USBDesc_HandleControl(XboxDeviceState* dev, USBPacket *p,
|
|||
}
|
||||
|
||||
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: {
|
||||
// From the standard: "This request is used to clear or disable a specific feature.
|
||||
// From the USB 1.1 standard: "This request is used to clear or disable a specific feature.
|
||||
// Feature selector values in wValue must be appropriate to the recipient"
|
||||
if (value == USB_DEVICE_REMOTE_WAKEUP) {
|
||||
dev->RemoteWakeup = 0;
|
||||
ret = 0;
|
||||
}
|
||||
DBG_PRINTF("received standard ClearFeature() request for device at address 0x%X. Feature selected is %d and returned %d\n",
|
||||
DBG_PRINTF("Received standard ClearFeature() request for device at address 0x%X. Feature selected is %d and returned %d\n",
|
||||
dev->Addr, value, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceOutRequest | USB_REQ_SET_FEATURE: {
|
||||
// From the standard: "This request is used to set or enable a specific feature.
|
||||
// From the USB 1.1 standard: "This request is used to set or enable a specific feature.
|
||||
// Feature selector values in wValue must be appropriate to the recipient"
|
||||
if (value == USB_DEVICE_REMOTE_WAKEUP) {
|
||||
dev->RemoteWakeup = 1;
|
||||
ret = 0;
|
||||
}
|
||||
DBG_PRINTF("received standard SetFeature() request for device at address 0x%X. Feature selected is %d and returned %d\n",
|
||||
DBG_PRINTF("Received standard SetFeature() request for device at address 0x%X. Feature selected is %d and returned %d\n",
|
||||
dev->Addr, value, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case InterfaceRequest | USB_REQ_GET_INTERFACE: {
|
||||
// From the standard: "This request returns the selected alternate setting for the specified interface.
|
||||
// From the USB 1.1 standard: "This request returns the selected alternate setting for the specified interface.
|
||||
// wValue = Zero; wIndex = Interface"
|
||||
if (index < 0 || index >= dev->NumInterfaces) {
|
||||
break;
|
||||
|
@ -935,10 +935,10 @@ int USBDevice::USBDesc_HandleControl(XboxDeviceState* dev, USBPacket *p,
|
|||
}
|
||||
|
||||
case InterfaceOutRequest | USB_REQ_SET_INTERFACE: {
|
||||
// From the standard: "This request allows the host to select an alternate setting for the specified interface"
|
||||
// From the USB 1.1 standard: "This request allows the host to select an alternate setting for the specified interface"
|
||||
// wValue = Alternative Setting; wIndex = Interface
|
||||
ret = USBDesc_SetInterface(dev, index, value);
|
||||
DBG_PRINTF("received standard SetInterface() request for device at address 0x%X. Interface selected is %d, Alternative Setting \
|
||||
DBG_PRINTF("Received standard SetInterface() request for device at address 0x%X. Interface selected is %d, Alternative Setting \
|
||||
is %d and returned %d\n", dev->Addr, index, value, ret);
|
||||
break;
|
||||
}
|
||||
|
@ -961,12 +961,12 @@ int USBDevice::USBDesc_HandleStandardGetDescriptor(XboxDeviceState* dev, USBPack
|
|||
|
||||
// Dropped from XQEMU bcdUSB check for usb 3.0 devices
|
||||
|
||||
// From the standard: "The standard request to a device supports three types of descriptors: DEVICE, CONFIGURATION, and STRING."
|
||||
// From the USB 1.1 standard: "The standard request to a device supports three types of descriptors: DEVICE, CONFIGURATION, and STRING."
|
||||
|
||||
switch (type) {
|
||||
case USB_DT_DEVICE: {
|
||||
ret = USB_ReadDeviceDesc(&desc->id, dev->Device, buf, sizeof(buf));
|
||||
DBG_PRINTF("read operation of device descriptor of device 0x%X returns %d\n", dev->Addr, ret);
|
||||
DBG_PRINTF("Read operation of device descriptor of device 0x%X returns %d\n", dev->Addr, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -974,13 +974,13 @@ int USBDevice::USBDesc_HandleStandardGetDescriptor(XboxDeviceState* dev, USBPack
|
|||
if (index < dev->Device->bNumConfigurations) {
|
||||
ret = USB_ReadConfigurationDesc(dev->Device->confs + index, flags, buf, sizeof(buf));
|
||||
}
|
||||
DBG_PRINTF("read operation of configuration descriptor %d of device 0x%X returns %d\n", index, dev->Addr, ret);
|
||||
DBG_PRINTF("Read operation of configuration descriptor %d of device 0x%X returns %d\n", index, dev->Addr, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_DT_STRING: {
|
||||
ret = USB_ReadStringDesc(dev, index, buf, sizeof(buf));
|
||||
DBG_PRINTF("read operation of string descriptor %d of device 0x%X returns %d\n", index, dev->Addr, ret);
|
||||
DBG_PRINTF("Read operation of string descriptor %d of device 0x%X returns %d\n", index, dev->Addr, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1048,7 +1048,7 @@ int USBDevice::USB_ReadConfigurationDesc(const USBDescConfig* conf, int flags, u
|
|||
return -1;
|
||||
}
|
||||
|
||||
// From the standard: "A request for a configuration descriptor returns the configuration descriptor, all interface
|
||||
// From the USB 1.1 standard: "A request for a configuration descriptor returns the configuration descriptor, all interface
|
||||
// descriptors, and endpoint descriptors for all of the interfaces in a single request."
|
||||
|
||||
d->bLength = bLength;
|
||||
|
@ -1084,7 +1084,7 @@ int USBDevice::USB_ReadInterfaceDesc(const USBDescIface* iface, int flags, uint8
|
|||
return -1;
|
||||
}
|
||||
|
||||
// From the standard: "The first interface descriptor follows the configuration descriptor.
|
||||
// From the USB 1.1 standard: "The first interface descriptor follows the configuration descriptor.
|
||||
// The endpoint descriptors for the first interface follow the first interface descriptor.
|
||||
// If there are additional interfaces, their interface descriptor and endpoint descriptors
|
||||
// follow the first interface’s endpoint descriptors. Class-specific and/or vendor-specific
|
||||
|
@ -1156,7 +1156,7 @@ int USBDevice::USB_ReadEndpointDesc(const USBDescEndpoint* ep, int flags, uint8_
|
|||
d->u.endpoint.bSynchAddress = ep->bSynchAddress;
|
||||
}
|
||||
|
||||
// Dropped from XQEMU the reading of SuperSpeed Endpoint Companion descriptors since those are usb 3.0 specific
|
||||
// Dropped from XQEMU the reading of the SuperSpeed Endpoint Companion descriptors since those are usb 3.0 specific
|
||||
|
||||
if (ep->extra) {
|
||||
std::memcpy(dest + bLength, ep->extra, extralen);
|
||||
|
@ -1175,7 +1175,7 @@ int USBDevice::USB_ReadStringDesc(XboxDeviceState* dev, int index, uint8_t* dest
|
|||
return -1;
|
||||
}
|
||||
|
||||
// From the standard: "String index zero for all languages returns a string descriptor
|
||||
// From the USB 1.1 standard: "String index zero for all languages returns a string descriptor
|
||||
// that contains an array of two-byte LANGID codes supported by the device"
|
||||
|
||||
if (index == 0) {
|
||||
|
@ -1192,7 +1192,7 @@ int USBDevice::USB_ReadStringDesc(XboxDeviceState* dev, int index, uint8_t* dest
|
|||
return 0;
|
||||
}
|
||||
|
||||
// From the standard: "The UNICODE string descriptor is not NULL-terminated. The string length is
|
||||
// From the USB 1.1 standard: "The UNICODE string descriptor is not NULL-terminated. The string length is
|
||||
// computed by subtracting two from the value of the first byte of the descriptor"
|
||||
|
||||
bLength = std::strlen(str) * 2 + 2;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
// *
|
||||
// ******************************************************************
|
||||
|
||||
// Acknowledgment: some the functions present are from XQEMU (GPLv2)
|
||||
// Acknowledgment: some of the functions present are from XQEMU (GPLv2)
|
||||
// https://xqemu.com/
|
||||
|
||||
#ifndef USBCOMMON_H_
|
||||
|
|
|
@ -312,7 +312,7 @@ int XidGamepad::UsbXid_Initfn(XboxDeviceState* dev)
|
|||
void XidGamepad::UsbXid_HandleDestroy()
|
||||
{
|
||||
UsbXidReleasePort(&m_XidState->dev);
|
||||
XidCleanUp();
|
||||
XpadCleanUp();
|
||||
}
|
||||
|
||||
void XidGamepad::UsbXid_Attach(XboxDeviceState* dev)
|
||||
|
@ -328,7 +328,7 @@ void XidGamepad::UsbXid_Attach(XboxDeviceState* dev)
|
|||
|
||||
void XidGamepad::UsbXid_HandleReset()
|
||||
{
|
||||
DBG_PRINTF("reset event\n");
|
||||
DBG_PRINTF("Reset event\n");
|
||||
}
|
||||
|
||||
void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
||||
|
@ -336,7 +336,7 @@ void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
{
|
||||
int ret = m_UsbDev->USBDesc_HandleControl(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
DBG_PRINTF("handled by USBDesc_HandleControl, ret is %d\n", ret);
|
||||
DBG_PRINTF("Handled by USBDesc_HandleControl, ret is %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -346,7 +346,7 @@ void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
// From the HID standard: "The Get_Report request allows the host to receive a report via the Control pipe.
|
||||
// The wValue field specifies the Report Type in the high byte and the Report ID in the low byte. Set Report ID
|
||||
// to 0 (zero) if Report IDs are not used. 01 = input, 02 = output, 03 = feature, 04-FF = reserved"
|
||||
DBG_PRINTF("GET_REPORT 0x%X\n", value);
|
||||
DBG_PRINTF("GET_REPORT xpad request 0x%X\n", value);
|
||||
// JayFoxRox's analysis: "This 0x0100 case is for input.
|
||||
// This is the case where the Xbox wants to read input data from the controller.
|
||||
// Confirmed with a real Duke controller :
|
||||
|
@ -387,7 +387,7 @@ void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
// setting the state of input, output, or feature controls. The meaning of the request fields for the Set_Report
|
||||
// request is the same as for the Get_Report request, however the data direction is reversed and the Report
|
||||
// Data is sent from host to device."
|
||||
DBG_PRINTF("SET_REPORT 0x%X\n", value);
|
||||
DBG_PRINTF("SET_REPORT xpad request 0x%X\n", value);
|
||||
// JayFoxRox's analysis: "The 0x0200 case below is for output.
|
||||
// This is the case where the Xbox wants to write rumble data to the controller.
|
||||
// To my knowledge :
|
||||
|
@ -417,7 +417,7 @@ void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
|
||||
// XID-specific requests
|
||||
case VendorInterfaceRequest | USB_REQ_GET_DESCRIPTOR: {
|
||||
DBG_PRINTF("GET_DESCRIPTOR 0x%x\n", value);
|
||||
DBG_PRINTF("GET_DESCRIPTOR xpad request 0x%x\n", value);
|
||||
if (value == 0x4200) {
|
||||
assert(m_XidState->xid_desc->bLength <= length);
|
||||
std::memcpy(data, m_XidState->xid_desc, m_XidState->xid_desc->bLength);
|
||||
|
@ -431,7 +431,7 @@ void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
}
|
||||
|
||||
case VendorInterfaceRequest | XID_GET_CAPABILITIES: {
|
||||
DBG_PRINTF("XID_GET_CAPABILITIES 0x%x\n", value);
|
||||
DBG_PRINTF("XID_GET_CAPABILITIES xpad request 0x%x\n", value);
|
||||
if (value == 0x0100) {
|
||||
if (length > m_XidState->in_state_capabilities.bLength) {
|
||||
length = m_XidState->in_state_capabilities.bLength;
|
||||
|
@ -455,7 +455,7 @@ void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
|
||||
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8) | USB_REQ_GET_DESCRIPTOR: {
|
||||
/* FIXME: ! */
|
||||
DBG_PRINTF("unknown xpad request 0x%X: value = 0x%X\n", request, value);
|
||||
DBG_PRINTF("Unknown xpad request 0x%X: value = 0x%X\n", request, value);
|
||||
std::memset(data, 0x00, length);
|
||||
//FIXME: Intended for the hub: usbd_get_hub_descriptor, UT_READ_CLASS?!
|
||||
p->Status = USB_RET_STALL;
|
||||
|
@ -465,7 +465,7 @@ void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
|||
|
||||
case ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT) << 8) | USB_REQ_CLEAR_FEATURE: {
|
||||
/* FIXME: ! */
|
||||
DBG_PRINTF("unknown xpad request 0x%X: value = 0x%X\n", request, value);
|
||||
DBG_PRINTF("Unknown xpad request 0x%X: value = 0x%X\n", request, value);
|
||||
std::memset(data, 0x00, length);
|
||||
p->Status = USB_RET_STALL;
|
||||
break;
|
||||
|
@ -530,7 +530,7 @@ void XidGamepad::UsbXid_HandleData(XboxDeviceState* dev, USBPacket* p)
|
|||
}
|
||||
}
|
||||
|
||||
void XidGamepad::XidCleanUp()
|
||||
void XidGamepad::XpadCleanUp()
|
||||
{
|
||||
delete m_pPeripheralFuncStruct;
|
||||
delete m_XidState;
|
||||
|
|
|
@ -49,7 +49,7 @@ class XidGamepad
|
|||
// initialize this peripheral
|
||||
int Init(int port);
|
||||
// destroy gamepad resources
|
||||
void XidCleanUp();
|
||||
void XpadCleanUp();
|
||||
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue