1fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling/*
2fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * Copyright (C) 2010 The Android Open Source Project
3fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling *
4fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * Licensed under the Apache License, Version 2.0 (the "License");
5fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * you may not use this file except in compliance with the License.
6fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * You may obtain a copy of the License at
7fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling *
8fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling *      http://www.apache.org/licenses/LICENSE-2.0
9fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling *
10fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * Unless required by applicable law or agreed to in writing, software
11fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * distributed under the License is distributed on an "AS IS" BASIS,
12fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * See the License for the specific language governing permissions and
14fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling * limitations under the License.
15fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling */
16fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
17bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling#include <endian.h>
18fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling#include <errno.h>
19fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling#include <stdio.h>
20fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling#include <stdint.h>
21fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling#include <string.h>
22fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
23fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling#include <usbhost/usbhost.h>
24fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
25bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic int verbose = 0;
26bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic char str_buff[4096];
27bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
28bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic const char *get_str(struct usb_device *dev, int id)
29bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling{
30bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    char *str = usb_device_get_string(dev, id);
31bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
32bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    if (id && str) {
33bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        strlcpy(str_buff, str, sizeof(str_buff));
34bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        free(str);
35bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    } else {
36bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        snprintf(str_buff, sizeof(str_buff), "%02x", id);
37bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    }
38bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
39bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    return str_buff;
40bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling}
41bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
42bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
43bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic void lsusb_parse_device_descriptor(struct usb_device *dev,
44bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling                                          struct usb_device_descriptor *desc)
45bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling{
46bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("  Device Descriptor\n");
47bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbcdUSB: %04x\n", letoh16(desc->bcdUSB));
48bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbDeviceClass: %02x\n", desc->bDeviceClass);
49bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbDeviceSubClass: %02x\n", desc->bDeviceSubClass);
50bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbDeviceProtocol: %02x\n", desc->bDeviceProtocol);
51bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbMaxPacketSize0: %02x\n", desc->bMaxPacketSize0);
52bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tidVendor: %04x\n", letoh16(desc->idVendor));
53bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tidProduct: %04x\n", letoh16(desc->idProduct));
54bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbcdDevice: %04x\n", letoh16(desc->bcdDevice));
55bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tiManufacturer: %s\n", get_str(dev, desc->iManufacturer));
56bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tiProduct: %s\n", get_str(dev, desc->iProduct));
57bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tiSerialNumber: %s\n", get_str(dev,desc->iSerialNumber));
58bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbNumConfiguration: %02x\n", desc->bNumConfigurations);
59bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\n");
60bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling}
61bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
62bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic void lsusb_parse_config_descriptor(struct usb_device *dev,
63bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling                                          struct usb_config_descriptor *desc)
64bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling{
65bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("  Config Descriptor\n");
66bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\twTotalLength: %04x\n", letoh16(desc->wTotalLength));
67bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbNumInterfaces: %02x\n", desc->bNumInterfaces);
68bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbConfigurationValue: %02x\n", desc->bConfigurationValue);
69bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tiConfiguration: %s\n", get_str(dev, desc->iConfiguration));
70bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbmAttributes: %02x\n", desc->bmAttributes);
71bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbMaxPower: %d mA\n", desc->bMaxPower * 2);
72bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\n");
73bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling}
74bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
75bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic void lsusb_parse_interface_descriptor(struct usb_device *dev,
76bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling                                             struct usb_interface_descriptor *desc)
77bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling{
78bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("  Interface Descriptor\n");
79bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbInterfaceNumber: %02x\n", desc->bInterfaceNumber);
80bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbAlternateSetting: %02x\n", desc->bAlternateSetting);
81bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbNumEndpoints: %02x\n", desc->bNumEndpoints);
82bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbInterfaceClass: %02x\n", desc->bInterfaceClass);
83bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbInterfaceSubClass: %02x\n", desc->bInterfaceSubClass);
84bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbInterfaceProtocol: %02x\n", desc->bInterfaceProtocol);
85bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tiInterface: %s\n", get_str(dev, desc->iInterface));
86bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\n");
87bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling}
88bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
89bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic void lsusb_parse_endpoint_descriptor(struct usb_device *dev,
90bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling                                            struct usb_endpoint_descriptor *desc)
91bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling{
92bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("  Endpoint Descriptor\n");
93bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbEndpointAddress: %02x\n", desc->bEndpointAddress);
94bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbmAttributes: %02x\n", desc->bmAttributes);
95bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\twMaxPacketSize: %02x\n", letoh16(desc->wMaxPacketSize));
96bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbInterval: %02x\n", desc->bInterval);
97bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbRefresh: %02x\n", desc->bRefresh);
98bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\tbSynchAddress: %02x\n", desc->bSynchAddress);
99bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\n");
100bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling}
101bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
102bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic void lsusb_dump_descriptor(struct usb_device *dev,
103bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling                                  struct usb_descriptor_header *desc)
104bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling{
105bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    int i;
106bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("  Descriptor type %02x\n", desc->bDescriptorType);
107bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
108bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    for (i = 0; i < desc->bLength; i++ ) {
109bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        if ((i % 16) == 0)
110bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling            printf("\t%02x:", i);
111bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        printf(" %02x", ((uint8_t *)desc)[i]);
112bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        if ((i % 16) == 15)
113bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling            printf("\n");
114bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    }
115bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
116bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    if ((i % 16) != 0)
117bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        printf("\n");
118bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    printf("\n");
119bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling}
120bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
121bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gillingstatic void lsusb_parse_descriptor(struct usb_device *dev,
122bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling                                   struct usb_descriptor_header *desc)
123bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling{
124bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    switch (desc->bDescriptorType) {
125bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    case USB_DT_DEVICE:
126bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        lsusb_parse_device_descriptor(dev, (struct usb_device_descriptor *) desc);
127bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        break;
128bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
129bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    case USB_DT_CONFIG:
130bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        lsusb_parse_config_descriptor(dev, (struct usb_config_descriptor *) desc);
131bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        break;
132bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
133bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    case USB_DT_INTERFACE:
134bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        lsusb_parse_interface_descriptor(dev, (struct usb_interface_descriptor *) desc);
135bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        break;
136bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
137bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    case USB_DT_ENDPOINT:
138bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        lsusb_parse_endpoint_descriptor(dev, (struct usb_endpoint_descriptor *) desc);
139bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        break;
140bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
141bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    default:
142bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        lsusb_dump_descriptor(dev, desc);
143bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
144bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        break;
145bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    }
146bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling}
147bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
148fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gillingstatic int lsusb_device_added(const char *dev_name, void *client_data)
149fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling{
150fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    struct usb_device *dev = usb_device_open(dev_name);
151fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
152fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    if (!dev) {
153fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling        fprintf(stderr, "can't open device %s: %s\n", dev_name, strerror(errno));
154fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling        return 0;
155fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    }
156fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
157bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    if (verbose) {
158bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        struct usb_descriptor_iter iter;
159bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        struct usb_descriptor_header *desc;
160bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
161bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        printf("%s:\n", dev_name);
162bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
163bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        usb_descriptor_iter_init(dev, &iter);
164bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
165bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        while ((desc = usb_descriptor_iter_next(&iter)) != NULL)
166bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling            lsusb_parse_descriptor(dev, desc);
167fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
168bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    } else {
169bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        uint16_t vid, pid;
170bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        char *mfg_name, *product_name, *serial;
171fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
172bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        vid = usb_device_get_vendor_id(dev);
173bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        pid = usb_device_get_product_id(dev);
174bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        mfg_name = usb_device_get_manufacturer_name(dev);
175bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        product_name = usb_device_get_product_name(dev);
176bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        serial = usb_device_get_serial(dev);
177bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
178bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        printf("%s: %04x:%04x %s %s %s\n", dev_name, vid, pid,
179bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling               mfg_name, product_name, serial);
180bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
181bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        free(mfg_name);
182bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        free(product_name);
183bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        free(serial);
184bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    }
185fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
186fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    usb_device_close(dev);
187fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
188fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    return 0;
189fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling}
190fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
191fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gillingstatic int lsusb_device_removed(const char *dev_name, void *client_data)
192fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling{
193fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    return 0;
194fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling}
195fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
196fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
197fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gillingstatic int lsusb_discovery_done(void *client_data)
198fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling{
199fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    return 1;
200fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling}
201fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
202fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
203fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
204fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gillingint lsusb_main(int argc, char **argv)
205fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling{
206bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    struct usb_host_context *ctx;
207bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
208bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    if (argc == 2 && !strcmp(argv[1], "-v"))
209bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling        verbose = 1;
210bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling
211bec29d4b48619bbbcf49421c78b3529c742e8506Erik Gilling    ctx = usb_host_init();
212fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    if (!ctx) {
213fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling        perror("usb_host_init:");
214fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling        return 1;
215fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    }
216fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
217fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    usb_host_run(ctx,
218fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling                 lsusb_device_added,
219fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling                 lsusb_device_removed,
220fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling                 lsusb_discovery_done,
221fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling                 NULL);
222fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
223fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    usb_host_cleanup(ctx);
224fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
225fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling    return 0;
226fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling}
227fd1e8553232aa6f3bfbb609158b24fa2e1c3d40bErik Gilling
228