Author: janderwald Date: Sun Apr 17 19:23:13 2011 New Revision: 51384
URL: http://svn.reactos.org/svn/reactos?rev=51384&view=rev Log: [USBEHCI_NEW] - Setup a default device descriptor for the root hub and initialize it with vendor & product id - Partly implement URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, URB_FUNCTION_CLASS_DEVICE - based on mjmartin usbehci
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp [iso-8859-1] Sun Apr 17 19:23:13 2011 @@ -54,6 +54,8 @@ NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice); NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice); VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine); + NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb); + NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
// constructor / destructor CHubController(IUnknown *OuterUnknown){} @@ -65,7 +67,6 @@ PUSBHARDWAREDEVICE m_Hardware; BOOLEAN m_IsRootHubDevice; ULONG m_DeviceAddress; - ULONG m_PDODeviceNumber; BOOLEAN m_InterfaceEnabled; UNICODE_STRING m_HubDeviceInterfaceString; PDEVICE_OBJECT m_HubControllerDeviceObject; @@ -74,6 +75,7 @@ PVOID m_HubCallbackContext; PRH_INIT_CALLBACK m_HubCallbackRoutine;
+ USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
KSPIN_LOCK m_Lock; RTL_BITMAP m_DeviceAddressBitmap; @@ -87,6 +89,64 @@ PUSBDEVICE Device; }USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY;
+/* Lifted from Linux with slight changes */ +const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] = +{ + 0x12, /* bLength; */ + USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */ + 0x00, 0x20, /* bcdUSB; v1.1 */ + USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */ + 0x01, /* bDeviceSubClass; */ + 0x00, /* bDeviceProtocol; [ low/full speeds only ] */ + 0x08, /* bMaxPacketSize0; 8 Bytes */ + /* Fill Vendor and Product in when init root hub */ + 0x00, 0x00, /* idVendor; */ + 0x00, 0x00, /* idProduct; */ + 0x00, 0x00, /* bcdDevice */ + 0x00, /* iManufacturer; */ + 0x00, /* iProduct; */ + 0x00, /* iSerialNumber; */ + 0x01 /* bNumConfigurations; */ + +}; + +const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] = +{ + /* one configuration */ + 0x09, /* bLength; */ + 0x02, /* bDescriptorType; Configuration */ + 0x19, 0x00, /* wTotalLength; */ + 0x01, /* bNumInterfaces; (1) */ + 0x23, /* bConfigurationValue; */ + 0x00, /* iConfiguration; */ + 0x40, /* bmAttributes; */ + 0x00 /* MaxPower; */ +}; + +const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] = +{ + /* one interface */ + 0x09, /* bLength: Interface; */ + 0x04, /* bDescriptorType; Interface */ + 0x00, /* bInterfaceNumber; */ + 0x00, /* bAlternateSetting; */ + 0x01, /* bNumEndpoints; */ + 0x09, /* bInterfaceClass; HUB_CLASSCODE */ + 0x01, /* bInterfaceSubClass; */ + 0x00, /* bInterfaceProtocol: */ + 0x00 /* iInterface; */ +}; + +const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] = +{ + /* one endpoint (status change endpoint) */ + 0x07, /* bLength; */ + 0x05, /* bDescriptorType; Endpoint */ + 0x81, /* bEndpointAddress; IN Endpoint 1 */ + 0x03, /* bmAttributes; Interrupt */ + 0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ + 0xFF /* bInterval; (255ms -- usb 2.0 spec) */ +};
//---------------------------------------------------------------------------------------- NTSTATUS @@ -108,6 +168,8 @@ { NTSTATUS Status; PCOMMON_DEVICE_EXTENSION DeviceExtension; + USHORT VendorID, DeviceID; + ULONG Dummy1;
DPRINT1("CHubController::Initialize\n");
@@ -120,6 +182,7 @@ m_DeviceAddress = DeviceAddress; m_DriverObject = DriverObject; KeInitializeSpinLock(&m_Lock); + InitializeListHead(&m_UsbDeviceList);
// // allocate device address bitmap buffer @@ -163,6 +226,22 @@ DeviceExtension->IsFDO = FALSE; DeviceExtension->IsHub = TRUE; //FIXME DeviceExtension->Dispatcher = PDISPATCHIRP(this); + + // + // intialize device descriptor + // + C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR)); + RtlMoveMemory(&m_DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR)); + + if (NT_SUCCESS(m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &Dummy1, &Dummy1))) + { + // + // update device descriptor + // + m_DeviceDescriptor.idVendor = VendorID; + m_DeviceDescriptor.idProduct = DeviceID; + m_DeviceDescriptor.bcdUSB = 0x200; //FIXME + }
// // clear init flag @@ -512,6 +591,174 @@
//----------------------------------------------------------------------------------------- NTSTATUS +CHubController::HandleClassDevice( + IN OUT PIRP Irp, + IN OUT PURB Urb) +{ + NTSTATUS Status = STATUS_NOT_IMPLEMENTED; + PUSB_HUB_DESCRIPTOR UsbHubDescriptor; + ULONG PortCount, Dummy2; + USHORT Dummy1; + + // + // check class request type + // + switch(Urb->UrbControlVendorClassRequest.Request) + { + case USB_DEVICE_CLASS_HUB: + { + // + // sanity checks + // + PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer); + PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR)); + + // + // get hub descriptor + // + UsbHubDescriptor = (PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer; + + // + // one hub is handled + // + UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR); + Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR); + + // + // type should 0x29 according to msdn + // + UsbHubDescriptor->bDescriptorType = 0x29; + + // + // get port count + // + Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &PortCount, &Dummy2); + PC_ASSERT(Status == STATUS_SUCCESS); + + // + // FIXME: retrieve values + // + UsbHubDescriptor->bNumberOfPorts = PortCount; + UsbHubDescriptor->wHubCharacteristics = 0x0012; + UsbHubDescriptor->bPowerOnToPowerGood = 0x01; + UsbHubDescriptor->bHubControlCurrent = 0x00; + + // + // done + // + Status = STATUS_SUCCESS; + break; + } + default: + DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb->UrbControlVendorClassRequest.Request); + break; + } + + return Status; +} +//----------------------------------------------------------------------------------------- +NTSTATUS +CHubController::HandleGetDescriptor( + IN OUT PIRP Irp, + IN OUT PURB Urb) +{ + NTSTATUS Status = STATUS_NOT_IMPLEMENTED; + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; + PUCHAR Buffer; + + // + // check descriptor type + // + switch(Urb->UrbControlDescriptorRequest.DescriptorType) + { + case USB_DEVICE_DESCRIPTOR_TYPE: + { + // + // sanity check + // + PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR)); + + if (Urb->UrbHeader.UsbdDeviceHandle == NULL) + { + DPRINT1("Root Hub descriptor\n"); + // + // copy root hub device descriptor + // + RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); + Status = STATUS_SUCCESS; + break; + } + break; + } + case USB_CONFIGURATION_DESCRIPTOR_TYPE: + { + // + // sanity checks + // + PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); + PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR)); + + // + // FIXME: support devices + // + PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL); + + // + // copy configuration descriptor template + // + C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR) == sizeof(USB_CONFIGURATION_DESCRIPTOR)); + RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR)); + + // + // get configuration descriptor, very retarded! + // + ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer; + + // + // check if buffer can hold interface and endpoint descriptor + // + if (ConfigurationDescriptor->wTotalLength > Urb->UrbControlDescriptorRequest.TransferBufferLength) + { + // + // buffer too small + // + Status = STATUS_SUCCESS; + break; + } + + // + // copy interface descriptor template + // + Buffer = (PUCHAR)(ConfigurationDescriptor + 1); + C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR) == sizeof(USB_INTERFACE_DESCRIPTOR)); + RtlCopyMemory(Buffer, ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR)); + + // + // copy end point descriptor template + // + Buffer += sizeof(USB_INTERFACE_DESCRIPTOR); + C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR) == sizeof(USB_ENDPOINT_DESCRIPTOR)); + RtlCopyMemory(Buffer, ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR)); + + // + // done + // + Status = STATUS_SUCCESS; + break; + } + default: + DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb->UrbControlDescriptorRequest.DescriptorType); + break; + } + + // + // done + // + return Status; +} + +//----------------------------------------------------------------------------------------- +NTSTATUS CHubController::HandleDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp) @@ -553,10 +800,17 @@
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x Length %lu Status %x Handle %p Flags %x UNIMPLEMENTED\n", Urb->UrbHeader.Function, Urb->UrbHeader.Length, Urb->UrbHeader.Status, Urb->UrbHeader.UsbdDeviceHandle, Urb->UrbHeader.UsbdFlags);
+ switch (Urb->UrbHeader.Function) + { + case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: + Status = HandleGetDescriptor(Irp, Urb); + break; + case URB_FUNCTION_CLASS_DEVICE: + Status = HandleClassDevice(Irp, Urb); + } // // request completed // - Status = STATUS_NOT_IMPLEMENTED; break; } case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: @@ -854,7 +1108,6 @@ PUSBDEVICE UsbDevice) { PUSBDEVICE_ENTRY DeviceEntry; - NTSTATUS Status; KIRQL OldLevel;
// @@ -1004,7 +1257,7 @@ // // now initialize device // - Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber); + Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
// // check for success @@ -1359,9 +1612,8 @@ PUSB_DEVICE_INFORMATION_0 DeviceInfo; PUSBDEVICE UsbDevice; CHubController * Controller; - NTSTATUS Status; - - DPRINT1("USBHI_QueryDeviceInformation\n"); + + DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
// // sanity check @@ -1382,17 +1634,54 @@ UsbDevice = (PUSBDEVICE)DeviceHandle; PC_ASSERT(UsbDevice);
- // - // validate device handle - // - if (!Controller->ValidateUsbDevice(UsbDevice)) - { - DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; + if (BusContext != DeviceHandle) + { + // + // validate device handle + // + if (!Controller->ValidateUsbDevice(UsbDevice)) + { + DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle); + + // + // invalid device handle + // + return STATUS_DEVICE_NOT_CONNECTED; + } + + // + // access information buffer + // + DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer; + + // + // initialize with default values + // + DeviceInfo->InformationLevel = 0; + DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0); + DeviceInfo->PortNumber = UsbDevice->GetPort(); + DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue(); + DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress(); + DeviceInfo->HubAddress = 0; //FIXME + DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed(); + DeviceInfo->DeviceType = UsbDevice->GetType(); + DeviceInfo->NumberOfOpenPipes = 0; //FIXME + + // + // get device descriptor + // + UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor); + + // + // FIXME return pipe information + // + + // + // store result length + // + *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0); + + return STATUS_SUCCESS; }
// @@ -1405,18 +1694,17 @@ // DeviceInfo->InformationLevel = 0; DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0); - DeviceInfo->PortNumber = UsbDevice->GetPort(); - DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue(); - DeviceInfo->DeviceAddress = 0; UsbDevice->GetDeviceAddress(); + DeviceInfo->PortNumber = 0; + DeviceInfo->CurrentConfigurationValue = 0; //FIXME; + DeviceInfo->DeviceAddress = 0; DeviceInfo->HubAddress = 0; //FIXME - DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed(); - DeviceInfo->DeviceType = UsbDevice->GetType(); + DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME + DeviceInfo->DeviceType = Usb20Device; //FIXME DeviceInfo->NumberOfOpenPipes = 0; //FIXME
// - // get device descriptor - // - UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor); + // FIXME get device descriptor + //
// // FIXME return pipe information @@ -1427,6 +1715,9 @@ // *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
+ // + // done + // return STATUS_SUCCESS; }
@@ -2077,12 +2368,7 @@ } }
- // - // store PDO number - // - //m_PDODeviceNumber = UsbDeviceNumber; - - DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName); + DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
/* done */ return Status;
Modified: branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] Sun Apr 17 19:23:13 2011 @@ -344,6 +344,8 @@
};
+typedef IUSBRequest *PUSBREQUEST; + //========================================================================================= // // class IUSBQueue @@ -398,6 +400,8 @@
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0; }; + +typedef IUSBQueue *PUSBQUEUE;
//========================================================================================= // @@ -495,7 +499,8 @@ virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, IN PUSBHARDWAREDEVICE Device, IN PVOID Parent, - IN ULONG Port) = 0; + IN ULONG Port, + IN ULONG PortStatus) = 0;
//----------------------------------------------------------------------------------------- // @@ -584,7 +589,7 @@ // // Description: gets current selected configuration index
- virtual UCHAR GetConfigurationValue(); + virtual UCHAR GetConfigurationValue() = 0;
//----------------------------------------------------------------------------------------- //
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp [iso-8859-1] Sun Apr 17 19:23:13 2011 @@ -11,12 +11,518 @@ #define INITGUID #include "usbehci.h"
- +class CUSBDevice : public IUSBDevice +{ +public: + STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); + + STDMETHODIMP_(ULONG) AddRef() + { + InterlockedIncrement(&m_Ref); + return m_Ref; + } + STDMETHODIMP_(ULONG) Release() + { + InterlockedDecrement(&m_Ref); + + if (!m_Ref) + { + delete this; + return 0; + } + return m_Ref; + } + + // IUSBDevice interface functions + virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, IN PUSBHARDWAREDEVICE Device, IN PVOID Parent, IN ULONG Port, IN ULONG PortStatus); + virtual BOOLEAN IsHub(); + virtual NTSTATUS GetParent(PVOID * Parent); + virtual ULONG GetDeviceAddress(); + virtual ULONG GetPort(); + virtual USB_DEVICE_SPEED GetSpeed(); + virtual USB_DEVICE_TYPE GetType(); + virtual ULONG GetState(); + virtual void SetDeviceHandleData(PVOID Data); + virtual NTSTATUS SetDeviceAddress(ULONG DeviceAddress); + virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor); + virtual UCHAR GetConfigurationValue(); + virtual NTSTATUS SubmitUrb(PURB Urb); + + // local function + virtual NTSTATUS CommitUrb(PURB Urb); + virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN ULONG BufferLength, IN OUT PVOID Buffer, IN OPTIONAL PIRP Irp, IN OPTIONAL PKEVENT pEvent); + + // constructor / destructor + CUSBDevice(IUnknown *OuterUnknown){} + virtual ~CUSBDevice(){} + +protected: + LONG m_Ref; + PHUBCONTROLLER m_HubController; + PUSBHARDWAREDEVICE m_Device; + PVOID m_Parent; + ULONG m_Port; + ULONG m_DeviceAddress; + PVOID m_Data; + KSPIN_LOCK m_Lock; + USB_DEVICE_DESCRIPTOR m_DeviceDescriptor; + ULONG m_PortStatus; + PUSBQUEUE m_Queue; +}; + +//---------------------------------------------------------------------------------------- +NTSTATUS +STDMETHODCALLTYPE +CUSBDevice::QueryInterface( + IN REFIID refiid, + OUT PVOID* Output) +{ + return STATUS_UNSUCCESSFUL; +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::Initialize( + IN PHUBCONTROLLER HubController, + IN PUSBHARDWAREDEVICE Device, + IN PVOID Parent, + IN ULONG Port, + IN ULONG PortStatus) +{ + NTSTATUS Status; + USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + + // + // initialize members + // + m_HubController = HubController; + m_Device = Device; + m_Parent = Parent; + m_Port = Port; + m_PortStatus = PortStatus; + + // + // initialize device lock + // + KeInitializeSpinLock(&m_Lock); + + // + // no device address has been set yet + // + m_DeviceAddress = 0; + + // + // get usb request queue + // + Status = m_Device->GetUSBQueue(&m_Queue); + if (!NT_SUCCESS(Status)) + { + // + // failed to get usb queue + // + DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n", Status); + return Status; + } + + // + // zero descriptor + // + RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); + RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); + + // + // setup request + // + CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR; + CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE; + CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR); + CtrlSetup.bmRequestType.B = 0x80; + + // + // commit setup packet + // + Status = CommitSetupPacket(&CtrlSetup, sizeof(USB_DEVICE_DESCRIPTOR), &m_DeviceDescriptor, 0, 0); + + // + // check for success + // + if (!NT_SUCCESS(Status)) + { + DPRINT1("CUSBDevice::Initialize CommitSetupPacket failed with %x\n", Status); + } + + // + // done + // + return Status; +} + +//---------------------------------------------------------------------------------------- +BOOLEAN +CUSBDevice::IsHub() +{ + // + // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h + // for details + // + return (m_DeviceDescriptor.bDeviceClass == 0x09 && m_DeviceDescriptor.bDeviceSubClass == 0x00); +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::GetParent( + PVOID * Parent) +{ + // + // returns parent + // + *Parent = m_Parent; + + // + // done + // + return STATUS_SUCCESS; +} + +//---------------------------------------------------------------------------------------- +ULONG +CUSBDevice::GetDeviceAddress() +{ + // + // get device address + // + return m_DeviceAddress; +} + +//---------------------------------------------------------------------------------------- +ULONG +CUSBDevice::GetPort() +{ + // + // get port to which this device is connected to + // + return m_Port; +} + +//---------------------------------------------------------------------------------------- +USB_DEVICE_SPEED +CUSBDevice::GetSpeed() +{ + if (m_PortStatus & USB_PORT_STATUS_LOW_SPEED) + { + // + // low speed device + // + return UsbLowSpeed; + } + else if (m_PortStatus & USB_PORT_STATUS_HIGH_SPEED) + { + // + // high speed device + // + return UsbHighSpeed; + } + + // + // default to full speed + // + return UsbFullSpeed; +} + +//---------------------------------------------------------------------------------------- +USB_DEVICE_TYPE +CUSBDevice::GetType() +{ + // + // device is encoded into bcdUSB + // + if (m_DeviceDescriptor.bcdUSB == 0x110) + { + // + // USB 1.1 device + // + return Usb11Device; + } + else if (m_DeviceDescriptor.bcdUSB == 0x200) + { + // + // USB 2.0 device + // + return Usb20Device; + } + + DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n", m_DeviceDescriptor.bcdUSB); + PC_ASSERT(FALSE); + + return Usb11Device; +} + +//---------------------------------------------------------------------------------------- +ULONG +CUSBDevice::GetState() +{ + UNIMPLEMENTED + return FALSE; +} + +//---------------------------------------------------------------------------------------- +void +CUSBDevice::SetDeviceHandleData( + PVOID Data) +{ + // + // set device data, for debugging issues + // + m_Data = Data; +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::SetDeviceAddress( + ULONG DeviceAddress) +{ + USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + NTSTATUS Status; + + // + // zero request + // + RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); + + // + // initialize request + // + CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS; + CtrlSetup.wValue.W = DeviceAddress; + + // + // set device address + // + Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0, 0); + + // + // check for success + // + if (!NT_SUCCESS(Status)) + { + // + // failed to set device address + // + DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with %x Address %x\n", Status, DeviceAddress); + return Status; + } + + // + // store device address + // + m_DeviceAddress = DeviceAddress; + + // + // done + // + return STATUS_SUCCESS; +} + +//---------------------------------------------------------------------------------------- +void +CUSBDevice::GetDeviceDescriptor( + PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) +{ + RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); +} + +//---------------------------------------------------------------------------------------- +UCHAR +CUSBDevice::GetConfigurationValue() +{ + UNIMPLEMENTED + return 0x1; +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::CommitUrb( + PURB Urb) +{ + UNIMPLEMENTED + return STATUS_NOT_IMPLEMENTED; +} + +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::SubmitUrb( + PURB Urb) +{ + KIRQL OldLevel; + NTSTATUS Status; + + // + // acquire device lock + // + KeAcquireSpinLock(&m_Lock, &OldLevel); + + // + // commit urb + // + Status = CommitUrb(Urb); + + // + // release lock + // + KeReleaseSpinLock(&m_Lock, OldLevel); + + return Status; +} +//---------------------------------------------------------------------------------------- +NTSTATUS +CUSBDevice::CommitSetupPacket( + PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, + IN ULONG BufferLength, + IN OUT PVOID Buffer, + IN PIRP Irp, + IN PKEVENT pEvent) +{ + NTSTATUS Status; + PUSBREQUEST Request; + KEVENT Event; + BOOLEAN Wait = FALSE; + + if (!m_Queue) + { + // + // no queue, wtf? + // + DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n"); + return STATUS_UNSUCCESSFUL; + } + + // + // build usb request + // + Status = m_Queue->CreateUSBRequest(&Request); + if (!NT_SUCCESS(Status)) + { + // + // failed to build request + // + DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with %x\n", Status); + return Status; + } + + // + // initialize request + // + Status = Request->InitializeWithSetupPacket(Packet, BufferLength, Buffer); + if (!NT_SUCCESS(Status)) + { + // + // failed to initialize request + // + DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request with %x\n", Status); + Request->Release(); + return Status; + } + + // + // is a irp or event provided ? + // + if (Irp == NULL && pEvent == NULL) + { + // + // no completion details provided, requestor wants synchronized + // + KeInitializeEvent(&Event, NotificationEvent, FALSE); + pEvent = &Event; + Wait = TRUE; + } + + // + // set completion details + // + Status = Request->SetCompletionDetails(Irp, pEvent); + if (!NT_SUCCESS(Status)) + { + // + // failed to set completion details + // + DPRINT1("CUSBDevice::CommitSetupPacket> failed to set completion details with %x\n", Status); + Request->Release(); + return Status; + } + + // + // now add the request + // + Status = m_Queue->AddUSBRequest(Request); + if (!NT_SUCCESS(Status)) + { + // + // failed to add request + // + DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with %x\n", Status); + Request->Release(); + return Status; + } + + if (Wait) + { + // + // wait for the operation to complete + // + KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, NULL); + } + + //TODO: + // Get result code from operation + // + + // + // returns the result code when the operation has been finished + // + //Status = Request->GetResultCode(); + + // + // release request + // + Request->Release(); + + // + // done + // + return Status; +} +//---------------------------------------------------------------------------------------- NTSTATUS CreateUSBDevice( PUSBDEVICE *OutDevice) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; -} - + CUSBDevice * This; + + // + // allocate controller + // + This = new(NonPagedPool, TAG_USBEHCI) CUSBDevice(0); + if (!This) + { + // + // failed to allocate + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // add reference count + // + This->AddRef(); + + // + // return result + // + *OutDevice = (PUSBDEVICE)This; + + // + // done + // + return STATUS_SUCCESS; +} +