| 66 | void |
| 67 | DumpDescriptorData(const usb_generic_descriptor* descriptor) { |
| 68 | puts( " Descriptor not recognized, dumping pure data"); |
| 69 | printf(" Type ............. 0x%02x\n", |
| 70 | descriptor->descriptor_type); |
| 71 | |
| 72 | printf(" Data ............. "); |
| 73 | //len includes len and descriptor_type field |
| 74 | for(int32 i = 0; i < descriptor->length - 2; i++) |
| 75 | printf("%02x ", descriptor->data[i]); |
| 76 | printf("\n"); |
| 77 | } |
| 78 | |
| 79 | void |
| 80 | DumpAudioCSInterfaceDescriptorHeader(const usb_generic_descriptor* descriptor) { |
| 81 | printf(" bLength: %u\n", descriptor->length); |
| 82 | printf(" bDescriptorType: %u (CS_INTERFACE)\n", descriptor->descriptor_type); |
| 83 | |
| 84 | printf(" bDescriptorSubtype: %u (HEADER)\n", (uint8)descriptor->data[0]); |
| 85 | printf(" bcdADC: 0x%04x\n", (uint16)descriptor->data[1]); |
| 86 | printf(" wTotalLength: %u\n", (uint16)descriptor->data[3]); |
| 87 | printf(" bInCollection: %u\n", (uint8)descriptor->data[5]); |
| 88 | |
| 89 | uint8 bInCollection = (uint8)descriptor->data[5]; |
| 90 | for (uint8 i = 0; i < bInCollection; i++) |
| 91 | printf(" baInterfaceNr %u: %u\n", i+1, (uint8)descriptor->data[6+i]); |
| 92 | } |
| 93 | |
| 94 | void |
| 95 | DumpChannelConfig(uint16 wChannelConfig) { |
| 96 | int mask = 1; |
| 97 | if(wChannelConfig & mask) |
| 98 | puts(" Left Front (L)"); |
| 99 | mask <<= 2; |
| 100 | if(wChannelConfig & mask) |
| 101 | puts(" Right Front (R)"); |
| 102 | mask <<= 2; |
| 103 | if(wChannelConfig & mask) |
| 104 | puts(" Center Front (C)"); |
| 105 | mask <<= 2; |
| 106 | if(wChannelConfig & mask) |
| 107 | puts(" Low Frequency Enchancement (LFE)"); |
| 108 | mask <<= 2; |
| 109 | if(wChannelConfig & mask) |
| 110 | puts(" Left Surround (Ls)"); |
| 111 | mask <<= 2; |
| 112 | if(wChannelConfig & mask) |
| 113 | puts(" Right Surround (Rs)"); |
| 114 | mask <<= 2; |
| 115 | if(wChannelConfig & mask) |
| 116 | puts(" Left of Center (Lc)"); |
| 117 | mask <<= 2; |
| 118 | if(wChannelConfig & mask) |
| 119 | puts(" Right of Center (Rc)"); |
| 120 | mask <<= 2; |
| 121 | if(wChannelConfig & mask) |
| 122 | puts(" Surround (S)"); |
| 123 | mask <<= 2; |
| 124 | if(wChannelConfig & mask) |
| 125 | puts(" Side Left (Sl)"); |
| 126 | mask <<= 2; |
| 127 | if(wChannelConfig & mask) |
| 128 | puts(" Side Right (Sr)"); |
| 129 | mask <<= 2; |
| 130 | if(wChannelConfig & mask) |
| 131 | puts(" Top (T)"); |
| 132 | } |
| 133 | |
| 134 | void |
| 135 | DumpAudioCSInterfaceDescriptorInputTerminal(const usb_generic_descriptor* descriptor) { |
| 136 | printf(" bLength: %u\n", descriptor->length); |
| 137 | printf(" bDescriptorType: %u (CS_INTERFACE)\n", descriptor->descriptor_type); |
| 138 | |
| 139 | printf(" bDescriptorSubtype: %u (INPUT_TERMINAL)\n", (uint8)descriptor->data[0]); |
| 140 | printf(" bTerminalID: %u\n", (uint8)descriptor->data[1]); |
| 141 | printf(" wTerminalType: %u\n", (uint16)descriptor->data[2]); |
| 142 | printf(" bAssocTerminal: %u\n", (uint8)descriptor->data[4]); |
| 143 | printf(" bNrChannels: %u\n", (uint8)descriptor->data[5]); |
| 144 | |
| 145 | uint16 wChannelConfig = (uint16)descriptor->data[6]; |
| 146 | printf(" wChannelConfig: %u\n", wChannelConfig); |
| 147 | DumpChannelConfig(wChannelConfig); |
| 148 | |
| 149 | printf(" iChannelNames: %u\n", (uint8)descriptor->data[8]); |
| 150 | printf(" iTerminal: %u\n", (uint8)descriptor->data[9]); |
| 151 | } |
| 152 | |
| 153 | |
| 154 | void |
| 155 | DumpAudioCSInterfaceDescriptorOutputTerminal(const usb_generic_descriptor* descriptor) { |
| 156 | printf(" bLength: %u\n", descriptor->length); |
| 157 | printf(" bDescriptorType: %u (CS_INTERFACE)\n", descriptor->descriptor_type); |
| 158 | |
| 159 | printf(" bDescriptorSubtype: %u (OUTPUT_TERMINAL)\n", (uint8)descriptor->data[0]); |
| 160 | printf(" bTerminalID: %u\n", (uint8)descriptor->data[1]); |
| 161 | printf(" wTerminalType: %u\n", (uint16)descriptor->data[2]); |
| 162 | printf(" bAssocTerminal: %u\n", (uint8)descriptor->data[4]); |
| 163 | printf(" bSourceID: %u\n", (uint8)descriptor->data[5]); |
| 164 | printf(" iTerminal: %u\n", (uint8)descriptor->data[6]); |
| 165 | } |
| 166 | |
| 167 | |
| 168 | void |
| 169 | DumpAudioCSInterfaceDescriptorMixerUnit(const usb_generic_descriptor* descriptor) { |
| 170 | printf(" bLength: %u\n", descriptor->length); |
| 171 | printf(" bDescriptorType: %u (CS_INTERFACE)\n", descriptor->descriptor_type); |
| 172 | |
| 173 | printf(" bDescriptorSubtype: %u (MIXER_UNIT)\n", (uint8)descriptor->data[0]); |
| 174 | printf(" bUnitID: %u\n", (uint8)descriptor->data[1]); |
| 175 | |
| 176 | uint8 bNrInPins = (uint8)descriptor->data[2]; |
| 177 | printf(" bNrInPins: %u\n", bNrInPins); |
| 178 | for(uint8 i = 0; i < bNrInPins; i++) |
| 179 | printf(" baSourceID %u: %u\n", i+1, (uint8)descriptor->data[3+i]); |
| 180 | |
| 181 | int idx = 3+bNrInPins; |
| 182 | printf(" bNrChannels: %u\n", (uint8)descriptor->data[idx++]); |
| 183 | |
| 184 | uint16 wChannelConfig = (uint16)descriptor->data[idx]; |
| 185 | printf(" wChannelConfig: %u\n", wChannelConfig); |
| 186 | DumpChannelConfig(wChannelConfig); |
| 187 | |
| 188 | printf(" iChannelNames: %u\n", (uint8)descriptor->data[idx += 2]); |
| 189 | |
| 190 | for(uint i = 1; idx < descriptor->length-3; idx++, i++) |
| 191 | printf(" bmControl %u: %u\n", i, (uint8)descriptor->data[idx]); |
| 192 | |
| 193 | printf(" iMixer: %u\n", (uint8)descriptor->data[descriptor->length-3]); |
| 194 | } |
| 195 | |
| 196 | void |
| 197 | DumpAudioCSInterfaceDescriptorSelectorUnit(const usb_generic_descriptor* descriptor) { |
| 198 | printf(" bLength: %u\n", descriptor->length); |
| 199 | printf(" bDescriptorType: %u (CS_INTERFACE)\n", descriptor->descriptor_type); |
| 200 | |
| 201 | printf(" bDescriptorSubtype: %u (SELECTOR_UNIT)\n", (uint8)descriptor->data[0]); |
| 202 | printf(" bUnitID: %u\n", (uint8)descriptor->data[1]); |
| 203 | |
| 204 | uint8 bNrInPins = (uint8)descriptor->data[2]; |
| 205 | printf(" bNrInPins: %u\n", bNrInPins); |
| 206 | for(uint8 i = 0; i < bNrInPins; i++) |
| 207 | printf(" baSourceID %u: %u\n", i+1, (uint8)descriptor->data[3+i]); |
| 208 | |
| 209 | printf(" iSelector: %u\n", (uint8)descriptor->data[bNrInPins+2]); |
| 210 | } |
| 211 | |
| 212 | |
| 213 | void |
| 214 | DumpBMAControl(uint16 bma) { |
| 215 | int mask = 1; |
| 216 | if(bma & mask) |
| 217 | puts(" Mute"); |
| 218 | mask <<= 2; |
| 219 | if(bma & mask) |
| 220 | puts(" Volume"); |
| 221 | mask <<= 2; |
| 222 | if(bma & mask) |
| 223 | puts(" Bass"); |
| 224 | mask <<= 2; |
| 225 | if(bma & mask) |
| 226 | puts(" Mid"); |
| 227 | mask <<= 2; |
| 228 | if(bma & mask) |
| 229 | puts(" Treble"); |
| 230 | mask <<= 2; |
| 231 | if(bma & mask) |
| 232 | puts(" Graphic Equalizer"); |
| 233 | mask <<= 2; |
| 234 | if(bma & mask) |
| 235 | puts(" Automatic Gain"); |
| 236 | mask <<= 2; |
| 237 | if(bma & mask) |
| 238 | puts(" Delay"); |
| 239 | mask <<= 2; |
| 240 | if(bma & mask) |
| 241 | puts(" Bass Boost"); |
| 242 | mask <<= 2; |
| 243 | if(bma & mask) |
| 244 | puts(" Loudness"); |
| 245 | } |
| 246 | |
| 247 | |
| 248 | void |
| 249 | DumpAudioCSInterfaceDescriptorFeatureUnit(const usb_generic_descriptor* descriptor) { |
| 250 | printf(" bLength: %u\n", descriptor->length); |
| 251 | printf(" bDescriptorType: %u (CS_INTERFACE)\n", descriptor->descriptor_type); |
| 252 | |
| 253 | printf(" bDescriptorSubtype: %u (FEATURE_UNIT)\n", (uint8)descriptor->data[0]); |
| 254 | printf(" bUnitID: %u\n", (uint8)descriptor->data[1]); |
| 255 | printf(" bSourceID: %u\n", (uint8)descriptor->data[2]); |
| 256 | |
| 257 | uint8 bControlSize = (uint8)descriptor->data[3]; |
| 258 | printf(" bControlSize: %u\b", bControlSize); |
| 259 | uint8 channels = ((descriptor->length-2)-4) / bControlSize; |
| 260 | if (bControlSize == 1) { |
| 261 | for(uint8 i = 0; i < channels; i++) { |
| 262 | printf(" bmaControl %u: %u\n", i+1, (uint8)descriptor->data[4+i]); |
| 263 | DumpBMAControl((uint8)descriptor->data[4+i]); |
| 264 | } |
| 265 | } else if (bControlSize == 2) { |
| 266 | for(uint8 i = 0; i < channels; i++) { |
| 267 | printf(" bmaControl %u: %u\n", i+1, (uint16)descriptor->data[4+i*2]); |
| 268 | DumpBMAControl((uint16)descriptor->data[4+i*2]); |
| 269 | } |
| 270 | } else { |
| 271 | for(uint8 i = 0; i < channels; i++) { |
| 272 | printf(" bmaControlRaw: "); |
| 273 | for(uint8 j = 0; j < bControlSize; j++) { |
| 274 | printf("0x%02x", descriptor->data[4+i+j]); |
| 275 | } |
| 276 | } |
| 277 | } |
| 278 | printf(" iFeature: %u\n", (uint8)descriptor->data[descriptor->length-3]); |
| 279 | } |
| 280 | |
| 281 | void |
| 282 | DumpAudioCSInterfaceDescriptorAssociated(const usb_generic_descriptor* descriptor) { |
| 283 | printf(" bLength: %u\n", descriptor->length); |
| 284 | printf(" bDescriptorType: %u (CS_INTERFACE)\n", descriptor->descriptor_type); |
| 285 | |
| 286 | printf(" bDescriptorSubtype: %u (ASSOC_INTERFACE)\n", (uint8)descriptor->data[0]); |
| 287 | printf(" bInterfaceNr: %u\n", (uint8)descriptor->data[1]); |
| 288 | printf(" Association-specific data:"); |
| 289 | for(uint8 i = 0; i < descriptor->length-2; i++) |
| 290 | printf("%02x ", descriptor->data[i+2]); |
| 291 | } |
| 292 | |
| 293 | void |
| 294 | DumpAudioCSInterfaceDescriptor(const usb_generic_descriptor* descriptor) { |
| 295 | puts(" Class-Specific Audio Control Interface Descriptor"); |
| 296 | |
| 297 | uint16 descriptorSubtype = descriptor->data[0]; |
| 298 | switch (descriptorSubtype) { |
| 299 | case 0x01: |
| 300 | DumpAudioCSInterfaceDescriptorHeader(descriptor); |
| 301 | break; |
| 302 | case 0x02: |
| 303 | DumpAudioCSInterfaceDescriptorInputTerminal(descriptor); |
| 304 | break; |
| 305 | case 0x03: |
| 306 | DumpAudioCSInterfaceDescriptorOutputTerminal(descriptor); |
| 307 | break; |
| 308 | case 0x04: |
| 309 | DumpAudioCSInterfaceDescriptorMixerUnit(descriptor); |
| 310 | break; |
| 311 | case 0x05: |
| 312 | DumpAudioCSInterfaceDescriptorSelectorUnit(descriptor); |
| 313 | break; |
| 314 | case 0x06: |
| 315 | DumpAudioCSInterfaceDescriptorFeatureUnit(descriptor); |
| 316 | break; |
| 317 | case 0x08: |
| 318 | DumpAudioCSInterfaceDescriptorAssociated(descriptor); |
| 319 | break; |
| 320 | default: |
| 321 | DumpDescriptorData(descriptor); |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | void |
| 326 | DumpAudioDescriptor(const usb_generic_descriptor* descriptor) { |
| 327 | switch (descriptor->descriptor_type) { |
| 328 | case 0x24: |
| 329 | DumpAudioCSInterfaceDescriptor(descriptor); |
| 330 | break; |
| 331 | default: |
| 332 | DumpDescriptorData(descriptor); |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | |
| 337 | void |
| 338 | DumpDescriptor(const usb_generic_descriptor* descriptor, int classNum) { |
| 339 | switch (classNum) { |
| 340 | case 1: |
| 341 | DumpAudioDescriptor(descriptor); |
| 342 | break; |
| 343 | default: |
| 344 | DumpDescriptorData(descriptor); |
| 345 | } |
| 346 | } |
| 347 | |