Synchronize with trunk r58528.
[reactos.git] / drivers / usb / usbhub / misc.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
5 * PURPOSE: Misc helper functions
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10 #include "usbhub.h"
11 #include <stdarg.h>
12
13 VOID
14 DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
15 {
16 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
17 DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
18 DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
19 DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
20 DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
21 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
22 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
23 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
24 DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
25 DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
26 DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
27 DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
28 DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
29 DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
30 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
31 }
32
33 //----------------------------------------------------------------------------------------
34 VOID
35 DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
36 {
37 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
38 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
39 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
40 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
41 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
42 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
43 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
44 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
45 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
46 }
47
48 VOID
49 DumpFullConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
50 {
51 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
52 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
53 LONG i, j;
54
55 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
56 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
57 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
58 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
59 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
60 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
61 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
62 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
63 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
64
65 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) ((ULONG_PTR)ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
66
67 for (i=0; i < ConfigurationDescriptor->bNumInterfaces; i++)
68 {
69 DPRINT1("- Dumping InterfaceDescriptor %x\n", InterfaceDescriptor);
70 DPRINT1(" bLength %x\n", InterfaceDescriptor->bLength);
71 DPRINT1(" bDescriptorType %x\n", InterfaceDescriptor->bDescriptorType);
72 DPRINT1(" bInterfaceNumber %x\n", InterfaceDescriptor->bInterfaceNumber);
73 DPRINT1(" bAlternateSetting %x\n", InterfaceDescriptor->bAlternateSetting);
74 DPRINT1(" bNumEndpoints %x\n", InterfaceDescriptor->bNumEndpoints);
75 DPRINT1(" bInterfaceClass %x\n", InterfaceDescriptor->bInterfaceClass);
76 DPRINT1(" bInterfaceSubClass %x\n", InterfaceDescriptor->bInterfaceSubClass);
77 DPRINT1(" bInterfaceProtocol %x\n", InterfaceDescriptor->bInterfaceProtocol);
78 DPRINT1(" iInterface %x\n", InterfaceDescriptor->iInterface);
79
80 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)InterfaceDescriptor + sizeof(USB_INTERFACE_DESCRIPTOR));
81
82 for (j=0; j < InterfaceDescriptor->bNumEndpoints; j++)
83 {
84 DPRINT1(" bLength %x\n", EndpointDescriptor->bLength);
85 DPRINT1(" bDescriptorType %x\n", EndpointDescriptor->bDescriptorType);
86 DPRINT1(" bEndpointAddress %x\n", EndpointDescriptor->bEndpointAddress);
87 DPRINT1(" bmAttributes %x\n", EndpointDescriptor->bmAttributes);
88 DPRINT1(" wMaxPacketSize %x\n", EndpointDescriptor->wMaxPacketSize);
89 DPRINT1(" bInterval %x\n", EndpointDescriptor->bInterval);
90 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)EndpointDescriptor + sizeof(USB_ENDPOINT_DESCRIPTOR));
91 }
92 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ULONG_PTR)EndpointDescriptor;
93 }
94 }
95
96 NTSTATUS
97 NTAPI
98 ForwardIrpAndWaitCompletion(
99 IN PDEVICE_OBJECT DeviceObject,
100 IN PIRP Irp,
101 IN PVOID Context)
102 {
103 if (Irp->PendingReturned)
104 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
105
106 return STATUS_MORE_PROCESSING_REQUIRED;
107 }
108
109 NTSTATUS
110 ForwardIrpAndWait(
111 IN PDEVICE_OBJECT DeviceObject,
112 IN PIRP Irp)
113 {
114 KEVENT Event;
115 NTSTATUS Status;
116
117 KeInitializeEvent(&Event, NotificationEvent, FALSE);
118 IoCopyCurrentIrpStackLocationToNext(Irp);
119
120 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
121
122 Status = IoCallDriver(DeviceObject, Irp);
123 if (Status == STATUS_PENDING)
124 {
125 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
126 if (NT_SUCCESS(Status))
127 Status = Irp->IoStatus.Status;
128 }
129
130 return Status;
131 }
132
133 NTSTATUS
134 ForwardIrpAndForget(
135 IN PDEVICE_OBJECT DeviceObject,
136 IN PIRP Irp)
137 {
138 PDEVICE_OBJECT LowerDevice = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDeviceObject;
139
140 ASSERT(LowerDevice);
141
142 IoSkipCurrentIrpStackLocation(Irp);
143 return IoCallDriver(LowerDevice, Irp);
144 }
145
146 NTSTATUS
147 SubmitRequestToRootHub(
148 IN PDEVICE_OBJECT RootHubDeviceObject,
149 IN ULONG IoControlCode,
150 OUT PVOID OutParameter1,
151 OUT PVOID OutParameter2)
152 {
153 KEVENT Event;
154 PIRP Irp;
155 IO_STATUS_BLOCK IoStatus;
156 NTSTATUS Status;
157 PIO_STACK_LOCATION Stack = NULL;
158
159 KeInitializeEvent(&Event, NotificationEvent, FALSE);
160
161 //
162 // Build Control Request
163 //
164 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
165 RootHubDeviceObject,
166 NULL, 0,
167 NULL, 0,
168 TRUE,
169 &Event,
170 &IoStatus);
171
172 if (Irp == NULL)
173 {
174 DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
175 return STATUS_INSUFFICIENT_RESOURCES;
176 }
177
178 //
179 // Initialize the status block before sending the IRP
180 //
181 IoStatus.Status = STATUS_NOT_SUPPORTED;
182 IoStatus.Information = 0;
183
184 //
185 // Get Next Stack Location and Initialize it
186 //
187 Stack = IoGetNextIrpStackLocation(Irp);
188 Stack->Parameters.Others.Argument1 = OutParameter1;
189 Stack->Parameters.Others.Argument2 = OutParameter2;
190
191 //
192 // Call RootHub
193 //
194 Status = IoCallDriver(RootHubDeviceObject, Irp);
195
196 //
197 // Its ok to block here as this function is called in an nonarbitrary thread
198 //
199 if (Status == STATUS_PENDING)
200 {
201 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
202 Status = IoStatus.Status;
203 }
204
205 //
206 // The IO Manager will free the IRP
207 //
208
209 return Status;
210 }
211
212 NTSTATUS
213 NTAPI
214 FDO_QueryInterfaceCompletionRoutine(
215 IN PDEVICE_OBJECT DeviceObject,
216 IN PIRP Irp,
217 IN PVOID Context)
218 {
219 /* Set event */
220 KeSetEvent((PRKEVENT)Context, 0, FALSE);
221
222 /* Completion is done in the HidClassFDO_QueryCapabilities routine */
223 return STATUS_MORE_PROCESSING_REQUIRED;
224 }
225
226 NTSTATUS
227 FDO_QueryInterface(
228 IN PDEVICE_OBJECT DeviceObject,
229 IN OUT PUSB_BUS_INTERFACE_USBDI_V2 Interface)
230 {
231 PIRP Irp;
232 KEVENT Event;
233 NTSTATUS Status;
234 PIO_STACK_LOCATION IoStack;
235 PHUB_DEVICE_EXTENSION HubDeviceExtension;
236
237 /* Get device extension */
238 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
239 ASSERT(HubDeviceExtension->Common.IsFDO);
240
241 /* Init event */
242 KeInitializeEvent(&Event, NotificationEvent, FALSE);
243
244 /* Now allocte the irp */
245 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
246 if (!Irp)
247 {
248 /* No memory */
249 return STATUS_INSUFFICIENT_RESOURCES;
250 }
251
252 /* Get next stack location */
253 IoStack = IoGetNextIrpStackLocation(Irp);
254
255 /* Init stack location */
256 IoStack->MajorFunction = IRP_MJ_PNP;
257 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
258 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)Interface;
259 IoStack->Parameters.QueryInterface.InterfaceType = &USB_BUS_INTERFACE_USBDI_GUID;
260 IoStack->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_2;
261 IoStack->Parameters.QueryInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V2);
262
263
264 /* Set completion routine */
265 IoSetCompletionRoutine(Irp,
266 FDO_QueryInterfaceCompletionRoutine,
267 (PVOID)&Event,
268 TRUE,
269 TRUE,
270 TRUE);
271
272 /* Pnp irps have default completion code */
273 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
274
275 /* Call lower device */
276 Status = IoCallDriver(HubDeviceExtension->LowerDeviceObject, Irp);
277 if (Status == STATUS_PENDING)
278 {
279 /* Wait for completion */
280 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
281 }
282
283 /* Get status */
284 Status = Irp->IoStatus.Status;
285
286 /* Complete request */
287 IoFreeIrp(Irp);
288
289 /* Done */
290 return Status;
291 }