ReactOS  0.4.14-dev-552-g2fad488
usbaudio.c
Go to the documentation of this file.
1 /*
2 * PROJECT: ReactOS Universal Audio Class Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbaudio/usbaudio.c
5 * PURPOSE: USB Audio device driver.
6 * PROGRAMMERS:
7 * Johannes Anderwald (johannes.anderwald@reactos.org)
8 */
9 
10 #include "usbaudio.h"
11 
12 static KSDEVICE_DISPATCH KsDeviceDispatch = {
15  NULL,
26 };
27 
28 static KSDEVICE_DESCRIPTOR KsDeviceDescriptor = {
30  0,
31  NULL,
32  0x100, //KSDEVICE_DESCRIPTOR_VERSION,
33  0
34 };
35 
39  IN PURB Urb)
40 {
41  PIRP Irp;
42  KEVENT Event;
44  PIO_STACK_LOCATION IoStack;
46 
47  // init event
49 
50  // build irp
53  NULL,
54  0,
55  NULL,
56  0,
57  TRUE,
58  &Event,
59  &IoStatus);
60 
61  if (!Irp)
62  {
63  //
64  // no memory
65  //
67  }
68 
69  // get next stack location
70  IoStack = IoGetNextIrpStackLocation(Irp);
71 
72  // store urb
73  IoStack->Parameters.Others.Argument1 = Urb;
74 
75  // call driver
77 
78  // wait for the request to finish
79  if (Status == STATUS_PENDING)
80  {
82  Status = IoStatus.Status;
83  }
84 
85  // done
86  return Status;
87 }
88 
90 NTAPI
92  IN PKSDEVICE Device,
93  IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
94 {
95  PDEVICE_EXTENSION DeviceExtension;
96  PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
98  PURB Urb;
100  ULONG InterfaceDescriptorCount;
101 
102  /* alloc item for configuration request */
103  InterfaceList = AllocFunction(sizeof(USBD_INTERFACE_LIST_ENTRY) * (ConfigurationDescriptor->bNumInterfaces + 1));
104  if (!InterfaceList)
105  {
106  /* insufficient resources*/
108  }
109 
110  /* grab interface descriptor */
111  InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
112  if (!InterfaceDescriptor)
113  {
114  /* no such interface */
116  }
117 
118  /* lets enumerate the interfaces */
119  InterfaceDescriptorCount = 0;
120  while (InterfaceDescriptor != NULL)
121  {
122  if (InterfaceDescriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL*/
123  {
124  InterfaceList[InterfaceDescriptorCount++].InterfaceDescriptor = InterfaceDescriptor;
125  }
126  else if (InterfaceDescriptor->bInterfaceSubClass == 0x03) /* MIDI_STREAMING*/
127  {
128  InterfaceList[InterfaceDescriptorCount++].InterfaceDescriptor = InterfaceDescriptor;
129  }
130 
131  InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
132  }
133 
134  /* build urb */
135  Urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, InterfaceList);
136  if (!Urb)
137  {
138  /* no memory */
141  }
142 
143  /* device extension */
144  DeviceExtension = Device->Context;
145 
146  /* submit configuration urb */
147  Status = SubmitUrbSync(DeviceExtension->LowerDevice, Urb);
148  if (!NT_SUCCESS(Status))
149  {
150  /* free resources */
151  ExFreePool(Urb);
153  return Status;
154  }
155 
156  /* store configuration handle */
157  DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
158 
159  /* alloc interface info */
160  DeviceExtension->InterfaceInfo = AllocFunction(Urb->UrbSelectConfiguration.Interface.Length);
161  if (DeviceExtension->InterfaceInfo)
162  {
163  /* copy interface info */
164  RtlCopyMemory(DeviceExtension->InterfaceInfo, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length);
165  }
166  return STATUS_SUCCESS;
167 }
168 
169 NTSTATUS
170 NTAPI
172  IN PKSDEVICE Device)
173 {
174  PURB Urb;
176  PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
177  PDEVICE_EXTENSION DeviceExtension;
179  ULONG Length;
180 
181  /* get device extension */
182  DeviceExtension = Device->Context;
183 
184  /* allocate urb */
185  Urb = AllocFunction(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
186  if (!Urb)
187  {
188  /* no memory */
190  }
191 
192  /* alloc buffer for device descriptor */
194  if (!DeviceDescriptor)
195  {
196  /* insufficient resources */
197  FreeFunction(Urb);
199  }
200 
201  /* build descriptor request */
203 
204  /* submit urb */
205  Status = SubmitUrbSync(DeviceExtension->LowerDevice, Urb);
206  if (!NT_SUCCESS(Status))
207  {
208  /* free resources */
209  FreeFunction(Urb);
211  return Status;
212  }
213 
214  /* now allocate some space for partial configuration descriptor */
215  ConfigurationDescriptor = AllocFunction(sizeof(USB_CONFIGURATION_DESCRIPTOR));
216  if (!ConfigurationDescriptor)
217  {
218  /* free resources */
219  FreeFunction(Urb);
221  return Status;
222  }
223 
224  /* build descriptor request */
226 
227  /* submit urb */
228  Status = SubmitUrbSync(DeviceExtension->LowerDevice, Urb);
229  if (!NT_SUCCESS(Status))
230  {
231  /* free resources */
232  FreeFunction(Urb);
234  FreeFunction(ConfigurationDescriptor);
235  return Status;
236  }
237 
238  /* backup length */
239  Length = ConfigurationDescriptor->wTotalLength;
240 
241  /* free old descriptor */
242  FreeFunction(ConfigurationDescriptor);
243 
244  /* now allocate some space for full configuration descriptor */
245  ConfigurationDescriptor = AllocFunction(Length);
246  if (!ConfigurationDescriptor)
247  {
248  /* free resources */
249  FreeFunction(Urb);
251  return Status;
252  }
253 
254  /* build descriptor request */
256 
257  /* submit urb */
258  Status = SubmitUrbSync(DeviceExtension->LowerDevice, Urb);
259 
260  /* free urb */
261  FreeFunction(Urb);
262  if (!NT_SUCCESS(Status))
263  {
264  /* free resources */
266  FreeFunction(ConfigurationDescriptor);
267  return Status;
268  }
269 
270  /* lets add to object bag */
272  KsAddItemToObjectBag(Device->Bag, ConfigurationDescriptor, ExFreePool);
273 
274  Status = USBAudioSelectConfiguration(Device, ConfigurationDescriptor);
275  if (NT_SUCCESS(Status))
276  {
277 
278  DeviceExtension->ConfigurationDescriptor = ConfigurationDescriptor;
279  DeviceExtension->DeviceDescriptor = DeviceDescriptor;
280  }
281  return Status;
282 }
283 
284 
285 NTSTATUS
286 NTAPI
288  _In_ PKSDEVICE Device)
289 {
290  /* no op */
291  DPRINT1("USBAudioAddDevice\n");
292  return STATUS_SUCCESS;
293 }
294 
295 NTSTATUS
296 NTAPI
298  _In_ PKSDEVICE Device,
299  _In_ PIRP Irp,
300  _In_opt_ PCM_RESOURCE_LIST TranslatedResourceList,
301  _In_opt_ PCM_RESOURCE_LIST UntranslatedResourceList)
302 {
304  PDEVICE_EXTENSION DeviceExtension;
305 
306  if (!Device->Started)
307  {
308  /* alloc context */
309  DeviceExtension = AllocFunction(sizeof(DEVICE_EXTENSION));
310  if (DeviceExtension == NULL)
311  {
312  /* insufficient resources */
314  }
315 
316  /* init context */
317  Device->Context = DeviceExtension;
318  DeviceExtension->LowerDevice = Device->NextDeviceObject;
319 
320  /* add to object bag*/
321  KsAddItemToObjectBag(Device->Bag, Device->Context, ExFreePool);
322 
323  /* init device*/
325  if (NT_SUCCESS(Status))
326  {
327  /* TODO retrieve interface */
329  }
330  }
331 
332  return Status;
333 }
334 
335 NTSTATUS
336 NTAPI
338  _In_ PKSDEVICE Device,
339  _In_ PIRP Irp)
340 {
341  /* no op */
342  return STATUS_SUCCESS;
343 }
344 
345 VOID
346 NTAPI
348  _In_ PKSDEVICE Device,
349  _In_ PIRP Irp)
350 {
351  /* no op */
352 }
353 
354 VOID
355 NTAPI
357  _In_ PKSDEVICE Device,
358  _In_ PIRP Irp)
359 {
360  /* TODO: stop device */
362 }
363 
364 NTSTATUS
365 NTAPI
367  _In_ PKSDEVICE Device,
368  _In_ PIRP Irp)
369 {
370  /* no op */
371  return STATUS_SUCCESS;
372 }
373 
374 
375 VOID
376 NTAPI
378  _In_ PKSDEVICE Device,
379  _In_ PIRP Irp)
380 {
381  /* no op */
382 }
383 
384 VOID
385 NTAPI
387  _In_ PKSDEVICE Device,
388  _In_ PIRP Irp)
389 {
390  /* TODO: stop device */
392 }
393 
394 NTSTATUS
395 NTAPI
397  _In_ PKSDEVICE Device,
398  _In_ PIRP Irp,
400 {
401  /* TODO: set caps */
403  return STATUS_SUCCESS;
404 }
405 
406 VOID
407 NTAPI
409  _In_ PKSDEVICE Device,
410  _In_ PIRP Irp)
411 {
412  /* TODO: stop streams */
414 }
415 
416 NTSTATUS
417 NTAPI
419  _In_ PKSDEVICE Device,
420  _In_ PIRP Irp,
421  _In_ DEVICE_POWER_STATE DeviceTo,
422  _In_ DEVICE_POWER_STATE DeviceFrom,
423  _In_ SYSTEM_POWER_STATE SystemTo,
424  _In_ SYSTEM_POWER_STATE SystemFrom,
426 {
427  /* no op */
428  return STATUS_SUCCESS;
429 }
430 
431 VOID
432 NTAPI
434  _In_ PKSDEVICE Device,
435  _In_ PIRP Irp,
438 {
439  /* TODO: stop streams */
441 }
442 
443 NTSTATUS
444 NTAPI
448 {
450 
451  // initialize driver
453  if (!NT_SUCCESS(Status))
454  {
455  // failed to initialize driver
456  DPRINT1("Failed to initialize driver with %x\n", Status);
457  return Status;
458  }
459  return Status;
460 }
VOID NTAPI USBAudioPnPStop(_In_ PKSDEVICE Device, _In_ PIRP Irp)
Definition: usbaudio.c:356
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI KsAddItemToObjectBag(IN KSOBJECT_BAG ObjectBag, IN PVOID Item, IN PFNKSFREE Free OPTIONAL)
Definition: bag.c:86
NTSTATUS NTAPI USBAudioSelectConfiguration(IN PKSDEVICE Device, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
Definition: usbaudio.c:91
NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
Definition: usbaudio.c:445
_In_ PIRP _In_ PDEVICE_OBJECT Device
Definition: fatprocs.h:2020
#define IOCTL_INTERNAL_USB_SUBMIT_URB
Definition: usbioctl.h:32
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG IN BOOLEAN OUT PIO_STATUS_BLOCK IoStatus
Definition: fatprocs.h:2650
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS NTAPI USBAudioCreateFilterContext(PKSDEVICE Device)
Definition: filter.c:1525
NTSTATUS NTAPI USBAudioPnPQueryCapabilities(_In_ PKSDEVICE Device, _In_ PIRP Irp, _Inout_ PDEVICE_CAPABILITIES Capabilities)
Definition: usbaudio.c:396
NTSTATUS NTAPI USBAudioAddDevice(_In_ PKSDEVICE Device)
Definition: usbaudio.c:287
_In_ PUSBD_INTERFACE_LIST_ENTRY InterfaceList
Definition: usbdlib.h:168
LONG NTSTATUS
Definition: precomp.h:26
#define UsbBuildGetDescriptorRequest(urb, length, descriptorType, descriptorIndex, languageId, transferBuffer, transferBufferMDL, transferBufferLength, link)
Definition: usbdlib.h:23
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
enum _SYSTEM_POWER_STATE SYSTEM_POWER_STATE
#define USB_DEVICE_CLASS_AUDIO
Definition: usb100.h:91
#define _In_opt_
Definition: no_sal2.h:213
NTSTATUS NTAPI USBAudioPnPQueryStop(_In_ PKSDEVICE Device, _In_ PIRP Irp)
Definition: usbaudio.c:337
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define USBD_STATUS_INSUFFICIENT_RESOURCES
Definition: usb.h:204
VOID NTAPI FreeFunction(IN PVOID Item)
Definition: hid.c:53
Definition: usbdlib.h:7
NTSTATUS NTAPI USBAudioPnPQueryRemove(_In_ PKSDEVICE Device, _In_ PIRP Irp)
Definition: usbaudio.c:366
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define USB_DEVICE_DESCRIPTOR_TYPE
Definition: usb100.h:49
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
#define USB_CONFIGURATION_DESCRIPTOR_TYPE
Definition: usb100.h:50
VOID NTAPI USBAudioPnPCancelRemove(_In_ PKSDEVICE Device, _In_ PIRP Irp)
Definition: usbaudio.c:377
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
smooth NULL
Definition: ftsmooth.c:416
static KSDEVICE_DESCRIPTOR KsDeviceDescriptor
Definition: usbaudio.c:28
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
NTSTATUS NTAPI USBAudioPnPStart(_In_ PKSDEVICE Device, _In_ PIRP Irp, _In_opt_ PCM_RESOURCE_LIST TranslatedResourceList, _In_opt_ PCM_RESOURCE_LIST UntranslatedResourceList)
Definition: usbaudio.c:297
enum _DEVICE_POWER_STATE DEVICE_POWER_STATE
const KSDEVICE_DESCRIPTOR DeviceDescriptor
Definition: splitter.c:257
PUSB_INTERFACE_DESCRIPTOR NTAPI USBD_ParseConfigurationDescriptorEx(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PVOID StartPosition, LONG InterfaceNumber, LONG AlternateSetting, LONG InterfaceClass, LONG InterfaceSubClass, LONG InterfaceProtocol)
Definition: usbd.c:496
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG Action
Definition: fsrtlfuncs.h:738
#define _Inout_
Definition: no_sal2.h:244
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
NTSTATUS NTAPI USBAudioStartDevice(IN PKSDEVICE Device)
Definition: usbaudio.c:171
VOID NTAPI USBAudioPnPSetPower(_In_ PKSDEVICE Device, _In_ PIRP Irp, _In_ DEVICE_POWER_STATE To, _In_ DEVICE_POWER_STATE From)
Definition: usbaudio.c:433
POWER_ACTION
Definition: ntpoapi.h:122
NTSTATUS SubmitUrbSync(IN PDEVICE_OBJECT DeviceObject, IN PURB Urb)
Definition: usbaudio.c:37
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
* PDEVICE_CAPABILITIES
Definition: iotypes.h:928
Status
Definition: gdiplustypes.h:24
VOID NTAPI USBAudioPnPSurpriseRemoval(_In_ PKSDEVICE Device, _In_ PIRP Irp)
Definition: usbaudio.c:408
#define _In_
Definition: no_sal2.h:204
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
NTSTATUS NTAPI USBAudioPnPQueryPower(_In_ PKSDEVICE Device, _In_ PIRP Irp, _In_ DEVICE_POWER_STATE DeviceTo, _In_ DEVICE_POWER_STATE DeviceFrom, _In_ SYSTEM_POWER_STATE SystemTo, _In_ SYSTEM_POWER_STATE SystemFrom, _In_ POWER_ACTION Action)
Definition: usbaudio.c:418
PVOID NTAPI AllocFunction(IN ULONG ItemSize)
Definition: hid.c:45
struct _URB_SELECT_CONFIGURATION UrbSelectConfiguration
Definition: usb.h:533
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
Definition: usbdlib.h:8
Definition: usb.h:529
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define DPRINT1
Definition: precomp.h:8
KSDDKAPI NTSTATUS NTAPI KsInitializeDriver(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath, IN const KSDEVICE_DESCRIPTOR *Descriptor OPTIONAL)
Definition: driver.c:155
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:114
_In_ PUNICODE_STRING RegistryPath
Definition: wmip.h:27
VOID NTAPI USBAudioPnPRemove(_In_ PKSDEVICE Device, _In_ PIRP Irp)
Definition: usbaudio.c:386
static KSDEVICE_DISPATCH KsDeviceDispatch
Definition: usbaudio.c:12
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
PURB NTAPI USBD_CreateConfigurationRequestEx(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSBD_INTERFACE_LIST_ENTRY InterfaceList)
Definition: usbd.c:329
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
VOID NTAPI USBAudioPnPCancelStop(_In_ PKSDEVICE Device, _In_ PIRP Irp)
Definition: usbaudio.c:347