3 * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #define __STDC_FORMAT_MACROS
18 #include <sys/types.h>
28 #include <libubox/utils.h>
29 #include <libubox/uloop.h>
33 #include "data/mbim-service-basic-connect.h"
38 struct mbim_handler *current_handler;
39 static uint8_t uuid_context_type_internet[16] = { 0x7E, 0x5E, 0x2A, 0x7E, 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E };
44 mbim_device_caps_response(void *buffer, int len)
46 struct mbim_basic_connect_device_caps_r *caps = (struct mbim_basic_connect_device_caps_r *) buffer;
47 char *deviceid, *firmwareinfo, *hardwareinfo;
49 if (len < sizeof(struct mbim_basic_connect_device_caps_r)) {
50 fprintf(stderr, "message not long enough\n");
54 deviceid = mbim_get_string(&caps->deviceid, buffer);
55 firmwareinfo = mbim_get_string(&caps->firmwareinfo, buffer);
56 hardwareinfo = mbim_get_string(&caps->hardwareinfo, buffer);
58 printf(" devicetype: %04X - %s\n", le32toh(caps->devicetype),
59 mbim_enum_string(mbim_device_type_values, le32toh(caps->devicetype)));
60 printf(" cellularclass: %04X\n", le32toh(caps->cellularclass));
61 printf(" voiceclass: %04X - %s\n", le32toh(caps->voiceclass),
62 mbim_enum_string(mbim_voice_class_values, le32toh(caps->voiceclass)));
63 printf(" simclass: %04X\n", le32toh(caps->simclass));
64 printf(" dataclass: %04X\n", le32toh(caps->dataclass));
65 printf(" smscaps: %04X\n", le32toh(caps->smscaps));
66 printf(" controlcaps: %04X\n", le32toh(caps->controlcaps));
67 printf(" maxsessions: %04X\n", le32toh(caps->maxsessions));
68 printf(" deviceid: %s\n", deviceid);
69 printf(" firmwareinfo: %s\n", firmwareinfo);
70 printf(" hardwareinfo: %s\n", hardwareinfo);
76 mbim_pin_state_response(void *buffer, int len)
78 struct mbim_basic_connect_pin_r *pin = (struct mbim_basic_connect_pin_r *) buffer;
80 if (len < sizeof(struct mbim_basic_connect_pin_r)) {
81 fprintf(stderr, "message not long enough\n");
85 if (le32toh(pin->pinstate) != MBIM_PIN_STATE_UNLOCKED) {
86 fprintf(stderr, "required pin: %d - %s\n",
87 le32toh(pin->pintype), mbim_enum_string(mbim_pin_type_values, le32toh(pin->pintype)));
88 fprintf(stderr, "remaining attempts: %d\n", le32toh(pin->remainingattempts));
89 return le32toh(pin->pintype);
92 fprintf(stderr, "Pin Unlocked\n");
98 mbim_registration_response(void *buffer, int len)
100 struct mbim_basic_connect_register_state_r *state = (struct mbim_basic_connect_register_state_r *) buffer;
101 char *provider_id, *provider_name, *roamingtext;
103 if (len < sizeof(struct mbim_basic_connect_register_state_r)) {
104 fprintf(stderr, "message not long enough\n");
108 provider_id = mbim_get_string(&state->providerid, buffer);
109 provider_name = mbim_get_string(&state->providername, buffer);
110 roamingtext = mbim_get_string(&state->roamingtext, buffer);
112 printf(" nwerror: %04X - %s\n", le32toh(state->nwerror),
113 mbim_enum_string(mbim_nw_error_values, le32toh(state->nwerror)));
114 printf(" registerstate: %04X - %s\n", le32toh(state->registerstate),
115 mbim_enum_string(mbim_register_state_values, le32toh(state->registerstate)));
116 printf(" registermode: %04X - %s\n", le32toh(state->registermode),
117 mbim_enum_string(mbim_register_mode_values, le32toh(state->registermode)));
118 printf(" availabledataclasses: %04X - %s\n", le32toh(state->availabledataclasses),
119 mbim_enum_string(mbim_data_class_values, le32toh(state->availabledataclasses)));
120 printf(" currentcellularclass: %04X - %s\n", le32toh(state->currentcellularclass),
121 mbim_enum_string(mbim_cellular_class_values, le32toh(state->currentcellularclass)));
122 printf(" provider_id: %s\n", provider_id);
123 printf(" provider_name: %s\n", provider_name);
124 printf(" roamingtext: %s\n", roamingtext);
126 if (le32toh(state->registerstate) == MBIM_REGISTER_STATE_HOME)
129 return le32toh(state->registerstate);
133 mbim_subscriber_response(void *buffer, int len)
135 struct mbim_basic_connect_subscriber_ready_status_r *state = (struct mbim_basic_connect_subscriber_ready_status_r *) buffer;
136 char *subscriberid, *simiccid;
139 if (len < sizeof(struct mbim_basic_connect_subscriber_ready_status_r)) {
140 fprintf(stderr, "message not long enough\n");
144 subscriberid = mbim_get_string(&state->subscriberid, buffer);
145 simiccid = mbim_get_string(&state->simiccid, buffer);
147 printf(" readystate: %04X - %s\n", le32toh(state->readystate),
148 mbim_enum_string(mbim_subscriber_ready_state_values, le32toh(state->readystate)));
149 printf(" simiccid: %s\n", simiccid);
150 printf(" subscriberid: %s\n", subscriberid);
151 if (le32toh(state->readyinfo) & MBIM_READY_INFO_FLAG_PROTECT_UNIQUE_ID)
152 printf(" dont display subscriberID: 1\n");
153 for (nr = 0; nr < le32toh(state->telephonenumberscount); nr++) {
154 struct mbim_string *str = buffer + le32toh(state->telephonenumbers) + (nr * sizeof(struct mbim_string));
155 char *number = mbim_get_string(str, buffer);
156 printf(" number: %s\n", number);
159 if (MBIM_SUBSCRIBER_READY_STATE_INITIALIZED == le32toh(state->readystate))
162 return le32toh(state->readystate);
166 mbim_attach_response(void *buffer, int len)
168 struct mbim_basic_connect_packet_service_r *ps = (struct mbim_basic_connect_packet_service_r *) buffer;
170 if (len < sizeof(struct mbim_basic_connect_packet_service_r)) {
171 fprintf(stderr, "message not long enough\n");
175 printf(" nwerror: %04X - %s\n", le32toh(ps->nwerror),
176 mbim_enum_string(mbim_nw_error_values, le32toh(ps->nwerror)));
177 printf(" packetservicestate: %04X - %s\n", le32toh(ps->packetservicestate),
178 mbim_enum_string(mbim_packet_service_state_values, le32toh(ps->packetservicestate)));
179 printf(" uplinkspeed: %"PRIu64"\n", le64toh(ps->uplinkspeed));
180 printf(" downlinkspeed: %"PRIu64"\n", le64toh(ps->downlinkspeed));
182 if (MBIM_PACKET_SERVICE_STATE_ATTACHED == le32toh(ps->packetservicestate))
185 return le32toh(ps->packetservicestate);
189 mbim_connect_response(void *buffer, int len)
191 struct mbim_basic_connect_connect_r *c = (struct mbim_basic_connect_connect_r *) buffer;
193 if (len < sizeof(struct mbim_basic_connect_connect_r)) {
194 fprintf(stderr, "message not long enough\n");
198 printf(" sessionid: %d\n", le32toh(c->sessionid));
199 printf(" activationstate: %04X - %s\n", le32toh(c->activationstate),
200 mbim_enum_string(mbim_activation_state_values, le32toh(c->activationstate)));
201 printf(" voicecallstate: %04X - %s\n", le32toh(c->voicecallstate),
202 mbim_enum_string(mbim_voice_call_state_values, le32toh(c->voicecallstate)));
203 printf(" nwerror: %04X - %s\n", le32toh(c->nwerror),
204 mbim_enum_string(mbim_nw_error_values, le32toh(c->nwerror)));
205 printf(" iptype: %04X - %s\n", le32toh(c->iptype),
206 mbim_enum_string(mbim_context_ip_type_values, le32toh(c->iptype)));
208 if (MBIM_ACTIVATION_STATE_ACTIVATED == le32toh(c->activationstate))
211 return le32toh(c->activationstate);
215 mbim_config_response(void *buffer, int len)
217 struct mbim_basic_connect_ip_configuration_r *ip = (struct mbim_basic_connect_ip_configuration_r *) buffer;
221 if (len < sizeof(struct mbim_basic_connect_ip_configuration_r)) {
222 fprintf(stderr, "message not long enough\n");
226 if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS)
227 for (i = 0; i < le32toh(ip->ipv4addresscount); i++) {
228 mbim_get_ipv4(buffer, ipv4, ip->ipv4address + (i * 4));
229 printf(" ipv4address: %s\n", ipv4);
231 if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS) {
232 mbim_get_ipv4(buffer, ipv4, ip->ipv4gateway);
233 printf(" ipv4gateway: %s\n", ipv4);
235 if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)
236 printf(" ipv4mtu: %d\n", le32toh(ip->ipv4mtu));
237 if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS)
238 for (i = 0; i < le32toh(ip->ipv4dnsservercount); i++) {
239 mbim_get_ipv4(buffer, ipv4, ip->ipv4dnsserver + (i * 4));
240 printf(" ipv4dnsserver: %s\n", ipv4);
243 printf(" ipv6configurationavailable: %04X\n", le32toh(ip->ipv6configurationavailable));
249 mbim_device_caps_request(void)
251 mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_DEVICE_CAPS, 0);
253 return mbim_send_command_msg();
257 mbim_pin_state_request(void)
259 mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_PIN, 0);
261 return mbim_send_command_msg();
265 mbim_registration_request(void)
267 mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_REGISTER_STATE, 0);
269 return mbim_send_command_msg();
273 mbim_subscriber_request(void)
275 mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_SUBSCRIBER_READY_STATUS, 0);
277 return mbim_send_command_msg();
281 _mbim_attach_request(int action)
283 struct mbim_basic_connect_packet_service_s *ps =
284 (struct mbim_basic_connect_packet_service_s *) mbim_setup_command_msg(basic_connect,
285 MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_PACKET_SERVICE,
286 sizeof(struct mbim_basic_connect_packet_service_s));
288 ps->packetserviceaction = htole32(action);
290 return mbim_send_command_msg();
294 mbim_attach_request(void)
296 return _mbim_attach_request(MBIM_PACKET_SERVICE_ACTION_ATTACH);
300 mbim_detach_request(void)
302 return _mbim_attach_request(MBIM_PACKET_SERVICE_ACTION_DETACH);
306 mbim_connect_request(void)
308 struct mbim_basic_connect_connect_s *c =
309 (struct mbim_basic_connect_connect_s *) mbim_setup_command_msg(basic_connect,
310 MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_CONNECT,
311 sizeof(struct mbim_basic_connect_connect_s));
313 c->activationcommand = htole32(MBIM_ACTIVATION_COMMAND_ACTIVATE);
314 c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_DEFAULT);
315 memcpy(c->contexttype, uuid_context_type_internet, 16);
317 mbim_encode_string(&c->accessstring, *_argv);
319 return mbim_send_command_msg();
323 mbim_disconnect_request(void)
325 struct mbim_basic_connect_connect_s *c =
326 (struct mbim_basic_connect_connect_s *) mbim_setup_command_msg(basic_connect,
327 MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_CONNECT,
328 sizeof(struct mbim_basic_connect_connect_s));
330 c->activationcommand = htole32(MBIM_ACTIVATION_COMMAND_DEACTIVATE);
331 memcpy(c->contexttype, uuid_context_type_internet, 16);
335 return mbim_send_command_msg();
339 mbim_pin_unlock_request(void)
341 struct mbim_basic_connect_pin_s *p =
342 (struct mbim_basic_connect_pin_s *) mbim_setup_command_msg(basic_connect,
343 MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_PIN,
344 sizeof(struct mbim_basic_connect_pin_s));
346 p->pintype = htole32(MBIM_PIN_TYPE_PIN1);
347 p->pinoperation = htole32(MBIM_PIN_OPERATION_ENTER);
348 mbim_encode_string(&p->pin, _argv[0]);
350 return mbim_send_command_msg();
354 mbim_config_request(void)
356 mbim_setup_command_msg(basic_connect,
357 MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_IP_CONFIGURATION,
358 sizeof(struct mbim_basic_connect_ip_configuration_q));
360 return mbim_send_command_msg();
363 static struct mbim_handler handlers[] = {
364 { "caps", 0, mbim_device_caps_request, mbim_device_caps_response },
365 { "pinstate", 0, mbim_pin_state_request, mbim_pin_state_response },
366 { "unlock", 1, mbim_pin_unlock_request, mbim_pin_state_response },
367 { "registration", 0, mbim_registration_request, mbim_registration_response },
368 { "subscriber", 0, mbim_subscriber_request, mbim_subscriber_response },
369 { "attach", 0, mbim_attach_request, mbim_attach_response },
370 { "detach", 0, mbim_detach_request, mbim_attach_response },
371 { "connect", 0, mbim_connect_request, mbim_connect_response },
372 { "disconnect", 0, mbim_disconnect_request, mbim_connect_response },
373 { "config", 0, mbim_config_request, mbim_config_response },
379 fprintf(stderr, "Usage: mbim <caps|pinstate|unlock|connect|disconnect> [options]\n"
381 " -d <device> the device (/dev/cdc-wdmX)\n"
382 " -t <transaction> the transaction id\n"
389 main(int argc, char **argv)
391 char *cmd, *device = NULL;
392 int no_open = 0, ch, i;
394 while ((ch = getopt(argc, argv, "nvd:t:")) != -1) {
407 transaction_id = atoi(optarg);
414 if (!device || optind == argc)
420 _argc = argc - optind;
421 _argv = &argv[optind];
423 for (i = 0; i < ARRAY_SIZE(handlers); i++)
424 if (!strcmp(cmd, handlers[i].name))
425 current_handler = &handlers[i];
427 if (!current_handler || (optind + current_handler->argc > argc))
434 mbim_send_open_msg();
435 else if (current_handler->request() < 0)