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