15 static void detach_driver(struct usbdev_data *data)
17 libusb_detach_kernel_driver(data->devh, data->interface);
20 static int send_msg(struct usbdev_data *data, int msg)
24 return libusb_bulk_transfer(data->devh, data->msg_endpoint,
25 (void *) messages[msg], message_len[msg],
29 static int read_response(struct usbdev_data *data, int len)
37 ret = libusb_bulk_transfer(data->devh, data->response_endpoint,
38 buf, len, &transferred, 3000);
39 libusb_bulk_transfer(data->devh, data->response_endpoint,
40 buf, 13, &transferred, 100);
44 static void send_messages(struct usbdev_data *data, struct blob_attr *attr)
46 struct blob_attr *cur;
49 libusb_claim_interface(data->devh, data->interface);
50 libusb_clear_halt(data->devh, data->msg_endpoint);
52 blobmsg_for_each_attr(cur, attr, rem) {
55 if (blobmsg_type(cur) != BLOBMSG_TYPE_INT32) {
56 fprintf(stderr, "Invalid data in message list\n");
60 msg = blobmsg_get_u32(cur);
61 if (msg >= n_messages) {
62 fprintf(stderr, "Message index out of range!\n");
66 if (send_msg(data, msg)) {
67 fprintf(stderr, "Failed to send switch message\n");
71 if (!data->need_response)
74 if (!memcmp(messages[msg], "\x55\x53\x42\x43", 4))
77 len = message_len[msg];
79 if (read_response(data, len))
83 libusb_clear_halt(data->devh, data->msg_endpoint);
84 libusb_clear_halt(data->devh, data->response_endpoint);
88 if (data->release_delay)
89 usleep(data->release_delay * 1000);
91 libusb_release_interface(data->devh, data->interface);
95 static void handle_generic(struct usbdev_data *data, struct blob_attr **tb)
98 send_messages(data, tb[DATA_MSG]);
101 static void handle_huawei(struct usbdev_data *data, struct blob_attr **tb)
106 static void handle_sierra(struct usbdev_data *data, struct blob_attr **tb)
111 static void handle_sony(struct usbdev_data *data, struct blob_attr **tb)
116 static void handle_qisda(struct usbdev_data *data, struct blob_attr **tb)
121 static void handle_gct(struct usbdev_data *data, struct blob_attr **tb)
127 static void handle_kobil(struct usbdev_data *data, struct blob_attr **tb)
133 static void handle_sequans(struct usbdev_data *data, struct blob_attr **tb)
138 static void handle_mobile_action(struct usbdev_data *data, struct blob_attr **tb)
143 static void handle_cisco(struct usbdev_data *data, struct blob_attr **tb)
163 static const struct {
165 void (*cb)(struct usbdev_data *data, struct blob_attr **tb);
166 } modeswitch_cb[__MODE_MAX] = {
167 [MODE_GENERIC] = { "Generic", handle_generic },
168 [MODE_HUAWEI] = { "Huawei", handle_huawei },
169 [MODE_SIERRA] = { "Sierra", handle_sierra },
170 [MODE_SONY] = { "Sony", handle_sony },
171 [MODE_QISDA] = { "Qisda", handle_qisda },
172 [MODE_GCT] = { "GCT", handle_gct },
173 [MODE_KOBIL] = { "Kobil", handle_kobil },
174 [MODE_SEQUANS] = { "Sequans", handle_sequans },
175 [MODE_MOBILE_ACTION] = { "MobileAction", handle_mobile_action },
176 [MODE_CISCO] = { "Cisco", handle_cisco },
179 void handle_switch(struct usbdev_data *data)
181 static const struct blobmsg_policy data_policy[__DATA_MAX] = {
182 [DATA_MODE] = { .name = "mode", .type = BLOBMSG_TYPE_STRING },
183 [DATA_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_ARRAY },
184 [DATA_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_INT32 },
185 [DATA_MSG_EP] = { .name = "msg_endpoint", .type = BLOBMSG_TYPE_INT32 },
186 [DATA_RES_EP] = { .name = "response_endpoint", .type = BLOBMSG_TYPE_INT32 },
187 [DATA_RESPONSE] = { .name = "response", .type = BLOBMSG_TYPE_INT32 },
189 struct blob_attr *tb[__DATA_MAX];
190 int mode = MODE_GENERIC;
192 blobmsg_parse(data_policy, __DATA_MAX, tb, blobmsg_data(data->info), blobmsg_data_len(data->info));
194 if (tb[DATA_INTERFACE])
195 data->interface = blobmsg_get_u32(tb[DATA_INTERFACE]);
198 data->msg_endpoint = blobmsg_get_u32(tb[DATA_MSG_EP]);
201 data->response_endpoint = blobmsg_get_u32(tb[DATA_RES_EP]);
203 if (tb[DATA_RELEASE_DELAY])
204 data->release_delay = blobmsg_get_u32(tb[DATA_RELEASE_DELAY]);
206 if (tb[DATA_RESPONSE])
207 data->need_response = blobmsg_get_bool(tb[DATA_RESPONSE]);
213 modestr = blobmsg_data(tb[DATA_MODE]);
214 for (i = 0; i < __MODE_MAX; i++) {
215 if (strcmp(modeswitch_cb[i].name, modestr) != 0)
223 modeswitch_cb[mode].cb(data, tb);