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