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);