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