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 IN PDEVICE_OBJECT DeviceObject
,
43 IO_STATUS_BLOCK IoStatus
;
44 PIO_STACK_LOCATION IoStack
;
48 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
51 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB
,
66 return STATUS_INSUFFICIENT_RESOURCES
;
69 // get next stack location
70 IoStack
= IoGetNextIrpStackLocation(Irp
);
73 IoStack
->Parameters
.Others
.Argument1
= Urb
;
76 Status
= IoCallDriver(DeviceObject
, Irp
);
78 // wait for the request to finish
79 if (Status
== STATUS_PENDING
)
81 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
85 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
87 if (Status
== STATUS_PENDING
)
90 Status
= IoStatus
.Status
;
99 USBAudioSelectConfiguration(
101 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
103 PDEVICE_EXTENSION DeviceExtension
;
104 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
105 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
;
108 ULONG InterfaceDescriptorCount
;
110 /* alloc item for configuration request */
111 InterfaceList
= AllocFunction(sizeof(USBD_INTERFACE_LIST_ENTRY
) * (ConfigurationDescriptor
->bNumInterfaces
+ 1));
114 /* insufficient resources*/
115 return USBD_STATUS_INSUFFICIENT_RESOURCES
;
118 /* grab interface descriptor */
119 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
120 if (!InterfaceDescriptor
)
122 /* no such interface */
123 return STATUS_INVALID_PARAMETER
;
126 /* lets enumerate the interfaces */
127 InterfaceDescriptorCount
= 0;
128 while (InterfaceDescriptor
!= NULL
)
130 if (InterfaceDescriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL*/
132 InterfaceList
[InterfaceDescriptorCount
++].InterfaceDescriptor
= InterfaceDescriptor
;
134 else if (InterfaceDescriptor
->bInterfaceSubClass
== 0x03) /* MIDI_STREAMING*/
136 InterfaceList
[InterfaceDescriptorCount
++].InterfaceDescriptor
= InterfaceDescriptor
;
139 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
143 Urb
= USBD_CreateConfigurationRequestEx(ConfigurationDescriptor
, InterfaceList
);
147 FreeFunction(InterfaceList
);
148 return STATUS_INSUFFICIENT_RESOURCES
;
151 /* device extension */
152 DeviceExtension
= Device
->Context
;
154 /* submit configuration urb */
155 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
156 if (!NT_SUCCESS(Status
))
160 FreeFunction(InterfaceList
);
164 /* store configuration handle */
165 DeviceExtension
->ConfigurationHandle
= Urb
->UrbSelectConfiguration
.ConfigurationHandle
;
167 /* alloc interface info */
168 DeviceExtension
->InterfaceInfo
= AllocFunction(Urb
->UrbSelectConfiguration
.Interface
.Length
);
169 if (DeviceExtension
->InterfaceInfo
)
171 /* copy interface info */
172 RtlCopyMemory(DeviceExtension
->InterfaceInfo
, &Urb
->UrbSelectConfiguration
.Interface
, Urb
->UrbSelectConfiguration
.Interface
.Length
);
174 return STATUS_SUCCESS
;
183 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
184 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
185 PDEVICE_EXTENSION DeviceExtension
;
189 /* get device extension */
190 DeviceExtension
= Device
->Context
;
193 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
));
197 return STATUS_INSUFFICIENT_RESOURCES
;
200 /* alloc buffer for device descriptor */
201 DeviceDescriptor
= AllocFunction(sizeof(USB_DEVICE_DESCRIPTOR
));
202 if (!DeviceDescriptor
)
204 /* insufficient resources */
206 return STATUS_INSUFFICIENT_RESOURCES
;
209 /* build descriptor request */
210 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_DEVICE_DESCRIPTOR_TYPE
, 0, 0, DeviceDescriptor
, NULL
, sizeof(USB_DEVICE_DESCRIPTOR
), NULL
);
213 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
214 if (!NT_SUCCESS(Status
))
218 FreeFunction(DeviceDescriptor
);
222 /* now allocate some space for partial configuration descriptor */
223 ConfigurationDescriptor
= AllocFunction(sizeof(USB_CONFIGURATION_DESCRIPTOR
));
224 if (!ConfigurationDescriptor
)
228 FreeFunction(DeviceDescriptor
);
232 /* build descriptor request */
233 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_CONFIGURATION_DESCRIPTOR_TYPE
, 0, 0, ConfigurationDescriptor
, NULL
, sizeof(USB_CONFIGURATION_DESCRIPTOR
), NULL
);
236 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
237 if (!NT_SUCCESS(Status
))
241 FreeFunction(DeviceDescriptor
);
242 FreeFunction(ConfigurationDescriptor
);
247 Length
= ConfigurationDescriptor
->wTotalLength
;
249 /* free old descriptor */
250 FreeFunction(ConfigurationDescriptor
);
252 /* now allocate some space for full configuration descriptor */
253 ConfigurationDescriptor
= AllocFunction(Length
);
254 if (!ConfigurationDescriptor
)
258 FreeFunction(DeviceDescriptor
);
262 /* build descriptor request */
263 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_CONFIGURATION_DESCRIPTOR_TYPE
, 0, 0, ConfigurationDescriptor
, NULL
, Length
, NULL
);
266 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
270 if (!NT_SUCCESS(Status
))
273 FreeFunction(DeviceDescriptor
);
274 FreeFunction(ConfigurationDescriptor
);
278 /* lets add to object bag */
279 KsAddItemToObjectBag(Device
->Bag
, DeviceDescriptor
, ExFreePool
);
280 KsAddItemToObjectBag(Device
->Bag
, ConfigurationDescriptor
, ExFreePool
);
282 Status
= USBAudioSelectConfiguration(Device
, ConfigurationDescriptor
);
283 if (NT_SUCCESS(Status
))
286 DeviceExtension
->ConfigurationDescriptor
= ConfigurationDescriptor
;
287 DeviceExtension
->DeviceDescriptor
= DeviceDescriptor
;
296 _In_ PKSDEVICE Device
)
299 DPRINT1("USBAudioAddDevice\n");
300 return STATUS_SUCCESS
;
306 _In_ PKSDEVICE Device
,
308 _In_opt_ PCM_RESOURCE_LIST TranslatedResourceList
,
309 _In_opt_ PCM_RESOURCE_LIST UntranslatedResourceList
)
311 NTSTATUS Status
= STATUS_SUCCESS
;
312 PDEVICE_EXTENSION DeviceExtension
;
314 if (!Device
->Started
)
317 DeviceExtension
= AllocFunction(sizeof(DEVICE_EXTENSION
));
318 if (DeviceExtension
== NULL
)
320 /* insufficient resources */
321 return STATUS_INSUFFICIENT_RESOURCES
;
325 Device
->Context
= DeviceExtension
;
326 DeviceExtension
->LowerDevice
= Device
->NextDeviceObject
;
328 /* add to object bag*/
329 KsAddItemToObjectBag(Device
->Bag
, Device
->Context
, ExFreePool
);
332 Status
= USBAudioStartDevice(Device
);
333 if (NT_SUCCESS(Status
))
335 /* TODO build filter topology and pin descriptors and retrieve interface */
336 Status
= USBAudioCreateFilterContext(Device
);
345 USBAudioPnPQueryStop(
346 _In_ PKSDEVICE Device
,
350 return STATUS_SUCCESS
;
355 USBAudioPnPCancelStop(
356 _In_ PKSDEVICE Device
,
365 _In_ PKSDEVICE Device
,
368 /* TODO: stop device */
374 USBAudioPnPQueryRemove(
375 _In_ PKSDEVICE Device
,
379 return STATUS_SUCCESS
;
385 USBAudioPnPCancelRemove(
386 _In_ PKSDEVICE Device
,
395 _In_ PKSDEVICE Device
,
398 /* TODO: stop device */
404 USBAudioPnPQueryCapabilities(
405 _In_ PKSDEVICE Device
,
407 _Inout_ PDEVICE_CAPABILITIES Capabilities
)
411 return STATUS_SUCCESS
;
416 USBAudioPnPSurpriseRemoval(
417 _In_ PKSDEVICE Device
,
420 /* TODO: stop streams */
426 USBAudioPnPQueryPower(
427 _In_ PKSDEVICE Device
,
429 _In_ DEVICE_POWER_STATE DeviceTo
,
430 _In_ DEVICE_POWER_STATE DeviceFrom
,
431 _In_ SYSTEM_POWER_STATE SystemTo
,
432 _In_ SYSTEM_POWER_STATE SystemFrom
,
433 _In_ POWER_ACTION Action
)
436 return STATUS_SUCCESS
;
442 _In_ PKSDEVICE Device
,
444 _In_ DEVICE_POWER_STATE To
,
445 _In_ DEVICE_POWER_STATE From
)
447 /* TODO: stop streams */
454 IN PDRIVER_OBJECT DriverObject
,
455 IN PUNICODE_STRING RegistryPath
)
460 Status
= KsInitializeDriver(DriverObject
, RegistryPath
, &KsDeviceDescriptor
);
461 if (!NT_SUCCESS(Status
))
463 // failed to initialize driver
464 DPRINT1("Failed to initialize driver with %x\n", Status
);