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
);
82 Status
= IoStatus
.Status
;
91 USBAudioSelectConfiguration(
93 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
95 PDEVICE_EXTENSION DeviceExtension
;
96 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
97 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
;
100 ULONG InterfaceDescriptorCount
;
102 /* alloc item for configuration request */
103 InterfaceList
= AllocFunction(sizeof(USBD_INTERFACE_LIST_ENTRY
) * (ConfigurationDescriptor
->bNumInterfaces
+ 1));
106 /* insufficient resources*/
107 return USBD_STATUS_INSUFFICIENT_RESOURCES
;
110 /* grab interface descriptor */
111 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
112 if (!InterfaceDescriptor
)
114 /* no such interface */
115 return STATUS_INVALID_PARAMETER
;
118 /* lets enumerate the interfaces */
119 InterfaceDescriptorCount
= 0;
120 while (InterfaceDescriptor
!= NULL
)
122 if (InterfaceDescriptor
->bInterfaceSubClass
== 0x01) /* AUDIO_CONTROL*/
124 InterfaceList
[InterfaceDescriptorCount
++].InterfaceDescriptor
= InterfaceDescriptor
;
126 else if (InterfaceDescriptor
->bInterfaceSubClass
== 0x03) /* MIDI_STREAMING*/
128 InterfaceList
[InterfaceDescriptorCount
++].InterfaceDescriptor
= InterfaceDescriptor
;
131 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
135 Urb
= USBD_CreateConfigurationRequestEx(ConfigurationDescriptor
, InterfaceList
);
139 FreeFunction(InterfaceList
);
140 return STATUS_INSUFFICIENT_RESOURCES
;
143 /* device extension */
144 DeviceExtension
= Device
->Context
;
146 /* submit configuration urb */
147 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
148 if (!NT_SUCCESS(Status
))
152 FreeFunction(InterfaceList
);
156 /* store configuration handle */
157 DeviceExtension
->ConfigurationHandle
= Urb
->UrbSelectConfiguration
.ConfigurationHandle
;
159 /* alloc interface info */
160 DeviceExtension
->InterfaceInfo
= AllocFunction(Urb
->UrbSelectConfiguration
.Interface
.Length
);
161 if (DeviceExtension
->InterfaceInfo
)
163 /* copy interface info */
164 RtlCopyMemory(DeviceExtension
->InterfaceInfo
, &Urb
->UrbSelectConfiguration
.Interface
, Urb
->UrbSelectConfiguration
.Interface
.Length
);
166 return STATUS_SUCCESS
;
175 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
;
176 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
;
177 PDEVICE_EXTENSION DeviceExtension
;
181 /* get device extension */
182 DeviceExtension
= Device
->Context
;
185 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
));
189 return STATUS_INSUFFICIENT_RESOURCES
;
192 /* alloc buffer for device descriptor */
193 DeviceDescriptor
= AllocFunction(sizeof(USB_DEVICE_DESCRIPTOR
));
194 if (!DeviceDescriptor
)
196 /* insufficient resources */
198 return STATUS_INSUFFICIENT_RESOURCES
;
201 /* build descriptor request */
202 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_DEVICE_DESCRIPTOR_TYPE
, 0, 0, DeviceDescriptor
, NULL
, sizeof(USB_DEVICE_DESCRIPTOR
), NULL
);
205 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
206 if (!NT_SUCCESS(Status
))
210 FreeFunction(DeviceDescriptor
);
214 /* now allocate some space for partial configuration descriptor */
215 ConfigurationDescriptor
= AllocFunction(sizeof(USB_CONFIGURATION_DESCRIPTOR
));
216 if (!ConfigurationDescriptor
)
220 FreeFunction(DeviceDescriptor
);
224 /* build descriptor request */
225 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_CONFIGURATION_DESCRIPTOR_TYPE
, 0, 0, ConfigurationDescriptor
, NULL
, sizeof(USB_CONFIGURATION_DESCRIPTOR
), NULL
);
228 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
229 if (!NT_SUCCESS(Status
))
233 FreeFunction(DeviceDescriptor
);
234 FreeFunction(ConfigurationDescriptor
);
239 Length
= ConfigurationDescriptor
->wTotalLength
;
241 /* free old descriptor */
242 FreeFunction(ConfigurationDescriptor
);
244 /* now allocate some space for full configuration descriptor */
245 ConfigurationDescriptor
= AllocFunction(Length
);
246 if (!ConfigurationDescriptor
)
250 FreeFunction(DeviceDescriptor
);
254 /* build descriptor request */
255 UsbBuildGetDescriptorRequest(Urb
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
), USB_CONFIGURATION_DESCRIPTOR_TYPE
, 0, 0, ConfigurationDescriptor
, NULL
, Length
, NULL
);
258 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
262 if (!NT_SUCCESS(Status
))
265 FreeFunction(DeviceDescriptor
);
266 FreeFunction(ConfigurationDescriptor
);
270 /* lets add to object bag */
271 KsAddItemToObjectBag(Device
->Bag
, DeviceDescriptor
, ExFreePool
);
272 KsAddItemToObjectBag(Device
->Bag
, ConfigurationDescriptor
, ExFreePool
);
274 Status
= USBAudioSelectConfiguration(Device
, ConfigurationDescriptor
);
275 if (NT_SUCCESS(Status
))
278 DeviceExtension
->ConfigurationDescriptor
= ConfigurationDescriptor
;
279 DeviceExtension
->DeviceDescriptor
= DeviceDescriptor
;
288 _In_ PKSDEVICE Device
)
291 DPRINT1("USBAudioAddDevice\n");
292 return STATUS_SUCCESS
;
298 _In_ PKSDEVICE Device
,
300 _In_opt_ PCM_RESOURCE_LIST TranslatedResourceList
,
301 _In_opt_ PCM_RESOURCE_LIST UntranslatedResourceList
)
303 NTSTATUS Status
= STATUS_SUCCESS
;
304 PDEVICE_EXTENSION DeviceExtension
;
306 if (!Device
->Started
)
309 DeviceExtension
= AllocFunction(sizeof(DEVICE_EXTENSION
));
310 if (DeviceExtension
== NULL
)
312 /* insufficient resources */
313 return STATUS_INSUFFICIENT_RESOURCES
;
317 Device
->Context
= DeviceExtension
;
318 DeviceExtension
->LowerDevice
= Device
->NextDeviceObject
;
320 /* add to object bag*/
321 KsAddItemToObjectBag(Device
->Bag
, Device
->Context
, ExFreePool
);
324 Status
= USBAudioStartDevice(Device
);
325 if (NT_SUCCESS(Status
))
327 /* TODO build filter topology and pin descriptors and retrieve interface */
328 Status
= USBAudioCreateFilterContext(Device
);
337 USBAudioPnPQueryStop(
338 _In_ PKSDEVICE Device
,
342 return STATUS_SUCCESS
;
347 USBAudioPnPCancelStop(
348 _In_ PKSDEVICE Device
,
357 _In_ PKSDEVICE Device
,
360 /* TODO: stop device */
366 USBAudioPnPQueryRemove(
367 _In_ PKSDEVICE Device
,
371 return STATUS_SUCCESS
;
377 USBAudioPnPCancelRemove(
378 _In_ PKSDEVICE Device
,
387 _In_ PKSDEVICE Device
,
390 /* TODO: stop device */
396 USBAudioPnPQueryCapabilities(
397 _In_ PKSDEVICE Device
,
399 _Inout_ PDEVICE_CAPABILITIES Capabilities
)
403 return STATUS_SUCCESS
;
408 USBAudioPnPSurpriseRemoval(
409 _In_ PKSDEVICE Device
,
412 /* TODO: stop streams */
418 USBAudioPnPQueryPower(
419 _In_ PKSDEVICE Device
,
421 _In_ DEVICE_POWER_STATE DeviceTo
,
422 _In_ DEVICE_POWER_STATE DeviceFrom
,
423 _In_ SYSTEM_POWER_STATE SystemTo
,
424 _In_ SYSTEM_POWER_STATE SystemFrom
,
425 _In_ POWER_ACTION Action
)
428 return STATUS_SUCCESS
;
434 _In_ PKSDEVICE Device
,
436 _In_ DEVICE_POWER_STATE To
,
437 _In_ DEVICE_POWER_STATE From
)
439 /* TODO: stop streams */
446 IN PDRIVER_OBJECT DriverObject
,
447 IN PUNICODE_STRING RegistryPath
)
452 Status
= KsInitializeDriver(DriverObject
, RegistryPath
, &KsDeviceDescriptor
);
453 if (!NT_SUCCESS(Status
))
455 // failed to initialize driver
456 DPRINT1("Failed to initialize driver with %x\n", Status
);