~ubuntu-branches/ubuntu/trusty/argyll/trusty-proposed

« back to all changes in this revision

Viewing changes to spectro/usbio_ox.c

  • Committer: Package Import Robot
  • Author(s): Artur Rona
  • Date: 2014-02-12 00:35:39 UTC
  • mfrom: (13.1.24 sid)
  • Revision ID: package-import@ubuntu.com-20140212003539-24tautzlitsiz61w
Tags: 1.5.1-5ubuntu1
* Merge from Debian unstable. (LP: #1275572) Remaining changes:
  - debian/control:
    + Build-depend on libtiff-dev rather than libtiff4-dev.
  - debian/control, debian/patches/06_fix_udev_rule.patch:
    + Fix udev rules to actually work; ENV{ACL_MANAGE} has
      stopped working ages ago, and with logind it's now the
      "uaccess" tag. Dropping also consolekit from Recommends.
  - debian/patches/drop-usb-db.patch:
    + Use hwdb builtin, instead of the obsolete usb-db
      in the udev rules.
* debian/patches/05_ftbfs-underlinkage.diff:
  - Dropped change, no needed anymore.
* Refresh the patches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* General USB I/O support, OS X native implementation. */
 
3
/* This file is conditionaly #included into usbio.c */
 
4
 
 
5
/* 
 
6
 * Argyll Color Correction System
 
7
 *
 
8
 * Author: Graeme W. Gill
 
9
 * Date:   2006/22/4
 
10
 *
 
11
 * Copyright 2006 - 2013 Graeme W. Gill
 
12
 * All rights reserved.
 
13
 *
 
14
 * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
 
15
 * see the License2.txt file for licencing details.
 
16
 */
 
17
 
 
18
#include <sys/time.h>
 
19
 
 
20
#include <CoreFoundation/CoreFoundation.h>
 
21
#include <IOKit/IOTypes.h>
 
22
#include <IOKit/IOKitLib.h>
 
23
#include <IOKit/usb/IOUSBLib.h>
 
24
#include <IOKit/IOCFPlugIn.h>
 
25
//#include <IOKit/IOCFBundle.h>
 
26
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
 
27
# include <objc/objc-auto.h>
 
28
#endif
 
29
 
 
30
/* Add paths to USB connected instruments */
 
31
/* Return an icom error */
 
32
int usb_get_paths(
 
33
icompaths *p 
 
34
) {
 
35
    kern_return_t kstat; 
 
36
    CFMutableDictionaryRef sdict;               /* USB Device  dictionary */
 
37
        io_iterator_t mit;                                      /* Matching itterator */
 
38
        int vid, pid;
 
39
        struct usb_idevice *usbd = NULL;
 
40
 
 
41
        a1logd(p->log, 6, "usb_get_paths: about to look through devices:\n");
 
42
 
 
43
        /* Get dictionary of USB devices */
 
44
        if ((sdict = IOServiceMatching(kIOUSBDeviceClassName)) == NULL) {
 
45
                a1loge(p->log, ICOM_SYS, "usb_get_paths() IOServiceMatching returned a NULL dictionary\n");
 
46
                return ICOM_SYS;
 
47
        }
 
48
 
 
49
        /* Init itterator to find matching types. Consumes sdict reference */
 
50
        if ((kstat = IOServiceGetMatchingServices(kIOMasterPortDefault, sdict, &mit))
 
51
                                                                          != KERN_SUCCESS) { 
 
52
                a1loge(p->log, ICOM_SYS, "usb_get_paths() IOServiceGetMatchingServices returned %d\n", kstat);
 
53
                return ICOM_SYS;
 
54
        }
 
55
 
 
56
        /* Find all the matching USB devices */
 
57
        for (;;) {
 
58
                io_object_t ioob;                                               /* USB object found */
 
59
                io_iterator_t it1;                                              /* Child level 1 */
 
60
            CFMutableDictionaryRef usbprops = 0;        /* USB Device properties */
 
61
                CFNumberRef vref, pref;                                 /* USB Vendor and Product ID propeties */
 
62
                CFNumberRef nconfref;                                   /* No configurations */
 
63
                CFNumberRef nepref, lidpref;                    /* No ep's, Location ID properties */
 
64
                unsigned int vid = 0, pid = 0, nep, tnep, nconfig = 0, lid = 0;
 
65
                instType itype;
 
66
 
 
67
            if ((ioob = IOIteratorNext(mit)) == 0)
 
68
                        break;
 
69
 
 
70
                /* Get the two properies we need. */
 
71
                if ((vref = IORegistryEntryCreateCFProperty(ioob, CFSTR(kUSBVendorID),
 
72
                                                         kCFAllocatorDefault,kNilOptions)) != 0) {
 
73
                        CFNumberGetValue(vref, kCFNumberIntType, &vid);
 
74
                    CFRelease(vref);
 
75
                }
 
76
                if ((pref = IORegistryEntryCreateCFProperty(ioob, CFSTR(kUSBProductID),
 
77
                                                         kCFAllocatorDefault,kNilOptions)) != 0) {
 
78
                        CFNumberGetValue(pref, kCFNumberIntType, &pid);
 
79
                    CFRelease(pref);
 
80
                }
 
81
 
 
82
                if ((nconfref = IORegistryEntryCreateCFProperty(ioob, CFSTR("bNumConfigurations"),
 
83
                                                         kCFAllocatorDefault,kNilOptions)) != 0) {
 
84
                        CFNumberGetValue(nconfref, kCFNumberIntType, &nconfig);
 
85
                    CFRelease(nconfref);
 
86
                }
 
87
 
 
88
                if ((lidpref = IORegistryEntryCreateCFProperty(ioob, CFSTR("locationID"),
 
89
                                                         kCFAllocatorDefault,kNilOptions)) != 0) {
 
90
                        CFNumberGetValue(lidpref, kCFNumberIntType, &lid);
 
91
                    CFRelease(lidpref);
 
92
                }
 
93
 
 
94
                a1logd(p->log, 6, "usb_check_and_add: checking vid 0x%04x, pid 0x%04x, lid 0x%x\n",vid,pid,lid);
 
95
 
 
96
                /* Do a preliminary match */
 
97
                if ((itype = inst_usb_match(vid, pid, 0)) == instUnknown) {
 
98
                        a1logd(p->log, 6 , "usb_check_and_add: 0x%04x 0x%04x not reconized\n",vid,pid);
 
99
                    IOObjectRelease(ioob);              /* Release found object */
 
100
                        continue;
 
101
                }
 
102
 
 
103
                /* Allocate an idevice so that we can fill in the end point information */
 
104
                if ((usbd = (struct usb_idevice *) calloc(sizeof(struct usb_idevice), 1)) == NULL) {
 
105
                        a1loge(p->log, ICOM_SYS, "icoms: calloc failed!\n");
 
106
                        return ICOM_SYS;
 
107
                }
 
108
 
 
109
                usbd->nconfig = nconfig;
 
110
                usbd->config = 1;                               /* We are only interested in config 1 */
 
111
 
 
112
                /* Go through all the Interfaces, adding up the number of end points */
 
113
                tnep = 0;
 
114
                if ((kstat = IORegistryEntryCreateIterator(ioob, kIOServicePlane,
 
115
                                          kIORegistryIterateRecursively, &it1)) != KERN_SUCCESS) {
 
116
                        IOObjectRelease(ioob);
 
117
                        IOObjectRelease(mit);
 
118
                        a1loge(p->log, kstat, "usb_check_and_add: IORegistryEntryCreateIterator() with %d\n",kstat);
 
119
                    return ICOM_SYS;
 
120
                }
 
121
                usbd->nifce = 0;
 
122
                for (;;) {
 
123
                        io_object_t ch1;                                        /* Child object 1 */
 
124
                    if ((ch1 = IOIteratorNext(it1)) == 0)
 
125
                                break;
 
126
                        if (IOObjectConformsTo(ch1, "IOUSBInterface")) {
 
127
                                unsigned int config = 0;
 
128
                                
 
129
                                /* Get the configuration number */
 
130
                                if ((nconfref = IORegistryEntryCreateCFProperty(ch1, CFSTR(kUSBNumEndpoints),
 
131
                                                                         kCFAllocatorDefault,kNilOptions)) != 0) {
 
132
                                        CFNumberGetValue(nconfref, kCFNumberIntType, &config);
 
133
                                    CFRelease(nconfref);
 
134
                                }
 
135
 
 
136
                                if (config != 1)
 
137
                                        continue;
 
138
 
 
139
                                usbd->nifce++;
 
140
 
 
141
                                /* Get the number of end points */
 
142
                                if ((nepref = IORegistryEntryCreateCFProperty(ch1, CFSTR(kUSBNumEndpoints),
 
143
                                                                         kCFAllocatorDefault,kNilOptions)) != 0) {
 
144
                                        CFNumberGetValue(nepref, kCFNumberIntType, &nep);
 
145
                                    CFRelease(nepref);
 
146
                                        tnep += nep;
 
147
                                }
 
148
                            IOObjectRelease(ch1);
 
149
                        }
 
150
                }
 
151
                IOObjectRelease(it1);
 
152
 
 
153
                if ((itype = inst_usb_match(vid, pid, tnep)) != instUnknown) {
 
154
                        int i;
 
155
                        char pname[400];
 
156
                        int rv;
 
157
 
 
158
                        /* If this device is HID, it will have already added to the paths list, */
 
159
                        /* so check for this and skip this device if it is already there. */
 
160
                        for (i = 0; i < p->npaths; i++) {
 
161
                                if (p->paths[i]->vid == vid
 
162
                                 && p->paths[i]->pid == pid
 
163
                                 && p->paths[i]->hidd != NULL
 
164
                                 && p->paths[i]->hidd->lid == lid) {
 
165
                                        a1logd(p->log, 1, "usb_check_and_add: Ignoring device because it is already in list as HID\n");
 
166
                                        break;
 
167
                                }
 
168
                        }
 
169
                        if (i < p->npaths) {
 
170
                            IOObjectRelease(ioob);              /* Release found object */
 
171
                                free(usbd);
 
172
 
 
173
                        } else {
 
174
                        
 
175
                                a1logd(p->log, 1, "usb_check_and_add: found instrument vid 0x%04x, pid 0x%04x\n",vid,pid);
 
176
                                usbd->lid = lid;
 
177
                                usbd->ioob = ioob;
 
178
 
 
179
                                /* Create a path/identification */
 
180
                                sprintf(pname,"usb%d: (%s)", lid >> 20, inst_name(itype));
 
181
 
 
182
                                /* Add the path and ep info to the list */
 
183
                                if ((rv = p->add_usb(p, pname, vid, pid, tnep, usbd, itype)) != ICOM_OK) {
 
184
                                    IOObjectRelease(ioob);              /* Release found object */
 
185
                                        free(usbd);
 
186
                                    IOObjectRelease(mit);               /* Release the itterator */
 
187
                                        return rv;
 
188
                                }
 
189
                        }
 
190
                } else {
 
191
                    IOObjectRelease(ioob);              /* Release found object */
 
192
                        free(usbd);
 
193
                }
 
194
        }
 
195
    IOObjectRelease(mit);                       /* Release the itterator */
 
196
 
 
197
        a1logd(p->log, 8, "usb_get_paths: returning %d paths and ICOM_OK\n",p->npaths);
 
198
        return ICOM_OK;
 
199
}
 
200
 
 
201
/* Copy usb_idevice contents from icompaths to icom */
 
202
/* return icom error */
 
203
int usb_copy_usb_idevice(icoms *d, icompath *s) {
 
204
        int i;
 
205
        if (s->usbd == NULL) { 
 
206
                d->usbd = NULL;
 
207
                return ICOM_OK;
 
208
        }
 
209
        if ((d->usbd = calloc(sizeof(struct usb_idevice), 1)) == NULL) {
 
210
                a1loge(d->log, ICOM_SYS, "usb_copy_usb_idevice: malloc\n");
 
211
                return ICOM_SYS;
 
212
        }
 
213
        d->nconfig = s->usbd->nconfig;
 
214
        d->config = s->usbd->config;
 
215
        d->nifce = s->usbd->nifce;
 
216
        d->usbd->ioob = s->usbd->ioob;
 
217
        IOObjectRetain(d->usbd->ioob);
 
218
        return ICOM_OK;
 
219
}
 
220
 
 
221
/* Cleanup and then free a usb dev entry */
 
222
void usb_del_usb_idevice(struct usb_idevice *usbd) {
 
223
 
 
224
        if (usbd == NULL)
 
225
                return;
 
226
 
 
227
        if (usbd->ioob != 0)
 
228
                IOObjectRelease(usbd->ioob);
 
229
 
 
230
        free(usbd);
 
231
}
 
232
 
 
233
/* Cleanup any USB specific icoms state */
 
234
void usb_del_usb(icoms *p) {
 
235
 
 
236
        usb_del_usb_idevice(p->usbd);
 
237
}
 
238
 
 
239
/* Clean up anything allocated/created in p->usbd, but don't free p->usbd itself */
 
240
static void cleanup_device(icoms *p) {
 
241
                
 
242
        if (p->usbd != NULL) {
 
243
                if (p->usbd->device != NULL) {  /* device is open */
 
244
                        int i;
 
245
 
 
246
                        /* Stop the RunLoop and wait for it */
 
247
                        if (p->usbd->cfrunloop != NULL) {
 
248
 
 
249
                                a1logd(p->log, 6, "usb_close_port: waiting for RunLoop thread to exit\n");
 
250
                                CFRunLoopStop(p->usbd->cfrunloop);
 
251
                                CFRelease(p->usbd->cfrunloop);
 
252
                                if (p->usbd->thread != NULL)
 
253
                                        pthread_join(p->usbd->thread, NULL);
 
254
                        }
 
255
 
 
256
                        /* Release all the interfaces */
 
257
                        for (i = 0; i < p->usbd->nifce; i++) {
 
258
                                if (p->usbd->interfaces[i] != NULL) {
 
259
                                        (*p->usbd->interfaces[i])->USBInterfaceClose(p->usbd->interfaces[i]);
 
260
                                        (*p->usbd->interfaces[i])->Release(p->usbd->interfaces[i]);
 
261
                                }
 
262
                        }
 
263
 
 
264
                        /* Close the device */
 
265
                        (*(p->usbd->device))->USBDeviceClose(p->usbd->device);
 
266
                        (*(p->usbd->device))->Release(p->usbd->device);
 
267
                }
 
268
                pthread_cond_destroy(&p->usbd->cond);
 
269
                pthread_mutex_destroy(&p->usbd->lock);
 
270
 
 
271
                memset(p->usbd, 0, sizeof(struct usb_idevice));
 
272
        }
 
273
}
 
274
 
 
275
/* Close an open USB port */
 
276
/* If we don't do this, the port and/or the device may be left in an unusable state. */
 
277
void usb_close_port(icoms *p) {
 
278
 
 
279
        a1logd(p->log, 6, "usb_close_port: called\n");
 
280
 
 
281
        if (p->is_open && p->usbd != NULL) {
 
282
 
 
283
                /* Workaround for some bugs - reset device on close */
 
284
                if (p->uflags & icomuf_reset_before_close) {
 
285
                        IOReturn rv;
 
286
                        if ((rv = (*(p->usbd->device))->ResetDevice(p->usbd->device)) != kIOReturnSuccess) {
 
287
                                a1logd(p->log, 1, "usb_close_port: ResetDevice failed with 0x%x\n",rv);
 
288
                        }
 
289
                }
 
290
 
 
291
                /* Close down and free everything in p->usbd */
 
292
                cleanup_device(p);
 
293
                if (p->usbd != NULL) {
 
294
                        free(p->usbd);
 
295
                        p->usbd = NULL;
 
296
                }
 
297
                a1logd(p->log, 6, "usb_close_port: usb port has been released and closed\n");
 
298
        }
 
299
        p->is_open = 0;
 
300
 
 
301
        /* Find it and delete it from our static cleanup list */
 
302
        usb_delete_from_cleanup_list(p);
 
303
}
 
304
 
 
305
static int icoms_usb_control_msg(icoms *p, int *transferred, int requesttype, int request,
 
306
                       int value, int index, unsigned char *bytes, int size, int timeout);
 
307
static void *io_runloop(void *context);
 
308
 
 
309
/* Open a USB port for all our uses. */
 
310
/* This always re-opens the port */
 
311
/* return icom error */
 
312
static int usb_open_port(
 
313
icoms *p,
 
314
int    config,          /* Configuration number, (1 based) */
 
315
int    wr_ep,           /* Write end point */
 
316
int    rd_ep,           /* Read end point */
 
317
icomuflags usbflags,/* Any special handling flags */
 
318
int retries,            /* > 0 if we should retry set_configuration (100msec) */ 
 
319
char **pnames           /* List of process names to try and kill before opening */
 
320
) {
 
321
        IOReturn rv;
 
322
        int tries = 0;
 
323
        a1logd(p->log, 8, "usb_open_port: Make sure USB port is open, tries %d\n",retries);
 
324
 
 
325
        if (p->is_open)
 
326
                p->close_port(p);
 
327
 
 
328
        /* Make sure the port is open */
 
329
        if (!p->is_open) {
 
330
                kkill_nproc_ctx *kpc = NULL;
 
331
 
 
332
                if (config != 1) {
 
333
                        /* Nothing currently needs it, so we haven't implemented it yet... */
 
334
                        a1loge(p->log, ICOM_NOTS, "usb_open_port: native driver cant handle config %d\n",config);
 
335
                        return ICOM_NOTS;
 
336
                }
 
337
 
 
338
                pthread_mutex_init(&p->usbd->lock, NULL);
 
339
                pthread_cond_init(&p->usbd->cond, NULL);
 
340
 
 
341
                /* Do open retries */
 
342
                for (tries = 0; retries >= 0; retries--, tries++) {
 
343
                        IOCFPlugInInterface **piif = NULL;
 
344
                        SInt32 score;
 
345
 
 
346
                        a1logd(p->log, 8, "usb_open_port: About to open USB port '%s'\n",p->name);
 
347
 
 
348
                        if (tries > 0) {
 
349
                                //msec_sleep(i_rand(50,100));
 
350
                                msec_sleep(77);
 
351
                        }
 
352
                        if (tries > 0 && pnames != NULL && kpc == NULL) {
 
353
                                if ((kpc = kkill_nprocess(pnames, p->log)) == NULL) {
 
354
                                        a1logd(p->log, 1, "kkill_nprocess returned error!\n");
 
355
                                }
 
356
                        }
 
357
 
 
358
                        if ((rv = IOCreatePlugInInterfaceForService(p->usbd->ioob,
 
359
                                               kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
 
360
                                               &piif, &score)) != kIOReturnSuccess || piif == NULL) {
 
361
                                a1loge(p->log, rv, "usb_open_port: Failed to get piif for "
 
362
                                  "USB device '%s', result 0x%x, piif 0x%x\n",p->name,rv,piif);
 
363
                                return ICOM_SYS;
 
364
                        }
 
365
        
 
366
                        p->usbd->device = NULL;
 
367
                        if ((rv = (*piif)->QueryInterface(piif,
 
368
                                    CFUUIDGetUUIDBytes(DeviceInterfaceID), (void *)&p->usbd->device))
 
369
                                != kIOReturnSuccess || p->usbd->device == NULL) {
 
370
                                a1loge(p->log, rv, "usb_open_port: QueryInterface '%s' failed with 0%x\n",p->name, rv);
 
371
                                (*piif)->Release(piif);
 
372
                                return ICOM_SYS;
 
373
                        }
 
374
                        (*piif)->Release(piif);         /* delete intermediate object */
 
375
        
 
376
                        if ((rv = (*p->usbd->device)->USBDeviceOpenSeize(p->usbd->device)) != kIOReturnSuccess) {
 
377
                                a1logd(p->log, 8, "usb_open_port: open '%s' config %d failed (0x%x) (Device being used ?)\n",p->name,config,rv);
 
378
                                if (retries <= 0) {
 
379
                                        if (kpc != NULL)
 
380
                                                kpc->del(kpc); 
 
381
                                        a1loge(p->log, rv, "usb_open_port: open '%s' config %d failed (0x%x) (Device being used ?)\n",p->name, config, rv);
 
382
                                        (*p->usbd->device)->Release(p->usbd->device);
 
383
                                        return ICOM_SYS;
 
384
                                }
 
385
                                continue;
 
386
                        } else if (p->debug)
 
387
                                a1logd(p->log, 1, "usb_open_port: open port '%s' succeeded\n",p->name);
 
388
 
 
389
                        p->uflags = usbflags;
 
390
 
 
391
                        /* We're done retries */
 
392
                        break;
 
393
                }
 
394
 
 
395
                if (kpc != NULL)
 
396
                        kpc->del(kpc); 
 
397
 
 
398
                /* We should only do a set configuration if the device has more than one */
 
399
                /* possible configuration and it is currently not the desired configuration, */
 
400
                /* but we should avoid doing a set configuration if the OS has already */
 
401
                /* selected the configuration we want, since two set configs seem to */
 
402
                /* mess up the Spyder2, BUT we can't do a get config because this */
 
403
                /* messes up the i1pro-D. */
 
404
 
 
405
                /* OS X doesn't do a set_configuration() by default */
 
406
                p->cconfig = 0;
 
407
 
 
408
                if (p->cconfig != config) {
 
409
                        if ((rv = (*(p->usbd->device))->SetConfiguration(
 
410
                                p->usbd->device, config)) != kIOReturnSuccess) {
 
411
                                a1loge(p->log, rv, "usb_open_port: SetConfiguration failed with 0x%x\n",rv);
 
412
                                cleanup_device(p);
 
413
                                return ICOM_SYS;
 
414
                        }
 
415
                        p->cconfig = config;
 
416
                        a1logd(p->log, 6, "usb_open_port: SetConfiguration %d OK\n",config);
 
417
                }
 
418
 
 
419
                /* Get interfaces */
 
420
                {
 
421
                        int i, j;
 
422
                        IOUSBFindInterfaceRequest req;
 
423
                        io_iterator_t ioit;
 
424
                        io_service_t iface;
 
425
                        IOCFPlugInInterface **pluginref = NULL;
 
426
                        SInt32 score;
 
427
 
 
428
                        req.bInterfaceClass    = 
 
429
                        req.bInterfaceSubClass = 
 
430
                        req.bInterfaceProtocol = 
 
431
                        req.bAlternateSetting  = kIOUSBFindInterfaceDontCare;
 
432
 
 
433
                        if ((rv = (*(p->usbd->device))->CreateInterfaceIterator(
 
434
                                             p->usbd->device, &req, &ioit)) != kIOReturnSuccess) {
 
435
                                a1loge(p->log, rv, "usb_open_port: CreateInterfaceIterator failed with 0x%x\n",rv);
 
436
                                cleanup_device(p);
 
437
                                return ICOM_SYS;
 
438
                        }
 
439
                        iface = IOIteratorNext(ioit);
 
440
                        for (i = 0; iface != 0; i++, iface = IOIteratorNext(ioit)) {
 
441
                                u_int8_t nep;
 
442
 
 
443
                                if ((rv = IOCreatePlugInInterfaceForService(iface,
 
444
                                             kIOUSBInterfaceUserClientTypeID,
 
445
                                             kIOCFPlugInInterfaceID,
 
446
                                             &pluginref, &score)) != kIOReturnSuccess) {
 
447
                                        a1loge(p->log, rv, "usb_open_port: IOCreatePlugInInterfaceForService failed with 0x%x\n",rv);
 
448
                                        IOObjectRelease(iface);
 
449
                                        IOObjectRelease(ioit);
 
450
                                        cleanup_device(p);
 
451
                                        return ICOM_SYS;
 
452
                                }
 
453
                                IOObjectRelease(iface);
 
454
                                if ((rv = (*pluginref)->QueryInterface(pluginref,
 
455
                                              CFUUIDGetUUIDBytes(InterfaceInterfaceID),
 
456
                                              (void *)&p->usbd->interfaces[i])) != kIOReturnSuccess) {
 
457
                                        a1loge(p->log, rv, "usb_open_port: QueryInterface failed with 0x%x\n",rv);
 
458
                                        (*pluginref)->Stop(pluginref);
 
459
                                        IODestroyPlugInInterface(pluginref);
 
460
                                        IOObjectRelease(ioit);
 
461
                                        cleanup_device(p);
 
462
                                        return ICOM_SYS;
 
463
                                }
 
464
                                (*pluginref)->Stop(pluginref);
 
465
                                IODestroyPlugInInterface(pluginref);
 
466
 
 
467
                                if ((rv = (*(p->usbd->interfaces[i]))->USBInterfaceOpen(
 
468
                                                   p->usbd->interfaces[i])) != kIOReturnSuccess) {
 
469
                                        a1loge(p->log, rv, "usb_open_port: USBInterfaceOpen failed with 0x%x\n",rv);
 
470
                                        IOObjectRelease(ioit);
 
471
                                        cleanup_device(p);
 
472
                                        return ICOM_SYS;
 
473
                                }
 
474
 
 
475
                                /* Get the end point details, and set reference to pipe no and interfece ix */
 
476
                                if ((rv = (*(p->usbd->interfaces[i]))->GetNumEndpoints(
 
477
                                                   p->usbd->interfaces[i], &nep)) != kIOReturnSuccess) {
 
478
                                        a1loge(p->log, rv, "usb_open_port: GetNumEndpoints failed with 0x%x\n",rv);
 
479
                                        IOObjectRelease(ioit);
 
480
                                        cleanup_device(p);
 
481
                                        return ICOM_SYS;
 
482
                                }
 
483
                                for (j = 0; j < nep; j++) {
 
484
                                        UInt8 direction, pnumber, transferType, interval;
 
485
                                        UInt16 maxPacketSize;
 
486
                                        int ad;
 
487
                                        if ((rv = (*(p->usbd->interfaces[i]))->GetPipeProperties(
 
488
                                                           p->usbd->interfaces[i], (UInt8)(j+1), &direction, &pnumber,
 
489
                                                           &transferType, &maxPacketSize, &interval)) != kIOReturnSuccess) {
 
490
                                                a1loge(p->log, rv, "usb_open_port: GetPipeProperties failed with 0x%x\n",rv);
 
491
                                                IOObjectRelease(ioit);
 
492
                                                cleanup_device(p);
 
493
                                                return ICOM_SYS;
 
494
                                        }
 
495
                                        ad = ((direction << IUSB_ENDPOINT_DIR_SHIFT) & IUSB_ENDPOINT_DIR_MASK)
 
496
                                           | (pnumber & IUSB_ENDPOINT_NUM_MASK);
 
497
                                        p->EPINFO(ad).valid = 1;
 
498
                                        p->EPINFO(ad).addr = ad;
 
499
                                        p->EPINFO(ad).packetsize = maxPacketSize;
 
500
                                        p->EPINFO(ad).type = transferType & IUSB_ENDPOINT_TYPE_MASK;
 
501
                                        p->EPINFO(ad).interface = i;
 
502
                                        p->EPINFO(ad).pipe = j+1;
 
503
                                        a1logd(p->log, 6, "set ep ad 0x%x packetsize %d type %d, if %d, pipe %d\n",ad,maxPacketSize,transferType & IUSB_ENDPOINT_TYPE_MASK,i,j);
 
504
                                }
 
505
                        }
 
506
                        p->usbd->nifce = i;             /* Just in case.. */
 
507
 
 
508
                        IOObjectRelease(ioit);
 
509
                }
 
510
                {
 
511
                        /* Setup the RunLoop thread */
 
512
                        a1logd(p->log, 6, "usb_open_port: Starting RunLoop thread\n");
 
513
                        if ((rv = pthread_create(&p->usbd->thread, NULL, io_runloop, (void*)p)) < 0) {
 
514
                                a1loge(p->log, ICOM_SYS, "usb_open_port: creating RunLoop thread failed with %s\n",rv);
 
515
                                cleanup_device(p);
 
516
                                return ICOM_SYS;
 
517
                        }
 
518
 
 
519
                        /* Wait for the runloop thread to start and create a cfrunloop */
 
520
                        pthread_mutex_lock(&p->usbd->lock);
 
521
                        while (p->usbd->cfrunloop == NULL)
 
522
                                pthread_cond_wait(&p->usbd->cond, &p->usbd->lock);
 
523
                        pthread_mutex_unlock(&p->usbd->lock);
 
524
                        if (p->usbd->thrv != kIOReturnSuccess) {        /* Thread failed */
 
525
                                pthread_join(p->usbd->thread, NULL);
 
526
                                cleanup_device(p);
 
527
                                return ICOM_SYS;
 
528
                        }
 
529
                        CFRetain(p->usbd->cfrunloop);
 
530
                        a1logd(p->log, 6, "usb_open_port: RunLoop thread started\n");
 
531
                }
 
532
 
 
533
                /* Clear any errors */
 
534
                /* (Some I/F seem to hang if we do this, some seem to hang if we don't !) */
 
535
                if (!(p->uflags & icomuf_no_open_clear)) {
 
536
                        int i;
 
537
                        for (i = 0; i < 32; i++) {
 
538
                                if (!p->ep[i].valid)
 
539
                                        continue;
 
540
                                p->usb_clearhalt(p, p->ep[i].addr); 
 
541
                        }
 
542
                }
 
543
 
 
544
                /* Set "serial" coms values */
 
545
                p->wr_ep = wr_ep;
 
546
                p->rd_ep = rd_ep;
 
547
                p->rd_qa = p->EPINFO(rd_ep).packetsize;
 
548
                if (p->rd_qa == 0)
 
549
                        p->rd_qa = 8;
 
550
                a1logd(p->log, 8, "usb_open_port: 'serial' read quanta = packet size = %d\n",p->rd_qa);
 
551
 
 
552
                p->is_open = 1;
 
553
                a1logd(p->log, 8, "usb_open_port: USB port is now open\n");
 
554
        }
 
555
 
 
556
        /* Install the cleanup signal handlers, and add to our cleanup list */
 
557
        usb_install_signal_handlers(p);
 
558
 
 
559
        return ICOM_OK;
 
560
}
 
561
 
 
562
/*  -------------------------------------------------------------- */
 
563
 
 
564
/* The run loop thread */
 
565
static void *io_runloop(void *context) {
 
566
        icoms *p = (icoms *)context;
 
567
        int i;
 
568
 
 
569
        /* Register this thread with the Objective-C garbage collector */
 
570
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
 
571
         objc_registerThreadWithCollector();
 
572
#endif
 
573
 
 
574
        a1logd(p->log, 6, "io_runloop: thread started\n");
 
575
 
 
576
        p->usbd->cfrunloop = CFRunLoopGetCurrent();             /* Get this threads RunLoop */
 
577
        CFRetain(p->usbd->cfrunloop);
 
578
 
 
579
        /* Add a device event source */
 
580
        if ((p->usbd->thrv = (*(p->usbd->device))->CreateDeviceAsyncEventSource(
 
581
                              p->usbd->device, &p->usbd->cfsource)) != kIOReturnSuccess) {
 
582
                a1loge(p->log, p->usbd->thrv, "io_runloop: CreateDeviceAsyncEventSource failed with 0x%x\n",p->usbd->thrv);
 
583
        } else {
 
584
                CFRunLoopAddSource(p->usbd->cfrunloop, p->usbd->cfsource, kCFRunLoopDefaultMode);
 
585
        }
 
586
 
 
587
        /* Create an async event source for the interfaces */
 
588
        for (i = 0; p->usbd->thrv == kIOReturnSuccess && i < p->usbd->nifce; i++) {
 
589
                if ((p->usbd->thrv = (*(p->usbd->interfaces[i]))->CreateInterfaceAsyncEventSource(
 
590
                             p->usbd->interfaces[i], &p->usbd->cfsources[i])) != kIOReturnSuccess) {
 
591
                        a1loge(p->log, p->usbd->thrv, "io_runloop: CreateInterfaceAsyncEventSource failed with 0x%x\n",p->usbd->thrv);
 
592
                } else {
 
593
                        /* Add it to the RunLoop */
 
594
                        CFRunLoopAddSource(p->usbd->cfrunloop, p->usbd->cfsources[i], kCFRunLoopDefaultMode);
 
595
                }
 
596
        }
 
597
 
 
598
        /* Signal main thread that we've started */
 
599
        pthread_mutex_lock(&p->usbd->lock);
 
600
        pthread_cond_signal(&p->usbd->cond);
 
601
        pthread_mutex_unlock(&p->usbd->lock);
 
602
 
 
603
        /* Run the loop, or exit on error */
 
604
        if (p->usbd->thrv == kIOReturnSuccess) {
 
605
                CFRunLoopRun();         /* Run the loop and deliver events */
 
606
        }
 
607
 
 
608
        /* Delete the interfaces async event sources */
 
609
        for (i = 0; i < p->usbd->nifce; i++) {
 
610
                if (p->usbd->cfsources[i] != NULL) {
 
611
                        CFRunLoopRemoveSource(p->usbd->cfrunloop, p->usbd->cfsources[i], kCFRunLoopDefaultMode);
 
612
                        CFRelease(p->usbd->cfsources[i]);
 
613
                }
 
614
        }
 
615
 
 
616
        /* Delete the devices event sources */
 
617
        if (p->usbd->cfsource != NULL) {
 
618
                CFRunLoopRemoveSource(p->usbd->cfrunloop, p->usbd->cfsource, kCFRunLoopDefaultMode);
 
619
                CFRelease(p->usbd->cfsource);
 
620
        }
 
621
 
 
622
        CFRelease(p->usbd->cfrunloop);
 
623
 
 
624
        a1logd(p->log, 6, "io_runloop: thread done\n");
 
625
        return NULL;
 
626
}
 
627
 
 
628
/* I/O structures */
 
629
 
 
630
typedef struct _usbio_req {
 
631
        icoms *p;
 
632
        int iix;                                        /* Interface index */
 
633
        UInt8 pno;                                      /* pipe index */
 
634
        volatile int done;                      /* Done flag */
 
635
        pthread_mutex_t lock;           /* Protect req & callback access */
 
636
        pthread_cond_t cond;            /* Signal to thread waiting on req */
 
637
        int xlength;                            /* Bytes transferred */
 
638
        IOReturn result;                        /* Result of transaction */
 
639
} usbio_req;
 
640
 
 
641
 
 
642
/* Async completion callback - called by RunLoop thread */
 
643
static void io_callback(void *refcon, IOReturn result, void *arg0) {
 
644
        usbio_req *req = (usbio_req *)refcon;
 
645
 
 
646
        a1logd(req->p->log, 1, "io_callback: result 0x%x, length %d\n",result,(int)(long)arg0);
 
647
 
 
648
        req->xlength = (int)(long)arg0;
 
649
        req->result = result;
 
650
        req->done = 1;
 
651
        pthread_mutex_lock(&req->lock);
 
652
        pthread_cond_signal(&req->cond);
 
653
        pthread_mutex_unlock(&req->lock);
 
654
}
 
655
 
 
656
/* Our universal USB transfer function */
 
657
static int icoms_usb_transaction(
 
658
        icoms *p,
 
659
        usb_cancelt *cancelt,
 
660
        int *transferred,
 
661
        icom_usb_trantype ttype,        /* transfer type */
 
662
        unsigned char endpoint,         /* 0x80 for control write, 0x00 for control read */
 
663
        unsigned char *buffer,
 
664
        int length,
 
665
        unsigned int timeout            /* In msec */
 
666
) {
 
667
        int reqrv = ICOM_OK, rv = 0;
 
668
        int dirw = (endpoint & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT ? 1 : 0;
 
669
        usbio_req req;
 
670
        IOReturn result;
 
671
        int iix = p->EPINFO(endpoint).interface;
 
672
        UInt8 pno = (UInt8)p->EPINFO(endpoint).pipe;
 
673
 
 
674
        in_usb_rw++;
 
675
 
 
676
        a1logd(p->log, 8, "icoms_usb_transaction: req type 0x%x ep 0x%x size %d\n",ttype,endpoint,length);
 
677
 
 
678
        if (ttype != icom_usb_trantype_interrutpt
 
679
         && ttype != icom_usb_trantype_bulk) {
 
680
                /* We only handle interrupt & bulk, not control */
 
681
                return ICOM_SYS;
 
682
        }
 
683
 
 
684
        req.p = p;
 
685
        req.iix = iix;
 
686
        req.pno = pno;
 
687
        req.xlength = 0;
 
688
        req.done = 0;
 
689
        pthread_mutex_init(&req.lock, NULL);
 
690
        pthread_cond_init(&req.cond, NULL);
 
691
 
 
692
        if (dirw)
 
693
                result = (*p->usbd->interfaces[iix])->WritePipeAsync(p->usbd->interfaces[iix], 
 
694
                                                  pno, buffer, length, io_callback, &req); 
 
695
        else
 
696
                result = (*p->usbd->interfaces[iix])->ReadPipeAsync(p->usbd->interfaces[iix], 
 
697
                                                  pno, buffer, length, io_callback, &req); 
 
698
 
 
699
        if (result != kIOReturnSuccess) {
 
700
                a1loge(p->log, ICOM_SYS, "icoms_usb_transaction: %sPipeAsync failed with 0x%x\n",dirw ? "Write" : "Read", result);
 
701
                reqrv = ICOM_SYS;
 
702
                goto done;
 
703
        }
 
704
 
 
705
        if (cancelt != NULL) {
 
706
                usb_lock_cancel(cancelt);
 
707
                cancelt->hcancel = (void *)&req;
 
708
                usb_unlock_cancel(cancelt);
 
709
        }
 
710
                                
 
711
        /* Wait for the callback to complete */
 
712
        pthread_mutex_lock(&req.lock);
 
713
        if (!req.done) {
 
714
                struct timeval tv;
 
715
                struct timespec ts;
 
716
 
 
717
                // this is unduly complicated...
 
718
                gettimeofday(&tv, NULL);
 
719
                ts.tv_sec = tv.tv_sec + timeout/1000;
 
720
                ts.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000L;
 
721
                if (ts.tv_nsec > 1000000000L) {
 
722
                        ts.tv_nsec -= 1000000000L;
 
723
                        ts.tv_sec++;
 
724
                }
 
725
                
 
726
                for(;;) {       /* Ignore spurious wakeups */
 
727
                        if ((rv = pthread_cond_timedwait(&req.cond, &req.lock, &ts)) != 0) {
 
728
                                if (rv != ETIMEDOUT) {
 
729
                                        a1logd(p->log, 1, "coms_usb_transaction: pthread_cond_timedwait failed with %d\n",rv);
 
730
                                        (*p->usbd->interfaces[iix])->AbortPipe(p->usbd->interfaces[iix], pno);
 
731
                                        req.result = kIOReturnAborted;
 
732
                                        reqrv = ICOM_SYS;
 
733
                                        break;
 
734
                                }
 
735
 
 
736
                                /* Timed out */
 
737
                                a1logd(p->log, 8, "coms_usb_transaction: time out - aborting io\n");
 
738
                                (*p->usbd->interfaces[iix])->AbortPipe(p->usbd->interfaces[iix], pno);
 
739
                                reqrv = ICOM_TO;
 
740
                                /* Wait for the cancelled io to be signalled */
 
741
                                if ((rv = pthread_cond_wait(&req.cond, &req.lock)) != 0) {
 
742
                                        pthread_mutex_unlock(&req.lock);
 
743
                                        a1logd(p->log, 1, "coms_usb_transaction:  pthread_cond_wait failed with %d\n",rv);
 
744
                                        req.result = kIOReturnAborted;
 
745
                                        reqrv = ICOM_SYS;
 
746
                                        break;
 
747
                                }
 
748
                                break;
 
749
                        }
 
750
                        if (req.done)   /* Ignore spurious wakeups */
 
751
                                break;
 
752
                }
 
753
        }
 
754
        pthread_mutex_unlock(&req.lock);
 
755
 
 
756
        a1logd(p->log, 8, "coms_usb_transaction: completed with reqrv 0x%x and xlength %d\n",req.result,req.xlength);
 
757
 
 
758
        /* If io was aborted, ClearPipeStall */
 
759
        if (req.result == kIOReturnAborted) {
 
760
#if defined(NEVER) && (InterfaceVersion > 182)
 
761
                (*p->usbd->interfaces[iix])->ClearPipeStallBothEnds(p->usbd->interfaces[iix], pno);
 
762
#else
 
763
                (*p->usbd->interfaces[iix])->ClearPipeStall(p->usbd->interfaces[iix], pno);
 
764
                icoms_usb_control_msg(p, NULL, IUSB_REQ_HOST_TO_DEV | IUSB_REQ_TYPE_STANDARD
 
765
                                       | IUSB_REQ_RECIP_ENDPOINT, IUSB_REQ_CLEAR_FEATURE,
 
766
                                         IUSB_FEATURE_EP_HALT, endpoint, NULL, 0, 200);
 
767
#endif
 
768
                if (reqrv == ICOM_OK)           /* If not aborted for a known reason, must be cancelled */
 
769
                        reqrv = ICOM_CANC;
 
770
        }
 
771
 
 
772
        /* If normal completion - not timed out or aborted */
 
773
        if (reqrv == ICOM_OK) {         /* Completed OK */
 
774
                if (req.result == kIOReturnSuccess) {
 
775
                        if (req.xlength != length)
 
776
                                reqrv = ICOM_SHORT;
 
777
                } else {
 
778
                        if (dirw)
 
779
                                reqrv = ICOM_USBW;
 
780
                        else
 
781
                                reqrv = ICOM_USBR;
 
782
                } 
 
783
        }
 
784
 
 
785
        if (transferred != NULL)
 
786
                *transferred = req.xlength;
 
787
 
 
788
done:;
 
789
        if (cancelt != NULL) {
 
790
                usb_lock_cancel(cancelt);
 
791
                cancelt->hcancel = (void *)NULL;
 
792
                usb_unlock_cancel(cancelt);
 
793
        }
 
794
 
 
795
        pthread_cond_destroy(&req.cond);
 
796
        pthread_mutex_destroy(&req.lock);
 
797
 
 
798
        if (in_usb_rw < 0)
 
799
                exit(0);
 
800
 
 
801
        in_usb_rw--;
 
802
 
 
803
        a1logd(p->log, 8, "coms_usb_transaction: returning err 0x%x and %d bytes\n",reqrv, req.xlength);
 
804
 
 
805
        return reqrv;
 
806
}
 
807
 
 
808
 
 
809
/* Our control message routine */
 
810
/* Return error icom error code */
 
811
static int icoms_usb_control_msg(
 
812
icoms *p,
 
813
int *transferred,
 
814
int requesttype, int request,
 
815
int value, int index, unsigned char *bytes, int size, 
 
816
int timeout) {
 
817
        int reqrv = ICOM_OK;
 
818
        int dirw = (requesttype & IUSB_REQ_DIR_MASK) == IUSB_REQ_HOST_TO_DEV ? 1 : 0;
 
819
        IOReturn rv;
 
820
        IOUSBDevRequestTO req;
 
821
 
 
822
        a1logd(p->log, 8, "icoms_usb_control_msg: type 0x%x req 0x%x size %d\n",requesttype,request,size);
 
823
        bzero(&req, sizeof(req));
 
824
        req.bmRequestType = requesttype;
 
825
        req.bRequest = request;
 
826
        req.wValue = value;
 
827
        req.wIndex = index;
 
828
        req.wLength = size;
 
829
        req.pData = bytes;
 
830
        req.completionTimeout = timeout;
 
831
        req.noDataTimeout = timeout;
 
832
 
 
833
        if (transferred != NULL)
 
834
                *transferred = 0;
 
835
 
 
836
        if ((rv = (*(p->usbd->device))->DeviceRequestTO(p->usbd->device, &req)) != kIOReturnSuccess) {
 
837
                if (rv == kIOUSBTransactionTimeout) {
 
838
                        reqrv = ICOM_TO;
 
839
                } else {
 
840
                        if (dirw)
 
841
                                reqrv = ICOM_USBW;
 
842
                        else
 
843
                                reqrv = ICOM_USBR;
 
844
                }
 
845
        } else {
 
846
                if (transferred != NULL)
 
847
                        *transferred = req.wLenDone;
 
848
        }
 
849
 
 
850
        a1logd(p->log, 8, "icoms_usb_control_msg: returning err 0x%x and %d bytes\n",reqrv, transferred != NULL ? *transferred : -1);
 
851
        return reqrv;
 
852
}
 
853
 
 
854
/*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
855
/* Time out error return value */
 
856
 
 
857
//#define USBIO_ERROR_TIMEOUT   -ETIMEDOUT
 
858
 
 
859
/*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
860
 
 
861
/* Cancel i/o in another thread */
 
862
int icoms_usb_cancel_io(
 
863
        icoms *p,
 
864
        usb_cancelt *cancelt
 
865
) {
 
866
        int reqrv = ICOM_OK;
 
867
 
 
868
        usb_lock_cancel(cancelt);
 
869
        usbio_req *req = (usbio_req *)cancelt->hcancel;
 
870
        if (req != NULL) {
 
871
                IOReturn rv;
 
872
 
 
873
                if ((rv = (*p->usbd->interfaces[req->iix])->AbortPipe(
 
874
                                 p->usbd->interfaces[req->iix], req->pno)) != kIOReturnSuccess) {
 
875
                        reqrv = ICOM_USBW;
 
876
                }
 
877
        }
 
878
        usb_unlock_cancel(cancelt);
 
879
 
 
880
        return reqrv;
 
881
}
 
882
 
 
883
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
 
884
/* Reset and end point data toggle to 0 */
 
885
int icoms_usb_resetep(
 
886
        icoms *p,
 
887
        int ep                                  /* End point address */
 
888
) {
 
889
        int reqrv = ICOM_OK;
 
890
        int iix = p->EPINFO(ep).interface;
 
891
        UInt8 pno = (UInt8)p->EPINFO(ep).pipe;
 
892
        IOReturn rv;
 
893
 
 
894
        if ((rv = (*p->usbd->interfaces[iix])->ResetPipe(
 
895
                         p->usbd->interfaces[iix], pno)) != kIOReturnSuccess) {
 
896
                a1logd(p->log, 1, "icoms_usb_resetep failed with 0x%x\n",rv);
 
897
                reqrv = ICOM_USBW;
 
898
        }
 
899
        return reqrv;
 
900
}
 
901
 
 
902
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
 
903
/* Clear a halt on an end point */
 
904
int icoms_usb_clearhalt(
 
905
        icoms *p,
 
906
        int ep                                  /* End point address */
 
907
) {
 
908
        int reqrv = ICOM_OK;
 
909
        int iix = p->EPINFO(ep).interface;
 
910
        UInt8 pno = (UInt8)p->EPINFO(ep).pipe;
 
911
        IOReturn rv;
 
912
        int irv;
 
913
 
 
914
#if defined(NEVER) && (InterfaceVersion > 182)
 
915
        if ((rv = (*p->usbd->interfaces[iix])->ClearPipeStallBothEnds(
 
916
                         p->usbd->interfaces[iix], pno)) != kIOReturnSuccess) {
 
917
                a1logd(p->log, 1, "icoms_usb_clearhalt failed with 0x%x\n",rv);
 
918
                reqrv = ICOM_USBW;
 
919
        }
 
920
#else
 
921
        if ((rv = (*p->usbd->interfaces[iix])->ClearPipeStall(
 
922
                         p->usbd->interfaces[iix], pno)) != kIOReturnSuccess) {
 
923
                a1logd(p->log, 1, "icoms_usb_clearhalt failed with 0x%x\n",rv);
 
924
                reqrv = ICOM_USBW;
 
925
        }
 
926
        if ((irv = icoms_usb_control_msg(p, NULL, IUSB_REQ_HOST_TO_DEV | IUSB_REQ_TYPE_STANDARD
 
927
                               | IUSB_REQ_RECIP_ENDPOINT, IUSB_REQ_CLEAR_FEATURE,
 
928
                                 IUSB_FEATURE_EP_HALT, ep, NULL, 0, 200)) != ICOM_OK) {
 
929
                a1logd(p->log, 1, "icoms_usb_clearhalt far end failed with 0x%x\n",irv);
 
930
                reqrv = ICOM_USBW;
 
931
        }
 
932
#endif
 
933
        return reqrv;
 
934
}
 
935
 
 
936
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
 
937
 
 
938
#ifdef NEVER
 
939
                {
 
940
                        IOUSBFindInterfaceRequest req;
 
941
                        io_iterator_t ioit;
 
942
 
 
943
                        /* See if we can find any interfaces */
 
944
                        req.bInterfaceClass    = 
 
945
                        req.bInterfaceSubClass = 
 
946
                        req.bInterfaceProtocol = 
 
947
                        req.bAlternateSetting  = kIOUSBFindInterfaceDontCare;
 
948
 
 
949
                        if ((rv = (*(p->usbd->device))->CreateInterfaceIterator(
 
950
                                             p->usbd->device, &req, &ioit)) != kIOReturnSuccess) {
 
951
                                a1loge(p->log, rv, "usb_open_port: CreateInterfaceIterator failed with 0x%x\n",rv);
 
952
                                cleanup_device(p);
 
953
                                return ICOM_SYS;
 
954
                        }
 
955
                    if (IOIteratorNext(ioit) == 0) {    /* Configure the device */
 
956
                                IOUSBConfigurationDescriptorPtr confdesc;
 
957
 
 
958
                                if ((rv = (*(p->usbd->device))->GetConfigurationDescriptorPtr(
 
959
                                                  p->usbd->device, config-1, &confdesc)) != kIOReturnSuccess) {
 
960
                                        a1loge(p->log, rv, "usb_open_port: GetConfigurationDescriptorPtr failed with 0x%x\n",rv);
 
961
                                        IOObjectRelease(ioit);
 
962
                                        cleanup_device(p);
 
963
                                        return ICOM_SYS;
 
964
                                }
 
965
                                if ((rv = (*(p->usbd->device))->SetConfiguration(
 
966
                                        p->usbd->device, confdesc->bConfigurationValue)) != kIOReturnSuccess) {
 
967
                                        a1loge(p->log, rv, "usb_open_port: SetConfiguration failed with 0x%x\n",rv);
 
968
                                        IOObjectRelease(ioit);
 
969
                                        cleanup_device(p);
 
970
                                        return ICOM_SYS;
 
971
                                }
 
972
                                a1logd(p->log, 6, "usb_open_port: SetConfiguration %d OK\n",confdesc->bConfigurationValue);
 
973
 
 
974
                        } else {        /* Some diagnostics */
 
975
                                UInt8 confno;
 
976
                                if ((rv = (*(p->usbd->device))->GetConfiguration(
 
977
                                                  p->usbd->device, &confno)) != kIOReturnSuccess) {
 
978
                                        a1logd(p->log, 6, "usb_open_port: GetConfiguration failed with 0x%x\n",rv);
 
979
                                } else {
 
980
                                        a1logd(p->log, 6, "usb_open_port: Device didn't need configuring - currently %d\n",confno);
 
981
                                }
 
982
                        }
 
983
                        IOObjectRelease(ioit);
 
984
 
 
985
                }
 
986
#endif /* NEVER */