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