X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=main.c;h=fca2a37cacd72f7b4d7e7bc83a1988e503e532d9;hb=925b9857173f5086c4afeed0a09fa29496b504ae;hp=a837ddcddfee77353f3ff0aac2fdcd2056f2f45c;hpb=63039a20e96c80ab20afca56d14d77af19eab270;p=project%2Fusbmode.git diff --git a/main.c b/main.c index a837ddc..fca2a37 100644 --- a/main.c +++ b/main.c @@ -1,11 +1,12 @@ #include #include #include +#include #include #include #include -#include +#include "switch.h" #define DEFAULT_CONFIG "/etc/usb-mode.json" @@ -14,21 +15,13 @@ struct device { struct blob_attr *data; }; -struct usbdev_data { - struct libusb_device_descriptor desc; - libusb_device_handle *devh; - struct blob_attr *info; - - char idstr[10]; - char mfg[128], prod[128], serial[128]; -}; - 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; +struct blob_attr **messages = NULL; +int *message_len; +int n_messages = 0; static struct avl_tree devices; @@ -36,6 +29,67 @@ static 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 { @@ -62,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) + 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++] = cur; + } blobmsg_for_each_attr(cur, tb[CONF_DEVICES], rem) { dev = calloc(1, sizeof(*dev)); @@ -129,6 +193,50 @@ 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; + + 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; @@ -163,9 +271,15 @@ 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); + + if (data.config) + libusb_free_config_descriptor(data.config); + libusb_close(data.devh); } } @@ -176,124 +290,6 @@ static void handle_list(struct usbdev_data *data) data->idstr, data->mfg, data->prod, data->serial); } -enum { - DATA_MODE, - DATA_MSG, - DATA_MSG2, - DATA_MSG3, - __DATA_MAX -}; - -static void handle_generic(struct usbdev_data *data, struct blob_attr **tb) -{ - fprintf(stderr, "Do generic switch!\n"); -} - -static void handle_huawei(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -static void handle_sierra(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -static void handle_sony(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -static void handle_qisda(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -static void handle_gct(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -static void handle_kobil(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -static void handle_sequans(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -static void handle_mobile_action(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -static void handle_cisco(struct usbdev_data *data, struct blob_attr **tb) -{ - /* TODO */ -} - -enum { - MODE_GENERIC, - MODE_HUAWEI, - MODE_SIERRA, - MODE_SONY, - MODE_QISDA, - MODE_GCT, - MODE_KOBIL, - MODE_SEQUANS, - MODE_MOBILE_ACTION, - MODE_CISCO, - __MODE_MAX -}; - -static const struct { - const char *name; - void (*cb)(struct usbdev_data *data, struct blob_attr **tb); -} modeswitch_cb[__MODE_MAX] = { - [MODE_GENERIC] = { "Generic", handle_generic }, - [MODE_HUAWEI] = { "Huawei", handle_huawei }, - [MODE_SIERRA] = { "Sierra", handle_sierra }, - [MODE_SONY] = { "Sony", handle_sony }, - [MODE_QISDA] = { "Qisda", handle_qisda }, - [MODE_GCT] = { "GCT", handle_gct }, - [MODE_KOBIL] = { "Kobil", handle_kobil }, - [MODE_SEQUANS] = { "Sequans", handle_sequans }, - [MODE_MOBILE_ACTION] = { "MobileAction", handle_mobile_action }, - [MODE_CISCO] = { "Cisco", handle_cisco }, -}; - -static void handle_switch(struct usbdev_data *data) -{ - static const struct blobmsg_policy data_policy[__DATA_MAX] = { - [DATA_MODE] = { .name = "mode", .type = BLOBMSG_TYPE_STRING }, - [DATA_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_INT32 }, - [DATA_MSG2] = { .name = "msg2", .type = BLOBMSG_TYPE_INT32 }, - [DATA_MSG3] = { .name = "msg3", .type = BLOBMSG_TYPE_INT32 }, - }; - struct blob_attr *tb[__DATA_MAX]; - int mode = MODE_GENERIC; - - blobmsg_parse(data_policy, __DATA_MAX, tb, blobmsg_data(data->info), blobmsg_data_len(data->info)); - - if (tb[DATA_MODE]) { - const char *modestr; - int i; - - modestr = blobmsg_data(tb[DATA_MODE]); - for (i = 0; i < __MODE_MAX; i++) { - if (strcmp(modeswitch_cb[i].name, modestr) != 0) - continue; - - mode = i; - break; - } - } - - modeswitch_cb[mode].cb(data, tb); -} - int main(int argc, char **argv) { cmd_cb_t cb = NULL;