~vibhavp/ubuntu/raring/dahdi-tools/merge-from-debian

« back to all changes in this revision

Viewing changes to xpp/xtalk/xusb.c

  • Committer: Vibhav Pant
  • Date: 2012-12-26 17:23:16 UTC
  • mfrom: (2.1.6 sid)
  • Revision ID: vibhavp@gmail.com-20121226172316-o2jojsfcnr0aqrme
* Merge from Debian unstable. Remaining changes:
  - Bug Fix: If linux-headers are not installed, don't block, and print
    information for the user.
  - added debian/dahdi.postinst
  - added --error-handler=init_failed to debian/rules
  - debian/control: Added gawk as dependency for dkms build (LP: #493304)
  - Changes from Debian:
    - debian/control: Change Maintainer
    - debian/control: Removed Uploaders field.
    - debian/control: Removed Debian Vcs-Svn entry and replaced with
      ubuntu-voip Vcs-Bzr, to reflect divergence in packages.
    - debian/control: Package dahdi Depends on dahdi-dkms | dahdi-source 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Written by Oron Peled <oron@actcom.co.il>
 
3
 * Copyright (C) 2008, Xorcom
 
4
 *
 
5
 * All rights reserved.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
 *
 
21
 */
 
22
 
 
23
#define _GNU_SOURCE     /* for memrchr() */
 
24
#include <stdio.h>
 
25
#include <string.h>
 
26
#include <assert.h>
 
27
#include <errno.h>
 
28
#include <stdarg.h>
 
29
#include <syslog.h>
 
30
#include <arpa/inet.h>
 
31
#include <debug.h>
 
32
#include <xusb.h>
 
33
 
 
34
static const char rcsid[] = "$Id: xusb.c 9825 2011-03-10 18:48:11Z tzafrir $";
 
35
 
 
36
#define DBG_MASK        0x01
 
37
#define TIMEOUT 500
 
38
 
 
39
struct xusb {
 
40
        struct usb_device       *dev;
 
41
        usb_dev_handle          *handle;
 
42
        const struct xusb_spec  *spec;
 
43
        char                    iManufacturer[BUFSIZ];
 
44
        char                    iProduct[BUFSIZ];
 
45
        char                    iSerialNumber[BUFSIZ];
 
46
        char                    iInterface[BUFSIZ];
 
47
        char                    devpath_tail[PATH_MAX + 1];
 
48
        int                     bus_num;
 
49
        int                     device_num;
 
50
        int                     interface_num;
 
51
        int                     ep_out;
 
52
        int                     ep_in;
 
53
        int                     is_usb2;
 
54
        int                     is_claimed;
 
55
        int                     is_open;
 
56
        size_t                  packet_size;
 
57
};
 
58
 
 
59
void xusb_init_spec(struct xusb_spec *spec, char *name,
 
60
                uint16_t vendor_id, uint16_t product_id,
 
61
                int nifaces, int iface, int nep, int ep_out, int ep_in)
 
62
{
 
63
        DBG("Initialize %s: interfaces=%d using interface num=%d endpoints=%d (OUT=0x%2X, IN=0x%2X)\n",
 
64
                        name, nifaces, iface, nep, ep_out, ep_in);
 
65
        memset(spec, 0, sizeof(*spec));
 
66
        spec->name = name;
 
67
        spec->num_interfaces = nifaces;
 
68
        spec->my_interface_num = iface;
 
69
        spec->num_endpoints = nep;
 
70
        spec->my_vendor_id = vendor_id;
 
71
        spec->my_product_id = product_id;
 
72
        spec->my_ep_in = ep_in;
 
73
        spec->my_ep_out = ep_out;
 
74
}
 
75
 
 
76
#define EP_OUT(xusb)    ((xusb)->spec->my_ep_out)
 
77
#define EP_IN(xusb)     ((xusb)->spec->my_ep_in)
 
78
 
 
79
/*
 
80
 * USB handling
 
81
 */
 
82
 
 
83
static int get_usb_string(struct xusb *xusb, uint8_t item, char *buf, unsigned int len)
 
84
{
 
85
        char    tmp[BUFSIZ];
 
86
        int     ret;
 
87
 
 
88
        assert(xusb->handle);
 
89
        if (!item)
 
90
                return 0;
 
91
        ret = usb_get_string_simple(xusb->handle, item, tmp, BUFSIZ);
 
92
        if (ret <= 0)
 
93
                return ret;
 
94
        return snprintf(buf, len, "%s", tmp);
 
95
}
 
96
 
 
97
static const struct usb_interface_descriptor *get_interface(const struct usb_device *dev, int my_interface_num, int num_interfaces)
 
98
{
 
99
        const struct usb_interface              *interface;
 
100
        const struct usb_interface_descriptor   *iface_desc;
 
101
        const struct usb_config_descriptor      *config_desc;
 
102
        int                                     num_altsetting;
 
103
 
 
104
        config_desc = dev->config;
 
105
        if (!config_desc) {
 
106
                ERR("No configuration descriptor: strange USB1 controller?\n");
 
107
                return NULL;
 
108
        }
 
109
        if(num_interfaces && config_desc->bNumInterfaces != num_interfaces) {
 
110
                DBG("Wrong number of interfaces: have %d need %d\n",
 
111
                        config_desc->bNumInterfaces, num_interfaces);
 
112
                return NULL;
 
113
        }
 
114
        interface = &config_desc->interface[my_interface_num];
 
115
        assert(interface != NULL);
 
116
        iface_desc = interface->altsetting;
 
117
        num_altsetting = interface->num_altsetting;
 
118
        assert(num_altsetting != 0);
 
119
        assert(iface_desc != NULL);
 
120
        return iface_desc;
 
121
}
 
122
 
 
123
static int match_interface(const struct usb_device *dev, const struct xusb_spec *spec)
 
124
{
 
125
        const struct usb_device_descriptor      *dev_desc;
 
126
        const struct usb_interface_descriptor   *iface_desc;
 
127
 
 
128
        //debug_mask = 0xFF;
 
129
        //verbose = 1;
 
130
        dev_desc = &dev->descriptor;
 
131
        assert(dev_desc);
 
132
        DBG("Checking: %04X:%04X interfaces=%d interface num=%d endpoints=%d: \"%s\"\n",
 
133
                        spec->my_vendor_id,
 
134
                        spec->my_product_id,
 
135
                        spec->num_interfaces,
 
136
                        spec->my_interface_num,
 
137
                        spec->num_endpoints,
 
138
                        spec->name);
 
139
        if(dev_desc->idVendor != spec->my_vendor_id) {
 
140
                DBG("Wrong vendor id 0x%X\n", dev_desc->idVendor);
 
141
                return 0;
 
142
        }
 
143
        if(dev_desc->idProduct != spec->my_product_id) {
 
144
                DBG("Wrong product id 0x%X\n", dev_desc->idProduct);
 
145
                return 0;
 
146
        }
 
147
        if((iface_desc = get_interface(dev, spec->my_interface_num, spec->num_interfaces)) == NULL) {
 
148
                ERR("Could not get interface descriptor of device: %s\n", usb_strerror());
 
149
                return 0;
 
150
        }
 
151
        if(iface_desc->bInterfaceClass != 0xFF) {
 
152
                DBG("Wrong interface class 0x%X\n", iface_desc->bInterfaceClass);
 
153
                return 0;
 
154
        }
 
155
        if(iface_desc->bInterfaceNumber != spec->my_interface_num) {
 
156
                DBG("Wrong interface number %d (expected %d)\n",
 
157
                        iface_desc->bInterfaceNumber, spec->my_interface_num);
 
158
                return 0;
 
159
        }
 
160
        if(iface_desc->bNumEndpoints != spec->num_endpoints) {
 
161
                DBG("Wrong number of endpoints %d\n", iface_desc->bNumEndpoints);
 
162
                return 0;
 
163
        }
 
164
        return  1;
 
165
}
 
166
 
 
167
static int xusb_fill_strings(struct xusb *xusb)
 
168
{
 
169
        const struct usb_device_descriptor      *dev_desc;
 
170
        const struct usb_interface_descriptor   *iface_desc;
 
171
 
 
172
 
 
173
        dev_desc = &xusb->dev->descriptor;
 
174
        assert(dev_desc);
 
175
        if(get_usb_string(xusb, dev_desc->iManufacturer, xusb->iManufacturer, BUFSIZ) < 0) {
 
176
                ERR("Failed reading iManufacturer string: %s\n", usb_strerror());
 
177
                return 0;
 
178
        }
 
179
        if(get_usb_string(xusb, dev_desc->iProduct, xusb->iProduct, BUFSIZ) < 0) {
 
180
                ERR("Failed reading iProduct string: %s\n", usb_strerror());
 
181
                return 0;
 
182
        }
 
183
        if(get_usb_string(xusb, dev_desc->iSerialNumber, xusb->iSerialNumber, BUFSIZ) < 0) {
 
184
                ERR("Failed reading iSerialNumber string: %s\n", usb_strerror());
 
185
                return 0;
 
186
        }
 
187
        if((iface_desc = get_interface(xusb->dev, xusb->interface_num, 0)) == NULL) {
 
188
                ERR("Could not get interface descriptor of device: %s\n", usb_strerror());
 
189
                return 0;
 
190
        }
 
191
        if(get_usb_string(xusb, iface_desc->iInterface, xusb->iInterface, BUFSIZ) < 0) {
 
192
                ERR("Failed reading iInterface string: %s\n", usb_strerror());
 
193
                return 0;
 
194
        }
 
195
        return 1;
 
196
}
 
197
 
 
198
static int xusb_open(struct xusb *xusb)
 
199
{
 
200
        assert(xusb);
 
201
        if (xusb->is_open)
 
202
                return 1;
 
203
        if((xusb->handle = usb_open(xusb->dev)) == NULL) {
 
204
                ERR("Failed to open usb device '%s': %s\n",
 
205
                        xusb->devpath_tail, usb_strerror());
 
206
                return 0;
 
207
        }
 
208
        xusb->is_open = 1;
 
209
        return 1;
 
210
}
 
211
 
 
212
int xusb_claim_interface(struct xusb *xusb)
 
213
{
 
214
        const struct usb_device_descriptor      *dev_desc;
 
215
        int                                     ret;
 
216
 
 
217
        assert(xusb);
 
218
        xusb_open(xusb);        /* If it's not open yet... */
 
219
        if(usb_claim_interface(xusb->handle, xusb->interface_num) != 0) {
 
220
                ERR("usb_claim_interface %d in '%s': %s\n",
 
221
                        xusb->interface_num, xusb->devpath_tail, usb_strerror());
 
222
                return 0;
 
223
        }
 
224
        xusb->is_claimed = 1;
 
225
        xusb_fill_strings(xusb);
 
226
        dev_desc = &xusb->dev->descriptor;
 
227
        DBG("ID=%04X:%04X Manufacturer=[%s] Product=[%s] SerialNumber=[%s] Interface=[%s]\n",
 
228
                dev_desc->idVendor,
 
229
                dev_desc->idProduct,
 
230
                xusb->iManufacturer,
 
231
                xusb->iProduct,
 
232
                xusb->iSerialNumber,
 
233
                xusb->iInterface);
 
234
        if(usb_clear_halt(xusb->handle, EP_OUT(xusb)) != 0) {
 
235
                ERR("Clearing output endpoint: %s\n", usb_strerror());
 
236
                return 0;
 
237
        }
 
238
        if(usb_clear_halt(xusb->handle, EP_IN(xusb)) != 0) {
 
239
                ERR("Clearing input endpoint: %s\n", usb_strerror());
 
240
                return 0;
 
241
        }
 
242
        if((ret = xusb_flushread(xusb)) < 0) {
 
243
                ERR("xusb_flushread failed: %d\n", ret);
 
244
                return 0;
 
245
        }
 
246
        return 1;
 
247
}
 
248
 
 
249
static void xusb_list_dump(struct xlist_node *xusb_list)
 
250
{
 
251
        struct xlist_node       *curr;
 
252
        struct xusb             *xusb;
 
253
 
 
254
        for(curr = xusb_list->next; curr != xusb_list; curr = curr->next) {
 
255
                struct usb_device               *dev;
 
256
                struct usb_bus                  *bus;
 
257
                struct usb_device_descriptor    *dev_desc;
 
258
 
 
259
                xusb = curr->data;
 
260
                assert(xusb);
 
261
                dev = xusb->dev;
 
262
                assert(dev);
 
263
                bus = dev->bus;
 
264
                assert(bus);
 
265
                dev_desc = &dev->descriptor;
 
266
                assert(dev_desc);
 
267
                DBG("usb:ID=%04X:%04X [%s / %s / %s], (%s/%s)\n",
 
268
                        dev_desc->idVendor,
 
269
                        dev_desc->idProduct,
 
270
                        xusb->iManufacturer,
 
271
                        xusb->iProduct,
 
272
                        xusb->iSerialNumber,
 
273
                        bus->dirname,
 
274
                        dev->filename
 
275
                        );
 
276
        }
 
277
}
 
278
 
 
279
void xusb_destroy(struct xusb *xusb)
 
280
{
 
281
        if(xusb) {
 
282
                xusb_close(xusb);
 
283
                memset(xusb, 0, sizeof(*xusb));
 
284
                free(xusb);
 
285
        }
 
286
}
 
287
 
 
288
static struct xusb *xusb_new(struct usb_device *dev, const struct xusb_spec *spec)
 
289
{
 
290
        struct usb_device_descriptor    *dev_desc;
 
291
        struct usb_config_descriptor    *config_desc;
 
292
        struct usb_interface            *interface;
 
293
        struct usb_interface_descriptor *iface_desc;
 
294
        struct usb_endpoint_descriptor  *endpoint;
 
295
        size_t                          max_packet_size;
 
296
        int                             i;
 
297
        struct xusb                     *xusb = NULL;
 
298
 
 
299
        /*
 
300
         * Get information from the usb_device
 
301
         */
 
302
        if((dev_desc = &dev->descriptor) == NULL) {
 
303
                ERR("usb device without a device descriptor\n");
 
304
                goto fail;
 
305
        }
 
306
        if((config_desc = dev->config) == NULL) {
 
307
                ERR("usb device without a configuration descriptor\n");
 
308
                goto fail;
 
309
        }
 
310
        interface = &config_desc->interface[spec->my_interface_num];
 
311
        iface_desc = interface->altsetting;
 
312
        endpoint = iface_desc->endpoint;
 
313
        /* Calculate max packet size */
 
314
        max_packet_size = PACKET_SIZE;
 
315
        for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) {
 
316
                DBG("Validating endpoint @ %d (interface %d)\n", i, spec->my_interface_num);
 
317
                if(endpoint->bEndpointAddress == spec->my_ep_out || endpoint->bEndpointAddress == spec->my_ep_in) {
 
318
                        if(endpoint->wMaxPacketSize > PACKET_SIZE) {
 
319
                                ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize);
 
320
                                goto fail;
 
321
                        }
 
322
                        if(endpoint->wMaxPacketSize < max_packet_size) {
 
323
                                max_packet_size = endpoint->wMaxPacketSize;
 
324
                        }
 
325
                }
 
326
        }
 
327
        /* Fill xusb */
 
328
        if((xusb = malloc(sizeof(*xusb))) == NULL) {
 
329
                ERR("Out of memory");
 
330
                goto fail;
 
331
        }
 
332
        memset(xusb, 0, sizeof(*xusb));
 
333
        xusb->dev = dev;
 
334
        xusb->spec = spec;
 
335
        sscanf(dev->bus->dirname, "%d", &xusb->bus_num);
 
336
        sscanf(dev->filename, "%d", &xusb->device_num);
 
337
        snprintf(xusb->devpath_tail, PATH_MAX, "%03d/%03d",
 
338
                xusb->bus_num, xusb->device_num);
 
339
        xusb->interface_num = spec->my_interface_num;
 
340
        xusb->ep_out = spec->my_ep_out;
 
341
        xusb->ep_in = spec->my_ep_in;
 
342
        xusb->packet_size = max_packet_size;
 
343
        xusb->is_usb2 = (max_packet_size == 512);
 
344
        if (! xusb_open(xusb)) {
 
345
                ERR("Failed opening device: %04X:%04X - %s\n",
 
346
                        dev_desc->idVendor,
 
347
                        dev_desc->idProduct,
 
348
                        xusb->devpath_tail);
 
349
                goto fail;
 
350
        }
 
351
        DBG("%04X:%04X - %s\n",
 
352
                dev_desc->idVendor,
 
353
                dev_desc->idProduct,
 
354
                xusb->devpath_tail);
 
355
        return xusb;
 
356
fail:
 
357
        xusb_destroy(xusb);
 
358
        return NULL;
 
359
}
 
360
 
 
361
struct xusb *xusb_find_iface(const char *devpath, int iface_num, int ep_out, int ep_in)
 
362
{
 
363
        struct usb_bus          *bus;
 
364
 
 
365
        DBG("\n");
 
366
        usb_init();
 
367
        usb_find_busses();
 
368
        usb_find_devices();
 
369
        for (bus = usb_get_busses(); bus; bus = bus->next) {
 
370
                int                     bus_num;
 
371
                char                    tmppath[PATH_MAX + 1];
 
372
                struct usb_device       *dev;
 
373
 
 
374
                tmppath[0] = '\0';
 
375
                sscanf(bus->dirname, "%d", &bus_num);
 
376
                snprintf(tmppath, sizeof(tmppath), "%03d", bus_num);
 
377
                DBG("Check bus %d: %s ? %s\n", bus_num, tmppath, devpath);
 
378
                if (strncmp(tmppath, devpath, strlen(tmppath)) != 0)
 
379
                        continue;
 
380
                DBG("Matched bus %d\n", bus_num);
 
381
                for (dev = bus->devices; dev; dev = dev->next) {
 
382
                        struct usb_device_descriptor    *dev_desc;
 
383
                        struct usb_config_descriptor    *config_desc;
 
384
                        struct usb_interface            *interface;
 
385
                        struct xusb_spec                spec;
 
386
                        struct xusb                     *xusb;
 
387
                        int                             device_num;
 
388
 
 
389
                        sscanf(dev->filename, "%d", &device_num);
 
390
                        DBG("Check device %d\n", device_num);
 
391
                        snprintf(tmppath, sizeof(tmppath), "%03d/%03d", bus_num, device_num);
 
392
                        if (strncmp(tmppath, devpath, strlen(tmppath)) != 0)
 
393
                                continue;
 
394
                        dev_desc = &dev->descriptor;
 
395
                        assert(dev_desc);
 
396
                        config_desc = dev->config;
 
397
                        assert(config_desc);
 
398
                        interface = config_desc->interface;
 
399
                        assert(interface);
 
400
                        INFO("Matched device %s: %X:%X\n", tmppath, dev_desc->idVendor, dev_desc->idProduct);
 
401
                        xusb_init_spec(&spec, "Astribank",
 
402
                                dev_desc->idVendor, dev_desc->idProduct,
 
403
                                config_desc->bNumInterfaces,
 
404
                                iface_num,
 
405
                                interface->altsetting->bNumEndpoints,
 
406
                                ep_out, ep_in);
 
407
                        if((xusb = xusb_new(dev, &spec)) == NULL) {
 
408
                                ERR("xusb allocation failed\n");
 
409
                        }
 
410
                        return xusb;
 
411
                }
 
412
        }
 
413
        return NULL;
 
414
}
 
415
 
 
416
static const char *path_tail(const char *path)
 
417
{
 
418
        const   char    *p;
 
419
 
 
420
        assert(path != NULL);
 
421
        /* Find last '/' */
 
422
        if((p = memrchr(path, '/', strlen(path))) == NULL) {
 
423
                ERR("Missing a '/' in %s\n", path);
 
424
                return NULL;
 
425
        }
 
426
        /* Search for a '/' before that */
 
427
        if((p = memrchr(path, '/', p - path)) == NULL) {
 
428
                p = path;               /* No more '/' */
 
429
        } else {
 
430
                p++;                    /* skip '/' */
 
431
        }
 
432
        return p;
 
433
}
 
434
 
 
435
int xusb_filter_bypath(const struct xusb *xusb, void *data)
 
436
{
 
437
        const char      *p;
 
438
        const char      *path = data;
 
439
 
 
440
        DBG("%s\n", path);
 
441
        assert(path != NULL);
 
442
        p = path_tail(path);
 
443
        if(strcmp(xusb->devpath_tail, p) != 0) {
 
444
                DBG("device path missmatch: '%s' != '%s'\n", xusb->devpath_tail, p);
 
445
                return 0;
 
446
        }
 
447
        return 1;
 
448
}
 
449
 
 
450
struct xusb *xusb_find_bypath(const struct xusb_spec *specs, int numspecs, const char *path)
 
451
{
 
452
        struct xlist_node       *xlist;
 
453
        struct xlist_node       *head;
 
454
        struct xusb             *xusb;
 
455
 
 
456
        xlist = xusb_find_byproduct(specs, numspecs, xusb_filter_bypath, (void *)path);
 
457
        head = xlist_shift(xlist);
 
458
        if (!head)
 
459
                return NULL;
 
460
        if (! xlist_empty(xlist)) {
 
461
                ERR("Too many matches (extra %zd) to '%s'\n", xlist_length(xlist), path);
 
462
                return NULL;
 
463
        }
 
464
        xusb = head->data;
 
465
        xlist_destroy(xlist, NULL);
 
466
        return xusb;
 
467
}
 
468
 
 
469
struct xlist_node *xusb_find_byproduct(const struct xusb_spec *specs, int numspecs, xusb_filter_t filterfunc, void *data)
 
470
{
 
471
        struct xlist_node       *xlist;
 
472
        struct usb_bus          *bus;
 
473
        struct usb_device       *dev;
 
474
 
 
475
        DBG("specs(%d)\n", numspecs);
 
476
        if((xlist = xlist_new(NULL)) == NULL) {
 
477
                ERR("Failed allocation new xlist");
 
478
                goto fail_xlist;
 
479
        }
 
480
        usb_init();
 
481
        usb_find_busses();
 
482
        usb_find_devices();
 
483
        for (bus = usb_get_busses(); bus; bus = bus->next) {
 
484
                for (dev = bus->devices; dev; dev = dev->next) {
 
485
                        struct usb_device_descriptor    *dev_desc;
 
486
                        struct xlist_node               *item;
 
487
                        int                             i;
 
488
 
 
489
                        dev_desc = &dev->descriptor;
 
490
                        assert(dev_desc);
 
491
                        DBG("usb:%s/%s: ID=%04X:%04X\n",
 
492
                                dev->bus->dirname,
 
493
                                dev->filename,
 
494
                                dev_desc->idVendor,
 
495
                                dev_desc->idProduct);
 
496
                        for(i = 0; i < numspecs; i++) {
 
497
                                struct xusb             *xusb;
 
498
                                const struct xusb_spec  *sp = &specs[i];
 
499
 
 
500
                                if(!match_interface(dev, sp))
 
501
                                        continue;
 
502
                                if((xusb = xusb_new(dev, sp)) == NULL) {
 
503
                                        ERR("xusb allocation failed\n");
 
504
                                        goto fail_malloc;
 
505
                                }
 
506
                                if(filterfunc && !filterfunc(xusb, data)) {
 
507
                                        xusb_destroy(xusb);
 
508
                                        continue;
 
509
                                }
 
510
                                item = xlist_new(xusb);
 
511
                                xlist_append_item(xlist, item);
 
512
                                break;
 
513
                        }
 
514
                }
 
515
        }
 
516
        xusb_list_dump(xlist);
 
517
        return xlist;
 
518
fail_malloc:
 
519
        xlist_destroy(xlist, NULL);
 
520
fail_xlist:
 
521
        return NULL;
 
522
}
 
523
 
 
524
struct xusb *xusb_open_one(const struct xusb_spec *specs, int numspecs, xusb_filter_t filterfunc, void *data)
 
525
{
 
526
        struct xlist_node       *xusb_list;
 
527
        struct xlist_node       *curr;
 
528
        int                     num;
 
529
        struct xusb             *xusb = NULL;
 
530
 
 
531
        xusb_list = xusb_find_byproduct(specs, numspecs, filterfunc, data);
 
532
        num = xlist_length(xusb_list);
 
533
        DBG("total %d devices\n", num);
 
534
        switch(num) {
 
535
        case 0:
 
536
                ERR("No matching device.\n");
 
537
                break;
 
538
        case 1:
 
539
                curr = xlist_shift(xusb_list);
 
540
                xusb = curr->data;
 
541
                xlist_destroy(curr, NULL);
 
542
                xlist_destroy(xusb_list, NULL);
 
543
                xusb_claim_interface(xusb);
 
544
                xusb_showinfo(xusb);
 
545
                break;
 
546
        default:
 
547
                ERR("Too many devices (%d). Aborting.\n", num);
 
548
                break;
 
549
        }
 
550
        return xusb;
 
551
}
 
552
 
 
553
int xusb_interface(struct xusb *xusb)
 
554
{
 
555
        return xusb->interface_num;
 
556
}
 
557
 
 
558
size_t xusb_packet_size(const struct xusb *xusb)
 
559
{
 
560
        return xusb->packet_size;
 
561
}
 
562
 
 
563
/*
 
564
 * MP device handling
 
565
 */
 
566
void xusb_showinfo(const struct xusb *xusb)
 
567
{
 
568
        struct usb_device_descriptor    *dev_desc;
 
569
        struct usb_device               *dev;
 
570
 
 
571
        assert(xusb != NULL);
 
572
        dev = xusb->dev;
 
573
        dev_desc = &dev->descriptor;
 
574
        if(verbose <= LOG_INFO) {
 
575
                INFO("usb:%s/%s: ID=%04X:%04X [%s / %s / %s]\n",
 
576
                        dev->bus->dirname,
 
577
                        dev->filename,
 
578
                        dev_desc->idVendor,
 
579
                        dev_desc->idProduct,
 
580
                        xusb->iManufacturer,
 
581
                        xusb->iProduct,
 
582
                        xusb->iSerialNumber);
 
583
        } else {
 
584
                printf("USB    Bus/Device:    [%s/%s] (%s,%s)\n",
 
585
                        dev->bus->dirname,
 
586
                        dev->filename,
 
587
                        (xusb->is_open) ? "open" : "closed",
 
588
                        (xusb->is_claimed) ? "claimed" : "unused");
 
589
                printf("USB    Spec name:     [%s]\n", xusb->spec->name);
 
590
                printf("USB    iManufacturer: [%s]\n", xusb->iManufacturer);
 
591
                printf("USB    iProduct:      [%s]\n", xusb->iProduct);
 
592
                printf("USB    iSerialNumber: [%s]\n", xusb->iSerialNumber);
 
593
        }
 
594
}
 
595
 
 
596
const char *xusb_serial(const struct xusb *xusb)
 
597
{
 
598
        return xusb->iSerialNumber;
 
599
}
 
600
 
 
601
const char *xusb_devpath(const struct xusb *xusb)
 
602
{
 
603
        return xusb->devpath_tail;
 
604
}
 
605
 
 
606
const char *xusb_manufacturer(const struct xusb *xusb)
 
607
{
 
608
        return xusb->iManufacturer;
 
609
}
 
610
 
 
611
const char *xusb_product(const struct xusb *xusb)
 
612
{
 
613
        return xusb->iProduct;
 
614
}
 
615
 
 
616
uint16_t xusb_vendor_id(const struct xusb *xusb)
 
617
{
 
618
        return  xusb->dev->descriptor.idVendor;
 
619
}
 
620
 
 
621
uint16_t xusb_product_id(const struct xusb *xusb)
 
622
{
 
623
        return  xusb->dev->descriptor.idProduct;
 
624
}
 
625
 
 
626
const struct xusb_spec *xusb_spec(const struct xusb *xusb)
 
627
{
 
628
        return xusb->spec;
 
629
}
 
630
 
 
631
int xusb_close(struct xusb *xusb)
 
632
{
 
633
        if(xusb) {
 
634
                if(xusb->handle) {
 
635
                        assert(xusb->spec);
 
636
                        assert(xusb->spec->name);
 
637
                        DBG("Closing interface \"%s\"\n", xusb->spec->name);
 
638
                        if(xusb->is_claimed) {
 
639
                                if(usb_release_interface(xusb->handle, xusb->spec->my_interface_num) != 0) {
 
640
                                        ERR("Releasing interface: usb: %s\n", usb_strerror());
 
641
                                }
 
642
                                xusb->is_claimed = 0;
 
643
                        }
 
644
                        if(xusb->is_open) {
 
645
                                if(usb_close(xusb->handle) != 0) {
 
646
                                        ERR("Closing device: usb: %s\n", usb_strerror());
 
647
                                }
 
648
                                xusb->is_open = 0;
 
649
                        }
 
650
                        xusb->handle = NULL;
 
651
                }
 
652
                xusb = NULL;
 
653
        }
 
654
        return 0;
 
655
}
 
656
 
 
657
int xusb_send(struct xusb *xusb, char *buf, int len, int timeout)
 
658
{
 
659
        int             ret;
 
660
 
 
661
        dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, len);
 
662
        if(EP_OUT(xusb) & USB_ENDPOINT_IN) {
 
663
                ERR("%s called with an input endpoint 0x%x\n", __FUNCTION__, EP_OUT(xusb));
 
664
                return -EINVAL;
 
665
        }
 
666
        ret = usb_bulk_write(xusb->handle, EP_OUT(xusb), buf, len, timeout);
 
667
        if(ret < 0) {
 
668
                /*
 
669
                 * If the device was gone, it may be the
 
670
                 * result of renumeration. Ignore it.
 
671
                 */
 
672
                if(ret != -ENODEV) {
 
673
                        ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n",
 
674
                                EP_OUT(xusb), ret, usb_strerror());
 
675
                        dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len);
 
676
                        //exit(2);
 
677
                } else {
 
678
                        DBG("bulk_write to endpoint 0x%x got ENODEV\n", EP_OUT(xusb));
 
679
                        xusb_close(xusb);
 
680
                }
 
681
                return ret;
 
682
        } else if(ret != len) {
 
683
                ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n",
 
684
                        EP_OUT(xusb), ret, usb_strerror());
 
685
                dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len);
 
686
                return -EFAULT;
 
687
        }
 
688
        return ret;
 
689
}
 
690
 
 
691
int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout)
 
692
{
 
693
        int     ret;
 
694
 
 
695
        if(EP_IN(xusb) & USB_ENDPOINT_OUT) {
 
696
                ERR("%s called with an output endpoint 0x%x\n", __FUNCTION__, EP_IN(xusb));
 
697
                return -EINVAL;
 
698
        }
 
699
        ret = usb_bulk_read(xusb->handle, EP_IN(xusb), buf, len, timeout);
 
700
        if(ret < 0) {
 
701
                DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n",
 
702
                        EP_IN(xusb), ret, usb_strerror());
 
703
                memset(buf, 0, len);
 
704
                return ret;
 
705
        }
 
706
        dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, ret);
 
707
        return ret;
 
708
}
 
709
 
 
710
int xusb_flushread(struct xusb *xusb)
 
711
{
 
712
        char            tmpbuf[BUFSIZ];
 
713
        int             ret;
 
714
 
 
715
        DBG("starting...\n");
 
716
        memset(tmpbuf, 0, BUFSIZ);
 
717
        ret = xusb_recv(xusb, tmpbuf, BUFSIZ, 1);
 
718
        if(ret < 0 && ret != -ETIMEDOUT) {
 
719
                ERR("ret=%d\n", ret);
 
720
                return ret;
 
721
        } else if(ret > 0) {
 
722
                DBG("Got %d bytes:\n", ret);
 
723
                dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, tmpbuf, ret);
 
724
        }
 
725
        return 0;
 
726
}