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