xref: /reactos/drivers/hid/hidusb/hidusb.c (revision 1734f297)
1 /*
2  * PROJECT:     ReactOS Universal Serial Bus Human Interface Device Driver
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        drivers/usb/hidusb/hidusb.c
5  * PURPOSE:     HID USB Interface Driver
6  * PROGRAMMERS:
7  *              Michael Martin (michael.martin@reactos.org)
8  *              Johannes Anderwald (johannes.anderwald@reactos.org)
9  */
10 
11 #include "hidusb.h"
12 
13 PUSBD_PIPE_INFORMATION
14 HidUsb_GetInputInterruptInterfaceHandle(
15     PUSBD_INTERFACE_INFORMATION InterfaceInformation)
16 {
17     ULONG Index;
18 
19     //
20     // sanity check
21     //
22     ASSERT(InterfaceInformation->NumberOfPipes);
23 
24     for (Index = 0; Index < InterfaceInformation->NumberOfPipes; Index++)
25     {
26         //DPRINT1("[HIDUSB] EndpointAddress %x PipeType %x PipeHandle %x\n", InterfaceInformation->Pipes[Index].EndpointAddress, InterfaceInformation->Pipes[Index].PipeType, InterfaceInformation->Pipes[Index].PipeHandle);
27         if (InterfaceInformation->Pipes[Index].PipeType == UsbdPipeTypeInterrupt && (InterfaceInformation->Pipes[Index].EndpointAddress & USB_ENDPOINT_DIRECTION_MASK))
28         {
29             //
30             // found handle
31             //
32             return &InterfaceInformation->Pipes[Index];
33         }
34     }
35 
36     //
37     // not found
38     //
39     return NULL;
40 }
41 
42 NTSTATUS
43 HidUsb_GetPortStatus(
44     IN PDEVICE_OBJECT DeviceObject,
45     IN PULONG PortStatus)
46 {
47     PIRP Irp;
48     KEVENT Event;
49     IO_STATUS_BLOCK IoStatus;
50     PHID_DEVICE_EXTENSION DeviceExtension;
51     PIO_STACK_LOCATION IoStack;
52     NTSTATUS Status;
53 
54     //
55     // get device extension
56     //
57     DeviceExtension = DeviceObject->DeviceExtension;
58 
59     //
60     // init result
61     //
62     *PortStatus = 0;
63 
64     //
65     // init event
66     //
67     KeInitializeEvent(&Event, NotificationEvent, FALSE);
68 
69     //
70     // build irp
71     //
72     Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_PORT_STATUS,
73                                         DeviceExtension->NextDeviceObject,
74                                         NULL,
75                                         0,
76                                         NULL,
77                                         0,
78                                         TRUE,
79                                         &Event,
80                                         &IoStatus);
81     if (!Irp)
82     {
83         //
84         // no memory
85         //
86         return STATUS_INSUFFICIENT_RESOURCES;
87     }
88 
89     //
90     // get stack location
91     //
92     IoStack = IoGetNextIrpStackLocation(Irp);
93 
94     //
95     // store result buffer
96     //
97     IoStack->Parameters.Others.Argument1 = PortStatus;
98 
99     //
100     // call driver
101     //
102     Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
103     if (Status == STATUS_PENDING)
104     {
105         //
106         // wait for completion
107         //
108         KeWaitForSingleObject(&Event, Executive, KernelMode, 0, NULL);
109         return IoStatus.Status;
110     }
111 
112     //
113     // done
114     //
115     return Status;
116 }
117 
118 NTSTATUS
119 HidUsb_ResetInterruptPipe(
120     IN PDEVICE_OBJECT DeviceObject)
121 {
122     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
123     PHID_DEVICE_EXTENSION DeviceExtension;
124     PUSBD_PIPE_INFORMATION PipeInformation;
125     PURB Urb;
126     NTSTATUS Status;
127 
128     //
129     // get device extension
130     //
131     DeviceExtension = DeviceObject->DeviceExtension;
132     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
133 
134     //
135     // get interrupt pipe handle
136     //
137     ASSERT(HidDeviceExtension->InterfaceInfo);
138     PipeInformation = HidUsb_GetInputInterruptInterfaceHandle(HidDeviceExtension->InterfaceInfo);
139     ASSERT(PipeInformation);
140     ASSERT(PipeInformation->PipeHandle);
141 
142     //
143     // allocate urb
144     //
145     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST), HIDUSB_URB_TAG);
146     if (!Urb)
147     {
148         //
149         // no memory
150         //
151         return STATUS_INSUFFICIENT_RESOURCES;
152     }
153 
154     //
155     // init urb
156     //
157     RtlZeroMemory(Urb, sizeof(struct _URB_PIPE_REQUEST));
158     Urb->UrbHeader.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL;
159     Urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
160     Urb->UrbPipeRequest.PipeHandle = PipeInformation->PipeHandle;
161 
162     //
163     // dispatch request
164     //
165     Status = Hid_DispatchUrb(DeviceObject, Urb);
166 
167     //
168     // free urb
169     //
170     ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
171 
172     //
173     // done
174     //
175     return Status;
176 }
177 
178 NTSTATUS
179 HidUsb_AbortPipe(
180     IN PDEVICE_OBJECT DeviceObject)
181 {
182     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
183     PHID_DEVICE_EXTENSION DeviceExtension;
184     PURB Urb;
185     NTSTATUS Status;
186     PUSBD_PIPE_INFORMATION PipeInformation;
187 
188     //
189     // get device extension
190     //
191     DeviceExtension = DeviceObject->DeviceExtension;
192     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
193 
194     //
195     // allocate urb
196     //
197     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST), HIDUSB_URB_TAG);
198     if (!Urb)
199     {
200         //
201         // no memory
202         //
203         return STATUS_INSUFFICIENT_RESOURCES;
204     }
205 
206     //
207     // get pipe information
208     //
209     PipeInformation = HidUsb_GetInputInterruptInterfaceHandle(HidDeviceExtension->InterfaceInfo);
210     ASSERT(PipeInformation);
211     ASSERT(PipeInformation->PipeHandle);
212 
213     //
214     // init urb
215     //
216     RtlZeroMemory(Urb, sizeof(struct _URB_PIPE_REQUEST));
217     Urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
218     Urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
219     Urb->UrbPipeRequest.PipeHandle = PipeInformation->PipeHandle;
220 
221     //
222     // dispatch request
223     //
224     Status = Hid_DispatchUrb(DeviceObject, Urb);
225 
226     //
227     // free urb
228     //
229     ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
230 
231     //
232     // done
233     //
234     return Status;
235 }
236 
237 NTSTATUS
238 HidUsb_ResetPort(
239     IN PDEVICE_OBJECT DeviceObject)
240 {
241     KEVENT Event;
242     PIRP Irp;
243     PHID_DEVICE_EXTENSION DeviceExtension;
244     IO_STATUS_BLOCK IoStatusBlock;
245     NTSTATUS Status;
246 
247     //
248     // get device extension
249     //
250     DeviceExtension = DeviceObject->DeviceExtension;
251 
252     //
253     // init event
254     //
255     KeInitializeEvent(&Event, NotificationEvent, FALSE);
256 
257     //
258     // build irp
259     //
260     Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_RESET_PORT,
261                                         DeviceExtension->NextDeviceObject,
262                                         NULL,
263                                         0,
264                                         NULL,
265                                         0,
266                                         TRUE,
267                                         &Event,
268                                         &IoStatusBlock);
269     if (!Irp)
270     {
271         //
272         // no memory
273         //
274         return STATUS_INSUFFICIENT_RESOURCES;
275     }
276 
277     //
278     // send the irp
279     //
280     Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
281     if (Status == STATUS_PENDING)
282     {
283         //
284         // wait for request completion
285         //
286         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
287         Status = IoStatusBlock.Status;
288     }
289 
290     //
291     // done
292     //
293     return IoStatusBlock.Status;
294 }
295 
296 NTSTATUS
297 NTAPI
298 HidCreate(
299     IN PDEVICE_OBJECT DeviceObject,
300     IN PIRP Irp)
301 {
302     PIO_STACK_LOCATION IoStack;
303 
304     //
305     // get current irp stack location
306     //
307     IoStack = IoGetCurrentIrpStackLocation(Irp);
308 
309     //
310     // sanity check for hidclass driver
311     //
312     ASSERT(IoStack->MajorFunction == IRP_MJ_CREATE || IoStack->MajorFunction == IRP_MJ_CLOSE);
313 
314     //
315     // informational debug print
316     //
317     DPRINT("HIDUSB Request: %x\n", IoStack->MajorFunction);
318 
319     //
320     // complete request
321     //
322     Irp->IoStatus.Information = 0;
323     Irp->IoStatus.Status = STATUS_SUCCESS;
324     IoCompleteRequest(Irp, IO_NO_INCREMENT);
325 
326     //
327     // done
328     //
329     return STATUS_SUCCESS;
330 }
331 
332 VOID
333 NTAPI
334 HidUsb_ResetWorkerRoutine(
335     IN PDEVICE_OBJECT DeviceObject,
336     IN PVOID Ctx)
337 {
338     NTSTATUS Status;
339     ULONG PortStatus;
340     PHID_USB_RESET_CONTEXT ResetContext;
341     PHID_DEVICE_EXTENSION DeviceExtension;
342 
343     DPRINT("[HIDUSB] ResetWorkerRoutine\n");
344 
345     //
346     // get context
347     //
348     ResetContext = Ctx;
349 
350     //
351     // get device extension
352     //
353     DeviceExtension = ResetContext->DeviceObject->DeviceExtension;
354 
355     //
356     // get port status
357     //
358     Status = HidUsb_GetPortStatus(ResetContext->DeviceObject, &PortStatus);
359     DPRINT("[HIDUSB] ResetWorkerRoutine GetPortStatus %x PortStatus %x\n", Status, PortStatus);
360     if (NT_SUCCESS(Status))
361     {
362         if (!(PortStatus & USB_PORT_STATUS_ENABLE))
363         {
364             //
365             // port is disabled
366             //
367             Status = HidUsb_ResetInterruptPipe(ResetContext->DeviceObject);
368             DPRINT1("[HIDUSB] ResetWorkerRoutine ResetPipe %x\n", Status);
369         }
370         else
371         {
372             //
373             // abort pipe
374             //
375             Status = HidUsb_AbortPipe(ResetContext->DeviceObject);
376             DPRINT1("[HIDUSB] ResetWorkerRoutine AbortPipe %x\n", Status);
377             if (NT_SUCCESS(Status))
378             {
379                 //
380                 // reset port
381                 //
382                 Status = HidUsb_ResetPort(ResetContext->DeviceObject);
383                 DPRINT1("[HIDUSB] ResetPort %x\n", Status);
384                 if (Status == STATUS_DEVICE_DATA_ERROR)
385                 {
386                     //
387                     // invalidate device state
388                     //
389                     IoInvalidateDeviceState(DeviceExtension->PhysicalDeviceObject);
390                 }
391 
392                 //
393                 // reset interrupt pipe
394                 //
395                 if (NT_SUCCESS(Status))
396                 {
397                     //
398                     // reset pipe
399                     //
400                     Status = HidUsb_ResetInterruptPipe(ResetContext->DeviceObject);
401                     DPRINT1("[HIDUSB] ResetWorkerRoutine ResetPipe %x\n", Status);
402                 }
403             }
404         }
405     }
406 
407     //
408     // cleanup
409     //
410     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
411     IoFreeWorkItem(ResetContext->WorkItem);
412     IoCompleteRequest(ResetContext->Irp, IO_NO_INCREMENT);
413     ExFreePoolWithTag(ResetContext, HIDUSB_TAG);
414 }
415 
416 
417 NTSTATUS
418 NTAPI
419 HidUsb_ReadReportCompletion(
420     IN PDEVICE_OBJECT DeviceObject,
421     IN PIRP Irp,
422     IN PVOID Context)
423 {
424     PURB Urb;
425     PHID_USB_RESET_CONTEXT ResetContext;
426 
427     //
428     // get urb
429     //
430     Urb = Context;
431     ASSERT(Urb);
432 
433     DPRINT("[HIDUSB] HidUsb_ReadReportCompletion %p Status %x Urb Status %x\n", Irp, Irp->IoStatus, Urb->UrbHeader.Status);
434 
435     if (Irp->PendingReturned)
436     {
437         //
438         // mark irp pending
439         //
440         IoMarkIrpPending(Irp);
441     }
442 
443     //
444     // did the reading report succeed / cancelled
445     //
446     if (NT_SUCCESS(Irp->IoStatus.Status) || Irp->IoStatus.Status == STATUS_CANCELLED || Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED)
447     {
448         //
449         // store result length
450         //
451         Irp->IoStatus.Information = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
452 
453         //
454         // FIXME handle error
455         //
456         ASSERT(Urb->UrbHeader.Status == USBD_STATUS_SUCCESS || Urb->UrbHeader.Status == USBD_STATUS_DEVICE_GONE);
457 
458         //
459         // free the urb
460         //
461         ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
462 
463         //
464         // finish completion
465         //
466         return STATUS_CONTINUE_COMPLETION;
467     }
468 
469     //
470     // allocate reset context
471     //
472     ResetContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(HID_USB_RESET_CONTEXT), HIDUSB_TAG);
473     if (ResetContext)
474     {
475         //
476         // allocate work item
477         //
478         ResetContext->WorkItem = IoAllocateWorkItem(DeviceObject);
479         if (ResetContext->WorkItem)
480         {
481             //
482             // init reset context
483             //
484             ResetContext->Irp = Irp;
485             ResetContext->DeviceObject = DeviceObject;
486 
487             //
488             // queue the work item
489             //
490             IoQueueWorkItem(ResetContext->WorkItem, HidUsb_ResetWorkerRoutine, DelayedWorkQueue, ResetContext);
491 
492             //
493             // free urb
494             //
495             ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
496 
497             //
498             // defer completion
499             //
500             return STATUS_MORE_PROCESSING_REQUIRED;
501         }
502         //
503         // free context
504         //
505         ExFreePoolWithTag(ResetContext, HIDUSB_TAG);
506     }
507 
508     //
509     // free urb
510     //
511     ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
512 
513     //
514     // complete request
515     //
516     return STATUS_CONTINUE_COMPLETION;
517 }
518 
519 
520 NTSTATUS
521 NTAPI
522 HidUsb_ReadReport(
523     IN PDEVICE_OBJECT DeviceObject,
524     IN PIRP Irp)
525 {
526     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
527     PHID_DEVICE_EXTENSION DeviceExtension;
528     PIO_STACK_LOCATION IoStack;
529     PURB Urb;
530     PUSBD_PIPE_INFORMATION PipeInformation;
531 
532     //
533     // get device extension
534     //
535     DeviceExtension = DeviceObject->DeviceExtension;
536     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
537 
538     //
539     // get current stack location
540     //
541     IoStack = IoGetCurrentIrpStackLocation(Irp);
542 
543     //
544     // sanity checks
545     //
546     ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength);
547     ASSERT(Irp->UserBuffer);
548     ASSERT(HidDeviceExtension->InterfaceInfo);
549 
550     //
551     // get interrupt input pipe
552     //
553     PipeInformation = HidUsb_GetInputInterruptInterfaceHandle(HidDeviceExtension->InterfaceInfo);
554     ASSERT(PipeInformation);
555 
556     //
557     // lets allocate urb
558     //
559     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), HIDUSB_URB_TAG);
560     if (!Urb)
561     {
562         //
563         // no memory
564         //
565         return STATUS_INSUFFICIENT_RESOURCES;
566     }
567 
568     //
569     // init urb
570     //
571     RtlZeroMemory(Urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
572 
573     //
574     // sanity check
575     //
576     ASSERT(Irp->UserBuffer);
577     ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength);
578     ASSERT(PipeInformation->PipeHandle);
579 
580     //
581     // build the urb
582     //
583     UsbBuildInterruptOrBulkTransferRequest(Urb,
584                                            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
585                                            PipeInformation->PipeHandle,
586                                            Irp->UserBuffer,
587                                            NULL,
588                                            IoStack->Parameters.DeviceIoControl.OutputBufferLength,
589                                            USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
590                                            NULL);
591 
592     //
593     // store configuration handle
594     //
595     Urb->UrbHeader.UsbdDeviceHandle = HidDeviceExtension->ConfigurationHandle;
596 
597     //
598     // get next location to setup irp
599     //
600     IoStack = IoGetNextIrpStackLocation(Irp);
601 
602     //
603     // init irp for lower driver
604     //
605     IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
606     IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
607     IoStack->Parameters.DeviceIoControl.InputBufferLength = 0;
608     IoStack->Parameters.DeviceIoControl.OutputBufferLength = 0;
609     IoStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
610     IoStack->Parameters.Others.Argument1 = Urb;
611 
612 
613     //
614     // set completion routine
615     //
616     IoSetCompletionRoutine(Irp, HidUsb_ReadReportCompletion, Urb, TRUE, TRUE, TRUE);
617 
618     //
619     // call driver
620     //
621     return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
622 }
623 
624 
625 NTSTATUS
626 NTAPI
627 HidUsb_GetReportDescriptor(
628     IN PDEVICE_OBJECT DeviceObject,
629     IN PIRP Irp)
630 {
631     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
632     PHID_DEVICE_EXTENSION DeviceExtension;
633     PVOID Report = NULL;
634     ULONG BufferLength, Length;
635     PIO_STACK_LOCATION IoStack;
636     NTSTATUS Status;
637 
638     //
639     // get device extension
640     //
641     DeviceExtension = DeviceObject->DeviceExtension;
642     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
643 
644     //
645     // sanity checks
646     //
647     ASSERT(HidDeviceExtension);
648     ASSERT(HidDeviceExtension->HidDescriptor);
649     ASSERT(HidDeviceExtension->HidDescriptor->bNumDescriptors >= 1);
650     ASSERT(HidDeviceExtension->HidDescriptor->DescriptorList[0].bReportType == HID_REPORT_DESCRIPTOR_TYPE);
651     ASSERT(HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength > 0);
652 
653     //
654     // FIXME: support old hid version
655     //
656     BufferLength = HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength;
657     Status = Hid_GetDescriptor(DeviceObject,
658                                URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE,
659                                sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
660                                &Report,
661                                &BufferLength,
662                                HidDeviceExtension->HidDescriptor->DescriptorList[0].bReportType,
663                                0,
664                                HidDeviceExtension->InterfaceInfo->InterfaceNumber);
665     if (!NT_SUCCESS(Status))
666     {
667         //
668         // failed to get descriptor
669         // try with old hid version
670         //
671         BufferLength = HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength;
672         Status = Hid_GetDescriptor(DeviceObject,
673                                    URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT,
674                                    sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
675                                    &Report,
676                                    &BufferLength,
677                                    HidDeviceExtension->HidDescriptor->DescriptorList[0].bReportType,
678                                    0,
679                                    0 /* FIXME*/);
680         if (!NT_SUCCESS(Status))
681         {
682             DPRINT("[HIDUSB] failed to get report descriptor with %x\n", Status);
683             return Status;
684         }
685     }
686 
687     //
688     // get current stack location
689     //
690     IoStack = IoGetCurrentIrpStackLocation(Irp);
691     DPRINT("[HIDUSB] GetReportDescriptor: Status %x ReportLength %lu OutputBufferLength %lu TransferredLength %lu\n", Status, HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, BufferLength);
692 
693     //
694     // get length to copy
695     //
696     Length = min(IoStack->Parameters.DeviceIoControl.OutputBufferLength, BufferLength);
697     ASSERT(Length);
698 
699     //
700     // copy result
701     //
702     RtlCopyMemory(Irp->UserBuffer, Report, Length);
703 
704     //
705     // store result length
706     //
707     Irp->IoStatus.Information = Length;
708 
709     //
710     // free the report buffer
711     //
712     ExFreePoolWithTag(Report, HIDUSB_TAG);
713 
714     //
715     // done
716     //
717     return Status;
718 
719 }
720 
721 NTSTATUS
722 NTAPI
723 HidInternalDeviceControl(
724     IN PDEVICE_OBJECT DeviceObject,
725     IN PIRP Irp)
726 {
727     PIO_STACK_LOCATION IoStack;
728     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
729     PHID_DEVICE_EXTENSION DeviceExtension;
730     PHID_DEVICE_ATTRIBUTES Attributes;
731     ULONG Length;
732     NTSTATUS Status;
733 
734     //
735     // get device extension
736     //
737     DeviceExtension = DeviceObject->DeviceExtension;
738     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
739 
740     //
741     // get current stack location
742     //
743     IoStack = IoGetCurrentIrpStackLocation(Irp);
744 
745     switch (IoStack->Parameters.DeviceIoControl.IoControlCode)
746     {
747         case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
748         {
749             if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_DEVICE_ATTRIBUTES))
750             {
751                 //
752                 // invalid request
753                 //
754                 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
755                 DPRINT1("[HIDUSB] IOCTL_HID_GET_DEVICE_ATTRIBUTES invalid buffer\n");
756                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
757                 return STATUS_INVALID_BUFFER_SIZE;
758             }
759             //
760             // store result
761             //
762             DPRINT("[HIDUSB] IOCTL_HID_GET_DEVICE_ATTRIBUTES\n");
763             ASSERT(HidDeviceExtension->DeviceDescriptor);
764             Irp->IoStatus.Information = sizeof(HID_DESCRIPTOR);
765             Attributes = Irp->UserBuffer;
766             Attributes->Size = sizeof(HID_DEVICE_ATTRIBUTES);
767             Attributes->VendorID = HidDeviceExtension->DeviceDescriptor->idVendor;
768             Attributes->ProductID = HidDeviceExtension->DeviceDescriptor->idProduct;
769             Attributes->VersionNumber = HidDeviceExtension->DeviceDescriptor->bcdDevice;
770 
771             //
772             // complete request
773             //
774             Irp->IoStatus.Status = STATUS_SUCCESS;
775             IoCompleteRequest(Irp, IO_NO_INCREMENT);
776             return STATUS_SUCCESS;
777         }
778         case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
779         {
780             //
781             // sanity check
782             //
783             ASSERT(HidDeviceExtension->HidDescriptor);
784             DPRINT("[HIDUSB] IOCTL_HID_GET_DEVICE_DESCRIPTOR DescriptorLength %lu OutputBufferLength %lu\n", HidDeviceExtension->HidDescriptor->bLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
785 
786             //
787             // store length
788             //
789             Length = min(HidDeviceExtension->HidDescriptor->bLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
790 
791             //
792             // copy descriptor
793             //
794             RtlCopyMemory(Irp->UserBuffer, HidDeviceExtension->HidDescriptor, Length);
795 
796             //
797             // store result length
798             //
799             Irp->IoStatus.Information = HidDeviceExtension->HidDescriptor->bLength;
800             Irp->IoStatus.Status = STATUS_SUCCESS;
801 
802             /* complete request */
803             IoCompleteRequest(Irp, IO_NO_INCREMENT);
804             return STATUS_SUCCESS;
805         }
806         case IOCTL_HID_GET_REPORT_DESCRIPTOR:
807         {
808             Status = HidUsb_GetReportDescriptor(DeviceObject, Irp);
809             DPRINT("[HIDUSB] IOCTL_HID_GET_REPORT_DESCRIPTOR Status %x\n", Status);
810             Irp->IoStatus.Status = Status;
811             IoCompleteRequest(Irp, IO_NO_INCREMENT);
812             return Status;
813         }
814         case IOCTL_HID_READ_REPORT:
815         {
816             DPRINT("[HIDUSB] IOCTL_HID_READ_REPORT\n");
817             Status = HidUsb_ReadReport(DeviceObject, Irp);
818             return Status;
819         }
820         case IOCTL_HID_WRITE_REPORT:
821         {
822             DPRINT1("[HIDUSB] IOCTL_HID_WRITE_REPORT not implemented \n");
823             ASSERT(FALSE);
824             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
825             IoCompleteRequest(Irp, IO_NO_INCREMENT);
826             return STATUS_NOT_IMPLEMENTED;
827         }
828         case IOCTL_GET_PHYSICAL_DESCRIPTOR:
829         {
830             DPRINT1("[HIDUSB] IOCTL_GET_PHYSICAL_DESCRIPTOR not implemented \n");
831             ASSERT(FALSE);
832             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
833             IoCompleteRequest(Irp, IO_NO_INCREMENT);
834             return STATUS_NOT_IMPLEMENTED;
835         }
836         case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
837         {
838             DPRINT1("[HIDUSB] IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST not implemented \n");
839             ASSERT(FALSE);
840             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
841             IoCompleteRequest(Irp, IO_NO_INCREMENT);
842             return STATUS_NOT_IMPLEMENTED;
843         }
844         case IOCTL_HID_GET_FEATURE:
845         {
846             DPRINT1("[HIDUSB] IOCTL_HID_GET_FEATURE not implemented \n");
847             ASSERT(FALSE);
848             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
849             IoCompleteRequest(Irp, IO_NO_INCREMENT);
850             return STATUS_NOT_IMPLEMENTED;
851         }
852         case IOCTL_HID_SET_FEATURE:
853         {
854             DPRINT1("[HIDUSB] IOCTL_HID_SET_FEATURE not implemented \n");
855             ASSERT(FALSE);
856             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
857             IoCompleteRequest(Irp, IO_NO_INCREMENT);
858             return STATUS_NOT_IMPLEMENTED;
859         }
860         case IOCTL_HID_SET_OUTPUT_REPORT:
861         {
862             DPRINT1("[HIDUSB] IOCTL_HID_SET_OUTPUT_REPORT not implemented \n");
863             ASSERT(FALSE);
864             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
865             IoCompleteRequest(Irp, IO_NO_INCREMENT);
866             return STATUS_NOT_IMPLEMENTED;
867         }
868         case IOCTL_HID_GET_INPUT_REPORT:
869         {
870             DPRINT1("[HIDUSB] IOCTL_HID_GET_INPUT_REPORT not implemented \n");
871             ASSERT(FALSE);
872             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
873             IoCompleteRequest(Irp, IO_NO_INCREMENT);
874             return STATUS_NOT_IMPLEMENTED;
875         }
876         case IOCTL_HID_GET_INDEXED_STRING:
877         {
878             DPRINT1("[HIDUSB] IOCTL_HID_GET_INDEXED_STRING not implemented \n");
879             ASSERT(FALSE);
880             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
881             IoCompleteRequest(Irp, IO_NO_INCREMENT);
882             return STATUS_NOT_IMPLEMENTED;
883         }
884         case IOCTL_HID_GET_MS_GENRE_DESCRIPTOR:
885         {
886             DPRINT1("[HIDUSB] IOCTL_HID_GET_MS_GENRE_DESCRIPTOR not implemented \n");
887             ASSERT(FALSE);
888             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
889             IoCompleteRequest(Irp, IO_NO_INCREMENT);
890             return STATUS_NOT_IMPLEMENTED;
891         }
892         default:
893         {
894             UNIMPLEMENTED;
895             ASSERT(FALSE);
896             Status = Irp->IoStatus.Status;
897             IoCompleteRequest(Irp, IO_NO_INCREMENT);
898             return Status;
899         }
900     }
901 }
902 
903 NTSTATUS
904 NTAPI
905 HidPower(
906     IN PDEVICE_OBJECT DeviceObject,
907     IN PIRP Irp)
908 {
909     PHID_DEVICE_EXTENSION DeviceExtension;
910 
911     DeviceExtension = DeviceObject->DeviceExtension;
912     PoStartNextPowerIrp(Irp);
913     IoSkipCurrentIrpStackLocation(Irp);
914     return PoCallDriver(DeviceExtension->NextDeviceObject, Irp);
915 }
916 
917 NTSTATUS
918 NTAPI
919 HidSystemControl(
920     IN PDEVICE_OBJECT DeviceObject,
921     IN PIRP Irp)
922 {
923     PHID_DEVICE_EXTENSION DeviceExtension;
924 
925     //
926     // get hid device extension
927     //
928     DeviceExtension = DeviceObject->DeviceExtension;
929 
930     //
931     // skip stack location
932     //
933     IoSkipCurrentIrpStackLocation(Irp);
934 
935     //
936     // submit request
937     //
938     return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
939 }
940 
941 NTSTATUS
942 NTAPI
943 Hid_PnpCompletion(
944     IN PDEVICE_OBJECT DeviceObject,
945     IN PIRP Irp,
946     IN PVOID Context)
947 {
948     //
949     // signal event
950     //
951     KeSetEvent(Context, 0, FALSE);
952 
953     //
954     // done
955     //
956     return STATUS_MORE_PROCESSING_REQUIRED;
957 }
958 
959 NTSTATUS
960 Hid_DispatchUrb(
961     IN PDEVICE_OBJECT DeviceObject,
962     IN PURB Urb)
963 {
964     PIRP Irp;
965     KEVENT Event;
966     PHID_DEVICE_EXTENSION DeviceExtension;
967     IO_STATUS_BLOCK IoStatus;
968     PIO_STACK_LOCATION IoStack;
969     NTSTATUS Status;
970 
971     //
972     // init event
973     //
974     KeInitializeEvent(&Event, NotificationEvent, FALSE);
975 
976     //
977     // get device extension
978     //
979     DeviceExtension = DeviceObject->DeviceExtension;
980 
981     //
982     // build irp
983     //
984     Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
985                                         DeviceExtension->NextDeviceObject,
986                                         NULL,
987                                         0,
988                                         NULL,
989                                         0,
990                                         TRUE,
991                                         &Event,
992                                         &IoStatus);
993     if (!Irp)
994     {
995         //
996         // no memory
997         //
998         return STATUS_INSUFFICIENT_RESOURCES;
999     }
1000 
1001     //
1002     // get next stack location
1003     //
1004     IoStack = IoGetNextIrpStackLocation(Irp);
1005 
1006     //
1007     // store urb
1008     //
1009     IoStack->Parameters.Others.Argument1 = Urb;
1010 
1011     //
1012     // set completion routine
1013     //
1014     IoSetCompletionRoutine(Irp, Hid_PnpCompletion, &Event, TRUE, TRUE, TRUE);
1015 
1016     //
1017     // call driver
1018     //
1019     Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1020 
1021     //
1022     // wait for the request to finish
1023     //
1024     if (Status == STATUS_PENDING)
1025     {
1026         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1027     }
1028 
1029     //
1030     // complete request
1031     //
1032     IoCompleteRequest(Irp, IO_NO_INCREMENT);
1033 
1034     if (Status == STATUS_PENDING)
1035     {
1036         //
1037         // get final status
1038         //
1039         Status = IoStatus.Status;
1040     }
1041 
1042     DPRINT("[HIDUSB] DispatchUrb %x\n", Status);
1043 
1044 
1045     //
1046     // done
1047     //
1048     return Status;
1049 }
1050 
1051 NTSTATUS
1052 Hid_GetDescriptor(
1053     IN PDEVICE_OBJECT DeviceObject,
1054     IN USHORT UrbFunction,
1055     IN USHORT UrbLength,
1056     IN OUT PVOID *UrbBuffer,
1057     IN OUT PULONG UrbBufferLength,
1058     IN UCHAR DescriptorType,
1059     IN UCHAR Index,
1060     IN USHORT LanguageIndex)
1061 {
1062     PURB Urb;
1063     NTSTATUS Status;
1064     UCHAR Allocated = FALSE;
1065 
1066     //
1067     // allocate urb
1068     //
1069     Urb = ExAllocatePoolWithTag(NonPagedPool, UrbLength, HIDUSB_URB_TAG);
1070     if (!Urb)
1071     {
1072         //
1073         // no memory
1074         //
1075         return STATUS_INSUFFICIENT_RESOURCES;
1076     }
1077 
1078     //
1079     // is there an urb buffer
1080     //
1081     if (!*UrbBuffer)
1082     {
1083         //
1084         // allocate buffer
1085         //
1086         *UrbBuffer = ExAllocatePoolWithTag(NonPagedPool, *UrbBufferLength, HIDUSB_TAG);
1087         if (!*UrbBuffer)
1088         {
1089             //
1090             // no memory
1091             //
1092             ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
1093             return STATUS_INSUFFICIENT_RESOURCES;
1094         }
1095 
1096         //
1097         // zero buffer
1098         //
1099         RtlZeroMemory(*UrbBuffer, *UrbBufferLength);
1100         Allocated = TRUE;
1101     }
1102 
1103     //
1104     // zero urb
1105     //
1106     RtlZeroMemory(Urb, UrbLength);
1107 
1108     //
1109     // build descriptor request
1110     //
1111     UsbBuildGetDescriptorRequest(Urb, UrbLength, DescriptorType, Index, LanguageIndex, *UrbBuffer, NULL, *UrbBufferLength, NULL);
1112 
1113     //
1114     // set urb function
1115     //
1116     Urb->UrbHeader.Function = UrbFunction;
1117 
1118     //
1119     // dispatch urb
1120     //
1121     Status = Hid_DispatchUrb(DeviceObject, Urb);
1122 
1123     //
1124     // did the request fail
1125     //
1126     if (!NT_SUCCESS(Status))
1127     {
1128         if (Allocated)
1129         {
1130             //
1131             // free allocated buffer
1132             //
1133             ExFreePoolWithTag(*UrbBuffer, HIDUSB_TAG);
1134             *UrbBuffer = NULL;
1135         }
1136 
1137         //
1138         // free urb
1139         //
1140         ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
1141         *UrbBufferLength = 0;
1142         return Status;
1143     }
1144 
1145     //
1146     // did urb request fail
1147     //
1148     if (!NT_SUCCESS(Urb->UrbHeader.Status))
1149     {
1150         if (Allocated)
1151         {
1152             //
1153             // free allocated buffer
1154             //
1155             ExFreePoolWithTag(*UrbBuffer, HIDUSB_TAG);
1156             *UrbBuffer = NULL;
1157         }
1158 
1159         //
1160         // free urb
1161         //
1162         ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
1163         *UrbBufferLength = 0;
1164         return STATUS_UNSUCCESSFUL;
1165     }
1166 
1167     //
1168     // store result length
1169     //
1170     *UrbBufferLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
1171 
1172     //
1173     // free urb
1174     //
1175     ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
1176 
1177     //
1178     // completed successfully
1179     //
1180     return STATUS_SUCCESS;
1181 }
1182 
1183 NTSTATUS
1184 Hid_SelectConfiguration(
1185     IN PDEVICE_OBJECT DeviceObject)
1186 {
1187     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1188     NTSTATUS Status;
1189     USBD_INTERFACE_LIST_ENTRY InterfaceList[2];
1190     PURB Urb;
1191     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1192     PHID_DEVICE_EXTENSION DeviceExtension;
1193 
1194     //
1195     // get device extension
1196     //
1197     DeviceExtension = DeviceObject->DeviceExtension;
1198     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
1199 
1200     //
1201     // now parse the descriptors
1202     //
1203     InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(HidDeviceExtension->ConfigurationDescriptor,
1204                                                               HidDeviceExtension->ConfigurationDescriptor,
1205                                                              -1,
1206                                                              -1,
1207                                                               USB_DEVICE_CLASS_HUMAN_INTERFACE,
1208                                                              -1,
1209                                                              -1);
1210     if (!InterfaceDescriptor)
1211     {
1212         //
1213         // bogus configuration descriptor
1214         //
1215         return STATUS_INVALID_PARAMETER;
1216     }
1217 
1218     //
1219     // sanity check
1220     //
1221     ASSERT(InterfaceDescriptor);
1222     ASSERT(InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_HUMAN_INTERFACE);
1223     ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
1224     ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
1225 
1226     //
1227     // setup interface list
1228     //
1229     RtlZeroMemory(InterfaceList, sizeof(InterfaceList));
1230     InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor;
1231 
1232     //
1233     // build urb
1234     //
1235     Urb = USBD_CreateConfigurationRequestEx(HidDeviceExtension->ConfigurationDescriptor, InterfaceList);
1236     if (!Urb)
1237     {
1238         //
1239         // no memory
1240         //
1241         return STATUS_INSUFFICIENT_RESOURCES;
1242     }
1243 
1244     //
1245     // dispatch request
1246     //
1247     Status = Hid_DispatchUrb(DeviceObject, Urb);
1248     if (NT_SUCCESS(Status))
1249     {
1250         //
1251         // store configuration handle
1252         //
1253         HidDeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
1254 
1255         //
1256         // copy interface info
1257         //
1258         HidDeviceExtension->InterfaceInfo = ExAllocatePoolWithTag(NonPagedPool, Urb->UrbSelectConfiguration.Interface.Length, HIDUSB_TAG);
1259         if (HidDeviceExtension->InterfaceInfo)
1260         {
1261             //
1262             // copy interface info
1263             //
1264             RtlCopyMemory(HidDeviceExtension->InterfaceInfo, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length);
1265         }
1266     }
1267 
1268     //
1269     // free urb request
1270     //
1271     ExFreePoolWithTag(Urb, 0);
1272 
1273     //
1274     // done
1275     //
1276     return Status;
1277 }
1278 
1279 NTSTATUS
1280 Hid_DisableConfiguration(
1281     IN PDEVICE_OBJECT DeviceObject)
1282 {
1283     PHID_DEVICE_EXTENSION DeviceExtension;
1284     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1285     NTSTATUS Status;
1286     PURB Urb;
1287 
1288     //
1289     // get device extension
1290     //
1291     DeviceExtension = DeviceObject->DeviceExtension;
1292     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
1293 
1294     //
1295     // build urb
1296     //
1297     Urb = ExAllocatePoolWithTag(NonPagedPool,
1298                                 sizeof(struct _URB_SELECT_CONFIGURATION),
1299                                 HIDUSB_URB_TAG);
1300     if (!Urb)
1301     {
1302         //
1303         // no memory
1304         //
1305         return STATUS_INSUFFICIENT_RESOURCES;
1306     }
1307 
1308     //
1309     // format urb
1310     //
1311     UsbBuildSelectConfigurationRequest(Urb,
1312                                        sizeof(struct _URB_SELECT_CONFIGURATION),
1313                                        NULL);
1314 
1315     //
1316     // dispatch request
1317     //
1318     Status = Hid_DispatchUrb(DeviceObject, Urb);
1319     if (!NT_SUCCESS(Status))
1320     {
1321         DPRINT1("[HIDUSB] Dispatching unconfigure URB failed with %lx\n", Status);
1322     }
1323     else if (!USBD_SUCCESS(Urb->UrbHeader.Status))
1324     {
1325         DPRINT("[HIDUSB] Unconfigure URB failed with %lx\n", Status);
1326     }
1327 
1328     //
1329     // free urb
1330     //
1331     ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
1332 
1333     //
1334     // free resources
1335     //
1336     HidDeviceExtension->ConfigurationHandle = NULL;
1337 
1338     if (HidDeviceExtension->InterfaceInfo)
1339     {
1340         ExFreePoolWithTag(HidDeviceExtension->InterfaceInfo, HIDUSB_TAG);
1341         HidDeviceExtension->InterfaceInfo = NULL;
1342     }
1343 
1344     if (HidDeviceExtension->ConfigurationDescriptor)
1345     {
1346         ExFreePoolWithTag(HidDeviceExtension->ConfigurationDescriptor, HIDUSB_TAG);
1347         HidDeviceExtension->ConfigurationDescriptor = NULL;
1348         HidDeviceExtension->HidDescriptor = NULL;
1349     }
1350 
1351     if (HidDeviceExtension->DeviceDescriptor)
1352     {
1353         ExFreePoolWithTag(HidDeviceExtension->DeviceDescriptor, HIDUSB_TAG);
1354         HidDeviceExtension->DeviceDescriptor = NULL;
1355     }
1356 
1357     //
1358     // done
1359     //
1360     return Status;
1361 }
1362 
1363 NTSTATUS
1364 Hid_SetIdle(
1365     IN PDEVICE_OBJECT DeviceObject)
1366 {
1367     PURB Urb;
1368     NTSTATUS Status;
1369 
1370     //
1371     // allocate urb
1372     //
1373     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), HIDUSB_URB_TAG);
1374     if (!Urb)
1375     {
1376         //
1377         // no memory
1378         //
1379         return STATUS_INSUFFICIENT_RESOURCES;
1380     }
1381 
1382     //
1383     // zero urb
1384     //
1385     RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
1386 
1387     //
1388     // format urb
1389     //
1390     UsbBuildVendorRequest(Urb,
1391                           URB_FUNCTION_CLASS_INTERFACE,
1392                           sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
1393                           0,
1394                           0,
1395                           USB_SET_IDLE_REQUEST, // HID_SET_IDLE
1396                           0,
1397                           0,
1398                           NULL,
1399                           NULL,
1400                           0,
1401                           NULL);
1402 
1403     //
1404     // dispatch urb
1405     //
1406     Status = Hid_DispatchUrb(DeviceObject, Urb);
1407 
1408     //
1409     // free urb
1410     //
1411     ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
1412 
1413     //
1414     // print status
1415     //
1416     DPRINT1("Status %x\n", Status);
1417     return Status;
1418 }
1419 
1420 
1421 VOID
1422 Hid_GetProtocol(
1423     IN PDEVICE_OBJECT DeviceObject)
1424 {
1425     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1426     PHID_DEVICE_EXTENSION DeviceExtension;
1427     PURB Urb;
1428     UCHAR Protocol[1];
1429 
1430     //
1431     // get device extension
1432     //
1433     DeviceExtension = DeviceObject->DeviceExtension;
1434     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
1435     ASSERT(HidDeviceExtension->InterfaceInfo);
1436 
1437     if (HidDeviceExtension->InterfaceInfo->SubClass != 0x1)
1438     {
1439         //
1440         // device does not support the boot protocol
1441         //
1442         return;
1443     }
1444 
1445     //
1446     // allocate urb
1447     //
1448     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), HIDUSB_URB_TAG);
1449     if (!Urb)
1450     {
1451         //
1452         // no memory
1453         //
1454         return;
1455     }
1456 
1457     //
1458     // zero urb
1459     //
1460     RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
1461 
1462     //
1463     // format urb
1464     //
1465     UsbBuildVendorRequest(Urb,
1466                           URB_FUNCTION_CLASS_INTERFACE,
1467                           sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
1468                           USBD_TRANSFER_DIRECTION_IN,
1469                           0,
1470                           USB_GET_PROTOCOL_REQUEST,
1471                           0,
1472                           0,
1473                           Protocol,
1474                           NULL,
1475                           1,
1476                           NULL);
1477     Protocol[0] = 0xFF;
1478 
1479     //
1480     // dispatch urb
1481     //
1482     Hid_DispatchUrb(DeviceObject, Urb);
1483 
1484     //
1485     // free urb
1486     //
1487     ExFreePoolWithTag(Urb, HIDUSB_URB_TAG);
1488 
1489     //
1490     // boot protocol active 0x00 disabled 0x1
1491     //
1492     if (Protocol[0] != 0x1)
1493     {
1494         if (Protocol[0] == 0x00)
1495         {
1496             DPRINT1("[HIDUSB] Need to disable boot protocol!\n");
1497         }
1498         else
1499         {
1500             DPRINT1("[HIDUSB] Unexpected protocol value %x\n", Protocol[0] & 0xFF);
1501         }
1502     }
1503 }
1504 
1505 NTSTATUS
1506 Hid_PnpStart(
1507     IN PDEVICE_OBJECT DeviceObject)
1508 {
1509     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1510     PHID_DEVICE_EXTENSION DeviceExtension;
1511     NTSTATUS Status;
1512     ULONG DescriptorLength;
1513     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1514     PHID_DESCRIPTOR HidDescriptor;
1515 
1516     //
1517     // get device extension
1518     //
1519     DeviceExtension = DeviceObject->DeviceExtension;
1520     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
1521 
1522     //
1523     // get device descriptor
1524     //
1525     DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR);
1526     Status = Hid_GetDescriptor(DeviceObject,
1527                                URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
1528                                sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
1529                                (PVOID *)&HidDeviceExtension->DeviceDescriptor,
1530                                &DescriptorLength,
1531                                USB_DEVICE_DESCRIPTOR_TYPE,
1532                                0,
1533                                0);
1534     if (!NT_SUCCESS(Status))
1535     {
1536         //
1537         // failed to obtain device descriptor
1538         //
1539         DPRINT1("[HIDUSB] failed to get device descriptor %x\n", Status);
1540         return Status;
1541     }
1542 
1543     //
1544     // now get the configuration descriptor
1545     //
1546     DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
1547     Status = Hid_GetDescriptor(DeviceObject,
1548                                URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
1549                                sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
1550                                (PVOID *)&HidDeviceExtension->ConfigurationDescriptor,
1551                                &DescriptorLength,
1552                                USB_CONFIGURATION_DESCRIPTOR_TYPE,
1553                                0,
1554                                0);
1555     if (!NT_SUCCESS(Status))
1556     {
1557         //
1558         // failed to obtain device descriptor
1559         //
1560         DPRINT1("[HIDUSB] failed to get device descriptor %x\n", Status);
1561         return Status;
1562     }
1563 
1564     //
1565     // sanity check
1566     //
1567     ASSERT(DescriptorLength);
1568     ASSERT(HidDeviceExtension->ConfigurationDescriptor);
1569     ASSERT(HidDeviceExtension->ConfigurationDescriptor->bLength);
1570 
1571     //
1572     // store full length
1573     //
1574     DescriptorLength = HidDeviceExtension->ConfigurationDescriptor->wTotalLength;
1575 
1576     //
1577     // delete partial configuration descriptor
1578     //
1579     ExFreePoolWithTag(HidDeviceExtension->ConfigurationDescriptor, HIDUSB_TAG);
1580     HidDeviceExtension->ConfigurationDescriptor = NULL;
1581 
1582     //
1583     // get full configuration descriptor
1584     //
1585     Status = Hid_GetDescriptor(DeviceObject,
1586                                URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
1587                                sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
1588                                (PVOID *)&HidDeviceExtension->ConfigurationDescriptor,
1589                                &DescriptorLength,
1590                                USB_CONFIGURATION_DESCRIPTOR_TYPE,
1591                                0,
1592                                0);
1593     if (!NT_SUCCESS(Status))
1594     {
1595         //
1596         // failed to obtain device descriptor
1597         //
1598         DPRINT1("[HIDUSB] failed to get device descriptor %x\n", Status);
1599         return Status;
1600     }
1601 
1602     //
1603     // now parse the descriptors
1604     //
1605     InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(HidDeviceExtension->ConfigurationDescriptor,
1606                                                               HidDeviceExtension->ConfigurationDescriptor,
1607                                                              -1,
1608                                                              -1,
1609                                                               USB_DEVICE_CLASS_HUMAN_INTERFACE,
1610                                                              -1,
1611                                                              -1);
1612     if (!InterfaceDescriptor)
1613     {
1614         //
1615         // no interface class
1616         //
1617         DPRINT1("[HIDUSB] HID Interface descriptor not found\n");
1618         return STATUS_UNSUCCESSFUL;
1619     }
1620 
1621     //
1622     // sanity check
1623     //
1624     ASSERT(InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_HUMAN_INTERFACE);
1625     ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
1626     ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
1627 
1628     //
1629     // move to next descriptor
1630     //
1631     HidDescriptor = (PHID_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
1632     ASSERT(HidDescriptor->bLength >= 2);
1633 
1634     //
1635     // check if this is the hid descriptor
1636     //
1637     if (HidDescriptor->bLength == sizeof(HID_DESCRIPTOR) && HidDescriptor->bDescriptorType == HID_HID_DESCRIPTOR_TYPE)
1638     {
1639         //
1640         // found
1641         //
1642         HidDeviceExtension->HidDescriptor = HidDescriptor;
1643 
1644         //
1645         // select configuration
1646         //
1647         Status = Hid_SelectConfiguration(DeviceObject);
1648 
1649         //
1650         // done
1651         //
1652         DPRINT("[HIDUSB] SelectConfiguration %x\n", Status);
1653 
1654         if (NT_SUCCESS(Status))
1655         {
1656             //
1657             // now set the device idle
1658             //
1659             Hid_SetIdle(DeviceObject);
1660 
1661             //
1662             // get protocol
1663             //
1664             Hid_GetProtocol(DeviceObject);
1665             return Status;
1666         }
1667     }
1668     else
1669     {
1670         //
1671         // FIXME parse hid descriptor
1672         // select configuration
1673         // set idle
1674         // and get protocol
1675         //
1676         UNIMPLEMENTED;
1677         ASSERT(FALSE);
1678     }
1679     return Status;
1680 }
1681 
1682 
1683 NTSTATUS
1684 NTAPI
1685 HidPnp(
1686     IN PDEVICE_OBJECT DeviceObject,
1687     IN PIRP Irp)
1688 {
1689     NTSTATUS Status;
1690     PIO_STACK_LOCATION IoStack;
1691     PHID_DEVICE_EXTENSION DeviceExtension;
1692     KEVENT Event;
1693 
1694     //
1695     // get device extension
1696     //
1697     DeviceExtension = DeviceObject->DeviceExtension;
1698 
1699     //
1700     // get current stack location
1701     //
1702     IoStack = IoGetCurrentIrpStackLocation(Irp);
1703     DPRINT("[HIDUSB] Pnp %x\n", IoStack->MinorFunction);
1704 
1705     //
1706     // handle requests based on request type
1707     //
1708     switch (IoStack->MinorFunction)
1709     {
1710         case IRP_MN_REMOVE_DEVICE:
1711         {
1712             //
1713             // unconfigure device
1714             // FIXME: Call this on IRP_MN_SURPRISE_REMOVAL, but don't send URBs
1715             // FIXME: Don't call this after we've already seen a surprise removal or stop
1716             //
1717             Hid_DisableConfiguration(DeviceObject);
1718 
1719             //
1720             // pass request onto lower driver
1721             //
1722             IoSkipCurrentIrpStackLocation(Irp);
1723             Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1724 
1725             return Status;
1726         }
1727         case IRP_MN_QUERY_PNP_DEVICE_STATE:
1728         {
1729             //
1730             // device can not be disabled
1731             //
1732             Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1733 
1734             //
1735             // pass request to next request
1736             //
1737             IoSkipCurrentIrpStackLocation(Irp);
1738             Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1739 
1740             //
1741             // done
1742             //
1743             return Status;
1744         }
1745         case IRP_MN_QUERY_STOP_DEVICE:
1746         case IRP_MN_QUERY_REMOVE_DEVICE:
1747         {
1748             //
1749             // we're fine with it
1750             //
1751             Irp->IoStatus.Status = STATUS_SUCCESS;
1752 
1753             //
1754             // pass request to next driver
1755             //
1756             IoSkipCurrentIrpStackLocation(Irp);
1757             Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1758 
1759             //
1760             // done
1761             //
1762             return Status;
1763         }
1764         case IRP_MN_STOP_DEVICE:
1765         {
1766             //
1767             // unconfigure device
1768             //
1769             Hid_DisableConfiguration(DeviceObject);
1770 
1771             //
1772             // prepare irp
1773             //
1774             KeInitializeEvent(&Event, NotificationEvent, FALSE);
1775             IoCopyCurrentIrpStackLocationToNext(Irp);
1776             IoSetCompletionRoutine(Irp, Hid_PnpCompletion, &Event, TRUE, TRUE, TRUE);
1777 
1778             //
1779             // send irp and wait for completion
1780             //
1781             Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1782             if (Status == STATUS_PENDING)
1783             {
1784                 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1785                 Status = Irp->IoStatus.Status;
1786             }
1787 
1788             //
1789             // done
1790             //
1791             IoCompleteRequest(Irp, IO_NO_INCREMENT);
1792             return Status;
1793         }
1794         case IRP_MN_QUERY_CAPABILITIES:
1795         {
1796             //
1797             // prepare irp
1798             //
1799             KeInitializeEvent(&Event, NotificationEvent, FALSE);
1800             IoCopyCurrentIrpStackLocationToNext(Irp);
1801             IoSetCompletionRoutine(Irp, Hid_PnpCompletion, &Event, TRUE, TRUE, TRUE);
1802 
1803             //
1804             // send irp and wait for completion
1805             //
1806             Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1807             if (Status == STATUS_PENDING)
1808             {
1809                 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1810                 Status = Irp->IoStatus.Status;
1811             }
1812 
1813             if (NT_SUCCESS(Status) && IoStack->Parameters.DeviceCapabilities.Capabilities != NULL)
1814             {
1815                 //
1816                 // don't need to safely remove
1817                 //
1818                 IoStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
1819             }
1820 
1821             //
1822             // done
1823             //
1824             IoCompleteRequest(Irp, IO_NO_INCREMENT);
1825             return Status;
1826         }
1827         case IRP_MN_START_DEVICE:
1828         {
1829             //
1830             // prepare irp
1831             //
1832             KeInitializeEvent(&Event, NotificationEvent, FALSE);
1833             IoCopyCurrentIrpStackLocationToNext(Irp);
1834             IoSetCompletionRoutine(Irp, Hid_PnpCompletion, &Event, TRUE, TRUE, TRUE);
1835 
1836             //
1837             // send irp and wait for completion
1838             //
1839             Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1840             if (Status == STATUS_PENDING)
1841             {
1842                 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1843                 Status = Irp->IoStatus.Status;
1844             }
1845 
1846             //
1847             // did the device successfully start
1848             //
1849             if (!NT_SUCCESS(Status))
1850             {
1851                 //
1852                 // failed
1853                 //
1854                 DPRINT1("HIDUSB: IRP_MN_START_DEVICE failed with %x\n", Status);
1855                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1856                 return Status;
1857             }
1858 
1859             //
1860             // start device
1861             //
1862             Status = Hid_PnpStart(DeviceObject);
1863 
1864             //
1865             // complete request
1866             //
1867             Irp->IoStatus.Status = Status;
1868             DPRINT("[HIDUSB] IRP_MN_START_DEVICE Status %x\n", Status);
1869             IoCompleteRequest(Irp, IO_NO_INCREMENT);
1870             return Status;
1871         }
1872         default:
1873         {
1874              //
1875              // forward and forget request
1876              //
1877              IoSkipCurrentIrpStackLocation(Irp);
1878              return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1879         }
1880     }
1881 }
1882 
1883 NTSTATUS
1884 NTAPI
1885 HidAddDevice(
1886     IN PDRIVER_OBJECT DriverObject,
1887     IN PDEVICE_OBJECT DeviceObject)
1888 {
1889     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1890     PHID_DEVICE_EXTENSION DeviceExtension;
1891 
1892     //
1893     // get device extension
1894     //
1895     DeviceExtension = DeviceObject->DeviceExtension;
1896     HidDeviceExtension = DeviceExtension->MiniDeviceExtension;
1897 
1898     //
1899     // init event
1900     //
1901     KeInitializeEvent(&HidDeviceExtension->Event, NotificationEvent, FALSE);
1902 
1903     //
1904     // done
1905     //
1906     return STATUS_SUCCESS;
1907 }
1908 
1909 VOID
1910 NTAPI
1911 Hid_Unload(
1912     IN PDRIVER_OBJECT DriverObject)
1913 {
1914     UNIMPLEMENTED;
1915 }
1916 
1917 
1918 NTSTATUS
1919 NTAPI
1920 DriverEntry(
1921     IN PDRIVER_OBJECT DriverObject,
1922     IN PUNICODE_STRING RegPath)
1923 {
1924     HID_MINIDRIVER_REGISTRATION Registration;
1925     NTSTATUS Status;
1926 
1927     //
1928     // initialize driver object
1929     //
1930     DriverObject->MajorFunction[IRP_MJ_CREATE] = HidCreate;
1931     DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidCreate;
1932     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidInternalDeviceControl;
1933     DriverObject->MajorFunction[IRP_MJ_POWER] = HidPower;
1934     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidSystemControl;
1935     DriverObject->MajorFunction[IRP_MJ_PNP] = HidPnp;
1936     DriverObject->DriverExtension->AddDevice = HidAddDevice;
1937     DriverObject->DriverUnload = Hid_Unload;
1938 
1939     //
1940     // prepare registration info
1941     //
1942     RtlZeroMemory(&Registration, sizeof(HID_MINIDRIVER_REGISTRATION));
1943 
1944     //
1945     // fill in registration info
1946     //
1947     Registration.Revision = HID_REVISION;
1948     Registration.DriverObject = DriverObject;
1949     Registration.RegistryPath = RegPath;
1950     Registration.DeviceExtensionSize = sizeof(HID_USB_DEVICE_EXTENSION);
1951     Registration.DevicesArePolled = FALSE;
1952 
1953     //
1954     // register driver
1955     //
1956     Status = HidRegisterMinidriver(&Registration);
1957 
1958     //
1959     // informal debug
1960     //
1961     DPRINT("********* HIDUSB *********\n");
1962     DPRINT("HIDUSB Registration Status %x\n", Status);
1963 
1964     return Status;
1965 }
1966