From: Felix Fietkau Date: Thu, 30 May 2013 19:17:56 +0000 (+0200) Subject: implement generic switching X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fusbmode.git;a=commitdiff_plain;h=525e150432e84636c420e499008713f228a4f134 implement generic switching --- diff --git a/main.c b/main.c index fca2a37..5cf6a45 100644 --- a/main.c +++ b/main.c @@ -19,7 +19,7 @@ static int verbose = 0; static const char *config_file = DEFAULT_CONFIG; static struct blob_buf conf; -struct blob_attr **messages = NULL; +char **messages = NULL; int *message_len; int n_messages = 0; @@ -127,7 +127,7 @@ static int parse_config(void) } message_len[n_messages] = len; - messages[n_messages++] = cur; + messages[n_messages++] = blobmsg_data(cur); } blobmsg_for_each_attr(cur, tb[CONF_DEVICES], rem) { diff --git a/switch.c b/switch.c index 15933d4..ec5baa0 100644 --- a/switch.c +++ b/switch.c @@ -1,9 +1,14 @@ +#include #include "switch.h" enum { DATA_MODE, DATA_MSG, DATA_INTERFACE, + DATA_MSG_EP, + DATA_RES_EP, + DATA_RESPONSE, + DATA_RELEASE_DELAY, __DATA_MAX }; @@ -12,9 +17,85 @@ static void detach_driver(struct usbdev_data *data) libusb_detach_kernel_driver(data->devh, data->interface); } +static int send_msg(struct usbdev_data *data, int msg) +{ + int transferred; + + return libusb_bulk_transfer(data->devh, data->msg_endpoint, + (void *) messages[msg], message_len[msg], + &transferred, 3000); +} + +static int read_response(struct usbdev_data *data, int len) +{ + unsigned char *buf; + int ret, transferred; + + if (len < 13) + len = 13; + buf = alloca(len); + ret = libusb_bulk_transfer(data->devh, data->response_endpoint, + buf, len, &transferred, 3000); + libusb_bulk_transfer(data->devh, data->response_endpoint, + buf, 13, &transferred, 100); + return ret; +} + +static void send_messages(struct usbdev_data *data, struct blob_attr *attr) +{ + struct blob_attr *cur; + int rem; + + libusb_claim_interface(data->devh, data->interface); + libusb_clear_halt(data->devh, data->msg_endpoint); + + blobmsg_for_each_attr(cur, attr, rem) { + int msg, len; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_INT32) { + fprintf(stderr, "Invalid data in message list\n"); + return; + } + + msg = blobmsg_get_u32(cur); + if (msg >= n_messages) { + fprintf(stderr, "Message index out of range!\n"); + return; + } + + if (send_msg(data, msg)) { + fprintf(stderr, "Failed to send switch message\n"); + continue; + } + + if (!data->need_response) + continue; + + if (!memcmp(messages[msg], "\x55\x53\x42\x43", 4)) + len = 13; + else + len = message_len[msg]; + + if (read_response(data, len)) + return; + } + + libusb_clear_halt(data->devh, data->msg_endpoint); + libusb_clear_halt(data->devh, data->response_endpoint); + + usleep(200000); + + if (data->release_delay) + usleep(data->release_delay * 1000); + + libusb_release_interface(data->devh, data->interface); + return; +} + static void handle_generic(struct usbdev_data *data, struct blob_attr **tb) { detach_driver(data); + send_messages(data, tb[DATA_MSG]); } static void handle_huawei(struct usbdev_data *data, struct blob_attr **tb) @@ -101,6 +182,9 @@ void handle_switch(struct usbdev_data *data) [DATA_MODE] = { .name = "mode", .type = BLOBMSG_TYPE_STRING }, [DATA_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_ARRAY }, [DATA_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_INT32 }, + [DATA_MSG_EP] = { .name = "msg_endpoint", .type = BLOBMSG_TYPE_INT32 }, + [DATA_RES_EP] = { .name = "response_endpoint", .type = BLOBMSG_TYPE_INT32 }, + [DATA_RESPONSE] = { .name = "response", .type = BLOBMSG_TYPE_INT32 }, }; struct blob_attr *tb[__DATA_MAX]; int mode = MODE_GENERIC; @@ -110,6 +194,18 @@ void handle_switch(struct usbdev_data *data) if (tb[DATA_INTERFACE]) data->interface = blobmsg_get_u32(tb[DATA_INTERFACE]); + if (tb[DATA_MSG_EP]) + data->msg_endpoint = blobmsg_get_u32(tb[DATA_MSG_EP]); + + if (tb[DATA_RES_EP]) + data->response_endpoint = blobmsg_get_u32(tb[DATA_RES_EP]); + + if (tb[DATA_RELEASE_DELAY]) + data->release_delay = blobmsg_get_u32(tb[DATA_RELEASE_DELAY]); + + if (tb[DATA_RESPONSE]) + data->need_response = blobmsg_get_bool(tb[DATA_RESPONSE]); + if (tb[DATA_MODE]) { const char *modestr; int i; diff --git a/switch.h b/switch.h index 1c964db..441e6a3 100644 --- a/switch.h +++ b/switch.h @@ -12,13 +12,14 @@ struct usbdev_data { int interface; int msg_endpoint; int response_endpoint; + int release_delay; bool need_response; char idstr[10]; char mfg[128], prod[128], serial[128]; }; -extern struct blob_attr **messages; +extern char **messages; extern int *message_len; extern int n_messages;