Statistics
| Branch: | Revision:

root / usb-linux.c @ feea13e1

History | View | Annotate | Download (14.7 kB)

1
/*
2
 * Linux host USB redirector
3
 *
4
 * Copyright (c) 2005 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25

    
26
#if defined(__linux__)
27
#include <dirent.h>
28
#include <sys/ioctl.h>
29
#include <linux/usbdevice_fs.h>
30
#include <linux/version.h>
31

    
32
/* We redefine it to avoid version problems */
33
struct usb_ctrltransfer {
34
    uint8_t  bRequestType;
35
    uint8_t  bRequest;
36
    uint16_t wValue;
37
    uint16_t wIndex;
38
    uint16_t wLength;
39
    uint32_t timeout;
40
    void *data;
41
};
42

    
43
typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
44
                        int vendor_id, int product_id, 
45
                        const char *product_name, int speed);
46
static int usb_host_find_device(int *pbus_num, int *paddr, 
47
                                char *product_name, int product_name_size,
48
                                const char *devname);
49

    
50
//#define DEBUG
51

    
52
#define USBDEVFS_PATH "/proc/bus/usb"
53
#define PRODUCT_NAME_SZ 32
54

    
55
typedef struct USBHostDevice {
56
    USBDevice dev;
57
    int fd;
58
} USBHostDevice;
59

    
60
static void usb_host_handle_reset(USBDevice *dev, int destroy)
61
{
62
#if 0
63
    USBHostDevice *s = (USBHostDevice *)dev;
64
    /* USBDEVFS_RESET, but not the first time as it has already be
65
       done by the host OS */
66
    ioctl(s->fd, USBDEVFS_RESET);
67
#endif
68
} 
69

    
70
static int usb_host_handle_control(USBDevice *dev,
71
                                   int request,
72
                                   int value,
73
                                   int index,
74
                                   int length,
75
                                   uint8_t *data)
76
{
77
    USBHostDevice *s = (USBHostDevice *)dev;
78
    struct usb_ctrltransfer ct;
79
    int ret;
80

    
81
    if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
82
        /* specific SET_ADDRESS support */
83
        dev->addr = value;
84
        return 0;
85
    } else {
86
        ct.bRequestType = request >> 8;
87
        ct.bRequest = request;
88
        ct.wValue = value;
89
        ct.wIndex = index;
90
        ct.wLength = length;
91
        ct.timeout = 50;
92
        ct.data = data;
93
        ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
94
        if (ret < 0) {
95
            switch(errno) {
96
            case ETIMEDOUT:
97
                return USB_RET_NAK;
98
            default:
99
                return USB_RET_STALL;
100
            }
101
        } else {
102
            return ret;
103
        }
104
   }
105
}
106

    
107
static int usb_host_handle_data(USBDevice *dev, int pid, 
108
                                uint8_t devep,
109
                                uint8_t *data, int len)
110
{
111
    USBHostDevice *s = (USBHostDevice *)dev;
112
    struct usbdevfs_bulktransfer bt;
113
    int ret;
114

    
115
    /* XXX: optimize and handle all data types by looking at the
116
       config descriptor */
117
    if (pid == USB_TOKEN_IN)
118
        devep |= 0x80;
119
    bt.ep = devep;
120
    bt.len = len;
121
    bt.timeout = 50;
122
    bt.data = data;
123
    ret = ioctl(s->fd, USBDEVFS_BULK, &bt);
124
    if (ret < 0) {
125
        switch(errno) {
126
        case ETIMEDOUT:
127
            return USB_RET_NAK;
128
        case EPIPE:
129
        default:
130
#ifdef DEBUG
131
            printf("handle_data: errno=%d\n", errno);
132
#endif
133
            return USB_RET_STALL;
134
        }
135
    } else {
136
        return ret;
137
    }
138
}
139

    
140
/* XXX: exclude high speed devices or implement EHCI */
141
USBDevice *usb_host_device_open(const char *devname)
142
{
143
    int fd, interface, ret, i;
144
    USBHostDevice *dev;
145
    struct usbdevfs_connectinfo ci;
146
    uint8_t descr[1024];
147
    char buf[1024];
148
    int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
149
    int bus_num, addr;
150
    char product_name[PRODUCT_NAME_SZ];
151

    
152
    if (usb_host_find_device(&bus_num, &addr, 
153
                             product_name, sizeof(product_name),
154
                             devname) < 0) 
155
        return NULL;
156
    
157
    snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d", 
158
             bus_num, addr);
159
    fd = open(buf, O_RDWR);
160
    if (fd < 0) {
161
        perror(buf);
162
        return NULL;
163
    }
164

    
165
    /* read the config description */
166
    descr_len = read(fd, descr, sizeof(descr));
167
    if (descr_len <= 0) {
168
        perror("read descr");
169
        goto fail;
170
    }
171
    
172
    i = 0;
173
    dev_descr_len = descr[0];
174
    if (dev_descr_len > descr_len)
175
        goto fail;
176
    i += dev_descr_len;
177
    config_descr_len = descr[i];
178
    if (i + config_descr_len > descr_len)
179
        goto fail;
180
    nb_interfaces = descr[i + 4];
181
    if (nb_interfaces != 1) {
182
        /* NOTE: currently we grab only one interface */
183
        fprintf(stderr, "usb_host: only one interface supported\n");
184
        goto fail;
185
    }
186

    
187
#ifdef USBDEVFS_DISCONNECT
188
    /* earlier Linux 2.4 do not support that */
189
    {
190
        struct usbdevfs_ioctl ctrl;
191
        ctrl.ioctl_code = USBDEVFS_DISCONNECT;
192
        ctrl.ifno = 0;
193
        ret = ioctl(fd, USBDEVFS_IOCTL, &ctrl);
194
        if (ret < 0 && errno != ENODATA) {
195
            perror("USBDEVFS_DISCONNECT");
196
            goto fail;
197
        }
198
    }
199
#endif
200

    
201
    /* XXX: only grab if all interfaces are free */
202
    interface = 0;
203
    ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
204
    if (ret < 0) {
205
        if (errno == EBUSY) {
206
            fprintf(stderr, "usb_host: device already grabbed\n");
207
        } else {
208
            perror("USBDEVFS_CLAIMINTERFACE");
209
        }
210
    fail:
211
        close(fd);
212
        return NULL;
213
    }
214

    
215
    ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
216
    if (ret < 0) {
217
        perror("USBDEVFS_CONNECTINFO");
218
        goto fail;
219
    }
220

    
221
#ifdef DEBUG
222
    printf("host USB device %d.%d grabbed\n", bus_num, addr);
223
#endif    
224

    
225
    dev = qemu_mallocz(sizeof(USBHostDevice));
226
    if (!dev)
227
        goto fail;
228
    dev->fd = fd;
229
    if (ci.slow)
230
        dev->dev.speed = USB_SPEED_LOW;
231
    else
232
        dev->dev.speed = USB_SPEED_HIGH;
233
    dev->dev.handle_packet = usb_generic_handle_packet;
234

    
235
    dev->dev.handle_reset = usb_host_handle_reset;
236
    dev->dev.handle_control = usb_host_handle_control;
237
    dev->dev.handle_data = usb_host_handle_data;
238

    
239
    if (product_name[0] == '\0')
240
        snprintf(dev->dev.devname, sizeof(dev->dev.devname),
241
                 "host:%s", devname);
242
    else
243
        pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
244
                product_name);
245

    
246
    return (USBDevice *)dev;
247
}
248

    
249
static int get_tag_value(char *buf, int buf_size,
250
                         const char *str, const char *tag, 
251
                         const char *stopchars)
252
{
253
    const char *p;
254
    char *q;
255
    p = strstr(str, tag);
256
    if (!p)
257
        return -1;
258
    p += strlen(tag);
259
    while (isspace(*p))
260
        p++;
261
    q = buf;
262
    while (*p != '\0' && !strchr(stopchars, *p)) {
263
        if ((q - buf) < (buf_size - 1))
264
            *q++ = *p;
265
        p++;
266
    }
267
    *q = '\0';
268
    return q - buf;
269
}
270

    
271
static int usb_host_scan(void *opaque, USBScanFunc *func)
272
{
273
    FILE *f;
274
    char line[1024];
275
    char buf[1024];
276
    int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
277
    int ret;
278
    char product_name[512];
279
    
280
    f = fopen(USBDEVFS_PATH "/devices", "r");
281
    if (!f) {
282
        term_printf("Could not open %s\n", USBDEVFS_PATH "/devices");
283
        return 0;
284
    }
285
    device_count = 0;
286
    bus_num = addr = speed = class_id = product_id = vendor_id = 0;
287
    ret = 0;
288
    for(;;) {
289
        if (fgets(line, sizeof(line), f) == NULL)
290
            break;
291
        if (strlen(line) > 0)
292
            line[strlen(line) - 1] = '\0';
293
        if (line[0] == 'T' && line[1] == ':') {
294
            if (device_count && (vendor_id || product_id)) {
295
                /* New device.  Add the previously discovered device.  */
296
                ret = func(opaque, bus_num, addr, class_id, vendor_id, 
297
                           product_id, product_name, speed);
298
                if (ret)
299
                    goto the_end;
300
            }
301
            if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0)
302
                goto fail;
303
            bus_num = atoi(buf);
304
            if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0)
305
                goto fail;
306
            addr = atoi(buf);
307
            if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0)
308
                goto fail;
309
            if (!strcmp(buf, "480"))
310
                speed = USB_SPEED_HIGH;
311
            else if (!strcmp(buf, "1.5"))
312
                speed = USB_SPEED_LOW;
313
            else
314
                speed = USB_SPEED_FULL;
315
            product_name[0] = '\0';
316
            class_id = 0xff;
317
            device_count++;
318
            product_id = 0;
319
            vendor_id = 0;
320
        } else if (line[0] == 'P' && line[1] == ':') {
321
            if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0)
322
                goto fail;
323
            vendor_id = strtoul(buf, NULL, 16);
324
            if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0)
325
                goto fail;
326
            product_id = strtoul(buf, NULL, 16);
327
        } else if (line[0] == 'S' && line[1] == ':') {
328
            if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0)
329
                goto fail;
330
            pstrcpy(product_name, sizeof(product_name), buf);
331
        } else if (line[0] == 'D' && line[1] == ':') {
332
            if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0)
333
                goto fail;
334
            class_id = strtoul(buf, NULL, 16);
335
        }
336
    fail: ;
337
    }
338
    if (device_count && (vendor_id || product_id)) {
339
        /* Add the last device.  */
340
        ret = func(opaque, bus_num, addr, class_id, vendor_id, 
341
                   product_id, product_name, speed);
342
    }
343
 the_end:
344
    fclose(f);
345
    return ret;
346
}
347

    
348
typedef struct FindDeviceState {
349
    int vendor_id;
350
    int product_id;
351
    int bus_num;
352
    int addr;
353
    char product_name[PRODUCT_NAME_SZ];
354
} FindDeviceState;
355

    
356
static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, 
357
                                     int class_id,
358
                                     int vendor_id, int product_id, 
359
                                     const char *product_name, int speed)
360
{
361
    FindDeviceState *s = opaque;
362
    if ((vendor_id == s->vendor_id &&
363
        product_id == s->product_id) ||
364
        (bus_num == s->bus_num &&
365
        addr == s->addr)) {
366
        pstrcpy(s->product_name, PRODUCT_NAME_SZ, product_name);
367
        s->bus_num = bus_num;
368
        s->addr = addr;
369
        return 1;
370
    } else {
371
        return 0;
372
    }
373
}
374

    
375
/* the syntax is : 
376
   'bus.addr' (decimal numbers) or 
377
   'vendor_id:product_id' (hexa numbers) */
378
static int usb_host_find_device(int *pbus_num, int *paddr, 
379
                                char *product_name, int product_name_size,
380
                                const char *devname)
381
{
382
    const char *p;
383
    int ret;
384
    FindDeviceState fs;
385

    
386
    p = strchr(devname, '.');
387
    if (p) {
388
        *pbus_num = strtoul(devname, NULL, 0);
389
        *paddr = strtoul(p + 1, NULL, 0);
390
        fs.bus_num = *pbus_num;
391
        fs.addr = *paddr;
392
        ret = usb_host_scan(&fs, usb_host_find_device_scan);
393
        if (ret)
394
            pstrcpy(product_name, product_name_size, fs.product_name);
395
        return 0;
396
    }
397
    p = strchr(devname, ':');
398
    if (p) {
399
        fs.vendor_id = strtoul(devname, NULL, 16);
400
        fs.product_id = strtoul(p + 1, NULL, 16);
401
        ret = usb_host_scan(&fs, usb_host_find_device_scan);
402
        if (ret) {
403
            *pbus_num = fs.bus_num;
404
            *paddr = fs.addr;
405
            pstrcpy(product_name, product_name_size, fs.product_name);
406
            return 0;
407
        }
408
    }
409
    return -1;
410
}
411

    
412
/**********************/
413
/* USB host device info */
414

    
415
struct usb_class_info {
416
    int class;
417
    const char *class_name;
418
};
419

    
420
static const struct usb_class_info usb_class_info[] = {
421
    { USB_CLASS_AUDIO, "Audio"},
422
    { USB_CLASS_COMM, "Communication"},
423
    { USB_CLASS_HID, "HID"},
424
    { USB_CLASS_HUB, "Hub" },
425
    { USB_CLASS_PHYSICAL, "Physical" },
426
    { USB_CLASS_PRINTER, "Printer" },
427
    { USB_CLASS_MASS_STORAGE, "Storage" },
428
    { USB_CLASS_CDC_DATA, "Data" },
429
    { USB_CLASS_APP_SPEC, "Application Specific" },
430
    { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
431
    { USB_CLASS_STILL_IMAGE, "Still Image" },
432
    { USB_CLASS_CSCID,         "Smart Card" },
433
    { USB_CLASS_CONTENT_SEC, "Content Security" },
434
    { -1, NULL }
435
};
436

    
437
static const char *usb_class_str(uint8_t class)
438
{
439
    const struct usb_class_info *p;
440
    for(p = usb_class_info; p->class != -1; p++) {
441
        if (p->class == class)
442
            break;
443
    }
444
    return p->class_name;
445
}
446

    
447
void usb_info_device(int bus_num, int addr, int class_id,
448
                     int vendor_id, int product_id, 
449
                     const char *product_name,
450
                     int speed)
451
{
452
    const char *class_str, *speed_str;
453

    
454
    switch(speed) {
455
    case USB_SPEED_LOW: 
456
        speed_str = "1.5"; 
457
        break;
458
    case USB_SPEED_FULL: 
459
        speed_str = "12"; 
460
        break;
461
    case USB_SPEED_HIGH: 
462
        speed_str = "480"; 
463
        break;
464
    default:
465
        speed_str = "?"; 
466
        break;
467
    }
468

    
469
    term_printf("  Device %d.%d, speed %s Mb/s\n", 
470
                bus_num, addr, speed_str);
471
    class_str = usb_class_str(class_id);
472
    if (class_str) 
473
        term_printf("    %s:", class_str);
474
    else
475
        term_printf("    Class %02x:", class_id);
476
    term_printf(" USB device %04x:%04x", vendor_id, product_id);
477
    if (product_name[0] != '\0')
478
        term_printf(", %s", product_name);
479
    term_printf("\n");
480
}
481

    
482
static int usb_host_info_device(void *opaque, int bus_num, int addr, 
483
                                int class_id,
484
                                int vendor_id, int product_id, 
485
                                const char *product_name,
486
                                int speed)
487
{
488
    usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
489
                    product_name, speed);
490
    return 0;
491
}
492

    
493
void usb_host_info(void)
494
{
495
    usb_host_scan(NULL, usb_host_info_device);
496
}
497

    
498
#else
499

    
500
void usb_host_info(void)
501
{
502
    term_printf("USB host devices not supported\n");
503
}
504

    
505
/* XXX: modify configure to compile the right host driver */
506
USBDevice *usb_host_device_open(const char *devname)
507
{
508
    return NULL;
509
}
510

    
511
#endif