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