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
HidUsb_GetInputInterruptInterfaceHandle(PUSBD_INTERFACE_INFORMATION InterfaceInformation)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
HidUsb_GetPortStatus(IN PDEVICE_OBJECT DeviceObject,IN PULONG PortStatus)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
HidUsb_ResetInterruptPipe(IN PDEVICE_OBJECT DeviceObject)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
HidUsb_AbortPipe(IN PDEVICE_OBJECT DeviceObject)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
HidUsb_ResetPort(IN PDEVICE_OBJECT DeviceObject)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
HidCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
HidUsb_ResetWorkerRoutine(IN PDEVICE_OBJECT DeviceObject,IN PVOID Ctx)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
HidUsb_ReadReportCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)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
HidUsb_ReadReport(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
HidUsb_GetReportDescriptor(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
HidInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
HidPower(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
HidSystemControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
Hid_PnpCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)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
Hid_DispatchUrb(IN PDEVICE_OBJECT DeviceObject,IN PURB Urb)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
Hid_GetDescriptor(IN PDEVICE_OBJECT DeviceObject,IN USHORT UrbFunction,IN USHORT UrbLength,IN OUT PVOID * UrbBuffer,IN OUT PULONG UrbBufferLength,IN UCHAR DescriptorType,IN UCHAR Index,IN USHORT LanguageIndex)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
Hid_SelectConfiguration(IN PDEVICE_OBJECT DeviceObject)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
Hid_DisableConfiguration(IN PDEVICE_OBJECT DeviceObject)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
Hid_SetIdle(IN PDEVICE_OBJECT DeviceObject)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
Hid_GetProtocol(IN PDEVICE_OBJECT DeviceObject)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
Hid_PnpStart(IN PDEVICE_OBJECT DeviceObject)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
HidPnp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
HidAddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT DeviceObject)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
Hid_Unload(IN PDRIVER_OBJECT DriverObject)1911 Hid_Unload(
1912 IN PDRIVER_OBJECT DriverObject)
1913 {
1914 UNIMPLEMENTED;
1915 }
1916
1917
1918 NTSTATUS
1919 NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegPath)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