cli.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. /*
  2. * umbim
  3. * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
  4. *
  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
  8. *
  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.
  13. */
  14. #define __STDC_FORMAT_MACROS
  15. #include <inttypes.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <alloca.h>
  19. #include <fcntl.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <unistd.h>
  24. #include <ctype.h>
  25. #include <libubox/utils.h>
  26. #include <libubox/uloop.h>
  27. #include "mbim.h"
  28. #include "data/mbim-service-basic-connect.h"
  29. int return_code = -1;
  30. int verbose;
  31. struct mbim_handler *current_handler;
  32. static uint8_t uuid_context_type_internet[16] = { 0x7E, 0x5E, 0x2A, 0x7E, 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E };
  33. static int _argc;
  34. static char **_argv;
  35. static int
  36. mbim_device_caps_response(void *buffer, size_t len)
  37. {
  38. struct mbim_basic_connect_device_caps_r *caps = (struct mbim_basic_connect_device_caps_r *) buffer;
  39. char *deviceid, *firmwareinfo, *hardwareinfo;
  40. if (len < sizeof(struct mbim_basic_connect_device_caps_r)) {
  41. fprintf(stderr, "message not long enough\n");
  42. return -1;
  43. }
  44. deviceid = mbim_get_string(&caps->deviceid, buffer);
  45. firmwareinfo = mbim_get_string(&caps->firmwareinfo, buffer);
  46. hardwareinfo = mbim_get_string(&caps->hardwareinfo, buffer);
  47. printf(" devicetype: %04X - %s\n", le32toh(caps->devicetype),
  48. mbim_enum_string(mbim_device_type_values, le32toh(caps->devicetype)));
  49. printf(" cellularclass: %04X\n", le32toh(caps->cellularclass));
  50. printf(" voiceclass: %04X - %s\n", le32toh(caps->voiceclass),
  51. mbim_enum_string(mbim_voice_class_values, le32toh(caps->voiceclass)));
  52. printf(" simclass: %04X\n", le32toh(caps->simclass));
  53. printf(" dataclass: %04X\n", le32toh(caps->dataclass));
  54. printf(" smscaps: %04X\n", le32toh(caps->smscaps));
  55. printf(" controlcaps: %04X\n", le32toh(caps->controlcaps));
  56. printf(" maxsessions: %04X\n", le32toh(caps->maxsessions));
  57. printf(" deviceid: %s\n", deviceid);
  58. printf(" firmwareinfo: %s\n", firmwareinfo);
  59. printf(" hardwareinfo: %s\n", hardwareinfo);
  60. return 0;
  61. }
  62. static int
  63. mbim_pin_state_response(void *buffer, size_t len)
  64. {
  65. struct mbim_basic_connect_pin_r *pin = (struct mbim_basic_connect_pin_r *) buffer;
  66. if (len < sizeof(struct mbim_basic_connect_pin_r)) {
  67. fprintf(stderr, "message not long enough\n");
  68. return -1;
  69. }
  70. if (le32toh(pin->pinstate) != MBIM_PIN_STATE_UNLOCKED) {
  71. fprintf(stderr, "required pin: %d - %s\n",
  72. le32toh(pin->pintype), mbim_enum_string(mbim_pin_type_values, le32toh(pin->pintype)));
  73. fprintf(stderr, "remaining attempts: %d\n", le32toh(pin->remainingattempts));
  74. return le32toh(pin->pintype);
  75. }
  76. fprintf(stderr, "Pin Unlocked\n");
  77. return 0;
  78. }
  79. static int
  80. mbim_registration_response(void *buffer, size_t len)
  81. {
  82. struct mbim_basic_connect_register_state_r *state = (struct mbim_basic_connect_register_state_r *) buffer;
  83. char *provider_id, *provider_name, *roamingtext;
  84. if (len < sizeof(struct mbim_basic_connect_register_state_r)) {
  85. fprintf(stderr, "message not long enough\n");
  86. return -1;
  87. }
  88. provider_id = mbim_get_string(&state->providerid, buffer);
  89. provider_name = mbim_get_string(&state->providername, buffer);
  90. roamingtext = mbim_get_string(&state->roamingtext, buffer);
  91. printf(" nwerror: %04X - %s\n", le32toh(state->nwerror),
  92. mbim_enum_string(mbim_nw_error_values, le32toh(state->nwerror)));
  93. printf(" registerstate: %04X - %s\n", le32toh(state->registerstate),
  94. mbim_enum_string(mbim_register_state_values, le32toh(state->registerstate)));
  95. printf(" registermode: %04X - %s\n", le32toh(state->registermode),
  96. mbim_enum_string(mbim_register_mode_values, le32toh(state->registermode)));
  97. printf(" availabledataclasses: %04X - %s\n", le32toh(state->availabledataclasses),
  98. mbim_enum_string(mbim_data_class_values, le32toh(state->availabledataclasses)));
  99. printf(" currentcellularclass: %04X - %s\n", le32toh(state->currentcellularclass),
  100. mbim_enum_string(mbim_cellular_class_values, le32toh(state->currentcellularclass)));
  101. printf(" provider_id: %s\n", provider_id);
  102. printf(" provider_name: %s\n", provider_name);
  103. printf(" roamingtext: %s\n", roamingtext);
  104. if (le32toh(state->registerstate) == MBIM_REGISTER_STATE_HOME)
  105. return 0;
  106. return le32toh(state->registerstate);
  107. }
  108. static int
  109. mbim_subscriber_response(void *buffer, size_t len)
  110. {
  111. struct mbim_basic_connect_subscriber_ready_status_r *state = (struct mbim_basic_connect_subscriber_ready_status_r *) buffer;
  112. char *subscriberid, *simiccid;
  113. unsigned int nr;
  114. if (len < sizeof(struct mbim_basic_connect_subscriber_ready_status_r)) {
  115. fprintf(stderr, "message not long enough\n");
  116. return -1;
  117. }
  118. subscriberid = mbim_get_string(&state->subscriberid, buffer);
  119. simiccid = mbim_get_string(&state->simiccid, buffer);
  120. printf(" readystate: %04X - %s\n", le32toh(state->readystate),
  121. mbim_enum_string(mbim_subscriber_ready_state_values, le32toh(state->readystate)));
  122. printf(" simiccid: %s\n", simiccid);
  123. printf(" subscriberid: %s\n", subscriberid);
  124. if (le32toh(state->readyinfo) & MBIM_READY_INFO_FLAG_PROTECT_UNIQUE_ID)
  125. printf(" dont display subscriberID: 1\n");
  126. for (nr = 0; nr < le32toh(state->telephonenumberscount); nr++) {
  127. struct mbim_string *str = (void *)&state->telephonenumbers + (nr * sizeof(struct mbim_string));
  128. char *number = mbim_get_string(str, buffer);
  129. printf(" number: %s\n", number);
  130. }
  131. if (MBIM_SUBSCRIBER_READY_STATE_INITIALIZED == le32toh(state->readystate))
  132. return 0;
  133. return le32toh(state->readystate);
  134. }
  135. static int
  136. mbim_attach_response(void *buffer, size_t len)
  137. {
  138. struct mbim_basic_connect_packet_service_r *ps = (struct mbim_basic_connect_packet_service_r *) buffer;
  139. if (len < sizeof(struct mbim_basic_connect_packet_service_r)) {
  140. fprintf(stderr, "message not long enough\n");
  141. return -1;
  142. }
  143. printf(" nwerror: %04X - %s\n", le32toh(ps->nwerror),
  144. mbim_enum_string(mbim_nw_error_values, le32toh(ps->nwerror)));
  145. printf(" packetservicestate: %04X - %s\n", le32toh(ps->packetservicestate),
  146. mbim_enum_string(mbim_packet_service_state_values, le32toh(ps->packetservicestate)));
  147. printf(" uplinkspeed: %"PRIu64"\n", (uint64_t) le64toh(ps->uplinkspeed));
  148. printf(" downlinkspeed: %"PRIu64"\n", (uint64_t) le64toh(ps->downlinkspeed));
  149. if (MBIM_PACKET_SERVICE_STATE_ATTACHED == le32toh(ps->packetservicestate))
  150. return 0;
  151. return le32toh(ps->packetservicestate);
  152. }
  153. static int
  154. mbim_connect_response(void *buffer, size_t len)
  155. {
  156. struct mbim_basic_connect_connect_r *c = (struct mbim_basic_connect_connect_r *) buffer;
  157. if (len < sizeof(struct mbim_basic_connect_connect_r)) {
  158. fprintf(stderr, "message not long enough\n");
  159. return -1;
  160. }
  161. printf(" sessionid: %d\n", le32toh(c->sessionid));
  162. printf(" activationstate: %04X - %s\n", le32toh(c->activationstate),
  163. mbim_enum_string(mbim_activation_state_values, le32toh(c->activationstate)));
  164. printf(" voicecallstate: %04X - %s\n", le32toh(c->voicecallstate),
  165. mbim_enum_string(mbim_voice_call_state_values, le32toh(c->voicecallstate)));
  166. printf(" nwerror: %04X - %s\n", le32toh(c->nwerror),
  167. mbim_enum_string(mbim_nw_error_values, le32toh(c->nwerror)));
  168. printf(" iptype: %04X - %s\n", le32toh(c->iptype),
  169. mbim_enum_string(mbim_context_ip_type_values, le32toh(c->iptype)));
  170. if (MBIM_ACTIVATION_STATE_ACTIVATED == le32toh(c->activationstate))
  171. return 0;
  172. return le32toh(c->activationstate);
  173. }
  174. static int
  175. mbim_config_response(void *buffer, size_t len)
  176. {
  177. struct mbim_basic_connect_ip_configuration_r *ip = (struct mbim_basic_connect_ip_configuration_r *) buffer;
  178. char out[40];
  179. unsigned int i;
  180. uint32_t offset;
  181. if (len < sizeof(struct mbim_basic_connect_ip_configuration_r)) {
  182. fprintf(stderr, "message not long enough\n");
  183. return -1;
  184. }
  185. if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS)
  186. for (i = 0; i < le32toh(ip->ipv4addresscount); i++) {
  187. offset = le32toh(ip->ipv4address) + (i * 4);
  188. mbim_get_ipv4(buffer, out, 4 + offset);
  189. printf(" ipv4address: %s/%d\n", out, mbim_get_int(buffer, offset));
  190. }
  191. if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS) {
  192. mbim_get_ipv4(buffer, out, le32toh(ip->ipv4gateway));
  193. printf(" ipv4gateway: %s\n", out);
  194. }
  195. if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)
  196. printf(" ipv4mtu: %d\n", le32toh(ip->ipv4mtu));
  197. if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS)
  198. for (i = 0; i < le32toh(ip->ipv4dnsservercount); i++) {
  199. mbim_get_ipv4(buffer, out, le32toh(ip->ipv4dnsserver) + (i * 4));
  200. printf(" ipv4dnsserver: %s\n", out);
  201. }
  202. if (le32toh(ip->ipv6configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS)
  203. for (i = 0; i < le32toh(ip->ipv6addresscount); i++) {
  204. offset = le32toh(ip->ipv6address) + (i * 16);
  205. mbim_get_ipv6(buffer, out, 4 + offset);
  206. printf(" ipv6address: %s/%d\n", out, mbim_get_int(buffer, offset));
  207. }
  208. if (le32toh(ip->ipv6configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS) {
  209. mbim_get_ipv6(buffer, out, le32toh(ip->ipv6gateway));
  210. printf(" ipv6gateway: %s\n", out);
  211. }
  212. if (le32toh(ip->ipv6configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)
  213. printf(" ipv6mtu: %d\n", le32toh(ip->ipv6mtu));
  214. if (le32toh(ip->ipv6configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS)
  215. for (i = 0; i < le32toh(ip->ipv6dnsservercount); i++) {
  216. mbim_get_ipv6(buffer, out, le32toh(ip->ipv6dnsserver) + (i * 16));
  217. printf(" ipv6dnsserver: %s\n", out);
  218. }
  219. return 0;
  220. }
  221. static int
  222. mbim_radio_response(void *buffer, size_t len)
  223. {
  224. struct mbim_basic_connect_radio_state_r *r = (struct mbim_basic_connect_radio_state_r *) buffer;
  225. if (len < sizeof(struct mbim_basic_connect_radio_state_r)) {
  226. fprintf(stderr, "message not long enough\n");
  227. return -1;
  228. }
  229. printf(" hwradiostate: %s\n", r->hwradiostate ? "on" : "off");
  230. printf(" swradiostate: %s\n", r->swradiostate ? "on" : "off");
  231. return 0;
  232. }
  233. static int
  234. mbim_device_caps_request(void)
  235. {
  236. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_DEVICE_CAPS, 0);
  237. return mbim_send_command_msg();
  238. }
  239. static int
  240. mbim_pin_state_request(void)
  241. {
  242. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_PIN, 0);
  243. return mbim_send_command_msg();
  244. }
  245. static int
  246. mbim_registration_request(void)
  247. {
  248. if (_argc > 0) {
  249. struct mbim_basic_connect_register_state_s *rs =
  250. (struct mbim_basic_connect_register_state_s *) mbim_setup_command_msg(basic_connect,
  251. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_REGISTER_STATE,
  252. sizeof(struct mbim_basic_connect_register_state_s));
  253. rs->registeraction = htole32(MBIM_REGISTER_ACTION_AUTOMATIC);
  254. } else {
  255. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_REGISTER_STATE, 0);
  256. }
  257. return mbim_send_command_msg();
  258. }
  259. static int
  260. mbim_subscriber_request(void)
  261. {
  262. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_SUBSCRIBER_READY_STATUS, 0);
  263. return mbim_send_command_msg();
  264. }
  265. static int
  266. _mbim_attach_request(int action)
  267. {
  268. struct mbim_basic_connect_packet_service_s *ps =
  269. (struct mbim_basic_connect_packet_service_s *) mbim_setup_command_msg(basic_connect,
  270. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_PACKET_SERVICE,
  271. sizeof(struct mbim_basic_connect_packet_service_s));
  272. ps->packetserviceaction = htole32(action);
  273. return mbim_send_command_msg();
  274. }
  275. static int
  276. mbim_attach_request(void)
  277. {
  278. return _mbim_attach_request(MBIM_PACKET_SERVICE_ACTION_ATTACH);
  279. }
  280. static int
  281. mbim_detach_request(void)
  282. {
  283. return _mbim_attach_request(MBIM_PACKET_SERVICE_ACTION_DETACH);
  284. }
  285. static int
  286. mbim_connect_request(void)
  287. {
  288. char *apn;
  289. struct mbim_basic_connect_connect_s *c =
  290. (struct mbim_basic_connect_connect_s *) mbim_setup_command_msg(basic_connect,
  291. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_CONNECT,
  292. sizeof(struct mbim_basic_connect_connect_s));
  293. c->activationcommand = htole32(MBIM_ACTIVATION_COMMAND_ACTIVATE);
  294. c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_DEFAULT);
  295. memcpy(c->contexttype, uuid_context_type_internet, 16);
  296. if (_argc > 0) {
  297. apn = index(*_argv, ':');
  298. if (!apn) {
  299. apn = *_argv;
  300. } else {
  301. apn[0] = 0;
  302. apn++;
  303. if (!strcmp(*_argv, "ipv4"))
  304. c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_IPV4);
  305. else if (!strcmp(*_argv, "ipv6"))
  306. c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_IPV6);
  307. else if (!strcmp(*_argv, "ipv4v6"))
  308. c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_IPV4V6);
  309. }
  310. mbim_encode_string(&c->accessstring, apn);
  311. }
  312. if (_argc > 3) {
  313. if (!strcmp(_argv[1], "pap"))
  314. c->authprotocol = htole32(MBIM_AUTH_PROTOCOL_PAP);
  315. else if (!strcmp(_argv[1], "chap"))
  316. c->authprotocol = htole32(MBIM_AUTH_PROTOCOL_CHAP);
  317. else if (!strcmp(_argv[1], "mschapv2"))
  318. c->authprotocol = htole32(MBIM_AUTH_PROTOCOL_MSCHAPV2);
  319. if (c->authprotocol) {
  320. mbim_encode_string(&c->username, _argv[2]);
  321. mbim_encode_string(&c->password, _argv[3]);
  322. }
  323. }
  324. return mbim_send_command_msg();
  325. }
  326. static int
  327. mbim_disconnect_request(void)
  328. {
  329. struct mbim_basic_connect_connect_s *c =
  330. (struct mbim_basic_connect_connect_s *) mbim_setup_command_msg(basic_connect,
  331. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_CONNECT,
  332. sizeof(struct mbim_basic_connect_connect_s));
  333. c->activationcommand = htole32(MBIM_ACTIVATION_COMMAND_DEACTIVATE);
  334. memcpy(c->contexttype, uuid_context_type_internet, 16);
  335. no_close = 0;
  336. return mbim_send_command_msg();
  337. }
  338. static char*
  339. mbim_pin_sanitize(char *pin)
  340. {
  341. char *p;
  342. while (*pin && !isdigit(*pin))
  343. pin++;
  344. p = pin;
  345. if (!*p)
  346. return NULL;
  347. while (*pin && isdigit(*pin))
  348. pin++;
  349. if (*pin)
  350. *pin = '\0';
  351. return p;
  352. }
  353. static int
  354. mbim_pin_unlock_request(void)
  355. {
  356. struct mbim_basic_connect_pin_s *p =
  357. (struct mbim_basic_connect_pin_s *) mbim_setup_command_msg(basic_connect,
  358. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_PIN,
  359. sizeof(struct mbim_basic_connect_pin_s));
  360. char *pin = mbim_pin_sanitize(_argv[0]);
  361. if (!pin || !strlen(pin)) {
  362. fprintf(stderr, "failed to sanitize the pincode\n");
  363. return -1;
  364. }
  365. p->pintype = htole32(MBIM_PIN_TYPE_PIN1);
  366. p->pinoperation = htole32(MBIM_PIN_OPERATION_ENTER);
  367. mbim_encode_string(&p->pin, _argv[0]);
  368. return mbim_send_command_msg();
  369. }
  370. static int
  371. mbim_config_request(void)
  372. {
  373. mbim_setup_command_msg(basic_connect,
  374. MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_IP_CONFIGURATION,
  375. sizeof(struct mbim_basic_connect_ip_configuration_q));
  376. return mbim_send_command_msg();
  377. }
  378. static int
  379. mbim_radio_request(void)
  380. {
  381. if (_argc > 0) {
  382. struct mbim_basic_connect_radio_state_s *rs =
  383. (struct mbim_basic_connect_radio_state_s *) mbim_setup_command_msg(basic_connect,
  384. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_RADIO_STATE,
  385. sizeof(struct mbim_basic_connect_radio_state_r));
  386. if (!strcmp(_argv[0], "off"))
  387. rs->radiostate = htole32(MBIM_RADIO_SWITCH_STATE_OFF);
  388. else
  389. rs->radiostate = htole32(MBIM_RADIO_SWITCH_STATE_ON);
  390. } else {
  391. mbim_setup_command_msg(basic_connect,
  392. MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_RADIO_STATE,
  393. sizeof(struct mbim_basic_connect_radio_state_r));
  394. }
  395. return mbim_send_command_msg();
  396. }
  397. static struct mbim_handler handlers[] = {
  398. { "caps", 0, mbim_device_caps_request, mbim_device_caps_response },
  399. { "pinstate", 0, mbim_pin_state_request, mbim_pin_state_response },
  400. { "unlock", 1, mbim_pin_unlock_request, mbim_pin_state_response },
  401. { "registration", 0, mbim_registration_request, mbim_registration_response },
  402. { "subscriber", 0, mbim_subscriber_request, mbim_subscriber_response },
  403. { "attach", 0, mbim_attach_request, mbim_attach_response },
  404. { "detach", 0, mbim_detach_request, mbim_attach_response },
  405. { "connect", 0, mbim_connect_request, mbim_connect_response },
  406. { "disconnect", 0, mbim_disconnect_request, mbim_connect_response },
  407. { "config", 0, mbim_config_request, mbim_config_response },
  408. { "radio", 0, mbim_radio_request, mbim_radio_response },
  409. };
  410. static int
  411. usage(void)
  412. {
  413. fprintf(stderr, "Usage: umbim <caps|pinstate|unlock|registration|subscriber|attach|detach|connect|disconnect|config|radio> [options]\n"
  414. "Options:\n"
  415. #ifdef LIBQMI_MBIM_PROXY
  416. " -p use mbim-proxy\n"
  417. #endif
  418. " -d <device> the device (/dev/cdc-wdmX)\n"
  419. " -t <transaction> the transaction id\n"
  420. " -n no close\n\n"
  421. " -v verbose\n\n");
  422. return 1;
  423. }
  424. int
  425. main(int argc, char **argv)
  426. {
  427. char *cmd, *device = NULL;
  428. int no_open = 0, ch;
  429. unsigned int i;
  430. #ifdef LIBQMI_MBIM_PROXY
  431. int proxy = 0;
  432. #endif
  433. while ((ch = getopt(argc, argv, "pnvd:t:")) != -1) {
  434. switch (ch) {
  435. case 'v':
  436. verbose = 1;
  437. break;
  438. case 'n':
  439. no_close = 1;
  440. break;
  441. case 'd':
  442. device = optarg;
  443. break;
  444. case 't':
  445. no_open = 1;
  446. transaction_id = atoi(optarg);
  447. break;
  448. #ifdef LIBQMI_MBIM_PROXY
  449. case 'p':
  450. proxy = 1;
  451. break;
  452. #endif
  453. default:
  454. return usage();
  455. }
  456. }
  457. if (!device || optind == argc)
  458. return usage();
  459. cmd = argv[optind];
  460. optind++;
  461. _argc = argc - optind;
  462. _argv = &argv[optind];
  463. for (i = 0; i < ARRAY_SIZE(handlers); i++)
  464. if (!strcmp(cmd, handlers[i].name))
  465. current_handler = &handlers[i];
  466. if (!current_handler || (optind + current_handler->argc > argc))
  467. return usage();
  468. uloop_init();
  469. #ifdef LIBQMI_MBIM_PROXY
  470. if (proxy)
  471. mbim_proxy_open(device);
  472. else
  473. #endif
  474. mbim_open(device);
  475. if (!no_open)
  476. mbim_send_open_msg();
  477. else if (current_handler->request() < 0)
  478. return -1;
  479. uloop_run();
  480. uloop_done();
  481. return return_code;
  482. }