Root/tools/lib/usbopen.c

Source at commit 1f003f1c2100f7f3670106fd13df0eaec7a0e4e1 created 4 years 2 months ago.
By Werner Almesberger, atusb/atusb.kicad_pcb: grow RF feed trace to 1.9 mm, for 1.0 mm PCB
1/*
2 * lib/usbopen.c - Common USB device lookup and open code
3 *
4 * Written 2008-2011 by Werner Almesberger
5 * Copyright 2008-2011 Werner Almesberger
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
13
14
15#include <stdarg.h>
16#include <stdint.h>
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20#include <usb.h>
21
22#include "usbopen.h"
23
24
25#define USB_PATH_ROOT "/sys/bus/usb/devices/"
26#define USB_BUS_LEAF "/busnum"
27#define USB_DEV_LEAF "/devnum"
28
29static uint16_t vendor = 0;
30static uint16_t product = 0;
31static const struct usb_device *restricted_path = NULL;
32static int initialized = 0;
33
34
35static void initialize(void)
36{
37
38    if (initialized)
39        return;
40    initialized = 1;
41
42    usb_init();
43    usb_find_busses();
44    usb_find_devices();
45}
46
47
48void usb_rescan(void)
49{
50    initialized = 0;
51}
52
53
54usb_dev_handle *open_usb(uint16_t default_vendor, uint16_t default_product)
55{
56    const struct usb_bus *bus;
57    struct usb_device *dev;
58    usb_dev_handle *handle;
59#ifdef DO_FULL_USB_BUREAUCRACY
60    int res;
61#endif
62
63    initialize();
64
65    if (!vendor)
66        vendor = default_vendor;
67    if (!product)
68        product = default_product;
69
70    for (bus = usb_get_busses(); bus; bus = bus->next)
71        for (dev = bus->devices; dev; dev = dev->next) {
72            if (restricted_path && restricted_path != dev)
73                continue;
74            if (vendor && dev->descriptor.idVendor != vendor)
75                continue;
76            if (product && dev->descriptor.idProduct != product)
77                continue;
78            handle = usb_open(dev);
79#ifdef DO_FULL_USB_BUREAUCRACY
80            if (!handle)
81                return NULL;
82            res = usb_set_configuration(handle, 1);
83            if (res < 0) {
84                fprintf(stderr, "usb_set_configuration: %d\n",
85                    res);
86                return NULL;
87            }
88            res = usb_claim_interface(handle, 0);
89            if (res < 0) {
90                fprintf(stderr, "usb_claim_interface: %d\n",
91                    res);
92                return NULL;
93            }
94            res = usb_set_altinterface(handle, 0);
95            if (res < 0) {
96                fprintf(stderr, "usb_set_altinterface: %d\n",
97                    res);
98                return NULL;
99            }
100#endif
101            return handle;
102        }
103    return NULL;
104}
105
106
107static void bad_id(const char *id)
108{
109    fprintf(stderr, "\"%s\" is not a valid [vendor]:[product] ID\n", id);
110    exit(1);
111}
112
113
114void parse_usb_id(const char *id)
115{
116    unsigned long tmp;
117    char *end;
118
119    if (*id == ':') {
120        vendor = 0;
121        end = (char *) id; /* ugly */
122    } else {
123        tmp = strtoul(id, &end, 16);
124        if (*end != ':')
125            bad_id(id);
126        if (tmp > 0xffff)
127            bad_id(id);
128        vendor = tmp;
129    }
130    if (!*end)
131        bad_id(id);
132    if (!end[1])
133        product = 0;
134    else {
135        tmp = strtoul(end+1, &end, 16);
136        if (*end)
137            bad_id(id);
138        if (tmp > 0xffff)
139            bad_id(id);
140        product = tmp;
141    }
142}
143
144
145static void restrict_usb_dev(int bus_num, int dev_num)
146{
147    const struct usb_bus *bus;
148    const struct usb_device *dev;
149
150    initialize();
151
152    for (bus = usb_busses; bus; bus = bus->next) {
153        if (atoi(bus->dirname) != bus_num)
154            continue;
155        for (dev = bus->devices; dev; dev = dev->next)
156            if (dev->devnum == dev_num) {
157                restricted_path = dev;
158                return;
159            }
160    }
161    fprintf(stderr, "no device %d/%d\n", bus_num, dev_num);
162    exit(1);
163}
164
165
166static void restrict_usb_by_dev(const char *path)
167{
168    int bus_num, dev_num;
169
170    if (sscanf(path, "%d/%d", &bus_num, &dev_num) != 2) {
171        fprintf(stderr, "invalid device syntax \"%s\"\n", path);
172        exit(1);
173    }
174    restrict_usb_dev(bus_num, dev_num);
175}
176
177
178static int read_num(const char *fmt, ...)
179{
180    va_list ap;
181    FILE *file;
182    char *buf;
183    int n, num;
184
185    va_start(ap, fmt);
186    n = vsnprintf(NULL, 0, fmt, ap);
187    va_end(ap);
188
189    buf = malloc(n+1);
190    if (!buf) {
191        perror("malloc");
192        exit(1);
193    }
194
195    va_start(ap, fmt);
196    vsprintf(buf, fmt, ap);
197    va_end(ap);
198
199    file = fopen(buf, "r");
200    if (!file) {
201        perror(buf);
202        exit(1);
203    }
204
205    n = fscanf(file, "%d", &num);
206    if (n <0) {
207        perror(buf);
208        exit(1);
209    }
210    if (n != 1) {
211        fprintf(stderr, "%s: can't read number\n", buf);
212        exit(1);
213    }
214
215    fclose(file);
216    free(buf);
217
218    return num;
219}
220
221
222static void restrict_usb_by_port(const char *path)
223{
224    const char *p;
225    int bus_num, dev_num;
226
227    /*
228     * We sanitize the path, in case we're part of a program running with
229     * suid.
230     */
231    for (p = path; *p; p++)
232        if (!strchr("0123456789-.", *p)) {
233            fprintf(stderr,
234                "invalid character \'%c\' in USB path\n", *p);
235            exit(1);
236        }
237
238    bus_num = read_num("%s%s%s", USB_PATH_ROOT, path, USB_BUS_LEAF);
239    dev_num = read_num("%s%s%s", USB_PATH_ROOT, path, USB_DEV_LEAF);
240    restrict_usb_dev(bus_num, dev_num);
241}
242
243
244void restrict_usb_path(const char *path)
245{
246    if (strchr(path, '/'))
247        restrict_usb_by_dev(path);
248    else
249        restrict_usb_by_port(path);
250}
251
252
253void usb_unrestrict(void)
254{
255    vendor = 0;
256    product = 0;
257    restricted_path = NULL;
258}
259

Archive Download this file



interactive