Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/usb/audio/audiosub.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <thread.h>
4
#include "usb.h"
5
#include "audio.h"
6
#include "audioctl.h"
7
 
8
typedef struct Namelist Namelist;
9
 
10
struct Namelist
11
{
12
	short	index;
13
	char		*name;
14
};
15
 
16
Namelist terminal_types[] = {
17
	{	0x100, "USB Terminal, undefined type"},
18
	{	0x101, "USB Streaming"},
19
	{	0x201, "Microphone"},
20
	{	0x301, "Speaker"},
21
	{	0x603, "Line connector"},
22
	{	0x605, "S/PDIF"},
23
	{	0, nil }
24
};
25
 
26
units[2][8];	/* rec and play units */
27
nunits[2];		/* number in use */
28
 
29
char *
30
namefor(Namelist *list, int item)
31
{
32
	while(list->name){
33
		if(list->index == item)
34
			return list->name;
35
		list++;
36
	}
37
	return "<unnamed>";
38
}
39
 
40
static int
41
findunit(int nr)
42
{
43
	int rec, i;
44
	for(rec = 0; rec < 2; rec++)
45
		for(i = 0; i < nunits[rec]; i++)
46
			if(units[rec][i] == nr)
47
				return rec;
48
	return -1;
49
}
50
 
51
void
52
audio_interface(Dev *, Desc *dd)
53
{
54
	byte *b = (uchar*)&dd->data;
55
	byte *bb = b;
56
	int nb = dd->data.bLength;
57
	int ctl, ch, u, x;
58
	byte *p;
59
	int class, subclass;
60
	Audioalt *aa;
61
	char *hd;
62
 
63
	class = Class(dd->iface->csp);
64
	subclass = Subclass(dd->iface->csp);
65
 
66
	dprint(2, "%d.%d: ", class, subclass);
67
	switch (subclass){
68
	case 1:	// control
69
		switch (b[2]){
70
		case 0x01:
71
			dprint(2, "Class-Specific AC Interface Header Descriptor\n");
72
			dprint(2, "\tAudioDevClass release (bcd)%c%c%c%c, "
73
				"TotalLength %d, InCollection %d aInterfaceNr %d\n",
74
					'0'+((b[4]>>4)&0xf), '0'+(b[4]&0xf),
75
					'0'+((b[3]>>4)&0xf), '0'+(b[3]&0xf),
76
					b[5]|(b[6]<<8), b[7], b[8]);
77
			break;
78
		case 0x02:	// input
79
			dprint(2, "Audio Input Terminal Descriptor\n");
80
			dprint(2, "\tbTerminalId %d, wTerminalType "
81
				"0x%x (%s), bAssocTerminal %d bNrChannels %d, "
82
				"wChannelConfig %d, iChannelNames %d iTerminal %d\n",
83
					b[3], b[4]|(b[5]<<8),
84
					namefor(terminal_types, b[4]|(b[5]<<8)),
85
					b[6], b[7], b[8]|(b[9]<<8), b[10], b[11]);
86
			if((b[4]|b[5]<<8) == 0x101){
87
				if(verbose)
88
					fprint(2, "Audio output unit %d\n", b[3]);
89
				/* USB streaming input: play interface */
90
				units[Play][nunits[Play]++] = b[3];
91
			}else{
92
				if(verbose)
93
					fprint(2, "Dev can record from %s\n",
94
						namefor(terminal_types, b[4]|(b[5]<<8)));
95
				/* Non-USB input: record interface */
96
				units[Record][nunits[Record]++] = b[3];
97
			}
98
			break;
99
		case 0x03:	// output
100
			if(usbdebug){
101
				fprint(2, "Audio Output Terminal Descriptor\n");
102
				fprint(2, "\tbTerminalId %d, wTerminalType 0x%x (%s), bAssocTerminal %d bSourceId %d, iTerminal %d\n",
103
					b[3], b[4]|(b[5]<<8),
104
					namefor(terminal_types, b[4]|(b[5]<<8)),
105
					b[6], b[7], b[8]);
106
			}
107
			if((b[4]|b[5]<<8) == 0x101){
108
				if(verbose)
109
					fprint(2, "Audio input unit %d\n", b[3]);
110
				/* USB streaming output: record interface */
111
				units[Record][nunits[Record]++] = b[3];
112
				if(verbose)
113
					fprint(2, "Dev can play to %s\n",
114
						namefor(terminal_types, b[4]|(b[5]<<8)));
115
				/* Non-USB output: play interface */
116
				units[Play][nunits[Play]++] = b[3];
117
			}
118
			break;
119
		case 0x04:
120
			if(verbose)
121
				fprint(2, "Audio Mixer Unit %d\n", b[3]);
122
			if(usbdebug){
123
				fprint(2, "\t%d bytes:", nb);
124
				for(ctl = 0; ctl < nb; ctl++)
125
					fprint(2, " 0x%2.2x", b[ctl]);
126
				fprint(2, "\n\tbUnitId %d, bNrInPins %d", b[3], b[4]);
127
			}
128
			if(b[4]){
129
				dprint(2, ", baSourceIDs: [%d", b[5]);
130
				u = findunit(b[5]);
131
				for(ctl = 1; ctl < b[4]; ctl++){
132
					if(u < 0)
133
						u = findunit(b[5+ctl]);
134
					else if((x = findunit(b[5+ctl])) >= 0 && u != x && verbose)
135
						fprint(2, "\tMixer %d for I & O \n", b[3]);
136
					dprint(2, ", %d", b[5+ctl]);
137
				}
138
				dprint(2, "]\n");
139
				if(u >= 0){
140
					units[u][nunits[u]++] = b[3];
141
					if(mixerid[u] >= 0)
142
						fprint(2, "Second mixer (%d, %d) on %s\n",
143
						 mixerid[u], b[3], u?"record":"playback");
144
					mixerid[u] = b[3];
145
				}
146
				if(usbdebug){
147
					fprint(2, "Channels %d, config %d, ",
148
						b[ctl+5], b[ctl+5+1] | b[ctl+5+2] << 8);
149
					x = b[ctl+5] * b[4];
150
					fprint(2, "programmable: %d bits, 0x", x);
151
					x = (x + 7) >> 3;
152
					while(x--)
153
						fprint(2, "%2.2x", b[ctl+x+5+4]);
154
				}
155
			}
156
			break;
157
		case 0x05:
158
			if(verbose)
159
				fprint(2, "Audio Selector Unit %d\n", b[3]);
160
			dprint(2, "\tbUnitId %d, bNrInPins %d", b[3], b[4]);
161
			if(b[4]){
162
				u = findunit(b[5]);
163
				dprint(2, ", baSourceIDs: %s [%d",
164
					u?"record":"playback", b[5]);
165
				for(ctl = 1; ctl < b[4]; ctl++){
166
					if(u < 0)
167
						u = findunit(b[5+ctl]);
168
					else if((x = findunit(b[5+ctl])) >= 0 &&
169
						u != x && verbose)
170
						fprint(2, "\tSelector %d for I & O\n", b[3]);
171
					dprint(2, ", %d", b[5+ctl]);
172
				}
173
				dprint(2, "]\n");
174
				if(u >= 0){
175
					units[u][nunits[u]++] = b[3];
176
					if(selectorid[u] >= 0)
177
						fprint(2, "Second selector (%d, %d) on %s\n", selectorid[u], b[3], u?"record":"playback");
178
					selectorid[u] = b[3];
179
					controls[u][Selector_control].readable = 1;
180
					controls[u][Selector_control].settable = 1;
181
					controls[u][Selector_control].chans = 0;
182
				}
183
			}
184
			break;
185
		case 0x06:	// feature
186
			if(verbose) fprint(2, "Audio Feature Unit %d", b[3]);
187
			dprint(2, "\tbUnitId %d, bSourceId %d, bControlSize %d\n",
188
				b[3], b[4], b[5]);
189
			u = findunit(b[4]);
190
			if(u >= 0){
191
				if(verbose) fprint(2, " for %s\n", u?"Record":"Playback");
192
				units[u][nunits[u]++] = b[3];
193
				if(featureid[u] >= 0)
194
					if(verbose)
195
						fprint(2, "Second feature unit (%d, %d)"
196
							" on %s\n", featureid[u], b[3],
197
							u?"record":"playback");
198
				featureid[u] = b[3];
199
			}else
200
				if(verbose) fprint(2, ", not known what for\n");
201
			p = b + 6;
202
			for(ctl = 1; ctl < 0x0b; ctl++)
203
				if((1<<(ctl-1)) & (b[6] | ((b[5]>1)?(b[7]<<8):0))){
204
					if(verbose)
205
						fprint(2, "\t%s control on master channel\n",
206
							controls[0][ctl].name);
207
					if(u >= 0){
208
						controls[u][ctl].readable = 1;
209
						controls[u][ctl].settable = 1;
210
						controls[u][ctl].chans = 0;
211
					}
212
				}
213
			p += (b[5]>1)?2:1;
214
			for(ch = 0; ch < (nb - 8)/b[5]; ch++){
215
				for(ctl = 1; ctl < 0x0b; ctl++)
216
					if((1<<(ctl-1)) & (p[0] | ((b[5]>1)?(p[1]<<8):0))){
217
						if(verbose)
218
						  fprint(2, "\t%s control on channel %d\n",
219
							controls[0][ctl].name, ch+1);
220
						if(u >= 0){
221
							controls[u][ctl].readable = 1;
222
							controls[u][ctl].settable = 1;
223
							controls[u][ctl].chans |= 1 <<(ch+1);
224
						}
225
					}
226
				p += (b[5]>1)?2:1;
227
			}
228
			break;
229
		default:
230
			hd = hexstr(bb, nb);
231
			fprint(2, "audio control unknown: %s\n", hd);
232
			free(hd);
233
		}
234
		break;
235
	case 2: // stream
236
		switch (b[2]){
237
		case 0x01:
238
			dprint(2, "Audio stream for TerminalID %d, delay %d, format_tag %#ux\n",
239
				b[3], b[4], b[5] | (b[6]<<8));
240
			break;
241
		case 0x02:
242
			aa = (Audioalt *)dd->altc->aux;
243
			if(aa == nil){
244
				aa = mallocz(sizeof(Audioalt), 1);
245
				dd->altc->aux = aa;
246
			}
247
			if(verbose){
248
				if(b[4] <= 2)
249
					fprint(2, "Interface %d: %s, %d bits, ",
250
						dd->iface->id, (b[4] == 1)?"mono":"stereo", b[6]);
251
				else
252
					fprint(2, "Interface %d, %d channels, %d bits, ",
253
						dd->iface->id, b[4], b[6]);
254
			}
255
			if(b[7] == 0){
256
				if(verbose)
257
					fprint(2, "frequency variable between %d and %d\n",
258
						b[8] | b[9]<<8 | b[10]<<16, b[11] | b[12]<<8 | b[13]<<16);
259
				aa->minfreq = b[8] | b[9]<<8 | b[10]<<16;
260
				aa->maxfreq = b[11] | b[12]<<8 | b[13]<<16;
261
				aa->caps |= has_contfreq;
262
			}else{
263
				if(verbose)
264
					fprint(2, "discrete frequencies are:");
265
				for(ch = 0; ch < b[7] && ch < 8; ch++){
266
					aa->freqs[ch] = b[8+3*ch] | b[9+3*ch]<<8 | b[10+3*ch]<<16;
267
					if(verbose)
268
						fprint(2, " %d", b[8+3*ch] | b[9+3*ch]<<8 | b[10+3*ch]<<16);
269
				}
270
				if(ch < 8)
271
					aa->freqs[ch] = -1;
272
				if(verbose)
273
					fprint(2, "\n");
274
				if(ch > 1)
275
					aa->caps |= has_discfreq;	/* more than one frequency */
276
				else
277
					aa->caps |= onefreq;		/* only one frequency */
278
			}
279
			aa->nchan = b[4];
280
			aa->res = b[6];
281
			aa->subframesize = b[5];
282
			break;
283
		default:
284
			if(usbdebug){
285
				hd = hexstr(bb, nb);
286
				fprint(2, "audio stream unknown: %s\n", hd);
287
				free(hd);
288
			}
289
		}
290
		break;
291
	case 3: // midi
292
	default:
293
		if(usbdebug){
294
			hd = hexstr(bb, nb);
295
			fprint(2, "Unknown audio stream type: CS_INTERFACE: %s\n", hd);
296
			free(hd);
297
		}
298
	}
299
}
300