X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fusbmode.git;a=blobdiff_plain;f=main.c;h=6cfe3b22bea35ff4aaa96ba0797a1810b91babaa;hp=5f5c4ff05d9bcfefbcd6c793049c07f4ea3cbcb5;hb=d8dc33512453fa73264a1990b25496da6cfd2a4a;hpb=a9aa888729f2564c14b668b19c9433d07d2669b5 diff --git a/main.c b/main.c index 5f5c4ff..6cfe3b2 100644 --- a/main.c +++ b/main.c @@ -19,12 +19,13 @@ static int verbose = 0; static const char *config_file = DEFAULT_CONFIG; static struct blob_buf conf; -static struct blob_attr **messages; -static int n_messages; +char **messages = NULL; +int *message_len; +int n_messages = 0; static struct avl_tree devices; -static struct libusb_context *usb; +struct libusb_context *usb; static struct libusb_device **usbdevs; static int n_usbdevs; @@ -73,20 +74,20 @@ static int hexstr2bin(const char *hex, char *buffer, int len) return 0; } -static bool convert_message(struct blob_attr *attr) +static int convert_message(struct blob_attr *attr) { char *data; int len; - if (!attr) - return true; - data = blobmsg_data(attr); len = strlen(data); if (len % 2) - return false; + return -1; + + if (hexstr2bin(data, data, len / 2)) + return -1; - return !hexstr2bin(data, data, len / 2); + return len / 2; } static int parse_config(void) @@ -115,13 +116,18 @@ static int parse_config(void) n_messages++; messages = calloc(n_messages, sizeof(*messages)); + message_len = calloc(n_messages, sizeof(*message_len)); n_messages = 0; blobmsg_for_each_attr(cur, tb[CONF_MESSAGES], rem) { - if (!convert_message(cur)) { + int len = convert_message(cur); + + if (len < 0) { fprintf(stderr, "Invalid data in message %d\n", n_messages); return -1; } - messages[n_messages++] = cur; + + message_len[n_messages] = len; + messages[n_messages++] = blobmsg_data(cur); } blobmsg_for_each_attr(cur, tb[CONF_DEVICES], rem) { @@ -187,6 +193,51 @@ find_dev_data(struct usbdev_data *data, struct device *dev) return NULL; } +static void +parse_interface_config(libusb_device *dev, struct usbdev_data *data) +{ + struct libusb_config_descriptor *config; + const struct libusb_interface *iface; + const struct libusb_interface_descriptor *alt; + int i; + + data->interface = -1; + if (libusb_get_config_descriptor(dev, 0, &config)) + return; + + data->config = config; + if (!config->bNumInterfaces) + return; + + iface = &config->interface[0]; + if (!iface->num_altsetting) + return; + + alt = &iface->altsetting[0]; + data->interface = alt->bInterfaceNumber; + data->dev_class = alt->bInterfaceClass; + + for (i = 0; i < alt->bNumEndpoints; i++) { + const struct libusb_endpoint_descriptor *ep = &alt->endpoint[i]; + bool out = false; + + if (data->msg_endpoint && data->response_endpoint) + break; + + if ((ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != + LIBUSB_TRANSFER_TYPE_BULK) + continue; + + out = (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == + LIBUSB_ENDPOINT_OUT; + + if (!data->msg_endpoint && out) + data->msg_endpoint = ep->bEndpointAddress; + if (!data->response_endpoint && !out) + data->response_endpoint = ep->bEndpointAddress; + } +} + static void iterate_devs(cmd_cb_t cb) { struct usbdev_data data; @@ -211,6 +262,8 @@ static void iterate_devs(cmd_cb_t cb) if (libusb_open(usbdevs[i], &data.devh)) continue; + data.dev = usbdevs[i]; + libusb_get_string_descriptor_ascii( data.devh, data.desc.iManufacturer, (void *) data.mfg, sizeof(data.mfg)); @@ -221,10 +274,17 @@ static void iterate_devs(cmd_cb_t cb) data.devh, data.desc.iSerialNumber, (void *) data.serial, sizeof(data.serial)); + parse_interface_config(usbdevs[i], &data); + data.info = find_dev_data(&data, dev); if (data.info) cb(&data); - libusb_close(data.devh); + + if (data.config) + libusb_free_config_descriptor(data.config); + + if (data.devh) + libusb_close(data.devh); } }