1/*
2 *	Driver for USB Audio Device Class devices.
3 *	Copyright (c) 2009-13 S.Zharski <imker@gmx.li>
4 *	Distributed under the tems of the MIT license.
5 *
6 */
7
8#include "AudioControlInterface.h"
9
10#include <usb/USB_audio.h>
11
12#include "Device.h"
13#include "Driver.h"
14#include "Settings.h"
15
16
17// control id is encoded in following way
18//	CS	CN	ID	IF where:
19//	CS				- control selector
20//		CN			- channel
21//			ID		- id of this feature unit
22//				IF	- interface
23
24#define CTL_ID(_CS, _CN, _ID, _IF) \
25	(((_CS) << 24) | ((_CN) << 16) | ((_ID) << 8) | (_IF))
26
27#define CS_FROM_CTLID(_ID) (0xff & ((_ID) >> 24))
28#define CN_FROM_CTLID(_ID) (0xff & ((_ID) >> 16))
29#define ID_FROM_CTLID(_ID) (0xff & ((_ID) >> 8))
30
31#define REQ_VALUE(_ID) (0xffff & ((_ID) >> 16))
32#define REQ_INDEX(_ID) (0xffff & (_ID))
33
34
35struct _Designation {
36	uint32 ch;
37	uint32 bus;
38} gDesignations[AudioControlInterface::kChannels] = {
39	{ B_CHANNEL_LEFT,				B_CHANNEL_STEREO_BUS	},
40	{ B_CHANNEL_RIGHT,				B_CHANNEL_STEREO_BUS	},
41	{ B_CHANNEL_CENTER,				B_CHANNEL_SURROUND_BUS	},
42	{ B_CHANNEL_SUB,				B_CHANNEL_SURROUND_BUS	},
43	{ B_CHANNEL_REARLEFT,			B_CHANNEL_STEREO_BUS	},
44	{ B_CHANNEL_REARRIGHT,			B_CHANNEL_STEREO_BUS	},
45	{ B_CHANNEL_FRONT_LEFT_CENTER,	B_CHANNEL_STEREO_BUS	},
46	{ B_CHANNEL_FRONT_RIGHT_CENTER,	B_CHANNEL_STEREO_BUS	},
47	{ B_CHANNEL_BACK_CENTER,		B_CHANNEL_SURROUND_BUS	},
48	{ B_CHANNEL_SIDE_LEFT,			B_CHANNEL_STEREO_BUS	},
49	{ B_CHANNEL_SIDE_RIGHT,			B_CHANNEL_STEREO_BUS	},
50	{ B_CHANNEL_TOP_CENTER,			B_CHANNEL_SURROUND_BUS	},
51	{ B_CHANNEL_TOP_FRONT_LEFT,		B_CHANNEL_STEREO_BUS	},
52	{ B_CHANNEL_TOP_FRONT_CENTER,	B_CHANNEL_SURROUND_BUS	},
53	{ B_CHANNEL_TOP_FRONT_RIGHT,	B_CHANNEL_STEREO_BUS	},
54	{ B_CHANNEL_TOP_BACK_LEFT,		B_CHANNEL_STEREO_BUS	},
55	{ B_CHANNEL_TOP_BACK_CENTER,	B_CHANNEL_SURROUND_BUS	},
56	{ B_CHANNEL_TOP_BACK_RIGHT,		B_CHANNEL_STEREO_BUS	}
57};
58
59
60struct _MixPageCollector : public Vector<multi_mix_control> {
61	_MixPageCollector(const char* pageName) {
62		multi_mix_control page;
63		memset(&page, 0, sizeof(multi_mix_control));
64		page.flags = B_MULTI_MIX_GROUP;
65		strlcpy(page.name, pageName, sizeof(page.name));
66		PushBack(page);
67	}
68};
69
70
71_AudioControl::_AudioControl(AudioControlInterface*	interface,
72		usb_audiocontrol_header_descriptor* Header)
73	:
74	fStatus(B_NO_INIT),
75	fInterface(interface),
76	fSubType(Header->descriptor_subtype),
77	fID(0),
78	fSourceID(0),
79	fStringIndex(0)
80{
81}
82
83
84_AudioControl::~_AudioControl()
85{
86}
87
88
89AudioChannelCluster*
90_AudioControl::OutCluster()
91{
92	if (SourceID() == 0 || fInterface == NULL)
93		return NULL;
94
95	_AudioControl* control = fInterface->Find(SourceID());
96	if (control == NULL)
97		return NULL;
98
99	return control->OutCluster();
100}
101
102
103AudioChannelCluster::AudioChannelCluster()
104	:
105	fOutChannelsNumber(0),
106	fChannelsConfig(0),
107	fChannelNames(0)
108{
109}
110
111
112AudioChannelCluster::~AudioChannelCluster()
113{
114}
115
116
117bool
118AudioChannelCluster::HasChannel(uint32 location)
119{
120	return (fChannelsConfig & location) == location;
121}
122
123
124_Terminal::_Terminal(AudioControlInterface*	interface,
125	usb_audiocontrol_header_descriptor* Header)
126	:
127	_AudioControl(interface, Header),
128	fTerminalType(0),
129	fAssociatedTerminal(0),
130	fClockSourceId(0),
131	fControlsBitmap(0)
132{
133}
134
135
136_Terminal::~_Terminal()
137{
138}
139
140
141const char*
142_Terminal::Name()
143{
144	return _GetTerminalDescription(fTerminalType);
145}
146
147
148bool
149_Terminal::IsUSBIO()
150{
151	return (fTerminalType & 0xff00) == USB_AUDIO_UNDEFINED_USB_IO;
152}
153
154
155const char*
156_Terminal::_GetTerminalDescription(uint16 TerminalType)
157{
158	static struct _pair {
159		uint16 type;
160		const char* description;
161	} termInfoPairs[] = {
162		// USB Terminal Types
163		{ USB_AUDIO_UNDEFINED_USB_IO,		"USB I/O" },
164		{ USB_AUDIO_STREAMING_USB_IO,		"USB I/O" },
165		{ USB_AUDIO_VENDOR_USB_IO,			"Vendor USB I/O" },
166		// Input Terminal Types
167		{ USB_AUDIO_UNDEFINED_IN,			"Undefined Input" },
168		{ USB_AUDIO_MICROPHONE_IN,			"Microphone" },
169		{ USB_AUDIO_DESKTOPMIC_IN,			"Desktop Microphone" },
170		{ USB_AUDIO_PERSONALMIC_IN,			"Personal Microphone" },
171		{ USB_AUDIO_OMNI_MIC_IN,			"Omni-directional Mic" },
172		{ USB_AUDIO_MICS_ARRAY_IN,			"Microphone Array" },
173		{ USB_AUDIO_PROC_MICS_ARRAY_IN,		"Processing Mic Array" },
174		// Output Terminal Types
175		{ USB_AUDIO_UNDEFINED_OUT,			"Undefined Output" },
176		{ USB_AUDIO_SPEAKER_OUT,			"Speaker" },
177		{ USB_AUDIO_HEAD_PHONES_OUT,		"Headphones" },
178		{ USB_AUDIO_HMD_AUDIO_OUT,			"Head Mounted Disp.Audio" },
179		{ USB_AUDIO_DESKTOP_SPEAKER,		"Desktop Speaker" },
180		{ USB_AUDIO_ROOM_SPEAKER,			"Room Speaker" },
181		{ USB_AUDIO_COMM_SPEAKER,			"Communication Speaker" },
182		{ USB_AUDIO_LFE_SPEAKER,			"LFE Speaker" },
183		// Bi-directional Terminal Types
184		{ USB_AUDIO_UNDEFINED_IO,			"Undefined I/O" },
185		{ USB_AUDIO_HANDSET_IO,				"Handset" },
186		{ USB_AUDIO_HEADSET_IO,				"Headset" },
187		{ USB_AUDIO_SPEAKER_PHONE_IO,		"Speakerphone" },
188		{ USB_AUDIO_SPEAKER_PHONEES_IO,		"Echo-supp Speakerphone" },
189		{ USB_AUDIO_SPEAKER_PHONEEC_IO,		"Echo-cancel Speakerphone" },
190		// Telephony Terminal Types
191		{ USB_AUDIO_UNDEF_TELEPHONY_IO,		"Undefined Telephony" },
192		{ USB_AUDIO_PHONE_LINE_IO,			"Phone Line" },
193		{ USB_AUDIO_TELEPHONE_IO,			"Telephone" },
194		{ USB_AUDIO_DOWNLINE_PHONE_IO,		"Down Line Phone" },
195		// External Terminal Types
196		{ USB_AUDIO_UNDEFINEDEXT_IO,		"Undefined External I/O" },
197		{ USB_AUDIO_ANALOG_CONNECTOR_IO,	"Analog Connector" },
198		{ USB_AUDIO_DAINTERFACE_IO,			"Digital Audio Interface" },
199		{ USB_AUDIO_LINE_CONNECTOR_IO,		"Line Connector" },
200		{ USB_AUDIO_LEGACY_CONNECTOR_IO,	"LegacyAudioConnector" },
201		{ USB_AUDIO_SPDIF_INTERFACE_IO,		"S/PDIF Interface" },
202		{ USB_AUDIO_DA1394_STREAM_IO,		"1394 DA Stream" },
203		{ USB_AUDIO_DV1394_STREAMSOUND_IO,	"1394 DV Stream Soundtrack" },
204		{ USB_AUDIO_ADAT_LIGHTPIPE_IO,		"Alesis DAT Stream" },
205		{ USB_AUDIO_TDIF_IO,				"Tascam Digital Interface" },
206		{ USB_AUDIO_MADI_IO,				"AES Multi-channel interface" },
207		// Embedded Terminal Types
208		{ USB_AUDIO_UNDEF_EMBEDDED_IO,		"Undefined Embedded I/O" },
209		{ USB_AUDIO_LC_NOISE_SOURCE_OUT,	"Level Calibration Noise Source" },
210		{ USB_AUDIO_EQUALIZATION_NOISE_OUT,	"Equalization Noise" },
211		{ USB_AUDIO_CDPLAYER_IN,			"CD Player" },
212		{ USB_AUDIO_DAT_IO,					"DAT" },
213		{ USB_AUDIO_DCC_IO,					"DCC" },
214		{ USB_AUDIO_MINI_DISK_IO,			"Mini Disk" },
215		{ USB_AUDIO_ANALOG_TAPE_IO,			"Analog Tape" },
216		{ USB_AUDIO_PHONOGRAPH_IN,			"Phonograph" },
217		{ USB_AUDIO_VCR_AUDIO_IN,			"VCR Audio" },
218		{ USB_AUDIO_VIDEO_DISC_AUDIO_IN,	"Video Disc Audio" },
219		{ USB_AUDIO_DVD_AUDIO_IN,			"DVD Audio" },
220		{ USB_AUDIO_TV_TUNER_AUDIO_IN,		"TV Tuner Audio" },
221		{ USB_AUDIO_SAT_RECEIVER_AUDIO_IN,	"Satellite Receiver Audio" },
222		{ USB_AUDIO_CABLE_TUNER_AUDIO_IN,	"Cable Tuner Audio" },
223		{ USB_AUDIO_DSS_AUDIO_IN,			"DSS Audio" },
224		{ USB_AUDIO_RADIO_RECEIVER_IN,		"Radio Receiver" },
225		{ USB_AUDIO_RADIO_TRANSMITTER_IN,	"Radio Transmitter" },
226		{ USB_AUDIO_MULTI_TRACK_RECORDER_IO,"Multi-track Recorder" },
227		{ USB_AUDIO_SYNTHESIZER_IO,			"Synthesizer" },
228		{ USB_AUDIO_PIANO_IO,				"Piano" },
229		{ USB_AUDIO_GUITAR_IO,				"Guitar" },
230		{ USB_AUDIO_DRUMS_IO,				"Percussion Instrument" },
231		{ USB_AUDIO_INSTRUMENT_IO,			"Musical Instrument" }
232	};
233
234	for (size_t i = 0; i < B_COUNT_OF(termInfoPairs); i++)
235		if (termInfoPairs[i].type == TerminalType)
236			return termInfoPairs[i].description;
237
238	TRACE(ERR, "Unknown Terminal Type: %#06x", TerminalType);
239	return "Unknown";
240}
241
242
243InputTerminal::InputTerminal(AudioControlInterface*	interface,
244		usb_audiocontrol_header_descriptor* Header)
245	:
246	_AudioChannelCluster<_Terminal>(interface, Header)
247{
248	usb_audio_input_terminal_descriptor* Terminal
249		= (usb_audio_input_terminal_descriptor*) Header;
250	fID					= Terminal->terminal_id;
251	fTerminalType		= Terminal->terminal_type;
252	fAssociatedTerminal = Terminal->assoc_terminal;
253
254	TRACE(UAC, "Input Terminal ID:%d >>>\n", fID);
255	TRACE(UAC, "Terminal type:%s (%#06x)\n",
256		_GetTerminalDescription(fTerminalType), fTerminalType);
257	TRACE(UAC, "Assoc.terminal:%d\n",	fAssociatedTerminal);
258
259	if (fInterface->SpecReleaseNumber() < 0x200) {
260		fOutChannelsNumber	= Terminal->r1.num_channels;
261		fChannelsConfig		= Terminal->r1.channel_config;
262		fChannelNames		= Terminal->r1.channel_names;
263		fStringIndex		= Terminal->r1.terminal;
264	} else {
265		fClockSourceId		= Terminal->r2.clock_source_id;
266		fOutChannelsNumber	= Terminal->r2.num_channels;
267		fChannelsConfig		= Terminal->r2.channel_config;
268		fChannelNames		= Terminal->r2.channel_names;
269		fControlsBitmap		= Terminal->r2.bm_controls;
270		fStringIndex		= Terminal->r2.terminal;
271
272		TRACE(UAC, "Clock Source ID:%d\n", fClockSourceId);
273		TRACE(UAC, "Controls Bitmap:%#04x\n", fControlsBitmap);
274	}
275
276	TRACE(UAC, "Out.channels num:%d\n",	 fOutChannelsNumber);
277	TRACE(UAC, "Channels config:%#06x\n", fChannelsConfig);
278	TRACE(UAC, "Channels names:%d\n",	 fChannelNames);
279	TRACE(UAC, "StringIndex:%d\n",		 fStringIndex);
280
281	fStatus = B_OK;
282}
283
284
285InputTerminal::~InputTerminal()
286{
287}
288
289
290const char*
291InputTerminal::Name()
292{
293	if (fTerminalType == USB_AUDIO_STREAMING_USB_IO)
294		return "USB Input";
295	return _Terminal::Name();
296}
297
298
299OutputTerminal::OutputTerminal(AudioControlInterface*	interface,
300		usb_audiocontrol_header_descriptor* Header)
301	:
302	_Terminal(interface, Header)
303{
304	usb_audio_output_terminal_descriptor* Terminal
305		= (usb_audio_output_terminal_descriptor*) Header;
306
307	fID					= Terminal->terminal_id;
308	fTerminalType		= Terminal->terminal_type;
309	fAssociatedTerminal	= Terminal->assoc_terminal;
310	fSourceID			= Terminal->source_id;
311
312	TRACE(UAC, "Output Terminal ID:%d >>>\n",	fID);
313	TRACE(UAC, "Terminal type:%s (%#06x)\n",
314		_GetTerminalDescription(fTerminalType), fTerminalType);
315	TRACE(UAC, "Assoc.terminal:%d\n",		fAssociatedTerminal);
316	TRACE(UAC, "Source ID:%d\n",				fSourceID);
317
318	if (fInterface->SpecReleaseNumber() < 0x200) {
319		fStringIndex = Terminal->r1.terminal;
320	} else {
321		fClockSourceId	= Terminal->r2.clock_source_id;
322		fControlsBitmap	= Terminal->r2.bm_controls;
323		fStringIndex	= Terminal->r2.terminal;
324
325		TRACE(UAC, "Clock Source ID:%d\n", fClockSourceId);
326		TRACE(UAC, "Controls Bitmap:%#04x\n", fControlsBitmap);
327	}
328
329	TRACE(UAC, "StringIndex:%d\n", fStringIndex);
330
331	fStatus = B_OK;
332}
333
334
335OutputTerminal::~OutputTerminal()
336{
337}
338
339
340const char*
341OutputTerminal::Name()
342{
343	if (fTerminalType == USB_AUDIO_STREAMING_USB_IO)
344		return "USB Output";
345	return _Terminal::Name();
346}
347
348
349MixerUnit::MixerUnit(AudioControlInterface*	interface,
350		usb_audiocontrol_header_descriptor* Header)
351	:
352	_AudioChannelCluster<_AudioControl>(interface, Header),
353	fBmControlsR2(0)
354{
355	usb_audio_mixer_unit_descriptor* Mixer
356		= (usb_audio_mixer_unit_descriptor*) Header;
357
358	fID = Mixer->unit_id;
359	TRACE(UAC, "Mixer ID:%d >>>\n", fID);
360
361	TRACE(UAC, "Number of input pins:%d\n", Mixer->num_input_pins);
362	for (size_t i = 0; i < Mixer->num_input_pins; i++) {
363		fInputPins.PushBack(Mixer->input_pins[i]);
364		TRACE(UAC, "Input pin #%d:%d\n", i, fInputPins[i]);
365	}
366
367	uint8* mixerControlsData = NULL;
368	uint8 mixerControlsSize = 0;
369
370	if (fInterface->SpecReleaseNumber() < 0x200) {
371		usb_audio_output_channels_descriptor_r1* OutChannels
372			= (usb_audio_output_channels_descriptor_r1*)
373			&Mixer->input_pins[Mixer->num_input_pins];
374
375		fOutChannelsNumber	= OutChannels->num_output_pins;
376		fChannelsConfig		= OutChannels->channel_config;
377		fChannelNames		= OutChannels->channel_names;
378
379		mixerControlsData = (uint8*) ++OutChannels;
380		mixerControlsSize = Mixer->length - 10 - Mixer->num_input_pins;
381		fStringIndex = *(mixerControlsData + mixerControlsSize);
382
383#if 0 // TEST
384		if (fOutChannelsNumber > 2) {
385		//	fOutChannelsNumber = 2;
386		//	fChannelsConfig = 0x03;
387			mixerControlsData[0] = 0x80;
388			mixerControlsData[1] = 0x40;
389			mixerControlsData[2] = 0x20;
390			mixerControlsData[3] = 0x10;
391			mixerControlsData[4] = 0x08;
392			mixerControlsData[5] = 0x04;
393			mixerControlsData[6] = 0x02;
394			mixerControlsData[7] = 0x01;
395			mixerControlsData[8] = 0x80;
396			mixerControlsData[9] = 0x40;
397			mixerControlsData[10] = 0x02;
398			mixerControlsData[11] = 0x01;
399		}
400#endif
401
402	} else {
403		usb_audio_output_channels_descriptor* OutChannels
404			= (usb_audio_output_channels_descriptor*)
405			&Mixer->input_pins[Mixer->num_input_pins];
406
407		fOutChannelsNumber	= OutChannels->num_output_pins;
408		fChannelsConfig		= OutChannels->channel_config;
409		fChannelNames		= OutChannels->channel_names;
410
411		mixerControlsData = (uint8*) ++OutChannels;
412		mixerControlsSize = Mixer->length - 13 - Mixer->num_input_pins;
413		fBmControlsR2 = *(mixerControlsData + mixerControlsSize);
414		fStringIndex = *(mixerControlsData + mixerControlsSize + 1);
415
416		TRACE(UAC, "Control Bitmap:%#04x\n", fBmControlsR2);
417	}
418
419	TRACE(UAC, "Out channels number:%d\n",		fOutChannelsNumber);
420	TRACE(UAC, "Out channels config:%#06x\n",	fChannelsConfig);
421	TRACE(UAC, "Out channels names:%d\n",		fChannelNames);
422	TRACE(UAC, "Controls Size:%d\n", mixerControlsSize);
423
424	for (size_t i = 0; i < mixerControlsSize; i++) {
425		fControlsBitmap.PushBack(mixerControlsData[i]);
426		TRACE(UAC, "Controls Data[%d]:%#x\n", i, fControlsBitmap[i]);
427	}
428
429	TRACE(UAC, "StringIndex:%d\n", fStringIndex);
430
431	fStatus = B_OK;
432}
433
434
435MixerUnit::~MixerUnit()
436{
437}
438
439
440bool
441MixerUnit::HasProgrammableControls()
442{
443	for (int i = 0; i < fControlsBitmap.Count(); i++)
444		if (fControlsBitmap[i] != 0)
445			return true;
446	return false;
447}
448
449
450bool
451MixerUnit::IsControlProgrammable(int inChannel, int outChannel)
452{
453	AudioChannelCluster* outCluster = OutCluster();
454	if (outCluster == NULL) {
455		TRACE(ERR, "Output cluster is not valid.\n");
456		return false;
457	}
458
459	bool result = false;
460	if (outChannel < outCluster->ChannelsCount()) {
461		int index = inChannel * outCluster->ChannelsCount()+ outChannel;
462		result = (fControlsBitmap[index >> 3] & (0x80 >> (index & 7))) != 0;
463	}
464
465//	TRACE(UAC, "in:%d out:%d is %s\n",
466//		inChannel, outChannel, result ? "on" : "off");
467	return result;
468}
469
470
471SelectorUnit::SelectorUnit(AudioControlInterface*	interface,
472		usb_audiocontrol_header_descriptor* Header)
473	:
474	_AudioControl(interface, Header),
475	fControlsBitmap(0)
476{
477	usb_audio_selector_unit_descriptor* Selector
478		= (usb_audio_selector_unit_descriptor*) Header;
479
480	fID = Selector->unit_id;
481	TRACE(UAC, "Selector ID:%d >>>\n", fID);
482
483	TRACE(UAC, "Number of input pins:%d\n", Selector->num_input_pins);
484	for (size_t i = 0; i < Selector->num_input_pins; i++) {
485		fInputPins.PushBack(Selector->input_pins[i]);
486		TRACE(UAC, "Input pin #%d:%d\n", i, fInputPins[i]);
487	}
488
489	if (fInterface->SpecReleaseNumber() < 0x200) {
490		fStringIndex = Selector->input_pins[Selector->num_input_pins];
491	} else {
492		fControlsBitmap = Selector->input_pins[Selector->num_input_pins];
493		fStringIndex = Selector->input_pins[Selector->num_input_pins + 1];
494
495		TRACE(UAC, "Controls Bitmap:%d\n", fControlsBitmap);
496	}
497
498	TRACE(UAC, "StringIndex:%d\n", fStringIndex);
499
500	fStatus = B_OK;
501}
502
503
504SelectorUnit::~SelectorUnit()
505{
506}
507
508
509AudioChannelCluster*
510SelectorUnit::OutCluster()
511{
512	if (fInterface == NULL)
513		return NULL;
514
515	for (int i = 0; i < fInputPins.Count(); i++) {
516		_AudioControl* control = fInterface->Find(fInputPins[i]);
517		if (control == NULL)
518			continue;
519		// selector has the same channels number in the
520		// out cluster as anyone of his inputs
521		if (control->OutCluster() != NULL)
522			return control->OutCluster();
523	}
524
525	return NULL;
526}
527
528
529FeatureUnit::FeatureUnit(AudioControlInterface*	interface,
530		usb_audiocontrol_header_descriptor* Header)
531	:
532	_AudioControl(interface, Header)
533{
534	usb_audio_feature_unit_descriptor* Feature
535		= (usb_audio_feature_unit_descriptor*) Header;
536
537	fID = Feature->unit_id;
538	TRACE(UAC, "Feature ID:%d >>>\n", fID);
539
540	fSourceID = Feature->source_id;
541	TRACE(UAC, "Source ID:%d\n", fSourceID);
542
543	uint8 controlSize = 4;
544	uint8 channelsCount = (Feature->length - 6) / controlSize;
545	uint8* ControlsBitmapPointer = (uint8*)&Feature->r2.bma_controls[0];
546
547	if (fInterface->SpecReleaseNumber() < 0x200) {
548		controlSize = Feature->r1.control_size;
549		channelsCount = (Feature->length - 7) / Feature->r1.control_size;
550		ControlsBitmapPointer = &Feature->r1.bma_controls[0];
551	}
552
553	TRACE(UAC, "Channel bitmap size:%d\n", controlSize);
554	TRACE(UAC, "Channels number:%d\n", channelsCount - 1); // not add master!
555
556	for (size_t i = 0; i < channelsCount; i++) {
557		uint8* controlPointer = &ControlsBitmapPointer[i* controlSize];
558		switch(controlSize) {
559			case 1: fControlBitmaps.PushBack(*controlPointer); break;
560			case 2: fControlBitmaps.PushBack(*(uint16*)controlPointer); break;
561			case 4: fControlBitmaps.PushBack(*(uint32*)controlPointer); break;
562			default:
563				TRACE(ERR, "Feature control of unsupported size %d ignored\n",
564														controlSize);
565				continue;
566		}
567
568		NormalizeAndTraceChannel(i);
569	}
570
571	fStringIndex = ControlsBitmapPointer[channelsCount* controlSize];
572	TRACE(UAC, "StringIndex:%d\n", fStringIndex);
573
574	fStatus = B_OK;
575}
576
577
578FeatureUnit::~FeatureUnit()
579{
580}
581
582
583const char*
584FeatureUnit::Name()
585{
586	// first check if source of this FU is an input terminal
587	_AudioControl* control = fInterface->Find(fSourceID);
588	while (control != NULL) {
589		if (control->SubType() != USB_AUDIO_AC_INPUT_TERMINAL)
590			break;
591
592		// USB I/O terminal is a not good candidate to use it's name
593		if (static_cast<_Terminal*>(control)->IsUSBIO())
594			break;
595
596		// use the name of source input terminal as name of this FU
597		return control->Name();
598	}
599
600	// check if output of this FU is connected to output terminal
601	control = fInterface->FindOutputTerminal(fID);
602	while (control != NULL) {
603		if (control->SubType() != USB_AUDIO_AC_OUTPUT_TERMINAL)
604			break;
605
606		// USB I/O terminal is a not good candidate to use it's name
607		if (static_cast<_Terminal*>(control)->IsUSBIO())
608			break;
609
610		// use the name of this output terminal as name of this FU
611		return control->Name();
612	}
613
614	// otherwise get the generic name of this FU's source
615	control = fInterface->Find(fSourceID);
616	if (control != NULL && control->Name() != NULL
617			&& strlen(control->Name()) > 0)
618		return control->Name();
619
620	// I have no more ideas, have you one?
621	return "Unknown";
622}
623
624
625bool
626FeatureUnit::HasControl(int32 Channel, uint32 Control)
627{
628	if (Channel >= fControlBitmaps.Count()) {
629		TRACE(ERR, "Out of limits error of retrieving control %#010x "
630			"for channel %d\n", Control, Channel);
631		return false;
632	}
633
634	return (Control & fControlBitmaps[Channel]) != 0;
635}
636
637
638void
639FeatureUnit::NormalizeAndTraceChannel(int32 Channel)
640{
641	if (Channel >= fControlBitmaps.Count()) {
642		TRACE(ERR, "Out of limits error of tracing channel %d\n", Channel);
643		return;
644	}
645
646	struct _RemapInfo {
647		uint32	rev1Bits;
648		uint32	rev2Bits;
649		const char* name;
650	} remapInfos[] = {
651		{ BMA_CTL_MUTE_R1,		BMA_CTL_MUTE,			"Mute"		},
652		{ BMA_CTL_VOLUME_R1,	BMA_CTL_VOLUME,			"Volume"	},
653		{ BMA_CTL_BASS_R1,		BMA_CTL_BASS,			"Bass"		},
654		{ BMA_CTL_MID_R1,		BMA_CTL_MID,			"Mid"		},
655		{ BMA_CTL_TREBLE_R1,	BMA_CTL_TREBLE,			"Treble"	},
656		{ BMA_CTL_GRAPHEQ_R1,	BMA_CTL_GRAPHEQ,		"Graphic Equalizer"	},
657		{ BMA_CTL_AUTOGAIN_R1,	BMA_CTL_AUTOGAIN,		"Automatic Gain"},
658		{ BMA_CTL_DELAY_R1,		BMA_CTL_DELAY,			"Delay"			},
659		{ BMA_CTL_BASSBOOST_R1,	BMA_CTL_BASSBOOST,		"Bass Boost"	},
660		{ BMA_CTL_LOUDNESS_R1,	BMA_CTL_LOUDNESS,		"Loudness"		},
661		{ 0,					BMA_CTL_INPUTGAIN,		"InputGain"		},
662		{ 0,					BMA_CTL_INPUTGAINPAD,	"InputGainPad"	},
663		{ 0,					BMA_CTL_PHASEINVERTER,	"PhaseInverter"	},
664		{ 0,					BMA_CTL_UNDERFLOW,		"Underflow"		},
665		{ 0,					BMA_CTL_OVERFLOW,		"Overflow"		}
666	};
667
668	if (Channel == 0)
669		TRACE(UAC, "Master channel bitmap:%#x\n", fControlBitmaps[Channel]);
670	else
671		TRACE(UAC, "Channel %d bitmap:%#x\n", Channel, fControlBitmaps[Channel]);
672
673	bool isRev1 = (fInterface->SpecReleaseNumber() < 0x200);
674
675	uint32 remappedBitmap = 0;
676	for (size_t i = 0; i < B_COUNT_OF(remapInfos); i++) {
677		uint32 bits = isRev1 ? remapInfos[i].rev1Bits : remapInfos[i].rev2Bits;
678		if ((fControlBitmaps[Channel] & bits) > 0) {
679			if (isRev1)
680				remappedBitmap |= remapInfos[i].rev2Bits;
681			TRACE(UAC, "\t%s\n", remapInfos[i].name);
682		}
683	}
684
685	if (isRev1) {
686		TRACE(UAC, "\t%#08x -> %#08x.\n",
687			fControlBitmaps[Channel], remappedBitmap);
688		fControlBitmaps[Channel] = remappedBitmap;
689	}
690}
691
692
693EffectUnit::EffectUnit(AudioControlInterface*	interface,
694		usb_audiocontrol_header_descriptor* Header)
695	:
696	_AudioControl(interface, Header)
697{
698	usb_audio_input_terminal_descriptor* descriptor
699		= (usb_audio_input_terminal_descriptor*) Header;
700	TRACE(UAC, "Effect Unit:%d >>>\n", descriptor->terminal_id);
701}
702
703
704EffectUnit::~EffectUnit()
705{
706}
707
708
709ProcessingUnit::ProcessingUnit(AudioControlInterface*	interface,
710		usb_audiocontrol_header_descriptor* Header)
711	:
712	_AudioChannelCluster<_AudioControl>(interface, Header),
713	fProcessType(0),
714	fControlsBitmap(0)
715{
716	usb_audio_processing_unit_descriptor* Processing
717		= (usb_audio_processing_unit_descriptor*) Header;
718
719	fID = Processing->unit_id;
720	TRACE(UAC, "Processing ID:%d >>>\n", fID);
721
722	fProcessType = Processing->process_type;
723	TRACE(UAC, "Processing Type:%d\n", fProcessType);
724
725	TRACE(UAC, "Number of input pins:%d\n", Processing->num_input_pins);
726	for (size_t i = 0; i < Processing->num_input_pins; i++) {
727		fInputPins.PushBack(Processing->input_pins[i]);
728		TRACE(UAC, "Input pin #%d:%d\n", i, fInputPins[i]);
729	}
730
731	if (fInterface->SpecReleaseNumber() < 0x200) {
732		usb_audio_output_channels_descriptor_r1* OutChannels
733			= (usb_audio_output_channels_descriptor_r1*)
734			&Processing->input_pins[Processing->num_input_pins];
735
736		fOutChannelsNumber	= OutChannels->num_output_pins;
737		fChannelsConfig		= OutChannels->channel_config;
738		fChannelNames		= OutChannels->channel_names;
739	} else {
740		usb_audio_output_channels_descriptor* OutChannels
741			= (usb_audio_output_channels_descriptor*)
742			&Processing->input_pins[Processing->num_input_pins];
743
744		fOutChannelsNumber	= OutChannels->num_output_pins;
745		fChannelsConfig		= OutChannels->channel_config;
746		fChannelNames		= OutChannels->channel_names;
747	}
748
749	TRACE(UAC, "Out channels number:%d\n",		fOutChannelsNumber);
750	TRACE(UAC, "Out channels config:%#06x\n",	fChannelsConfig);
751	TRACE(UAC, "Out channels names:%d\n",		fChannelNames);
752	/*
753	uint8 controlsSize = Processing->length - 10 - Processing->num_input_pins;
754	TRACE(UAC, "Controls Size:%d\n", controlsSize);
755
756	uint8* controlsData = (uint8*) ++OutChannels;
757
758	for (size_t i = 0; i < controlsSize; i++) {
759		fProgrammableControls.PushBack(controlsData[i]);
760		TRACE(UAC, "Controls Data[%d]:%#x\n", i, controlsData[i]);
761	}
762
763	fStringIndex = *(controlsData + controlsSize);
764
765	TRACE(UAC, "StringIndex:%d\n", fStringIndex);
766*/
767	fStatus = B_OK;
768}
769
770
771ProcessingUnit::~ProcessingUnit()
772{
773}
774
775
776ExtensionUnit::ExtensionUnit(AudioControlInterface*	interface,
777		usb_audiocontrol_header_descriptor* Header)
778	:
779	_AudioChannelCluster<_AudioControl>(interface, Header),
780	fExtensionCode(0),
781	fControlsBitmap(0)
782{
783	usb_audio_extension_unit_descriptor* Extension
784		= (usb_audio_extension_unit_descriptor*) Header;
785
786	fID = Extension->unit_id;
787	TRACE(UAC, "Extension ID:%d >>>\n", fID);
788
789	fExtensionCode = Extension->extension_code;
790	TRACE(UAC, "Extension Type:%d\n", fExtensionCode);
791
792	TRACE(UAC, "Number of input pins:%d\n", Extension->num_input_pins);
793	for (size_t i = 0; i < Extension->num_input_pins; i++) {
794		fInputPins.PushBack(Extension->input_pins[i]);
795		TRACE(UAC, "Input pin #%d:%d\n", i, fInputPins[i]);
796	}
797
798	if (fInterface->SpecReleaseNumber() < 0x200) {
799		usb_audio_output_channels_descriptor_r1* OutChannels
800			= (usb_audio_output_channels_descriptor_r1*)
801			&Extension->input_pins[Extension->num_input_pins];
802
803		fOutChannelsNumber	= OutChannels->num_output_pins;
804		fChannelsConfig		= OutChannels->channel_config;
805		fChannelNames		= OutChannels->channel_names;
806	} else {
807		usb_audio_output_channels_descriptor* OutChannels
808			= (usb_audio_output_channels_descriptor*)
809			&Extension->input_pins[Extension->num_input_pins];
810
811		fOutChannelsNumber	= OutChannels->num_output_pins;
812		fChannelsConfig		= OutChannels->channel_config;
813		fChannelNames		= OutChannels->channel_names;
814	}
815
816	TRACE(UAC, "Out channels number:%d\n",		fOutChannelsNumber);
817	TRACE(UAC, "Out channels config:%#06x\n",	fChannelsConfig);
818	TRACE(UAC, "Out channels names:%d\n",		fChannelNames);
819	/*
820	uint8 controlsSize = Processing->length - 10 - Processing->num_input_pins;
821	TRACE(UAC, "Controls Size:%d\n", controlsSize);
822
823	uint8* controlsData = (uint8*) ++OutChannels;
824
825	for (size_t i = 0; i < controlsSize; i++) {
826		fProgrammableControls.PushBack(controlsData[i]);
827		TRACE(UAC, "Controls Data[%d]:%#x\n", i, controlsData[i]);
828	}
829
830	fStringIndex = *(controlsData + controlsSize);
831
832	TRACE(UAC, "StringIndex:%d\n", fStringIndex);
833*/
834	fStatus = B_OK;
835}
836
837
838ExtensionUnit::~ExtensionUnit()
839{
840}
841
842
843ClockSource::ClockSource(AudioControlInterface*	interface,
844		usb_audiocontrol_header_descriptor* Header)
845	:
846	_AudioControl(interface, Header)
847{
848	usb_audio_input_terminal_descriptor* descriptor
849		= (usb_audio_input_terminal_descriptor*) Header;
850	TRACE(UAC, "Clock Source:%d >>>\n",	descriptor->terminal_id);
851}
852
853
854ClockSource::~ClockSource()
855{
856}
857
858
859ClockSelector::ClockSelector(AudioControlInterface*	interface,
860		usb_audiocontrol_header_descriptor* Header)
861	:
862	_AudioControl(interface, Header)
863{
864	usb_audio_input_terminal_descriptor* descriptor
865		= (usb_audio_input_terminal_descriptor*) Header;
866	TRACE(UAC, "Clock Selector:%d >>>\n", descriptor->terminal_id);
867}
868
869
870ClockSelector::~ClockSelector()
871{
872}
873
874
875ClockMultiplier::ClockMultiplier(AudioControlInterface*	interface,
876		usb_audiocontrol_header_descriptor* Header)
877	:
878	_AudioControl(interface, Header)
879{
880	usb_audio_input_terminal_descriptor* descriptor
881		= (usb_audio_input_terminal_descriptor*) Header;
882	TRACE(UAC, "Clock Multiplier:%d >>>\n",	descriptor->terminal_id);
883}
884
885
886ClockMultiplier::~ClockMultiplier()
887{
888}
889
890
891SampleRateConverter::SampleRateConverter(AudioControlInterface*	interface,
892		usb_audiocontrol_header_descriptor* Header)
893	:
894	_AudioControl(interface, Header)
895{
896	usb_audio_input_terminal_descriptor* descriptor
897		= (usb_audio_input_terminal_descriptor*) Header;
898	TRACE(UAC, "Sample Rate Converter:%d >>>\n", descriptor->terminal_id);
899}
900
901
902SampleRateConverter::~SampleRateConverter()
903{
904}
905
906
907AudioControlInterface::AudioControlInterface(Device* device)
908	:
909	fInterface(0),
910	fStatus(B_NO_INIT),
911	fADCSpecification(0),
912	fFunctionCategory(0),
913	fControlsBitmap(0),
914	fDevice(device)
915{
916}
917
918
919AudioControlInterface::~AudioControlInterface()
920{
921	for (AudioControlsIterator I = fAudioControls.Begin();
922			I != fAudioControls.End(); I++)
923		delete I->Value();
924
925	fAudioControls.MakeEmpty();
926
927	// object already freed. just purge the map
928	fOutputTerminals.MakeEmpty();
929
930	// object already freed. just purge the map
931	fInputTerminals.MakeEmpty();
932}
933
934
935status_t
936AudioControlInterface::Init(size_t interface, usb_interface_info* Interface)
937{
938	for (size_t i = 0; i < Interface->generic_count; i++) {
939		usb_audiocontrol_header_descriptor* Header
940			= (usb_audiocontrol_header_descriptor* )Interface->generic[i];
941
942		if (Header->descriptor_type != USB_AUDIO_CS_INTERFACE) {
943			TRACE(ERR, "Ignore Audio Control of "
944				"unknown descriptor type %#04x.\n",	Header->descriptor_type);
945			continue;
946		}
947
948		_AudioControl* control = NULL;
949
950		switch(Header->descriptor_subtype) {
951			default:
952				TRACE(ERR, "Ignore Audio Control of unknown "
953					"descriptor sub-type %#04x\n", Header->descriptor_subtype);
954				break;
955			case USB_AUDIO_AC_DESCRIPTOR_UNDEFINED:
956				TRACE(ERR, "Ignore Audio Control of undefined sub-type\n");
957				break;
958			case USB_AUDIO_AC_HEADER:
959				InitACHeader(interface, Header);
960				break;
961			case USB_AUDIO_AC_INPUT_TERMINAL:
962				control = new(std::nothrow) InputTerminal(this, Header);
963				break;
964			case USB_AUDIO_AC_OUTPUT_TERMINAL:
965				control = new(std::nothrow) OutputTerminal(this, Header);
966				break;
967			case USB_AUDIO_AC_MIXER_UNIT:
968				control = new(std::nothrow) MixerUnit(this, Header);
969				break;
970			case USB_AUDIO_AC_SELECTOR_UNIT:
971				control = new(std::nothrow) SelectorUnit(this, Header);
972				break;
973			case USB_AUDIO_AC_FEATURE_UNIT:
974				control = new(std::nothrow) FeatureUnit(this, Header);
975				break;
976			case USB_AUDIO_AC_PROCESSING_UNIT:
977				if (SpecReleaseNumber() < 200)
978					control = new(std::nothrow) ProcessingUnit(this, Header);
979				else
980					control = new(std::nothrow) EffectUnit(this, Header);
981				break;
982			case USB_AUDIO_AC_EXTENSION_UNIT:
983				if (SpecReleaseNumber() < 200)
984					control = new(std::nothrow) ExtensionUnit(this, Header);
985				else
986					control = new(std::nothrow) ProcessingUnit(this, Header);
987				break;
988			case USB_AUDIO_AC_EXTENSION_UNIT_R2:
989				control = new(std::nothrow) ExtensionUnit(this, Header);
990				break;
991			case USB_AUDIO_AC_CLOCK_SOURCE_R2:
992				control = new(std::nothrow) ClockSource(this, Header);
993				break;
994			case USB_AUDIO_AC_CLOCK_SELECTOR_R2:
995				control = new(std::nothrow) ClockSelector(this, Header);
996				break;
997			case USB_AUDIO_AC_CLOCK_MULTIPLIER_R2:
998				control = new(std::nothrow) ClockMultiplier(this, Header);
999				break;
1000			case USB_AUDIO_AC_SAMPLE_RATE_CONVERTER_R2:
1001				control = new(std::nothrow) SampleRateConverter(this, Header);
1002				break;
1003		}
1004
1005		if (control != 0 && control->InitCheck() == B_OK) {
1006			switch(control->SubType()) {
1007				case USB_AUDIO_AC_OUTPUT_TERMINAL:
1008					fOutputTerminals.Put(control->SourceID(), control);
1009					break;
1010				case USB_AUDIO_AC_INPUT_TERMINAL:
1011					fInputTerminals.Put(control->ID(), control);
1012					break;
1013			}
1014			fAudioControls.Put(control->ID(), control);
1015
1016		} else
1017			delete control;
1018	}
1019
1020	return fStatus = B_OK;
1021}
1022
1023
1024_AudioControl*
1025AudioControlInterface::Find(uint8 id)
1026{
1027	return fAudioControls.Get(id);
1028}
1029
1030
1031_AudioControl*
1032AudioControlInterface::FindOutputTerminal(uint8 id)
1033{
1034	return fOutputTerminals.Get(id);
1035}
1036
1037
1038status_t
1039AudioControlInterface::InitACHeader(size_t interface,
1040		usb_audiocontrol_header_descriptor* Header)
1041{
1042	if (Header == NULL)
1043		return fStatus = B_NO_INIT;
1044
1045	fInterface = interface;
1046
1047	fADCSpecification = Header->bcd_release_no;
1048	TRACE(UAC, "ADCSpecification:%#06x\n", fADCSpecification);
1049
1050	if (fADCSpecification < 0x200) {
1051		TRACE(UAC, "InterfacesCount:%d\n",	Header->r1.in_collection);
1052		for (size_t i = 0; i < Header->r1.in_collection; i++) {
1053			fStreams.PushBack(Header->r1.interface_numbers[i]);
1054			TRACE(UAC, "Interface[%d] number is %d\n", i, fStreams[i]);
1055		}
1056	} else {
1057		fFunctionCategory = Header->r2.function_category;
1058		fControlsBitmap = Header->r2.bm_controls;
1059		TRACE(UAC, "Function Category:%#04x\n", fFunctionCategory);
1060		TRACE(UAC, "Controls Bitmap:%#04x\n", fControlsBitmap);
1061	}
1062
1063	return B_OK;
1064}
1065
1066
1067uint32
1068AudioControlInterface::GetChannelsDescription(
1069	Vector<multi_channel_info>& Channels, multi_description* Description,
1070	Vector<_AudioControl*>& Terminals, bool isForInput)
1071{
1072	uint32 addedChannels = 0;
1073
1074	for (int32 i = 0; i < Terminals.Count(); i++) {
1075		AudioChannelCluster* cluster = Terminals[i]->OutCluster();
1076		if (cluster == NULL || cluster->ChannelsCount() <= 0) {
1077			TRACE(ERR, "Terminal #%d ignored due null "
1078				"channels cluster (%08x)\n", Terminals[i]->ID(), cluster);
1079			continue;
1080		}
1081
1082		uint32 channels = GetTerminalChannels(Channels, cluster,
1083			isForInput ? B_MULTI_INPUT_CHANNEL : B_MULTI_OUTPUT_CHANNEL);
1084
1085		if (isForInput)
1086			Description->input_channel_count += channels;
1087		else
1088			Description->output_channel_count += channels;
1089
1090		addedChannels += channels;
1091	}
1092
1093	return addedChannels;
1094}
1095
1096
1097uint32
1098AudioControlInterface::GetTerminalChannels(Vector<multi_channel_info>& Channels,
1099		AudioChannelCluster* cluster, channel_kind kind, uint32 connectors)
1100{
1101	if (cluster->ChannelsCount() < 2) { // mono channel
1102		multi_channel_info info;
1103		info.channel_id	= Channels.Count();
1104		info.kind		= kind;
1105		info.designations= B_CHANNEL_MONO_BUS;
1106		info.connectors	= connectors;
1107		Channels.PushBack(info);
1108
1109		return 1;
1110	}
1111
1112	uint32 startCount = Channels.Count();
1113
1114	// Haiku multi-aduio designations have the same bits
1115	// as USB Audio 2.0 cluster spatial locations :-)
1116	for (size_t i = 0; i < kChannels; i++) {
1117		uint32 designation = 1 << i;
1118		if ((cluster->ChannelsConfig() & designation) == designation) {
1119			multi_channel_info info;
1120			info.channel_id	= Channels.Count();
1121			info.kind		= kind;
1122			info.designations= gDesignations[i].ch | gDesignations[i].bus;
1123			info.connectors	= connectors;
1124			Channels.PushBack(info);
1125		}
1126	}
1127
1128	return Channels.Count() - startCount;
1129}
1130
1131
1132uint32
1133AudioControlInterface::GetBusChannelsDescription(
1134	Vector<multi_channel_info>& Channels, multi_description* Description)
1135{
1136	uint32 addedChannels = 0;
1137
1138	// first iterate output channels
1139	for (AudioControlsIterator I = fOutputTerminals.Begin();
1140			I != fOutputTerminals.End(); I++) {
1141		_AudioControl* control = I->Value();
1142		if (static_cast<_Terminal*>(control)->IsUSBIO())
1143			continue;
1144
1145		AudioChannelCluster* cluster = control->OutCluster();
1146		if (cluster == 0 || cluster->ChannelsCount() <= 0) {
1147			TRACE(ERR, "Terminal #%d ignored due null "
1148				"channels cluster (%08x)\n", control->ID(), cluster);
1149			continue;
1150		}
1151
1152		uint32 channels = GetTerminalChannels(Channels,
1153			cluster, B_MULTI_OUTPUT_BUS);
1154
1155		Description->output_bus_channel_count += channels;
1156		addedChannels += channels;
1157	}
1158
1159	// input channels should follow too
1160	for (AudioControlsIterator I = fInputTerminals.Begin();
1161			I != fInputTerminals.End(); I++) {
1162		_AudioControl* control = I->Value();
1163		if (static_cast<_Terminal*>(control)->IsUSBIO())
1164			continue;
1165
1166		AudioChannelCluster* cluster = control->OutCluster();
1167		if (cluster == NULL || cluster->ChannelsCount() <= 0) {
1168			TRACE(ERR, "Terminal #%d ignored due null "
1169				"channels cluster (%08x)\n", control->ID(), cluster);
1170			continue;
1171		}
1172
1173		uint32 channels = GetTerminalChannels(Channels,
1174			cluster, B_MULTI_INPUT_BUS);
1175
1176		Description->input_bus_channel_count += channels;
1177		addedChannels += channels;
1178	}
1179
1180	return addedChannels;
1181}
1182
1183
1184void
1185AudioControlInterface::_HarvestRecordFeatureUnits(_AudioControl* rootControl,
1186		AudioControlsMap& Map)
1187{
1188	if (rootControl == 0) {
1189		TRACE(ERR, "Not processing due NULL root control.\n");
1190		return;
1191	}
1192
1193	switch(rootControl->SubType()) {
1194		case USB_AUDIO_AC_SELECTOR_UNIT:
1195			{
1196				SelectorUnit* unit = static_cast<SelectorUnit*>(rootControl);
1197				for (int i = 0; i < unit->fInputPins.Count(); i++)
1198					_HarvestRecordFeatureUnits(Find(unit->fInputPins[i]), Map);
1199				Map.Put(rootControl->ID(), rootControl);
1200			}
1201			break;
1202
1203		case USB_AUDIO_AC_FEATURE_UNIT:
1204			Map.Put(rootControl->ID(), rootControl);
1205			break;
1206	}
1207}
1208
1209
1210void
1211AudioControlInterface::_HarvestOutputFeatureUnits(_AudioControl* rootControl,
1212		AudioControlsMap& Map)
1213{
1214	if (rootControl == 0) {
1215		TRACE(ERR, "Not processing due NULL root control.\n");
1216		return;
1217	}
1218
1219	switch(rootControl->SubType()) {
1220		case USB_AUDIO_AC_MIXER_UNIT:
1221			{
1222				MixerUnit* unit = static_cast<MixerUnit*>(rootControl);
1223				for (int i = 0; i < unit->fInputPins.Count(); i++)
1224					_HarvestOutputFeatureUnits(Find(unit->fInputPins[i]), Map);
1225				Map.Put(rootControl->ID(), rootControl);
1226			}
1227			break;
1228
1229		case USB_AUDIO_AC_FEATURE_UNIT:
1230			Map.Put(rootControl->ID(), rootControl);
1231			break;
1232	}
1233}
1234
1235
1236bool
1237AudioControlInterface::_InitGainLimits(multi_mix_control& Control)
1238{
1239	bool canControl = false;
1240	float current = 0.;
1241	struct _GainInfo {
1242		uint8	request;
1243		int16	data;
1244		float&	value;
1245	} gainInfos[] = {
1246		{ USB_AUDIO_GET_CUR, 0, current },
1247		{ USB_AUDIO_GET_MIN, 0, Control.gain.min_gain },
1248		{ USB_AUDIO_GET_MAX, 0, Control.gain.max_gain },
1249		{ USB_AUDIO_GET_RES, 0, Control.gain.granularity }
1250	};
1251
1252	Control.gain.min_gain = 0.;
1253	Control.gain.max_gain = 100.;
1254	Control.gain.granularity = 1.;
1255
1256	size_t actualLength = 0;
1257	for (size_t i = 0; i < B_COUNT_OF(gainInfos); i++) {
1258		status_t status = gUSBModule->send_request(fDevice->USBDevice(),
1259			USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS,
1260			gainInfos[i].request, REQ_VALUE(Control.id),
1261			REQ_INDEX(Control.id), sizeof(gainInfos[i].data),
1262			&gainInfos[i].data, &actualLength);
1263
1264		if (status != B_OK || actualLength != sizeof(gainInfos[i].data)) {
1265			TRACE(ERR, "Request %d (%04x:%04x) fail:%#08x; received %d of %d\n",
1266				i, REQ_VALUE(Control.id), REQ_INDEX(Control.id), status,
1267				actualLength, sizeof(gainInfos[i].data));
1268			continue;
1269		}
1270
1271		if (i == 0)
1272			canControl = true;
1273
1274		gainInfos[i].value = static_cast<float>(gainInfos[i].data) / 256.;
1275	}
1276
1277	TRACE(ERR, "Control %s: %f dB, from %f to %f dB, step %f dB.\n",
1278		Control.name, current, Control.gain.min_gain, Control.gain.max_gain,
1279		Control.gain.granularity);
1280	return canControl;
1281}
1282
1283
1284uint32
1285AudioControlInterface::_ListFeatureUnitOption(uint32 controlType,
1286		int32& index, int32 parentIndex, multi_mix_control_info* Info,
1287		FeatureUnit* unit, uint32 channel, uint32 channels)
1288{
1289	int32 startIndex = index;
1290	uint32 id = 0;
1291	uint32 flags = 0;
1292	strind_id string = S_null;
1293	const char* name = NULL;
1294	bool initGainLimits = false;
1295
1296	switch(controlType) {
1297		case BMA_CTL_MUTE:
1298			id = USB_AUDIO_MUTE_CONTROL;
1299			flags = B_MULTI_MIX_ENABLE;
1300			string = S_MUTE;
1301			break;
1302		case BMA_CTL_VOLUME:
1303			id = USB_AUDIO_VOLUME_CONTROL;
1304			flags = B_MULTI_MIX_GAIN;
1305			string = S_GAIN;
1306			initGainLimits = true;
1307			break;
1308		case BMA_CTL_AUTOGAIN:
1309			id = USB_AUDIO_AUTOMATIC_GAIN_CONTROL;
1310			flags = B_MULTI_MIX_ENABLE;
1311			name = "Auto Gain";
1312			break;
1313		default:
1314			TRACE(ERR, "Unsupported type %#08x ignored.\n", controlType);
1315			return 0;
1316	}
1317
1318	multi_mix_control* Controls = Info->controls;
1319
1320	if (unit->HasControl(channel, controlType)) {
1321		uint32 masterIndex = CTL_ID(id, channel, unit->ID(), fInterface);
1322		Controls[index].id  = masterIndex;
1323		Controls[index].flags = flags;
1324		Controls[index].parent = parentIndex;
1325		Controls[index].string = string;
1326		if (name != NULL)
1327			strlcpy(Controls[index].name, name, sizeof(Controls[index].name));
1328		if (initGainLimits)
1329			_InitGainLimits(Controls[index]);
1330
1331		index++;
1332
1333		if (channels == 2) {
1334			Controls[index].id = CTL_ID(id, channel + 1, unit->ID(), fInterface);
1335			Controls[index].flags = flags;
1336			Controls[index].parent = parentIndex;
1337			Controls[index].master = masterIndex;
1338			Controls[index].string = string;
1339			if (name != NULL)
1340				strlcpy(Controls[index].name, name, sizeof(Controls[index].name));
1341			if (initGainLimits)
1342				_InitGainLimits(Controls[index]);
1343			index++;
1344		}
1345	}
1346
1347	return index - startIndex;
1348}
1349
1350
1351int32
1352AudioControlInterface::_ListFeatureUnitControl(int32& index, int32 parentIndex,
1353		multi_mix_control_info* Info, _AudioControl* control)
1354{
1355	FeatureUnit* unit = static_cast<FeatureUnit*>(control);
1356	if (unit == 0) {
1357		TRACE(ERR, "Feature Unit for null control ignored.\n");
1358		return 0;
1359	}
1360
1361	if (index + 4 > Info->control_count) {
1362		TRACE(ERR, "Could not list feature control group."
1363			" Limit %d of %d has been reached.\n",
1364			index, Info->control_count);
1365		return 0;
1366	}
1367
1368	AudioChannelCluster* cluster = unit->OutCluster();
1369	if (cluster == 0) {
1370		TRACE(ERR, "Control %s with null cluster ignored.\n", unit->Name());
1371		return 0;
1372	}
1373
1374	struct _ChannelInfo {
1375		const char*	Name;
1376		uint8		channels;
1377		uint32		Mask;
1378	} channelInfos[] = {
1379		{ "",			1, 0 },	// Master channel entry - no bitmask
1380		{ "",			2, B_CHANNEL_LEFT | B_CHANNEL_RIGHT },
1381		{ "Left",		1, B_CHANNEL_LEFT	},
1382		{ "Right",		1, B_CHANNEL_RIGHT	},
1383		{ "Center",		1, B_CHANNEL_CENTER },
1384		{ "L.F.E.",		1, B_CHANNEL_SUB	},
1385		{ "Back",		2, B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT },
1386		{ "Back Left",	1, B_CHANNEL_REARLEFT	},
1387		{ "Back Right",	1, B_CHANNEL_REARRIGHT	},
1388		{ "Front of Center",		2, B_CHANNEL_FRONT_LEFT_CENTER
1389										| B_CHANNEL_FRONT_RIGHT_CENTER },
1390		{ "Front Left of Center",	1, B_CHANNEL_FRONT_LEFT_CENTER	},
1391		{ "Front Right of Center",	1, B_CHANNEL_FRONT_RIGHT_CENTER	},
1392		{ "Back Center",		1, B_CHANNEL_BACK_CENTER },
1393		{ "Side",				2, B_CHANNEL_SIDE_LEFT | B_CHANNEL_SIDE_RIGHT },
1394		{ "Side Left",			1, B_CHANNEL_SIDE_LEFT },
1395		{ "Side Right",			1, B_CHANNEL_SIDE_RIGHT },
1396		{ "Top Center",			1, B_CHANNEL_TOP_CENTER },
1397		{ "Top Front Left",		1, B_CHANNEL_TOP_FRONT_LEFT },
1398		{ "Top Front Center",	1, B_CHANNEL_TOP_FRONT_CENTER },
1399		{ "Top Front Right",	1, B_CHANNEL_TOP_FRONT_RIGHT },
1400		{ "Top Back Left",		1, B_CHANNEL_TOP_BACK_LEFT },
1401		{ "Top Back Center",	1, B_CHANNEL_TOP_BACK_CENTER },
1402		{ "Top Back Right",		1, B_CHANNEL_TOP_BACK_RIGHT }
1403	};
1404
1405	multi_mix_control* Controls = Info->controls;
1406
1407	uint32 channelsConfig = cluster->ChannelsConfig();
1408	int32 groupIndex = 0;
1409	int32 channel = 0;
1410	int32 masterIndex = 0;	// in case master channel has no volume
1411							// control - add following "L+R" channels into it
1412
1413	for (size_t i = 0; i < B_COUNT_OF(channelInfos); i++) {
1414		if ((channelsConfig & channelInfos[i].Mask) != channelInfos[i].Mask) {
1415			// ignore non-listed and possibly non-paired stereo channels.
1416			//	note that master channel with zero mask pass this check! ;-)
1417			continue;
1418		}
1419
1420		if (masterIndex == 0) {
1421			groupIndex = index;
1422			Controls[index].id = groupIndex;
1423			Controls[index].flags = B_MULTI_MIX_GROUP;
1424			Controls[index].parent = parentIndex;
1425			snprintf(Controls[index].name, sizeof(Controls[index].name),
1426				"%s %s", unit->Name(), channelInfos[i].Name);
1427			index++;
1428		} else {
1429			groupIndex = masterIndex;
1430			masterIndex = 0;
1431		}
1432
1433		// First list possible Mute controls
1434		_ListFeatureUnitOption(BMA_CTL_MUTE, index, groupIndex, Info,
1435				unit, channel, channelInfos[i].channels);
1436
1437		// Gain controls may be usefull too
1438		if (_ListFeatureUnitOption(BMA_CTL_VOLUME, index, groupIndex, Info,
1439				unit, channel, channelInfos[i].channels) == 0) {
1440			masterIndex = (i == 0) ? groupIndex : 0 ;
1441			TRACE(UAC, "channel:%d set master index to %d\n",
1442				channel, masterIndex);
1443		}
1444
1445		// Auto Gain checkbox will be listed too
1446		_ListFeatureUnitOption(BMA_CTL_AUTOGAIN, index, groupIndex, Info,
1447			unit, channel, channelInfos[i].channels);
1448
1449		// Now check if the group filled with something usefull.
1450		// In case no controls were added into it - "remove" it
1451		if (Controls[index - 1].flags == B_MULTI_MIX_GROUP) {
1452			Controls[index - 1].id = 0;
1453			index--;
1454
1455			masterIndex = 0;
1456		}
1457
1458		channel += channelInfos[i].channels;
1459
1460		// remove bits for already processed channels - this prevent from
1461		// duplication of the stereo channels as "orphaned" ones and optimize
1462		// exit from this iterations after all channels are processed.
1463		channelsConfig &= ~channelInfos[i].Mask;
1464
1465		if (0 == channelsConfig)
1466			break;
1467	}
1468
1469	if (channelsConfig > 0)
1470		TRACE(ERR, "Following channels were not processed: %#08x.\n",
1471			channelsConfig);
1472
1473	// return last group index to stick possible selector unit to it. ;-)
1474	return groupIndex;
1475}
1476
1477
1478void
1479AudioControlInterface::_ListSelectorUnitControl(int32& index, int32 parentGroup,
1480		multi_mix_control_info* Info, _AudioControl* control)
1481{
1482	SelectorUnit* selector = static_cast<SelectorUnit*>(control);
1483	if (selector == 0 || selector->SubType() != USB_AUDIO_AC_SELECTOR_UNIT)
1484		return;
1485
1486	if ((index + 1 + selector->fInputPins.Count()) > Info->control_count) {
1487		TRACE(ERR, "Could not list selector control."
1488			" Limit %d of %d has been reached.\n",
1489			index, Info->control_count);
1490		return;
1491	}
1492
1493	multi_mix_control* Controls = Info->controls;
1494
1495	int32 recordMUX = CTL_ID(0, 0, selector->ID(), fInterface);
1496	Controls[index].id	= recordMUX;
1497	Controls[index].flags = B_MULTI_MIX_MUX;
1498	Controls[index].parent = parentGroup;
1499	Controls[index].string = S_null;
1500	strlcpy(Controls[index].name, "Source", sizeof(Controls[index].name));
1501	index++;
1502
1503	for (int i = 0; i < selector->fInputPins.Count(); i++) {
1504		Controls[index].id = CTL_ID(0, 1, selector->ID(), fInterface);
1505		Controls[index].flags = B_MULTI_MIX_MUX_VALUE;
1506		Controls[index].master = 0;
1507		Controls[index].string = S_null;
1508		Controls[index].parent = recordMUX;
1509		_AudioControl* control = Find(selector->fInputPins[i]);
1510		if (control != NULL)
1511			strlcpy(Controls[index].name,
1512				control->Name(), sizeof(Controls[index].name));
1513		else
1514			snprintf(Controls[index].name,
1515				sizeof(Controls[index].name), "Input #%d", i + 1);
1516		index++;
1517	}
1518}
1519
1520
1521size_t
1522AudioControlInterface::_CollectMixerUnitControls(
1523		const uint32 controlIds[kChannels][kChannels],
1524		size_t inLeft, size_t outLeft, size_t inRight, size_t outRight,
1525		const char* inputName, const char* name,
1526		Vector<multi_mix_control>& Controls)
1527{
1528	size_t count = 0;
1529	uint32 leftId = controlIds[inLeft][outLeft];
1530	uint32 rightId = controlIds[inRight][outRight];
1531
1532//	TRACE(UAC, "left:%d %d: %08x; right:%d %d: %08x\n",
1533//			inLeft, outLeft, leftId, inRight, outRight, rightId);
1534
1535	multi_mix_control control;
1536	memset(&control, 0, sizeof(multi_mix_control));
1537	snprintf(control.name, sizeof(control.name), "%s %s", inputName, name);
1538
1539	for (size_t i = 0; i < 2; i++) {
1540		if (leftId != 0 || rightId != 0) {
1541			control.flags = B_MULTI_MIX_GROUP;
1542			control.string = S_null;
1543			Controls.PushBack(control);
1544
1545			int gainControls = 0;
1546			if (leftId != 0) {
1547				control.id = leftId;
1548				control.flags = B_MULTI_MIX_GAIN;
1549				control.string = S_GAIN;
1550				if (_InitGainLimits(control)) {
1551					gainControls++;
1552					Controls.PushBack(control);
1553				}
1554			}
1555
1556			if (rightId != 0) {
1557				control.id = rightId;
1558				control.flags = B_MULTI_MIX_GAIN;
1559				control.string = S_GAIN;
1560				control.master = leftId;
1561				if (_InitGainLimits(control)) {
1562					gainControls++;
1563					Controls.PushBack(control);
1564				}
1565			}
1566
1567			// remove empty mix group
1568			if (gainControls == 0)
1569				Controls.PopBack();
1570			else
1571				count++;
1572		}
1573
1574		// take care about surround bus
1575		if (inLeft == inRight)
1576			break;
1577		// handle possible reverse controls
1578		leftId = controlIds[inLeft][outRight];
1579		rightId = controlIds[inRight][outLeft];
1580		snprintf(control.name, sizeof(control.name),
1581			"%s %s (Reverse)", inputName, name);
1582	}
1583
1584	return count;
1585}
1586
1587
1588void
1589AudioControlInterface::_ListMixerUnitControls(int32& index,
1590		multi_mix_control_info* Info, Vector<multi_mix_control>& controls)
1591{
1592	multi_mix_control* Controls = Info->controls;
1593	uint32 groupParent = 0;
1594	uint32 gainParent = 0;
1595	for (Vector<multi_mix_control>::Iterator I = controls.Begin();
1596			I != controls.End() && index < Info->control_count; I++) {
1597		memcpy(Controls + index, &*I, sizeof(multi_mix_control));
1598		switch (I->flags) {
1599			case B_MULTI_MIX_GROUP:
1600				Controls[index].id = index;
1601				Controls[index].parent = groupParent;
1602				if (groupParent == 0) {
1603					Controls[index].id |= 0x10000;
1604					groupParent = Controls[index].id;
1605				}
1606				gainParent = Controls[index].id;
1607				break;
1608			case B_MULTI_MIX_GAIN:
1609				Controls[index].parent = gainParent;
1610				break;
1611			default:
1612				TRACE(ERR, "Control type %d ignored\n", I->flags);
1613				continue;
1614		}
1615
1616		index++;
1617	}
1618
1619	if (index == Info->control_count)
1620		TRACE(ERR, "Control count limit %d has been reached.\n", index);
1621}
1622
1623
1624void
1625AudioControlInterface::_ListMixControlsForMixerUnit(int32& index,
1626		multi_mix_control_info* Info, _AudioControl* control)
1627{
1628	MixerUnit* mixer = static_cast<MixerUnit*>(control);
1629	if (mixer == 0 || mixer->SubType() != USB_AUDIO_AC_MIXER_UNIT)
1630		return;
1631
1632	struct _ChannelPair {
1633		size_t inLeft;
1634		size_t inRight;
1635		const char* name;
1636	} channelPairs[] = {
1637		{ 0, 1, "" },
1638		{ 2, 2, "Center" },
1639		{ 3, 3, "L.F.E" },
1640		{ 4, 5, "Back" },
1641		{ 6, 7, "Front of Center" },
1642		{ 8, 8, "Back Center" },
1643		{ 9, 10, "Side" },
1644		{ 11, 11, "Top Center" },
1645		{ 12, 14, "Top Front" },
1646		{ 13, 13, "Top Front Center" },
1647		{ 15, 17, "Top Back" },
1648		{ 16, 16, "Top Back Center" }
1649	};
1650
1651	Vector<_MixPageCollector*> mixControls;
1652
1653	_MixPageCollector* genericPage = new(std::nothrow) _MixPageCollector("Mixer");
1654	mixControls.PushBack(genericPage);
1655
1656	// page for extended in (>2) and out (>2) mixer controls
1657	size_t controlsOnExMixerPage = 0;
1658	_MixPageCollector* exMixerPage = new(std::nothrow) _MixPageCollector("Mixer");
1659
1660	AudioChannelCluster* outCluster = mixer->OutCluster();
1661
1662	int inOffset = 0;
1663	for (int iPin = 0; iPin < mixer->fInputPins.Count(); iPin++) {
1664		_AudioControl* control = Find(mixer->fInputPins[iPin]);
1665		AudioChannelCluster* inCluster = NULL;
1666		if (control != NULL)
1667			inCluster = control->OutCluster();
1668		if (inCluster == NULL) {
1669			TRACE(ERR, "control %p cluster %p failed!\n", control, inCluster);
1670			break;
1671		}
1672
1673		// at first - collect programmable control ids
1674		uint32 controlIds[kChannels][kChannels] = { { 0 } };
1675
1676		int inChannel = 0;
1677		for (size_t in = 0; in < kChannels
1678				&& inChannel < inCluster->ChannelsCount(); in++) {
1679			if ((inCluster->ChannelsConfig() & (1 << in)) == 0)
1680				continue;
1681
1682			for (size_t out = 0, outChannel = 0; out < kChannels
1683					&& outChannel < outCluster->ChannelsCount(); out++) {
1684				if ((outCluster->ChannelsConfig() & (1 << out)) == 0)
1685					continue;
1686
1687				if (mixer->IsControlProgrammable(
1688						inOffset + inChannel, outChannel)) {
1689					if (SpecReleaseNumber() < 0x200)
1690						// USB Audio 1.0 uses ICN/OCN for request
1691						controlIds[in][out] = CTL_ID(inOffset + inChannel + 1,
1692							outChannel + 1, mixer->ID(), fInterface);
1693					else
1694						// USB Audio 2.0 uses CS/MCN for request
1695						controlIds[in][out] = CTL_ID(USB_AUDIO_MIXER_CONTROL,
1696							(inOffset + inChannel) * outCluster->ChannelsCount()
1697							+ outChannel, mixer->ID(), fInterface);
1698				}
1699
1700				outChannel++;
1701			}
1702
1703			inChannel++;
1704		}
1705
1706		inOffset += inChannel;
1707
1708		for (size_t in = 0; in < kChannels; in++)
1709			for (size_t out = 0; out < kChannels; out++)
1710				if (controlIds[in][out] != 0)
1711					TRACE(UAC, "ctrl:%08x for in %d; out %d;\n",
1712						controlIds[in][out], in, out);
1713
1714		// second step - distribute controls on
1715		// mixer pages in logical groups
1716		uint32 exChannelsMask = ~(B_CHANNEL_LEFT | B_CHANNEL_RIGHT);
1717		bool inIsEx = (inCluster->ChannelsConfig() & exChannelsMask) != 0;
1718		bool outIsEx = (outCluster->ChannelsConfig() & exChannelsMask) != 0;
1719
1720		if (!inIsEx && !outIsEx) {
1721			// heap up all mono and stereo controls into single "Mixer" page
1722			for (size_t i = 0; i < 2; i++)
1723				_CollectMixerUnitControls(controlIds,
1724					kLeftChannel, channelPairs[i].inLeft,
1725					kRightChannel, channelPairs[i].inRight,
1726					control->Name(), channelPairs[i].name,
1727					*mixControls[0]);
1728			continue; // go next input cluster
1729		}
1730
1731		if (!outIsEx) {
1732			// special case - extended (>2 channels) input cluster
1733			// connected to 2-channels output - add into generic "Mixer" page
1734			for (size_t i = 0; i < B_COUNT_OF(channelPairs); i++)
1735				_CollectMixerUnitControls(controlIds,
1736					channelPairs[i].inLeft, kLeftChannel,
1737					channelPairs[i].inRight, kRightChannel,
1738					control->Name(), channelPairs[i].name,
1739					*mixControls[0]);
1740			continue; // go next input cluster
1741		}
1742
1743		// make separate mixer pages for set of extended (>2) input
1744		// channels connected to extended (>2 channels) output
1745		for (size_t in = 0; in < B_COUNT_OF(channelPairs); in++) {
1746			for (size_t out = 0; out < B_COUNT_OF(channelPairs); out++) {
1747				char outName[sizeof(Info->controls->name)] = { 0 };
1748				if (in == out)
1749					strlcpy(outName, channelPairs[out].name, sizeof(outName));
1750				else
1751					snprintf(outName, sizeof(outName), "%s to %s",
1752						channelPairs[in].name, channelPairs[out].name);
1753
1754				controlsOnExMixerPage += _CollectMixerUnitControls(controlIds,
1755					channelPairs[in].inLeft, channelPairs[out].inLeft,
1756					channelPairs[in].inRight, channelPairs[out].inRight,
1757					control->Name(), outName, *exMixerPage);
1758			}
1759
1760			if (controlsOnExMixerPage >= 6) {
1761				mixControls.PushBack(exMixerPage);
1762				exMixerPage = new(std::nothrow) _MixPageCollector("Mixer");
1763				controlsOnExMixerPage = 0;
1764			}
1765		}
1766	}
1767
1768	if (exMixerPage->Count() > 1)
1769		mixControls.PushBack(exMixerPage);
1770	else
1771		delete exMixerPage;
1772
1773	// final step - fill multiaudio controls info with
1774	// already structured pages/controls info arrays
1775	for (Vector<_MixPageCollector*>::Iterator I = mixControls.Begin();
1776			I != mixControls.End(); I++) {
1777		Vector<multi_mix_control>* controls = *I;
1778			TRACE(UAC, "controls count: %d\n", controls->Count());
1779		if (controls->Count() > 1)
1780			_ListMixerUnitControls(index, Info, *controls);
1781		delete controls;
1782	}
1783}
1784
1785
1786void
1787AudioControlInterface::_ListMixControlsPage(int32& index,
1788		multi_mix_control_info* Info, AudioControlsMap& Map, const char* Name)
1789{
1790	multi_mix_control* Controls = Info->controls;
1791	int32 groupIndex = index | 0x10000;
1792	Controls[index].id	= groupIndex;
1793	Controls[index].flags = B_MULTI_MIX_GROUP;
1794	Controls[index].parent = 0;
1795	strlcpy(Controls[index].name, Name, sizeof(Controls[index].name));
1796	index++;
1797
1798	int32 group = groupIndex;
1799	for (AudioControlsIterator I = Map.Begin(); I != Map.End(); I++) {
1800		TRACE(UAC, "%s control %d listed.\n", Name, I->Value()->ID());
1801		switch(I->Value()->SubType()) {
1802			case USB_AUDIO_AC_FEATURE_UNIT:
1803				group = _ListFeatureUnitControl(index, groupIndex,
1804					Info, I->Value());
1805				break;
1806			case USB_AUDIO_AC_SELECTOR_UNIT:
1807				_ListSelectorUnitControl(index, group, Info, I->Value());
1808				break;
1809			default:
1810				break;
1811		}
1812	}
1813}
1814
1815
1816status_t
1817AudioControlInterface::ListMixControls(multi_mix_control_info* Info)
1818{
1819	// first harvest feature units that assigned to output terminal(s)
1820	AudioControlsMap RecordControlsMap;
1821	AudioControlsMap OutputControlsMap;
1822
1823	for (AudioControlsIterator I = fOutputTerminals.Begin();
1824			I != fOutputTerminals.End(); I++) {
1825		_Terminal* terminal = static_cast<_Terminal*>(I->Value());
1826		if (terminal->IsUSBIO())
1827			_HarvestRecordFeatureUnits(terminal, RecordControlsMap);
1828		else
1829			_HarvestOutputFeatureUnits(terminal, OutputControlsMap);
1830	}
1831
1832	// separate input and output Feature units
1833	// and collect mixer units that can be controlled
1834	AudioControlsMap InputControlsMap;
1835	AudioControlsMap MixerControlsMap;
1836
1837	for (AudioControlsIterator I = fAudioControls.Begin();
1838			I != fAudioControls.End(); I++) {
1839		_AudioControl* control = I->Value();
1840
1841		if (control->SubType() == USB_AUDIO_AC_MIXER_UNIT) {
1842			MixerUnit* mixerControl = static_cast<MixerUnit*>(control);
1843			if (mixerControl->HasProgrammableControls())
1844				MixerControlsMap.Put(control->ID(), control);
1845			continue;
1846		}
1847
1848		// filter out feature units
1849		if (control->SubType() != USB_AUDIO_AC_FEATURE_UNIT)
1850			continue;
1851
1852		// ignore controls that are already in the output controls maps
1853		if (RecordControlsMap.Find(control->ID()) != RecordControlsMap.End()
1854			|| OutputControlsMap.Find(control->ID()) != OutputControlsMap.End())
1855			continue;
1856
1857		_AudioControl* sourceControl = Find(control->SourceID());
1858		if (sourceControl != 0
1859				&& sourceControl->SubType() == USB_AUDIO_AC_INPUT_TERMINAL)
1860			InputControlsMap.Put(control->ID(), control);
1861		else
1862			OutputControlsMap.Put(control->ID(), control);
1863	}
1864
1865	int32 index = 0;
1866	if (InputControlsMap.Count() > 0)
1867		_ListMixControlsPage(index, Info, InputControlsMap, "Input");
1868
1869	if (OutputControlsMap.Count() > 0)
1870		_ListMixControlsPage(index, Info, OutputControlsMap, "Output");
1871
1872	if (RecordControlsMap.Count() > 0)
1873		_ListMixControlsPage(index, Info, RecordControlsMap, "Record");
1874
1875
1876	for (AudioControlsIterator I = MixerControlsMap.Begin();
1877			I != MixerControlsMap.End(); I++)
1878		_ListMixControlsForMixerUnit(index, Info, I->Value());
1879
1880	Info->control_count = index;
1881
1882	return B_OK;
1883}
1884
1885
1886status_t
1887AudioControlInterface::GetMix(multi_mix_value_info* Info)
1888{
1889	for (int32 i = 0; i < Info->item_count; i++) {
1890		uint16 length = 0;
1891		int16 data = 0;
1892
1893		_AudioControl* control = Find(ID_FROM_CTLID(Info->values[i].id));
1894		if (control == NULL) {
1895			TRACE(ERR, "No control found for unit id %#02x. Ignore it.\n",
1896				ID_FROM_CTLID(Info->values[i].id));
1897			continue;
1898		}
1899
1900		switch (control->SubType()) {
1901			case USB_AUDIO_AC_FEATURE_UNIT:
1902				switch(CS_FROM_CTLID(Info->values[i].id)) {
1903					case USB_AUDIO_VOLUME_CONTROL:
1904						length = 2;
1905						break;
1906					case USB_AUDIO_MUTE_CONTROL:
1907					case USB_AUDIO_AUTOMATIC_GAIN_CONTROL:
1908						length = 1;
1909						break;
1910					default:
1911						TRACE(ERR, "Unsupported control id:%08x of type %#02x "
1912							"ignored.\n", ID_FROM_CTLID(Info->values[i].id),
1913							CS_FROM_CTLID(Info->values[i].id));
1914						continue;
1915				}
1916				break;
1917			case USB_AUDIO_AC_SELECTOR_UNIT:
1918				length = 1;
1919				break;
1920			case USB_AUDIO_AC_MIXER_UNIT:
1921				length = 2;
1922				break;
1923			default:
1924				TRACE(ERR, "Control id:%08x of type %d is not supported\n",
1925					ID_FROM_CTLID(Info->values[i].id), control->SubType());
1926				continue;
1927		}
1928
1929		size_t actualLength = 0;
1930		status_t status = gUSBModule->send_request(fDevice->USBDevice(),
1931			USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS, USB_AUDIO_GET_CUR,
1932			REQ_VALUE(Info->values[i].id), REQ_INDEX(Info->values[i].id),
1933			length, &data, &actualLength);
1934
1935		if (status != B_OK || actualLength != length) {
1936			TRACE(ERR, "Request (%04x:%04x) failed:%#08x; received %d of %d\n",
1937				REQ_VALUE(Info->values[i].id), REQ_INDEX(Info->values[i].id),
1938				status, actualLength, length);
1939			continue;
1940		}
1941
1942		switch (control->SubType()) {
1943			case USB_AUDIO_AC_FEATURE_UNIT:
1944				switch(CS_FROM_CTLID(Info->values[i].id)) {
1945					case USB_AUDIO_VOLUME_CONTROL:
1946						Info->values[i].gain = static_cast<float>(data) / 256.;
1947						TRACE(MIX, "Gain control %d; channel: %d; is %f dB.\n",
1948							ID_FROM_CTLID(Info->values[i].id),
1949							CN_FROM_CTLID(Info->values[i].id),
1950							Info->values[i].gain);
1951						break;
1952					case USB_AUDIO_MUTE_CONTROL:
1953						Info->values[i].enable = data > 0;
1954						TRACE(MIX, "Mute control %d; channel: %d; is %d.\n",
1955							ID_FROM_CTLID(Info->values[i].id),
1956							CN_FROM_CTLID(Info->values[i].id),
1957							Info->values[i].enable);
1958						break;
1959					case USB_AUDIO_AUTOMATIC_GAIN_CONTROL:
1960						Info->values[i].enable = data > 0;
1961						TRACE(MIX, "AGain control %d; channel: %d; is %d.\n",
1962							ID_FROM_CTLID(Info->values[i].id),
1963							CN_FROM_CTLID(Info->values[i].id),
1964							Info->values[i].enable);
1965						break;
1966					default:
1967						break;
1968				}
1969				break;
1970			case USB_AUDIO_AC_SELECTOR_UNIT:
1971				Info->values[i].mux = data - 1;
1972				TRACE(MIX, "Selector control %d; is %d.\n",
1973					ID_FROM_CTLID(Info->values[i].id),
1974					Info->values[i].mux);
1975				break;
1976			case USB_AUDIO_AC_MIXER_UNIT:
1977				Info->values[i].gain = static_cast<float>(data) / 256.;
1978				TRACE(MIX, "Mixer #%d channels in: %d; out: %d; is %f dB.\n",
1979					ID_FROM_CTLID(Info->values[i].id),
1980					CS_FROM_CTLID(Info->values[i].id),
1981					CN_FROM_CTLID(Info->values[i].id),
1982					Info->values[i].gain);
1983				break;
1984		}
1985	}
1986
1987	return B_OK;
1988}
1989
1990
1991status_t
1992AudioControlInterface::SetMix(multi_mix_value_info* Info)
1993{
1994	for (int32 i = 0; i < Info->item_count; i++) {
1995		uint16 length = 0;
1996		int16 data = 0;
1997
1998		_AudioControl* control = Find(ID_FROM_CTLID(Info->values[i].id));
1999		if (control == NULL) {
2000			TRACE(ERR, "No control found for unit id %#02x. Ignore it.\n",
2001				ID_FROM_CTLID(Info->values[i].id));
2002			continue;
2003		}
2004
2005		switch (control->SubType()) {
2006			case USB_AUDIO_AC_FEATURE_UNIT:
2007				switch(CS_FROM_CTLID(Info->values[i].id)) {
2008					case USB_AUDIO_VOLUME_CONTROL:
2009						data = static_cast<int16>(Info->values[i].gain * 256.);
2010						length = 2;
2011						TRACE(MIX, "Gain control %d; channel: %d; "
2012							"about to set to %f dB.\n",
2013							ID_FROM_CTLID(Info->values[i].id),
2014							CN_FROM_CTLID(Info->values[i].id),
2015							Info->values[i].gain);
2016						break;
2017					case USB_AUDIO_MUTE_CONTROL:
2018						data = (Info->values[i].enable ? 1 : 0);
2019						length = 1;
2020						TRACE(MIX, "Mute control %d; channel: %d; "
2021							"about to set to %d.\n",
2022							ID_FROM_CTLID(Info->values[i].id),
2023							CN_FROM_CTLID(Info->values[i].id),
2024							Info->values[i].enable);
2025						break;
2026					case USB_AUDIO_AUTOMATIC_GAIN_CONTROL:
2027						data = (Info->values[i].enable ? 1 : 0);
2028						length = 1;
2029						TRACE(MIX, "AGain control %d; channel: %d; "
2030							"about to set to %d.\n",
2031							ID_FROM_CTLID(Info->values[i].id),
2032							CN_FROM_CTLID(Info->values[i].id),
2033							Info->values[i].enable);
2034						break;
2035					default:
2036						TRACE(ERR, "Unsupported control id:%08x of type %#02x "
2037							"ignored.\n", ID_FROM_CTLID(Info->values[i].id),
2038							CS_FROM_CTLID(Info->values[i].id));
2039						continue;
2040				}
2041				break;
2042			case USB_AUDIO_AC_SELECTOR_UNIT:
2043				data = Info->values[i].mux + 1;
2044				length = 1;
2045				TRACE(MIX, "Selector Control %d about to set to %d.\n",
2046					ID_FROM_CTLID(Info->values[i].id),
2047					Info->values[i].mux);
2048				break;
2049			case USB_AUDIO_AC_MIXER_UNIT:
2050				data = static_cast<int16>(Info->values[i].gain * 256.);
2051				length = 2;
2052				TRACE(MIX, "Mixer %d channels in: %d; out: %d; "
2053					"about to set to %f dB.\n",
2054					ID_FROM_CTLID(Info->values[i].id),
2055					CS_FROM_CTLID(Info->values[i].id),
2056					CN_FROM_CTLID(Info->values[i].id),
2057					Info->values[i].gain);
2058				break;
2059			default:
2060				TRACE(ERR, "Control id:%08x of type %d is not supported\n",
2061					Info->values[i].id, control->SubType());
2062				continue;
2063		}
2064
2065		size_t actualLength = 0;
2066		status_t status = gUSBModule->send_request(fDevice->USBDevice(),
2067			USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_CLASS, USB_AUDIO_SET_CUR,
2068			REQ_VALUE(Info->values[i].id), REQ_INDEX(Info->values[i].id),
2069			length, &data, &actualLength);
2070
2071		if (status != B_OK || actualLength != length) {
2072			TRACE(ERR, "Request (%04x:%04x) failed:%#08x; send %d of %d\n",
2073				REQ_VALUE(Info->values[i].id), REQ_INDEX(Info->values[i].id),
2074				status, actualLength, length);
2075			continue;
2076		}
2077
2078		TRACE(MIX, "Value set OK\n");
2079	}
2080
2081	return B_OK;
2082}
2083
2084