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