1/*
2 *	Driver for USB Audio Device Class devices.
3 *	Copyright (c) 2009-13 S.Zharski <imker@gmx.li>
4 *	Distributed under the terms of the MIT license.
5 */
6
7
8#include "Stream.h"
9
10#include <kernel.h>
11#include <usb/USB_audio.h>
12
13#include "Device.h"
14#include "Driver.h"
15#include "Settings.h"
16
17
18Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
19	:
20	AudioStreamingInterface(&device->AudioControl(), interface, List),
21	fDevice(device),
22	fStatus(B_NO_INIT),
23	fStreamEndpoint(0),
24	fIsRunning(false),
25	fArea(-1),
26	fKernelArea(-1),
27	fAreaSize(0),
28	fDescriptors(NULL),
29	fDescriptorsCount(0),
30	fCurrentBuffer(0),
31	fSamplesCount(0),
32	fRealTime(0),
33	fStartingFrame(0),
34	fProcessedBuffers(0),
35	fInsideNotify(0)
36{
37}
38
39
40Stream::~Stream()
41{
42	delete_area(fArea);
43	delete_area(fKernelArea);
44	delete fDescriptors;
45}
46
47
48status_t
49Stream::_ChooseAlternate()
50{
51	// lookup alternate with maximal (ch * 100 + resolution)
52	uint16 maxChxRes = 0;
53	for (int i = 0; i < fAlternates.Count(); i++) {
54		if (fAlternates[i]->Interface() == 0) {
55			TRACE(INF, "Ignore alternate %d - zero interface description.\n", i);
56			continue;
57		}
58
59		if (fAlternates[i]->Format() == 0) {
60			TRACE(INF, "Ignore alternate %d - zero format description.\n", i);
61			continue;
62		}
63
64		if (fAlternates[i]->Format()->fFormatType
65				!= USB_AUDIO_FORMAT_TYPE_I) {
66			TRACE(ERR, "Ignore alternate %d - format type %#02x "
67				"is not supported.\n", i, fAlternates[i]->Format()->fFormatType);
68			continue;
69		}
70
71		switch (fAlternates[i]->Interface()->fFormatTag) {
72			case USB_AUDIO_FORMAT_PCM:
73			case USB_AUDIO_FORMAT_PCM8:
74			case USB_AUDIO_FORMAT_IEEE_FLOAT:
75		//	case USB_AUDIO_FORMAT_ALAW:
76		//	case USB_AUDIO_FORMAT_MULAW:
77				break;
78			default:
79				TRACE(ERR, "Ignore alternate %d - format %#04x is not "
80					"supported.\n", i, fAlternates[i]->Interface()->fFormatTag);
81			continue;
82		}
83
84		TypeIFormatDescriptor* format
85			= static_cast<TypeIFormatDescriptor*>(fAlternates[i]->Format());
86
87		if (format->fNumChannels > 2) {
88			TRACE(ERR, "Ignore alternate %d - channel count %d "
89				"is not supported.\n", i, format->fNumChannels);
90			continue;
91		}
92
93		if (fAlternates[i]->Interface()->fFormatTag == USB_AUDIO_FORMAT_PCM) {
94			switch(format->fBitResolution) {
95				default:
96				TRACE(ERR, "Ignore alternate %d - bit resolution %d "
97					"is not supported.\n", i, format->fBitResolution);
98					continue;
99				case 8: case 16: case 18: case 20: case 24: case 32:
100					break;
101			}
102		}
103
104		uint16 chxRes = format->fNumChannels * 100 + format->fBitResolution;
105		if (chxRes > maxChxRes) {
106			maxChxRes = chxRes;
107			fActiveAlternate = i;
108		}
109	}
110
111	if (maxChxRes <= 0) {
112		TRACE(ERR, "No compatible alternate found. "
113			"Stream initialization failed.\n");
114		return B_NO_INIT;
115	}
116
117	const ASEndpointDescriptor* endpoint
118		= fAlternates[fActiveAlternate]->Endpoint();
119	fIsInput = (endpoint->fEndpointAddress & USB_ENDPOINT_ADDR_DIR_IN)
120		== USB_ENDPOINT_ADDR_DIR_IN;
121
122	if (fIsInput)
123		fCurrentBuffer = (size_t)-1;
124
125	TRACE(INF, "Alternate %d EP:%x selected for %s!\n",
126		fActiveAlternate, endpoint->fEndpointAddress,
127		fIsInput ? "recording" : "playback");
128
129	return B_OK;
130}
131
132
133status_t
134Stream::Init()
135{
136	fStatus = _ChooseAlternate();
137	return fStatus;
138}
139
140
141void
142Stream::OnRemove()
143{
144	// the transfer callback schedule traffic - so we must ensure that we are
145	// not inside the callback anymore before returning, as we would otherwise
146	// violate the promise not to use any of the pipes after returning from the
147	// removed callback
148	while (atomic_get(&fInsideNotify) != 0)
149		snooze(100);
150
151	gUSBModule->cancel_queued_transfers(fStreamEndpoint);
152}
153
154
155status_t
156Stream::_SetupBuffers()
157{
158	// allocate buffer for worst (maximal size) case
159	TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>(
160		fAlternates[fActiveAlternate]->Format());
161
162	uint32 samplingRate = fAlternates[fActiveAlternate]->GetSamplingRate();
163	uint32 sampleSize = format->fNumChannels * format->fSubframeSize;
164
165	// data size pro 1 ms USB 1 frame or 1/8 ms USB 2 microframe
166	size_t packetSize = samplingRate * sampleSize
167		/ (fDevice->fUSBVersion < 0x0200 ? 1000 : 8000);
168	TRACE(INF, "packetSize:%ld\n", packetSize);
169
170	if (packetSize == 0) {
171		TRACE(ERR, "computed packet size is 0!");
172		return B_BAD_VALUE;
173	}
174
175	if (fArea != -1) {
176		Stop();
177		delete_area(fArea);
178		delete_area(fKernelArea);
179		delete fDescriptors;
180	}
181
182	fAreaSize = sampleSize * kSamplesBufferSize * kSamplesBufferCount;
183	TRACE(INF, "estimate fAreaSize:%d\n", fAreaSize);
184
185	// round up to B_PAGE_SIZE and create area
186	fAreaSize = (fAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1);
187	TRACE(INF, "rounded up fAreaSize:%d\n", fAreaSize);
188
189	fArea = create_area(fIsInput ? DRIVER_NAME "_record_area"
190		: DRIVER_NAME "_playback_area", (void**)&fBuffers,
191		B_ANY_ADDRESS, fAreaSize, B_NO_LOCK,
192		B_READ_AREA | B_WRITE_AREA);
193	if (fArea < 0) {
194		TRACE(ERR, "Error of creating %#x - "
195			"bytes size buffer area:%#010x\n", fAreaSize, fArea);
196		fStatus = fArea;
197		return fStatus;
198	}
199
200	// The kernel is not allowed to touch userspace areas, so we clone our
201	// area into kernel space.
202	fKernelArea = clone_area("usb_audio cloned area", (void**)&fKernelBuffers,
203		B_ANY_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, fArea);
204	if (fKernelArea < 0) {
205		fStatus = fKernelArea;
206		return fStatus;
207	}
208
209	TRACE(INF, "Created area id:%d at addr:%#010x size:%#010lx\n",
210		fArea, fDescriptors, fAreaSize);
211
212	fDescriptorsCount = fAreaSize / packetSize;
213	// we need same size sub-buffers. round it
214	fDescriptorsCount = ROUNDDOWN(fDescriptorsCount, kSamplesBufferCount);
215	fDescriptors = new usb_iso_packet_descriptor[fDescriptorsCount];
216	TRACE(INF, "descriptorsCount:%d\n", fDescriptorsCount);
217
218	// samples count
219	fSamplesCount = fDescriptorsCount * packetSize / sampleSize;
220	TRACE(INF, "samplesCount:%d\n", fSamplesCount);
221
222	// initialize descriptors array
223	for (size_t i = 0; i < fDescriptorsCount; i++) {
224		fDescriptors[i].request_length = packetSize;
225		fDescriptors[i].actual_length = 0;
226		fDescriptors[i].status = B_OK;
227	}
228
229	return fStatus;
230}
231
232
233status_t
234Stream::OnSetConfiguration(usb_device device,
235		const usb_configuration_info* config)
236{
237	if (config == NULL) {
238		TRACE(ERR, "NULL configuration. Not set.\n");
239		return B_ERROR;
240	}
241
242	usb_interface_info* interface
243		= &config->interface[fInterface].alt[fActiveAlternate];
244	if (interface == NULL) {
245		TRACE(ERR, "NULL interface. Not set.\n");
246		return B_ERROR;
247	}
248
249	status_t status = gUSBModule->set_alt_interface(device, interface);
250	uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress;
251
252	TRACE(INF, "set_alt_interface %x\n", status);
253
254	for (size_t i = 0; i < interface->endpoint_count; i++) {
255		if (address == interface->endpoint[i].descr->endpoint_address) {
256			fStreamEndpoint = interface->endpoint[i].handle;
257			TRACE(INF, "%s Stream Endpoint [address %#04x] handle is: %#010x.\n",
258				fIsInput ? "Input" : "Output", address, fStreamEndpoint);
259			return B_OK;
260		}
261	}
262
263	TRACE(INF, "%s Stream Endpoint [address %#04x] was not found.\n",
264		fIsInput ? "Input" : "Output", address);
265	return B_ERROR;
266}
267
268
269status_t
270Stream::Start()
271{
272	status_t result = B_BUSY;
273	if (!fIsRunning) {
274		for (size_t i = 0; i < kSamplesBufferCount; i++)
275			result = _QueueNextTransfer(i, i == 0);
276		fIsRunning = result == B_OK;
277	}
278	return result;
279}
280
281
282status_t
283Stream::Stop()
284{
285	if (fIsRunning) {
286		// wait until possible notification handling finished...
287		while (atomic_get(&fInsideNotify) != 0)
288			snooze(100);
289		fIsRunning = false;
290	}
291	gUSBModule->cancel_queued_transfers(fStreamEndpoint);
292
293	return B_OK;
294}
295
296
297status_t
298Stream::_QueueNextTransfer(size_t queuedBuffer, bool start)
299{
300	TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>(
301		fAlternates[fActiveAlternate]->Format());
302
303	size_t bufferSize = format->fNumChannels * format->fSubframeSize;
304	bufferSize *= fSamplesCount / kSamplesBufferCount;
305
306	size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
307
308	TRACE(DTA, "buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n",
309		fKernelBuffers + bufferSize * queuedBuffer, bufferSize,
310		fDescriptors + queuedBuffer * packetsCount, packetsCount);
311
312	status_t status = gUSBModule->queue_isochronous(fStreamEndpoint,
313		fKernelBuffers + bufferSize * queuedBuffer, bufferSize,
314		fDescriptors + queuedBuffer * packetsCount, packetsCount,
315		&fStartingFrame, USB_ISO_ASAP,
316		Stream::_TransferCallback, this);
317
318	TRACE(DTA, "frame:%#010x\n", fStartingFrame);
319	return status;
320}
321
322
323void
324Stream::_TransferCallback(void* cookie, status_t status, void* data,
325	size_t actualLength)
326{
327	Stream* stream = (Stream*)cookie;
328
329	TRACE(status == B_OK ? DTA : ERR,
330		"stream:%010x: status:%#010x, data:%#010x, len:%d\n",
331		stream->fStreamEndpoint, status, data, actualLength);
332
333	atomic_add(&stream->fInsideNotify, 1);
334	if (status == B_CANCELED || stream->fDevice->fRemoved || !stream->fIsRunning) {
335		TRACE(ERR, "Cancelled: c:%p st:%#010x, data:%#010x, len:%d\n",
336			cookie, status, data, actualLength);
337		atomic_add(&stream->fInsideNotify, -1);
338		return;
339	}
340
341#if 0
342	stream->_DumpDescriptors();
343#endif
344
345	if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount)
346		TRACE(ERR, "Processed buffers overflow:%d\n", stream->fProcessedBuffers);
347	stream->fRealTime = system_time();
348
349	release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
350
351	stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount;
352	status = stream->_QueueNextTransfer(stream->fCurrentBuffer, false);
353
354	atomic_add(&stream->fInsideNotify, -1);
355}
356
357
358void
359Stream::_DumpDescriptors()
360{
361	for (size_t i = 0; i < fDescriptorsCount; i++)
362		TRACE(ISO, "%d:req_len:%d; act_len:%d; stat:%#010x\n", i,
363			fDescriptors[i].request_length,	fDescriptors[i].actual_length,
364			fDescriptors[i].status);
365}
366
367
368status_t
369Stream::GetEnabledChannels(uint32& offset, multi_channel_enable* Enable)
370{
371	AudioChannelCluster* cluster = ChannelCluster();
372	if (cluster == 0)
373		return B_ERROR;
374
375	for (size_t i = 0; i < cluster->ChannelsCount(); i++) {
376		B_SET_CHANNEL(Enable->enable_bits, offset++, true);
377		TRACE(INF, "Report channel %d as enabled.\n", offset);
378	}
379
380	return B_OK;
381}
382
383
384status_t
385Stream::SetEnabledChannels(uint32& offset, multi_channel_enable* Enable)
386{
387	AudioChannelCluster* cluster = ChannelCluster();
388	if (cluster == 0)
389		return B_ERROR;
390
391	for (size_t i = 0; i < cluster->ChannelsCount(); i++, offset++) {
392		TRACE(INF, "%s channel %d.\n",
393			(B_TEST_CHANNEL(Enable->enable_bits, offset)
394			? "Enable" : "Disable"), offset + 1);
395	}
396
397	return B_OK;
398}
399
400
401status_t
402Stream::GetGlobalFormat(multi_format_info* Format)
403{
404	_multi_format* format = fIsInput ? &Format->input : &Format->output;
405	format->cvsr = fAlternates[fActiveAlternate]->GetSamplingRate();
406	format->rate = fAlternates[fActiveAlternate]->GetSamplingRateId(0);
407	format->format = fAlternates[fActiveAlternate]->GetFormatId();
408	TRACE(INF, "%s.rate:%d cvsr:%f format:%#08x\n",
409		fIsInput ? "input" : "ouput",
410		format->rate, format->cvsr, format->format);
411	return B_OK;
412}
413
414
415status_t
416Stream::SetGlobalFormat(multi_format_info* Format)
417{
418	_multi_format* format = fIsInput ? &Format->input : &Format->output;
419	AudioStreamAlternate* alternate = fAlternates[fActiveAlternate];
420	if (format->rate == alternate->GetSamplingRateId(0)
421			&& format->format == alternate->GetFormatId()) {
422		TRACE(INF, "No changes required\n");
423		return B_OK;
424	}
425
426	alternate->SetSamplingRateById(format->rate);
427	alternate->SetFormatId(format->format);
428	TRACE(INF, "%s.rate:%d cvsr:%f format:%#08x\n",
429		fIsInput ? "input" : "ouput",
430		format->rate, format->cvsr, format->format);
431
432	// cancel data flow - it will be rewaked at next buffer exchange call
433	Stop();
434
435	// TODO: wait for cancelling?
436
437	// layout of buffers should be adjusted after changing sampling rate/format
438	status_t status = _SetupBuffers();
439
440	if (status != B_OK)
441		return status;
442
443	// set endpoint speed
444	uint32 samplingRate = fAlternates[fActiveAlternate]->GetSamplingRate();
445	size_t actualLength = 0;
446	usb_audio_sampling_freq freq = _ASFormatDescriptor::GetSamFreq(samplingRate);
447	uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress;
448
449	status = gUSBModule->send_request(fDevice->fDevice,
450		USB_REQTYPE_CLASS | USB_REQTYPE_ENDPOINT_OUT,
451		USB_AUDIO_SET_CUR, USB_AUDIO_SAMPLING_FREQ_CONTROL << 8,
452		address, sizeof(freq), &freq, &actualLength);
453
454	TRACE(ERR, "set_speed %02x%02x%02x for ep %#x %d: %s\n",
455		freq.bytes[0], freq.bytes[1], freq.bytes[2],
456		address, actualLength, strerror(status));
457	return status;
458}
459
460
461status_t
462Stream::GetBuffers(multi_buffer_list* List)
463{
464// TODO: check the available buffers count!
465	if (fAreaSize == 0)
466		return B_NO_INIT;
467
468	int32 startChannel = List->return_playback_channels;
469	buffer_desc** Buffers = List->playback_buffers;
470
471	if (fIsInput) {
472		List->flags |= B_MULTI_BUFFER_RECORD;
473		List->return_record_buffer_size = fSamplesCount / kSamplesBufferCount;
474		List->return_record_buffers = kSamplesBufferCount;
475		startChannel = List->return_record_channels;
476		Buffers = List->record_buffers;
477
478		TRACE(DTA, "flags:%#10x\nreturn_record_buffer_size:%#010x\n"
479			"return_record_buffers:%#010x\n", List->flags,
480			List->return_record_buffer_size, List->return_record_buffers);
481	} else {
482		List->flags |= B_MULTI_BUFFER_PLAYBACK;
483		List->return_playback_buffer_size = fSamplesCount / kSamplesBufferCount;
484		List->return_playback_buffers = kSamplesBufferCount;
485
486		TRACE(DTA, "flags:%#10x\nreturn_playback_buffer_size:%#010x\n"
487			"return_playback_buffers:%#010x\n", List->flags,
488			List->return_playback_buffer_size, List->return_playback_buffers);
489	}
490
491	TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>(
492		fAlternates[fActiveAlternate]->Format());
493
494	// [buffer][channel] init buffers
495	for (size_t buffer = 0; buffer < kSamplesBufferCount; buffer++) {
496		TRACE(DTA, "%s buffer #%d:\n", fIsInput ? "input" : "output", buffer + 1);
497
498		struct buffer_desc descs[format->fNumChannels];
499		for (size_t channel = startChannel;
500				channel < format->fNumChannels; channel++) {
501			// init stride to the same for all buffers
502			uint32 stride = format->fSubframeSize * format->fNumChannels;
503			descs[channel].stride = stride;
504
505			size_t bufferSize = (fSamplesCount / kSamplesBufferCount) * stride;
506			descs[channel].base = (char*)fBuffers;
507			descs[channel].base += buffer * bufferSize;
508			descs[channel].base += channel * format->fSubframeSize;
509
510			TRACE(DTA, "%d:%d: base:%#010x; stride:%#010x\n", buffer, channel,
511				descs[channel].base, descs[channel].stride);
512		}
513		if (!IS_USER_ADDRESS(Buffers[buffer])
514				|| user_memcpy(Buffers[buffer], descs, sizeof(descs)) < B_OK) {
515			return B_BAD_ADDRESS;
516		}
517	}
518
519	if (fIsInput) {
520		List->return_record_channels += format->fNumChannels;
521		TRACE(MIX, "return_record_channels:%#010x\n",
522			List->return_record_channels);
523	} else {
524		List->return_playback_channels += format->fNumChannels;
525		TRACE(MIX, "return_playback_channels:%#010x\n",
526			List->return_playback_channels);
527	}
528
529	return B_OK;
530}
531
532
533bool
534Stream::ExchangeBuffer(multi_buffer_info* Info)
535{
536	if (atomic_get(&fProcessedBuffers) <= 0)
537		return false;
538
539	if (fIsInput) {
540		Info->recorded_real_time = fRealTime;
541		Info->recorded_frames_count += fSamplesCount / kSamplesBufferCount;
542		Info->record_buffer_cycle = fCurrentBuffer;
543	} else {
544		Info->played_real_time = fRealTime;
545		Info->played_frames_count += fSamplesCount / kSamplesBufferCount;
546		Info->playback_buffer_cycle = fCurrentBuffer;
547	}
548
549	atomic_add(&fProcessedBuffers, -1);
550
551	return true;
552}
553