- Sync with trunk r58248 to bring the latest changes from Amine (headers) and others...
[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 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 // try with old hid version
655 //
656 BufferLength = HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength;
657 Status = Hid_GetDescriptor(DeviceObject, URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), &Report, &BufferLength, HidDeviceExtension->HidDescriptor->DescriptorList[0].bReportType, 0, 0 /* FIXME*/);
658 if (!NT_SUCCESS(Status))
659 {
660 DPRINT("[HIDUSB] failed to get report descriptor with %x\n", Status);
661 return Status;
662 }
663 }
664
665 //
666 // get current stack location
667 //
668 IoStack = IoGetCurrentIrpStackLocation(Irp);
669 DPRINT("[HIDUSB] GetReportDescriptor: Status %x ReportLength %lu OutputBufferLength %lu TransferredLength %lu\n", Status, HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, BufferLength);
670
671 //
672 // get length to copy
673 //
674 Length = min(IoStack->Parameters.DeviceIoControl.OutputBufferLength, BufferLength);
675 ASSERT(Length);
676
677 //
678 // copy result
679 //
680 RtlCopyMemory(Irp->UserBuffer, Report, Length);
681
682 //
683 // store result length
684 //
685 Irp->IoStatus.Information = Length;
686
687 //
688 // done
689 //
690 return Status;
691
692 }
693
694 NTSTATUS
695 NTAPI
696 HidInternalDeviceControl(
697 IN PDEVICE_OBJECT DeviceObject,
698 IN PIRP Irp)
699 {
700 PIO_STACK_LOCATION IoStack;
701 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
702 PHID_DEVICE_EXTENSION DeviceExtension;
703 PHID_DEVICE_ATTRIBUTES Attributes;
704 ULONG Length;
705 NTSTATUS Status;
706
707 //
708 // get device extension
709 //
710 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
711 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
712
713 //
714 // get current stack location
715 //
716 IoStack = IoGetCurrentIrpStackLocation(Irp);
717
718 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
719 {
720 case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
721 {
722 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_DEVICE_ATTRIBUTES))
723 {
724 //
725 // invalid request
726 //
727 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
728 DPRINT1("[HIDUSB] IOCTL_HID_GET_DEVICE_ATTRIBUTES invalid buffer\n");
729 IoCompleteRequest(Irp, IO_NO_INCREMENT);
730 return STATUS_INVALID_BUFFER_SIZE;
731 }
732 //
733 // store result
734 //
735 DPRINT("[HIDUSB] IOCTL_HID_GET_DEVICE_ATTRIBUTES\n");
736 ASSERT(HidDeviceExtension->DeviceDescriptor);
737 Irp->IoStatus.Information = sizeof(HID_DESCRIPTOR);
738 Attributes = (PHID_DEVICE_ATTRIBUTES)Irp->UserBuffer;
739 Attributes->Size = sizeof(HID_DEVICE_ATTRIBUTES);
740 Attributes->VendorID = HidDeviceExtension->DeviceDescriptor->idVendor;
741 Attributes->ProductID = HidDeviceExtension->DeviceDescriptor->idProduct;
742 Attributes->VersionNumber = HidDeviceExtension->DeviceDescriptor->bcdDevice;
743
744 //
745 // complete request
746 //
747 Irp->IoStatus.Status = STATUS_SUCCESS;
748 IoCompleteRequest(Irp, IO_NO_INCREMENT);
749 return STATUS_SUCCESS;
750 }
751 case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
752 {
753 //
754 // sanity check
755 //
756 ASSERT(HidDeviceExtension->HidDescriptor);
757 DPRINT("[HIDUSB] IOCTL_HID_GET_DEVICE_DESCRIPTOR DescriptorLength %lu OutputBufferLength %lu\n", HidDeviceExtension->HidDescriptor->bLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
758
759 //
760 // store length
761 //
762 Length = min(HidDeviceExtension->HidDescriptor->bLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
763
764 //
765 // copy descriptor
766 //
767 RtlCopyMemory(Irp->UserBuffer, HidDeviceExtension->HidDescriptor, Length);
768
769 //
770 // store result length
771 //
772 Irp->IoStatus.Information = HidDeviceExtension->HidDescriptor->bLength;
773 Irp->IoStatus.Status = STATUS_SUCCESS;
774
775 /* complete request */
776 IoCompleteRequest(Irp, IO_NO_INCREMENT);
777 return STATUS_SUCCESS;
778 }
779 case IOCTL_HID_GET_REPORT_DESCRIPTOR:
780 {
781 Status = HidUsb_GetReportDescriptor(DeviceObject, Irp);
782 DPRINT("[HIDUSB] IOCTL_HID_GET_REPORT_DESCRIPTOR Status %x\n", Status);
783 Irp->IoStatus.Status = Status;
784 IoCompleteRequest(Irp, IO_NO_INCREMENT);
785 return Status;
786 }
787 case IOCTL_HID_READ_REPORT:
788 {
789 DPRINT("[HIDUSB] IOCTL_HID_READ_REPORT\n");
790 Status = HidUsb_ReadReport(DeviceObject, Irp);
791 return Status;
792 }
793 case IOCTL_HID_WRITE_REPORT:
794 {
795 DPRINT1("[HIDUSB] IOCTL_HID_WRITE_REPORT not implemented \n");
796 ASSERT(FALSE);
797 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
798 IoCompleteRequest(Irp, IO_NO_INCREMENT);
799 return STATUS_NOT_IMPLEMENTED;
800 }
801 case IOCTL_GET_PHYSICAL_DESCRIPTOR:
802 {
803 DPRINT1("[HIDUSB] IOCTL_GET_PHYSICAL_DESCRIPTOR not implemented \n");
804 ASSERT(FALSE);
805 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
806 IoCompleteRequest(Irp, IO_NO_INCREMENT);
807 return STATUS_NOT_IMPLEMENTED;
808 }
809 case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
810 {
811 DPRINT1("[HIDUSB] IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST not implemented \n");
812 ASSERT(FALSE);
813 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
814 IoCompleteRequest(Irp, IO_NO_INCREMENT);
815 return STATUS_NOT_IMPLEMENTED;
816 }
817 case IOCTL_HID_GET_FEATURE:
818 {
819 DPRINT1("[HIDUSB] IOCTL_HID_GET_FEATURE not implemented \n");
820 ASSERT(FALSE);
821 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
822 IoCompleteRequest(Irp, IO_NO_INCREMENT);
823 return STATUS_NOT_IMPLEMENTED;
824 }
825 case IOCTL_HID_SET_FEATURE:
826 {
827 DPRINT1("[HIDUSB] IOCTL_HID_SET_FEATURE not implemented \n");
828 ASSERT(FALSE);
829 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
830 IoCompleteRequest(Irp, IO_NO_INCREMENT);
831 return STATUS_NOT_IMPLEMENTED;
832 }
833 case IOCTL_HID_SET_OUTPUT_REPORT:
834 {
835 DPRINT1("[HIDUSB] IOCTL_HID_SET_OUTPUT_REPORT not implemented \n");
836 ASSERT(FALSE);
837 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
838 IoCompleteRequest(Irp, IO_NO_INCREMENT);
839 return STATUS_NOT_IMPLEMENTED;
840 }
841 case IOCTL_HID_GET_INPUT_REPORT:
842 {
843 DPRINT1("[HIDUSB] IOCTL_HID_GET_INPUT_REPORT not implemented \n");
844 ASSERT(FALSE);
845 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
846 IoCompleteRequest(Irp, IO_NO_INCREMENT);
847 return STATUS_NOT_IMPLEMENTED;
848 }
849 case IOCTL_HID_GET_INDEXED_STRING:
850 {
851 DPRINT1("[HIDUSB] IOCTL_HID_GET_INDEXED_STRING not implemented \n");
852 ASSERT(FALSE);
853 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
854 IoCompleteRequest(Irp, IO_NO_INCREMENT);
855 return STATUS_NOT_IMPLEMENTED;
856 }
857 case IOCTL_HID_GET_MS_GENRE_DESCRIPTOR:
858 {
859 DPRINT1("[HIDUSB] IOCTL_HID_GET_MS_GENRE_DESCRIPTOR not implemented \n");
860 ASSERT(FALSE);
861 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
862 IoCompleteRequest(Irp, IO_NO_INCREMENT);
863 return STATUS_NOT_IMPLEMENTED;
864 }
865 default:
866 {
867 UNIMPLEMENTED
868 ASSERT(FALSE);
869 Status = Irp->IoStatus.Status;
870 IoCompleteRequest(Irp, IO_NO_INCREMENT);
871 return Status;
872 }
873 }
874 }
875
876 NTSTATUS
877 NTAPI
878 HidPower(
879 IN PDEVICE_OBJECT DeviceObject,
880 IN PIRP Irp)
881 {
882 UNIMPLEMENTED
883 ASSERT(FALSE);
884 return STATUS_NOT_IMPLEMENTED;
885 }
886
887 NTSTATUS
888 NTAPI
889 HidSystemControl(
890 IN PDEVICE_OBJECT DeviceObject,
891 IN PIRP Irp)
892 {
893 PHID_DEVICE_EXTENSION DeviceExtension;
894
895 //
896 // get hid device extension
897 //
898 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
899
900 //
901 // copy stack location
902 //
903 IoCopyCurrentIrpStackLocationToNext(Irp);
904
905 //
906 // submit request
907 //
908 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
909 }
910
911 NTSTATUS
912 NTAPI
913 Hid_PnpCompletion(
914 IN PDEVICE_OBJECT DeviceObject,
915 IN PIRP Irp,
916 IN PVOID Context)
917 {
918 //
919 // signal event
920 //
921 KeSetEvent((PRKEVENT)Context, 0, FALSE);
922
923 //
924 // done
925 //
926 return STATUS_MORE_PROCESSING_REQUIRED;
927 }
928
929
930 NTSTATUS
931 Hid_DispatchUrb(
932 IN PDEVICE_OBJECT DeviceObject,
933 IN PURB Urb)
934 {
935 PIRP Irp;
936 KEVENT Event;
937 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
938 PHID_DEVICE_EXTENSION DeviceExtension;
939 IO_STATUS_BLOCK IoStatus;
940 PIO_STACK_LOCATION IoStack;
941 NTSTATUS Status;
942
943 //
944 // init event
945 //
946 KeInitializeEvent(&Event, NotificationEvent, FALSE);
947
948 //
949 // get device extension
950 //
951 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
952 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
953
954
955 //
956 // build irp
957 //
958 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, DeviceExtension->NextDeviceObject, NULL, 0, NULL, 0, TRUE, &Event, &IoStatus);
959 if (!Irp)
960 {
961 //
962 // no memory
963 //
964 return STATUS_INSUFFICIENT_RESOURCES;
965 }
966
967 //
968 // get next stack location
969 //
970 IoStack = IoGetNextIrpStackLocation(Irp);
971
972 //
973 // store urb
974 //
975 IoStack->Parameters.Others.Argument1 = (PVOID)Urb;
976
977 //
978 // set completion routine
979 //
980 IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
981
982 //
983 // call driver
984 //
985 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
986
987 //
988 // wait for the request to finish
989 //
990 if (Status == STATUS_PENDING)
991 {
992 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
993 }
994
995 //
996 // complete request
997 //
998 IoCompleteRequest(Irp, IO_NO_INCREMENT);
999
1000 if (Status == STATUS_PENDING)
1001 {
1002 //
1003 // get final status
1004 //
1005 Status = IoStatus.Status;
1006 }
1007
1008 DPRINT("[HIDUSB] DispatchUrb %x\n", Status);
1009
1010
1011 //
1012 // done
1013 //
1014 return Status;
1015 }
1016
1017 NTSTATUS
1018 Hid_GetDescriptor(
1019 IN PDEVICE_OBJECT DeviceObject,
1020 IN USHORT UrbFunction,
1021 IN USHORT UrbLength,
1022 IN OUT PVOID *UrbBuffer,
1023 IN OUT PULONG UrbBufferLength,
1024 IN UCHAR DescriptorType,
1025 IN UCHAR Index,
1026 IN USHORT LanguageIndex)
1027 {
1028 PURB Urb;
1029 NTSTATUS Status;
1030 UCHAR Allocated = FALSE;
1031
1032 //
1033 // allocate urb
1034 //
1035 Urb = (PURB)ExAllocatePool(NonPagedPool, UrbLength);
1036 if (!Urb)
1037 {
1038 //
1039 // no memory
1040 //
1041 return STATUS_INSUFFICIENT_RESOURCES;
1042 }
1043
1044 //
1045 // is there an urb buffer
1046 //
1047 if (!*UrbBuffer)
1048 {
1049 //
1050 // allocate buffer
1051 //
1052 *UrbBuffer = ExAllocatePool(NonPagedPool, *UrbBufferLength);
1053 if (!*UrbBuffer)
1054 {
1055 //
1056 // no memory
1057 //
1058 ExFreePool(Urb);
1059 return STATUS_INSUFFICIENT_RESOURCES;
1060 }
1061
1062 //
1063 // zero buffer
1064 //
1065 RtlZeroMemory(*UrbBuffer, *UrbBufferLength);
1066 Allocated = TRUE;
1067 }
1068
1069 //
1070 // zero urb
1071 //
1072 RtlZeroMemory(Urb, UrbLength);
1073
1074 //
1075 // build descriptor request
1076 //
1077 UsbBuildGetDescriptorRequest(Urb, UrbLength, DescriptorType, Index, LanguageIndex, *UrbBuffer, NULL, *UrbBufferLength, NULL);
1078
1079 //
1080 // set urb function
1081 //
1082 Urb->UrbHeader.Function = UrbFunction;
1083
1084 //
1085 // dispatch urb
1086 //
1087 Status = Hid_DispatchUrb(DeviceObject, Urb);
1088
1089 //
1090 // did the request fail
1091 //
1092 if (!NT_SUCCESS(Status))
1093 {
1094 if (Allocated)
1095 {
1096 //
1097 // free allocated buffer
1098 //
1099 ExFreePool(*UrbBuffer);
1100 *UrbBuffer = NULL;
1101 }
1102
1103 //
1104 // free urb
1105 //
1106 ExFreePool(Urb);
1107 *UrbBufferLength = 0;
1108 return Status;
1109 }
1110
1111 //
1112 // did urb request fail
1113 //
1114 if (!NT_SUCCESS(Urb->UrbHeader.Status))
1115 {
1116 if (Allocated)
1117 {
1118 //
1119 // free allocated buffer
1120 //
1121 ExFreePool(*UrbBuffer);
1122 *UrbBuffer = NULL;
1123 }
1124
1125 //
1126 // free urb
1127 //
1128 ExFreePool(Urb);
1129 *UrbBufferLength = 0;
1130 return STATUS_UNSUCCESSFUL;
1131 }
1132
1133 //
1134 // store result length
1135 //
1136 *UrbBufferLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
1137
1138 //
1139 // free urb
1140 //
1141 ExFreePool(Urb);
1142
1143 //
1144 // completed successfully
1145 //
1146 return STATUS_SUCCESS;
1147 }
1148
1149 NTSTATUS
1150 Hid_SelectConfiguration(
1151 IN PDEVICE_OBJECT DeviceObject)
1152 {
1153 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1154 NTSTATUS Status;
1155 USBD_INTERFACE_LIST_ENTRY InterfaceList[2];
1156 PURB Urb;
1157 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1158 PHID_DEVICE_EXTENSION DeviceExtension;
1159
1160 //
1161 // get device extension
1162 //
1163 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1164 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1165
1166 //
1167 // now parse the descriptors
1168 //
1169 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(HidDeviceExtension->ConfigurationDescriptor,
1170 HidDeviceExtension->ConfigurationDescriptor,
1171 -1,
1172 -1,
1173 USB_DEVICE_CLASS_HUMAN_INTERFACE,
1174 -1,
1175 -1);
1176 if (!InterfaceDescriptor)
1177 {
1178 //
1179 // bogus configuration descriptor
1180 //
1181 return STATUS_INVALID_PARAMETER;
1182 }
1183
1184 //
1185 // sanity check
1186 //
1187 ASSERT(InterfaceDescriptor);
1188 ASSERT(InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_HUMAN_INTERFACE);
1189 ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
1190 ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
1191
1192 //
1193 // setup interface list
1194 //
1195 RtlZeroMemory(InterfaceList, sizeof(InterfaceList));
1196 InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor;
1197
1198 //
1199 // build urb
1200 //
1201 Urb = USBD_CreateConfigurationRequestEx(HidDeviceExtension->ConfigurationDescriptor, InterfaceList);
1202 if (!Urb)
1203 {
1204 //
1205 // no memory
1206 //
1207 return STATUS_INSUFFICIENT_RESOURCES;
1208 }
1209
1210 //
1211 // dispatch request
1212 //
1213 Status = Hid_DispatchUrb(DeviceObject, Urb);
1214 if (NT_SUCCESS(Status))
1215 {
1216 //
1217 // store configuration handle
1218 //
1219 HidDeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
1220
1221 //
1222 // copy interface info
1223 //
1224 HidDeviceExtension->InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)ExAllocatePool(NonPagedPool, Urb->UrbSelectConfiguration.Interface.Length);
1225 if (HidDeviceExtension->InterfaceInfo)
1226 {
1227 //
1228 // copy interface info
1229 //
1230 RtlCopyMemory(HidDeviceExtension->InterfaceInfo, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length);
1231 }
1232 }
1233
1234 //
1235 // free urb request
1236 //
1237 ExFreePool(Urb);
1238
1239 //
1240 // done
1241 //
1242 return Status;
1243 }
1244
1245 NTSTATUS
1246 Hid_SetIdle(
1247 IN PDEVICE_OBJECT DeviceObject)
1248 {
1249 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1250 PHID_DEVICE_EXTENSION DeviceExtension;
1251 PURB Urb;
1252 NTSTATUS Status;
1253
1254 //
1255 // get device extension
1256 //
1257 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1258 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1259
1260 //
1261 // allocate urb
1262 //
1263 Urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
1264 if (!Urb)
1265 {
1266 //
1267 // no memory
1268 //
1269 return STATUS_INSUFFICIENT_RESOURCES;
1270 }
1271
1272 //
1273 // zero urb
1274 //
1275 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
1276
1277 //
1278 // format urb
1279 //
1280 UsbBuildVendorRequest(Urb,
1281 URB_FUNCTION_CLASS_INTERFACE,
1282 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
1283 0,
1284 0,
1285 USB_SET_IDLE_REQUEST, // HID_SET_IDLE
1286 0,
1287 0,
1288 NULL,
1289 NULL,
1290 0,
1291 NULL);
1292
1293 //
1294 // dispatch urb
1295 //
1296 Status = Hid_DispatchUrb(DeviceObject, Urb);
1297
1298 //
1299 // free urb
1300 //
1301 ExFreePool(Urb);
1302
1303 //
1304 // print status
1305 //
1306 DPRINT1("Status %x\n", Status);
1307 return Status;
1308 }
1309
1310
1311 VOID
1312 Hid_GetProtocol(
1313 IN PDEVICE_OBJECT DeviceObject)
1314 {
1315 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1316 PHID_DEVICE_EXTENSION DeviceExtension;
1317 PURB Urb;
1318 NTSTATUS Status;
1319 UCHAR Protocol[1];
1320
1321 //
1322 // get device extension
1323 //
1324 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1325 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1326 ASSERT(HidDeviceExtension->InterfaceInfo);
1327
1328 if (HidDeviceExtension->InterfaceInfo->SubClass != 0x1)
1329 {
1330 //
1331 // device does not support the boot protocol
1332 //
1333 return;
1334 }
1335
1336
1337 //
1338 // allocate urb
1339 //
1340 Urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
1341 if (!Urb)
1342 {
1343 //
1344 // no memory
1345 //
1346 return;
1347 }
1348
1349 //
1350 // zero urb
1351 //
1352 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
1353
1354 //
1355 // format urb
1356 //
1357 UsbBuildVendorRequest(Urb,
1358 URB_FUNCTION_CLASS_INTERFACE,
1359 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
1360 USBD_TRANSFER_DIRECTION_IN,
1361 0,
1362 USB_GET_PROTOCOL_REQUEST,
1363 0,
1364 0,
1365 Protocol,
1366 NULL,
1367 1,
1368 NULL);
1369 Protocol[0] = 0xFF;
1370 //
1371 // dispatch urb
1372 //
1373 Status = Hid_DispatchUrb(DeviceObject, Urb);
1374
1375 //
1376 // free urb
1377 //
1378 ExFreePool(Urb);
1379
1380 //
1381 // boot protocol active 0x00 disabled 0x1
1382 //
1383 if (Protocol[0] != 0x1)
1384 {
1385 if (Protocol[0] == 0x00)
1386 {
1387 DPRINT1("[HIDUSB] Need to disable boot protocol!\n");
1388 }
1389 else
1390 {
1391 DPRINT1("[HIDUSB] Unexpected protocol value %x\n", Protocol[0] & 0xFF);
1392 }
1393 }
1394 }
1395
1396 NTSTATUS
1397 Hid_PnpStart(
1398 IN PDEVICE_OBJECT DeviceObject)
1399 {
1400 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1401 PHID_DEVICE_EXTENSION DeviceExtension;
1402 NTSTATUS Status;
1403 ULONG DescriptorLength;
1404 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1405 PHID_DESCRIPTOR HidDescriptor;
1406
1407 //
1408 // get device extension
1409 //
1410 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1411 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1412
1413 //
1414 // get device descriptor
1415 //
1416 DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR);
1417 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);
1418 if (!NT_SUCCESS(Status))
1419 {
1420 //
1421 // failed to obtain device descriptor
1422 //
1423 DPRINT1("[HIDUSB] failed to get device descriptor %x\n", Status);
1424 return Status;
1425 }
1426
1427 //
1428 // now get the configuration descriptor
1429 //
1430 DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
1431 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);
1432 if (!NT_SUCCESS(Status))
1433 {
1434 //
1435 // failed to obtain device descriptor
1436 //
1437 DPRINT1("[HIDUSB] failed to get device descriptor %x\n", Status);
1438 return Status;
1439 }
1440
1441 //
1442 // sanity check
1443 //
1444 ASSERT(DescriptorLength);
1445 ASSERT(HidDeviceExtension->ConfigurationDescriptor);
1446 ASSERT(HidDeviceExtension->ConfigurationDescriptor->bLength);
1447
1448 //
1449 // store full length
1450 //
1451 DescriptorLength = HidDeviceExtension->ConfigurationDescriptor->wTotalLength;
1452
1453 //
1454 // delete partial configuration descriptor
1455 //
1456 ExFreePool(HidDeviceExtension->ConfigurationDescriptor);
1457 HidDeviceExtension->ConfigurationDescriptor = NULL;
1458
1459 //
1460 // get full configuration descriptor
1461 //
1462 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);
1463 if (!NT_SUCCESS(Status))
1464 {
1465 //
1466 // failed to obtain device descriptor
1467 //
1468 DPRINT1("[HIDUSB] failed to get device descriptor %x\n", Status);
1469 return Status;
1470 }
1471
1472 //
1473 // now parse the descriptors
1474 //
1475 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(HidDeviceExtension->ConfigurationDescriptor,
1476 HidDeviceExtension->ConfigurationDescriptor,
1477 -1,
1478 -1,
1479 USB_DEVICE_CLASS_HUMAN_INTERFACE,
1480 -1,
1481 -1);
1482 if (!InterfaceDescriptor)
1483 {
1484 //
1485 // no interface class
1486 //
1487 DPRINT1("[HIDUSB] HID Interface descriptor not found\n");
1488 return STATUS_UNSUCCESSFUL;
1489 }
1490
1491 //
1492 // sanity check
1493 //
1494 ASSERT(InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_HUMAN_INTERFACE);
1495 ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
1496 ASSERT(InterfaceDescriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
1497
1498 //
1499 // move to next descriptor
1500 //
1501 HidDescriptor = (PHID_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
1502 ASSERT(HidDescriptor->bLength >= 2);
1503
1504 //
1505 // check if this is the hid descriptor
1506 //
1507 if (HidDescriptor->bLength == sizeof(HID_DESCRIPTOR) && HidDescriptor->bDescriptorType == HID_HID_DESCRIPTOR_TYPE)
1508 {
1509 //
1510 // found
1511 //
1512 HidDeviceExtension->HidDescriptor = HidDescriptor;
1513
1514 //
1515 // select configuration
1516 //
1517 Status = Hid_SelectConfiguration(DeviceObject);
1518
1519 //
1520 // done
1521 //
1522 DPRINT1("[HIDUSB] SelectConfiguration %x\n", Status);
1523
1524 if (NT_SUCCESS(Status))
1525 {
1526 //
1527 // now set the device idle
1528 //
1529 Hid_SetIdle(DeviceObject);
1530
1531 //
1532 // get protocol
1533 //
1534 Hid_GetProtocol(DeviceObject);
1535 return Status;
1536 }
1537 }
1538 else
1539 {
1540 //
1541 // FIXME parse hid descriptor
1542 // select configuration
1543 // set idle
1544 // and get protocol
1545 //
1546 UNIMPLEMENTED
1547 ASSERT(FALSE);
1548 }
1549 return Status;
1550 }
1551
1552
1553 NTSTATUS
1554 NTAPI
1555 HidPnp(
1556 IN PDEVICE_OBJECT DeviceObject,
1557 IN PIRP Irp)
1558 {
1559 NTSTATUS Status;
1560 PIO_STACK_LOCATION IoStack;
1561 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1562 PHID_DEVICE_EXTENSION DeviceExtension;
1563 KEVENT Event;
1564
1565 //
1566 // get device extension
1567 //
1568 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1569 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1570
1571 //
1572 // get current stack location
1573 //
1574 IoStack = IoGetCurrentIrpStackLocation(Irp);
1575 DPRINT("[HIDUSB] Pnp %x\n", IoStack->MinorFunction);
1576
1577 //
1578 // handle requests based on request type
1579 //
1580 switch(IoStack->MinorFunction)
1581 {
1582 case IRP_MN_REMOVE_DEVICE:
1583 {
1584 //
1585 // pass request onto lower driver
1586 //
1587 IoSkipCurrentIrpStackLocation(Irp);
1588 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1589
1590 //
1591 // free resources
1592 //
1593 if (HidDeviceExtension->ConfigurationDescriptor)
1594 {
1595 ExFreePool(HidDeviceExtension->ConfigurationDescriptor);
1596 HidDeviceExtension->ConfigurationDescriptor = NULL;
1597 }
1598
1599 //
1600 // delete and detach device
1601 //
1602 IoDetachDevice(DeviceExtension->NextDeviceObject);
1603 IoDeleteDevice(DeviceObject);
1604
1605 return Status;
1606 }
1607 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1608 {
1609 //
1610 // device can not be disabled
1611 //
1612 Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
1613
1614 //
1615 // pass request to next request
1616 //
1617 IoSkipCurrentIrpStackLocation(Irp);
1618 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1619
1620 //
1621 // done
1622 //
1623 return Status;
1624 }
1625 case IRP_MN_QUERY_STOP_DEVICE:
1626 case IRP_MN_QUERY_REMOVE_DEVICE:
1627 {
1628 //
1629 // we're fine with it
1630 //
1631 Irp->IoStatus.Status = STATUS_SUCCESS;
1632
1633 //
1634 // pass request to next driver
1635 //
1636 IoSkipCurrentIrpStackLocation(Irp);
1637 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1638
1639 //
1640 // done
1641 //
1642 return Status;
1643 }
1644 case IRP_MN_STOP_DEVICE:
1645 {
1646 //
1647 // FIXME: unconfigure the device
1648 //
1649
1650 //
1651 // prepare irp
1652 //
1653 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1654 IoCopyCurrentIrpStackLocationToNext(Irp);
1655 IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1656
1657 //
1658 // send irp and wait for completion
1659 //
1660 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1661 if (Status == STATUS_PENDING)
1662 {
1663 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1664 Status = Irp->IoStatus.Status;
1665 }
1666
1667 //
1668 // free resources
1669 //
1670 if (HidDeviceExtension->HidDescriptor)
1671 {
1672 ExFreePool(HidDeviceExtension->HidDescriptor);
1673 HidDeviceExtension->HidDescriptor = NULL;
1674 }
1675
1676 //
1677 // done
1678 //
1679 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1680 return Status;
1681 }
1682 case IRP_MN_QUERY_CAPABILITIES:
1683 {
1684 //
1685 // prepare irp
1686 //
1687 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1688 IoCopyCurrentIrpStackLocationToNext(Irp);
1689 IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1690
1691 //
1692 // send irp and wait for completion
1693 //
1694 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1695 if (Status == STATUS_PENDING)
1696 {
1697 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1698 Status = Irp->IoStatus.Status;
1699 }
1700
1701 if (NT_SUCCESS(Status) && IoStack->Parameters.DeviceCapabilities.Capabilities != NULL)
1702 {
1703 //
1704 // don't need to safely remove
1705 //
1706 IoStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
1707 }
1708
1709 //
1710 // done
1711 //
1712 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1713 return Status;
1714 }
1715 case IRP_MN_START_DEVICE:
1716 {
1717 //
1718 // prepare irp
1719 //
1720 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1721 IoCopyCurrentIrpStackLocationToNext(Irp);
1722 IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1723
1724 //
1725 // send irp and wait for completion
1726 //
1727 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1728 if (Status == STATUS_PENDING)
1729 {
1730 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1731 Status = Irp->IoStatus.Status;
1732 }
1733
1734 //
1735 // did the device successfully start
1736 //
1737 if (!NT_SUCCESS(Status))
1738 {
1739 //
1740 // failed
1741 //
1742 DPRINT1("HIDUSB: IRP_MN_START_DEVICE failed with %x\n", Status);
1743 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1744 return Status;
1745 }
1746
1747 //
1748 // start device
1749 //
1750 Status = Hid_PnpStart(DeviceObject);
1751
1752 //
1753 // complete request
1754 //
1755 Irp->IoStatus.Status = Status;
1756 DPRINT("[HIDUSB] IRP_MN_START_DEVICE Status %x\n", Status);
1757 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1758 return Status;
1759 }
1760 default:
1761 {
1762 //
1763 // forward and forget request
1764 //
1765 IoSkipCurrentIrpStackLocation(Irp);
1766 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
1767 }
1768 }
1769 }
1770
1771 NTSTATUS
1772 NTAPI
1773 HidAddDevice(
1774 IN PDRIVER_OBJECT DriverObject,
1775 IN PDEVICE_OBJECT DeviceObject)
1776 {
1777 PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
1778 PHID_DEVICE_EXTENSION DeviceExtension;
1779
1780 //
1781 // get device extension
1782 //
1783 DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1784 HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
1785
1786 //
1787 // init event
1788 //
1789 KeInitializeEvent(&HidDeviceExtension->Event, NotificationEvent, FALSE);
1790
1791 //
1792 // done
1793 //
1794 return STATUS_SUCCESS;
1795 }
1796
1797 VOID
1798 NTAPI
1799 Hid_Unload(
1800 IN PDRIVER_OBJECT DriverObject)
1801 {
1802 UNIMPLEMENTED
1803 }
1804
1805
1806 NTSTATUS
1807 NTAPI
1808 DriverEntry(
1809 IN PDRIVER_OBJECT DriverObject,
1810 IN PUNICODE_STRING RegPath)
1811 {
1812 HID_MINIDRIVER_REGISTRATION Registration;
1813 NTSTATUS Status;
1814
1815 //
1816 // initialize driver object
1817 //
1818 DriverObject->MajorFunction[IRP_MJ_CREATE] = HidCreate;
1819 DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidCreate;
1820 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidInternalDeviceControl;
1821 DriverObject->MajorFunction[IRP_MJ_POWER] = HidPower;
1822 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidSystemControl;
1823 DriverObject->MajorFunction[IRP_MJ_PNP] = HidPnp;
1824 DriverObject->DriverExtension->AddDevice = HidAddDevice;
1825 DriverObject->DriverUnload = Hid_Unload;
1826
1827 //
1828 // prepare registration info
1829 //
1830 RtlZeroMemory(&Registration, sizeof(HID_MINIDRIVER_REGISTRATION));
1831
1832 //
1833 // fill in registration info
1834 //
1835 Registration.Revision = HID_REVISION;
1836 Registration.DriverObject = DriverObject;
1837 Registration.RegistryPath = RegPath;
1838 Registration.DeviceExtensionSize = sizeof(HID_USB_DEVICE_EXTENSION);
1839 Registration.DevicesArePolled = FALSE;
1840
1841 //
1842 // register driver
1843 //
1844 Status = HidRegisterMinidriver(&Registration);
1845
1846 //
1847 // informal debug
1848 //
1849 DPRINT("********* HIDUSB *********\n");
1850 DPRINT("HIDUSB Registration Status %x\n", Status);
1851
1852 return Status;
1853 }