mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 07:56:59 +00:00
[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 svn path=/branches/usb-bringup/; revision=51384
This commit is contained in:
parent
79bfd697d0
commit
5290479c41
3 changed files with 827 additions and 30 deletions
|
@ -54,6 +54,8 @@ public:
|
|||
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 @@ protected:
|
|||
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 @@ protected:
|
|||
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 @@ typedef struct
|
|||
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 @@ CHubController::Initialize(
|
|||
{
|
||||
NTSTATUS Status;
|
||||
PCOMMON_DEVICE_EXTENSION DeviceExtension;
|
||||
USHORT VendorID, DeviceID;
|
||||
ULONG Dummy1;
|
||||
|
||||
DPRINT1("CHubController::Initialize\n");
|
||||
|
||||
|
@ -120,6 +182,7 @@ CHubController::Initialize(
|
|||
m_DeviceAddress = DeviceAddress;
|
||||
m_DriverObject = DriverObject;
|
||||
KeInitializeSpinLock(&m_Lock);
|
||||
InitializeListHead(&m_UsbDeviceList);
|
||||
|
||||
//
|
||||
// allocate device address bitmap buffer
|
||||
|
@ -164,6 +227,22 @@ CHubController::Initialize(
|
|||
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
|
||||
//
|
||||
|
@ -510,6 +589,174 @@ CHubController::HandlePower(
|
|||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
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(
|
||||
|
@ -553,10 +800,17 @@ CHubController::HandleDeviceControl(
|
|||
|
||||
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 @@ CHubController::AddUsbDevice(
|
|||
PUSBDEVICE UsbDevice)
|
||||
{
|
||||
PUSBDEVICE_ENTRY DeviceEntry;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldLevel;
|
||||
|
||||
//
|
||||
|
@ -1004,7 +1257,7 @@ USBHI_CreateUsbDevice(
|
|||
//
|
||||
// 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 @@ USBHI_QueryDeviceInformation(
|
|||
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 @@ USBHI_QueryDeviceInformation(
|
|||
UsbDevice = (PUSBDEVICE)DeviceHandle;
|
||||
PC_ASSERT(UsbDevice);
|
||||
|
||||
//
|
||||
// validate device handle
|
||||
//
|
||||
if (!Controller->ValidateUsbDevice(UsbDevice))
|
||||
if (BusContext != DeviceHandle)
|
||||
{
|
||||
DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", 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;
|
||||
}
|
||||
|
||||
//
|
||||
// invalid device handle
|
||||
// access information buffer
|
||||
//
|
||||
return STATUS_DEVICE_NOT_CONNECTED;
|
||||
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 @@ USBHI_QueryDeviceInformation(
|
|||
//
|
||||
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
|
||||
// FIXME get device descriptor
|
||||
//
|
||||
UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
|
||||
|
||||
//
|
||||
// FIXME return pipe information
|
||||
|
@ -1427,6 +1715,9 @@ USBHI_QueryDeviceInformation(
|
|||
//
|
||||
*LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2077,12 +2368,7 @@ CHubController::CreatePDO(
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// store PDO number
|
||||
//
|
||||
//m_PDODeviceNumber = UsbDeviceNumber;
|
||||
|
||||
DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
|
||||
DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
|
|
|
@ -344,6 +344,8 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
|
|||
|
||||
};
|
||||
|
||||
typedef IUSBRequest *PUSBREQUEST;
|
||||
|
||||
//=========================================================================================
|
||||
//
|
||||
// class IUSBQueue
|
||||
|
@ -399,6 +401,8 @@ DECLARE_INTERFACE_(IUSBQueue, IUnknown)
|
|||
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0;
|
||||
};
|
||||
|
||||
typedef IUSBQueue *PUSBQUEUE;
|
||||
|
||||
//=========================================================================================
|
||||
//
|
||||
// class IHubController
|
||||
|
@ -495,7 +499,8 @@ DECLARE_INTERFACE_(IUSBDevice, IUnknown)
|
|||
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 @@ DECLARE_INTERFACE_(IUSBDevice, IUnknown)
|
|||
//
|
||||
// Description: gets current selected configuration index
|
||||
|
||||
virtual UCHAR GetConfigurationValue();
|
||||
virtual UCHAR GetConfigurationValue() = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
//
|
||||
|
|
|
@ -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
|
||||
CreateUSBDevice(
|
||||
PUSBDEVICE *OutDevice)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue