[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:
Johannes Anderwald 2011-04-17 19:23:13 +00:00
parent 79bfd697d0
commit 5290479c41
3 changed files with 827 additions and 30 deletions

View file

@ -54,6 +54,8 @@ public:
NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice); NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice);
NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice); NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice);
VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine); 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 // constructor / destructor
CHubController(IUnknown *OuterUnknown){} CHubController(IUnknown *OuterUnknown){}
@ -65,7 +67,6 @@ protected:
PUSBHARDWAREDEVICE m_Hardware; PUSBHARDWAREDEVICE m_Hardware;
BOOLEAN m_IsRootHubDevice; BOOLEAN m_IsRootHubDevice;
ULONG m_DeviceAddress; ULONG m_DeviceAddress;
ULONG m_PDODeviceNumber;
BOOLEAN m_InterfaceEnabled; BOOLEAN m_InterfaceEnabled;
UNICODE_STRING m_HubDeviceInterfaceString; UNICODE_STRING m_HubDeviceInterfaceString;
PDEVICE_OBJECT m_HubControllerDeviceObject; PDEVICE_OBJECT m_HubControllerDeviceObject;
@ -74,6 +75,7 @@ protected:
PVOID m_HubCallbackContext; PVOID m_HubCallbackContext;
PRH_INIT_CALLBACK m_HubCallbackRoutine; PRH_INIT_CALLBACK m_HubCallbackRoutine;
USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
KSPIN_LOCK m_Lock; KSPIN_LOCK m_Lock;
RTL_BITMAP m_DeviceAddressBitmap; RTL_BITMAP m_DeviceAddressBitmap;
@ -87,6 +89,64 @@ typedef struct
PUSBDEVICE Device; PUSBDEVICE Device;
}USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY; }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 NTSTATUS
@ -108,6 +168,8 @@ CHubController::Initialize(
{ {
NTSTATUS Status; NTSTATUS Status;
PCOMMON_DEVICE_EXTENSION DeviceExtension; PCOMMON_DEVICE_EXTENSION DeviceExtension;
USHORT VendorID, DeviceID;
ULONG Dummy1;
DPRINT1("CHubController::Initialize\n"); DPRINT1("CHubController::Initialize\n");
@ -120,6 +182,7 @@ CHubController::Initialize(
m_DeviceAddress = DeviceAddress; m_DeviceAddress = DeviceAddress;
m_DriverObject = DriverObject; m_DriverObject = DriverObject;
KeInitializeSpinLock(&m_Lock); KeInitializeSpinLock(&m_Lock);
InitializeListHead(&m_UsbDeviceList);
// //
// allocate device address bitmap buffer // allocate device address bitmap buffer
@ -164,6 +227,22 @@ CHubController::Initialize(
DeviceExtension->IsHub = TRUE; //FIXME DeviceExtension->IsHub = TRUE; //FIXME
DeviceExtension->Dispatcher = PDISPATCHIRP(this); 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 // clear init flag
// //
@ -510,6 +589,174 @@ CHubController::HandlePower(
return STATUS_NOT_IMPLEMENTED; 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 NTSTATUS
CHubController::HandleDeviceControl( 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); 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 // request completed
// //
Status = STATUS_NOT_IMPLEMENTED;
break; break;
} }
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
@ -854,7 +1108,6 @@ CHubController::AddUsbDevice(
PUSBDEVICE UsbDevice) PUSBDEVICE UsbDevice)
{ {
PUSBDEVICE_ENTRY DeviceEntry; PUSBDEVICE_ENTRY DeviceEntry;
NTSTATUS Status;
KIRQL OldLevel; KIRQL OldLevel;
// //
@ -1004,7 +1257,7 @@ USBHI_CreateUsbDevice(
// //
// now initialize device // 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 // check for success
@ -1359,9 +1612,8 @@ USBHI_QueryDeviceInformation(
PUSB_DEVICE_INFORMATION_0 DeviceInfo; PUSB_DEVICE_INFORMATION_0 DeviceInfo;
PUSBDEVICE UsbDevice; PUSBDEVICE UsbDevice;
CHubController * Controller; CHubController * Controller;
NTSTATUS Status;
DPRINT1("USBHI_QueryDeviceInformation\n"); DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
// //
// sanity check // sanity check
@ -1382,17 +1634,54 @@ USBHI_QueryDeviceInformation(
UsbDevice = (PUSBDEVICE)DeviceHandle; UsbDevice = (PUSBDEVICE)DeviceHandle;
PC_ASSERT(UsbDevice); PC_ASSERT(UsbDevice);
// if (BusContext != DeviceHandle)
// validate device handle
//
if (!Controller->ValidateUsbDevice(UsbDevice))
{ {
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->InformationLevel = 0;
DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0); DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
DeviceInfo->PortNumber = UsbDevice->GetPort(); DeviceInfo->PortNumber = 0;
DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue(); DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
DeviceInfo->DeviceAddress = 0; UsbDevice->GetDeviceAddress(); DeviceInfo->DeviceAddress = 0;
DeviceInfo->HubAddress = 0; //FIXME DeviceInfo->HubAddress = 0; //FIXME
DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed(); DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
DeviceInfo->DeviceType = UsbDevice->GetType(); DeviceInfo->DeviceType = Usb20Device; //FIXME
DeviceInfo->NumberOfOpenPipes = 0; //FIXME DeviceInfo->NumberOfOpenPipes = 0; //FIXME
// //
// get device descriptor // FIXME get device descriptor
// //
UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
// //
// FIXME return pipe information // FIXME return pipe information
@ -1427,6 +1715,9 @@ USBHI_QueryDeviceInformation(
// //
*LengthReturned = sizeof(USB_DEVICE_INFORMATION_0); *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
//
// done
//
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2077,12 +2368,7 @@ CHubController::CreatePDO(
} }
} }
// DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
// store PDO number
//
//m_PDODeviceNumber = UsbDeviceNumber;
DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
/* done */ /* done */
return Status; return Status;

View file

@ -344,6 +344,8 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
}; };
typedef IUSBRequest *PUSBREQUEST;
//========================================================================================= //=========================================================================================
// //
// class IUSBQueue // class IUSBQueue
@ -399,6 +401,8 @@ DECLARE_INTERFACE_(IUSBQueue, IUnknown)
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0; virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0;
}; };
typedef IUSBQueue *PUSBQUEUE;
//========================================================================================= //=========================================================================================
// //
// class IHubController // class IHubController
@ -495,7 +499,8 @@ DECLARE_INTERFACE_(IUSBDevice, IUnknown)
virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController,
IN PUSBHARDWAREDEVICE Device, IN PUSBHARDWAREDEVICE Device,
IN PVOID Parent, 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 // Description: gets current selected configuration index
virtual UCHAR GetConfigurationValue(); virtual UCHAR GetConfigurationValue() = 0;
//----------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------
// //

View file

@ -11,12 +11,518 @@
#define INITGUID #define INITGUID
#include "usbehci.h" #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 NTSTATUS
CreateUSBDevice( STDMETHODCALLTYPE
PUSBDEVICE *OutDevice) 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 UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED; 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;
}