Remove module from future :)
[calfbox.git] / usbprobe.c
blob2068deb0cf6dcbcde43386cb84b9798e35361ad4
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2013 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "usbio_impl.h"
20 #include <errno.h>
22 ////////////////////////////////////////////////////////////////////////////////
24 static const struct libusb_endpoint_descriptor *get_midi_endpoint(const struct libusb_interface_descriptor *asdescr, gboolean is_output)
26 for (int epi = 0; epi < asdescr->bNumEndpoints; epi++)
28 const struct libusb_endpoint_descriptor *ep = &asdescr->endpoint[epi];
29 if ((ep->bEndpointAddress >= 0x80) == !is_output)
30 return ep;
32 return NULL;
35 static const struct libusb_endpoint_descriptor *get_audio_output_endpoint(const struct libusb_interface_descriptor *asdescr, const struct libusb_endpoint_descriptor **sync_endpoint)
37 for (int epi = 0; epi < asdescr->bNumEndpoints; epi++)
39 const struct libusb_endpoint_descriptor *ep = &asdescr->endpoint[epi];
40 uint8_t ep_type = (ep->bmAttributes & 0xF);
41 if (ep->bEndpointAddress < 0x80 && (ep_type == 9 || ep_type == 13)) // output, isochronous, adaptive or synchronous
43 if (sync_endpoint)
44 *sync_endpoint = NULL;
45 return ep;
47 if (ep->bEndpointAddress < 0x80 && ep_type == 5) // output, isochronous, asynchronous
49 // Look for corresponding synch endpoint. It must be placed after the original output endpoint.
50 if (sync_endpoint && ep->bSynchAddress >= 0x81)
52 *sync_endpoint = NULL;
53 for(int epi2 = epi + 1; epi2 < asdescr->bNumEndpoints; epi2++)
55 const struct libusb_endpoint_descriptor *ep2 = &asdescr->endpoint[epi2];
56 if (ep2->bEndpointAddress == ep->bSynchAddress && (ep2->bmAttributes & 0xF) == 1) // input, isochronous, no sync
58 *sync_endpoint = ep2;
59 break;
63 return ep;
66 return NULL;
69 static void fill_endpoint_desc(struct usbio_endpoint_descriptor *epdesc, const struct libusb_endpoint_descriptor *ep)
71 epdesc->found = TRUE;
72 epdesc->interrupt = FALSE;
73 epdesc->bEndpointAddress = ep->bEndpointAddress;
74 epdesc->wMaxPacketSize = ep->wMaxPacketSize;
77 static gboolean fill_endpoint_by_address(const struct libusb_interface_descriptor *asdescr, uint8_t addr, struct usbio_endpoint_descriptor *epdesc)
79 epdesc->found = FALSE;
80 epdesc->interrupt = FALSE;
81 for (int epi = 0; epi < asdescr->bNumEndpoints; epi++)
83 const struct libusb_endpoint_descriptor *ep = &asdescr->endpoint[epi];
84 if (ep->bEndpointAddress == addr)
86 fill_endpoint_desc(epdesc, ep);
87 return TRUE;
90 return FALSE;
93 ////////////////////////////////////////////////////////////////////////////////
95 struct usb_ut_descriptor_header
97 uint8_t bLength;
98 uint8_t bDescriptorType;
99 uint8_t bDescriptorSubtype;
102 struct usb_class_specific_header
104 struct usb_ut_descriptor_header hdr;
105 uint8_t bcdADC[2];
106 uint8_t wTotalLengthLo, wTotalLengthHi;
107 uint8_t bInCollection;
108 uint8_t baInterfaceNr[0];
111 struct usbaudio_input_terminal_descriptor
113 uint8_t bTerminalID;
114 uint8_t wTerminalTypeLo, wTerminalTypeHi;
115 uint8_t bAssocTerminal;
116 uint8_t bNrChannels;
117 uint8_t wChannelConfigLo, wChannelConfigHi;
118 uint8_t iChannelNames;
119 uint8_t iTerminal;
122 struct usbaudio_output_terminal_descriptor
124 uint8_t bTerminalID;
125 uint8_t wTerminalTypeLo, wTerminalTypeHi;
126 uint8_t bAssocTerminal;
127 uint8_t bSourceID;
128 uint8_t iTerminal;
131 struct usbaudio_mixer_unit_descriptor1
133 uint8_t bUnitID;
134 uint8_t bNrInPins;
135 uint8_t baSourceID[0];
138 struct usbaudio_mixer_unit_descriptor2
140 uint8_t bNrChannels;
141 uint8_t wChannelConfigLo, wChannelConfigHi;
142 uint8_t bmControls[0];
143 // after the last index, 8-bit iMixer
146 struct usbaudio_selector_unit_descriptor1
148 uint8_t bUnitID;
149 uint8_t bNrInPins;
150 uint8_t baSourceID[0];
151 // after the last index, 8-bit iSelector
154 struct usbaudio_feature_unit_descriptor1
156 uint8_t bUnitID;
157 uint8_t bSourceID;
158 uint8_t bControlSize;
159 uint8_t bmaControls[0];
160 // after the last index, 8-bit iFeature
163 // Unit/Terminal Descriptor header from the spec
164 #include <stdio.h>
166 #if 0
167 // termt10.pdf
168 static const char *get_terminal_type_name(int type)
170 switch(type)
172 case 0x101: return "USB Streaming";
173 case 0x1FF: return "USB vendor specific";
174 case 0x201: return "Microphone";
175 case 0x202: return "Desktop microphone";
176 case 0x203: return "Personal microphone";
177 case 0x204: return "Omni-directional microphone";
178 case 0x205: return "Microphone array";
179 case 0x206: return "Processing microphone array";
180 case 0x301: return "Speaker";
181 case 0x302: return "Headphones";
182 case 0x303: return "Head-mounted display audio";
183 case 0x304: return "Desktop speaker";
184 case 0x305: return "Room speaker";
185 case 0x306: return "Communication speaker";
186 case 0x307: return "Low-frequency effects speaker";
187 case 0x400: return "Bi-directional Undefined";
188 case 0x401: return "Handset (handheld)";
189 case 0x402: return "Handset (head-mounted)";
190 case 0x403: return "Speakerphone";
191 case 0x404: return "Echo-suppressing speakerphone";
192 case 0x405: return "Echo-cancelling speakerphone";
193 case 0x501: return "Phone line";
194 case 0x502: return "Telephone";
195 case 0x503: return "Down line phone";
196 case 0x600: return "External Undefined";
197 case 0x601: return "Analog connector";
198 case 0x602: return "Digital audio interface";
199 case 0x603: return "Line connector";
200 case 0x604: return "Legacy audio";
201 case 0x605: return "S/PDIF";
202 case 0x606: return "1394 D/A Stream";
203 case 0x607: return "1394 D/V Stream Sountrack";
204 case 0x700: return "Embedded undefined";
205 case 0x701: return "Level calibration noise source";
206 case 0x702: return "Equalization noise";
207 case 0x703: return "CD player";
208 case 0x704: return "DAT";
209 case 0x705: return "DCC";
210 case 0x706: return "MiniDisc";
211 case 0x707: return "Analog tape";
212 case 0x708: return "Phono";
213 case 0x709: return "VCR Audio";
214 case 0x70A: return "VideoDisc Audio";
215 case 0x70B: return "DVD Audio";
216 case 0x70C: return "TV Tuner Audio";
217 case 0x70D: return "Satellite Receiver Audio";
218 case 0x70E: return "Cable Tuner Audio";
219 case 0x70F: return "DSS Audio";
220 case 0x710: return "Radio Receiver";
221 case 0x711: return "Radio Transmitter";
222 case 0x712: return "Multitrack Recorder";
223 case 0x713: return "Synthesizer";
224 default:
225 return "Unknown";
228 #endif
230 static gboolean parse_audio_control_class(struct cbox_usb_audio_info *uai, const struct libusb_interface_descriptor *asdescr, gboolean other_config)
232 #if 0
233 if (asdescr->extra_length < 8)
235 g_warning("AudioControl interface descriptor length is %d, should be at least 8", (int)asdescr->extra_length);
236 return FALSE;
238 const struct usb_class_specific_header *extra = (const struct usb_class_specific_header *)asdescr->extra;
239 uint16_t wTotalLength = extra->wTotalLengthLo + 256 * extra->wTotalLengthHi;
240 if (wTotalLength > asdescr->extra_length)
242 g_warning("AudioControl interface descriptor total length is %d, but libusb value is %d", (int)wTotalLength, (int)asdescr->extra_length);
243 return FALSE;
245 if (extra->hdr.bDescriptorType != 36)
247 g_warning("AudioControl interface descriptor type is %d, but expected 36 (CS_INTERFACE)", (int)extra->hdr.bDescriptorType);
248 return FALSE;
250 if (extra->hdr.bDescriptorSubtype != 1)
252 g_warning("AudioControl interface descriptor type is %d, but expected 1 (HEADER)", (int)extra->hdr.bDescriptorSubtype);
253 return FALSE;
256 printf("Device %04x:%04x\n", uai->udi->vid, uai->udi->pid);
257 printf("hdrlen=%d dt=%d dst=%d ver=%02x%02x total len=%d\n", extra->hdr.bLength, extra->hdr.bDescriptorType, extra->hdr.bDescriptorSubtype, extra->bcdADC[0], extra->bcdADC[1], wTotalLength);
258 for(int i = 0; i < extra->bInCollection; i++)
260 printf("interface nr %d = %d\n", i, extra->baInterfaceNr[i]);
263 for(uint32_t pos = extra->hdr.bLength; pos < wTotalLength; pos += asdescr->extra[pos])
265 const struct usb_ut_descriptor_header *hdr = (const struct usb_ut_descriptor_header *)(asdescr->extra + pos);
266 if (hdr->bDescriptorType != 36)
268 g_warning("Skipping unit/terminal descriptor type %d,%d", (int)hdr->bDescriptorType, (int)hdr->bDescriptorSubtype);
269 continue;
271 printf("hdr %d,%d len %d\n", hdr->bDescriptorType, hdr->bDescriptorSubtype, hdr->bLength);
272 switch(hdr->bDescriptorSubtype)
274 case 2: // INPUT_TERMINAL
276 const struct usbaudio_input_terminal_descriptor *itd = (const struct usbaudio_input_terminal_descriptor *)(hdr + 1);
277 int wTerminalType = itd->wTerminalTypeHi * 256 + itd->wTerminalTypeLo;
278 printf("INPUT TERMINAL %d: type %04x (%s)\n", (int)itd->bTerminalID, wTerminalType, get_terminal_type_name(wTerminalType));
279 break;
281 case 3: // OUTPUT_TERMINAL
283 const struct usbaudio_output_terminal_descriptor *otd = (const struct usbaudio_output_terminal_descriptor *)(hdr + 1);
284 int wTerminalType = otd->wTerminalTypeHi * 256 + otd->wTerminalTypeLo;
285 printf("OUTPUT TERMINAL %d: type %04x (%s) source %d\n", (int)otd->bTerminalID, wTerminalType, get_terminal_type_name(wTerminalType), otd->bSourceID);
286 break;
288 case 4: // MIXER_UNIT
290 const struct usbaudio_mixer_unit_descriptor1 *mud = (const struct usbaudio_mixer_unit_descriptor1 *)(hdr + 1);
291 printf("MIXER UNIT %d\n", (int)mud->bUnitID);
292 for (int i = 0; i < mud->bNrInPins; i++)
294 printf("Input[%d] = %d\n", i, mud->baSourceID[i]);
296 break;
298 case 5: // SELECTOR_UNIT
300 const struct usbaudio_selector_unit_descriptor1 *sud = (const struct usbaudio_selector_unit_descriptor1 *)(hdr + 1);
301 printf("SELECTOR UNIT %d (%d pins)\n", (int)sud->bUnitID, sud->bNrInPins);
302 for (int i = 0; i < sud->bNrInPins; i++)
304 printf("Input[%d] = %d\n", i, sud->baSourceID[i]);
306 break;
308 case 6: // FEATURE_UNIT
310 static const char *features[] = {"Mute", "Volume", "Bass", "Mid", "Treble", "EQ", "AGC", "Delay", "Bass Boost", "Loudness" };
311 const struct usbaudio_feature_unit_descriptor1 *fud = (const struct usbaudio_feature_unit_descriptor1 *)(hdr + 1);
312 printf("FEATURE UNIT %d (source = %d, control size %d)\n", (int)fud->bUnitID, fud->bSourceID, fud->bControlSize);
313 for (int i = 0; i < fud->bControlSize * 8; i++)
315 if (i >= sizeof(features) / sizeof(features[0]))
316 break;
317 if (fud->bmaControls[i >> 3] & (1 << (i & 7)))
318 printf("Master %s\n", features[i]);
320 for (int ch = 1; ch < (hdr->bLength - 7) / fud->bControlSize; ch++)
322 int chofs = ch * fud->bControlSize;
323 for (int i = 0; i < fud->bControlSize * 8; i++)
325 if (i >= sizeof(features) / sizeof(features[0]))
326 break;
327 if (fud->bmaControls[(i >> 3) + chofs] & (1 << (i & 7)))
328 printf("Channel %d %s\n", ch, features[i]);
331 break;
333 default:
334 printf("Unsupported unit type %d\n", hdr->bDescriptorSubtype);
335 break;
338 #endif
339 return FALSE;
342 struct usbaudio_streaming_interface_descriptor_general
344 struct usb_ut_descriptor_header hdr; // 7, 36, 1
345 uint8_t bTerminalLink;
346 uint8_t bDelay;
347 uint8_t wFormatTagLo, wFormatTagHi;
350 struct usbaudio_streaming_interface_descriptor_format_type_pcm
352 struct usb_ut_descriptor_header hdr; // 7, 36, 2
353 uint8_t bFormatType;
354 uint8_t bNrChannels;
355 uint8_t bSubframeSize;
356 uint8_t bBitResolution;
357 uint8_t bSamFreqType;
358 uint8_t taSamFreq[0][3];
361 static gboolean parse_audio_class(struct cbox_usb_io_impl *uii, struct cbox_usb_audio_info *uai, const struct libusb_interface_descriptor *asdescr, gboolean other_config)
363 // omit alternate setting 0, as it's used to describe a 'standby' setting of the interface (no bandwidth)
364 if (asdescr->bAlternateSetting == 0)
365 return FALSE;
366 if (asdescr->extra_length < 7)
368 g_warning("AudioStreaming interface descriptor length is %d, should be at least 7", (int)asdescr->extra_length);
369 return FALSE;
371 const struct usbaudio_streaming_interface_descriptor_general *extra = (struct usbaudio_streaming_interface_descriptor_general *)asdescr->extra;
372 if (extra->hdr.bLength != 7 || extra->hdr.bDescriptorType != 36 || extra->hdr.bDescriptorSubtype != 1)
374 g_warning("The AudioStreaming descriptor does not start with the general descriptor (len %d, type %d, subtype %d)", (int)extra->hdr.bLength, (int)extra->hdr.bDescriptorType, (int)extra->hdr.bDescriptorSubtype);
375 return FALSE;
377 if (extra->wFormatTagLo != 1 || extra->wFormatTagHi != 0)
379 g_warning("The AudioStreaming descriptor does not describe a PCM device");
380 return FALSE;
382 const struct usbaudio_streaming_interface_descriptor_format_type_pcm *fmt = (struct usbaudio_streaming_interface_descriptor_format_type_pcm *)(asdescr->extra + extra->hdr.bLength);
383 if (fmt->hdr.bLength < 11 || ((fmt->hdr.bLength - 11) % 3) || fmt->hdr.bDescriptorType != 36 || fmt->hdr.bDescriptorSubtype != 2)
385 g_warning("The AudioStreaming descriptor does not have a format type descriptor after general descriptor (len %d, type %d, subtype %d)", (int)fmt->hdr.bLength, (int)fmt->hdr.bDescriptorType, (int)fmt->hdr.bDescriptorSubtype);
386 return FALSE;
389 // We need this to tell inputs from outputs - until I implement reasonable
390 // Audio Control support
391 const struct libusb_endpoint_descriptor *sync_ep = NULL;
392 const struct libusb_endpoint_descriptor *ep = get_audio_output_endpoint(asdescr, &sync_ep);
393 if (ep)
395 if (fmt->bBitResolution != uii->output_resolution * 8)
397 g_warning("Interface %d alternate setting %d does not support %d bit resolution, only %d", asdescr->bInterfaceNumber, asdescr->bAlternateSetting, uii->output_resolution * 8, fmt->bBitResolution);
398 return FALSE;
400 if (fmt->bSamFreqType)
402 gboolean found = FALSE;
403 for (int i = 0; i < fmt->bSamFreqType; i++)
405 int sf = fmt->taSamFreq[i][0] + 256 * fmt->taSamFreq[i][1] + 65536 * fmt->taSamFreq[i][2];
406 if (sf == uii->sample_rate)
408 found = TRUE;
409 break;
412 if (!found)
414 g_warning("Interface %d alternate setting %d does not support sample rate of %d Hz", asdescr->bInterfaceNumber, asdescr->bAlternateSetting, uii->sample_rate);
415 for (int i = 0; i < fmt->bSamFreqType; i++)
417 int sf = fmt->taSamFreq[i][0] + 256 * fmt->taSamFreq[i][1] + 65536 * fmt->taSamFreq[i][2];
418 g_warning("Sample rate[%d] = %d Hz", i, sf);
420 return FALSE;
423 // XXXKF in case of continuous sample rate, check the limits... assuming
424 // that there are any devices with continuous sample rate, that is.
425 if (other_config)
426 return TRUE;
427 if (uai->epdesc.found)
428 return FALSE;
429 if (sync_ep)
430 g_warning("Interface %d alt-setting %d endpoint %02x (synched via %02x) looks promising", asdescr->bInterfaceNumber, asdescr->bAlternateSetting, ep->bEndpointAddress, sync_ep->bEndpointAddress);
431 else
432 g_warning("Interface %d alt-setting %d endpoint %02x looks promising", asdescr->bInterfaceNumber, asdescr->bAlternateSetting, ep->bEndpointAddress);
433 uai->intf = asdescr->bInterfaceNumber;
434 uai->alt_setting = asdescr->bAlternateSetting;
435 fill_endpoint_desc(&uai->epdesc, ep);
436 uai->sync_protocol = (sync_ep != NULL) ? USBAUDIOSYNC_PROTOCOL_CLASS : USBAUDIOSYNC_PROTOCOL_NONE;
437 if (sync_ep)
438 fill_endpoint_desc(&uai->sync_epdesc, sync_ep);
439 else
440 uai->sync_epdesc.found = FALSE;
441 return TRUE;
443 return FALSE;
446 static gboolean parse_midi_class(struct cbox_usb_midi_info *umi, const struct libusb_interface_descriptor *asdescr, gboolean other_config, gboolean is_output)
448 const struct libusb_endpoint_descriptor *ep = get_midi_endpoint(asdescr, is_output);
449 if (!ep)
450 return FALSE;
452 if (other_config)
453 return TRUE;
455 struct usbio_endpoint_descriptor *epd = is_output ? &umi->epdesc_out : &umi->epdesc_in;
457 if (epd->found)
458 return FALSE;
459 umi->intf = asdescr->bInterfaceNumber;
460 umi->alt_setting = asdescr->bAlternateSetting;
461 fill_endpoint_desc(epd, ep);
462 return TRUE;
465 static gboolean inspect_device(struct cbox_usb_io_impl *uii, struct libusb_device *dev, uint16_t busdevadr, gboolean probe_only)
467 struct libusb_device_descriptor dev_descr;
468 int bus = busdevadr >> 8;
469 int devadr = busdevadr & 255;
471 if (0 != libusb_get_device_descriptor(dev, &dev_descr))
473 g_warning("USB device %03d:%03d - cannot get device descriptor (will retry)", bus, devadr);
474 return FALSE;
477 struct cbox_usb_device_info *udi = g_hash_table_lookup(uii->device_table, GINT_TO_POINTER(busdevadr));
478 if (!udi)
480 struct libusb_config_descriptor *cfg_descr = NULL;
481 if (0 != libusb_get_active_config_descriptor(dev, &cfg_descr))
482 return FALSE;
483 udi = malloc(sizeof(struct cbox_usb_device_info));
484 udi->dev = dev;
485 udi->handle = NULL;
486 udi->status = CBOX_DEVICE_STATUS_PROBING;
487 udi->active_config = cfg_descr->bConfigurationValue;
488 udi->bus = bus;
489 udi->devadr = devadr;
490 udi->busdevadr = busdevadr;
491 udi->vid = dev_descr.idVendor;
492 udi->pid = dev_descr.idProduct;
493 udi->configs_with_midi = 0;
494 udi->configs_with_audio = 0;
495 udi->is_midi = FALSE;
496 udi->is_audio = FALSE;
497 udi->last_probe_time = time(NULL);
498 udi->failures = 0;
499 g_hash_table_insert(uii->device_table, GINT_TO_POINTER(busdevadr), udi);
500 libusb_free_config_descriptor(cfg_descr);
502 else
503 if (udi->vid == dev_descr.idVendor && udi->pid == dev_descr.idProduct)
505 // device already open or determined to be
506 if (udi->status == CBOX_DEVICE_STATUS_OPENED ||
507 udi->status == CBOX_DEVICE_STATUS_UNSUPPORTED)
508 return FALSE;
509 // give up after 10 attempts to query or open the device
510 if (udi->failures > 10)
511 return FALSE;
512 // only do ~1 attempt per second
513 if (probe_only && time(NULL) == udi->last_probe_time)
514 return FALSE;
515 udi->last_probe_time = time(NULL);
518 struct cbox_usb_audio_info uainf;
519 cbox_usb_audio_info_init(&uainf, udi);
521 struct cbox_usb_midi_info uminf;
522 cbox_usb_midi_info_init(&uminf, udi);
524 gboolean is_audio = FALSE;
526 // printf("%03d:%03d Device %04X:%04X\n", bus, devadr, dev_descr.idVendor, dev_descr.idProduct);
527 for (int ci = 0; ci < (int)dev_descr.bNumConfigurations; ci++)
529 struct libusb_config_descriptor *cfg_descr = NULL;
530 // if this is not the current config, and another config with MIDI input
531 // has already been found, do not look any further
532 if (0 != libusb_get_config_descriptor(dev, ci, &cfg_descr))
534 udi->failures++;
535 g_warning("%03d:%03d - cannot get configuration descriptor (try %d)", bus, devadr, udi->failures);
536 return FALSE;
539 int cur_config = cfg_descr->bConfigurationValue;
540 gboolean other_config = cur_config != udi->active_config;
541 uint32_t config_mask = 0;
542 // XXXKF not sure about legal range for bConfigurationValue
543 if(cfg_descr->bConfigurationValue >= 0 && cfg_descr->bConfigurationValue < 32)
544 config_mask = 1 << cfg_descr->bConfigurationValue;
545 else
546 g_warning("Unexpected configuration value %d", cfg_descr->bConfigurationValue);
548 for (int ii = 0; ii < cfg_descr->bNumInterfaces; ii++)
550 const struct libusb_interface *idescr = &cfg_descr->interface[ii];
551 for (int as = 0; as < idescr->num_altsetting; as++)
553 const struct libusb_interface_descriptor *asdescr = &idescr->altsetting[as];
554 if (asdescr->bInterfaceClass == LIBUSB_CLASS_AUDIO && asdescr->bInterfaceSubClass == 1) // Audio control
556 if (parse_audio_control_class(&uainf, asdescr, other_config) && other_config)
557 udi->configs_with_audio |= config_mask;
559 else if (asdescr->bInterfaceClass == LIBUSB_CLASS_AUDIO && asdescr->bInterfaceSubClass == 2) // Audio streaming
561 if (parse_audio_class(uii, &uainf, asdescr, other_config) && other_config)
562 udi->configs_with_audio |= config_mask;
564 else if (asdescr->bInterfaceClass == LIBUSB_CLASS_AUDIO && asdescr->bInterfaceSubClass == 3) // MIDI streaming
566 if (parse_midi_class(&uminf, asdescr, other_config, FALSE) && other_config)
567 udi->configs_with_midi |= config_mask;
568 if (parse_midi_class(&uminf, asdescr, other_config, TRUE) && other_config)
569 udi->configs_with_midi |= config_mask;
570 uminf.protocol = USBMIDI_PROTOCOL_CLASS;
572 else if (udi->vid == 0x09e8 && udi->pid == 0x0062) // Akai MPD16
574 uminf.intf = asdescr->bInterfaceNumber;
575 uminf.alt_setting = asdescr->bAlternateSetting;
576 uminf.protocol = USBMIDI_PROTOCOL_MPD16;
577 fill_endpoint_by_address(asdescr, 0x82, &uminf.epdesc_in);
579 else if (udi->vid == 0x1235 && udi->pid == 0x000a) // Novation Nocturn
581 uminf.intf = asdescr->bInterfaceNumber;
582 uminf.alt_setting = asdescr->bAlternateSetting;
583 fill_endpoint_by_address(asdescr, 0x81, &uminf.epdesc_in);
584 fill_endpoint_by_address(asdescr, 0x02, &uminf.epdesc_out);
585 uminf.epdesc_in.interrupt = TRUE;
586 uminf.epdesc_out.interrupt = TRUE;
587 uminf.protocol = USBMIDI_PROTOCOL_NOCTURN;
591 libusb_free_config_descriptor(cfg_descr);
593 if (!uminf.epdesc_in.found && !uminf.epdesc_out.found && udi->configs_with_midi)
594 g_warning("%03d:%03d - MIDI port available on different configs: mask=0x%x", bus, devadr, udi->configs_with_midi);
596 if (uainf.epdesc.found) // Class-compliant USB audio device
597 is_audio = TRUE;
598 if (udi->vid == 0x13b2 && udi->pid == 0x0030) // Alesis Multimix 8
600 uainf.sync_protocol = USBAUDIOSYNC_PROTOCOL_MULTIMIX8; // not used later
601 is_audio = TRUE;
604 // All configs/interfaces/alts scanned, nothing interesting found -> mark as unsupported
605 udi->is_midi = uminf.epdesc_in.found || uminf.epdesc_out.found;
606 udi->is_audio = is_audio;
607 if (!udi->is_midi && !udi->is_audio)
609 udi->status = CBOX_DEVICE_STATUS_UNSUPPORTED;
610 return FALSE;
613 gboolean opened = FALSE;
614 struct libusb_device_handle *handle = NULL;
615 int err = libusb_open(dev, &handle);
616 if (0 != err)
618 g_warning("Cannot open device %03d:%03d: %s; errno = %s", bus, devadr, libusb_error_name(err), strerror(errno));
619 udi->failures++;
620 return FALSE;
623 if (probe_only)
625 libusb_close(handle);
626 // Make sure that the reconnection code doesn't bail out due to
627 // last_probe_time == now.
628 udi->last_probe_time = 0;
629 return udi->is_midi || udi->is_audio;
632 if (uminf.epdesc_in.found || uminf.epdesc_out.found)
634 g_debug("Found MIDI device %03d:%03d, trying to open", bus, devadr);
635 if (0 != usbio_open_midi_interface(uii, &uminf, handle))
636 opened = TRUE;
638 if (uainf.epdesc.found)
640 GError *error = NULL;
641 if (usbio_open_audio_interface(uii, &uainf, handle, &error))
643 // should have already been marked as opened by the MIDI code, but
644 // I might add the ability to disable some MIDI interfaces at some point
645 udi->status = CBOX_DEVICE_STATUS_OPENED;
646 opened = TRUE;
648 else
650 g_warning("Cannot open class-compliant USB audio output: %s", error->message);
651 g_error_free(error);
654 else if (udi->vid == 0x13b2 && udi->pid == 0x0030)
656 GError *error = NULL;
657 if (usbio_open_audio_interface_multimix(uii, bus, devadr, handle, &error))
659 // should have already been marked as opened by the MIDI code, but
660 // I might add the ability to disable some MIDI interfaces at some point
661 udi->status = CBOX_DEVICE_STATUS_OPENED;
662 opened = TRUE;
664 else
666 g_warning("Cannot open Alesis Multimix audio output: %s", error->message);
667 g_error_free(error);
671 if (!opened)
673 udi->failures++;
674 libusb_close(handle);
676 else
677 udi->handle = handle;
679 return opened;
682 gboolean usbio_scan_devices(struct cbox_usb_io_impl *uii, gboolean probe_only)
684 struct libusb_device **dev_list;
685 size_t i, num_devices;
686 gboolean added = FALSE;
687 gboolean removed = FALSE;
689 num_devices = libusb_get_device_list(probe_only ? uii->usbctx_probe : uii->usbctx, &dev_list);
691 uint16_t *busdevadrs = malloc(sizeof(uint16_t) * num_devices);
692 for (i = 0; i < num_devices; i++)
694 struct libusb_device *dev = dev_list[i];
695 int bus = libusb_get_bus_number(dev);
696 int devadr = libusb_get_device_address(dev);
697 busdevadrs[i] = (bus << 8) | devadr;
700 GList *prev_keys = g_hash_table_get_values(uii->device_table);
701 for (GList *p = prev_keys; p; p = p->next)
703 gboolean found = FALSE;
704 struct cbox_usb_device_info *udi = p->data;
705 for (i = 0; !found && i < num_devices; i++)
706 found = busdevadrs[i] == udi->busdevadr;
707 if (!found)
709 // Only specifically trigger removal if the device is ours
710 if (udi->status == CBOX_DEVICE_STATUS_OPENED)
712 g_message("Disconnected: %03d:%03d (%s)", udi->bus, udi->devadr, probe_only ? "probe" : "reconfigure");
713 removed = TRUE;
715 if (!probe_only)
716 usbio_forget_device(uii, udi);
719 g_list_free(prev_keys);
721 for (i = 0; i < num_devices; i++)
722 added = inspect_device(uii, dev_list[i], busdevadrs[i], probe_only) || added;
724 free(busdevadrs);
725 libusb_free_device_list(dev_list, 0);
726 return added || removed;
729 void usbio_forget_device(struct cbox_usb_io_impl *uii, struct cbox_usb_device_info *devinfo)
731 g_hash_table_remove(uii->device_table, GINT_TO_POINTER(devinfo->busdevadr));
732 for (GList *p = uii->midi_ports, *pNext = NULL; p; p = pNext)
734 pNext = p->next;
735 struct cbox_usb_midi_interface *umi = p->data;
736 if (umi->busdevadr == devinfo->busdevadr)
738 uii->midi_ports = g_list_delete_link(uii->midi_ports, p);
739 free(umi);
742 if (uii->handle_audiodev == devinfo->handle)
743 uii->handle_audiodev = NULL;
744 libusb_close(devinfo->handle);
745 free(devinfo);