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 #include "qmi-message.h" 22 23 static struct { 24 QmiDmsUimPinId pin_id; 25 char* pin; 26 char* new_pin; 27 char* puk; 28 } dms_req_data; 29 30 const char *oper_modes[] = { 31 [QMI_DMS_OPERATING_MODE_ONLINE] = "online", 32 [QMI_DMS_OPERATING_MODE_LOW_POWER] = "low_power", 33 [QMI_DMS_OPERATING_MODE_FACTORY_TEST] = "factory_test", 34 [QMI_DMS_OPERATING_MODE_OFFLINE] = "offline", 35 [QMI_DMS_OPERATING_MODE_RESET] = "reset", 36 [QMI_DMS_OPERATING_MODE_SHUTTING_DOWN] = "shutting_down", 37 [QMI_DMS_OPERATING_MODE_PERSISTENT_LOW_POWER] = "persistent_low_power", 38 [QMI_DMS_OPERATING_MODE_MODE_ONLY_LOW_POWER] = "mode_only_low_power", 39 }; 40 41 static void cmd_dms_get_capabilities_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 42 { 43 void *t, *networks; 44 int i; 45 struct qmi_dms_get_capabilities_response res; 46 const char *radio_cap[] = { 47 [QMI_DMS_RADIO_INTERFACE_CDMA20001X] = "cdma1x", 48 [QMI_DMS_RADIO_INTERFACE_EVDO] = "cdma1xevdo", 49 [QMI_DMS_RADIO_INTERFACE_GSM] = "gsm", 50 [QMI_DMS_RADIO_INTERFACE_UMTS] = "umts", 51 [QMI_DMS_RADIO_INTERFACE_LTE] = "lte", 52 [QMI_DMS_RADIO_INTERFACE_5GNR] = "5gnr", 53 }; 54 const char *service_cap[] = { 55 [QMI_DMS_DATA_SERVICE_CAPABILITY_NONE] = "none", 56 [QMI_DMS_DATA_SERVICE_CAPABILITY_CS] = "cs", 57 [QMI_DMS_DATA_SERVICE_CAPABILITY_PS] = "ps", 58 [QMI_DMS_DATA_SERVICE_CAPABILITY_SIMULTANEOUS_CS_PS] = "simultaneous_cs_ps", 59 [QMI_DMS_DATA_SERVICE_CAPABILITY_NON_SIMULTANEOUS_CS_PS] = "non_simultaneous_cs_ps", 60 }; 61 62 qmi_parse_dms_get_capabilities_response(msg, &res); 63 64 t = blobmsg_open_table(&status, NULL); 65 66 blobmsg_add_u32(&status, "max_tx_channel_rate", (int32_t) res.data.info.max_tx_channel_rate); 67 blobmsg_add_u32(&status, "max_rx_channel_rate", (int32_t) res.data.info.max_rx_channel_rate); 68 if ((int)res.data.info.data_service_capability >= 0 && res.data.info.data_service_capability < ARRAY_SIZE(service_cap)) 69 blobmsg_add_string(&status, "data_service", service_cap[res.data.info.data_service_capability]); 70 71 if(res.data.info.sim_capability == QMI_DMS_SIM_CAPABILITY_NOT_SUPPORTED) 72 blobmsg_add_string(&status, "sim", "not supported"); 73 else if(res.data.info.sim_capability == QMI_DMS_SIM_CAPABILITY_SUPPORTED) 74 blobmsg_add_string(&status, "sim", "supported"); 75 76 networks = blobmsg_open_array(&status, "networks"); 77 for (i = 0; i < res.data.info.radio_interface_list_n; i++) { 78 if ((int)res.data.info.radio_interface_list[i] >= 0 && res.data.info.radio_interface_list[i] < ARRAY_SIZE(radio_cap)) 79 blobmsg_add_string(&status, NULL, radio_cap[res.data.info.radio_interface_list[i]]); 80 else 81 blobmsg_add_string(&status, NULL, "unknown"); 82 } 83 blobmsg_close_array(&status, networks); 84 85 blobmsg_close_table(&status, t); 86 } 87 88 static enum qmi_cmd_result 89 cmd_dms_get_capabilities_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 90 { 91 qmi_set_dms_get_capabilities_request(msg); 92 return QMI_CMD_REQUEST; 93 } 94 95 const char *get_pin_status(int status) 96 { 97 static const char *pin_status[] = { 98 [QMI_DMS_UIM_PIN_STATUS_NOT_INITIALIZED] = "not_initialized", 99 [QMI_DMS_UIM_PIN_STATUS_ENABLED_NOT_VERIFIED] = "not_verified", 100 [QMI_DMS_UIM_PIN_STATUS_ENABLED_VERIFIED] = "verified", 101 [QMI_DMS_UIM_PIN_STATUS_DISABLED] = "disabled", 102 [QMI_DMS_UIM_PIN_STATUS_BLOCKED] = "blocked", 103 [QMI_DMS_UIM_PIN_STATUS_PERMANENTLY_BLOCKED] = "permanently_blocked", 104 [QMI_DMS_UIM_PIN_STATUS_UNBLOCKED] = "unblocked", 105 [QMI_DMS_UIM_PIN_STATUS_CHANGED] = "changed", 106 }; 107 const char *res = "Unknown"; 108 109 if (status < ARRAY_SIZE(pin_status) && pin_status[status]) 110 res = pin_status[status]; 111 112 return res; 113 } 114 115 static void cmd_dms_get_pin_status_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 116 { 117 struct qmi_dms_uim_get_pin_status_response res; 118 void *c; 119 120 qmi_parse_dms_uim_get_pin_status_response(msg, &res); 121 c = blobmsg_open_table(&status, NULL); 122 if (res.set.pin1_status) { 123 blobmsg_add_string(&status, "pin1_status", get_pin_status(res.data.pin1_status.current_status)); 124 blobmsg_add_u32(&status, "pin1_verify_tries", (int32_t) res.data.pin1_status.verify_retries_left); 125 blobmsg_add_u32(&status, "pin1_unblock_tries", (int32_t) res.data.pin1_status.unblock_retries_left); 126 } 127 if (res.set.pin2_status) { 128 blobmsg_add_string(&status, "pin2_status", get_pin_status(res.data.pin2_status.current_status)); 129 blobmsg_add_u32(&status, "pin2_verify_tries", (int32_t) res.data.pin2_status.verify_retries_left); 130 blobmsg_add_u32(&status, "pin2_unblock_tries", (int32_t) res.data.pin2_status.unblock_retries_left); 131 } 132 blobmsg_close_table(&status, c); 133 } 134 135 static enum qmi_cmd_result 136 cmd_dms_get_pin_status_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 137 { 138 qmi_set_dms_uim_get_pin_status_request(msg); 139 return QMI_CMD_REQUEST; 140 } 141 142 #define cmd_dms_verify_pin1_cb no_cb 143 static enum qmi_cmd_result 144 cmd_dms_verify_pin1_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 145 { 146 struct qmi_dms_uim_verify_pin_request data = { 147 QMI_INIT_SEQUENCE(info, 148 .pin_id = QMI_DMS_UIM_PIN_ID_PIN, 149 .pin = arg 150 ) 151 }; 152 qmi_set_dms_uim_verify_pin_request(msg, &data); 153 return QMI_CMD_REQUEST; 154 } 155 156 #define cmd_dms_verify_pin2_cb no_cb 157 static enum qmi_cmd_result 158 cmd_dms_verify_pin2_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 159 { 160 struct qmi_dms_uim_verify_pin_request data = { 161 QMI_INIT_SEQUENCE(info, 162 .pin_id = QMI_DMS_UIM_PIN_ID_PIN2, 163 .pin = arg 164 ) 165 }; 166 qmi_set_dms_uim_verify_pin_request(msg, &data); 167 return QMI_CMD_REQUEST; 168 } 169 170 #define cmd_dms_set_pin_cb no_cb 171 static enum qmi_cmd_result 172 cmd_dms_set_pin_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 173 { 174 dms_req_data.pin = arg; 175 return QMI_CMD_DONE; 176 } 177 178 static enum qmi_cmd_result 179 cmd_dms_set_pin_protection_prepare(struct qmi_msg *msg, char *arg) 180 { 181 if (!dms_req_data.pin) { 182 uqmi_add_error("Missing argument"); 183 return QMI_CMD_EXIT; 184 } 185 186 int is_enabled; 187 if (strcasecmp(arg, "disabled") == 0) 188 is_enabled = false; 189 else if (strcasecmp(arg, "enabled") == 0) 190 is_enabled = true; 191 else { 192 uqmi_add_error("Invalid value (valid: disabled, enabled)"); 193 return QMI_CMD_EXIT; 194 } 195 196 struct qmi_dms_uim_set_pin_protection_request dms_pin_protection_req = { 197 QMI_INIT_SEQUENCE(info, 198 .pin_id = dms_req_data.pin_id 199 ), 200 QMI_INIT_PTR(info.pin, dms_req_data.pin), 201 QMI_INIT_PTR(info.protection_enabled, is_enabled) 202 }; 203 204 qmi_set_dms_uim_set_pin_protection_request(msg, &dms_pin_protection_req); 205 return QMI_CMD_REQUEST; 206 } 207 208 #define cmd_dms_set_pin1_protection_cb no_cb 209 static enum qmi_cmd_result 210 cmd_dms_set_pin1_protection_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 211 { 212 dms_req_data.pin_id = QMI_DMS_UIM_PIN_ID_PIN; 213 return cmd_dms_set_pin_protection_prepare(msg, arg); 214 } 215 216 #define cmd_dms_set_pin2_protection_cb no_cb 217 static enum qmi_cmd_result 218 cmd_dms_set_pin2_protection_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 219 { 220 dms_req_data.pin_id = QMI_DMS_UIM_PIN_ID_PIN2; 221 return cmd_dms_set_pin_protection_prepare(msg, arg); 222 } 223 224 static enum qmi_cmd_result 225 cmd_dms_change_pin_prepare(struct qmi_msg *msg, char *arg) 226 { 227 if (!dms_req_data.pin || !dms_req_data.new_pin) { 228 uqmi_add_error("Missing argument"); 229 return QMI_CMD_EXIT; 230 } 231 232 struct qmi_dms_uim_change_pin_request dms_change_pin_req = { 233 QMI_INIT_SEQUENCE(info, 234 .pin_id = dms_req_data.pin_id 235 ), 236 QMI_INIT_PTR(info.old_pin, dms_req_data.pin), 237 QMI_INIT_PTR(info.new_pin, dms_req_data.new_pin) 238 }; 239 240 qmi_set_dms_uim_change_pin_request(msg, &dms_change_pin_req); 241 return QMI_CMD_REQUEST; 242 } 243 244 #define cmd_dms_change_pin1_cb no_cb 245 static enum qmi_cmd_result 246 cmd_dms_change_pin1_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 247 { 248 dms_req_data.pin_id = QMI_DMS_UIM_PIN_ID_PIN; 249 return cmd_dms_change_pin_prepare(msg, arg); 250 } 251 252 #define cmd_dms_change_pin2_cb no_cb 253 static enum qmi_cmd_result 254 cmd_dms_change_pin2_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 255 { 256 dms_req_data.pin_id = QMI_DMS_UIM_PIN_ID_PIN2; 257 return cmd_dms_change_pin_prepare(msg, arg); 258 } 259 260 #define cmd_dms_set_new_pin_cb no_cb 261 static enum qmi_cmd_result 262 cmd_dms_set_new_pin_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 263 { 264 dms_req_data.new_pin = arg; 265 return QMI_CMD_DONE; 266 } 267 268 #define cmd_dms_set_puk_cb no_cb 269 static enum qmi_cmd_result 270 cmd_dms_set_puk_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 271 { 272 dms_req_data.puk = arg; 273 return QMI_CMD_DONE; 274 } 275 276 #define cmd_dms_unblock_pin1_cb no_cb 277 static enum qmi_cmd_result 278 cmd_dms_unblock_pin1_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 279 { 280 if (!dms_req_data.puk || !dms_req_data.new_pin) { 281 uqmi_add_error("Missing argument"); 282 return QMI_CMD_EXIT; 283 } 284 285 struct qmi_dms_uim_unblock_pin_request dms_unlock_pin_req = { 286 QMI_INIT_SEQUENCE(info, 287 .pin_id = QMI_DMS_UIM_PIN_ID_PIN 288 ), 289 QMI_INIT_PTR(info.puk, dms_req_data.puk), 290 QMI_INIT_PTR(info.new_pin, dms_req_data.new_pin) 291 }; 292 293 qmi_set_dms_uim_unblock_pin_request(msg, &dms_unlock_pin_req); 294 return QMI_CMD_REQUEST; 295 } 296 297 #define cmd_dms_unblock_pin2_cb no_cb 298 static enum qmi_cmd_result 299 cmd_dms_unblock_pin2_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 300 { 301 if (!dms_req_data.puk || !dms_req_data.new_pin) { 302 uqmi_add_error("Missing argument"); 303 return QMI_CMD_EXIT; 304 } 305 306 struct qmi_dms_uim_unblock_pin_request dms_unlock_pin_req = { 307 QMI_INIT_SEQUENCE(info, 308 .pin_id = QMI_DMS_UIM_PIN_ID_PIN2 309 ), 310 QMI_INIT_PTR(info.puk, dms_req_data.puk), 311 QMI_INIT_PTR(info.new_pin, dms_req_data.new_pin) 312 }; 313 314 qmi_set_dms_uim_unblock_pin_request(msg, &dms_unlock_pin_req); 315 return QMI_CMD_REQUEST; 316 } 317 318 static void cmd_dms_get_iccid_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 319 { 320 struct qmi_dms_uim_get_iccid_response res; 321 322 qmi_parse_dms_uim_get_iccid_response(msg, &res); 323 if (res.data.iccid) 324 blobmsg_add_string(&status, NULL, res.data.iccid); 325 } 326 327 static enum qmi_cmd_result 328 cmd_dms_get_iccid_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 329 { 330 qmi_set_dms_uim_get_iccid_request(msg); 331 return QMI_CMD_REQUEST; 332 } 333 334 static void cmd_dms_get_imsi_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 335 { 336 struct qmi_dms_uim_get_imsi_response res; 337 338 qmi_parse_dms_uim_get_imsi_response(msg, &res); 339 if (res.data.imsi) 340 blobmsg_add_string(&status, NULL, res.data.imsi); 341 } 342 343 static enum qmi_cmd_result 344 cmd_dms_get_imsi_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 345 { 346 qmi_set_dms_uim_get_imsi_request(msg); 347 return QMI_CMD_REQUEST; 348 } 349 350 static void cmd_dms_get_msisdn_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 351 { 352 struct qmi_dms_get_msisdn_response res; 353 354 qmi_parse_dms_get_msisdn_response(msg, &res); 355 if (res.data.msisdn) 356 blobmsg_add_string(&status, NULL, res.data.msisdn); 357 } 358 359 static enum qmi_cmd_result 360 cmd_dms_get_msisdn_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 361 { 362 qmi_set_dms_get_msisdn_request(msg); 363 return QMI_CMD_REQUEST; 364 } 365 366 static void cmd_dms_get_imei_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 367 { 368 struct qmi_dms_get_ids_response res; 369 370 qmi_parse_dms_get_ids_response(msg, &res); 371 if (res.data.imei) 372 blobmsg_add_string(&status, NULL, res.data.imei); 373 } 374 375 static enum qmi_cmd_result 376 cmd_dms_get_imei_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 377 { 378 qmi_set_dms_get_ids_request(msg); 379 return QMI_CMD_REQUEST; 380 } 381 382 #define cmd_dms_reset_cb no_cb 383 static enum qmi_cmd_result 384 cmd_dms_reset_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 385 { 386 qmi_set_dms_reset_request(msg); 387 return QMI_CMD_REQUEST; 388 } 389 390 static void 391 cmd_dms_get_operating_mode_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 392 { 393 struct qmi_dms_get_operating_mode_response res; 394 395 qmi_parse_dms_get_operating_mode_response(msg, &res); 396 if (res.data.mode < ARRAY_SIZE(oper_modes)) 397 blobmsg_add_string(&status, NULL, oper_modes[res.data.mode]); 398 else 399 blobmsg_add_string(&status, NULL, "unknown"); 400 } 401 402 static enum qmi_cmd_result 403 cmd_dms_get_operating_mode_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 404 { 405 qmi_set_dms_get_operating_mode_request(msg); 406 return QMI_CMD_REQUEST; 407 } 408 409 #define cmd_dms_set_operating_mode_cb no_cb 410 static enum qmi_cmd_result 411 cmd_dms_set_operating_mode_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 412 { 413 static struct qmi_dms_set_operating_mode_request sreq = { 414 QMI_INIT(mode, QMI_DMS_OPERATING_MODE_ONLINE), 415 }; 416 int i; 417 418 for (i = 0; i < ARRAY_SIZE(oper_modes); i++) { 419 if (!oper_modes[i]) 420 continue; 421 422 if (strcmp(arg, oper_modes[i]) != 0) 423 continue; 424 425 sreq.data.mode = i; 426 qmi_set_dms_set_operating_mode_request(msg, &sreq); 427 return QMI_CMD_REQUEST; 428 } 429 430 return uqmi_add_error("Invalid argument"); 431 } 432 433 #define cmd_dms_set_fcc_authentication_cb no_cb 434 static enum qmi_cmd_result 435 cmd_dms_set_fcc_authentication_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 436 { 437 qmi_set_dms_set_fcc_authentication_request(msg); 438 return QMI_CMD_REQUEST; 439 } 440
This page was automatically generated by LXR 0.3.1. • OpenWrt