[USBCCGP]
[reactos.git] / drivers / usb / usbccgp / descriptor.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/descriptor.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 NTAPI
16 USBCCGP_GetDescriptor(
17 IN PDEVICE_OBJECT DeviceObject,
18 IN UCHAR DescriptorType,
19 IN ULONG DescriptorLength,
20 IN UCHAR DescriptorIndex,
21 IN LANGID LanguageId,
22 OUT PVOID *OutDescriptor)
23 {
24 PURB Urb;
25 NTSTATUS Status;
26 PVOID Descriptor;
27
28 //
29 // sanity checks
30 //
31 ASSERT(DeviceObject);
32 ASSERT(OutDescriptor);
33 ASSERT(DescriptorLength);
34
35 //
36 // first allocate descriptor buffer
37 //
38 Descriptor = AllocateItem(NonPagedPool, DescriptorLength);
39 if (!Descriptor)
40 {
41 //
42 // no memory
43 //
44 return STATUS_INSUFFICIENT_RESOURCES;
45 }
46
47 //
48 // allocate urb
49 //
50 Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB));
51 if (!Urb)
52 {
53 //
54 // no memory
55 //
56 FreeItem(Descriptor);
57 return STATUS_INSUFFICIENT_RESOURCES;
58 }
59
60 //
61 // initialize urb
62 //
63 UsbBuildGetDescriptorRequest(Urb,
64 sizeof(Urb->UrbControlDescriptorRequest),
65 DescriptorType,
66 DescriptorIndex,
67 LanguageId,
68 Descriptor,
69 NULL,
70 DescriptorLength,
71 NULL);
72
73 //
74 // submit urb
75 //
76 Status = USBCCGP_SyncUrbRequest(DeviceObject, Urb);
77
78 //
79 // free urb
80 //
81 FreeItem(Urb);
82
83 if (NT_SUCCESS(Status))
84 {
85 //
86 // store result
87 //
88 *OutDescriptor = Descriptor;
89 }
90
91 //
92 // done
93 //
94 return Status;
95 }
96
97
98 NTSTATUS
99 USBCCGP_GetDescriptors(
100 IN PDEVICE_OBJECT DeviceObject)
101 {
102 NTSTATUS Status;
103 PFDO_DEVICE_EXTENSION DeviceExtension;
104 USHORT DescriptorLength;
105
106 //
107 // get device extension
108 //
109 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
110
111 //
112 // first get device descriptor
113 //
114 Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor);
115 if (!NT_SUCCESS(Status))
116 {
117 //
118 // failed to get device descriptor
119 //
120 DeviceExtension->DeviceDescriptor = NULL;
121 return Status;
122 }
123
124 //
125 // now get basic configuration descriptor
126 //
127 Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
128 if (!NT_SUCCESS(Status))
129 {
130 //
131 // failed to get configuration descriptor
132 //
133 FreeItem(DeviceExtension->DeviceDescriptor);
134 DeviceExtension->DeviceDescriptor = NULL;
135 return Status;
136 }
137
138 //
139 // backup length
140 //
141 DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength;
142
143 //
144 // release basic descriptor
145 //
146 FreeItem(DeviceExtension->ConfigurationDescriptor);
147 DeviceExtension->ConfigurationDescriptor = NULL;
148
149 //
150 // allocate full descriptor
151 //
152 Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
153 if (!NT_SUCCESS(Status))
154 {
155 //
156 // failed to get configuration descriptor
157 //
158 FreeItem(DeviceExtension->DeviceDescriptor);
159 DeviceExtension->DeviceDescriptor = NULL;
160 return Status;
161 }
162 return Status;
163 }
164
165 NTSTATUS
166 NTAPI
167 USBCCGP_ScanConfigurationDescriptor(
168 IN OUT PFDO_DEVICE_EXTENSION FDODeviceExtension,
169 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
170 {
171 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
172 ULONG InterfaceIndex = 0;
173
174 //
175 // sanity checks
176 //
177 ASSERT(ConfigurationDescriptor);
178 ASSERT(ConfigurationDescriptor->bNumInterfaces);
179
180 //
181 // allocate array holding the interface descriptors
182 //
183 FDODeviceExtension->InterfaceList = AllocateItem(NonPagedPool, sizeof(USB_CONFIGURATION_DESCRIPTOR) * (ConfigurationDescriptor->bNumInterfaces + 1));
184 if (!FDODeviceExtension->InterfaceList)
185 {
186 //
187 // no memory
188 //
189 return STATUS_INSUFFICIENT_RESOURCES;
190 }
191
192 do
193 {
194 //
195 // parse configuration descriptor
196 //
197 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, InterfaceIndex, 0, -1, -1, -1);
198 if (InterfaceDescriptor)
199 {
200 //
201 // store in interface list
202 //
203 FDODeviceExtension->InterfaceList[FDODeviceExtension->InterfaceListCount].InterfaceDescriptor = InterfaceDescriptor;
204 FDODeviceExtension->InterfaceListCount++;
205 }
206
207 //
208 // move to next interface
209 //
210 InterfaceIndex++;
211
212 }while(InterfaceIndex < ConfigurationDescriptor->bNumInterfaces);
213
214 //
215 // sanity check
216 //
217 ASSERT(FDODeviceExtension->InterfaceListCount);
218
219 //
220 // done
221 //
222 return STATUS_SUCCESS;
223 }
224
225 VOID
226 DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
227 {
228 DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
229 DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
230 DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
231 DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
232 DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
233 DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
234 DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
235 DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
236 DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
237 }
238
239 NTSTATUS
240 USBCCGP_SelectInterface(
241 IN PDEVICE_OBJECT DeviceObject,
242 IN PFDO_DEVICE_EXTENSION DeviceExtension,
243 IN ULONG InterfaceIndex)
244 {
245 NTSTATUS Status;
246 PURB Urb;
247
248 //
249 // allocate urb
250 //
251 Urb = AllocateItem(NonPagedPool, sizeof(struct _URB_SELECT_INTERFACE));
252 if (!Urb)
253 {
254 //
255 // no memory
256 //
257 return STATUS_INSUFFICIENT_RESOURCES;
258 }
259
260 //
261 // now prepare interface urb
262 //
263 UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bInterfaceNumber, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bAlternateSetting);
264
265 //
266 // copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ
267 //
268 RtlCopyMemory(&Urb->UrbSelectInterface.Interface, DeviceExtension->InterfaceList[InterfaceIndex].Interface, DeviceExtension->InterfaceList[InterfaceIndex].Interface->Length);
269
270 //
271 // now select the interface
272 //
273 Status = USBCCGP_SyncUrbRequest(DeviceExtension->NextDeviceObject, Urb);
274
275 //
276 // did it succeeed
277 //
278 if (NT_SUCCESS(Status))
279 {
280 //
281 // update configuration info
282 //
283 ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceList[InterfaceIndex].Interface->Length);
284 RtlCopyMemory(DeviceExtension->InterfaceList[InterfaceIndex].Interface, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length);
285 }
286
287 //
288 // free urb
289 //
290 FreeItem(Urb);
291
292 //
293 // done
294 //
295 return Status;
296 }
297
298 NTSTATUS
299 USBCCGP_SelectConfiguration(
300 IN PDEVICE_OBJECT DeviceObject,
301 IN PFDO_DEVICE_EXTENSION DeviceExtension)
302 {
303 PUSBD_INTERFACE_INFORMATION InterfaceInformation;
304 NTSTATUS Status;
305 PURB Urb;
306 ULONG Index;
307
308 //
309 // now scan configuration descriptors
310 //
311 Status = USBCCGP_ScanConfigurationDescriptor(DeviceExtension, DeviceExtension->ConfigurationDescriptor);
312 if (!NT_SUCCESS(Status))
313 {
314 //
315 // failed to scan
316 //
317 return Status;
318 }
319
320 //
321 // now allocate the urb
322 //
323 Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->InterfaceList);
324 if (!Urb)
325 {
326 //
327 // no memory
328 //
329 return STATUS_INSUFFICIENT_RESOURCES;
330 }
331
332 //
333 // submit urb
334 //
335 Status = USBCCGP_SyncUrbRequest(DeviceExtension->NextDeviceObject, Urb);
336 if (!NT_SUCCESS(Status))
337 {
338 //
339 // failed to set configuration
340 //
341 DPRINT1("USBCCGP_SyncUrbRequest failed to set interface %x\n", Status);
342 ExFreePool(Urb);
343 return Status;
344 }
345
346 //
347 // get interface information
348 //
349 InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
350
351 for(Index = 0; Index < DeviceExtension->InterfaceListCount; Index++)
352 {
353 //
354 // allocate buffer to store interface information
355 //
356 DeviceExtension->InterfaceList[Index].Interface = AllocateItem(NonPagedPool, InterfaceInformation[Index].Length);
357 if (!DeviceExtension->InterfaceList[Index].Interface)
358 {
359 //
360 // no memory
361 //
362 return STATUS_INSUFFICIENT_RESOURCES;
363 }
364
365 //
366 // copy interface information
367 //
368 RtlCopyMemory(DeviceExtension->InterfaceList[Index].Interface, InterfaceInformation, InterfaceInformation->Length);
369 }
370
371 //
372 // store pipe handle
373 //
374 DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
375
376 //
377 // free interface list & urb
378 //
379 ExFreePool(Urb);
380
381 //
382 // done
383 //
384 return Status;
385 }
386