cli.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  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_home_provider_response(void *buffer, size_t len)
  81. {
  82. struct mbim_basic_connect_home_provider_r *state = (struct mbim_basic_connect_home_provider_r *) buffer;
  83. struct mbimprovider *provider;
  84. char *provider_id, *provider_name;
  85. if (len < sizeof(struct mbim_basic_connect_home_provider_r)) {
  86. fprintf(stderr, "message not long enough\n");
  87. return -1;
  88. }
  89. provider = &state->provider;
  90. provider_id = mbim_get_string(&provider->providerid, buffer);
  91. provider_name = mbim_get_string(&provider->providername, buffer);
  92. printf(" provider_id: %s\n", provider_id);
  93. printf(" provider_name: %s\n", provider_name);
  94. printf(" cellularclass: %04X - %s\n", le32toh(provider->cellularclass),
  95. mbim_enum_string(mbim_cellular_class_values, le32toh(provider->cellularclass)));
  96. printf(" rssi: %04X\n", le32toh(provider->rssi));
  97. printf(" errorrate: %04X\n", le32toh(provider->errorrate));
  98. return 0;
  99. }
  100. static int
  101. mbim_registration_response(void *buffer, size_t len)
  102. {
  103. struct mbim_basic_connect_register_state_r *state = (struct mbim_basic_connect_register_state_r *) buffer;
  104. char *provider_id, *provider_name, *roamingtext;
  105. if (len < sizeof(struct mbim_basic_connect_register_state_r)) {
  106. fprintf(stderr, "message not long enough\n");
  107. return -1;
  108. }
  109. provider_id = mbim_get_string(&state->providerid, buffer);
  110. provider_name = mbim_get_string(&state->providername, buffer);
  111. 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);
  125. if (le32toh(state->registerstate) == MBIM_REGISTER_STATE_HOME)
  126. return 0;
  127. return le32toh(state->registerstate);
  128. }
  129. static int
  130. mbim_subscriber_response(void *buffer, size_t len)
  131. {
  132. struct mbim_basic_connect_subscriber_ready_status_r *state = (struct mbim_basic_connect_subscriber_ready_status_r *) buffer;
  133. char *subscriberid, *simiccid;
  134. unsigned int nr;
  135. if (len < sizeof(struct mbim_basic_connect_subscriber_ready_status_r)) {
  136. fprintf(stderr, "message not long enough\n");
  137. return -1;
  138. }
  139. subscriberid = mbim_get_string(&state->subscriberid, buffer);
  140. simiccid = mbim_get_string(&state->simiccid, buffer);
  141. printf(" readystate: %04X - %s\n", le32toh(state->readystate),
  142. mbim_enum_string(mbim_subscriber_ready_state_values, le32toh(state->readystate)));
  143. printf(" simiccid: %s\n", simiccid);
  144. printf(" subscriberid: %s\n", subscriberid);
  145. if (le32toh(state->readyinfo) & MBIM_READY_INFO_FLAG_PROTECT_UNIQUE_ID)
  146. printf(" dont display subscriberID: 1\n");
  147. for (nr = 0; nr < le32toh(state->telephonenumberscount); nr++) {
  148. struct mbim_string *str = (void *)&state->telephonenumbers + (nr * sizeof(struct mbim_string));
  149. char *number = mbim_get_string(str, buffer);
  150. printf(" number: %s\n", number);
  151. }
  152. if (MBIM_SUBSCRIBER_READY_STATE_INITIALIZED == le32toh(state->readystate))
  153. return 0;
  154. return le32toh(state->readystate);
  155. }
  156. static int
  157. mbim_attach_response(void *buffer, size_t len)
  158. {
  159. struct mbim_basic_connect_packet_service_r *ps = (struct mbim_basic_connect_packet_service_r *) buffer;
  160. if (len < sizeof(struct mbim_basic_connect_packet_service_r)) {
  161. fprintf(stderr, "message not long enough\n");
  162. return -1;
  163. }
  164. printf(" nwerror: %04X - %s\n", le32toh(ps->nwerror),
  165. mbim_enum_string(mbim_nw_error_values, le32toh(ps->nwerror)));
  166. printf(" packetservicestate: %04X - %s\n", le32toh(ps->packetservicestate),
  167. mbim_enum_string(mbim_packet_service_state_values, le32toh(ps->packetservicestate)));
  168. printf(" uplinkspeed: %"PRIu64"\n", (uint64_t) le64toh(ps->uplinkspeed));
  169. printf(" downlinkspeed: %"PRIu64"\n", (uint64_t) le64toh(ps->downlinkspeed));
  170. if (MBIM_PACKET_SERVICE_STATE_ATTACHED == le32toh(ps->packetservicestate))
  171. return 0;
  172. return le32toh(ps->packetservicestate);
  173. }
  174. static int
  175. mbim_connect_response(void *buffer, size_t len)
  176. {
  177. struct mbim_basic_connect_connect_r *c = (struct mbim_basic_connect_connect_r *) buffer;
  178. if (len < sizeof(struct mbim_basic_connect_connect_r)) {
  179. fprintf(stderr, "message not long enough\n");
  180. return -1;
  181. }
  182. printf(" sessionid: %d\n", le32toh(c->sessionid));
  183. printf(" activationstate: %04X - %s\n", le32toh(c->activationstate),
  184. mbim_enum_string(mbim_activation_state_values, le32toh(c->activationstate)));
  185. printf(" voicecallstate: %04X - %s\n", le32toh(c->voicecallstate),
  186. mbim_enum_string(mbim_voice_call_state_values, le32toh(c->voicecallstate)));
  187. printf(" nwerror: %04X - %s\n", le32toh(c->nwerror),
  188. mbim_enum_string(mbim_nw_error_values, le32toh(c->nwerror)));
  189. printf(" iptype: %04X - %s\n", le32toh(c->iptype),
  190. mbim_enum_string(mbim_context_ip_type_values, le32toh(c->iptype)));
  191. if (MBIM_ACTIVATION_STATE_ACTIVATED == le32toh(c->activationstate))
  192. return 0;
  193. return le32toh(c->activationstate);
  194. }
  195. static int
  196. mbim_config_response(void *buffer, size_t len)
  197. {
  198. struct mbim_basic_connect_ip_configuration_r *ip = (struct mbim_basic_connect_ip_configuration_r *) buffer;
  199. char out[40];
  200. unsigned int i;
  201. uint32_t offset;
  202. if (len < sizeof(struct mbim_basic_connect_ip_configuration_r)) {
  203. fprintf(stderr, "message not long enough\n");
  204. return -1;
  205. }
  206. if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS)
  207. for (i = 0; i < le32toh(ip->ipv4addresscount); i++) {
  208. offset = le32toh(ip->ipv4address) + (i * 4);
  209. mbim_get_ipv4(buffer, out, 4 + offset);
  210. printf(" ipv4address: %s/%d\n", out, mbim_get_int(buffer, offset));
  211. }
  212. if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS) {
  213. mbim_get_ipv4(buffer, out, le32toh(ip->ipv4gateway));
  214. printf(" ipv4gateway: %s\n", out);
  215. }
  216. if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)
  217. printf(" ipv4mtu: %d\n", le32toh(ip->ipv4mtu));
  218. if (le32toh(ip->ipv4configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS)
  219. for (i = 0; i < le32toh(ip->ipv4dnsservercount); i++) {
  220. mbim_get_ipv4(buffer, out, le32toh(ip->ipv4dnsserver) + (i * 4));
  221. printf(" ipv4dnsserver: %s\n", out);
  222. }
  223. if (le32toh(ip->ipv6configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS)
  224. for (i = 0; i < le32toh(ip->ipv6addresscount); i++) {
  225. offset = le32toh(ip->ipv6address) + (i * 16);
  226. mbim_get_ipv6(buffer, out, 4 + offset);
  227. printf(" ipv6address: %s/%d\n", out, mbim_get_int(buffer, offset));
  228. }
  229. if (le32toh(ip->ipv6configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS) {
  230. mbim_get_ipv6(buffer, out, le32toh(ip->ipv6gateway));
  231. printf(" ipv6gateway: %s\n", out);
  232. }
  233. if (le32toh(ip->ipv6configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)
  234. printf(" ipv6mtu: %d\n", le32toh(ip->ipv6mtu));
  235. if (le32toh(ip->ipv6configurationavailable) & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS)
  236. for (i = 0; i < le32toh(ip->ipv6dnsservercount); i++) {
  237. mbim_get_ipv6(buffer, out, le32toh(ip->ipv6dnsserver) + (i * 16));
  238. printf(" ipv6dnsserver: %s\n", out);
  239. }
  240. return 0;
  241. }
  242. static int
  243. mbim_radio_response(void *buffer, size_t len)
  244. {
  245. struct mbim_basic_connect_radio_state_r *r = (struct mbim_basic_connect_radio_state_r *) buffer;
  246. if (len < sizeof(struct mbim_basic_connect_radio_state_r)) {
  247. fprintf(stderr, "message not long enough\n");
  248. return -1;
  249. }
  250. printf(" hwradiostate: %s\n", r->hwradiostate ? "on" : "off");
  251. printf(" swradiostate: %s\n", r->swradiostate ? "on" : "off");
  252. return 0;
  253. }
  254. static int
  255. mbim_device_caps_request(void)
  256. {
  257. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_DEVICE_CAPS, 0);
  258. return mbim_send_command_msg();
  259. }
  260. static int
  261. mbim_pin_state_request(void)
  262. {
  263. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_PIN, 0);
  264. return mbim_send_command_msg();
  265. }
  266. static int
  267. mbim_home_provider_request(void)
  268. {
  269. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CID_BASIC_CONNECT_HOME_PROVIDER, 0);
  270. return mbim_send_command_msg();
  271. }
  272. static int
  273. mbim_registration_request(void)
  274. {
  275. if (_argc > 0) {
  276. struct mbim_basic_connect_register_state_s *rs =
  277. (struct mbim_basic_connect_register_state_s *) mbim_setup_command_msg(basic_connect,
  278. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_REGISTER_STATE,
  279. sizeof(struct mbim_basic_connect_register_state_s));
  280. rs->registeraction = htole32(MBIM_REGISTER_ACTION_AUTOMATIC);
  281. } else {
  282. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_REGISTER_STATE, 0);
  283. }
  284. return mbim_send_command_msg();
  285. }
  286. static int
  287. mbim_subscriber_request(void)
  288. {
  289. mbim_setup_command_msg(basic_connect, MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_SUBSCRIBER_READY_STATUS, 0);
  290. return mbim_send_command_msg();
  291. }
  292. static int
  293. _mbim_attach_request(int action)
  294. {
  295. struct mbim_basic_connect_packet_service_s *ps =
  296. (struct mbim_basic_connect_packet_service_s *) mbim_setup_command_msg(basic_connect,
  297. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_PACKET_SERVICE,
  298. sizeof(struct mbim_basic_connect_packet_service_s));
  299. ps->packetserviceaction = htole32(action);
  300. return mbim_send_command_msg();
  301. }
  302. static int
  303. mbim_attach_request(void)
  304. {
  305. return _mbim_attach_request(MBIM_PACKET_SERVICE_ACTION_ATTACH);
  306. }
  307. static int
  308. mbim_detach_request(void)
  309. {
  310. return _mbim_attach_request(MBIM_PACKET_SERVICE_ACTION_DETACH);
  311. }
  312. static int
  313. mbim_connect_request(void)
  314. {
  315. char *apn;
  316. struct mbim_basic_connect_connect_s *c =
  317. (struct mbim_basic_connect_connect_s *) mbim_setup_command_msg(basic_connect,
  318. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_CONNECT,
  319. sizeof(struct mbim_basic_connect_connect_s));
  320. c->activationcommand = htole32(MBIM_ACTIVATION_COMMAND_ACTIVATE);
  321. c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_DEFAULT);
  322. memcpy(c->contexttype, uuid_context_type_internet, 16);
  323. if (_argc > 0) {
  324. apn = index(*_argv, ':');
  325. if (!apn) {
  326. apn = *_argv;
  327. } else {
  328. apn[0] = 0;
  329. apn++;
  330. if (!strcmp(*_argv, "ipv4"))
  331. c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_IPV4);
  332. else if (!strcmp(*_argv, "ipv6"))
  333. c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_IPV6);
  334. else if (!strcmp(*_argv, "ipv4v6"))
  335. c->iptype = htole32(MBIM_CONTEXT_IP_TYPE_IPV4V6);
  336. }
  337. mbim_encode_string(&c->accessstring, apn);
  338. }
  339. if (_argc > 3) {
  340. if (!strcmp(_argv[1], "pap"))
  341. c->authprotocol = htole32(MBIM_AUTH_PROTOCOL_PAP);
  342. else if (!strcmp(_argv[1], "chap"))
  343. c->authprotocol = htole32(MBIM_AUTH_PROTOCOL_CHAP);
  344. else if (!strcmp(_argv[1], "mschapv2"))
  345. c->authprotocol = htole32(MBIM_AUTH_PROTOCOL_MSCHAPV2);
  346. if (c->authprotocol) {
  347. mbim_encode_string(&c->username, _argv[2]);
  348. mbim_encode_string(&c->password, _argv[3]);
  349. }
  350. }
  351. return mbim_send_command_msg();
  352. }
  353. static int
  354. mbim_disconnect_request(void)
  355. {
  356. struct mbim_basic_connect_connect_s *c =
  357. (struct mbim_basic_connect_connect_s *) mbim_setup_command_msg(basic_connect,
  358. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_CONNECT,
  359. sizeof(struct mbim_basic_connect_connect_s));
  360. c->activationcommand = htole32(MBIM_ACTIVATION_COMMAND_DEACTIVATE);
  361. memcpy(c->contexttype, uuid_context_type_internet, 16);
  362. no_close = 0;
  363. return mbim_send_command_msg();
  364. }
  365. static char*
  366. mbim_pin_sanitize(char *pin)
  367. {
  368. char *p;
  369. while (*pin && !isdigit(*pin))
  370. pin++;
  371. p = pin;
  372. if (!*p)
  373. return NULL;
  374. while (*pin && isdigit(*pin))
  375. pin++;
  376. if (*pin)
  377. *pin = '\0';
  378. return p;
  379. }
  380. static int
  381. mbim_pin_unlock_request(void)
  382. {
  383. struct mbim_basic_connect_pin_s *p =
  384. (struct mbim_basic_connect_pin_s *) mbim_setup_command_msg(basic_connect,
  385. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_PIN,
  386. sizeof(struct mbim_basic_connect_pin_s));
  387. char *pin = mbim_pin_sanitize(_argv[0]);
  388. if (!pin || !strlen(pin)) {
  389. fprintf(stderr, "failed to sanitize the pincode\n");
  390. return -1;
  391. }
  392. p->pintype = htole32(MBIM_PIN_TYPE_PIN1);
  393. p->pinoperation = htole32(MBIM_PIN_OPERATION_ENTER);
  394. mbim_encode_string(&p->pin, _argv[0]);
  395. return mbim_send_command_msg();
  396. }
  397. static int
  398. mbim_config_request(void)
  399. {
  400. mbim_setup_command_msg(basic_connect,
  401. MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_IP_CONFIGURATION,
  402. sizeof(struct mbim_basic_connect_ip_configuration_q));
  403. return mbim_send_command_msg();
  404. }
  405. static int
  406. mbim_radio_request(void)
  407. {
  408. if (_argc > 0) {
  409. struct mbim_basic_connect_radio_state_s *rs =
  410. (struct mbim_basic_connect_radio_state_s *) mbim_setup_command_msg(basic_connect,
  411. MBIM_MESSAGE_COMMAND_TYPE_SET, MBIM_CMD_BASIC_CONNECT_RADIO_STATE,
  412. sizeof(struct mbim_basic_connect_radio_state_r));
  413. if (!strcmp(_argv[0], "off"))
  414. rs->radiostate = htole32(MBIM_RADIO_SWITCH_STATE_OFF);
  415. else
  416. rs->radiostate = htole32(MBIM_RADIO_SWITCH_STATE_ON);
  417. } else {
  418. mbim_setup_command_msg(basic_connect,
  419. MBIM_MESSAGE_COMMAND_TYPE_QUERY, MBIM_CMD_BASIC_CONNECT_RADIO_STATE,
  420. sizeof(struct mbim_basic_connect_radio_state_r));
  421. }
  422. return mbim_send_command_msg();
  423. }
  424. static struct mbim_handler handlers[] = {
  425. { "caps", 0, mbim_device_caps_request, mbim_device_caps_response },
  426. { "pinstate", 0, mbim_pin_state_request, mbim_pin_state_response },
  427. { "unlock", 1, mbim_pin_unlock_request, mbim_pin_state_response },
  428. { "home", 0, mbim_home_provider_request, mbim_home_provider_response },
  429. { "registration", 0, mbim_registration_request, mbim_registration_response },
  430. { "subscriber", 0, mbim_subscriber_request, mbim_subscriber_response },
  431. { "attach", 0, mbim_attach_request, mbim_attach_response },
  432. { "detach", 0, mbim_detach_request, mbim_attach_response },
  433. { "connect", 0, mbim_connect_request, mbim_connect_response },
  434. { "disconnect", 0, mbim_disconnect_request, mbim_connect_response },
  435. { "config", 0, mbim_config_request, mbim_config_response },
  436. { "radio", 0, mbim_radio_request, mbim_radio_response },
  437. };
  438. static int
  439. usage(void)
  440. {
  441. fprintf(stderr, "Usage: umbim <caps|pinstate|unlock|home|registration|subscriber|attach|detach|connect|disconnect|config|radio> [options]\n"
  442. "Options:\n"
  443. #ifdef LIBQMI_MBIM_PROXY
  444. " -p use mbim-proxy\n"
  445. #endif
  446. " -d <device> the device (/dev/cdc-wdmX)\n"
  447. " -t <transaction> the transaction id\n"
  448. " -n no close\n\n"
  449. " -v verbose\n\n");
  450. return 1;
  451. }
  452. int
  453. main(int argc, char **argv)
  454. {
  455. char *cmd, *device = NULL;
  456. int no_open = 0, ch;
  457. unsigned int i;
  458. #ifdef LIBQMI_MBIM_PROXY
  459. int proxy = 0;
  460. #endif
  461. while ((ch = getopt(argc, argv, "pnvd:t:")) != -1) {
  462. switch (ch) {
  463. case 'v':
  464. verbose = 1;
  465. break;
  466. case 'n':
  467. no_close = 1;
  468. break;
  469. case 'd':
  470. device = optarg;
  471. break;
  472. case 't':
  473. no_open = 1;
  474. transaction_id = atoi(optarg);
  475. break;
  476. #ifdef LIBQMI_MBIM_PROXY
  477. case 'p':
  478. proxy = 1;
  479. break;
  480. #endif
  481. default:
  482. return usage();
  483. }
  484. }
  485. if (!device || optind == argc)
  486. return usage();
  487. cmd = argv[optind];
  488. optind++;
  489. _argc = argc - optind;
  490. _argv = &argv[optind];
  491. for (i = 0; i < ARRAY_SIZE(handlers); i++)
  492. if (!strcmp(cmd, handlers[i].name))
  493. current_handler = &handlers[i];
  494. if (!current_handler || (optind + current_handler->argc > argc))
  495. return usage();
  496. uloop_init();
  497. #ifdef LIBQMI_MBIM_PROXY
  498. if (proxy)
  499. mbim_proxy_open(device);
  500. else
  501. #endif
  502. mbim_open(device);
  503. if (!no_open)
  504. mbim_send_open_msg();
  505. else if (current_handler->request() < 0)
  506. return -1;
  507. uloop_run();
  508. uloop_done();
  509. return return_code;
  510. }