xref: /haiku/src/add-ons/kernel/drivers/audio/usb/Stream.cpp (revision b785b0cf1ccb28e2a40bf5ef797c98b112534edf)
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 
Stream(Device * device,size_t interface,usb_interface_list * List)18 Stream::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 
~Stream()40 Stream::~Stream()
41 {
42 	delete_area(fArea);
43 	delete_area(fKernelArea);
44 	delete fDescriptors;
45 }
46 
47 
48 status_t
_ChooseAlternate()49 Stream::_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 
133 status_t
Init()134 Stream::Init()
135 {
136 	fStatus = _ChooseAlternate();
137 	return fStatus;
138 }
139 
140 
141 void
OnRemove()142 Stream::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 
155 status_t
_SetupBuffers()156 Stream::_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 
233 status_t
OnSetConfiguration(usb_device device,const usb_configuration_info * config)234 Stream::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 
269 status_t
Start()270 Stream::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 
282 status_t
Stop()283 Stream::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 
297 status_t
_QueueNextTransfer(size_t queuedBuffer,bool start)298 Stream::_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 
323 void
_TransferCallback(void * cookie,status_t status,void * data,size_t actualLength)324 Stream::_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 
358 void
_DumpDescriptors()359 Stream::_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 
368 status_t
GetEnabledChannels(uint32 & offset,multi_channel_enable * Enable)369 Stream::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 
384 status_t
SetEnabledChannels(uint32 & offset,multi_channel_enable * Enable)385 Stream::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 
401 status_t
GetGlobalFormat(multi_format_info * Format)402 Stream::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 
415 status_t
SetGlobalFormat(multi_format_info * Format)416 Stream::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 
461 status_t
GetBuffers(multi_buffer_list * List)462 Stream::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 
533 bool
ExchangeBuffer(multi_buffer_info * Info)534 Stream::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