xref: /haiku/src/add-ons/kernel/drivers/audio/usb/Device.cpp (revision 4b7e219688450694efc9d1890f83f816758c16d3)
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 "Device.h"
10 
11 #include <usb/USB_audio.h>
12 
13 #include "Driver.h"
14 #include "Settings.h"
15 
16 
17 Device::Device(usb_device device)
18 	:
19 	fStatus(B_ERROR),
20 	fOpen(false),
21 	fRemoved(false),
22 	fDevice(device),
23 	fNonBlocking(false),
24 	fAudioControl(this),
25 	fBuffersReadySem(-1)
26 {
27 	const usb_device_descriptor* deviceDescriptor
28 		= gUSBModule->get_device_descriptor(device);
29 
30 	if (deviceDescriptor == NULL) {
31 		TRACE(ERR, "Error of getting USB device descriptor.\n");
32 		return;
33 	}
34 
35 	fVendorID = deviceDescriptor->vendor_id;
36 	fProductID = deviceDescriptor->product_id;
37 	fUSBVersion = deviceDescriptor->usb_version;
38 
39 	fBuffersReadySem = create_sem(0, DRIVER_NAME "_buffers_ready");
40 	if (fBuffersReadySem < B_OK) {
41 		TRACE(ERR, "Error of creating ready "
42 			"buffers semaphore:%#010x\n", fBuffersReadySem);
43 		return;
44 	}
45 
46 	if (_SetupEndpoints() != B_OK)
47 		return;
48 
49 	// must be set in derived class constructor
50 	fStatus = B_OK;
51 }
52 
53 
54 Device::~Device()
55 {
56 	for (Vector<Stream*>::Iterator I = fStreams.Begin();
57 			I != fStreams.End(); I++)
58 		delete *I;
59 
60 	fStreams.MakeEmpty();
61 
62 	if (fBuffersReadySem > B_OK)
63 		delete_sem(fBuffersReadySem);
64 }
65 
66 
67 status_t
68 Device::Open(uint32 flags)
69 {
70 	if (fOpen)
71 		return B_BUSY;
72 	if (fRemoved)
73 		return B_ERROR;
74 
75 	status_t result = StartDevice();
76 	if (result != B_OK)
77 		return result;
78 
79 	// TODO: are we need this???
80 	fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK;
81 	fOpen = true;
82 	return result;
83 }
84 
85 
86 status_t
87 Device::Close()
88 {
89 	if (fRemoved) {
90 		fOpen = false;
91 		return B_OK;
92 	}
93 
94 	for (int i = 0; i < fStreams.Count(); i++)
95 		fStreams[i]->Stop();
96 
97 	fOpen = false;
98 
99 	return StopDevice();
100 }
101 
102 
103 status_t
104 Device::Free()
105 {
106 	return B_OK;
107 }
108 
109 
110 status_t
111 Device::Read(uint8* buffer, size_t* numBytes)
112 {
113 	*numBytes = 0;
114 	return B_IO_ERROR;
115 }
116 
117 
118 status_t
119 Device::Write(const uint8* buffer, size_t* numBytes)
120 {
121 	*numBytes = 0;
122 	return B_IO_ERROR;
123 }
124 
125 
126 status_t
127 Device::Control(uint32 op, void* buffer, size_t length)
128 {
129 	switch (op) {
130 		case B_MULTI_GET_DESCRIPTION:
131 			return _MultiGetDescription((multi_description*)buffer);
132 
133 		case B_MULTI_GET_EVENT_INFO:
134 			TRACE(ERR, "B_MULTI_GET_EVENT_INFO n/i\n");
135 			return B_ERROR;
136 
137 		case B_MULTI_SET_EVENT_INFO:
138 			TRACE(ERR, "B_MULTI_SET_EVENT_INFO n/i\n");
139 			return B_ERROR;
140 
141 		case B_MULTI_GET_EVENT:
142 			TRACE(ERR, "B_MULTI_GET_EVENT n/i\n");
143 			return B_ERROR;
144 
145 		case B_MULTI_GET_ENABLED_CHANNELS:
146 			return _MultiGetEnabledChannels((multi_channel_enable*)buffer);
147 
148 		case B_MULTI_SET_ENABLED_CHANNELS:
149 			return _MultiSetEnabledChannels((multi_channel_enable*)buffer);
150 
151 		case B_MULTI_GET_GLOBAL_FORMAT:
152 			return _MultiGetGlobalFormat((multi_format_info*)buffer);
153 
154 		case B_MULTI_SET_GLOBAL_FORMAT:
155 			return _MultiSetGlobalFormat((multi_format_info*)buffer);
156 
157 		case B_MULTI_GET_CHANNEL_FORMATS:
158 			TRACE(ERR, "B_MULTI_GET_CHANNEL_FORMATS n/i\n");
159 			return B_ERROR;
160 
161 		case B_MULTI_SET_CHANNEL_FORMATS:
162 			TRACE(ERR, "B_MULTI_SET_CHANNEL_FORMATS n/i\n");
163 			return B_ERROR;
164 
165 		case B_MULTI_GET_MIX:
166 			return _MultiGetMix((multi_mix_value_info*)buffer);
167 
168 		case B_MULTI_SET_MIX:
169 			return _MultiSetMix((multi_mix_value_info*)buffer);
170 
171 		case B_MULTI_LIST_MIX_CHANNELS:
172 			TRACE(ERR, "B_MULTI_LIST_MIX_CHANNELS n/i\n");
173 			return B_ERROR;
174 
175 		case B_MULTI_LIST_MIX_CONTROLS:
176 			return _MultiListMixControls((multi_mix_control_info*)buffer);
177 
178 		case B_MULTI_LIST_MIX_CONNECTIONS:
179 			TRACE(ERR, "B_MULTI_LIST_MIX_CONNECTIONS n/i\n");
180 			return B_ERROR;
181 
182 		case B_MULTI_GET_BUFFERS:
183 			// Fill out the struct for the first time; doesn't start anything.
184 			return _MultiGetBuffers((multi_buffer_list*)buffer);
185 
186 		case B_MULTI_SET_BUFFERS:
187 			// Set what buffers to use, if the driver supports soft buffers.
188 			TRACE(ERR, "B_MULTI_SET_BUFFERS n/i\n");
189 			return B_ERROR; /* we do not support soft buffers */
190 
191 		case B_MULTI_SET_START_TIME:
192 			// When to actually start
193 			TRACE(ERR, "B_MULTI_SET_START_TIME n/i\n");
194 			return B_ERROR;
195 
196 		case B_MULTI_BUFFER_EXCHANGE:
197 			// stop and go are derived from this being called
198 			return _MultiBufferExchange((multi_buffer_info*)buffer);
199 
200 		case B_MULTI_BUFFER_FORCE_STOP:
201 			// force stop of playback, nothing in data
202 			return _MultiBufferForceStop();
203 
204 		default:
205 			TRACE(ERR, "Unhandled IOCTL catched: %#010x\n", op);
206 	}
207 
208 	return B_DEV_INVALID_IOCTL;
209 }
210 
211 
212 void
213 Device::Removed()
214 {
215 	fRemoved = true;
216 
217 	for (int i = 0; i < fStreams.Count(); i++)
218 		fStreams[i]->OnRemove();
219 }
220 
221 
222 status_t
223 Device::SetupDevice(bool deviceReplugged)
224 {
225 	return B_OK;
226 }
227 
228 
229 status_t
230 Device::CompareAndReattach(usb_device device)
231 {
232 	const usb_device_descriptor* deviceDescriptor
233 		= gUSBModule->get_device_descriptor(device);
234 
235 	if (deviceDescriptor == NULL) {
236 		TRACE(ERR, "Error of getting USB device descriptor.\n");
237 		return B_ERROR;
238 	}
239 
240 	if (deviceDescriptor->vendor_id != fVendorID
241 		&& deviceDescriptor->product_id != fProductID)
242 		// this certainly isn't the same device
243 		return B_BAD_VALUE;
244 
245 	// this is the same device that was replugged - clear the removed state,
246 	// re- setup the endpoints and transfers and open the device if it was
247 	// previously opened
248 	fDevice = device;
249 	fRemoved = false;
250 	status_t result = _SetupEndpoints();
251 	if (result != B_OK) {
252 		fRemoved = true;
253 		return result;
254 	}
255 
256 	// we need to setup hardware on device replug
257 	result = SetupDevice(true);
258 	if (result != B_OK)
259 		return result;
260 
261 	if (fOpen) {
262 		fOpen = false;
263 		result = Open(fNonBlocking ? O_NONBLOCK : 0);
264 	}
265 
266 	return result;
267 }
268 
269 
270 status_t
271 Device::_MultiGetDescription(multi_description* multiDescription)
272 {
273 	multi_description Description;
274 	if (user_memcpy(&Description, multiDescription,
275 			sizeof(multi_description)) != B_OK)
276 		return B_BAD_ADDRESS;
277 
278 	Description.interface_version = B_CURRENT_INTERFACE_VERSION;
279 	Description.interface_minimum = B_CURRENT_INTERFACE_VERSION;
280 
281 	strlcpy(Description.friendly_name, "USB Audio",
282 		sizeof(Description.friendly_name));
283 
284 	strlcpy(Description.vendor_info, "S.Zharski",
285 		sizeof(Description.vendor_info));
286 
287 	Description.output_channel_count = 0;
288 	Description.input_channel_count = 0;
289 	Description.output_bus_channel_count = 0;
290 	Description.input_bus_channel_count = 0;
291 	Description.aux_bus_channel_count = 0;
292 
293 	Description.output_rates = 0;
294 	Description.input_rates = 0;
295 
296 	Description.min_cvsr_rate = 0;
297 	Description.max_cvsr_rate = 0;
298 
299 	Description.output_formats = 0;
300 	Description.input_formats = 0;
301 	Description.lock_sources = B_MULTI_LOCK_INTERNAL;
302 	Description.timecode_sources = 0;
303 	Description.interface_flags = 0;
304 	Description.start_latency = 3000;
305 
306 	Description.control_panel[0] = '\0';
307 
308 	Vector<_AudioControl*>	USBTerminals;
309 
310 	// channels (USB I/O  terminals) are already in fStreams
311 	// in outputs->inputs order, use them.
312 	for (int i = 0; i < fStreams.Count(); i++) {
313 		uint8 id = fStreams[i]->TerminalLink();
314 		_AudioControl* control = fAudioControl.Find(id);
315 		// if (control->SubType() == USB_AUDIO_AC_OUTPUT_TERMINAL) {
316 		// if (control->SubType() == USB_AUDIO_AC_INPUT_TERMINAL) {
317 		//	USBTerminals.PushFront(control);
318 		//	fStreams[i]->GetFormatsAndRates(Description);
319 		// } else
320 		// if (control->SubType() == IDSInputTerminal) {
321 			USBTerminals.PushBack(control);
322 			fStreams[i]->GetFormatsAndRates(&Description);
323 		// }
324 	}
325 
326 	Vector<multi_channel_info> Channels;
327 	fAudioControl.GetChannelsDescription(Channels, &Description, USBTerminals);
328 	fAudioControl.GetBusChannelsDescription(Channels, &Description );
329 
330 	// Description.request_channel_count = channels + bus_channels;
331 
332 	TraceMultiDescription(&Description, Channels);
333 
334 	if (user_memcpy(multiDescription, &Description,
335 			sizeof(multi_description)) != B_OK)
336 		return B_BAD_ADDRESS;
337 
338 	if (user_memcpy(multiDescription->channels,
339 			&Channels[0], sizeof(multi_channel_info) * min_c(Channels.Count(),
340 			Description.request_channel_count)) != B_OK)
341 		return B_BAD_ADDRESS;
342 
343 	return B_OK;
344 }
345 
346 
347 void
348 Device::TraceMultiDescription(multi_description* Description,
349 		Vector<multi_channel_info>& Channels)
350 {
351 	TRACE(API, "interface_version:%d\n", Description->interface_version);
352 	TRACE(API, "interface_minimum:%d\n", Description->interface_minimum);
353 	TRACE(API, "friendly_name:%s\n", Description->friendly_name);
354 	TRACE(API, "vendor_info:%s\n", Description->vendor_info);
355 	TRACE(API, "output_channel_count:%d\n", Description->output_channel_count);
356 	TRACE(API, "input_channel_count:%d\n", Description->input_channel_count);
357 	TRACE(API, "output_bus_channel_count:%d\n",
358 		Description->output_bus_channel_count);
359 	TRACE(API, "input_bus_channel_count:%d\n",
360 		Description->input_bus_channel_count);
361 	TRACE(API, "aux_bus_channel_count:%d\n", Description->aux_bus_channel_count);
362 	TRACE(API, "output_rates:%#08x\n", Description->output_rates);
363 	TRACE(API, "input_rates:%#08x\n", Description->input_rates);
364 	TRACE(API, "min_cvsr_rate:%f\n", Description->min_cvsr_rate);
365 	TRACE(API, "max_cvsr_rate:%f\n", Description->max_cvsr_rate);
366 	TRACE(API, "output_formats:%#08x\n", Description->output_formats);
367 	TRACE(API, "input_formats:%#08x\n", Description->input_formats);
368 	TRACE(API, "lock_sources:%d\n", Description->lock_sources);
369 	TRACE(API, "timecode_sources:%d\n", Description->timecode_sources);
370 	TRACE(API, "interface_flags:%#08x\n", Description->interface_flags);
371 	TRACE(API, "start_latency:%d\n", Description->start_latency);
372 	TRACE(API, "control_panel:%s\n", Description->control_panel);
373 
374 	// multi_channel_info* Channels = Description->channels;
375 	// for (int i = 0; i < Description->request_channel_count; i++) {
376 	for (int i = 0; i < Channels.Count(); i++) {
377 		TRACE(API, " channel_id:%d\n", Channels[i].channel_id);
378 		TRACE(API, "  kind:%#02x\n", Channels[i].kind);
379 		TRACE(API, "  designations:%#08x\n", Channels[i].designations);
380 		TRACE(API, "  connectors:%#08x\n", Channels[i].connectors);
381 	}
382 
383 	TRACE(API, "request_channel_count:%d\n\n",
384 		Description->request_channel_count);
385 }
386 
387 
388 status_t
389 Device::_MultiGetEnabledChannels(multi_channel_enable* Enable)
390 {
391 	status_t status = B_OK;
392 
393 	Enable->lock_source = B_MULTI_LOCK_INTERNAL;
394 
395 	uint32 offset = 0;
396 	for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
397 		status = fStreams[i]->GetEnabledChannels(offset, Enable);
398 
399 	return status;
400 }
401 
402 
403 status_t
404 Device::_MultiSetEnabledChannels(multi_channel_enable* Enable)
405 {
406 	status_t status = B_OK;
407 	uint32 offset = 0;
408 	for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
409 		status = fStreams[i]->SetEnabledChannels(offset, Enable);
410 
411 	return status;
412 }
413 
414 
415 status_t
416 Device::_MultiGetGlobalFormat(multi_format_info* Format)
417 {
418 	status_t status = B_OK;
419 
420 	Format->output_latency = 0;
421 	Format->input_latency = 0;
422 	Format->timecode_kind = 0;
423 
424 	// uint32 offset = 0;
425 	for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
426 		status = fStreams[i]->GetGlobalFormat(Format);
427 
428 	return status;
429 }
430 
431 
432 status_t
433 Device::_MultiSetGlobalFormat(multi_format_info* Format)
434 {
435 	status_t status = B_OK;
436 
437 	TRACE(API, "output_latency:%lld\n", Format->output_latency);
438 	TRACE(API, "input_latency:%lld\n",  Format->input_latency);
439 	TRACE(API, "timecode_kind:%#08x\n", Format->timecode_kind);
440 
441 	// uint32 offset = 0;
442 	for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
443 		status = fStreams[i]->SetGlobalFormat(Format);
444 
445 	return status;
446 }
447 
448 
449 status_t
450 Device::_MultiGetBuffers(multi_buffer_list* List)
451 {
452 	status_t status = B_OK;
453 
454 	TRACE(API, "info_size:%d\n"
455 	"request_playback_buffers:%d\n"
456 	"request_playback_channels:%d\n"
457 	"request_playback_buffer_size:%d\n"
458 	"request_record_buffers:%d\n"
459 	"request_record_channels:%d\n"
460 	"request_record_buffer_size:%d\n",
461 		List->info_size,
462 		List->request_playback_buffers,
463 		List->request_playback_channels,
464 		List->request_playback_buffer_size,
465 		List->request_record_buffers,
466 		List->request_record_channels,
467 		List->request_record_buffer_size);
468 
469 	List->flags = 0;
470 	List->return_playback_channels = 0;
471 	List->return_record_channels = 0;
472 
473 	for (int i = 0; i < fStreams.Count() && status == B_OK; i++)
474 		status = fStreams[i]->GetBuffers(List);
475 
476 	TRACE(API, "flags:%#x\n"
477 	"return_playback_buffers:%d\n"
478 	"return_playback_channels:%d\n"
479 	"return_playback_buffer_size:%d\n"
480 	"return_record_buffers:%d\n"
481 	"return_record_channels:%d\n"
482 	"return_record_buffer_size:%d\n",
483 		List->flags,
484 		List->return_playback_buffers,
485 		List->return_playback_channels,
486 		List->return_playback_buffer_size,
487 		List->return_record_buffers,
488 		List->return_record_channels,
489 		List->return_record_buffer_size);
490 
491 	TRACE(API, "playback buffers\n");
492 	for (int32_t b = 0; b <  List->return_playback_buffers; b++)
493 		for (int32 c = 0; c < List->return_playback_channels; c++)
494 			TRACE(API, "%d:%d %08x:%d\n", b, c, List->playback_buffers[b][c].base,
495 				List->playback_buffers[b][c].stride);
496 
497 	TRACE(API, "record buffers:\n");
498 	for (int32_t b = 0; b <  List->return_record_buffers; b++)
499 		for (int32 c = 0; c < List->return_record_channels; c++)
500 			TRACE(API, "%d:%d %08x:%d\n", b, c, List->record_buffers[b][c].base,
501 				List->record_buffers[b][c].stride);
502 
503 	return B_OK;
504 }
505 
506 
507 status_t
508 Device::_MultiBufferExchange(multi_buffer_info* multiInfo)
509 {
510 	multi_buffer_info Info;
511 	if (user_memcpy(&Info, multiInfo, sizeof(multi_buffer_info)) != B_OK)
512 		return B_BAD_ADDRESS;
513 
514 	for (int i = 0; i < fStreams.Count(); i++)
515 		if (!fStreams[i]->IsRunning())
516 			fStreams[i]->Start();
517 
518 	status_t status = acquire_sem_etc(fBuffersReadySem, 1,
519 		B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000);
520 	if (status == B_TIMED_OUT) {
521 		TRACE(ERR, "Timeout during buffers exchange.\n");
522 		return status;
523 	}
524 
525 	status = B_ERROR;
526 	for (int i = 0; i < fStreams.Count(); i++)
527 		if (fStreams[i]->ExchangeBuffer(&Info)) {
528 			status = B_OK;
529 			break;
530 		}
531 
532 	if (status != B_OK) {
533 		TRACE(ERR, "Error processing buffers:%08x.\n", status);
534 		return status;
535 	}
536 
537 	if (user_memcpy(multiInfo, &Info, sizeof(multi_buffer_info)) != B_OK)
538 		return B_BAD_ADDRESS;
539 
540 	return status;
541 }
542 
543 
544 status_t
545 Device::_MultiBufferForceStop()
546 {
547 	for (int i = 0; i < fStreams.Count(); i++)
548 		fStreams[i]->Stop();
549 	return B_OK;
550 }
551 
552 
553 status_t
554 Device::_MultiGetMix(multi_mix_value_info* Info)
555 {
556 	return fAudioControl.GetMix(Info);
557 }
558 
559 
560 status_t
561 Device::_MultiSetMix(multi_mix_value_info* Info)
562 {
563 	return fAudioControl.SetMix(Info);
564 }
565 
566 
567 status_t
568 Device::_MultiListMixControls(multi_mix_control_info* Info)
569 {
570 	status_t status = fAudioControl.ListMixControls(Info);
571 	TraceListMixControls(Info);
572 	return status;
573 }
574 
575 
576 void
577 Device::TraceListMixControls(multi_mix_control_info* Info)
578 {
579 	TRACE(MIX, "control_count:%d\n.", Info->control_count);
580 
581 	int32 i = 0;
582 	while (Info->controls[i].id > 0) {
583 		multi_mix_control &c = Info->controls[i];
584 		TRACE(MIX, "id:%#08x\n",		c.id);
585 		TRACE(MIX, "flags:%#08x\n",	c.flags);
586 		TRACE(MIX, "master:%#08x\n", c.master);
587 		TRACE(MIX, "parent:%#08x\n", c.parent);
588 		TRACE(MIX, "string:%d\n",	c.string);
589 		TRACE(MIX, "name:%s\n",		c.name);
590 		i++;
591 	}
592 }
593 
594 
595 status_t
596 Device::_SetupEndpoints()
597 {
598 	const usb_configuration_info* config
599 		= gUSBModule->get_nth_configuration(fDevice, 0);
600 
601 	if (config == NULL) {
602 		TRACE(ERR, "Error of getting USB device configuration.\n");
603 		return B_ERROR;
604 	}
605 
606 	if (config->interface_count <= 0) {
607 		TRACE(ERR, "Error:no interfaces found in USB device configuration\n");
608 		return B_ERROR;
609 	}
610 
611 	for (size_t i = 0; i < config->interface_count; i++) {
612 		usb_interface_info* Interface = config->interface[i].active;
613 		if (Interface->descr->interface_class != USB_AUDIO_INTERFACE_AUDIO_CLASS)
614 			continue;
615 
616 		switch (Interface->descr->interface_subclass) {
617 			case USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS:
618 				fAudioControl.Init(i, Interface);
619 				break;
620 			case USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS:
621 				{
622 					Stream* stream = new(std::nothrow) Stream(this, i,
623 						&config->interface[i]);
624 					if (B_OK == stream->Init()) {
625 						// put the stream in the correct order:
626 						// first output that input ones.
627 						if (stream->IsInput())
628 							fStreams.PushBack(stream);
629 						else
630 							fStreams.PushFront(stream);
631 					} else
632 						delete stream;
633 				}
634 				break;
635 			default:
636 				TRACE(ERR, "Ignore interface of unsupported subclass %#x.\n",
637 					Interface->descr->interface_subclass);
638 				break;
639 		}
640 	}
641 
642 	if (fAudioControl.InitCheck() == B_OK && fStreams.Count() > 0) {
643 		TRACE(INF, "Found device %#06x:%#06x\n", fVendorID, fProductID);
644 		gUSBModule->set_configuration(fDevice, config);
645 
646 		for (int i = 0; i < fStreams.Count(); i++)
647 			fStreams[i]->OnSetConfiguration(fDevice, config);
648 
649 		return B_OK;
650 	}
651 
652 	return B_NO_INIT;
653 }
654 
655 
656 status_t
657 Device::StopDevice()
658 {
659 	status_t result = B_OK;
660 
661 	if (result != B_OK)
662 		TRACE(ERR, "Error of writing %#04x RX Control:%#010x\n", 0, result);
663 
664 	//TRACE_RET(result);
665 	return result;
666 }
667 
668