2 * PROJECT: ReactOS Universal Audio Class Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbaudio/pin.c
5 * PURPOSE: USB Audio device driver.
7 * Johannes Anderwald (johannes.anderwald@reactos.org)
13 GetMaxPacketSizeForInterface(
14 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
15 IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
16 KSPIN_DATAFLOW DataFlow
)
18 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
19 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
21 /* loop descriptors */
22 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
);
23 ASSERT(InterfaceDescriptor
->bNumEndpoints
> 0);
24 while (CommonDescriptor
)
26 if (CommonDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
)
28 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)CommonDescriptor
;
29 return EndpointDescriptor
->wMaxPacketSize
;
32 if (CommonDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
34 /* reached next interface descriptor */
38 if ((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
>= ((ULONG_PTR
)ConfigurationDescriptor
+ ConfigurationDescriptor
->wTotalLength
))
41 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
49 UsbAudioAllocCaptureUrbIso(
50 IN USBD_PIPE_HANDLE PipeHandle
,
51 IN ULONG MaxPacketSize
,
53 IN ULONG BufferLength
,
61 /* calculate packet count */
62 PacketCount
= BufferLength
/ MaxPacketSize
;
64 /* calculate urb size*/
65 UrbSize
= GET_ISO_URB_SIZE(PacketCount
);
68 Urb
= AllocFunction(UrbSize
);
72 return STATUS_INSUFFICIENT_RESOURCES
;
76 Urb
->UrbIsochronousTransfer
.Hdr
.Function
= URB_FUNCTION_ISOCH_TRANSFER
;
77 Urb
->UrbIsochronousTransfer
.Hdr
.Length
= UrbSize
;
78 Urb
->UrbIsochronousTransfer
.PipeHandle
= PipeHandle
;
79 Urb
->UrbIsochronousTransfer
.TransferFlags
= USBD_TRANSFER_DIRECTION_IN
| USBD_START_ISO_TRANSFER_ASAP
;
80 Urb
->UrbIsochronousTransfer
.TransferBufferLength
= BufferLength
;
81 Urb
->UrbIsochronousTransfer
.TransferBuffer
= Buffer
;
82 Urb
->UrbIsochronousTransfer
.NumberOfPackets
= PacketCount
;
84 for (Index
= 0; Index
< PacketCount
; Index
++)
86 Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
= Index
* MaxPacketSize
;
90 return STATUS_SUCCESS
;
101 PUCHAR SampleRateBuffer
;
102 PPIN_CONTEXT PinContext
;
104 PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx
;
106 /* allocate sample rate buffer */
107 SampleRateBuffer
= AllocFunction(sizeof(ULONG
));
108 if (!SampleRateBuffer
)
111 return STATUS_INSUFFICIENT_RESOURCES
;
114 if (IsEqualGUIDAligned(&Pin
->ConnectionFormat
->MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
) &&
115 IsEqualGUIDAligned(&Pin
->ConnectionFormat
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
116 IsEqualGUIDAligned(&Pin
->ConnectionFormat
->Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
))
118 WaveFormatEx
= (PKSDATAFORMAT_WAVEFORMATEX
)Pin
->ConnectionFormat
;
119 SampleRateBuffer
[2] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 16) & 0xFF;
120 SampleRateBuffer
[1] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 8) & 0xFF;
121 SampleRateBuffer
[0] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 0) & 0xFF;
123 /* TODO: verify connection format */
127 /* not supported yet*/
129 FreeFunction(SampleRateBuffer
);
130 return STATUS_INVALID_PARAMETER
;
134 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
138 FreeFunction(SampleRateBuffer
);
139 return STATUS_INSUFFICIENT_RESOURCES
;
143 UsbBuildVendorRequest(Urb
,
144 URB_FUNCTION_CLASS_ENDPOINT
,
145 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
),
146 USBD_TRANSFER_DIRECTION_OUT
,
150 0x81, //FIXME bEndpointAddress
156 /* get pin context */
157 PinContext
= Pin
->Context
;
160 Status
= SubmitUrbSync(PinContext
->LowerDevice
, Urb
);
162 DPRINT1("USBAudioPinSetDataFormat Pin %p Status %x\n", Pin
, Status
);
164 FreeFunction(SampleRateBuffer
);
169 USBAudioSelectAudioStreamingInterface(
170 IN PPIN_CONTEXT PinContext
,
171 IN PDEVICE_EXTENSION DeviceExtension
,
172 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
175 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
178 /* grab interface descriptor */
179 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
180 if (!InterfaceDescriptor
)
182 /* no such interface */
183 return STATUS_INVALID_PARAMETER
;
186 /* FIXME selects the first interface with audio streaming and non zero num of endpoints */
187 while (InterfaceDescriptor
!= NULL
)
189 if (InterfaceDescriptor
->bInterfaceSubClass
== 0x02 /* AUDIO_STREAMING */ && InterfaceDescriptor
->bNumEndpoints
> 0)
193 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
196 if (!InterfaceDescriptor
)
198 /* no such interface */
199 return STATUS_INVALID_PARAMETER
;
202 Urb
= AllocFunction(GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor
->bNumEndpoints
));
206 return USBD_STATUS_INSUFFICIENT_RESOURCES
;
209 /* now prepare interface urb */
210 UsbBuildSelectInterfaceRequest(Urb
, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor
->bNumEndpoints
), DeviceExtension
->ConfigurationHandle
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
);
212 /* copy interface information */
213 RtlCopyMemory(&Urb
->UrbSelectInterface
.Interface
, DeviceExtension
->InterfaceInfo
, DeviceExtension
->InterfaceInfo
->Length
);
215 /* now select the interface */
216 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
218 DPRINT1("USBAudioSelectAudioStreamingInterface Status %x UrbStatus %x\n", Status
, Urb
->UrbSelectInterface
.Hdr
.Status
);
220 /* did it succeeed */
221 if (NT_SUCCESS(Status
))
223 /* update configuration info */
224 ASSERT(Urb
->UrbSelectInterface
.Interface
.Length
== DeviceExtension
->InterfaceInfo
->Length
);
225 RtlCopyMemory(DeviceExtension
->InterfaceInfo
, &Urb
->UrbSelectInterface
.Interface
, Urb
->UrbSelectInterface
.Interface
.Length
);
226 PinContext
->InterfaceDescriptor
= InterfaceDescriptor
;
241 ULONG MaximumPacketSize
;
244 PPIN_CONTEXT PinContext
;
245 PIO_STACK_LOCATION IoStack
;
247 /* set sample rate */
248 Status
= UsbAudioSetFormat(Pin
);
249 if (!NT_SUCCESS(Status
))
255 /* get pin context */
256 PinContext
= Pin
->Context
;
258 MaximumPacketSize
= GetMaxPacketSizeForInterface(PinContext
->DeviceExtension
->ConfigurationDescriptor
, PinContext
->InterfaceDescriptor
, Pin
->DataFlow
);
260 /* calculate buffer size 8 irps * 10 iso packets * max packet size */
261 BufferSize
= 8 * 10 * MaximumPacketSize
;
263 /* allocate pin capture buffer */
264 PinContext
->Buffer
= AllocFunction(BufferSize
);
265 if (!PinContext
->Buffer
)
268 return STATUS_INSUFFICIENT_RESOURCES
;
270 KsAddItemToObjectBag(Pin
->Bag
, PinContext
->Buffer
, ExFreePool
);
273 for (Index
= 0; Index
< 8; Index
++)
276 Irp
= IoAllocateIrp(PinContext
->DeviceExtension
->LowerDevice
->StackSize
, FALSE
);
280 return STATUS_INSUFFICIENT_RESOURCES
;
283 /* insert into irp list */
284 InsertTailList(&PinContext
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
286 /* add to object bag*/
287 KsAddItemToObjectBag(Pin
->Bag
, Irp
, IoFreeIrp
);
289 Status
= UsbAudioAllocCaptureUrbIso(PinContext
->DeviceExtension
->InterfaceInfo
->Pipes
[0].PipeHandle
,
291 &PinContext
->Buffer
[MaximumPacketSize
* 10 * Index
],
292 MaximumPacketSize
* 10,
295 if (NT_SUCCESS(Status
))
297 /* get next stack location */
298 IoStack
= IoGetNextIrpStackLocation(Irp
);
301 IoStack
->Parameters
.Others
.Argument1
= Urb
;
317 return STATUS_NOT_IMPLEMENTED
;
328 PFILTER_CONTEXT FilterContext
;
329 PPIN_CONTEXT PinContext
;
332 Filter
= KsPinGetParentFilter(Pin
);
335 /* invalid parameter */
336 return STATUS_INVALID_PARAMETER
;
339 /* get filter context */
340 FilterContext
= Filter
->Context
;
342 /* allocate pin context */
343 PinContext
= AllocFunction(sizeof(PIN_CONTEXT
));
347 return STATUS_INSUFFICIENT_RESOURCES
;
350 /* init pin context */
351 PinContext
->DeviceExtension
= FilterContext
->DeviceExtension
;
352 PinContext
->LowerDevice
= FilterContext
->LowerDevice
;
353 InitializeListHead(&PinContext
->IrpListHead
);
355 /* store pin context*/
356 Pin
->Context
= PinContext
;
358 /* select streaming interface */
359 Status
= USBAudioSelectAudioStreamingInterface(PinContext
, PinContext
->DeviceExtension
, PinContext
->DeviceExtension
->ConfigurationDescriptor
);
360 if (!NT_SUCCESS(Status
))
366 if (Pin
->DataFlow
== KSPIN_DATAFLOW_OUT
)
368 /* init capture pin */
369 Status
= InitCapturePin(Pin
);
373 /* audio streaming pin*/
374 Status
= InitStreamPin(Pin
);
377 return STATUS_SUCCESS
;
387 return STATUS_NOT_IMPLEMENTED
;
396 return STATUS_SUCCESS
;
410 USBAudioPinSetDataFormat(
412 _In_opt_ PKSDATAFORMAT OldFormat
,
413 _In_opt_ PKSMULTIPLE_ITEM OldAttributeList
,
414 _In_
const KSDATARANGE
* DataRange
,
415 _In_opt_
const KSATTRIBUTE_LIST
* AttributeRange
)
417 if (OldFormat
== NULL
)
419 /* TODO: verify connection format */
421 return STATUS_SUCCESS
;
424 return UsbAudioSetFormat(Pin
);
429 USBAudioPinSetDeviceState(
431 _In_ KSSTATE ToState
,
432 _In_ KSSTATE FromState
)
435 return STATUS_SUCCESS
;