[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 #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 ASSERT(FALSE);
761 return STATUS_INVALID_PARAMETER;
762 }
763
764 //
765 // now query the total interface list
766 //
767 Entry = NULL;
768 for (InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->InterfaceListCount; InterfaceIndex++)
769 {
770 if (PDODeviceExtension->InterfaceList[InterfaceIndex].Interface->InterfaceNumber == InterfaceInformation->InterfaceNumber)
771 {
772 //
773 // found entry
774 //
775 Entry = &PDODeviceExtension->InterfaceList[InterfaceIndex];
776 }
777 }
778
779 //
780 // sanity check
781 //
782 ASSERT(Entry);
783 if (!Entry)
784 {
785 //
786 // corruption detected
787 //
788 KeBugCheck(0);
789 }
790
791 NeedSelect = FALSE;
792 if (Entry->InterfaceDescriptor->bAlternateSetting == InterfaceInformation->AlternateSetting)
793 {
794 for(InterfaceIndex = 0; InterfaceIndex < InterfaceInformation->NumberOfPipes; InterfaceIndex++)
795 {
796 if (InterfaceInformation->Pipes[InterfaceIndex].MaximumTransferSize != Entry->Interface->Pipes[InterfaceIndex].MaximumTransferSize)
797 {
798 //
799 // changed interface
800 //
801 NeedSelect = TRUE;
802 }
803 }
804 }
805 else
806 {
807 //
808 // need select as the interface number differ
809 //
810 NeedSelect = TRUE;
811 }
812
813 if (!NeedSelect)
814 {
815 //
816 // interface is already selected
817 //
818 ASSERT(Length >= Entry->Interface->Length);
819 RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
820
821 //
822 // adjust remaining buffer size
823 //
824 ASSERT(Entry->Interface->Length);
825 Length -= Entry->Interface->Length;
826
827 //
828 // move to next output interface information
829 //
830 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + Entry->Interface->Length);
831 }
832 else
833 {
834 //
835 // select interface
836 //
837 DPRINT1("Selecting InterfaceIndex %lu AlternateSetting %lu NumberOfPipes %lu\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
838 ASSERT(InterfaceInformation->Length == Entry->Interface->Length);
839
840 //
841 // build urb
842 //
843 NewUrb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes));
844 if (!NewUrb)
845 {
846 //
847 // no memory
848 //
849 return STATUS_INSUFFICIENT_RESOURCES;
850 }
851
852 //
853 // now prepare interface urb
854 //
855 UsbBuildSelectInterfaceRequest(NewUrb, (USHORT)GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes), PDODeviceExtension->ConfigurationHandle, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
856
857 //
858 // now select the interface
859 //
860 Status = USBCCGP_SyncUrbRequest(PDODeviceExtension->NextDeviceObject, NewUrb);
861 DPRINT1("SelectInterface Status %x\n", Status);
862
863 if (!NT_SUCCESS(Status))
864 {
865 //
866 // failed
867 //
868 break;
869 }
870
871 //
872 // update configuration info
873 //
874 ASSERT(Entry->Interface->Length >= NewUrb->UrbSelectInterface.Interface.Length);
875 ASSERT(Length >= NewUrb->UrbSelectInterface.Interface.Length);
876 RtlCopyMemory(Entry->Interface, &NewUrb->UrbSelectInterface.Interface, NewUrb->UrbSelectInterface.Interface.Length);
877
878 //
879 // update provided interface information
880 //
881 ASSERT(Length >= Entry->Interface->Length);
882 RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
883
884 //
885 // decrement remaining buffer size
886 //
887 ASSERT(Entry->Interface->Length);
888 Length -= Entry->Interface->Length;
889
890 //
891 // adjust output buffer offset
892 //
893 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + Entry->Interface->Length);
894
895 //
896 // free urb
897 //
898 FreeItem(NewUrb);
899 }
900
901 } while(Length);
902
903 //
904 // store configuration handle
905 //
906 Urb->UrbSelectConfiguration.ConfigurationHandle = PDODeviceExtension->ConfigurationHandle;
907
908 DPRINT1("[USBCCGP] SelectConfiguration Function %x Completed\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber);
909
910 //
911 // done
912 //
913 return STATUS_SUCCESS;
914 }
915
916 NTSTATUS
917 PDO_HandleInternalDeviceControl(
918 PDEVICE_OBJECT DeviceObject,
919 PIRP Irp)
920 {
921 PIO_STACK_LOCATION IoStack;
922 PPDO_DEVICE_EXTENSION PDODeviceExtension;
923 NTSTATUS Status;
924 PURB Urb;
925
926 //
927 // get current stack location
928 //
929 IoStack = IoGetCurrentIrpStackLocation(Irp);
930
931 //
932 // get device extension
933 //
934 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
935
936 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
937 {
938 //
939 // get urb
940 //
941 Urb = (PURB)IoStack->Parameters.Others.Argument1;
942 ASSERT(Urb);
943 DPRINT("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function);
944
945 if (Urb->UrbHeader.Function == URB_FUNCTION_SELECT_CONFIGURATION)
946 {
947 //
948 // select configuration
949 //
950 Status = USBCCGP_PDOSelectConfiguration(DeviceObject, Irp);
951 Irp->IoStatus.Status = Status;
952 IoCompleteRequest(Irp, IO_NO_INCREMENT);
953 return Status;
954 }
955 else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
956 {
957 if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
958 {
959 //
960 // is the buffer big enough
961 //
962 if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR))
963 {
964 //
965 // invalid buffer size
966 //
967 DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
968 Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
969 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
970 IoCompleteRequest(Irp, IO_NO_INCREMENT);
971 return STATUS_INVALID_BUFFER_SIZE;
972 }
973
974 //
975 // copy device descriptor
976 //
977 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
978 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
979 Irp->IoStatus.Status = STATUS_SUCCESS;
980 IoCompleteRequest(Irp, IO_NO_INCREMENT);
981 return STATUS_SUCCESS;
982 }
983 else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE)
984 {
985 //
986 // build configuration descriptor
987 //
988 Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp);
989 Irp->IoStatus.Status = Status;
990 IoCompleteRequest(Irp, IO_NO_INCREMENT);
991 return Status;
992 }
993 else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_STRING_DESCRIPTOR_TYPE)
994 {
995 PUSB_STRING_DESCRIPTOR StringDescriptor;
996
997 //
998 // get the requested string descriptor
999 //
1000 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1001 Status = USBCCGP_GetDescriptor(PDODeviceExtension->FDODeviceExtension->NextDeviceObject,
1002 USB_STRING_DESCRIPTOR_TYPE,
1003 Urb->UrbControlDescriptorRequest.TransferBufferLength,
1004 Urb->UrbControlDescriptorRequest.Index,
1005 Urb->UrbControlDescriptorRequest.LanguageId,
1006 (PVOID*)&StringDescriptor);
1007 if (NT_SUCCESS(Status))
1008 {
1009 if (StringDescriptor->bLength == 2)
1010 {
1011 FreeItem(StringDescriptor);
1012 Status = STATUS_DEVICE_DATA_ERROR;
1013 }
1014 else
1015 {
1016 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
1017 StringDescriptor->bString,
1018 StringDescriptor->bLength + sizeof(WCHAR));
1019 FreeItem(StringDescriptor);
1020 Status = STATUS_SUCCESS;
1021 }
1022 }
1023 Irp->IoStatus.Status = Status;
1024 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1025 return Status;
1026 }
1027 }
1028 else
1029 {
1030 IoSkipCurrentIrpStackLocation(Irp);
1031 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
1032 return Status;
1033 }
1034 }
1035 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_GET_PORT_STATUS)
1036 {
1037 IoSkipCurrentIrpStackLocation(Irp);
1038 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
1039 return Status;
1040 }
1041 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT)
1042 {
1043 IoSkipCurrentIrpStackLocation(Irp);
1044 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
1045 return Status;
1046 }
1047 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT)
1048 {
1049 IoSkipCurrentIrpStackLocation(Irp);
1050 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
1051 return Status;
1052 }
1053
1054 DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
1055 DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength);
1056 DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
1057 DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer);
1058
1059 ASSERT(FALSE);
1060
1061 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1062 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1063 return STATUS_NOT_IMPLEMENTED;
1064 }
1065
1066
1067 NTSTATUS
1068 PDO_Dispatch(
1069 PDEVICE_OBJECT DeviceObject,
1070 PIRP Irp)
1071 {
1072 PIO_STACK_LOCATION IoStack;
1073 NTSTATUS Status;
1074
1075 /* get stack location */
1076 IoStack = IoGetCurrentIrpStackLocation(Irp);
1077
1078 switch(IoStack->MajorFunction)
1079 {
1080 case IRP_MJ_PNP:
1081 return PDO_HandlePnp(DeviceObject, Irp);
1082 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
1083 return PDO_HandleInternalDeviceControl(DeviceObject, Irp);
1084 case IRP_MJ_POWER:
1085 PoStartNextPowerIrp(Irp);
1086 Irp->IoStatus.Status = STATUS_SUCCESS;
1087 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1088 return STATUS_SUCCESS;
1089 default:
1090 DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
1091 Status = Irp->IoStatus.Status;
1092 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1093 return Status;
1094 }
1095 }