9d7180dc66607be57e5f14b216e33a8bd5740fc7
[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 ULONG Index;
311
312 //
313 // get current stack location
314 //
315 IoStack = IoGetCurrentIrpStackLocation(Irp);
316
317 //
318 // get device extension
319 //
320 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
321
322 //
323 // sanity check
324 //
325 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
326
327 switch(IoStack->MinorFunction)
328 {
329 case IRP_MN_QUERY_DEVICE_RELATIONS:
330 {
331 //
332 // handle device relations
333 //
334 Status = USBCCGP_PdoHandleDeviceRelations(DeviceObject, Irp);
335 break;
336 }
337 case IRP_MN_QUERY_DEVICE_TEXT:
338 {
339 //
340 // handle query device text
341 //
342 Status = USBCCGP_PdoHandleQueryDeviceText(DeviceObject, Irp);
343 break;
344 }
345 case IRP_MN_QUERY_ID:
346 {
347 //
348 // handle request
349 //
350 Status = USBCCGP_PdoHandleQueryId(DeviceObject, Irp);
351 break;
352 }
353 case IRP_MN_REMOVE_DEVICE:
354 {
355 //
356 // remove us from the fdo's pdo list
357 //
358 for(Index = 0; Index < PDODeviceExtension->FDODeviceExtension->FunctionDescriptorCount; Index++)
359 {
360 if (PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] == DeviceObject)
361 {
362 //
363 // remove us
364 //
365 PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] = NULL;
366 break;
367 }
368 }
369
370 //
371 // Complete the IRP
372 //
373 Irp->IoStatus.Status = STATUS_SUCCESS;
374 IoCompleteRequest(Irp, IO_NO_INCREMENT);
375
376 //
377 // Delete the device object
378 //
379 IoDeleteDevice(DeviceObject);
380 return STATUS_SUCCESS;
381 }
382 case IRP_MN_QUERY_CAPABILITIES:
383 {
384 //
385 // copy device capabilities
386 //
387 RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &PDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
388
389 /* Complete the IRP */
390 Irp->IoStatus.Status = STATUS_SUCCESS;
391 IoCompleteRequest(Irp, IO_NO_INCREMENT);
392 return STATUS_SUCCESS;
393 }
394 case IRP_MN_START_DEVICE:
395 {
396 //
397 // no-op for PDO
398 //
399 DPRINT1("[USBCCGP] PDO IRP_MN_START\n");
400 Status = STATUS_SUCCESS;
401 break;
402 }
403 default:
404 {
405 //
406 // do nothing
407 //
408 Status = Irp->IoStatus.Status;
409 }
410 }
411
412 //
413 // complete request
414 //
415 if (Status != STATUS_PENDING)
416 {
417 //
418 // store result
419 //
420 Irp->IoStatus.Status = Status;
421
422 //
423 // complete request
424 //
425 IoCompleteRequest(Irp, IO_NO_INCREMENT);
426 }
427
428 //
429 // done processing
430 //
431 return Status;
432
433 }
434
435 NTSTATUS
436 USBCCGP_BuildConfigurationDescriptor(
437 PDEVICE_OBJECT DeviceObject,
438 PIRP Irp)
439 {
440 PIO_STACK_LOCATION IoStack;
441 PPDO_DEVICE_EXTENSION PDODeviceExtension;
442 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
443 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
444 ULONG TotalSize, Index;
445 PURB Urb;
446 PVOID Buffer;
447 PUCHAR BufferPtr;
448
449 //
450 // get current stack location
451 //
452 IoStack = IoGetCurrentIrpStackLocation(Irp);
453
454 DPRINT1("USBCCGP_BuildConfigurationDescriptor\n");
455
456 //
457 // get device extension
458 //
459 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
460
461 //
462 // get configuration descriptor
463 //
464 ConfigurationDescriptor = PDODeviceExtension->ConfigurationDescriptor;
465
466 //
467 // calculate size of configuration descriptor
468 //
469 TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
470
471 for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
472 {
473 //
474 // get current interface descriptor
475 //
476 InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
477
478 //
479 // add to size and move to next descriptor
480 //
481 TotalSize += InterfaceDescriptor->bLength;
482 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
483
484 do
485 {
486 if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
487 {
488 //
489 // reached end of configuration descriptor
490 //
491 break;
492 }
493
494 //
495 // association descriptors are removed
496 //
497 if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
498 {
499 if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
500 {
501 //
502 // reached next descriptor
503 //
504 break;
505 }
506
507 //
508 // append size
509 //
510 TotalSize += InterfaceDescriptor->bLength;
511 }
512
513 //
514 // move to next descriptor
515 //
516 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
517 }while(TRUE);
518 }
519
520 //
521 // now allocate temporary buffer for the configuration descriptor
522 //
523 Buffer = AllocateItem(NonPagedPool, TotalSize);
524 if (!Buffer)
525 {
526 //
527 // failed to allocate buffer
528 //
529 DPRINT1("[USBCCGP] Failed to allocate %lu Bytes\n", TotalSize);
530 return STATUS_INSUFFICIENT_RESOURCES;
531 }
532
533 //
534 // first copy the configuration descriptor
535 //
536 RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
537 BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength);
538
539 for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
540 {
541 //
542 // get current interface descriptor
543 //
544 InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
545
546 //
547 // copy descriptor and move to next descriptor
548 //
549 RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
550 BufferPtr += InterfaceDescriptor->bLength;
551 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
552
553 do
554 {
555 if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
556 {
557 //
558 // reached end of configuration descriptor
559 //
560 break;
561 }
562
563 //
564 // association descriptors are removed
565 //
566 if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
567 {
568 if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
569 {
570 //
571 // reached next descriptor
572 //
573 break;
574 }
575
576 //
577 // copy descriptor
578 //
579 RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
580 BufferPtr += InterfaceDescriptor->bLength;
581 }
582
583 //
584 // move to next descriptor
585 //
586 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
587 }while(TRUE);
588 }
589
590 //
591 // modify configuration descriptor
592 //
593 ConfigurationDescriptor = Buffer;
594 ConfigurationDescriptor->wTotalLength = TotalSize;
595 ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces;
596
597 //
598 // get urb
599 //
600 Urb = (PURB)IoStack->Parameters.Others.Argument1;
601 ASSERT(Urb);
602
603 //
604 // copy descriptor
605 //
606 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength));
607
608 //
609 // store final size
610 //
611 Urb->UrbControlDescriptorRequest.TransferBufferLength = TotalSize;
612
613 //
614 // free buffer
615 //
616 FreeItem(Buffer);
617
618 //
619 // done
620 //
621 return STATUS_SUCCESS;
622 }
623
624 NTSTATUS
625 USBCCGP_PDOSelectConfiguration(
626 PDEVICE_OBJECT DeviceObject,
627 PIRP Irp)
628 {
629 PIO_STACK_LOCATION IoStack;
630 PPDO_DEVICE_EXTENSION PDODeviceExtension;
631 PURB Urb, NewUrb;
632 PUSBD_INTERFACE_INFORMATION InterfaceInformation;
633 ULONG InterfaceInformationCount, Index, InterfaceIndex;
634 PUSBD_INTERFACE_LIST_ENTRY Entry;
635 ULONG NeedSelect, FoundInterface;
636 NTSTATUS Status;
637
638 //
639 // get current stack location
640 //
641 IoStack = IoGetCurrentIrpStackLocation(Irp);
642
643 //
644 // get device extension
645 //
646 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
647
648 //
649 // get urb
650 //
651 Urb = (PURB)IoStack->Parameters.Others.Argument1;
652 ASSERT(Urb);
653
654 //
655 // is there already an configuration handle
656 //
657 if (Urb->UrbSelectConfiguration.ConfigurationHandle)
658 {
659 //
660 // nothing to do
661 //
662 return STATUS_SUCCESS;
663 }
664
665 //
666 // count interface information
667 //
668 InterfaceInformationCount = 0;
669 InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
670 do
671 {
672 InterfaceInformationCount++;
673 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
674 }while((ULONG_PTR)InterfaceInformation < (ULONG_PTR)Urb + Urb->UrbSelectConfiguration.Hdr.Length);
675
676 //
677 // check all interfaces
678 //
679 InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
680 Index = 0;
681 Entry = NULL;
682 DPRINT1("Count %x\n", InterfaceInformationCount);
683 do
684 {
685 DPRINT1("[USBCCGP] SelectConfiguration Function %x InterfaceNumber %x Alternative %x\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
686
687 //
688 // search for the interface in the local interface list
689 //
690 FoundInterface = FALSE;
691 for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; InterfaceIndex++)
692 {
693 if (PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[InterfaceIndex]->bInterfaceNumber == InterfaceInformation->InterfaceNumber)
694 {
695 // found interface entry
696 FoundInterface = TRUE;
697 break;
698 }
699 }
700
701 if (!FoundInterface)
702 {
703 //
704 // invalid parameter
705 //
706 DPRINT1("InterfaceInformation InterfaceNumber %x Alternative %x NumberOfPipes %x not found\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
707 ASSERT(FALSE);
708 return STATUS_INVALID_PARAMETER;
709 }
710
711 //
712 // now query the total interface list
713 //
714 Entry = NULL;
715 for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->InterfaceListCount; InterfaceIndex++)
716 {
717 if (PDODeviceExtension->InterfaceList[InterfaceIndex].Interface->InterfaceNumber == InterfaceInformation->InterfaceNumber)
718 {
719 //
720 // found entry
721 //
722 Entry = &PDODeviceExtension->InterfaceList[InterfaceIndex];
723 }
724 }
725
726 //
727 // sanity check
728 //
729 ASSERT(Entry);
730 if (!Entry)
731 {
732 //
733 // corruption detected
734 //
735 KeBugCheck(0);
736 }
737
738 NeedSelect = FALSE;
739 if (Entry->InterfaceDescriptor->bAlternateSetting == InterfaceInformation->AlternateSetting)
740 {
741
742 for(InterfaceIndex = 0; InterfaceIndex < InterfaceInformation->NumberOfPipes; InterfaceIndex++)
743 {
744 if (InterfaceInformation->Pipes[InterfaceIndex].MaximumTransferSize != Entry->Interface->Pipes[InterfaceIndex].MaximumTransferSize)
745 {
746 //
747 // changed interface
748 //
749 NeedSelect = TRUE;
750 }
751 }
752 }
753 else
754 {
755 //
756 // need select as the interface number differ
757 //
758 NeedSelect = TRUE;
759 }
760
761 if (!NeedSelect)
762 {
763 //
764 // interface is already selected
765 //
766 RtlCopyMemory(InterfaceInformation, Entry->Interface, min(InterfaceInformation->Length, Entry->Interface->Length));
767 }
768 else
769 {
770 //
771 // select interface
772 //
773 DPRINT1("Selecting InterfaceIndex %lu AlternateSetting %lu NumberOfPipes %lu\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
774 ASSERT(InterfaceInformation->Length == Entry->Interface->Length);
775
776 //
777 // build urb
778 //
779 NewUrb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes));
780 if (!NewUrb)
781 {
782 //
783 // no memory
784 //
785 return STATUS_INSUFFICIENT_RESOURCES;
786 }
787
788 //
789 // now prepare interface urb
790 //
791 UsbBuildSelectInterfaceRequest(NewUrb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes), PDODeviceExtension->ConfigurationHandle, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
792
793 //
794 // now select the interface
795 //
796 Status = USBCCGP_SyncUrbRequest(PDODeviceExtension->NextDeviceObject, NewUrb);
797 DPRINT1("SelectInterface Status %x\n", Status);
798
799 //
800 // did it succeeed
801 //
802 if (NT_SUCCESS(Status))
803 {
804 //
805 // update configuration info
806 //
807 ASSERT(Entry->Interface->Length == NewUrb->UrbSelectInterface.Interface.Length);
808 ASSERT(InterfaceInformation->Length == NewUrb->UrbSelectInterface.Interface.Length);
809 RtlCopyMemory(Entry->Interface, &NewUrb->UrbSelectInterface.Interface, NewUrb->UrbSelectInterface.Interface.Length);
810
811 //
812 // update provided interface information
813 //
814 RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
815 }
816
817 //
818 // free urb
819 //
820 FreeItem(NewUrb);
821 }
822
823 //
824 // move to next information
825 //
826 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
827 Index++;
828 }while(Index < InterfaceInformationCount);
829
830 //
831 // store configuration handle
832 //
833 Urb->UrbSelectConfiguration.ConfigurationHandle = PDODeviceExtension->ConfigurationHandle;
834
835 DPRINT1("[USBCCGP] SelectConfiguration Function %x Completed\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber);
836
837 //
838 // done
839 //
840 return STATUS_SUCCESS;
841 }
842
843 NTSTATUS
844 PDO_HandleInternalDeviceControl(
845 PDEVICE_OBJECT DeviceObject,
846 PIRP Irp)
847 {
848 PIO_STACK_LOCATION IoStack;
849 PPDO_DEVICE_EXTENSION PDODeviceExtension;
850 NTSTATUS Status;
851 PURB Urb;
852
853 //
854 // get current stack location
855 //
856 IoStack = IoGetCurrentIrpStackLocation(Irp);
857
858 //
859 // get device extension
860 //
861 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
862
863 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
864 {
865 //
866 // get urb
867 //
868 Urb = (PURB)IoStack->Parameters.Others.Argument1;
869 ASSERT(Urb);
870 DPRINT("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function);
871
872 if (Urb->UrbHeader.Function == URB_FUNCTION_SELECT_CONFIGURATION)
873 {
874 //
875 // select configuration
876 //
877 Status = USBCCGP_PDOSelectConfiguration(DeviceObject, Irp);
878 Irp->IoStatus.Status = Status;
879 IoCompleteRequest(Irp, IO_NO_INCREMENT);
880 return Status;
881 }
882 else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
883 {
884 if(Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
885 {
886 //
887 // is the buffer big enough
888 //
889 if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR))
890 {
891 //
892 // invalid buffer size
893 //
894 DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
895 Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
896 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
897 IoCompleteRequest(Irp, IO_NO_INCREMENT);
898 return STATUS_INVALID_BUFFER_SIZE;
899 }
900
901 //
902 // copy device descriptor
903 //
904 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
905 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
906 Irp->IoStatus.Status = STATUS_SUCCESS;
907 IoCompleteRequest(Irp, IO_NO_INCREMENT);
908 return STATUS_SUCCESS;
909 }
910 else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE)
911 {
912 //
913 // build configuration descriptor
914 //
915 Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp);
916 Irp->IoStatus.Status = Status;
917 IoCompleteRequest(Irp, IO_NO_INCREMENT);
918 return Status;
919 }
920 }
921 else
922 {
923 IoSkipCurrentIrpStackLocation(Irp);
924 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
925 return Status;
926 }
927 }
928
929
930
931 DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
932 DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength);
933 DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
934 DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer);
935
936 ASSERT(FALSE);
937
938 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
939 IoCompleteRequest(Irp, IO_NO_INCREMENT);
940 return STATUS_NOT_IMPLEMENTED;
941 }
942
943
944 NTSTATUS
945 PDO_Dispatch(
946 PDEVICE_OBJECT DeviceObject,
947 PIRP Irp)
948 {
949 PIO_STACK_LOCATION IoStack;
950 NTSTATUS Status;
951
952 /* get stack location */
953 IoStack = IoGetCurrentIrpStackLocation(Irp);
954
955 switch(IoStack->MajorFunction)
956 {
957 case IRP_MJ_PNP:
958 return PDO_HandlePnp(DeviceObject, Irp);
959 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
960 return PDO_HandleInternalDeviceControl(DeviceObject, Irp);
961 default:
962 DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
963 ASSERT(FALSE);
964 Status = Irp->IoStatus.Status;
965 IoCompleteRequest(Irp, IO_NO_INCREMENT);
966 return Status;
967 }
968
969 }