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