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 301