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.
7 * Johannes Anderwald (johannes.anderwald@reactos.org)
12 static KSDEVICE_DISPATCH KsDeviceDispatch
= {
17 USBAudioPnPCancelStop
,
19 USBAudioPnPQueryRemove
,
20 USBAudioPnPCancelRemove
,
22 USBAudioPnPQueryCapabilities
,
23 USBAudioPnPSurpriseRemoval
,
24 USBAudioPnPQueryPower
,
28 static KSDEVICE_DESCRIPTOR KsDeviceDescriptor
= {
32 0x100, //KSDEVICE_DESCRIPTOR_VERSION,
38 USBAudioCancelCompleteSynch(
39 IN PDEVICE_OBJECT DeviceObject
,
44 KeSetEvent(Context
, 0, FALSE
);
47 return STATUS_MORE_PROCESSING_REQUIRED
;
57 PDEVICE_EXTENSION DeviceExtension
;
58 IO_STATUS_BLOCK IoStatus
;
59 PIO_STACK_LOCATION IoStack
;
63 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
65 // get device extension
66 DeviceExtension
= (PDEVICE_EXTENSION
)Device
->Context
;
69 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB
,
70 DeviceExtension
->LowerDevice
,
84 return STATUS_INSUFFICIENT_RESOURCES
;
87 // get next stack location
88 IoStack
= IoGetNextIrpStackLocation(Irp
);
91 IoStack
->Parameters
.Others
.Argument1
= Urb
;
93 // set completion routine
94 IoSetCompletionRoutine(Irp
, USBAudioCancelCompleteSynch
, &Event
, TRUE
, TRUE
, TRUE
);
97 Status
= IoCallDriver(DeviceExtension
->LowerDevice
, Irp
);
99 // wait for the request to finish
100 if (Status
== STATUS_PENDING
)
102 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
106 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
108 if (Status
== STATUS_PENDING
)
111 Status
= IoStatus
.Status
;
120 USBAudioSelectConfiguration(
122 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
124 PDEVICE_EXTENSION DeviceExtension
;
125 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
126 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
;
129 ULONG InterfaceDescriptorCount
;
131 /* alloc item for configuration request */
132 InterfaceList
= AllocFunction(sizeof(USBD_INTERFACE_LIST_ENTRY
) * (ConfigurationDescriptor
->bNumInterfaces
+ 1));
135 /* insufficient resources*/
136 return USBD_STATUS_INSUFFICIENT_RESOURCES
;
139 /* grab interface descriptor */
140 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
141 if (!InterfaceDescriptor
)
143 /* no such interface */
144 return STATUS_INVALID_PARAMETER
;
147 /* lets enumerate the interfaces */
148 InterfaceDescriptorCount
= 0;
149 while (InterfaceDescriptor
!= NULL
)
151 if (InterfaceDescriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL*/
153 InterfaceList
[InterfaceDescriptorCount
++].InterfaceDescriptor
= InterfaceDescriptor
;
155 else if (InterfaceDescriptor
->bInterfaceSubClass
== 0x03) /* MIDI_STREAMING*/
157 InterfaceList
[InterfaceDescriptorCount
++].InterfaceDescriptor
= InterfaceDescriptor
;
160 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
164 Urb
= USBD_CreateConfigurationRequestEx(ConfigurationDescriptor
, InterfaceList
);
168 FreeFunction(InterfaceList
);
169 return STATUS_INSUFFICIENT_RESOURCES
;
172 /* submit configuration urb */
173 Status
= SubmitUrbSync(Device
, Urb
);
174 if (!NT_SUCCESS(Status
))
178 FreeFunction(InterfaceList
);
182 /* store configuration handle */
183 DeviceExtension
= Device
->Context
;
184 DeviceExtension
->ConfigurationHandle
= Urb
->UrbSelectConfiguration
.ConfigurationHandle
;
186 /* alloc interface info */
187 DeviceExtension
->InterfaceInfo
= AllocFunction(Urb
->UrbSelectConfiguration
.Interface
.Length
);
188 if (DeviceExtension
->InterfaceInfo
)
190 /* copy interface info */
191 RtlCopyMemory(DeviceExtension
->InterfaceInfo
, &Urb
->UrbSelectConfiguration
.Interface
, Urb
->UrbSelectConfiguration
.Interface
.Length
);
193 return STATUS_SUCCESS
;
202 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
203 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
204 PDEVICE_EXTENSION DeviceExtension
;
209 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
));
213 return STATUS_INSUFFICIENT_RESOURCES
;
216 /* alloc buffer for device descriptor */
217 DeviceDescriptor
= AllocFunction(sizeof(USB_DEVICE_DESCRIPTOR
));
218 if (!DeviceDescriptor
)
220 /* insufficient resources */
222 return STATUS_INSUFFICIENT_RESOURCES
;
225 /* build descriptor request */
226 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_DEVICE_DESCRIPTOR_TYPE
, 0, 0, DeviceDescriptor
, NULL
, sizeof(USB_DEVICE_DESCRIPTOR
), NULL
);
229 Status
= SubmitUrbSync(Device
, Urb
);
230 if (!NT_SUCCESS(Status
))
234 FreeFunction(DeviceDescriptor
);
238 /* now allocate some space for partial configuration descriptor */
239 ConfigurationDescriptor
= AllocFunction(sizeof(USB_CONFIGURATION_DESCRIPTOR
));
240 if (!ConfigurationDescriptor
)
244 FreeFunction(DeviceDescriptor
);
248 /* build descriptor request */
249 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_DEVICE_DESCRIPTOR_TYPE
, 0, 0, ConfigurationDescriptor
, NULL
, sizeof(USB_CONFIGURATION_DESCRIPTOR
), NULL
);
252 Status
= SubmitUrbSync(Device
, Urb
);
253 if (!NT_SUCCESS(Status
))
257 FreeFunction(DeviceDescriptor
);
258 FreeFunction(ConfigurationDescriptor
);
263 Length
= ConfigurationDescriptor
->wTotalLength
;
265 /* free old descriptor */
266 FreeFunction(ConfigurationDescriptor
);
268 /* now allocate some space for full configuration descriptor */
269 ConfigurationDescriptor
= AllocFunction(Length
);
270 if (!ConfigurationDescriptor
)
274 FreeFunction(DeviceDescriptor
);
278 /* build descriptor request */
279 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_DEVICE_DESCRIPTOR_TYPE
, 0, 0, ConfigurationDescriptor
, NULL
, Length
, NULL
);
282 Status
= SubmitUrbSync(Device
, Urb
);
286 if (!NT_SUCCESS(Status
))
289 FreeFunction(DeviceDescriptor
);
290 FreeFunction(ConfigurationDescriptor
);
294 /* lets add to object bag */
295 KsAddItemToObjectBag(Device
->Bag
, DeviceDescriptor
, ExFreePool
);
296 KsAddItemToObjectBag(Device
->Bag
, ConfigurationDescriptor
, ExFreePool
);
298 Status
= USBAudioSelectConfiguration(Device
, ConfigurationDescriptor
);
299 if (NT_SUCCESS(Status
))
301 DeviceExtension
= Device
->Context
;
302 DeviceExtension
->ConfigurationDescriptor
= ConfigurationDescriptor
;
303 DeviceExtension
->DeviceDescriptor
= DeviceDescriptor
;
312 _In_ PKSDEVICE Device
)
315 DPRINT1("USBAudioAddDevice\n");
316 return STATUS_SUCCESS
;
322 _In_ PKSDEVICE Device
,
324 _In_opt_ PCM_RESOURCE_LIST TranslatedResourceList
,
325 _In_opt_ PCM_RESOURCE_LIST UntranslatedResourceList
)
327 NTSTATUS Status
= STATUS_SUCCESS
;
328 PDEVICE_EXTENSION DeviceExtension
;
330 if (!Device
->Started
)
333 DeviceExtension
= AllocFunction(sizeof(DEVICE_EXTENSION
));
334 if (DeviceExtension
== NULL
)
336 /* insufficient resources */
337 return STATUS_INSUFFICIENT_RESOURCES
;
341 Device
->Context
= DeviceExtension
;
342 DeviceExtension
->LowerDevice
= Device
->NextDeviceObject
;
344 /* add to object bag*/
345 KsAddItemToObjectBag(Device
->Bag
, Device
->Context
, ExFreePool
);
348 Status
= USBAudioStartDevice(Device
);
349 if (NT_SUCCESS(Status
))
351 /* TODO build filter topology and pin descriptors and retrieve interface */
361 USBAudioPnPQueryStop(
362 _In_ PKSDEVICE Device
,
366 return STATUS_SUCCESS
;
371 USBAudioPnPCancelStop(
372 _In_ PKSDEVICE Device
,
381 _In_ PKSDEVICE Device
,
384 /* TODO: stop device */
390 USBAudioPnPQueryRemove(
391 _In_ PKSDEVICE Device
,
395 return STATUS_SUCCESS
;
401 USBAudioPnPCancelRemove(
402 _In_ PKSDEVICE Device
,
411 _In_ PKSDEVICE Device
,
414 /* TODO: stop device */
420 USBAudioPnPQueryCapabilities(
421 _In_ PKSDEVICE Device
,
423 _Inout_ PDEVICE_CAPABILITIES Capabilities
)
427 return STATUS_SUCCESS
;
432 USBAudioPnPSurpriseRemoval(
433 _In_ PKSDEVICE Device
,
436 /* TODO: stop streams */
442 USBAudioPnPQueryPower(
443 _In_ PKSDEVICE Device
,
445 _In_ DEVICE_POWER_STATE DeviceTo
,
446 _In_ DEVICE_POWER_STATE DeviceFrom
,
447 _In_ SYSTEM_POWER_STATE SystemTo
,
448 _In_ SYSTEM_POWER_STATE SystemFrom
,
449 _In_ POWER_ACTION Action
)
452 return STATUS_SUCCESS
;
458 _In_ PKSDEVICE Device
,
460 _In_ DEVICE_POWER_STATE To
,
461 _In_ DEVICE_POWER_STATE From
)
463 /* TODO: stop streams */
470 IN PDRIVER_OBJECT DriverObject
,
471 IN PUNICODE_STRING RegistryPath
)
476 Status
= KsInitializeDriver(DriverObject
, RegistryPath
, &KsDeviceDescriptor
);
477 if (!NT_SUCCESS(Status
))
479 // failed to initialize driver
480 DPRINT1("Failed to initialize driver with %x\n", Status
);