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
18Device::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
60Device::~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
73status_t
74Device::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
92status_t
93Device::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
109status_t
110Device::Free()
111{
112	return B_OK;
113}
114
115
116status_t
117Device::Read(uint8* buffer, size_t* numBytes)
118{
119	*numBytes = 0;
120	return B_IO_ERROR;
121}
122
123
124status_t
125Device::Write(const uint8* buffer, size_t* numBytes)
126{
127	*numBytes = 0;
128	return B_IO_ERROR;
129}
130
131
132status_t
133Device::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
405void
406Device::Removed()
407{
408	fRemoved = true;
409
410	for (int i = 0; i < fStreams.Count(); i++)
411		fStreams[i]->OnRemove();
412}
413
414
415status_t
416Device::SetupDevice(bool deviceReplugged)
417{
418	return B_OK;
419}
420
421
422status_t
423Device::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
463status_t
464Device::_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
532void
533Device::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
573status_t
574Device::_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
588status_t
589Device::_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
600status_t
601Device::_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
617status_t
618Device::_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
634status_t
635Device::_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
693status_t
694Device::_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
734status_t
735Device::_MultiBufferForceStop()
736{
737	for (int i = 0; i < fStreams.Count(); i++)
738		fStreams[i]->Stop();
739	return B_OK;
740}
741
742
743status_t
744Device::_MultiGetMix(multi_mix_value_info* Info)
745{
746	return fAudioControl.GetMix(Info);
747}
748
749
750status_t
751Device::_MultiSetMix(multi_mix_value_info* Info)
752{
753	return fAudioControl.SetMix(Info);
754}
755
756
757status_t
758Device::_MultiListMixControls(multi_mix_control_info* Info)
759{
760	status_t status = fAudioControl.ListMixControls(Info);
761	TraceListMixControls(Info);
762	return status;
763}
764
765
766void
767Device::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
785status_t
786Device::_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
851status_t
852Device::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