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