X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fusbmode.git;a=blobdiff_plain;f=main.c;h=6cfe3b22bea35ff4aaa96ba0797a1810b91babaa;hp=c00b5b96de1ed9c2bba9e0b0cb282e858cd4efbc;hb=d8dc33512453fa73264a1990b25496da6cfd2a4a;hpb=7fdfb969d521f5198345b675081aa220743de909 diff --git a/main.c b/main.c index c00b5b9..6cfe3b2 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -18,15 +19,77 @@ 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; +static int hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + + c = toupper(c); + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return -1; +} + +static int hex2byte(const char *hex) +{ + int a, b; + + a = hex2num(*hex++); + if (a < 0) + return -1; + + b = hex2num(*hex++); + if (b < 0) + return -1; + + return (a << 4) | b; +} + +static int hexstr2bin(const char *hex, char *buffer, int len) +{ + const char *ipos = hex; + char *opos = buffer; + int i, a; + + for (i = 0; i < len; i++) { + a = hex2byte(ipos); + if (a < 0) + return -1; + + *opos++ = a; + ipos += 2; + } + + return 0; +} + +static int convert_message(struct blob_attr *attr) +{ + char *data; + int len; + + data = blobmsg_data(attr); + len = strlen(data); + if (len % 2) + return -1; + + if (hexstr2bin(data, data, len / 2)) + return -1; + + return len / 2; +} + static int parse_config(void) { enum { @@ -53,9 +116,19 @@ 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) - messages[n_messages++] = cur; + blobmsg_for_each_attr(cur, tb[CONF_MESSAGES], rem) { + int len = convert_message(cur); + + if (len < 0) { + fprintf(stderr, "Invalid data in message %d\n", n_messages); + return -1; + } + + message_len[n_messages] = len; + messages[n_messages++] = blobmsg_data(cur); + } blobmsg_for_each_attr(cur, tb[CONF_DEVICES], rem) { dev = calloc(1, sizeof(*dev)); @@ -120,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; @@ -144,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)); @@ -154,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); } }