[USBEHCI_NEW]

- Invoke status change callback at passive level
- Fill out usb descriptor struct instead passing everything in char array
- Use 1 byte interrupt endpoint packet size for hub for now
- Fill in interface information when SelectConfiguration request is passed. Fixes sce callback and pool corruptions
- Return device descriptor in USBHI_QueryDeviceInformation
- Tested in WinXP with special pool enabled & overrun support

svn path=/branches/usb-bringup/; revision=51572
This commit is contained in:
Johannes Anderwald 2011-05-04 11:49:00 +00:00
parent 9cbc4f8f60
commit c2b34a98be
3 changed files with 117 additions and 55 deletions

View file

@ -20,13 +20,18 @@ InterruptServiceRoutine(
IN PKINTERRUPT Interrupt, IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext); IN PVOID ServiceContext);
VOID NTAPI VOID
NTAPI
EhciDefferedRoutine( EhciDefferedRoutine(
IN PKDPC Dpc, IN PKDPC Dpc,
IN PVOID DeferredContext, IN PVOID DeferredContext,
IN PVOID SystemArgument1, IN PVOID SystemArgument1,
IN PVOID SystemArgument2); IN PVOID SystemArgument2);
VOID
NTAPI
StatusChangeWorkItemRoutine(PVOID Context);
class CUSBHardwareDevice : public IUSBHardwareDevice class CUSBHardwareDevice : public IUSBHardwareDevice
{ {
public: public:
@ -81,7 +86,7 @@ public:
// friend function // friend function
friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext);
friend VOID NTAPI EhciDefferedRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); friend VOID NTAPI EhciDefferedRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context);
// constructor / destructor // constructor / destructor
CUSBHardwareDevice(IUnknown *OuterUnknown){} CUSBHardwareDevice(IUnknown *OuterUnknown){}
virtual ~CUSBHardwareDevice(){} virtual ~CUSBHardwareDevice(){}
@ -110,6 +115,7 @@ protected:
PVOID m_SCEContext; // status change callback routine context PVOID m_SCEContext; // status change callback routine context
BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress
EHCI_PORT_STATUS m_PortStatus[16]; // port status EHCI_PORT_STATUS m_PortStatus[16]; // port status
WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback
// set command // set command
VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd); VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd);
@ -190,6 +196,11 @@ CUSBHardwareDevice::Initialize(
// //
KeInitializeSpinLock(&m_Lock); KeInitializeSpinLock(&m_Lock);
//
// intialize status change work item
//
ExInitializeWorkItem(&m_StatusChangeWorkItem, StatusChangeWorkItemRoutine, PVOID(this));
m_VendorID = 0; m_VendorID = 0;
m_DeviceID = 0; m_DeviceID = 0;
@ -774,7 +785,7 @@ CUSBHardwareDevice::ClearPortStatus(
{ {
ULONG Value; ULONG Value;
DPRINT("CUSBHardwareDevice::ClearPortStatus\n"); DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status);
if (PortId > m_Capabilities.HCSParams.PortCount) if (PortId > m_Capabilities.HCSParams.PortCount)
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
@ -1112,9 +1123,9 @@ EhciDefferedRoutine(
if (This->m_SCECallBack != NULL) if (This->m_SCECallBack != NULL)
{ {
// //
// issue callback // queue work item for processing
// //
This->m_SCECallBack(This->m_SCEContext); ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
} }
} }
else else
@ -1131,6 +1142,29 @@ EhciDefferedRoutine(
return; return;
} }
VOID
NTAPI
StatusChangeWorkItemRoutine(
PVOID Context)
{
//
// cast to hardware object
//
CUSBHardwareDevice * This = (CUSBHardwareDevice*)Context;
//
// is there a callback
//
if (This->m_SCECallBack)
{
//
// issue callback
//
This->m_SCECallBack(This->m_SCEContext);
}
}
NTSTATUS NTSTATUS
CreateUSBHardware( CreateUSBHardware(
PUSBHARDWAREDEVICE *OutHardware) PUSBHARDWAREDEVICE *OutHardware)

View file

@ -129,42 +129,39 @@ const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
}; };
const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] = const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR =
{ {
/* one configuration */ sizeof(USB_CONFIGURATION_DESCRIPTOR),
0x09, /* bLength; */ USB_CONFIGURATION_DESCRIPTOR_TYPE,
0x02, /* bDescriptorType; Configuration */ sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
0x19, 0x00, /* wTotalLength; */ 1,
0x01, /* bNumInterfaces; (1) */ 1,
0x23, /* bConfigurationValue; */ 0,
0x00, /* iConfiguration; */ 0x40, /* self powered */
0x40, /* bmAttributes; */ 0x0
0x00 /* MaxPower; */
}; };
const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] = const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR =
{ {
/* one interface */ sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */
0x09, /* bLength: Interface; */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType; Interface */
0x04, /* bDescriptorType; Interface */ 0, /* bInterfaceNumber; */
0x00, /* bInterfaceNumber; */ 0, /* bAlternateSetting; */
0x00, /* bAlternateSetting; */ 0x1, /* bNumEndpoints; */
0x01, /* bNumEndpoints; */
0x09, /* bInterfaceClass; HUB_CLASSCODE */ 0x09, /* bInterfaceClass; HUB_CLASSCODE */
0x01, /* bInterfaceSubClass; */ 0x01, /* bInterfaceSubClass; */
0x00, /* bInterfaceProtocol: */ 0x00, /* bInterfaceProtocol: */
0x00 /* iInterface; */ 0x00, /* iInterface; */
}; };
const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] = const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR =
{ {
/* one endpoint (status change endpoint) */ sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */
0x07, /* bLength; */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
0x05, /* bDescriptorType; Endpoint */ 0x81, /* bEndPointAddress */
0x81, /* bEndpointAddress; IN Endpoint 1 */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
0x03, /* bmAttributes; Interrupt */ 0x01, /* wMaxPacketSize */
0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ 0xC /* bInterval */
0xFF /* bInterval; (255ms -- usb 2.0 spec) */
}; };
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
@ -266,12 +263,12 @@ CHubController::Initialize(
// Set the SCE Callback that the Hardware Device will call on port status change // Set the SCE Callback that the Hardware Device will call on port status change
// //
Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this); Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this);
// //
// clear init flag // clear init flag
// //
m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -286,6 +283,8 @@ CHubController::QueryStatusChageEndpoint(
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
USHORT PortStatus, PortChange; USHORT PortStatus, PortChange;
PURB Urb; PURB Urb;
PUCHAR TransferBuffer;
UCHAR Changed = FALSE;
// //
// get current stack location // get current stack location
@ -303,8 +302,9 @@ CHubController::QueryStatusChageEndpoint(
// Get the number of ports and check each one for device connected // Get the number of ports and check each one for device connected
// //
m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL); m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
DPRINT1("SCE Request\n"); DPRINT1("SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, Urb->UrbBulkOrInterruptTransfer.TransferFlags, Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
((PULONG)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 0;
TransferBuffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer;
for (PortId = 0; PortId < PortCount; PortId++) for (PortId = 0; PortId < PortCount; PortId++)
{ {
m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange); m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
@ -318,14 +318,15 @@ CHubController::QueryStatusChageEndpoint(
{ {
DPRINT1("Device is connected on port %d\n", PortId); DPRINT1("Device is connected on port %d\n", PortId);
// Set the value for the port number // Set the value for the port number
((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((PortId + 1) & 7); *TransferBuffer = 1 << ((PortId + 1) & 7);
Changed = TRUE;
} }
} }
// //
// If there were changes then return TRUE // If there were changes then return TRUE
// //
if (((PULONG)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] != 0) if (Changed != 0)
return TRUE; return TRUE;
return FALSE; return FALSE;
@ -835,7 +836,7 @@ CHubController::HandleClassOther(
ULONG NumPort; ULONG NumPort;
ULONG PortId; ULONG PortId;
//DPRINT1("CHubController::HandleClassOther> Request %x Value %x not implemented\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value); DPRINT("CHubController::HandleClassOther> Request %x Value %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
// //
// get number of ports available // get number of ports available
@ -877,6 +878,7 @@ CHubController::HandleClassOther(
// //
// request contains buffer of 2 ushort which are used from submitting port status and port change status // request contains buffer of 2 ushort which are used from submitting port status and port change status
// //
DPRINT("PortId %x PortStatus %x PortChange %x\n", PortId, PortStatus, PortChange);
Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer; Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer;
// //
@ -973,6 +975,7 @@ CHubController::HandleSelectConfiguration(
PURB Urb) PURB Urb)
{ {
PUSBDEVICE UsbDevice; PUSBDEVICE UsbDevice;
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
// //
// is the request for the Root Hub // is the request for the Root Hub
@ -987,11 +990,33 @@ CHubController::HandleSelectConfiguration(
// //
// set device handle // set device handle
// //
Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)ROOTHUB2_CONFIGURATION_DESCRIPTOR; Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&ROOTHUB2_CONFIGURATION_DESCRIPTOR;
// //
// TODO: copy interface info // copy interface info
// //
InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&ROOTHUB2_INTERFACE_DESCRIPTOR;
InterfaceInfo->Class = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceClass;
InterfaceInfo->SubClass = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceSubClass;
InterfaceInfo->Protocol = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceProtocol;
InterfaceInfo->Reserved = 0;
//
// sanity check
//
PC_ASSERT(InterfaceInfo->NumberOfPipes == 1);
//
// copy pipe info
//
InterfaceInfo->Pipes[0].MaximumPacketSize = ROOTHUB2_ENDPOINT_DESCRIPTOR.wMaxPacketSize;
InterfaceInfo->Pipes[0].EndpointAddress = ROOTHUB2_ENDPOINT_DESCRIPTOR.bEndpointAddress;
InterfaceInfo->Pipes[0].Interval = ROOTHUB2_ENDPOINT_DESCRIPTOR.bInterval;
InterfaceInfo->Pipes[0].PipeType = (USBD_PIPE_TYPE)(ROOTHUB2_ENDPOINT_DESCRIPTOR.bmAttributes & USB_ENDPOINT_TYPE_MASK);
InterfaceInfo->Pipes[0].PipeHandle = (PVOID)&ROOTHUB2_ENDPOINT_DESCRIPTOR;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
else else
@ -1098,6 +1123,8 @@ CHubController::HandleClassDevice(
ULONG PortCount, Dummy2; ULONG PortCount, Dummy2;
USHORT Dummy1; USHORT Dummy1;
DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
// //
// check class request type // check class request type
// //
@ -1142,7 +1169,7 @@ CHubController::HandleClassDevice(
// FIXME: retrieve values // FIXME: retrieve values
// //
UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount; UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount;
UsbHubDescriptor->wHubCharacteristics = 0x0012; UsbHubDescriptor->wHubCharacteristics = 0x00;
UsbHubDescriptor->bPowerOnToPowerGood = 0x01; UsbHubDescriptor->bPowerOnToPowerGood = 0x01;
UsbHubDescriptor->bHubControlCurrent = 0x00; UsbHubDescriptor->bHubControlCurrent = 0x00;
@ -1177,6 +1204,8 @@ CHubController::HandleGetDescriptor(
PUSBDEVICE UsbDevice; PUSBDEVICE UsbDevice;
ULONG Length; ULONG Length;
DPRINT("CHubController::HandleGetDescriptor\n");
// //
// check descriptor type // check descriptor type
// //
@ -1231,8 +1260,7 @@ CHubController::HandleGetDescriptor(
// //
// request is for the root bus controller // request is for the root bus controller
// //
C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR) == sizeof(USB_CONFIGURATION_DESCRIPTOR)); RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR));
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR));
// //
// get configuration descriptor, very retarded! // get configuration descriptor, very retarded!
@ -1248,6 +1276,7 @@ CHubController::HandleGetDescriptor(
// buffer too small // buffer too small
// //
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
ASSERT(FALSE);
break; break;
} }
@ -1255,15 +1284,13 @@ CHubController::HandleGetDescriptor(
// copy interface descriptor template // copy interface descriptor template
// //
Buffer = (PUCHAR)(ConfigurationDescriptor + 1); Buffer = (PUCHAR)(ConfigurationDescriptor + 1);
C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR) == sizeof(USB_INTERFACE_DESCRIPTOR)); RtlCopyMemory(Buffer, &ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR));
RtlCopyMemory(Buffer, ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR));
// //
// copy end point descriptor template // copy end point descriptor template
// //
Buffer += sizeof(USB_INTERFACE_DESCRIPTOR); Buffer += sizeof(USB_INTERFACE_DESCRIPTOR);
C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR) == sizeof(USB_ENDPOINT_DESCRIPTOR)); RtlCopyMemory(Buffer, &ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR));
RtlCopyMemory(Buffer, ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR));
// //
// done // done
@ -1498,7 +1525,7 @@ CHubController::HandleDeviceControl(
} }
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
{ {
DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n"); DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
if (IoStack->Parameters.Others.Argument1) if (IoStack->Parameters.Others.Argument1)
{ {
@ -2392,8 +2419,9 @@ USBHI_QueryDeviceInformation(
DeviceInfo->NumberOfOpenPipes = 0; //FIXME DeviceInfo->NumberOfOpenPipes = 0; //FIXME
// //
// FIXME get device descriptor // get device descriptor
// //
RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
// //
// FIXME return pipe information // FIXME return pipe information
@ -2402,7 +2430,7 @@ USBHI_QueryDeviceInformation(
// //
// store result length // store result length
// //
*LengthReturned = sizeof(USB_DEVICE_INFORMATION_0); *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
// //
// done // done
@ -2587,7 +2615,7 @@ USBHI_Initialize20Hub(
PUSB_DEVICE_HANDLE HubDeviceHandle, PUSB_DEVICE_HANDLE HubDeviceHandle,
ULONG TtCount) ULONG TtCount)
{ {
UNIMPLEMENTED DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle, TtCount);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2600,7 +2628,7 @@ USBHI_RootHubInitNotification(
{ {
CHubController * Controller; CHubController * Controller;
DPRINT1("USBHI_RootHubInitNotification\n"); DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
// //
// get controller object // get controller object

View file

@ -2,7 +2,7 @@
#define USBEHCI_H__ #define USBEHCI_H__
#include <ntddk.h> #include <ntddk.h>
#define NDEBUG #define YDEBUG
#include <debug.h> #include <debug.h>
#include <hubbusif.h> #include <hubbusif.h>
#include <usbbusif.h> #include <usbbusif.h>