1 /* 2 * uqmi -- tiny QMI support implementation 3 * 4 * Copyright (C) 2014-2015 Felix Fietkau <nbd@openwrt.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the 18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301 USA. 20 */ 21 22 #include <stdlib.h> 23 #include <arpa/inet.h> 24 25 #include "qmi-message.h" 26 27 static const struct { 28 const char *auth_name; 29 QmiWdsAuthentication auth; 30 } auth_modes[] = { 31 { "none", QMI_WDS_AUTHENTICATION_NONE }, 32 { "pap", QMI_WDS_AUTHENTICATION_PAP }, 33 { "chap", QMI_WDS_AUTHENTICATION_CHAP }, 34 { "both", QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP }, 35 }; 36 37 static const struct { 38 const char *ipfam_name; 39 const QmiWdsIpFamily mode; 40 } ipfam_modes[] = { 41 { "ipv4", QMI_WDS_IP_FAMILY_IPV4 }, 42 { "ipv6", QMI_WDS_IP_FAMILY_IPV6 }, 43 { "unspecified", QMI_WDS_IP_FAMILY_UNSPECIFIED }, 44 }; 45 46 static const struct { 47 const char *pdp_name; 48 const QmiWdsPdpType type; 49 } pdp_types[] = { 50 { "ipv4", QMI_WDS_PDP_TYPE_IPV4 }, 51 { "ppp", QMI_WDS_PDP_TYPE_PPP }, 52 { "ipv6", QMI_WDS_PDP_TYPE_IPV6 }, 53 { "ipv4v6", QMI_WDS_PDP_TYPE_IPV4_OR_IPV6 }, 54 }; 55 56 static const struct { 57 const char *profile_name; 58 const QmiWdsProfileType profile; 59 } profile_types[] = { 60 { "3gpp", QMI_WDS_PROFILE_TYPE_3GPP }, 61 { "3gpp2", QMI_WDS_PROFILE_TYPE_3GPP2 }, 62 }; 63 64 static struct qmi_wds_start_network_request wds_sn_req = { 65 QMI_INIT(authentication_preference, 66 QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP), 67 }; 68 69 static struct qmi_wds_stop_network_request wds_stn_req; 70 71 static struct qmi_wds_modify_profile_request wds_mp_req = { 72 QMI_INIT_SEQUENCE(profile_identifier, 73 .profile_type = QMI_WDS_PROFILE_TYPE_3GPP, 74 .profile_index = 1, 75 ), 76 QMI_INIT(apn_disabled_flag, false), 77 }; 78 79 static struct qmi_wds_create_profile_request wds_cp_req = { 80 QMI_INIT(profile_type,QMI_WDS_PROFILE_TYPE_3GPP), 81 QMI_INIT(apn_disabled_flag, false), 82 }; 83 84 #define cmd_wds_set_apn_cb no_cb 85 static enum qmi_cmd_result 86 cmd_wds_set_apn_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 87 { 88 qmi_set_ptr(&wds_sn_req, apn, arg); 89 qmi_set_ptr(&wds_mp_req, apn_name, arg); 90 qmi_set_ptr(&wds_cp_req, apn_name, arg); 91 return QMI_CMD_DONE; 92 } 93 94 #define cmd_wds_set_auth_cb no_cb 95 static enum qmi_cmd_result 96 cmd_wds_set_auth_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 97 { 98 int i; 99 for (i = 0; i < ARRAY_SIZE(auth_modes); i++) { 100 if (strcasecmp(auth_modes[i].auth_name, arg) != 0) 101 continue; 102 103 qmi_set(&wds_sn_req, authentication_preference, auth_modes[i].auth); 104 qmi_set(&wds_mp_req, authentication, auth_modes[i].auth); 105 qmi_set(&wds_cp_req, authentication, auth_modes[i].auth); 106 return QMI_CMD_DONE; 107 } 108 109 uqmi_add_error("Invalid auth mode (valid: pap, chap, both, none)"); 110 return QMI_CMD_EXIT; 111 } 112 113 #define cmd_wds_set_username_cb no_cb 114 static enum qmi_cmd_result 115 cmd_wds_set_username_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 116 { 117 qmi_set_ptr(&wds_sn_req, username, arg); 118 qmi_set_ptr(&wds_mp_req, username, arg); 119 qmi_set_ptr(&wds_cp_req, username, arg); 120 return QMI_CMD_DONE; 121 } 122 123 #define cmd_wds_set_password_cb no_cb 124 static enum qmi_cmd_result 125 cmd_wds_set_password_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 126 { 127 qmi_set_ptr(&wds_sn_req, password, arg); 128 qmi_set_ptr(&wds_mp_req, password, arg); 129 qmi_set_ptr(&wds_cp_req, password, arg); 130 return QMI_CMD_DONE; 131 } 132 133 #define cmd_wds_set_autoconnect_cb no_cb 134 static enum qmi_cmd_result 135 cmd_wds_set_autoconnect_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 136 { 137 qmi_set(&wds_sn_req, enable_autoconnect, true); 138 qmi_set(&wds_stn_req, disable_autoconnect, true); 139 return QMI_CMD_DONE; 140 } 141 142 #define cmd_wds_set_ip_family_pref_cb no_cb 143 static enum qmi_cmd_result 144 cmd_wds_set_ip_family_pref_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 145 { 146 int i; 147 for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) { 148 if (strcasecmp(ipfam_modes[i].ipfam_name, arg) != 0) 149 continue; 150 151 qmi_set(&wds_sn_req, ip_family_preference, ipfam_modes[i].mode); 152 return QMI_CMD_DONE; 153 } 154 155 uqmi_add_error("Invalid value (valid: ipv4, ipv6, unspecified)"); 156 return QMI_CMD_EXIT; 157 } 158 159 #define cmd_wds_set_pdp_type_cb no_cb 160 static enum qmi_cmd_result 161 cmd_wds_set_pdp_type_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 162 { 163 int i; 164 165 for (i = 0; i < ARRAY_SIZE(pdp_types); i++) { 166 if (strcasecmp(pdp_types[i].pdp_name, arg) != 0) 167 continue; 168 169 qmi_set(&wds_mp_req, pdp_type, pdp_types[i].type); 170 qmi_set(&wds_cp_req, pdp_type, pdp_types[i].type); 171 return QMI_CMD_DONE; 172 } 173 174 uqmi_add_error("Invalid value (valid: ipv4, ipv6, ipv4v6)"); 175 return QMI_CMD_EXIT; 176 } 177 178 #define cmd_wds_no_roaming_cb no_cb 179 static enum qmi_cmd_result 180 cmd_wds_no_roaming_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 181 { 182 if (strcmp(arg, "true") == 0) { 183 qmi_set(&wds_mp_req, roaming_disallowed_flag, true); 184 qmi_set(&wds_cp_req, roaming_disallowed_flag, true); 185 } else if (strcmp(arg, "false") == 0) { 186 qmi_set(&wds_mp_req, roaming_disallowed_flag, false); 187 qmi_set(&wds_cp_req, roaming_disallowed_flag, false); 188 } else { 189 uqmi_add_error("Invalid value (true or false)"); 190 return QMI_CMD_EXIT; 191 } 192 return QMI_CMD_DONE; 193 } 194 195 #define cmd_wds_set_profile_cb no_cb 196 static enum qmi_cmd_result 197 cmd_wds_set_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 198 { 199 uint32_t idx = strtoul(arg, NULL, 10); 200 201 qmi_set(&wds_sn_req, profile_index_3gpp, idx); 202 return QMI_CMD_DONE; 203 } 204 205 static void 206 cmd_wds_start_network_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 207 { 208 struct qmi_wds_start_network_response res; 209 210 qmi_parse_wds_start_network_response(msg, &res); 211 if (res.set.packet_data_handle) 212 blobmsg_add_u32(&status, NULL, res.data.packet_data_handle); 213 } 214 215 static enum qmi_cmd_result 216 cmd_wds_start_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 217 { 218 qmi_set_wds_start_network_request(msg, &wds_sn_req); 219 return QMI_CMD_REQUEST; 220 } 221 222 #define cmd_wds_stop_network_cb no_cb 223 static enum qmi_cmd_result 224 cmd_wds_stop_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 225 { 226 uint32_t pdh = strtoul(arg, NULL, 0); 227 228 qmi_set(&wds_stn_req, packet_data_handle, pdh); 229 qmi_set_wds_stop_network_request(msg, &wds_stn_req); 230 return QMI_CMD_REQUEST; 231 } 232 233 static void 234 cmd_wds_modify_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 235 { 236 struct qmi_wds_modify_profile_response res; 237 qmi_parse_wds_modify_profile_response(msg, &res); 238 } 239 240 static enum qmi_cmd_result 241 cmd_wds_modify_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 242 { 243 int id; 244 char *s; 245 char *p_type; 246 247 s = strchr(arg, ','); 248 if (!s) { 249 fprintf(stderr, "Invalid argument\n"); 250 return QMI_CMD_EXIT; 251 } 252 *s = 0; 253 s++; 254 255 id = strtoul(s, &s, 0); 256 if (s && *s) { 257 fprintf(stderr, "Invalid argument\n"); 258 return QMI_CMD_EXIT; 259 } 260 261 p_type = strtok(arg, ","); 262 263 int i; 264 for (i = 0; i < ARRAY_SIZE(profile_types); i++) { 265 if (strcasecmp(profile_types[i].profile_name, p_type) != 0) 266 continue; 267 268 qmi_set_ptr(&wds_mp_req, profile_identifier.profile_type, profile_types[i].profile); 269 qmi_set_ptr(&wds_mp_req, profile_identifier.profile_index, id); 270 qmi_set_wds_modify_profile_request(msg, &wds_mp_req); 271 return QMI_CMD_REQUEST; 272 } 273 274 uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)"); 275 return QMI_CMD_EXIT; 276 } 277 278 static void 279 cmd_wds_create_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 280 { 281 struct qmi_wds_create_profile_response res; 282 void *p; 283 284 qmi_parse_wds_create_profile_response(msg, &res); 285 286 if (res.set.profile_identifier) { 287 p = blobmsg_open_table(&status, NULL); 288 blobmsg_add_u32(&status, "created-profile", res.data.profile_identifier.profile_index); 289 blobmsg_close_table(&status, p); 290 } 291 } 292 293 static enum qmi_cmd_result 294 cmd_wds_create_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 295 { 296 int i; 297 for (i = 0; i < ARRAY_SIZE(profile_types); i++) { 298 if (strcasecmp(profile_types[i].profile_name, arg) != 0) 299 continue; 300 301 qmi_set_ptr(&wds_cp_req, profile_type, profile_types[i].profile); 302 303 qmi_set_wds_create_profile_request(msg, &wds_cp_req); 304 return QMI_CMD_REQUEST; 305 } 306 307 uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)"); 308 return QMI_CMD_EXIT; 309 } 310 311 static void 312 cmd_wds_get_packet_service_status_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 313 { 314 struct qmi_wds_get_packet_service_status_response res; 315 const char *data_status[] = { 316 [QMI_WDS_CONNECTION_STATUS_UNKNOWN] = "unknown", 317 [QMI_WDS_CONNECTION_STATUS_DISCONNECTED] = "disconnected", 318 [QMI_WDS_CONNECTION_STATUS_CONNECTED] = "connected", 319 [QMI_WDS_CONNECTION_STATUS_SUSPENDED] = "suspended", 320 [QMI_WDS_CONNECTION_STATUS_AUTHENTICATING] = "authenticating", 321 }; 322 int s = 0; 323 324 qmi_parse_wds_get_packet_service_status_response(msg, &res); 325 if (res.set.connection_status && 326 res.data.connection_status < ARRAY_SIZE(data_status)) 327 s = res.data.connection_status; 328 329 blobmsg_add_string(&status, NULL, data_status[s]); 330 } 331 332 static enum qmi_cmd_result 333 cmd_wds_get_packet_service_status_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 334 { 335 qmi_set_wds_get_packet_service_status_request(msg); 336 return QMI_CMD_REQUEST; 337 } 338 339 #define cmd_wds_set_autoconnect_settings_cb no_cb 340 static enum qmi_cmd_result 341 cmd_wds_set_autoconnect_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 342 { 343 struct qmi_wds_set_autoconnect_settings_request ac_req; 344 const char *modes[] = { 345 [QMI_WDS_AUTOCONNECT_SETTING_DISABLED] = "disabled", 346 [QMI_WDS_AUTOCONNECT_SETTING_ENABLED] = "enabled", 347 [QMI_WDS_AUTOCONNECT_SETTING_PAUSED] = "paused", 348 }; 349 int i; 350 351 for (i = 0; i < ARRAY_SIZE(modes); i++) { 352 if (strcasecmp(modes[i], arg) != 0) 353 continue; 354 355 qmi_set(&ac_req, status, i); 356 qmi_set_wds_set_autoconnect_settings_request(msg, &ac_req); 357 return QMI_CMD_DONE; 358 } 359 360 uqmi_add_error("Invalid value (valid: disabled, enabled, paused)"); 361 return QMI_CMD_EXIT; 362 } 363 364 #define cmd_wds_reset_cb no_cb 365 static enum qmi_cmd_result 366 cmd_wds_reset_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 367 { 368 qmi_set_wds_reset_request(msg); 369 return QMI_CMD_REQUEST; 370 } 371 372 #define cmd_wds_set_ip_family_cb no_cb 373 static enum qmi_cmd_result 374 cmd_wds_set_ip_family_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 375 { 376 struct qmi_wds_set_ip_family_request ipf_req; 377 378 int i; 379 for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) { 380 if (strcasecmp(ipfam_modes[i].ipfam_name, arg) != 0) 381 continue; 382 383 qmi_set(&ipf_req, preference, ipfam_modes[i].mode); 384 qmi_set_wds_set_ip_family_request(msg, &ipf_req); 385 return QMI_CMD_REQUEST; 386 } 387 388 uqmi_add_error("Invalid value (valid: ipv4, ipv6, unspecified)"); 389 return QMI_CMD_EXIT; 390 } 391 392 static void wds_to_ipv4(const char *name, const uint32_t addr) 393 { 394 struct in_addr ip_addr; 395 char buf[INET_ADDRSTRLEN]; 396 397 ip_addr.s_addr = htonl(addr); 398 blobmsg_add_string(&status, name, inet_ntop(AF_INET, &ip_addr, buf, sizeof(buf))); 399 } 400 401 static void wds_to_ipv6(const char *name, const uint16_t *addr) 402 { 403 char buf[INET6_ADDRSTRLEN]; 404 uint16_t ip_addr[8]; 405 int i; 406 407 for (i = 0; i < ARRAY_SIZE(ip_addr); i++) 408 ip_addr[i] = htons(addr[i]); 409 410 blobmsg_add_string(&status, name, inet_ntop(AF_INET6, &ip_addr, buf, sizeof(buf))); 411 } 412 413 static enum qmi_cmd_result 414 cmd_wds_get_profile_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 415 { 416 int id; 417 char *s; 418 char *p_type; 419 420 s = strchr(arg, ','); 421 if (!s) { 422 fprintf(stderr, "Invalid argument\n"); 423 return QMI_CMD_EXIT; 424 } 425 *s = 0; 426 s++; 427 428 id = strtoul(s, &s, 0); 429 if (s && *s) { 430 fprintf(stderr, "Invalid argument\n"); 431 return QMI_CMD_EXIT; 432 } 433 434 p_type = strtok(arg, ","); 435 436 int i; 437 for (i = 0; i < ARRAY_SIZE(profile_types); i++) { 438 if (strcasecmp(profile_types[i].profile_name, p_type) != 0) 439 continue; 440 441 struct qmi_wds_get_profile_settings_request p_num = { 442 QMI_INIT_SEQUENCE(profile_id, 443 .profile_type = profile_types[i].profile, 444 .profile_index = id, 445 ) 446 }; 447 qmi_set_wds_get_profile_settings_request(msg, &p_num); 448 return QMI_CMD_REQUEST; 449 } 450 451 uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)"); 452 return QMI_CMD_EXIT; 453 } 454 455 static void 456 cmd_wds_get_profile_settings_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 457 { 458 struct qmi_wds_get_profile_settings_response res; 459 460 void *p; 461 462 qmi_parse_wds_get_profile_settings_response(msg, &res); 463 464 p = blobmsg_open_table(&status, NULL); 465 466 blobmsg_add_string(&status, "apn", res.data.apn_name); 467 if (res.set.pdp_type && (int) res.data.pdp_type < ARRAY_SIZE(pdp_types)) 468 blobmsg_add_string(&status, "pdp-type", pdp_types[res.data.pdp_type].pdp_name); 469 blobmsg_add_string(&status, "username", res.data.username); 470 blobmsg_add_string(&status, "password", res.data.password); 471 if (res.set.authentication && (int) res.data.authentication < ARRAY_SIZE(auth_modes)) 472 blobmsg_add_string(&status, "auth", auth_modes[res.data.authentication].auth_name); 473 blobmsg_add_u8(&status, "no-roaming", res.data.roaming_disallowed_flag); 474 blobmsg_add_u8(&status, "apn-disabled", res.data.apn_disabled_flag); 475 blobmsg_close_table(&status, p); 476 } 477 478 static void 479 cmd_wds_get_current_settings_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 480 { 481 void *v4, *v6, *d, *t; 482 struct qmi_wds_get_current_settings_response res; 483 int i; 484 485 qmi_parse_wds_get_current_settings_response(msg, &res); 486 487 t = blobmsg_open_table(&status, NULL); 488 489 if (res.set.pdp_type && (int) res.data.pdp_type < ARRAY_SIZE(pdp_types)) 490 blobmsg_add_string(&status, "pdp-type", pdp_types[res.data.pdp_type].pdp_name); 491 492 if (res.set.ip_family) { 493 for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) { 494 if (ipfam_modes[i].mode != res.data.ip_family) 495 continue; 496 blobmsg_add_string(&status, "ip-family", ipfam_modes[i].ipfam_name); 497 break; 498 } 499 } 500 501 if (res.set.mtu) 502 blobmsg_add_u32(&status, "mtu", res.data.mtu); 503 504 /* IPV4 */ 505 v4 = blobmsg_open_table(&status, "ipv4"); 506 507 if (res.set.ipv4_address) 508 wds_to_ipv4("ip", res.data.ipv4_address); 509 if (res.set.primary_ipv4_dns_address) 510 wds_to_ipv4("dns1", res.data.primary_ipv4_dns_address); 511 if (res.set.secondary_ipv4_dns_address) 512 wds_to_ipv4("dns2", res.data.secondary_ipv4_dns_address); 513 if (res.set.ipv4_gateway_address) 514 wds_to_ipv4("gateway", res.data.ipv4_gateway_address); 515 if (res.set.ipv4_gateway_subnet_mask) 516 wds_to_ipv4("subnet", res.data.ipv4_gateway_subnet_mask); 517 blobmsg_close_table(&status, v4); 518 519 /* IPV6 */ 520 v6 = blobmsg_open_table(&status, "ipv6"); 521 522 if (res.set.ipv6_address) { 523 wds_to_ipv6("ip", res.data.ipv6_address.address); 524 blobmsg_add_u32(&status, "ip-prefix-length", res.data.ipv6_address.prefix_length); 525 } 526 if (res.set.ipv6_gateway_address) { 527 wds_to_ipv6("gateway", res.data.ipv6_gateway_address.address); 528 blobmsg_add_u32(&status, "gw-prefix-length", res.data.ipv6_gateway_address.prefix_length); 529 } 530 if (res.set.ipv6_primary_dns_address) 531 wds_to_ipv6("dns1", res.data.ipv6_primary_dns_address); 532 if (res.set.ipv6_secondary_dns_address) 533 wds_to_ipv6("dns2", res.data.ipv6_secondary_dns_address); 534 535 blobmsg_close_table(&status, v6); 536 537 d = blobmsg_open_table(&status, "domain-names"); 538 for (i = 0; i < res.data.domain_name_list_n; i++) { 539 blobmsg_add_string(&status, NULL, res.data.domain_name_list[i]); 540 } 541 blobmsg_close_table(&status, d); 542 543 blobmsg_close_table(&status, t); 544 } 545 546 static enum qmi_cmd_result 547 cmd_wds_get_current_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 548 { 549 struct qmi_wds_get_current_settings_request gcs_req; 550 memset(&gcs_req, '\0', sizeof(struct qmi_wds_get_current_settings_request)); 551 qmi_set(&gcs_req, requested_settings, 552 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PDP_TYPE | 553 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS | 554 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS | 555 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS | 556 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO | 557 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU | 558 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST | 559 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY); 560 qmi_set_wds_get_current_settings_request(msg, &gcs_req); 561 return QMI_CMD_REQUEST; 562 } 563 564 static enum qmi_cmd_result 565 cmd_wds_get_default_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 566 { 567 int i; 568 for (i = 0; i < ARRAY_SIZE(profile_types); i++) { 569 if (strcasecmp(profile_types[i].profile_name, arg) != 0) 570 continue; 571 572 struct qmi_wds_get_default_profile_number_request type_family = { 573 QMI_INIT_SEQUENCE(profile_type, 574 .type = profile_types[i].profile, 575 .family = QMI_WDS_PROFILE_FAMILY_TETHERED, 576 ) 577 }; 578 579 qmi_set_wds_get_default_profile_number_request(msg, &type_family); 580 return QMI_CMD_REQUEST; 581 } 582 583 uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)"); 584 return QMI_CMD_EXIT; 585 } 586 587 static void 588 cmd_wds_get_default_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 589 { 590 struct qmi_wds_get_default_profile_number_response res; 591 void *p; 592 qmi_parse_wds_get_default_profile_number_response(msg, &res); 593 594 p = blobmsg_open_table(&status, NULL); 595 596 blobmsg_add_u32(&status, "default-profile", res.data.index); 597 598 blobmsg_close_table(&status, p); 599 } 600
This page was automatically generated by LXR 0.3.1. • OpenWrt