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