We're including config.h everywhere, so we should pass compatible compiler options.
[calfbox.git] / usbprobe.c
blob44a3ebdf43cd5827b01c315815cf29b286202d4e
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)
37 for (int epi = 0; epi < asdescr->bNumEndpoints; epi++)
39 const struct libusb_endpoint_descriptor *ep = &asdescr->endpoint[epi];
40 if (ep->bEndpointAddress < 0x80 && (ep->bmAttributes & 0xF) == 9) // output, isochronous, adaptive
41 return ep;
43 return NULL;
46 static void fill_endpoint_desc(struct usbio_endpoint_descriptor *epdesc, const struct libusb_endpoint_descriptor *ep)
48 epdesc->found = TRUE;
49 epdesc->interrupt = FALSE;
50 epdesc->bEndpointAddress = ep->bEndpointAddress;
51 epdesc->wMaxPacketSize = ep->wMaxPacketSize;
54 static gboolean fill_endpoint_by_address(const struct libusb_interface_descriptor *asdescr, uint8_t addr, struct usbio_endpoint_descriptor *epdesc)
56 epdesc->found = FALSE;
57 epdesc->interrupt = FALSE;
58 for (int epi = 0; epi < asdescr->bNumEndpoints; epi++)
60 const struct libusb_endpoint_descriptor *ep = &asdescr->endpoint[epi];
61 if (ep->bEndpointAddress == addr)
63 fill_endpoint_desc(epdesc, ep);
64 return TRUE;
67 return FALSE;
70 ////////////////////////////////////////////////////////////////////////////////
72 struct usb_ut_descriptor_header
74 uint8_t bLength;
75 uint8_t bDescriptorType;
76 uint8_t bDescriptorSubtype;
79 struct usb_class_specific_header
81 struct usb_ut_descriptor_header hdr;
82 uint8_t bcdADC[2];
83 uint8_t wTotalLengthLo, wTotalLengthHi;
84 uint8_t bInCollection;
85 uint8_t baInterfaceNr[0];
88 struct usbaudio_input_terminal_descriptor
90 uint8_t bTerminalID;
91 uint8_t wTerminalTypeLo, wTerminalTypeHi;
92 uint8_t bAssocTerminal;
93 uint8_t bNrChannels;
94 uint8_t wChannelConfigLo, wChannelConfigHi;
95 uint8_t iChannelNames;
96 uint8_t iTerminal;
99 struct usbaudio_output_terminal_descriptor
101 uint8_t bTerminalID;
102 uint8_t wTerminalTypeLo, wTerminalTypeHi;
103 uint8_t bAssocTerminal;
104 uint8_t bSourceID;
105 uint8_t iTerminal;
108 struct usbaudio_mixer_unit_descriptor1
110 uint8_t bUnitID;
111 uint8_t bNrInPins;
112 uint8_t baSourceID[0];
115 struct usbaudio_mixer_unit_descriptor2
117 uint8_t bNrChannels;
118 uint8_t wChannelConfigLo, wChannelConfigHi;
119 uint8_t bmControls[0];
120 // after the last index, 8-bit iMixer
123 struct usbaudio_selector_unit_descriptor1
125 uint8_t bUnitID;
126 uint8_t bNrInPins;
127 uint8_t baSourceID[0];
128 // after the last index, 8-bit iSelector
131 struct usbaudio_feature_unit_descriptor1
133 uint8_t bUnitID;
134 uint8_t bSourceID;
135 uint8_t bControlSize;
136 uint8_t bmaControls[0];
137 // after the last index, 8-bit iFeature
140 // Unit/Terminal Descriptor header from the spec
141 #include <stdio.h>
143 #if 0
144 // termt10.pdf
145 static const char *get_terminal_type_name(int type)
147 switch(type)
149 case 0x101: return "USB Streaming";
150 case 0x1FF: return "USB vendor specific";
151 case 0x201: return "Microphone";
152 case 0x202: return "Desktop microphone";
153 case 0x203: return "Personal microphone";
154 case 0x204: return "Omni-directional microphone";
155 case 0x205: return "Microphone array";
156 case 0x206: return "Processing microphone array";
157 case 0x301: return "Speaker";
158 case 0x302: return "Headphones";
159 case 0x303: return "Head-mounted display audio";
160 case 0x304: return "Desktop speaker";
161 case 0x305: return "Room speaker";
162 case 0x306: return "Communication speaker";
163 case 0x307: return "Low-frequency effects speaker";
164 case 0x400: return "Bi-directional Undefined";
165 case 0x401: return "Handset (handheld)";
166 case 0x402: return "Handset (head-mounted)";
167 case 0x403: return "Speakerphone";
168 case 0x404: return "Echo-suppressing speakerphone";
169 case 0x405: return "Echo-cancelling speakerphone";
170 case 0x501: return "Phone line";
171 case 0x502: return "Telephone";
172 case 0x503: return "Down line phone";
173 case 0x600: return "External Undefined";
174 case 0x601: return "Analog connector";
175 case 0x602: return "Digital audio interface";
176 case 0x603: return "Line connector";
177 case 0x604: return "Legacy audio";
178 case 0x605: return "S/PDIF";
179 case 0x606: return "1394 D/A Stream";
180 case 0x607: return "1394 D/V Stream Sountrack";
181 case 0x700: return "Embedded undefined";
182 case 0x701: return "Level calibration noise source";
183 case 0x702: return "Equalization noise";
184 case 0x703: return "CD player";
185 case 0x704: return "DAT";
186 case 0x705: return "DCC";
187 case 0x706: return "MiniDisc";
188 case 0x707: return "Analog tape";
189 case 0x708: return "Phono";
190 case 0x709: return "VCR Audio";
191 case 0x70A: return "VideoDisc Audio";
192 case 0x70B: return "DVD Audio";
193 case 0x70C: return "TV Tuner Audio";
194 case 0x70D: return "Satellite Receiver Audio";
195 case 0x70E: return "Cable Tuner Audio";
196 case 0x70F: return "DSS Audio";
197 case 0x710: return "Radio Receiver";
198 case 0x711: return "Radio Transmitter";
199 case 0x712: return "Multitrack Recorder";
200 case 0x713: return "Synthesizer";
201 default:
202 return "Unknown";
205 #endif
207 static gboolean parse_audio_control_class(struct cbox_usb_audio_info *uai, const struct libusb_interface_descriptor *asdescr, gboolean other_config)
209 #if 0
210 if (asdescr->extra_length < 8)
212 g_warning("AudioControl interface descriptor length is %d, should be at least 8", (int)asdescr->extra_length);
213 return FALSE;
215 const struct usb_class_specific_header *extra = (const struct usb_class_specific_header *)asdescr->extra;
216 uint16_t wTotalLength = extra->wTotalLengthLo + 256 * extra->wTotalLengthHi;
217 if (wTotalLength > asdescr->extra_length)
219 g_warning("AudioControl interface descriptor total length is %d, but libusb value is %d", (int)wTotalLength, (int)asdescr->extra_length);
220 return FALSE;
222 if (extra->hdr.bDescriptorType != 36)
224 g_warning("AudioControl interface descriptor type is %d, but expected 36 (CS_INTERFACE)", (int)extra->hdr.bDescriptorType);
225 return FALSE;
227 if (extra->hdr.bDescriptorSubtype != 1)
229 g_warning("AudioControl interface descriptor type is %d, but expected 1 (HEADER)", (int)extra->hdr.bDescriptorSubtype);
230 return FALSE;
233 printf("Device %04x:%04x\n", uai->udi->vid, uai->udi->pid);
234 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);
235 for(int i = 0; i < extra->bInCollection; i++)
237 printf("interface nr %d = %d\n", i, extra->baInterfaceNr[i]);
240 for(uint32_t pos = extra->hdr.bLength; pos < wTotalLength; pos += asdescr->extra[pos])
242 const struct usb_ut_descriptor_header *hdr = (const struct usb_ut_descriptor_header *)(asdescr->extra + pos);
243 if (hdr->bDescriptorType != 36)
245 g_warning("Skipping unit/terminal descriptor type %d,%d", (int)hdr->bDescriptorType, (int)hdr->bDescriptorSubtype);
246 continue;
248 printf("hdr %d,%d len %d\n", hdr->bDescriptorType, hdr->bDescriptorSubtype, hdr->bLength);
249 switch(hdr->bDescriptorSubtype)
251 case 2: // INPUT_TERMINAL
253 const struct usbaudio_input_terminal_descriptor *itd = (const struct usbaudio_input_terminal_descriptor *)(hdr + 1);
254 int wTerminalType = itd->wTerminalTypeHi * 256 + itd->wTerminalTypeLo;
255 printf("INPUT TERMINAL %d: type %04x (%s)\n", (int)itd->bTerminalID, wTerminalType, get_terminal_type_name(wTerminalType));
256 break;
258 case 3: // OUTPUT_TERMINAL
260 const struct usbaudio_output_terminal_descriptor *otd = (const struct usbaudio_output_terminal_descriptor *)(hdr + 1);
261 int wTerminalType = otd->wTerminalTypeHi * 256 + otd->wTerminalTypeLo;
262 printf("OUTPUT TERMINAL %d: type %04x (%s) source %d\n", (int)otd->bTerminalID, wTerminalType, get_terminal_type_name(wTerminalType), otd->bSourceID);
263 break;
265 case 4: // MIXER_UNIT
267 const struct usbaudio_mixer_unit_descriptor1 *mud = (const struct usbaudio_mixer_unit_descriptor1 *)(hdr + 1);
268 printf("MIXER UNIT %d\n", (int)mud->bUnitID);
269 for (int i = 0; i < mud->bNrInPins; i++)
271 printf("Input[%d] = %d\n", i, mud->baSourceID[i]);
273 break;
275 case 5: // SELECTOR_UNIT
277 const struct usbaudio_selector_unit_descriptor1 *sud = (const struct usbaudio_selector_unit_descriptor1 *)(hdr + 1);
278 printf("SELECTOR UNIT %d (%d pins)\n", (int)sud->bUnitID, sud->bNrInPins);
279 for (int i = 0; i < sud->bNrInPins; i++)
281 printf("Input[%d] = %d\n", i, sud->baSourceID[i]);
283 break;
285 case 6: // FEATURE_UNIT
287 static const char *features[] = {"Mute", "Volume", "Bass", "Mid", "Treble", "EQ", "AGC", "Delay", "Bass Boost", "Loudness" };
288 const struct usbaudio_feature_unit_descriptor1 *fud = (const struct usbaudio_feature_unit_descriptor1 *)(hdr + 1);
289 printf("FEATURE UNIT %d (source = %d, control size %d)\n", (int)fud->bUnitID, fud->bSourceID, fud->bControlSize);
290 for (int i = 0; i < fud->bControlSize * 8; i++)
292 if (i >= sizeof(features) / sizeof(features[0]))
293 break;
294 if (fud->bmaControls[i >> 3] & (1 << (i & 7)))
295 printf("Master %s\n", features[i]);
297 for (int ch = 1; ch < (hdr->bLength - 7) / fud->bControlSize; ch++)
299 int chofs = ch * fud->bControlSize;
300 for (int i = 0; i < fud->bControlSize * 8; i++)
302 if (i >= sizeof(features) / sizeof(features[0]))
303 break;
304 if (fud->bmaControls[(i >> 3) + chofs] & (1 << (i & 7)))
305 printf("Channel %d %s\n", ch, features[i]);
308 break;
310 default:
311 printf("Unsupported unit type %d\n", hdr->bDescriptorSubtype);
312 break;
315 #endif
316 return FALSE;
319 struct usbaudio_streaming_interface_descriptor_general
321 struct usb_ut_descriptor_header hdr; // 7, 36, 1
322 uint8_t bTerminalLink;
323 uint8_t bDelay;
324 uint8_t wFormatTagLo, wFormatTagHi;
327 struct usbaudio_streaming_interface_descriptor_format_type_pcm
329 struct usb_ut_descriptor_header hdr; // 7, 36, 2
330 uint8_t bFormatType;
331 uint8_t bNrChannels;
332 uint8_t bSubframeSize;
333 uint8_t bBitResolution;
334 uint8_t bSamFreqType;
335 uint8_t taSamFreq[0][3];
338 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)
340 // omit alternate setting 0, as it's used to describe a 'standby' setting of the interface (no bandwidth)
341 if (asdescr->bAlternateSetting == 0)
342 return FALSE;
343 if (asdescr->extra_length < 7)
345 g_warning("AudioStreaming interface descriptor length is %d, should be at least 7", (int)asdescr->extra_length);
346 return FALSE;
348 const struct usbaudio_streaming_interface_descriptor_general *extra = (struct usbaudio_streaming_interface_descriptor_general *)asdescr->extra;
349 if (extra->hdr.bLength != 7 || extra->hdr.bDescriptorType != 36 || extra->hdr.bDescriptorSubtype != 1)
351 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);
352 return FALSE;
354 if (extra->wFormatTagLo != 1 || extra->wFormatTagHi != 0)
356 g_warning("The AudioStreaming descriptor does not describe a PCM device");
357 return FALSE;
359 const struct usbaudio_streaming_interface_descriptor_format_type_pcm *fmt = (struct usbaudio_streaming_interface_descriptor_format_type_pcm *)(asdescr->extra + extra->hdr.bLength);
360 if (fmt->hdr.bLength != 14 || fmt->hdr.bDescriptorType != 36 || fmt->hdr.bDescriptorSubtype != 2)
362 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);
363 return FALSE;
366 // We need this to tell inputs from outputs - until I implement reasonable
367 // Audio Control support
368 const struct libusb_endpoint_descriptor *ep = get_audio_output_endpoint(asdescr);
369 if (ep)
371 if (fmt->bBitResolution != uii->output_resolution * 8)
373 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);
374 return FALSE;
376 if (fmt->bSamFreqType)
378 gboolean found = FALSE;
379 for (int i = 0; i < fmt->bSamFreqType; i++)
381 int sf = fmt->taSamFreq[i][0] + 256 * fmt->taSamFreq[i][1] + 65536 * fmt->taSamFreq[i][2];
382 if (sf == uii->sample_rate)
384 found = TRUE;
385 break;
388 if (!found)
390 g_warning("Interface %d alternate setting %d does not support sample rate of %d Hz", asdescr->bInterfaceNumber, asdescr->bAlternateSetting, uii->sample_rate);
391 for (int i = 0; i < fmt->bSamFreqType; i++)
393 int sf = fmt->taSamFreq[i][0] + 256 * fmt->taSamFreq[i][1] + 65536 * fmt->taSamFreq[i][2];
394 g_warning("Sample rate[%d] = %d Hz", i, sf);
396 return FALSE;
399 // XXXKF in case of continuous sample rate, check the limits... assuming
400 // that there are any devices with continuous sample rate, that is.
401 if (other_config)
402 return TRUE;
403 if (uai->epdesc.found)
404 return FALSE;
405 g_warning("Interface %d alt-setting %d endpoint %02x looks promising", asdescr->bInterfaceNumber, asdescr->bAlternateSetting, ep->bEndpointAddress);
406 uai->intf = asdescr->bInterfaceNumber;
407 uai->alt_setting = asdescr->bAlternateSetting;
408 fill_endpoint_desc(&uai->epdesc, ep);
409 return TRUE;
411 return FALSE;
414 static gboolean parse_midi_class(struct cbox_usb_midi_info *umi, const struct libusb_interface_descriptor *asdescr, gboolean other_config, gboolean is_output)
416 const struct libusb_endpoint_descriptor *ep = get_midi_endpoint(asdescr, is_output);
417 if (!ep)
418 return FALSE;
420 if (other_config)
421 return TRUE;
423 struct usbio_endpoint_descriptor *epd = is_output ? &umi->epdesc_out : &umi->epdesc_in;
425 if (epd->found)
426 return FALSE;
427 umi->intf = asdescr->bInterfaceNumber;
428 umi->alt_setting = asdescr->bAlternateSetting;
429 fill_endpoint_desc(epd, ep);
430 return TRUE;
433 static gboolean inspect_device(struct cbox_usb_io_impl *uii, struct libusb_device *dev, uint16_t busdevadr, gboolean probe_only)
435 struct libusb_device_descriptor dev_descr;
436 int bus = busdevadr >> 8;
437 int devadr = busdevadr & 255;
439 if (0 != libusb_get_device_descriptor(dev, &dev_descr))
441 g_warning("USB device %03d:%03d - cannot get device descriptor (will retry)", bus, devadr);
442 return FALSE;
445 struct cbox_usb_device_info *udi = g_hash_table_lookup(uii->device_table, GINT_TO_POINTER(busdevadr));
446 if (!udi)
448 struct libusb_config_descriptor *cfg_descr = NULL;
449 if (0 != libusb_get_active_config_descriptor(dev, &cfg_descr))
450 return FALSE;
451 udi = malloc(sizeof(struct cbox_usb_device_info));
452 udi->dev = dev;
453 udi->handle = NULL;
454 udi->status = CBOX_DEVICE_STATUS_PROBING;
455 udi->active_config = cfg_descr->bConfigurationValue;
456 udi->bus = bus;
457 udi->devadr = devadr;
458 udi->busdevadr = busdevadr;
459 udi->vid = dev_descr.idVendor;
460 udi->pid = dev_descr.idProduct;
461 udi->configs_with_midi = 0;
462 udi->configs_with_audio = 0;
463 udi->is_midi = FALSE;
464 udi->is_audio = FALSE;
465 udi->last_probe_time = time(NULL);
466 udi->failures = 0;
467 g_hash_table_insert(uii->device_table, GINT_TO_POINTER(busdevadr), udi);
468 libusb_free_config_descriptor(cfg_descr);
470 else
471 if (udi->vid == dev_descr.idVendor && udi->pid == dev_descr.idProduct)
473 // device already open or determined to be
474 if (udi->status == CBOX_DEVICE_STATUS_OPENED ||
475 udi->status == CBOX_DEVICE_STATUS_UNSUPPORTED)
476 return FALSE;
477 // give up after 10 attempts to query or open the device
478 if (udi->failures > 10)
479 return FALSE;
480 // only do ~1 attempt per second
481 if (probe_only && time(NULL) == udi->last_probe_time)
482 return FALSE;
483 udi->last_probe_time = time(NULL);
486 struct cbox_usb_audio_info uainf;
487 cbox_usb_audio_info_init(&uainf, udi);
489 struct cbox_usb_midi_info uminf;
490 cbox_usb_midi_info_init(&uminf, udi);
492 gboolean is_audio = FALSE;
494 // printf("%03d:%03d Device %04X:%04X\n", bus, devadr, dev_descr.idVendor, dev_descr.idProduct);
495 for (int ci = 0; ci < (int)dev_descr.bNumConfigurations; ci++)
497 struct libusb_config_descriptor *cfg_descr = NULL;
498 // if this is not the current config, and another config with MIDI input
499 // has already been found, do not look any further
500 if (0 != libusb_get_config_descriptor(dev, ci, &cfg_descr))
502 udi->failures++;
503 g_warning("%03d:%03d - cannot get configuration descriptor (try %d)", bus, devadr, udi->failures);
504 return FALSE;
507 int cur_config = cfg_descr->bConfigurationValue;
508 gboolean other_config = cur_config != udi->active_config;
509 uint32_t config_mask = 0;
510 // XXXKF not sure about legal range for bConfigurationValue
511 if(cfg_descr->bConfigurationValue >= 0 && cfg_descr->bConfigurationValue < 32)
512 config_mask = 1 << cfg_descr->bConfigurationValue;
513 else
514 g_warning("Unexpected configuration value %d", cfg_descr->bConfigurationValue);
516 for (int ii = 0; ii < cfg_descr->bNumInterfaces; ii++)
518 const struct libusb_interface *idescr = &cfg_descr->interface[ii];
519 for (int as = 0; as < idescr->num_altsetting; as++)
521 const struct libusb_interface_descriptor *asdescr = &idescr->altsetting[as];
522 if (asdescr->bInterfaceClass == LIBUSB_CLASS_AUDIO && asdescr->bInterfaceSubClass == 1) // Audio control
524 if (parse_audio_control_class(&uainf, asdescr, other_config) && other_config)
525 udi->configs_with_audio |= config_mask;
527 else if (asdescr->bInterfaceClass == LIBUSB_CLASS_AUDIO && asdescr->bInterfaceSubClass == 2) // Audio streaming
529 if (parse_audio_class(uii, &uainf, asdescr, other_config) && other_config)
530 udi->configs_with_audio |= config_mask;
532 else if (asdescr->bInterfaceClass == LIBUSB_CLASS_AUDIO && asdescr->bInterfaceSubClass == 3) // MIDI streaming
534 if (parse_midi_class(&uminf, asdescr, other_config, FALSE) && other_config)
535 udi->configs_with_midi |= config_mask;
536 if (parse_midi_class(&uminf, asdescr, other_config, TRUE) && other_config)
537 udi->configs_with_midi |= config_mask;
538 uminf.protocol = USBMIDI_PROTOCOL_CLASS;
540 else if (udi->vid == 0x09e8 && udi->pid == 0x0062) // Akai MPD16
542 uminf.intf = asdescr->bInterfaceNumber;
543 uminf.alt_setting = asdescr->bAlternateSetting;
544 uminf.protocol = USBMIDI_PROTOCOL_MPD16;
545 fill_endpoint_by_address(asdescr, 0x82, &uminf.epdesc_in);
547 else if (udi->vid == 0x1235 && udi->pid == 0x000a) // Novation Nocturn
549 uminf.intf = asdescr->bInterfaceNumber;
550 uminf.alt_setting = asdescr->bAlternateSetting;
551 fill_endpoint_by_address(asdescr, 0x81, &uminf.epdesc_in);
552 fill_endpoint_by_address(asdescr, 0x02, &uminf.epdesc_out);
553 uminf.epdesc_in.interrupt = TRUE;
554 uminf.epdesc_out.interrupt = TRUE;
555 uminf.protocol = USBMIDI_PROTOCOL_NOCTURN;
559 libusb_free_config_descriptor(cfg_descr);
561 if (!uminf.epdesc_in.found && !uminf.epdesc_out.found && udi->configs_with_midi)
562 g_warning("%03d:%03d - MIDI port available on different configs: mask=0x%x", bus, devadr, udi->configs_with_midi);
564 if (uainf.epdesc.found) // Class-compliant USB audio device
565 is_audio = TRUE;
566 if (udi->vid == 0x13b2 && udi->pid == 0x0030) // Alesis Multimix 8
567 is_audio = TRUE;
569 // All configs/interfaces/alts scanned, nothing interesting found -> mark as unsupported
570 udi->is_midi = uminf.epdesc_in.found || uminf.epdesc_out.found;
571 udi->is_audio = is_audio;
572 if (!udi->is_midi && !udi->is_audio)
574 udi->status = CBOX_DEVICE_STATUS_UNSUPPORTED;
575 return FALSE;
578 gboolean opened = FALSE;
579 struct libusb_device_handle *handle = NULL;
580 int err = libusb_open(dev, &handle);
581 if (0 != err)
583 g_warning("Cannot open device %03d:%03d: %s; errno = %s", bus, devadr, libusb_error_name(err), strerror(errno));
584 udi->failures++;
585 return FALSE;
588 if (probe_only)
590 libusb_close(handle);
591 // Make sure that the reconnection code doesn't bail out due to
592 // last_probe_time == now.
593 udi->last_probe_time = 0;
594 return udi->is_midi || udi->is_audio;
597 if (uminf.epdesc_in.found || uminf.epdesc_out.found)
599 g_debug("Found MIDI device %03d:%03d, trying to open", bus, devadr);
600 if (0 != usbio_open_midi_interface(uii, &uminf, handle))
601 opened = TRUE;
603 if (uainf.epdesc.found)
605 GError *error = NULL;
606 if (usbio_open_audio_interface(uii, &uainf, handle, &error))
608 // should have already been marked as opened by the MIDI code, but
609 // I might add the ability to disable some MIDI interfaces at some point
610 udi->status = CBOX_DEVICE_STATUS_OPENED;
611 opened = TRUE;
613 else
615 g_warning("Cannot open class-compliant USB audio output: %s", error->message);
616 g_error_free(error);
619 else if (udi->vid == 0x13b2 && udi->pid == 0x0030)
621 GError *error = NULL;
622 if (usbio_open_audio_interface_multimix(uii, bus, devadr, handle, &error))
624 // should have already been marked as opened by the MIDI code, but
625 // I might add the ability to disable some MIDI interfaces at some point
626 udi->status = CBOX_DEVICE_STATUS_OPENED;
627 opened = TRUE;
629 else
631 g_warning("Cannot open Alesis Multimix audio output: %s", error->message);
632 g_error_free(error);
636 if (!opened)
638 udi->failures++;
639 libusb_close(handle);
641 else
642 udi->handle = handle;
644 return opened;
647 gboolean usbio_scan_devices(struct cbox_usb_io_impl *uii, gboolean probe_only)
649 struct libusb_device **dev_list;
650 size_t i, num_devices;
651 gboolean added = FALSE;
652 gboolean removed = FALSE;
654 num_devices = libusb_get_device_list(probe_only ? uii->usbctx_probe : uii->usbctx, &dev_list);
656 uint16_t *busdevadrs = malloc(sizeof(uint16_t) * num_devices);
657 for (i = 0; i < num_devices; i++)
659 struct libusb_device *dev = dev_list[i];
660 int bus = libusb_get_bus_number(dev);
661 int devadr = libusb_get_device_address(dev);
662 busdevadrs[i] = (bus << 8) | devadr;
665 GList *prev_keys = g_hash_table_get_values(uii->device_table);
666 for (GList *p = prev_keys; p; p = p->next)
668 gboolean found = FALSE;
669 struct cbox_usb_device_info *udi = p->data;
670 for (i = 0; !found && i < num_devices; i++)
671 found = busdevadrs[i] == udi->busdevadr;
672 if (!found)
674 // Only specifically trigger removal if the device is ours
675 if (udi->status == CBOX_DEVICE_STATUS_OPENED)
677 g_message("Disconnected: %03d:%03d (%s)", udi->bus, udi->devadr, probe_only ? "probe" : "reconfigure");
678 removed = TRUE;
680 if (!probe_only)
681 usbio_forget_device(uii, udi);
684 g_list_free(prev_keys);
686 for (i = 0; i < num_devices; i++)
687 added = inspect_device(uii, dev_list[i], busdevadrs[i], probe_only) || added;
689 free(busdevadrs);
690 libusb_free_device_list(dev_list, 0);
691 return added || removed;
694 void usbio_forget_device(struct cbox_usb_io_impl *uii, struct cbox_usb_device_info *devinfo)
696 g_hash_table_remove(uii->device_table, GINT_TO_POINTER(devinfo->busdevadr));
697 for (GList *p = uii->midi_ports, *pNext = NULL; p; p = pNext)
699 pNext = p->next;
700 struct cbox_usb_midi_interface *umi = p->data;
701 if (umi->busdevadr == devinfo->busdevadr)
703 uii->midi_ports = g_list_delete_link(uii->midi_ports, p);
704 free(umi);
707 if (uii->handle_audiodev == devinfo->handle)
708 uii->handle_audiodev = NULL;
709 libusb_close(devinfo->handle);
710 free(devinfo);