1 /** @file 2 * @brief HL7800 modem public API header file. 3 * 4 * Allows an application to control the HL7800 modem. 5 * 6 * Copyright (c) 2020 Laird Connectivity 7 * 8 * SPDX-License-Identifier: Apache-2.0 9 */ 10 11 #ifndef ZEPHYR_INCLUDE_DRIVERS_MODEM_HL7800_H_ 12 #define ZEPHYR_INCLUDE_DRIVERS_MODEM_HL7800_H_ 13 14 #ifdef __cplusplus 15 extern "C" { 16 #endif 17 18 #include <zephyr/types.h> 19 20 #include <time.h> 21 22 /* The size includes the NUL character, the strlen doesn't */ 23 #define MDM_HL7800_REVISION_MAX_SIZE 29 24 #define MDM_HL7800_REVISION_MAX_STRLEN (MDM_HL7800_REVISION_MAX_SIZE - 1) 25 26 #define MDM_HL7800_IMEI_SIZE 16 27 #define MDM_HL7800_IMEI_STRLEN (MDM_HL7800_IMEI_SIZE - 1) 28 29 #define MDM_HL7800_ICCID_MAX_SIZE 21 30 #define MDM_HL7800_ICCID_MAX_STRLEN (MDM_HL7800_ICCID_MAX_SIZE - 1) 31 32 #define MDM_HL7800_SERIAL_NUMBER_SIZE 15 33 #define MDM_HL7800_SERIAL_NUMBER_STRLEN (MDM_HL7800_SERIAL_NUMBER_SIZE - 1) 34 35 #define MDM_HL7800_APN_MAX_SIZE 64 36 #define MDM_HL7800_APN_USERNAME_MAX_SIZE 65 37 #define MDM_HL7800_APN_PASSWORD_MAX_SIZE 65 38 39 #define MDM_HL7800_APN_MAX_STRLEN (MDM_HL7800_APN_MAX_SIZE - 1) 40 #define MDM_HL7800_APN_USERNAME_MAX_STRLEN \ 41 (MDM_HL7800_APN_USERNAME_MAX_SIZE - 1) 42 #define MDM_HL7800_APN_PASSWORD_MAX_STRLEN \ 43 (MDM_HL7800_APN_PASSWORD_MAX_SIZE - 1) 44 45 #define MDM_HL7800_APN_CMD_MAX_SIZE \ 46 (32 + MDM_HL7800_APN_USERNAME_MAX_STRLEN + \ 47 MDM_HL7800_APN_PASSWORD_MAX_STRLEN) 48 49 #define MDM_HL7800_APN_CMD_MAX_STRLEN (MDM_HL7800_APN_CMD_MAX_SIZE - 1) 50 51 struct mdm_hl7800_apn { 52 char value[MDM_HL7800_APN_MAX_SIZE]; 53 char username[MDM_HL7800_APN_USERNAME_MAX_SIZE]; 54 char password[MDM_HL7800_APN_PASSWORD_MAX_SIZE]; 55 }; 56 57 #define MDM_HL7800_LTE_BAND_STR_SIZE 21 58 #define MDM_HL7800_LTE_BAND_STRLEN (MDM_HL7800_LTE_BAND_STR_SIZE - 1) 59 60 #define MDM_HL7800_OPERATOR_INDEX_SIZE 3 61 #define MDM_HL7800_OPERATOR_INDEX_STRLEN (MDM_HL7800_OPERATOR_INDEX_SIZE - 1) 62 63 #define MDM_HL7800_IMSI_MIN_STR_SIZE 15 64 #define MDM_HL7800_IMSI_MAX_STR_SIZE 16 65 #define MDM_HL7800_IMSI_MAX_STRLEN (MDM_HL7800_IMSI_MAX_STR_SIZE - 1) 66 67 #define MDM_HL7800_MODEM_FUNCTIONALITY_SIZE 2 68 #define MDM_HL7800_MODEM_FUNCTIONALITY_STRLEN \ 69 (MDM_HL7800_MODEM_FUNCTIONALITY_SIZE - 1) 70 71 #define MDM_HL7800_MAX_GPS_STR_SIZE 33 72 73 #define MDM_HL7800_MAX_POLTE_USER_ID_SIZE 16 74 #define MDM_HL7800_MAX_POLTE_PASSWORD_SIZE 16 75 #define MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE 33 76 77 /* Assign the server error code (location response) to a value 78 * that isn't used by locate response so that a single status 79 * callback can be used. 80 */ 81 #define MDM_HL7800_POLTE_SERVER_ERROR 10 82 83 #define MDM_HL7800_SET_POLTE_USER_AND_PASSWORD_FMT_STR "AT%%POLTECMD=\"SERVERAUTH\",\"%s\",\"%s\"" 84 85 struct mdm_hl7800_site_survey { 86 uint32_t earfcn; /* EUTRA Absolute Radio Frequency Channel Number */ 87 uint32_t cell_id; 88 int rsrp; 89 int rsrq; 90 }; 91 92 enum mdm_hl7800_radio_mode { MDM_RAT_CAT_M1 = 0, MDM_RAT_CAT_NB1 }; 93 94 enum mdm_hl7800_event { 95 HL7800_EVENT_RESERVED = 0, 96 HL7800_EVENT_NETWORK_STATE_CHANGE, 97 HL7800_EVENT_APN_UPDATE, 98 HL7800_EVENT_RSSI, 99 HL7800_EVENT_SINR, 100 HL7800_EVENT_STARTUP_STATE_CHANGE, 101 HL7800_EVENT_SLEEP_STATE_CHANGE, 102 HL7800_EVENT_RAT, 103 HL7800_EVENT_BANDS, 104 HL7800_EVENT_ACTIVE_BANDS, 105 HL7800_EVENT_FOTA_STATE, 106 HL7800_EVENT_FOTA_COUNT, 107 HL7800_EVENT_REVISION, 108 HL7800_EVENT_GPS, 109 HL7800_EVENT_GPS_POSITION_STATUS, 110 HL7800_EVENT_POLTE_REGISTRATION, 111 HL7800_EVENT_POLTE_LOCATE_STATUS, 112 HL7800_EVENT_POLTE, 113 HL7800_EVENT_SITE_SURVEY, 114 }; 115 116 enum mdm_hl7800_startup_state { 117 HL7800_STARTUP_STATE_READY = 0, 118 HL7800_STARTUP_STATE_WAITING_FOR_ACCESS_CODE, 119 HL7800_STARTUP_STATE_SIM_NOT_PRESENT, 120 HL7800_STARTUP_STATE_SIMLOCK, 121 HL7800_STARTUP_STATE_UNRECOVERABLE_ERROR, 122 HL7800_STARTUP_STATE_UNKNOWN, 123 HL7800_STARTUP_STATE_INACTIVE_SIM 124 }; 125 126 enum mdm_hl7800_network_state { 127 HL7800_NOT_REGISTERED = 0, 128 HL7800_HOME_NETWORK, 129 HL7800_SEARCHING, 130 HL7800_REGISTRATION_DENIED, 131 HL7800_OUT_OF_COVERAGE, 132 HL7800_ROAMING, 133 HL7800_EMERGENCY = 8, 134 /* Laird defined states */ 135 HL7800_UNABLE_TO_CONFIGURE = 0xf0 136 }; 137 138 enum mdm_hl7800_sleep { 139 HL7800_SLEEP_UNINITIALIZED = 0, 140 HL7800_SLEEP_HIBERNATE, 141 HL7800_SLEEP_AWAKE, 142 HL7800_SLEEP_LITE_HIBERNATE, 143 HL7800_SLEEP_SLEEP, 144 }; 145 146 enum mdm_hl7800_fota_state { 147 HL7800_FOTA_IDLE, 148 HL7800_FOTA_START, 149 HL7800_FOTA_WIP, 150 HL7800_FOTA_PAD, 151 HL7800_FOTA_SEND_EOT, 152 HL7800_FOTA_FILE_ERROR, 153 HL7800_FOTA_INSTALL, 154 HL7800_FOTA_REBOOT_AND_RECONFIGURE, 155 HL7800_FOTA_COMPLETE, 156 }; 157 158 enum mdm_hl7800_functionality { 159 HL7800_FUNCTIONALITY_MINIMUM = 0, 160 HL7800_FUNCTIONALITY_FULL = 1, 161 HL7800_FUNCTIONALITY_AIRPLANE = 4 162 }; 163 164 /* The modem reports state values as an enumeration and a string. 165 * GPS values are reported with a type of value and string. 166 */ 167 struct mdm_hl7800_compound_event { 168 uint8_t code; 169 char *string; 170 }; 171 172 enum mdm_hl7800_gnss_event { 173 HL7800_GNSS_EVENT_INVALID = -1, 174 HL7800_GNSS_EVENT_INIT, 175 HL7800_GNSS_EVENT_START, 176 HL7800_GNSS_EVENT_STOP, 177 HL7800_GNSS_EVENT_POSITION, 178 }; 179 180 enum mdm_hl7800_gnss_status { 181 HL7800_GNSS_STATUS_INVALID = -1, 182 HL7800_GNSS_STATUS_FAILURE, 183 HL7800_GNSS_STATUS_SUCCESS, 184 }; 185 186 enum mdm_hl7800_gnss_position_event { 187 HL7800_GNSS_POSITION_EVENT_INVALID = -1, 188 HL7800_GNSS_POSITION_EVENT_LOST_OR_NOT_AVAILABLE_YET, 189 HL7800_GNSS_POSITION_EVENT_PREDICTION_AVAILABLE, 190 HL7800_GNSS_POSITION_EVENT_2D_AVAILABLE, 191 HL7800_GNSS_POSITION_EVENT_3D_AVAILABLE, 192 HL7800_GNSS_POSITION_EVENT_FIXED_TO_INVALID, 193 }; 194 195 enum mdm_hl7800_gps_string_types { 196 HL7800_GPS_STR_LATITUDE, 197 HL7800_GPS_STR_LONGITUDE, 198 HL7800_GPS_STR_GPS_TIME, 199 HL7800_GPS_STR_FIX_TYPE, 200 HL7800_GPS_STR_HEPE, 201 HL7800_GPS_STR_ALTITUDE, 202 HL7800_GPS_STR_ALT_UNC, 203 HL7800_GPS_STR_DIRECTION, 204 HL7800_GPS_STR_HOR_SPEED, 205 HL7800_GPS_STR_VER_SPEED 206 }; 207 208 /* status: negative errno, 0 on success 209 * user and password aren't valid if status is non-zero. 210 */ 211 struct mdm_hl7800_polte_registration_event_data { 212 int status; 213 char *user; 214 char *password; 215 }; 216 217 /* status: negative errno, 0 on success, non-zero error code 218 * Data is not valid if status is non-zero. 219 */ 220 struct mdm_hl7800_polte_location_data { 221 uint32_t timestamp; 222 int status; 223 char latitude[MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE]; 224 char longitude[MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE]; 225 char confidence_in_meters[MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE]; 226 }; 227 228 /** 229 * event - The type of event 230 * event_data - Pointer to event specific data structure 231 * HL7800_EVENT_NETWORK_STATE_CHANGE - compound event 232 * HL7800_EVENT_APN_UPDATE - struct mdm_hl7800_apn 233 * HL7800_EVENT_RSSI - int 234 * HL7800_EVENT_SINR - int 235 * HL7800_EVENT_STARTUP_STATE_CHANGE - compound event 236 * HL7800_EVENT_SLEEP_STATE_CHANGE - compound event 237 * HL7800_EVENT_RAT - int 238 * HL7800_EVENT_BANDS - string 239 * HL7800_EVENT_ACTIVE_BANDS - string 240 * HL7800_EVENT_FOTA_STATE - compound event 241 * HL7800_EVENT_FOTA_COUNT - uint32_t 242 * HL7800_EVENT_REVISION - string 243 * HL7800_EVENT_GPS - compound event 244 * HL7800_EVENT_GPS_POSITION_STATUS int 245 * HL7800_EVENT_POLTE_REGISTRATION mdm_hl7800_polte_registration_event_data 246 * HL7800_EVENT_POLTE mdm_hl7800_polte_location_data 247 * HL7800_EVENT_POLTE_LOCATE_STATUS int 248 * HL7800_EVENT_SITE_SURVEY mdm_hl7800_site_survey 249 */ 250 typedef void (*mdm_hl7800_event_callback_t)(enum mdm_hl7800_event event, 251 void *event_data); 252 253 struct mdm_hl7800_callback_agent { 254 sys_snode_t node; 255 mdm_hl7800_event_callback_t event_callback; 256 }; 257 258 /** 259 * @brief Power off the HL7800 260 * 261 * @return int32_t 0 for success 262 */ 263 int32_t mdm_hl7800_power_off(void); 264 265 /** 266 * @brief Reset the HL7800 (and allow it to reconfigure). 267 * 268 * @return int32_t 0 for success 269 */ 270 int32_t mdm_hl7800_reset(void); 271 272 /** 273 * @brief Control the wake signals to the HL7800. 274 * @note this API should only be used for debug purposes. 275 * 276 * @param awake True to keep the HL7800 awake, False to allow sleep 277 */ 278 void mdm_hl7800_wakeup(bool awake); 279 280 /** 281 * @brief Send an AT command to the HL7800. 282 * @note this API should only be used for debug purposes. 283 * 284 * @param data AT command string 285 * @return int32_t 0 for success 286 */ 287 int32_t mdm_hl7800_send_at_cmd(const uint8_t *data); 288 289 /** 290 * @brief Get the signal quality of the HL7800. 291 * If CONFIG_MODEM_HL7800_RSSI_RATE_SECONDS is non-zero, then 292 * this function returns the value from the last periodic read. 293 * If CONFIG_MODEM_HL7800_RSSI_RATE_SECONDS is 0, then this 294 * may cause the modem to be woken so that the values can be queried. 295 * 296 * @param rsrp Reference Signals Received Power (dBm) 297 * Range = -140 dBm to -44 dBm 298 * @param sinr Signal to Interference plus Noise Ratio (dB) 299 * Range = -128 dB to 40 dB 300 */ 301 void mdm_hl7800_get_signal_quality(int *rsrp, int *sinr); 302 303 /** 304 * @brief Get the SIM card ICCID 305 * 306 */ 307 char *mdm_hl7800_get_iccid(void); 308 309 /** 310 * @brief Get the HL7800 serial number 311 * 312 */ 313 char *mdm_hl7800_get_sn(void); 314 315 /** 316 * @brief Get the HL7800 IMEI 317 * 318 */ 319 char *mdm_hl7800_get_imei(void); 320 321 /** 322 * @brief Get the HL7800 firmware version 323 * 324 */ 325 char *mdm_hl7800_get_fw_version(void); 326 327 /** 328 * @brief Get the IMSI 329 * 330 */ 331 char *mdm_hl7800_get_imsi(void); 332 333 /** 334 * @brief Update the Access Point Name in the modem. 335 * 336 * @retval 0 on success, negative on failure. 337 */ 338 int32_t mdm_hl7800_update_apn(char *access_point_name); 339 340 /** 341 * @brief Update the Radio Access Technology (mode). 342 * 343 * @retval 0 on success, negative on failure. 344 */ 345 int32_t mdm_hl7800_update_rat(enum mdm_hl7800_radio_mode value); 346 347 /** 348 * @retval true if RAT value is valid 349 */ 350 bool mdm_hl7800_valid_rat(uint8_t value); 351 352 /** 353 * @brief Register a function that is called when a modem event occurs. 354 * Multiple users registering for callbacks is supported. 355 * 356 * @param agent event callback agent 357 * 358 * @retval 0 on success, negative on failure 359 */ 360 int mdm_hl7800_register_event_callback(struct mdm_hl7800_callback_agent *agent); 361 362 /** 363 * @brief Unregister a callback event function 364 * 365 * @param agent event callback agent 366 * 367 * @retval 0 on success, negative on failure 368 */ 369 int mdm_hl7800_unregister_event_callback(struct mdm_hl7800_callback_agent *agent); 370 371 /** 372 * @brief Force modem module to generate status events. 373 * 374 * @note This can be used to get the current state when a module initializes 375 * later than the modem. 376 */ 377 void mdm_hl7800_generate_status_events(void); 378 379 /** 380 * @brief Get the local time from the modem's real time clock. 381 * 382 * @param tm time structure 383 * @param offset The amount the local time is offset from GMT/UTC in seconds. 384 * @return int32_t 0 if successful 385 */ 386 int32_t mdm_hl7800_get_local_time(struct tm *tm, int32_t *offset); 387 388 #ifdef CONFIG_MODEM_HL7800_FW_UPDATE 389 /** 390 * @brief Update the HL7800 via XMODEM protocol. During the firmware update 391 * no other modem fuctions will be available. 392 * 393 * @param file_path Absolute path of the update file 394 * 395 * @param 0 if successful 396 */ 397 int32_t mdm_hl7800_update_fw(char *file_path); 398 #endif 399 400 /** 401 * @brief Read the operator index from the modem. 402 * 403 * @retval negative error code, 0 on success 404 */ 405 int32_t mdm_hl7800_get_operator_index(void); 406 407 /** 408 * @brief Get modem functionality 409 * 410 * @return int32_t negative errno on failure, else mdm_hl7800_functionality 411 */ 412 int32_t mdm_hl7800_get_functionality(void); 413 414 /** 415 * @brief Set airplane, normal, or reduced functionality mode. 416 * Airplane mode persists when reset. 417 * 418 * @note Boot functionality is also controlled by Kconfig 419 * MODEM_HL7800_BOOT_IN_AIRPLANE_MODE. 420 * 421 * @param mode 422 * @return int32_t negative errno, 0 on success 423 */ 424 int32_t mdm_hl7800_set_functionality(enum mdm_hl7800_functionality mode); 425 426 /** 427 * @brief When rate is non-zero: Put modem into Airplane mode. Enable GPS and 428 * generate HL7800_EVENT_GPS events. 429 * When zero: Disable GPS and put modem into normal mode. 430 * 431 * @note Airplane mode isn't cleared when the modem is reset. 432 * 433 * @param rate in seconds to query location 434 * @return int32_t negative errno, 0 on success 435 */ 436 int32_t mdm_hl7800_set_gps_rate(uint32_t rate); 437 438 /** 439 * @brief Register modem/SIM with polte.io 440 * 441 * @note It takes around 30 seconds for HL7800_EVENT_POLTE_REGISTRATION to 442 * be generated. If the applications saves the user and password 443 * information into non-volatile memory, then this command 444 * only needs to be run once. 445 * 446 * @return int32_t negative errno, 0 on success 447 */ 448 int32_t mdm_hl7800_polte_register(void); 449 450 /** 451 * @brief Enable PoLTE. 452 * 453 * @param user from polte.io or register command callback 454 * @param password from polte.io register command callback 455 * @return int32_t negative errno, 0 on success 456 */ 457 int32_t mdm_hl7800_polte_enable(char *user, char *password); 458 459 /** 460 * @brief Locate device using PoLTE. 461 * 462 * @note The first HL7800_EVENT_POLTE_LOCATE_STATUS event indicates 463 * the status of issuing the locate command. The second event 464 * requires 20-120 seconds to be generated and it contains the 465 * location information (or indicates server failure). 466 * 467 * @return int32_t negative errno, 0 on success 468 */ 469 int32_t mdm_hl7800_polte_locate(void); 470 471 /** 472 * @brief Perform a site survey. This command may return different values 473 * each time it is run (depending on what is in range). 474 * 475 * HL7800_EVENT_SITE_SURVEY is generated for each response received from modem. 476 * 477 * @retval negative error code, 0 on success 478 */ 479 int32_t mdm_hl7800_perform_site_survey(void); 480 481 /** 482 * @brief Set desired sleep level. Requires MODEM_HL7800_LOW_POWER_MODE 483 * 484 * @param level (sleep, lite hibernate, or hibernate) 485 * @return int negative errno, 0 on success 486 */ 487 int mdm_hl7800_set_desired_sleep_level(enum mdm_hl7800_sleep level); 488 489 /** 490 * @brief Allows mapping of WAKE_UP signal 491 * to a user accessible test point on the development board. 492 * 493 * @param func to be called when application requests modem wake/sleep. 494 * The state parameter of the callback is 1 when modem should stay awake, 495 * 0 when modem can sleep 496 */ 497 void mdm_hl7800_register_wake_test_point_callback(void (*func)(int state)); 498 499 /** 500 * @brief Allows mapping of P1.12_GPIO6 signal 501 * to a user accessible test point on the development board. 502 * 503 * @param func to be called when modem wakes/sleeps is sleep level is 504 * hibernate or lite hibernate. 505 * The state parameter of the callback follows gpio_pin_get definitions, 506 * but will default high if there is an error reading pin 507 */ 508 void mdm_hl7800_register_gpio6_callback(void (*func)(int state)); 509 510 /** 511 * @brief Allows mapping of UART1_CTS signal 512 * to a user accessible test point on the development board. 513 * 514 * @param func to be called when CTS state changes if sleep level is sleep. 515 * The state parameter of the callback follows gpio_pin_get definitions, 516 * but will default low if there is an error reading pin 517 */ 518 void mdm_hl7800_register_cts_callback(void (*func)(int state)); 519 520 /** 521 * @brief Set the bands available for the LTE connection. 522 * NOTE: This will cause the modem to reboot. This call returns before the reboot. 523 * 524 * @param bands Band bitmap in hexadecimal format without the 0x prefix. 525 * Leading 0's for the value can be ommited. 526 * 527 * @return int32_t negative errno, 0 on success 528 */ 529 int32_t mdm_hl7800_set_bands(const char *bands); 530 531 /** 532 * @brief Set the log level for the modem. 533 * 534 * @note It cannot be set higher than CONFIG_MODEM_LOG_LEVEL. 535 * If debug level is desired, then it must be compiled with that level. 536 * 537 * @param level 0 (None) - 4 (Debug) 538 * 539 * @retval new log level 540 */ 541 uint32_t mdm_hl7800_log_filter_set(uint32_t level); 542 543 #ifdef __cplusplus 544 } 545 #endif 546 547 #endif /* ZEPHYR_INCLUDE_DRIVERS_MODEM_HL7800_H_ */ 548