22d06979ce2e9f9dd2e6cf6115816c07aee180ee
[reactos.git] / drivers / usb / usbccgp / pdo.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbccgp/pdo.c
5 * PURPOSE: USB device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 * Cameron Gutman
10 */
11
12 #include "usbccgp.h"
13
14 NTSTATUS
15 USBCCGP_PdoHandleQueryDeviceText(
16 IN PDEVICE_OBJECT DeviceObject,
17 IN OUT PIRP Irp)
18 {
19 LPWSTR Buffer;
20 PPDO_DEVICE_EXTENSION PDODeviceExtension;
21 LPWSTR GenericString = L"Composite USB Device";
22 //
23 // get device extension
24 //
25 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
26
27 //
28 // is there a device description
29 //
30 if (PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length)
31 {
32 //
33 // allocate buffer
34 //
35 Buffer = AllocateItem(NonPagedPool, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length + sizeof(WCHAR));
36 if (!Buffer)
37 {
38 //
39 // no memory
40 //
41 return STATUS_INSUFFICIENT_RESOURCES;
42 }
43
44 //
45 // copy buffer
46 //
47 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
48 RtlCopyMemory(Buffer, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Buffer, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length);
49 return STATUS_SUCCESS;
50 }
51
52 //
53 // FIXME use GenericCompositeUSBDeviceString
54 //
55 UNIMPLEMENTED
56 Buffer = AllocateItem(PagedPool, (wcslen(GenericString) + 1) * sizeof(WCHAR));
57 if (!Buffer)
58 {
59 //
60 // no memory
61 //
62 return STATUS_INSUFFICIENT_RESOURCES;
63 }
64 RtlCopyMemory(Buffer, GenericString, (wcslen(GenericString) + 1) * sizeof(WCHAR));
65 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
66
67 return STATUS_SUCCESS;
68 }
69
70 NTSTATUS
71 USBCCGP_PdoHandleDeviceRelations(
72 IN PDEVICE_OBJECT DeviceObject,
73 IN OUT PIRP Irp)
74 {
75 PDEVICE_RELATIONS DeviceRelations;
76 PIO_STACK_LOCATION IoStack;
77
78 DPRINT1("USBCCGP_PdoHandleDeviceRelations\n");
79
80 //
81 // get current irp stack location
82 //
83 IoStack = IoGetCurrentIrpStackLocation(Irp);
84
85 //
86 // check if relation type is BusRelations
87 //
88 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
89 {
90 //
91 // PDO handles only target device relation
92 //
93 return Irp->IoStatus.Status;
94 }
95
96 //
97 // allocate device relations
98 //
99 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
100 if (!DeviceRelations)
101 {
102 //
103 // no memory
104 //
105 return STATUS_INSUFFICIENT_RESOURCES;
106 }
107
108 //
109 // initialize device relations
110 //
111 DeviceRelations->Count = 1;
112 DeviceRelations->Objects[0] = DeviceObject;
113 ObReferenceObject(DeviceObject);
114
115 //
116 // store result
117 //
118 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
119
120 //
121 // completed successfully
122 //
123 return STATUS_SUCCESS;
124 }
125
126 NTSTATUS
127 USBCCGP_PdoAppendInterfaceNumber(
128 IN LPWSTR DeviceId,
129 IN ULONG InterfaceNumber,
130 OUT LPWSTR *OutString)
131 {
132 ULONG Length = 0, StringLength;
133 LPWSTR String;
134
135 //
136 // count length of string
137 //
138 String = DeviceId;
139 while(*String)
140 {
141 StringLength = wcslen(String) + 1;
142 Length += StringLength;
143 Length += 6; //&MI_XX
144 String += StringLength;
145 }
146
147 //
148 // now allocate the buffer
149 //
150 String = AllocateItem(NonPagedPool, (Length + 2) * sizeof(WCHAR));
151 if (!String)
152 {
153 //
154 // no memory
155 //
156 return STATUS_INSUFFICIENT_RESOURCES;
157 }
158
159 //
160 // store result
161 //
162 *OutString = String;
163
164 while(*DeviceId)
165 {
166 StringLength = swprintf(String, L"%s&MI_%02x", DeviceId) + 1;
167 Length = wcslen(DeviceId) + 1;
168 DPRINT1("String %p\n", String);
169
170 //
171 // next string
172 //
173 String += StringLength;
174 DeviceId += Length;
175 }
176
177 //
178 // success
179 //
180 return STATUS_SUCCESS;
181 }
182
183
184 NTSTATUS
185 USBCCGP_PdoHandleQueryId(
186 PDEVICE_OBJECT DeviceObject,
187 PIRP Irp)
188 {
189 PIO_STACK_LOCATION IoStack;
190 PUNICODE_STRING DeviceString = NULL;
191 PPDO_DEVICE_EXTENSION PDODeviceExtension;
192 NTSTATUS Status;
193 LPWSTR Buffer;
194
195 //
196 // get current irp stack location
197 //
198 IoStack = IoGetCurrentIrpStackLocation(Irp);
199
200 //
201 // get device extension
202 //
203 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
204
205
206 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
207 {
208 //
209 // handle query device id
210 //
211 Status = USBCCGP_SyncForwardIrp(PDODeviceExtension->NextDeviceObject, Irp);
212 if (NT_SUCCESS(Status))
213 {
214 //
215 // allocate buffer
216 //
217 Buffer = AllocateItem(NonPagedPool, (wcslen((LPWSTR)Irp->IoStatus.Information) + 7) * sizeof(WCHAR));
218 if (Buffer)
219 {
220 //
221 // append interface number
222 //
223 ASSERT(Irp->IoStatus.Information);
224 swprintf(Buffer, L"%s&MI_%02x", (LPWSTR)Irp->IoStatus.Information, PDODeviceExtension->FunctionDescriptor->FunctionNumber);
225 DPRINT1("BusQueryDeviceID %S\n", Buffer);
226
227 ExFreePool((PVOID)Irp->IoStatus.Information);
228 Irp->IoStatus .Information = (ULONG_PTR)Buffer;
229 }
230 else
231 {
232 //
233 // no memory
234 //
235 Status = STATUS_INSUFFICIENT_RESOURCES;
236 }
237 }
238 return Status;
239 }
240 else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
241 {
242 //
243 // handle instance id
244 //
245 DeviceString = &PDODeviceExtension->FunctionDescriptor->HardwareId;
246 }
247 else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
248 {
249 //
250 // handle instance id
251 //
252 Buffer = AllocateItem(NonPagedPool, 5 * sizeof(WCHAR));
253 if (!Buffer)
254 {
255 //
256 // no memory
257 //
258 return STATUS_INSUFFICIENT_RESOURCES;
259 }
260
261 //
262 // use function number
263 //
264 swprintf(Buffer, L"%04x", PDODeviceExtension->FunctionDescriptor->FunctionNumber);
265 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
266 return STATUS_SUCCESS;
267 }
268 else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
269 {
270 //
271 // handle instance id
272 //
273 DeviceString = &PDODeviceExtension->FunctionDescriptor->CompatibleId;
274 }
275
276 //
277 // sanity check
278 //
279 ASSERT(DeviceString != NULL);
280
281 //
282 // allocate buffer
283 //
284 Buffer = AllocateItem(NonPagedPool, DeviceString->Length + sizeof(WCHAR));
285 if (!Buffer)
286 {
287 //
288 // no memory
289 //
290 return STATUS_INSUFFICIENT_RESOURCES;
291 }
292
293 //
294 // copy buffer
295 //
296 RtlCopyMemory(Buffer, DeviceString->Buffer, DeviceString->Length);
297 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
298
299 return STATUS_SUCCESS;
300 }
301
302 NTSTATUS
303 PDO_HandlePnp(
304 PDEVICE_OBJECT DeviceObject,
305 PIRP Irp)
306 {
307 PIO_STACK_LOCATION IoStack;
308 PPDO_DEVICE_EXTENSION PDODeviceExtension;
309 NTSTATUS Status;
310
311 //
312 // get current stack location
313 //
314 IoStack = IoGetCurrentIrpStackLocation(Irp);
315
316 //
317 // get device extension
318 //
319 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
320
321 //
322 // sanity check
323 //
324 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
325
326 switch(IoStack->MinorFunction)
327 {
328 case IRP_MN_QUERY_DEVICE_RELATIONS:
329 {
330 //
331 // handle device relations
332 //
333 Status = USBCCGP_PdoHandleDeviceRelations(DeviceObject, Irp);
334 break;
335 }
336 case IRP_MN_QUERY_DEVICE_TEXT:
337 {
338 //
339 // handle query device text
340 //
341 Status = USBCCGP_PdoHandleQueryDeviceText(DeviceObject, Irp);
342 break;
343 }
344 case IRP_MN_QUERY_ID:
345 {
346 //
347 // handle request
348 //
349 Status = USBCCGP_PdoHandleQueryId(DeviceObject, Irp);
350 break;
351 }
352 case IRP_MN_REMOVE_DEVICE:
353 {
354 DPRINT1("IRP_MN_REMOVE_DEVICE\n");
355
356 /* Complete the IRP */
357 Irp->IoStatus.Status = STATUS_SUCCESS;
358 IoCompleteRequest(Irp, IO_NO_INCREMENT);
359
360 /* Delete the device object */
361 IoDeleteDevice(DeviceObject);
362
363 return STATUS_SUCCESS;
364 }
365 case IRP_MN_QUERY_CAPABILITIES:
366 {
367 //
368 // copy device capabilities
369 //
370 RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &PDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
371
372 /* Complete the IRP */
373 Irp->IoStatus.Status = STATUS_SUCCESS;
374 IoCompleteRequest(Irp, IO_NO_INCREMENT);
375 return STATUS_SUCCESS;
376 }
377 case IRP_MN_START_DEVICE:
378 {
379 //
380 // no-op for PDO
381 //
382 DPRINT1("[USBCCGP] PDO IRP_MN_START\n");
383 Status = STATUS_SUCCESS;
384 break;
385 }
386 default:
387 {
388 //
389 // do nothing
390 //
391 Status = Irp->IoStatus.Status;
392 }
393 }
394
395 //
396 // complete request
397 //
398 if (Status != STATUS_PENDING)
399 {
400 //
401 // store result
402 //
403 Irp->IoStatus.Status = Status;
404
405 //
406 // complete request
407 //
408 IoCompleteRequest(Irp, IO_NO_INCREMENT);
409 }
410
411 //
412 // done processing
413 //
414 return Status;
415
416 }
417
418 NTSTATUS
419 USBCCGP_BuildConfigurationDescriptor(
420 PDEVICE_OBJECT DeviceObject,
421 PIRP Irp)
422 {
423 PIO_STACK_LOCATION IoStack;
424 PPDO_DEVICE_EXTENSION PDODeviceExtension;
425 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
426 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
427 ULONG TotalSize, Index;
428 PURB Urb;
429 PVOID Buffer;
430 PUCHAR BufferPtr;
431
432 //
433 // get current stack location
434 //
435 IoStack = IoGetCurrentIrpStackLocation(Irp);
436
437 DPRINT1("USBCCGP_BuildConfigurationDescriptor\n");
438
439 //
440 // get device extension
441 //
442 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
443
444 //
445 // get configuration descriptor
446 //
447 ConfigurationDescriptor = PDODeviceExtension->ConfigurationDescriptor;
448
449 //
450 // calculate size of configuration descriptor
451 //
452 TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
453
454 for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
455 {
456 //
457 // get current interface descriptor
458 //
459 InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
460
461 //
462 // add to size and move to next descriptor
463 //
464 TotalSize += InterfaceDescriptor->bLength;
465 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
466
467 do
468 {
469 if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
470 {
471 //
472 // reached end of configuration descriptor
473 //
474 break;
475 }
476
477 //
478 // association descriptors are removed
479 //
480 if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
481 {
482 if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
483 {
484 //
485 // reached next descriptor
486 //
487 break;
488 }
489
490 //
491 // append size
492 //
493 TotalSize += InterfaceDescriptor->bLength;
494 }
495
496 //
497 // move to next descriptor
498 //
499 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
500 }while(TRUE);
501 }
502
503 //
504 // now allocate temporary buffer for the configuration descriptor
505 //
506 Buffer = AllocateItem(NonPagedPool, TotalSize);
507 if (!Buffer)
508 {
509 //
510 // failed to allocate buffer
511 //
512 DPRINT1("[USBCCGP] Failed to allocate %lu Bytes\n", TotalSize);
513 return STATUS_INSUFFICIENT_RESOURCES;
514 }
515
516 //
517 // first copy the configuration descriptor
518 //
519 RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
520 BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength);
521
522 for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
523 {
524 //
525 // get current interface descriptor
526 //
527 InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
528
529 //
530 // copy descriptor and move to next descriptor
531 //
532 RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
533 BufferPtr += InterfaceDescriptor->bLength;
534 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
535
536 do
537 {
538 if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
539 {
540 //
541 // reached end of configuration descriptor
542 //
543 break;
544 }
545
546 //
547 // association descriptors are removed
548 //
549 if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
550 {
551 if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
552 {
553 //
554 // reached next descriptor
555 //
556 break;
557 }
558
559 //
560 // copy descriptor
561 //
562 RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
563 BufferPtr += InterfaceDescriptor->bLength;
564 }
565
566 //
567 // move to next descriptor
568 //
569 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
570 }while(TRUE);
571 }
572
573 //
574 // modify configuration descriptor
575 //
576 ConfigurationDescriptor = Buffer;
577 ConfigurationDescriptor->wTotalLength = TotalSize;
578 ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces;
579
580 //
581 // get urb
582 //
583 Urb = (PURB)IoStack->Parameters.Others.Argument1;
584 ASSERT(Urb);
585
586 //
587 // copy descriptor
588 //
589 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength));
590
591 //
592 // store final size
593 //
594 Urb->UrbControlDescriptorRequest.TransferBufferLength = TotalSize;
595
596 //
597 // free buffer
598 //
599 FreeItem(Buffer);
600
601 //
602 // done
603 //
604 return STATUS_SUCCESS;
605 }
606
607 NTSTATUS
608 USBCCGP_PDOSelectConfiguration(
609 PDEVICE_OBJECT DeviceObject,
610 PIRP Irp)
611 {
612 PIO_STACK_LOCATION IoStack;
613 PPDO_DEVICE_EXTENSION PDODeviceExtension;
614 PURB Urb, NewUrb;
615 PUSBD_INTERFACE_INFORMATION InterfaceInformation;
616 ULONG InterfaceInformationCount, Index, InterfaceIndex;
617 PUSBD_INTERFACE_LIST_ENTRY Entry;
618 ULONG NeedSelect, FoundInterface;
619 NTSTATUS Status;
620
621 //
622 // get current stack location
623 //
624 IoStack = IoGetCurrentIrpStackLocation(Irp);
625
626 //
627 // get device extension
628 //
629 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
630
631 //
632 // get urb
633 //
634 Urb = (PURB)IoStack->Parameters.Others.Argument1;
635 ASSERT(Urb);
636
637 //
638 // is there already an configuration handle
639 //
640 if (Urb->UrbSelectConfiguration.ConfigurationHandle)
641 {
642 //
643 // nothing to do
644 //
645 return STATUS_SUCCESS;
646 }
647
648 //
649 // count interface information
650 //
651 InterfaceInformationCount = 0;
652 InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
653 do
654 {
655 InterfaceInformationCount++;
656 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
657 }while((ULONG_PTR)InterfaceInformation < (ULONG_PTR)Urb + Urb->UrbSelectConfiguration.Hdr.Length);
658
659 //
660 // check all interfaces
661 //
662 InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
663 Index = 0;
664 Entry = NULL;
665 DPRINT1("Count %x\n", InterfaceInformationCount);
666 do
667 {
668 DPRINT1("[USBCCGP] SelectConfiguration Function %x InterfaceNumber %x Alternative %x\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
669
670 //
671 // search for the interface in the local interface list
672 //
673 FoundInterface = FALSE;
674 for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; InterfaceIndex++)
675 {
676 if (PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[InterfaceIndex]->bInterfaceNumber == InterfaceInformation->InterfaceNumber)
677 {
678 // found interface entry
679 FoundInterface = TRUE;
680 break;
681 }
682 }
683
684 if (!FoundInterface)
685 {
686 //
687 // invalid parameter
688 //
689 DPRINT1("InterfaceInformation InterfaceNumber %x Alternative %x NumberOfPipes %x not found\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
690 ASSERT(FALSE);
691 return STATUS_INVALID_PARAMETER;
692 }
693
694 //
695 // now query the total interface list
696 //
697 Entry = NULL;
698 for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->InterfaceListCount; InterfaceIndex++)
699 {
700 if (PDODeviceExtension->InterfaceList[InterfaceIndex].Interface->InterfaceNumber == InterfaceInformation->InterfaceNumber)
701 {
702 //
703 // found entry
704 //
705 Entry = &PDODeviceExtension->InterfaceList[InterfaceIndex];
706 }
707 }
708
709 //
710 // sanity check
711 //
712 ASSERT(Entry);
713 if (!Entry)
714 {
715 //
716 // corruption detected
717 //
718 KeBugCheck(0);
719 }
720
721 NeedSelect = FALSE;
722 if (Entry->InterfaceDescriptor->bAlternateSetting == InterfaceInformation->AlternateSetting)
723 {
724
725 for(InterfaceIndex = 0; InterfaceIndex < InterfaceInformation->NumberOfPipes; InterfaceIndex++)
726 {
727 if (InterfaceInformation->Pipes[InterfaceIndex].MaximumTransferSize != Entry->Interface->Pipes[InterfaceIndex].MaximumTransferSize)
728 {
729 //
730 // changed interface
731 //
732 NeedSelect = TRUE;
733 }
734 }
735 }
736 else
737 {
738 //
739 // need select as the interface number differ
740 //
741 NeedSelect = TRUE;
742 }
743
744 if (!NeedSelect)
745 {
746 //
747 // interface is already selected
748 //
749 RtlCopyMemory(InterfaceInformation, Entry->Interface, min(InterfaceInformation->Length, Entry->Interface->Length));
750 }
751 else
752 {
753 //
754 // select interface
755 //
756 DPRINT1("Selecting InterfaceIndex %lu AlternateSetting %lu NumberOfPipes %lu\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
757 ASSERT(InterfaceInformation->Length == Entry->Interface->Length);
758
759 //
760 // build urb
761 //
762 NewUrb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes));
763 if (!NewUrb)
764 {
765 //
766 // no memory
767 //
768 return STATUS_INSUFFICIENT_RESOURCES;
769 }
770
771 //
772 // now prepare interface urb
773 //
774 UsbBuildSelectInterfaceRequest(NewUrb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes), PDODeviceExtension->ConfigurationHandle, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
775
776 //
777 // now select the interface
778 //
779 Status = USBCCGP_SyncUrbRequest(PDODeviceExtension->NextDeviceObject, NewUrb);
780 DPRINT1("SelectInterface Status %x\n", Status);
781
782 //
783 // did it succeeed
784 //
785 if (NT_SUCCESS(Status))
786 {
787 //
788 // update configuration info
789 //
790 ASSERT(Entry->Interface->Length == NewUrb->UrbSelectInterface.Interface.Length);
791 ASSERT(InterfaceInformation->Length == NewUrb->UrbSelectInterface.Interface.Length);
792 RtlCopyMemory(Entry->Interface, &NewUrb->UrbSelectInterface.Interface, NewUrb->UrbSelectInterface.Interface.Length);
793
794 //
795 // update provided interface information
796 //
797 RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
798 }
799
800 //
801 // free urb
802 //
803 FreeItem(NewUrb);
804 }
805
806 //
807 // move to next information
808 //
809 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
810 Index++;
811 }while(Index < InterfaceInformationCount);
812
813 //
814 // store configuration handle
815 //
816 Urb->UrbSelectConfiguration.ConfigurationHandle = PDODeviceExtension->ConfigurationHandle;
817
818 DPRINT1("[USBCCGP] SelectConfiguration Function %x Completed\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber);
819
820 //
821 // done
822 //
823 return STATUS_SUCCESS;
824 }
825
826 NTSTATUS
827 PDO_HandleInternalDeviceControl(
828 PDEVICE_OBJECT DeviceObject,
829 PIRP Irp)
830 {
831 PIO_STACK_LOCATION IoStack;
832 PPDO_DEVICE_EXTENSION PDODeviceExtension;
833 NTSTATUS Status;
834 PURB Urb;
835
836 //
837 // get current stack location
838 //
839 IoStack = IoGetCurrentIrpStackLocation(Irp);
840
841 //
842 // get device extension
843 //
844 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
845
846 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
847 {
848 //
849 // get urb
850 //
851 Urb = (PURB)IoStack->Parameters.Others.Argument1;
852 ASSERT(Urb);
853 DPRINT("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function);
854
855 if (Urb->UrbHeader.Function == URB_FUNCTION_SELECT_CONFIGURATION)
856 {
857 //
858 // select configuration
859 //
860 Status = USBCCGP_PDOSelectConfiguration(DeviceObject, Irp);
861 Irp->IoStatus.Status = Status;
862 IoCompleteRequest(Irp, IO_NO_INCREMENT);
863 return Status;
864 }
865 else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
866 {
867 if(Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
868 {
869 //
870 // is the buffer big enough
871 //
872 if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR))
873 {
874 //
875 // invalid buffer size
876 //
877 DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
878 Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
879 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
880 IoCompleteRequest(Irp, IO_NO_INCREMENT);
881 return STATUS_INVALID_BUFFER_SIZE;
882 }
883
884 //
885 // copy device descriptor
886 //
887 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
888 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
889 Irp->IoStatus.Status = STATUS_SUCCESS;
890 IoCompleteRequest(Irp, IO_NO_INCREMENT);
891 return STATUS_SUCCESS;
892 }
893 else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE)
894 {
895 //
896 // build configuration descriptor
897 //
898 Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp);
899 Irp->IoStatus.Status = Status;
900 IoCompleteRequest(Irp, IO_NO_INCREMENT);
901 return Status;
902 }
903 }
904 else
905 {
906 IoSkipCurrentIrpStackLocation(Irp);
907 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
908 return Status;
909 }
910 }
911
912
913
914 DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
915 DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength);
916 DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
917 DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer);
918
919 ASSERT(FALSE);
920
921 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
922 IoCompleteRequest(Irp, IO_NO_INCREMENT);
923 return STATUS_NOT_IMPLEMENTED;
924 }
925
926
927 NTSTATUS
928 PDO_Dispatch(
929 PDEVICE_OBJECT DeviceObject,
930 PIRP Irp)
931 {
932 PIO_STACK_LOCATION IoStack;
933 NTSTATUS Status;
934
935 /* get stack location */
936 IoStack = IoGetCurrentIrpStackLocation(Irp);
937
938 switch(IoStack->MajorFunction)
939 {
940 case IRP_MJ_PNP:
941 return PDO_HandlePnp(DeviceObject, Irp);
942 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
943 return PDO_HandleInternalDeviceControl(DeviceObject, Irp);
944 default:
945 DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
946 ASSERT(FALSE);
947 Status = Irp->IoStatus.Status;
948 IoCompleteRequest(Irp, IO_NO_INCREMENT);
949 return Status;
950 }
951
952 }