17 static void detach_driver(struct usbdev_data *data)
19 libusb_detach_kernel_driver(data->devh, data->interface);
22 static int send_msg(struct usbdev_data *data, int msg)
26 return libusb_bulk_transfer(data->devh, data->msg_endpoint,
27 (void *) messages[msg], message_len[msg],
31 static int read_response(struct usbdev_data *data, int len)
39 ret = libusb_bulk_transfer(data->devh, data->response_endpoint,
40 buf, len, &transferred, 3000);
41 libusb_bulk_transfer(data->devh, data->response_endpoint,
42 buf, 13, &transferred, 100);
46 static void send_messages(struct usbdev_data *data, struct blob_attr *attr)
48 struct blob_attr *cur;
51 libusb_claim_interface(data->devh, data->interface);
52 libusb_clear_halt(data->devh, data->msg_endpoint);
54 blobmsg_for_each_attr(cur, attr, rem) {
57 if (blobmsg_type(cur) != BLOBMSG_TYPE_INT32) {
58 fprintf(stderr, "Invalid data in message list\n");
62 msg = blobmsg_get_u32(cur);
63 if (msg >= n_messages) {
64 fprintf(stderr, "Message index out of range!\n");
68 if (send_msg(data, msg)) {
69 fprintf(stderr, "Failed to send switch message\n");
73 if (!data->need_response)
76 if (!memcmp(messages[msg], "\x55\x53\x42\x43", 4))
79 len = message_len[msg];
81 if (read_response(data, len))
85 libusb_clear_halt(data->devh, data->msg_endpoint);
86 libusb_clear_halt(data->devh, data->response_endpoint);
90 if (data->release_delay)
91 usleep(data->release_delay * 1000);
93 libusb_release_interface(data->devh, data->interface);
97 static void handle_generic(struct usbdev_data *data, struct blob_attr **tb)
100 send_messages(data, tb[DATA_MSG]);
103 static void handle_huawei(struct usbdev_data *data, struct blob_attr **tb)
108 static void handle_sierra(struct usbdev_data *data, struct blob_attr **tb)
113 static void handle_sony(struct usbdev_data *data, struct blob_attr **tb)
118 static void handle_qisda(struct usbdev_data *data, struct blob_attr **tb)
123 static void handle_gct(struct usbdev_data *data, struct blob_attr **tb)
129 static void handle_kobil(struct usbdev_data *data, struct blob_attr **tb)
135 static void handle_sequans(struct usbdev_data *data, struct blob_attr **tb)
140 static void handle_mobile_action(struct usbdev_data *data, struct blob_attr **tb)
145 static void handle_cisco(struct usbdev_data *data, struct blob_attr **tb)
151 static void set_alt_setting(struct usbdev_data *data, int setting)
153 if (libusb_claim_interface(data->devh, data->interface))
156 libusb_set_interface_alt_setting(data->devh, data->interface, setting);
157 libusb_release_interface(data->devh, data->interface);
174 static const struct {
176 void (*cb)(struct usbdev_data *data, struct blob_attr **tb);
177 } modeswitch_cb[__MODE_MAX] = {
178 [MODE_GENERIC] = { "Generic", handle_generic },
179 [MODE_HUAWEI] = { "Huawei", handle_huawei },
180 [MODE_SIERRA] = { "Sierra", handle_sierra },
181 [MODE_SONY] = { "Sony", handle_sony },
182 [MODE_QISDA] = { "Qisda", handle_qisda },
183 [MODE_GCT] = { "GCT", handle_gct },
184 [MODE_KOBIL] = { "Kobil", handle_kobil },
185 [MODE_SEQUANS] = { "Sequans", handle_sequans },
186 [MODE_MOBILE_ACTION] = { "MobileAction", handle_mobile_action },
187 [MODE_CISCO] = { "Cisco", handle_cisco },
190 void handle_switch(struct usbdev_data *data)
192 static const struct blobmsg_policy data_policy[__DATA_MAX] = {
193 [DATA_MODE] = { .name = "mode", .type = BLOBMSG_TYPE_STRING },
194 [DATA_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_ARRAY },
195 [DATA_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_INT32 },
196 [DATA_MSG_EP] = { .name = "msg_endpoint", .type = BLOBMSG_TYPE_INT32 },
197 [DATA_RES_EP] = { .name = "response_endpoint", .type = BLOBMSG_TYPE_INT32 },
198 [DATA_RESPONSE] = { .name = "response", .type = BLOBMSG_TYPE_INT32 },
199 [DATA_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_INT32 },
200 [DATA_ALT] = { .name = "alt", .type = BLOBMSG_TYPE_INT32 },
202 struct blob_attr *tb[__DATA_MAX];
203 int mode = MODE_GENERIC;
205 blobmsg_parse(data_policy, __DATA_MAX, tb, blobmsg_data(data->info), blobmsg_data_len(data->info));
207 if (tb[DATA_INTERFACE])
208 data->interface = blobmsg_get_u32(tb[DATA_INTERFACE]);
211 data->msg_endpoint = blobmsg_get_u32(tb[DATA_MSG_EP]);
214 data->response_endpoint = blobmsg_get_u32(tb[DATA_RES_EP]);
216 if (tb[DATA_RELEASE_DELAY])
217 data->release_delay = blobmsg_get_u32(tb[DATA_RELEASE_DELAY]);
219 if (tb[DATA_RESPONSE])
220 data->need_response = blobmsg_get_bool(tb[DATA_RESPONSE]);
226 modestr = blobmsg_data(tb[DATA_MODE]);
227 for (i = 0; i < __MODE_MAX; i++) {
228 if (strcmp(modeswitch_cb[i].name, modestr) != 0)
236 modeswitch_cb[mode].cb(data, tb);
238 if (tb[DATA_CONFIG]) {
239 int config, config_new;
241 config_new = blobmsg_get_u32(tb[DATA_CONFIG]);
242 if (libusb_get_configuration(data->devh, &config) ||
243 config != config_new)
244 libusb_set_configuration(data->devh, config_new);
248 int new = blobmsg_get_u32(tb[DATA_ALT]);
249 set_alt_setting(data, new);