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