- Do not assert on failed devices
[reactos.git] / reactos / 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 DPRINT("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 DPRINT("[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 DPRINT("[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 DPRINT("[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 DPRINT("[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 DPRINT("[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 DPRINT("[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 DPRINT("[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 DPRINT("Status %x\n", Status);
1295 return Status;
1296 }
1297
1298
1299 VOID
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 ASSERT(HidDeviceExtension->InterfaceInfo);
1315
1316 if (HidDeviceExtension->InterfaceInfo->SubClass != 0x1)
1317 {
1318 //
1319 // device does not support the boot protocol
1320 //
1321 return;
1322 }
1323
1324
1325 //
1326 // allocate urb
1327 //
1328 Urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
1329 if (!Urb)
1330 {
1331 //
1332 // no memory
1333 //
1334 return;
1335 }
1336
1337 //
1338 // zero urb
1339 //
1340 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
1341
1342 //
1343 // format urb
1344 //
1345 UsbBuildVendorRequest(Urb,
1346 URB_FUNCTION_CLASS_INTERFACE,
1347 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
1348 USBD_TRANSFER_DIRECTION_IN,
1349 0,
1350 USB_GET_PROTOCOL_REQUEST,
1351 0,
1352 0,
1353 Protocol,
1354 NULL,
1355 1,
1356 NULL);
1357 Protocol[0] = 0xFF;
1358 //
1359 // dispatch urb
1360 //
1361 Status = Hid_DispatchUrb(DeviceObject, Urb);
1362
1363 //
1364 // free urb
1365 //
1366 ExFreePool(Urb);
1367
1368 //
1369 // boot protocol active 0x00 disabled 0x1
1370 //
1371 if (Protocol[0] != 0x1)
1372 {
1373 if (Protocol[0] == 0x00)
1374 {
1375 DPRINT1("[HIDUSB] Need to disable boot protocol!\n");
1376 }
1377 else
1378 {
1379 DPRINT1("[HIDUSB] Unexpected protocol value %x\n", Protocol[0] & 0xFF);
1380 }
1381 }
1382 }
1383
1384 NTSTATUS
1385 Hid_PnpStart(
1386 IN PDEVICE_OBJECT DeviceObject)
1387 {
1388 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1389 PHID_DEVICE_EXTENSION DeviceExtension;
1390 NTSTATUS Status;
1391 ULONG DescriptorLength;
1392 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1393 PHID_DESCRIPTOR HidDescriptor;
1394
1395 //
1396 // get device extension
1397 //
1398 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1399 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1400
1401 //
1402 // get device descriptor
1403 //
1404 DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR);
1405 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);
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 // now get the configuration descriptor
1417 //
1418 DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
1419 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);
1420 if (!NT_SUCCESS(Status))
1421 {
1422 //
1423 // failed to obtain device descriptor
1424 //
1425 DPRINT1("[HIDUSB] failed to get device descriptor %x\n", Status);
1426 return Status;
1427 }
1428
1429 //
1430 // sanity check
1431 //
1432 ASSERT(DescriptorLength);
1433 ASSERT(HidDeviceExtension->ConfigurationDescriptor);
1434 ASSERT(HidDeviceExtension->ConfigurationDescriptor->bLength);
1435
1436 //
1437 // store full length
1438 //
1439 DescriptorLength = HidDeviceExtension->ConfigurationDescriptor->wTotalLength;
1440
1441 //
1442 // delete partial configuration descriptor
1443 //
1444 ExFreePool(HidDeviceExtension->ConfigurationDescriptor);
1445 HidDeviceExtension->ConfigurationDescriptor = NULL;
1446
1447 //
1448 // get full configuration descriptor
1449 //
1450 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);
1451 if (!NT_SUCCESS(Status))
1452 {
1453 //
1454 // failed to obtain device descriptor
1455 //
1456 DPRINT1("[HIDUSB] failed to get device descriptor %x\n", Status);
1457 return Status;
1458 }
1459
1460 //
1461 // now parse the descriptors
1462 //
1463 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(HidDeviceExtension->ConfigurationDescriptor,
1464 HidDeviceExtension->ConfigurationDescriptor,
1465 -1,
1466 -1,
1467 USB_DEVICE_CLASS_HUMAN_INTERFACE,
1468 -1,
1469 -1);
1470 if (!InterfaceDescriptor)
1471 {
1472 //
1473 // no interface class
1474 //
1475 DPRINT1("[HIDUSB] HID Class found\n");
1476 return STATUS_UNSUCCESSFUL;
1477 }
1478
1479 //
1480 // sanity check
1481 //
1482 ASSERT(InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_HUMAN_INTERFACE);
1483 ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
1484 ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
1485
1486 //
1487 // now set the device idle
1488 //
1489 Hid_SetIdle(DeviceObject);
1490
1491 //
1492 // move to next descriptor
1493 //
1494 HidDescriptor = (PHID_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
1495 ASSERT(HidDescriptor->bLength >= 2);
1496
1497 //
1498 // check if this is the hid descriptor
1499 //
1500 if (HidDescriptor->bLength == sizeof(HID_DESCRIPTOR) && HidDescriptor->bDescriptorType == HID_HID_DESCRIPTOR_TYPE)
1501 {
1502 //
1503 // found
1504 //
1505 HidDeviceExtension->HidDescriptor = HidDescriptor;
1506
1507 //
1508 // select configuration
1509 //
1510 Status = Hid_SelectConfiguration(DeviceObject);
1511
1512 //
1513 // done
1514 //
1515 DPRINT("[HIDUSB] SelectConfiguration %x\n", Status);
1516
1517 if (NT_SUCCESS(Status))
1518 {
1519 //
1520 // get protocol
1521 //
1522 Hid_GetProtocol(DeviceObject);
1523 return Status;
1524 }
1525 }
1526
1527 //
1528 // FIXME parse hid descriptor
1529 //
1530 UNIMPLEMENTED
1531 ASSERT(FALSE);
1532
1533 //
1534 // get protocol
1535 //
1536 Hid_GetProtocol(DeviceObject);
1537 return STATUS_SUCCESS;
1538 }
1539
1540
1541 NTSTATUS
1542 NTAPI
1543 HidPnp(
1544 IN PDEVICE_OBJECT DeviceObject,
1545 IN PIRP Irp)
1546 {
1547 NTSTATUS Status;
1548 PIO_STACK_LOCATION IoStack;
1549 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1550 PHID_DEVICE_EXTENSION DeviceExtension;
1551 KEVENT Event;
1552
1553 //
1554 // get device extension
1555 //
1556 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1557 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1558
1559 //
1560 // get current stack location
1561 //
1562 IoStack = IoGetCurrentIrpStackLocation(Irp);
1563 DPRINT("[HIDUSB] Pnp %x\n", IoStack->MinorFunction);
1564
1565 //
1566 // handle requests based on request type
1567 //
1568 switch(IoStack->MinorFunction)
1569 {
1570 case IRP_MN_REMOVE_DEVICE:
1571 {
1572 //
1573 // pass request onto lower driver
1574 //
1575 IoSkipCurrentIrpStackLocation(Irp);
1576 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1577
1578 //
1579 // free resources
1580 //
1581 if (HidDeviceExtension->ConfigurationDescriptor)
1582 {
1583 ExFreePool(HidDeviceExtension->ConfigurationDescriptor);
1584 HidDeviceExtension->ConfigurationDescriptor = NULL;
1585 }
1586
1587 //
1588 // delete and detach device
1589 //
1590 IoDetachDevice(DeviceExtension->NextDeviceObject);
1591 IoDeleteDevice(DeviceObject);
1592
1593 return Status;
1594 }
1595 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1596 {
1597 //
1598 // device can not be disabled
1599 //
1600 Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1601
1602 //
1603 // pass request to next request
1604 //
1605 IoSkipCurrentIrpStackLocation(Irp);
1606 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1607
1608 //
1609 // done
1610 //
1611 return Status;
1612 }
1613 case IRP_MN_QUERY_STOP_DEVICE:
1614 case IRP_MN_QUERY_REMOVE_DEVICE:
1615 {
1616 //
1617 // we're fine with it
1618 //
1619 Irp->IoStatus.Status = STATUS_SUCCESS;
1620
1621 //
1622 // pass request to next driver
1623 //
1624 IoSkipCurrentIrpStackLocation(Irp);
1625 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1626
1627 //
1628 // done
1629 //
1630 return Status;
1631 }
1632 case IRP_MN_STOP_DEVICE:
1633 {
1634 //
1635 // FIXME: unconfigure the device
1636 //
1637
1638 //
1639 // prepare irp
1640 //
1641 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1642 IoCopyCurrentIrpStackLocationToNext(Irp);
1643 IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1644
1645 //
1646 // send irp and wait for completion
1647 //
1648 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1649 if (Status == STATUS_PENDING)
1650 {
1651 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1652 Status = Irp->IoStatus.Status;
1653 }
1654
1655 //
1656 // free resources
1657 //
1658 if (HidDeviceExtension->HidDescriptor)
1659 {
1660 ExFreePool(HidDeviceExtension->HidDescriptor);
1661 HidDeviceExtension->HidDescriptor = NULL;
1662 }
1663
1664 //
1665 // done
1666 //
1667 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1668 return Status;
1669 }
1670 case IRP_MN_QUERY_CAPABILITIES:
1671 {
1672 //
1673 // prepare irp
1674 //
1675 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1676 IoCopyCurrentIrpStackLocationToNext(Irp);
1677 IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1678
1679 //
1680 // send irp and wait for completion
1681 //
1682 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1683 if (Status == STATUS_PENDING)
1684 {
1685 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1686 Status = Irp->IoStatus.Status;
1687 }
1688
1689 //
1690 // don't need to safely remove
1691 //
1692 IoStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
1693
1694 //
1695 // done
1696 //
1697 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1698 return Status;
1699 }
1700 case IRP_MN_START_DEVICE:
1701 {
1702 //
1703 // prepare irp
1704 //
1705 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1706 IoCopyCurrentIrpStackLocationToNext(Irp);
1707 IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1708
1709 //
1710 // send irp and wait for completion
1711 //
1712 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1713 if (Status == STATUS_PENDING)
1714 {
1715 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1716 Status = Irp->IoStatus.Status;
1717 }
1718
1719 //
1720 // did the device successfully start
1721 //
1722 if (!NT_SUCCESS(Status))
1723 {
1724 //
1725 // failed
1726 //
1727 DPRINT1("HIDUSB: IRP_MN_START_DEVICE failed with %x\n", Status);
1728 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1729 return Status;
1730 }
1731
1732 //
1733 // start device
1734 //
1735 Status = Hid_PnpStart(DeviceObject);
1736
1737 //
1738 // complete request
1739 //
1740 Irp->IoStatus.Status = Status;
1741 DPRINT("[HIDUSB] IRP_MN_START_DEVICE Status %x\n", Status);
1742 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1743 return Status;
1744 }
1745 default:
1746 {
1747 //
1748 // forward and forget request
1749 //
1750 IoSkipCurrentIrpStackLocation(Irp);
1751 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1752 }
1753 }
1754 }
1755
1756 NTSTATUS
1757 NTAPI
1758 HidAddDevice(
1759 IN PDRIVER_OBJECT DriverObject,
1760 IN PDEVICE_OBJECT DeviceObject)
1761 {
1762 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1763 PHID_DEVICE_EXTENSION DeviceExtension;
1764
1765 //
1766 // get device extension
1767 //
1768 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1769 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1770
1771 //
1772 // init event
1773 //
1774 KeInitializeEvent(&HidDeviceExtension->Event, NotificationEvent, FALSE);
1775
1776 //
1777 // done
1778 //
1779 return STATUS_SUCCESS;
1780 }
1781
1782 VOID
1783 NTAPI
1784 Hid_Unload(
1785 IN PDRIVER_OBJECT DriverObject)
1786 {
1787 UNIMPLEMENTED
1788 }
1789
1790
1791 NTSTATUS
1792 NTAPI
1793 DriverEntry(
1794 IN PDRIVER_OBJECT DriverObject,
1795 IN PUNICODE_STRING RegPath)
1796 {
1797 HID_MINIDRIVER_REGISTRATION Registration;
1798 NTSTATUS Status;
1799
1800 //
1801 // initialize driver object
1802 //
1803 DriverObject->MajorFunction[IRP_MJ_CREATE] = HidCreate;
1804 DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidCreate;
1805 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidInternalDeviceControl;
1806 DriverObject->MajorFunction[IRP_MJ_POWER] = HidPower;
1807 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidSystemControl;
1808 DriverObject->MajorFunction[IRP_MJ_PNP] = HidPnp;
1809 DriverObject->DriverExtension->AddDevice = HidAddDevice;
1810 DriverObject->DriverUnload = Hid_Unload;
1811
1812 //
1813 // prepare registration info
1814 //
1815 RtlZeroMemory(&Registration, sizeof(HID_MINIDRIVER_REGISTRATION));
1816
1817 //
1818 // fill in registration info
1819 //
1820 Registration.Revision = HID_REVISION;
1821 Registration.DriverObject = DriverObject;
1822 Registration.RegistryPath = RegPath;
1823 Registration.DeviceExtensionSize = sizeof(HID_USB_DEVICE_EXTENSION);
1824 Registration.DevicesArePolled = FALSE;
1825
1826 //
1827 // register driver
1828 //
1829 Status = HidRegisterMinidriver(&Registration);
1830
1831 //
1832 // informal debug
1833 //
1834 DPRINT("********* HIDUSB *********\n");
1835 DPRINT("HIDUSB Registration Status %x\n", Status);
1836
1837 return Status;
1838 }