+enum {
+ DATA_MODE,
+ DATA_MSG,
+ DATA_INTERFACE,
+ DATA_MSG_EP,
+ DATA_RES_EP,
+ DATA_RESPONSE,
+ DATA_RELEASE_DELAY,
+ DATA_CONFIG,
+ DATA_ALT,
+ __DATA_MAX
+};
+
+static void detach_driver(struct usbdev_data *data)
+{
+ libusb_detach_kernel_driver(data->devh, data->interface);
+}
+
+struct msg_entry {
+ char *data;
+ int len;
+};
+
+static int send_msg(struct usbdev_data *data, struct msg_entry *msg)
+{
+ int transferred;
+
+ return libusb_bulk_transfer(data->devh, data->msg_endpoint,
+ (void *) msg->data, msg->len,
+ &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 msg_entry *msg, int n_msg)
+{
+ int i, len;
+
+ libusb_claim_interface(data->devh, data->interface);
+ libusb_clear_halt(data->devh, data->msg_endpoint);
+
+ for (i = 0; i < n_msg; i++) {
+ if (send_msg(data, &msg[i])) {
+ fprintf(stderr, "Failed to send switch message\n");
+ continue;
+ }
+
+ if (!data->need_response)
+ continue;
+
+ if (!memcmp(msg[i].data, "\x55\x53\x42\x43", 4))
+ len = 13;
+ else
+ len = msg[i].len;
+
+ 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 send_config_messages(struct usbdev_data *data, struct blob_attr *attr)
+{
+ struct blob_attr *cur;
+ int rem, n_msg = 0;
+ struct msg_entry *msg;
+
+ blobmsg_for_each_attr(cur, attr, rem)
+ n_msg++;
+
+ msg = alloca(n_msg * sizeof(*msg));
+ n_msg = 0;
+ blobmsg_for_each_attr(cur, attr, rem) {
+ int msg_nr;
+
+ if (blobmsg_type(cur) != BLOBMSG_TYPE_INT32) {
+ fprintf(stderr, "Invalid data in message list\n");
+ return;
+ }
+
+ msg_nr = blobmsg_get_u32(cur);
+ if (msg_nr >= n_messages) {
+ fprintf(stderr, "Message index out of range!\n");
+ return;
+ }
+
+ msg[n_msg].data = messages[msg_nr];
+ msg[n_msg++].len = message_len[msg_nr];
+ }
+
+ send_messages(data, msg, n_msg);
+}
+