xref: /haiku/src/add-ons/kernel/drivers/audio/usb/AudioControlInterface.cpp (revision a127b88ecbfab58f64944c98aa47722a18e363b2)
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 
35 struct _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 
60 struct _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 
89 AudioChannelCluster*
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 
103 AudioChannelCluster::AudioChannelCluster()
104 	:
105 	fOutChannelsNumber(0),
106 	fChannelsConfig(0),
107 	fChannelNames(0)
108 {
109 }
110 
111 
112 AudioChannelCluster::~AudioChannelCluster()
113 {
114 }
115 
116 
117 bool
118 AudioChannelCluster::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 
141 const char*
142 _Terminal::Name()
143 {
144 	return _GetTerminalDescription(fTerminalType);
145 }
146 
147 
148 bool
149 _Terminal::IsUSBIO()
150 {
151 	return (fTerminalType & 0xff00) == USB_AUDIO_UNDEFINED_USB_IO;
152 }
153 
154 
155 const 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 
243 InputTerminal::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 
285 InputTerminal::~InputTerminal()
286 {
287 }
288 
289 
290 const char*
291 InputTerminal::Name()
292 {
293 	if (fTerminalType == USB_AUDIO_STREAMING_USB_IO)
294 		return "USB Input";
295 	return _Terminal::Name();
296 }
297 
298 
299 OutputTerminal::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 
335 OutputTerminal::~OutputTerminal()
336 {
337 }
338 
339 
340 const char*
341 OutputTerminal::Name()
342 {
343 	if (fTerminalType == USB_AUDIO_STREAMING_USB_IO)
344 		return "USB Output";
345 	return _Terminal::Name();
346 }
347 
348 
349 MixerUnit::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 
435 MixerUnit::~MixerUnit()
436 {
437 }
438 
439 
440 bool
441 MixerUnit::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 
450 bool
451 MixerUnit::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 
471 SelectorUnit::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 
504 SelectorUnit::~SelectorUnit()
505 {
506 }
507 
508 
509 AudioChannelCluster*
510 SelectorUnit::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 
529 FeatureUnit::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 
578 FeatureUnit::~FeatureUnit()
579 {
580 }
581 
582 
583 const char*
584 FeatureUnit::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 
625 bool
626 FeatureUnit::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 
638 void
639 FeatureUnit::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 
693 EffectUnit::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 
704 EffectUnit::~EffectUnit()
705 {
706 }
707 
708 
709 ProcessingUnit::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 
771 ProcessingUnit::~ProcessingUnit()
772 {
773 }
774 
775 
776 ExtensionUnit::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 
838 ExtensionUnit::~ExtensionUnit()
839 {
840 }
841 
842 
843 ClockSource::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 
854 ClockSource::~ClockSource()
855 {
856 }
857 
858 
859 ClockSelector::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 
870 ClockSelector::~ClockSelector()
871 {
872 }
873 
874 
875 ClockMultiplier::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 
886 ClockMultiplier::~ClockMultiplier()
887 {
888 }
889 
890 
891 SampleRateConverter::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 
902 SampleRateConverter::~SampleRateConverter()
903 {
904 }
905 
906 
907 AudioControlInterface::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 
919 AudioControlInterface::~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 
935 status_t
936 AudioControlInterface::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*
1025 AudioControlInterface::Find(uint8 id)
1026 {
1027 	return fAudioControls.Get(id);
1028 }
1029 
1030 
1031 _AudioControl*
1032 AudioControlInterface::FindOutputTerminal(uint8 id)
1033 {
1034 	return fOutputTerminals.Get(id);
1035 }
1036 
1037 
1038 status_t
1039 AudioControlInterface::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 
1067 uint32
1068 AudioControlInterface::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 
1097 uint32
1098 AudioControlInterface::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 
1132 uint32
1133 AudioControlInterface::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 
1184 void
1185 AudioControlInterface::_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 
1210 void
1211 AudioControlInterface::_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 
1236 bool
1237 AudioControlInterface::_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 
1284 uint32
1285 AudioControlInterface::_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 
1351 int32
1352 AudioControlInterface::_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 
1478 void
1479 AudioControlInterface::_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 
1521 size_t
1522 AudioControlInterface::_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 
1588 void
1589 AudioControlInterface::_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 
1624 void
1625 AudioControlInterface::_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 
1786 void
1787 AudioControlInterface::_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 
1816 status_t
1817 AudioControlInterface::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 
1886 status_t
1887 AudioControlInterface::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 
1991 status_t
1992 AudioControlInterface::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