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