mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[USB-BRINGUP]
- Implement retrieving device / configuration descriptor - Partly implement hid descriptor parsing - Select configuration when initialization is complete - Implement starting up device svn path=/branches/usb-bringup/; revision=54765
This commit is contained in:
parent
c626190319
commit
bf1f779fff
2 changed files with 460 additions and 17 deletions
|
@ -86,13 +86,13 @@ HidInternalDeviceControl(
|
|||
//
|
||||
// store result
|
||||
//
|
||||
ASSERT(HidDeviceExtension->HidDescriptor);
|
||||
ASSERT(HidDeviceExtension->DeviceDescriptor);
|
||||
Irp->IoStatus.Information = sizeof(HID_DESCRIPTOR);
|
||||
Attributes = (PHID_DEVICE_ATTRIBUTES)Irp->UserBuffer;
|
||||
Attributes->Size = sizeof(HID_DEVICE_ATTRIBUTES);
|
||||
Attributes->VendorID = HidDeviceExtension->VendorID;
|
||||
Attributes->ProductID = HidDeviceExtension->ProductID;
|
||||
Attributes->VersionNumber = HidDeviceExtension->VersionNumber;
|
||||
Attributes->VendorID = HidDeviceExtension->DeviceDescriptor->idVendor;
|
||||
Attributes->ProductID = HidDeviceExtension->DeviceDescriptor->idProduct;
|
||||
Attributes->VersionNumber = HidDeviceExtension->DeviceDescriptor->bcdDevice;
|
||||
|
||||
//
|
||||
// complete request
|
||||
|
@ -186,14 +186,6 @@ HidSystemControl(
|
|||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
Hid_PnpStart(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
Hid_PnpCompletion(
|
||||
|
@ -212,6 +204,437 @@ Hid_PnpCompletion(
|
|||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
Hid_DispatchUrb(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PURB Urb)
|
||||
{
|
||||
PIRP Irp;
|
||||
KEVENT Event;
|
||||
PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
|
||||
PHID_DEVICE_EXTENSION DeviceExtension;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// init event
|
||||
//
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
|
||||
|
||||
|
||||
//
|
||||
// build irp
|
||||
//
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, DeviceExtension->NextDeviceObject, NULL, 0, NULL, 0, TRUE, &Event, &IoStatus);
|
||||
if (!Irp)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// get next stack location
|
||||
//
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// store urb
|
||||
//
|
||||
IoStack->Parameters.Others.Argument1 = (PVOID)Urb;
|
||||
|
||||
//
|
||||
// set completion routine
|
||||
//
|
||||
IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
|
||||
|
||||
//
|
||||
// call driver
|
||||
//
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
|
||||
//
|
||||
// wait for the request to finish
|
||||
//
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatus.Status;
|
||||
}
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
Hid_GetDescriptor(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN USHORT UrbLength,
|
||||
IN OUT PVOID *UrbBuffer,
|
||||
IN OUT PULONG UrbBufferLength,
|
||||
IN UCHAR DescriptorType,
|
||||
IN UCHAR Index,
|
||||
IN USHORT LanguageIndex)
|
||||
{
|
||||
PURB Urb;
|
||||
NTSTATUS Status;
|
||||
UCHAR Allocated = FALSE;
|
||||
|
||||
//
|
||||
// allocate urb
|
||||
//
|
||||
Urb = (PURB)ExAllocatePool(NonPagedPool, UrbLength);
|
||||
if (!Urb)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// is there an urb buffer
|
||||
//
|
||||
if (!*UrbBuffer)
|
||||
{
|
||||
//
|
||||
// allocate buffer
|
||||
//
|
||||
*UrbBuffer = ExAllocatePool(NonPagedPool, *UrbBufferLength);
|
||||
if (!*UrbBuffer)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
ExFreePool(Urb);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// zero buffer
|
||||
//
|
||||
RtlZeroMemory(*UrbBuffer, *UrbBufferLength);
|
||||
Allocated = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// zero urb
|
||||
//
|
||||
RtlZeroMemory(Urb, UrbLength);
|
||||
|
||||
//
|
||||
// build descriptor request
|
||||
//
|
||||
UsbBuildGetDescriptorRequest(Urb, UrbLength, DescriptorType, Index, LanguageIndex, *UrbBuffer, NULL, *UrbBufferLength, NULL);
|
||||
|
||||
//
|
||||
// dispatch urb
|
||||
//
|
||||
Status = Hid_DispatchUrb(DeviceObject, Urb);
|
||||
|
||||
//
|
||||
// did the request fail
|
||||
//
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (Allocated)
|
||||
{
|
||||
//
|
||||
// free allocated buffer
|
||||
//
|
||||
ExFreePool(*UrbBuffer);
|
||||
*UrbBuffer = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// free urb
|
||||
//
|
||||
ExFreePool(Urb);
|
||||
*UrbBufferLength = 0;
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// did urb request fail
|
||||
//
|
||||
if (!NT_SUCCESS(Urb->UrbHeader.Status))
|
||||
{
|
||||
if (Allocated)
|
||||
{
|
||||
//
|
||||
// free allocated buffer
|
||||
//
|
||||
ExFreePool(*UrbBuffer);
|
||||
*UrbBuffer = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// free urb
|
||||
//
|
||||
ExFreePool(Urb);
|
||||
*UrbBufferLength = 0;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
//
|
||||
// store result length
|
||||
//
|
||||
*UrbBufferLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
|
||||
|
||||
//
|
||||
// free urb
|
||||
//
|
||||
ExFreePool(Urb);
|
||||
|
||||
//
|
||||
// completed successfully
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
Hid_SelectConfiguration(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
NTSTATUS Status;
|
||||
USBD_INTERFACE_LIST_ENTRY InterfaceList[2];
|
||||
PURB Urb;
|
||||
PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
|
||||
PHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
|
||||
|
||||
//
|
||||
// now parse the descriptors
|
||||
//
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(HidDeviceExtension->ConfigurationDescriptor,
|
||||
HidDeviceExtension->ConfigurationDescriptor,
|
||||
-1,
|
||||
-1,
|
||||
USB_DEVICE_CLASS_HUMAN_INTERFACE,
|
||||
-1,
|
||||
-1);
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(InterfaceDescriptor);
|
||||
ASSERT(InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_HUMAN_INTERFACE);
|
||||
ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
|
||||
ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
|
||||
|
||||
//
|
||||
// setup interface list
|
||||
//
|
||||
RtlZeroMemory(InterfaceList, sizeof(InterfaceList));
|
||||
InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor;
|
||||
|
||||
//
|
||||
// build urb
|
||||
//
|
||||
Urb = USBD_CreateConfigurationRequestEx(HidDeviceExtension->ConfigurationDescriptor, InterfaceList);
|
||||
if (!Urb)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// dispatch request
|
||||
//
|
||||
Status = Hid_DispatchUrb(DeviceObject, Urb);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// store configuration handle
|
||||
//
|
||||
HidDeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
|
||||
|
||||
//
|
||||
// copy interface info
|
||||
//
|
||||
HidDeviceExtension->InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)ExAllocatePool(NonPagedPool, Urb->UrbSelectConfiguration.Interface.Length);
|
||||
if (HidDeviceExtension->InterfaceInfo)
|
||||
{
|
||||
//
|
||||
// copy interface info
|
||||
//
|
||||
RtlCopyMemory(HidDeviceExtension->InterfaceInfo, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// free urb request
|
||||
//
|
||||
ExFreePool(Urb);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
Hid_PnpStart(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
|
||||
PHID_DEVICE_EXTENSION DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
ULONG DescriptorLength;
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
PHID_DESCRIPTOR HidDescriptor;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
|
||||
|
||||
//
|
||||
// get device descriptor
|
||||
//
|
||||
DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR);
|
||||
Status = Hid_GetDescriptor(DeviceObject, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), (PVOID*)&HidDeviceExtension->DeviceDescriptor, &DescriptorLength, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to obtain device descriptor
|
||||
//
|
||||
DPRINT1("Hid_PnpStart failed to get device descriptor %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// now get the configuration descriptor
|
||||
//
|
||||
DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
|
||||
Status = Hid_GetDescriptor(DeviceObject, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), (PVOID*)&HidDeviceExtension->ConfigurationDescriptor, &DescriptorLength, USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to obtain device descriptor
|
||||
//
|
||||
DPRINT1("Hid_PnpStart failed to get device descriptor %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(DescriptorLength);
|
||||
ASSERT(HidDeviceExtension->ConfigurationDescriptor);
|
||||
ASSERT(HidDeviceExtension->ConfigurationDescriptor->bLength);
|
||||
|
||||
//
|
||||
// store full length
|
||||
//
|
||||
DescriptorLength = HidDeviceExtension->ConfigurationDescriptor->wTotalLength;
|
||||
|
||||
//
|
||||
// delete partial configuration descriptor
|
||||
//
|
||||
ExFreePool(HidDeviceExtension->ConfigurationDescriptor);
|
||||
HidDeviceExtension->ConfigurationDescriptor = NULL;
|
||||
|
||||
//
|
||||
// get full configuration descriptor
|
||||
//
|
||||
Status = Hid_GetDescriptor(DeviceObject, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), (PVOID*)&HidDeviceExtension->ConfigurationDescriptor, &DescriptorLength, USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to obtain device descriptor
|
||||
//
|
||||
DPRINT1("Hid_PnpStart failed to get device descriptor %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// now parse the descriptors
|
||||
//
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(HidDeviceExtension->ConfigurationDescriptor,
|
||||
HidDeviceExtension->ConfigurationDescriptor,
|
||||
-1,
|
||||
-1,
|
||||
USB_DEVICE_CLASS_HUMAN_INTERFACE,
|
||||
-1,
|
||||
-1);
|
||||
if (!InterfaceDescriptor)
|
||||
{
|
||||
//
|
||||
// no interface class
|
||||
//
|
||||
DPRINT1("NO HID Class found\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_HUMAN_INTERFACE);
|
||||
ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
|
||||
ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
|
||||
|
||||
//
|
||||
// move to next descriptor
|
||||
//
|
||||
HidDescriptor = (PHID_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
ASSERT(HidDescriptor->bLength >= 2);
|
||||
|
||||
//
|
||||
// check if this is the hid descriptor
|
||||
//
|
||||
if (HidDescriptor->bLength == sizeof(HID_DESCRIPTOR) && HidDescriptor->bDescriptorType == HID_HID_DESCRIPTOR_TYPE)
|
||||
{
|
||||
//
|
||||
// found
|
||||
//
|
||||
HidDeviceExtension->HidDescriptor = HidDescriptor;
|
||||
|
||||
//
|
||||
// select configuration
|
||||
//
|
||||
Status = Hid_SelectConfiguration(DeviceObject);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// FIXME parse hid descriptor
|
||||
//
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidPnp(
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
#include <ntddk.h>
|
||||
#include <hidport.h>
|
||||
#include <debug.h>
|
||||
#include <hubbusif.h>
|
||||
#include <usbbusif.h>
|
||||
#include <usbioctl.h>
|
||||
#include <usb.h>
|
||||
#include <usbdlib.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -18,14 +23,29 @@ typedef struct
|
|||
//
|
||||
LIST_ENTRY PendingRequests;
|
||||
|
||||
//
|
||||
// device descriptor
|
||||
//
|
||||
PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||
|
||||
//
|
||||
// configuration descriptor
|
||||
//
|
||||
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
||||
|
||||
//
|
||||
// interface information
|
||||
//
|
||||
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
|
||||
|
||||
//
|
||||
// configuration handle
|
||||
//
|
||||
USBD_CONFIGURATION_HANDLE ConfigurationHandle;
|
||||
|
||||
//
|
||||
// hid descriptor
|
||||
//
|
||||
PHID_DESCRIPTOR HidDescriptor;
|
||||
|
||||
USHORT VendorID;
|
||||
USHORT ProductID;
|
||||
USHORT VersionNumber;
|
||||
|
||||
}HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
|
||||
|
||||
|
|
Loading…
Reference in a new issue