Revision 5d0c5750

b/hw/usb.h
240 240

  
241 241
/* usb-linux.c */
242 242
USBDevice *usb_host_device_open(const char *devname);
243
int usb_host_device_close(const char *devname);
243 244
void usb_host_info(void);
244 245

  
245 246
/* usb-hid.c */
b/usb-linux.c
5 5
 *
6 6
 * Copyright (c) 2008 Max Krasnyansky
7 7
 *      Support for host device auto connect & disconnect
8
 *      Magor rewrite to support fully async operation
8
 *      Major rewrite to support fully async operation
9 9
 *
10 10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 11
 * of this software and associated documentation files (the "Software"), to deal
......
951 951
    return NULL;
952 952
}
953 953

  
954
static int usb_host_auto_add(const char *spec);
955
static int usb_host_auto_del(const char *spec);
956

  
954 957
USBDevice *usb_host_device_open(const char *devname)
955 958
{
956 959
    int bus_num, addr;
957 960
    char product_name[PRODUCT_NAME_SZ];
958 961

  
959
    if (usb_host_find_device(&bus_num, &addr,
960
                             product_name, sizeof(product_name),
961
                             devname) < 0)
962
    if (strstr(devname, "auto:")) {
963
        usb_host_auto_add(devname);
962 964
        return NULL;
965
    }
963 966

  
964
     if (hostdev_find(bus_num, addr)) {
965
        term_printf("husb: host usb device %d.%d is already open\n", bus_num, addr);
967
    if (usb_host_find_device(&bus_num, &addr, product_name, sizeof(product_name),
968
                             devname) < 0)
966 969
        return NULL;
967
     }
970

  
971
    if (hostdev_find(bus_num, addr)) {
972
       term_printf("husb: host usb device %d.%d is already open\n", bus_num, addr);
973
       return NULL;
974
    }
968 975

  
969 976
    return usb_host_device_open_addr(bus_num, addr, product_name);
970 977
}
978

  
979
int usb_host_device_close(const char *devname)
980
{
981
    char product_name[PRODUCT_NAME_SZ];
982
    int bus_num, addr;
983
    USBHostDevice *s;
984

  
985
    if (strstr(devname, "auto:"))
986
        return usb_host_auto_del(devname);
987

  
988
    if (usb_host_find_device(&bus_num, &addr, product_name, sizeof(product_name),
989
                             devname) < 0)
990
        return -1;
991
 
992
    s = hostdev_find(bus_num, addr);
993
    if (s) {
994
        usb_device_del_addr(0, s->dev.addr);
995
        return 0;
996
    }
997

  
998
    return -1;
999
}
971 1000
 
972 1001
static int get_tag_value(char *buf, int buf_size,
973 1002
                         const char *str, const char *tag,
......
1126 1155
}
1127 1156

  
1128 1157
/*
1129
 * Add autoconnect filter
1130
 * -1 means 'any' (device, vendor, etc)
1158
 * Autoconnect filter
1159
 * Format:
1160
 *    auto:bus:dev[:vid:pid]
1161
 *    auto:bus.dev[:vid:pid]
1162
 *
1163
 *    bus  - bus number    (dec, * means any)
1164
 *    dev  - device number (dec, * means any)
1165
 *    vid  - vendor id     (hex, * means any)
1166
 *    pid  - product id    (hex, * means any)
1167
 *
1168
 *    See 'lsusb' output.
1131 1169
 */
1132
static void usb_host_auto_add(int bus_num, int addr, int vendor_id, int product_id)
1170
static int parse_filter(const char *spec, struct USBAutoFilter *f)
1133 1171
{
1134
    struct USBAutoFilter *f = qemu_mallocz(sizeof(*f));
1172
    enum { BUS, DEV, VID, PID, DONE };
1173
    const char *p = spec;
1174
    int i;
1175

  
1176
    f->bus_num    = -1;
1177
    f->addr       = -1;
1178
    f->vendor_id  = -1;
1179
    f->product_id = -1;
1180

  
1181
    for (i = BUS; i < DONE; i++) {
1182
    	p = strpbrk(p, ":.");
1183
    	if (!p) break;
1184
        p++;
1185
 
1186
    	if (*p == '*')
1187
            continue;
1188

  
1189
        switch(i) {
1190
        case BUS: f->bus_num = strtol(p, NULL, 10);    break;
1191
        case DEV: f->addr    = strtol(p, NULL, 10);    break;
1192
        case VID: f->vendor_id  = strtol(p, NULL, 16); break;
1193
        case PID: f->product_id = strtol(p, NULL, 16); break;
1194
        }
1195
    }
1196

  
1197
    if (i < DEV) {
1198
        fprintf(stderr, "husb: invalid auto filter spec %s\n", spec);
1199
        return -1;
1200
    }
1201

  
1202
    return 0;
1203
}
1204

  
1205
static int match_filter(const struct USBAutoFilter *f1, 
1206
                        const struct USBAutoFilter *f2)
1207
{
1208
    return f1->bus_num    == f2->bus_num &&
1209
           f1->addr       == f2->addr &&
1210
           f1->vendor_id  == f2->vendor_id &&
1211
           f1->product_id == f2->product_id;
1212
}
1213

  
1214
static int usb_host_auto_add(const char *spec)
1215
{
1216
    struct USBAutoFilter filter, *f;
1217

  
1218
    if (parse_filter(spec, &filter) < 0)
1219
        return -1;
1220

  
1221
    f = qemu_mallocz(sizeof(*f));
1135 1222
    if (!f) {
1136 1223
        fprintf(stderr, "husb: failed to allocate auto filter\n");
1137
        return;
1224
        return -1;
1138 1225
    }
1139 1226

  
1140
    f->bus_num = bus_num;
1141
    f->addr    = addr;
1142
    f->vendor_id  = vendor_id;
1143
    f->product_id = product_id;
1227
    *f = filter; 
1144 1228

  
1145 1229
    if (!usb_auto_filter) {
1146 1230
        /*
......
1153 1237
	if (!usb_auto_timer) {
1154 1238
            fprintf(stderr, "husb: failed to allocate auto scan timer\n");
1155 1239
            qemu_free(f);
1156
            return;
1240
            return -1;
1157 1241
        }
1158 1242

  
1159 1243
        /* Check for new devices every two seconds */
1160 1244
        qemu_mod_timer(usb_auto_timer, qemu_get_clock(rt_clock) + 2000);
1161 1245
    }
1162 1246

  
1163
    dprintf("husb: auto filter: bus_num %d addr %d vid %d pid %d\n",
1164
	bus_num, addr, vendor_id, product_id);
1247
    dprintf("husb: added auto filter: bus_num %d addr %d vid %d pid %d\n",
1248
	f->bus_num, f->addr, f->vendor_id, f->product_id);
1165 1249

  
1166 1250
    f->next = usb_auto_filter;
1167 1251
    usb_auto_filter = f;
1252

  
1253
    return 0;
1254
}
1255

  
1256
static int usb_host_auto_del(const char *spec)
1257
{
1258
    struct USBAutoFilter *pf = usb_auto_filter;
1259
    struct USBAutoFilter **prev = &usb_auto_filter;
1260
    struct USBAutoFilter filter;
1261

  
1262
    if (parse_filter(spec, &filter) < 0)
1263
        return -1;
1264

  
1265
    while (pf) {
1266
        if (match_filter(pf, &filter)) {
1267
            dprintf("husb: removed auto filter: bus_num %d addr %d vid %d pid %d\n",
1268
	             pf->bus_num, pf->addr, pf->vendor_id, pf->product_id);
1269

  
1270
            *prev = pf->next;
1271

  
1272
	    if (!usb_auto_filter) {
1273
                /* No more filters. Stop scanning. */
1274
                qemu_del_timer(usb_auto_timer);
1275
                qemu_free_timer(usb_auto_timer);
1276
            }
1277

  
1278
            return 0;
1279
        }
1280

  
1281
        prev = &pf->next;
1282
        pf   = pf->next;
1283
    }
1284

  
1285
    return -1;
1168 1286
}
1169 1287

  
1170 1288
typedef struct FindDeviceState {
......
1208 1326
    p = strchr(devname, '.');
1209 1327
    if (p) {
1210 1328
        *pbus_num = strtoul(devname, NULL, 0);
1211

  
1212
        if (*(p + 1) == '*') {
1213
            usb_host_auto_add(*pbus_num, -1, -1, -1);
1214
	    return -1;
1215
	}
1216

  
1217 1329
        *paddr = strtoul(p + 1, NULL, 0);
1218 1330
        fs.bus_num = *pbus_num;
1219 1331
        fs.addr = *paddr;
......
1222 1334
            pstrcpy(product_name, product_name_size, fs.product_name);
1223 1335
        return 0;
1224 1336
    }
1337

  
1225 1338
    p = strchr(devname, ':');
1226 1339
    if (p) {
1227 1340
        fs.vendor_id = strtoul(devname, NULL, 16);
1228

  
1229
        if (*(p + 1) == '*') {
1230
            usb_host_auto_add(-1, -1, fs.vendor_id, -1);
1231
	    return -1;
1232
	}
1233

  
1234 1341
        fs.product_id = strtoul(p + 1, NULL, 16);
1235 1342
        ret = usb_host_scan(&fs, usb_host_find_device_scan);
1236 1343
        if (ret) {
......
1324 1431
    return 0;
1325 1432
}
1326 1433

  
1434
static void dec2str(int val, char *str)
1435
{
1436
    if (val == -1)
1437
        strcpy(str, "*");
1438
    else
1439
        sprintf(str, "%d", val); 
1440
}
1441

  
1442
static void hex2str(int val, char *str)
1443
{
1444
    if (val == -1)
1445
        strcpy(str, "*");
1446
    else
1447
        sprintf(str, "%x", val);
1448
}
1449

  
1327 1450
void usb_host_info(void)
1328 1451
{
1452
    struct USBAutoFilter *f;
1453

  
1329 1454
    usb_host_scan(NULL, usb_host_info_device);
1455

  
1456
    if (usb_auto_filter)
1457
        term_printf("  Auto filters:\n");
1458
    for (f = usb_auto_filter; f; f = f->next) {
1459
        char bus[10], addr[10], vid[10], pid[10];
1460
        dec2str(f->bus_num, bus);
1461
        dec2str(f->addr, addr);
1462
        hex2str(f->vendor_id, vid);
1463
        hex2str(f->product_id, pid);
1464
    	term_printf("    Device %s.%s ID %s:%s\n", bus, addr, vid, pid);
1465
    }
1330 1466
}
1331 1467

  
1332 1468
#else
......
1344 1480
    return NULL;
1345 1481
}
1346 1482

  
1483
int usb_host_device_close(const char *devname)
1484
{
1485
    return 0;
1486
}
1487

  
1347 1488
#endif
b/vl.c
5866 5866
    int bus_num, addr;
5867 5867
    const char *p;
5868 5868

  
5869
    if (strstart(devname, "host:", &p))
5870
        return usb_host_device_close(p);
5871

  
5869 5872
    if (!used_usb_ports)
5870 5873
        return -1;
5871 5874

  

Also available in: Unified diff