[USBCCGP]
[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 PURB Urb;
477 PVOID Buffer;
478 PUCHAR BufferPtr;
479 UCHAR InterfaceNumber;
480
481 //
482 // get current stack location
483 //
484 IoStack = IoGetCurrentIrpStackLocation(Irp);
485
486 DPRINT("USBCCGP_BuildConfigurationDescriptor\n");
487
488 //
489 // get device extension
490 //
491 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
492
493 //
494 // get configuration descriptor
495 //
496 ConfigurationDescriptor = PDODeviceExtension->ConfigurationDescriptor;
497
498 //
499 // calculate size of configuration descriptor
500 //
501 TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
502
503 for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
504 {
505 //
506 // get current interface descriptor
507 //
508 InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
509 InterfaceNumber = InterfaceDescriptor->bInterfaceNumber;
510
511 //
512 // add to size and move to next descriptor
513 //
514 TotalSize += InterfaceDescriptor->bLength;
515 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
516
517 do
518 {
519 if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
520 {
521 //
522 // reached end of configuration descriptor
523 //
524 break;
525 }
526
527 //
528 // association descriptors are removed
529 //
530 if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
531 {
532 if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
533 {
534 if (InterfaceNumber != InterfaceDescriptor->bInterfaceNumber)
535 {
536 //
537 // reached next descriptor
538 //
539 break;
540 }
541
542 //
543 // include alternate descriptor
544 //
545 }
546
547 //
548 // append size
549 //
550 TotalSize += InterfaceDescriptor->bLength;
551 }
552
553 //
554 // move to next descriptor
555 //
556 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
557 }while(TRUE);
558 }
559
560 //
561 // now allocate temporary buffer for the configuration descriptor
562 //
563 Buffer = AllocateItem(NonPagedPool, TotalSize);
564 if (!Buffer)
565 {
566 //
567 // failed to allocate buffer
568 //
569 DPRINT1("[USBCCGP] Failed to allocate %lu Bytes\n", TotalSize);
570 return STATUS_INSUFFICIENT_RESOURCES;
571 }
572
573 //
574 // first copy the configuration descriptor
575 //
576 RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
577 BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength);
578
579 for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
580 {
581 //
582 // get current interface descriptor
583 //
584 InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
585 InterfaceNumber = InterfaceDescriptor->bInterfaceNumber;
586
587 //
588 // copy descriptor and move to next descriptor
589 //
590 RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
591 BufferPtr += InterfaceDescriptor->bLength;
592 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
593
594 do
595 {
596 if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
597 {
598 //
599 // reached end of configuration descriptor
600 //
601 break;
602 }
603
604 //
605 // association descriptors are removed
606 //
607 if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
608 {
609 if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
610 {
611 if (InterfaceNumber != InterfaceDescriptor->bInterfaceNumber)
612 {
613 //
614 // reached next descriptor
615 //
616 break;
617 }
618
619 //
620 // include alternate descriptor
621 //
622 DPRINT("InterfaceDescriptor %p Alternate %x InterfaceNumber %x\n", InterfaceDescriptor, InterfaceDescriptor->bAlternateSetting, InterfaceDescriptor->bInterfaceNumber);
623 }
624
625 //
626 // copy descriptor
627 //
628 RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
629 BufferPtr += InterfaceDescriptor->bLength;
630 }
631
632 //
633 // move to next descriptor
634 //
635 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
636 }while(TRUE);
637 }
638
639 //
640 // modify configuration descriptor
641 //
642 ConfigurationDescriptor = Buffer;
643 ConfigurationDescriptor->wTotalLength = TotalSize;
644 ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces;
645
646 //
647 // get urb
648 //
649 Urb = (PURB)IoStack->Parameters.Others.Argument1;
650 ASSERT(Urb);
651
652 //
653 // copy descriptor
654 //
655 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength));
656
657 //
658 // store final size
659 //
660 Urb->UrbControlDescriptorRequest.TransferBufferLength = TotalSize;
661
662 //
663 // free buffer
664 //
665 FreeItem(Buffer);
666
667 //
668 // done
669 //
670 return STATUS_SUCCESS;
671 }
672
673 NTSTATUS
674 USBCCGP_PDOSelectConfiguration(
675 PDEVICE_OBJECT DeviceObject,
676 PIRP Irp)
677 {
678 PIO_STACK_LOCATION IoStack;
679 PPDO_DEVICE_EXTENSION PDODeviceExtension;
680 PURB Urb, NewUrb;
681 PUSBD_INTERFACE_INFORMATION InterfaceInformation;
682 ULONG InterfaceIndex, Length;
683 PUSBD_INTERFACE_LIST_ENTRY Entry;
684 ULONG NeedSelect, FoundInterface;
685 NTSTATUS Status;
686
687 //
688 // get current stack location
689 //
690 IoStack = IoGetCurrentIrpStackLocation(Irp);
691
692 //
693 // get device extension
694 //
695 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
696
697 //
698 // get urb
699 //
700 Urb = (PURB)IoStack->Parameters.Others.Argument1;
701 ASSERT(Urb);
702
703 //
704 // is there already an configuration handle
705 //
706 if (Urb->UrbSelectConfiguration.ConfigurationHandle)
707 {
708 //
709 // nothing to do
710 //
711 return STATUS_SUCCESS;
712 }
713
714 // sanity checks
715 //C_ASSERT(sizeof(struct _URB_HEADER) == 16);
716 //C_ASSERT(FIELD_OFFSET(struct _URB_SELECT_CONFIGURATION, Interface.Length) == 24);
717 //C_ASSERT(sizeof(USBD_INTERFACE_INFORMATION) == 36);
718 //C_ASSERT(sizeof(struct _URB_SELECT_CONFIGURATION) == 0x3C);
719
720 // available buffer length
721 Length = Urb->UrbSelectConfiguration.Hdr.Length - FIELD_OFFSET(struct _URB_SELECT_CONFIGURATION, Interface.Length);
722
723 //
724 // check all interfaces
725 //
726 InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
727
728 Entry = NULL;
729 do
730 {
731 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);
732 ASSERT(InterfaceInformation->Length);
733 //
734 // search for the interface in the local interface list
735 //
736 FoundInterface = FALSE;
737 for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; InterfaceIndex++)
738 {
739 if (PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[InterfaceIndex]->bInterfaceNumber == InterfaceInformation->InterfaceNumber)
740 {
741 // found interface entry
742 FoundInterface = TRUE;
743 break;
744 }
745 }
746
747 if (!FoundInterface)
748 {
749 //
750 // invalid parameter
751 //
752 DPRINT1("InterfaceInformation InterfaceNumber %x Alternative %x NumberOfPipes %x not found\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
753 ASSERT(FALSE);
754 return STATUS_INVALID_PARAMETER;
755 }
756
757 //
758 // now query the total interface list
759 //
760 Entry = NULL;
761 for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->InterfaceListCount; InterfaceIndex++)
762 {
763 if (PDODeviceExtension->InterfaceList[InterfaceIndex].Interface->InterfaceNumber == InterfaceInformation->InterfaceNumber)
764 {
765 //
766 // found entry
767 //
768 Entry = &PDODeviceExtension->InterfaceList[InterfaceIndex];
769 }
770 }
771
772 //
773 // sanity check
774 //
775 ASSERT(Entry);
776 if (!Entry)
777 {
778 //
779 // corruption detected
780 //
781 KeBugCheck(0);
782 }
783
784 NeedSelect = FALSE;
785 if (Entry->InterfaceDescriptor->bAlternateSetting == InterfaceInformation->AlternateSetting)
786 {
787
788 for(InterfaceIndex = 0; InterfaceIndex < InterfaceInformation->NumberOfPipes; InterfaceIndex++)
789 {
790 if (InterfaceInformation->Pipes[InterfaceIndex].MaximumTransferSize != Entry->Interface->Pipes[InterfaceIndex].MaximumTransferSize)
791 {
792 //
793 // changed interface
794 //
795 NeedSelect = TRUE;
796 }
797 }
798 }
799 else
800 {
801 //
802 // need select as the interface number differ
803 //
804 NeedSelect = TRUE;
805 }
806
807 if (!NeedSelect)
808 {
809 //
810 // interface is already selected
811 //
812 ASSERT(Length >= Entry->Interface->Length);
813 RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
814
815 //
816 // adjust remaining buffer size
817 //
818 ASSERT(Entry->Interface->Length);
819 Length -= Entry->Interface->Length;
820
821 //
822 // move to next output interface information
823 //
824 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + Entry->Interface->Length);
825 }
826 else
827 {
828 //
829 // select interface
830 //
831 DPRINT1("Selecting InterfaceIndex %lu AlternateSetting %lu NumberOfPipes %lu\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
832 ASSERT(InterfaceInformation->Length == Entry->Interface->Length);
833
834 //
835 // build urb
836 //
837 NewUrb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes));
838 if (!NewUrb)
839 {
840 //
841 // no memory
842 //
843 return STATUS_INSUFFICIENT_RESOURCES;
844 }
845
846 //
847 // now prepare interface urb
848 //
849 UsbBuildSelectInterfaceRequest(NewUrb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes), PDODeviceExtension->ConfigurationHandle, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
850
851 //
852 // now select the interface
853 //
854 Status = USBCCGP_SyncUrbRequest(PDODeviceExtension->NextDeviceObject, NewUrb);
855 DPRINT1("SelectInterface Status %x\n", Status);
856
857 if (!NT_SUCCESS(Status))
858 {
859 //
860 // failed
861 //
862 break;
863 }
864
865 //
866 // update configuration info
867 //
868 ASSERT(Entry->Interface->Length >= NewUrb->UrbSelectInterface.Interface.Length);
869 ASSERT(Length >= NewUrb->UrbSelectInterface.Interface.Length);
870 RtlCopyMemory(Entry->Interface, &NewUrb->UrbSelectInterface.Interface, NewUrb->UrbSelectInterface.Interface.Length);
871
872 //
873 // update provided interface information
874 //
875 ASSERT(Length >= Entry->Interface->Length);
876 RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
877
878 //
879 // decrement remaining buffer size
880 //
881 ASSERT(Entry->Interface->Length);
882 Length -= Entry->Interface->Length;
883
884 //
885 // adjust output buffer offset
886 //
887 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + Entry->Interface->Length);
888
889 //
890 // free urb
891 //
892 FreeItem(NewUrb);
893 }
894
895 }while(Length);
896
897 //
898 // store configuration handle
899 //
900 Urb->UrbSelectConfiguration.ConfigurationHandle = PDODeviceExtension->ConfigurationHandle;
901
902 DPRINT1("[USBCCGP] SelectConfiguration Function %x Completed\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber);
903
904 //
905 // done
906 //
907 return STATUS_SUCCESS;
908 }
909
910 NTSTATUS
911 PDO_HandleInternalDeviceControl(
912 PDEVICE_OBJECT DeviceObject,
913 PIRP Irp)
914 {
915 PIO_STACK_LOCATION IoStack;
916 PPDO_DEVICE_EXTENSION PDODeviceExtension;
917 NTSTATUS Status;
918 PURB Urb;
919
920 //
921 // get current stack location
922 //
923 IoStack = IoGetCurrentIrpStackLocation(Irp);
924
925 //
926 // get device extension
927 //
928 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
929
930 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
931 {
932 //
933 // get urb
934 //
935 Urb = (PURB)IoStack->Parameters.Others.Argument1;
936 ASSERT(Urb);
937 DPRINT("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function);
938
939 if (Urb->UrbHeader.Function == URB_FUNCTION_SELECT_CONFIGURATION)
940 {
941 //
942 // select configuration
943 //
944 Status = USBCCGP_PDOSelectConfiguration(DeviceObject, Irp);
945 Irp->IoStatus.Status = Status;
946 IoCompleteRequest(Irp, IO_NO_INCREMENT);
947 return Status;
948 }
949 else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
950 {
951 if(Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
952 {
953 //
954 // is the buffer big enough
955 //
956 if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR))
957 {
958 //
959 // invalid buffer size
960 //
961 DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
962 Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
963 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
964 IoCompleteRequest(Irp, IO_NO_INCREMENT);
965 return STATUS_INVALID_BUFFER_SIZE;
966 }
967
968 //
969 // copy device descriptor
970 //
971 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
972 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
973 Irp->IoStatus.Status = STATUS_SUCCESS;
974 IoCompleteRequest(Irp, IO_NO_INCREMENT);
975 return STATUS_SUCCESS;
976 }
977 else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE)
978 {
979 //
980 // build configuration descriptor
981 //
982 Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp);
983 Irp->IoStatus.Status = Status;
984 IoCompleteRequest(Irp, IO_NO_INCREMENT);
985 return Status;
986 }
987 else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_STRING_DESCRIPTOR_TYPE)
988 {
989 PUSB_STRING_DESCRIPTOR StringDescriptor;
990
991 //
992 // get the requested string descriptor
993 //
994 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
995 Status = USBCCGP_GetDescriptor(PDODeviceExtension->FDODeviceExtension->NextDeviceObject,
996 USB_STRING_DESCRIPTOR_TYPE,
997 Urb->UrbControlDescriptorRequest.TransferBufferLength,
998 Urb->UrbControlDescriptorRequest.Index,
999 Urb->UrbControlDescriptorRequest.LanguageId,
1000 (PVOID*)&StringDescriptor);
1001 if (NT_SUCCESS(Status))
1002 {
1003 if (StringDescriptor->bLength == 2)
1004 {
1005 FreeItem(StringDescriptor);
1006 Status = STATUS_DEVICE_DATA_ERROR;
1007 }
1008 else
1009 {
1010 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
1011 StringDescriptor->bString,
1012 StringDescriptor->bLength + sizeof(WCHAR));
1013 FreeItem(StringDescriptor);
1014 Status = STATUS_SUCCESS;
1015 }
1016 }
1017 Irp->IoStatus.Status = Status;
1018 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1019 return Status;
1020 }
1021 }
1022 else
1023 {
1024 IoSkipCurrentIrpStackLocation(Irp);
1025 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
1026 return Status;
1027 }
1028 }
1029 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_GET_PORT_STATUS)
1030 {
1031 IoSkipCurrentIrpStackLocation(Irp);
1032 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
1033 return Status;
1034 }
1035 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT)
1036 {
1037 IoSkipCurrentIrpStackLocation(Irp);
1038 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
1039 return Status;
1040 }
1041 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT)
1042 {
1043 IoSkipCurrentIrpStackLocation(Irp);
1044 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
1045 return Status;
1046 }
1047
1048
1049
1050 DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
1051 DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength);
1052 DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
1053 DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer);
1054
1055 ASSERT(FALSE);
1056
1057 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1058 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1059 return STATUS_NOT_IMPLEMENTED;
1060 }
1061
1062
1063 NTSTATUS
1064 PDO_Dispatch(
1065 PDEVICE_OBJECT DeviceObject,
1066 PIRP Irp)
1067 {
1068 PIO_STACK_LOCATION IoStack;
1069 NTSTATUS Status;
1070
1071 /* get stack location */
1072 IoStack = IoGetCurrentIrpStackLocation(Irp);
1073
1074 switch(IoStack->MajorFunction)
1075 {
1076 case IRP_MJ_PNP:
1077 return PDO_HandlePnp(DeviceObject, Irp);
1078 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
1079 return PDO_HandleInternalDeviceControl(DeviceObject, Irp);
1080 default:
1081 DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
1082 Status = Irp->IoStatus.Status;
1083 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1084 return Status;
1085 }
1086
1087 }