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 #ifdef CONFIG_NEWLIB_LIBC 21 #include <time.h> 22 #endif 23 24 /* The size includes the NUL character, the strlen doesn't */ 25 #define MDM_HL7800_REVISION_MAX_SIZE 29 26 #define MDM_HL7800_REVISION_MAX_STRLEN (MDM_HL7800_REVISION_MAX_SIZE - 1) 27 28 #define MDM_HL7800_IMEI_SIZE 16 29 #define MDM_HL7800_IMEI_STRLEN (MDM_HL7800_IMEI_SIZE - 1) 30 31 #define MDM_HL7800_ICCID_SIZE 21 32 #define MDM_HL7800_ICCID_STRLEN (MDM_HL7800_ICCID_SIZE - 1) 33 34 #define MDM_HL7800_SERIAL_NUMBER_SIZE 15 35 #define MDM_HL7800_SERIAL_NUMBER_STRLEN (MDM_HL7800_SERIAL_NUMBER_SIZE - 1) 36 37 #define MDM_HL7800_APN_MAX_SIZE 64 38 #define MDM_HL7800_APN_USERNAME_MAX_SIZE 65 39 #define MDM_HL7800_APN_PASSWORD_MAX_SIZE 65 40 41 #define MDM_HL7800_APN_MAX_STRLEN (MDM_HL7800_APN_MAX_SIZE - 1) 42 #define MDM_HL7800_APN_USERNAME_MAX_STRLEN \ 43 (MDM_HL7800_APN_USERNAME_MAX_SIZE - 1) 44 #define MDM_HL7800_APN_PASSWORD_MAX_STRLEN \ 45 (MDM_HL7800_APN_PASSWORD_MAX_SIZE - 1) 46 47 #define MDM_HL7800_APN_CMD_MAX_SIZE \ 48 (32 + MDM_HL7800_APN_USERNAME_MAX_STRLEN + \ 49 MDM_HL7800_APN_PASSWORD_MAX_STRLEN) 50 51 #define MDM_HL7800_APN_CMD_MAX_STRLEN (MDM_HL7800_APN_CMD_MAX_SIZE - 1) 52 53 struct mdm_hl7800_apn { 54 char value[MDM_HL7800_APN_MAX_SIZE]; 55 char username[MDM_HL7800_APN_USERNAME_MAX_SIZE]; 56 char password[MDM_HL7800_APN_PASSWORD_MAX_SIZE]; 57 }; 58 59 #define MDM_HL7800_LTE_BAND_STR_SIZE 21 60 #define MDM_HL7800_LTE_BAND_STRLEN (MDM_HL7800_LTE_BAND_STR_SIZE - 1) 61 62 #define MDM_HL7800_OPERATOR_INDEX_SIZE 3 63 #define MDM_HL7800_OPERATOR_INDEX_STRLEN (MDM_HL7800_OPERATOR_INDEX_SIZE - 1) 64 65 #define MDM_HL7800_IMSI_MIN_STR_SIZE 15 66 #define MDM_HL7800_IMSI_MAX_STR_SIZE 16 67 #define MDM_HL7800_IMSI_MAX_STRLEN (MDM_HL7800_IMSI_MAX_STR_SIZE - 1) 68 69 #define MDM_HL7800_MODEM_FUNCTIONALITY_SIZE 2 70 #define MDM_HL7800_MODEM_FUNCTIONALITY_STRLEN \ 71 (MDM_HL7800_MODEM_FUNCTIONALITY_SIZE - 1) 72 73 #define MDM_HL7800_MAX_GPS_STR_SIZE 33 74 75 #define MDM_HL7800_MAX_POLTE_USER_ID_SIZE 16 76 #define MDM_HL7800_MAX_POLTE_PASSWORD_SIZE 16 77 #define MDM_HL7800_MAX_POLTE_LOCATION_STR_SIZE 33 78 79 /* Assign the server error code (location response) to a value 80 * that isn't used by locate response so that a single status 81 * callback can be used. 82 */ 83 #define MDM_HL7800_POLTE_SERVER_ERROR 10 84 85 #define MDM_HL7800_SET_POLTE_USER_AND_PASSWORD_FMT_STR "AT%%POLTECMD=\"SERVERAUTH\",\"%s\",\"%s\"" 86 87 struct mdm_hl7800_site_survey { 88 uint32_t earfcn; /* EUTRA Absolute Radio Frequency Channel Number */ 89 uint32_t cell_id; 90 int rsrp; 91 int rsrq; 92 }; 93 94 enum mdm_hl7800_radio_mode { MDM_RAT_CAT_M1 = 0, MDM_RAT_CAT_NB1 }; 95 96 enum mdm_hl7800_event { 97 HL7800_EVENT_RESERVED = 0, 98 HL7800_EVENT_NETWORK_STATE_CHANGE, 99 HL7800_EVENT_APN_UPDATE, 100 HL7800_EVENT_RSSI, 101 HL7800_EVENT_SINR, 102 HL7800_EVENT_STARTUP_STATE_CHANGE, 103 HL7800_EVENT_SLEEP_STATE_CHANGE, 104 HL7800_EVENT_RAT, 105 HL7800_EVENT_BANDS, 106 HL7800_EVENT_ACTIVE_BANDS, 107 HL7800_EVENT_FOTA_STATE, 108 HL7800_EVENT_FOTA_COUNT, 109 HL7800_EVENT_REVISION, 110 HL7800_EVENT_GPS, 111 HL7800_EVENT_GPS_POSITION_STATUS, 112 HL7800_EVENT_POLTE_REGISTRATION, 113 HL7800_EVENT_POLTE_LOCATE_STATUS, 114 HL7800_EVENT_POLTE, 115 HL7800_EVENT_SITE_SURVEY, 116 }; 117 118 enum mdm_hl7800_startup_state { 119 HL7800_STARTUP_STATE_READY = 0, 120 HL7800_STARTUP_STATE_WAITING_FOR_ACCESS_CODE, 121 HL7800_STARTUP_STATE_SIM_NOT_PRESENT, 122 HL7800_STARTUP_STATE_SIMLOCK, 123 HL7800_STARTUP_STATE_UNRECOVERABLE_ERROR, 124 HL7800_STARTUP_STATE_UNKNOWN, 125 HL7800_STARTUP_STATE_INACTIVE_SIM 126 }; 127 128 enum mdm_hl7800_network_state { 129 HL7800_NOT_REGISTERED = 0, 130 HL7800_HOME_NETWORK, 131 HL7800_SEARCHING, 132 HL7800_REGISTRATION_DENIED, 133 HL7800_OUT_OF_COVERAGE, 134 HL7800_ROAMING, 135 HL7800_EMERGENCY = 8, 136 /* Laird defined states */ 137 HL7800_UNABLE_TO_CONFIGURE = 0xf0 138 }; 139 140 enum mdm_hl7800_sleep_state { 141 HL7800_SLEEP_STATE_UNINITIALIZED = 0, 142 HL7800_SLEEP_STATE_ASLEEP, 143 HL7800_SLEEP_STATE_AWAKE 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 /** 254 * @brief Power off the HL7800 255 * 256 * @return int32_t 0 for success 257 */ 258 int32_t mdm_hl7800_power_off(void); 259 260 /** 261 * @brief Reset the HL7800 (and allow it to reconfigure). 262 * 263 * @return int32_t 0 for success 264 */ 265 int32_t mdm_hl7800_reset(void); 266 267 /** 268 * @brief Control the wake signals to the HL7800. 269 * @note this API should only be used for debug purposes. 270 * 271 * @param awake True to keep the HL7800 awake, False to allow sleep 272 */ 273 void mdm_hl7800_wakeup(bool awake); 274 275 /** 276 * @brief Send an AT command to the HL7800. 277 * @note this API should only be used for debug purposes. 278 * 279 * @param data AT command string 280 * @return int32_t 0 for success 281 */ 282 int32_t mdm_hl7800_send_at_cmd(const uint8_t *data); 283 284 /** 285 * @brief Get the signal quality of the HL7800 286 * 287 * @param rsrp Reference Signals Received Power (dBm) 288 * Range = -140 dBm to -44 dBm 289 * @param sinr Signal to Interference plus Noise Ratio (dBm) 290 * Range = -128 dBm to 40dBm 291 */ 292 void mdm_hl7800_get_signal_quality(int *rsrp, int *sinr); 293 294 /** 295 * @brief Get the SIM card ICCID 296 * 297 */ 298 char *mdm_hl7800_get_iccid(void); 299 300 /** 301 * @brief Get the HL7800 serial number 302 * 303 */ 304 char *mdm_hl7800_get_sn(void); 305 306 /** 307 * @brief Get the HL7800 IMEI 308 * 309 */ 310 char *mdm_hl7800_get_imei(void); 311 312 /** 313 * @brief Get the HL7800 firmware version 314 * 315 */ 316 char *mdm_hl7800_get_fw_version(void); 317 318 /** 319 * @brief Get the IMSI 320 * 321 */ 322 char *mdm_hl7800_get_imsi(void); 323 324 /** 325 * @brief Update the Access Point Name in the modem. 326 * 327 * @retval 0 on success, negative on failure. 328 */ 329 int32_t mdm_hl7800_update_apn(char *access_point_name); 330 331 /** 332 * @brief Update the Radio Access Technology (mode). 333 * 334 * @retval 0 on success, negative on failure. 335 */ 336 int32_t mdm_hl7800_update_rat(enum mdm_hl7800_radio_mode value); 337 338 /** 339 * @retval true if RAT value is valid 340 */ 341 bool mdm_hl7800_valid_rat(uint8_t value); 342 343 /** 344 * @brief Register a function that is called when a modem event occurs. 345 * 346 * @param cb event callback 347 */ 348 void mdm_hl7800_register_event_callback(mdm_hl7800_event_callback_t cb); 349 350 /** 351 * @brief Force modem module to generate status events. 352 * 353 * @note This can be used to get the current state when a module initializes 354 * later than the modem. 355 */ 356 void mdm_hl7800_generate_status_events(void); 357 358 #ifdef CONFIG_NEWLIB_LIBC 359 /** 360 * @brief Get the local time from the modem's real time clock. 361 * 362 * @param tm time structure 363 * @param offset The amount the local time is offset from GMT/UTC in seconds. 364 * 365 * @param 0 if successful 366 */ 367 int32_t mdm_hl7800_get_local_time(struct tm *tm, int32_t *offset); 368 #endif 369 370 #ifdef CONFIG_MODEM_HL7800_FW_UPDATE 371 /** 372 * @brief Update the HL7800 via XMODEM protocol. During the firmware update 373 * no other modem fuctions will be available. 374 * 375 * @param file_path Absolute path of the update file 376 * 377 * @param 0 if successful 378 */ 379 int32_t mdm_hl7800_update_fw(char *file_path); 380 #endif 381 382 /** 383 * @brief Read the operator index from the modem. 384 * 385 * @retval negative error code, 0 on success 386 */ 387 int32_t mdm_hl7800_get_operator_index(void); 388 389 /** 390 * @brief Get modem functionality 391 * 392 * @return int32_t negative errno on failure, else mdm_hl7800_functionality 393 */ 394 int32_t mdm_hl7800_get_functionality(void); 395 396 /** 397 * @brief Set airplane, normal, or reduced functionality mode. 398 * Airplane mode persists when reset. 399 * 400 * @note Boot functionality is also controlled by Kconfig 401 * MODEM_HL7800_BOOT_IN_AIRPLANE_MODE. 402 * 403 * @param mode 404 * @return int32_t negative errno, 0 on success 405 */ 406 int32_t mdm_hl7800_set_functionality(enum mdm_hl7800_functionality mode); 407 408 /** 409 * @brief When rate is non-zero: Put modem into Airplane mode. Enable GPS and 410 * generate HL7800_EVENT_GPS events. 411 * When zero: Disable GPS and put modem into normal mode. 412 * 413 * @note Airplane mode isn't cleared when the modem is reset. 414 * 415 * @param rate in seconds to query location 416 * @return int32_t negative errno, 0 on success 417 */ 418 int32_t mdm_hl7800_set_gps_rate(uint32_t rate); 419 420 /** 421 * @brief Register modem/SIM with polte.io 422 * 423 * @note It takes around 30 seconds for HL7800_EVENT_POLTE_REGISTRATION to 424 * be generated. If the applications saves the user and password 425 * information into non-volatile memory, then this command 426 * only needs to be run once. 427 * 428 * @return int32_t negative errno, 0 on success 429 */ 430 int32_t mdm_hl7800_polte_register(void); 431 432 /** 433 * @brief Enable PoLTE. 434 * 435 * @param user from polte.io or register command callback 436 * @param password from polte.io register command callback 437 * @return int32_t negative errno, 0 on success 438 */ 439 int32_t mdm_hl7800_polte_enable(char *user, char *password); 440 441 /** 442 * @brief Locate device using PoLTE. 443 * 444 * @note The first HL7800_EVENT_POLTE_LOCATE_STATUS event indicates 445 * the status of issuing the locate command. The second event 446 * requires 20-120 seconds to be generated and it contains the 447 * location information (or indicates server failure). 448 * 449 * @return int32_t negative errno, 0 on success 450 */ 451 int32_t mdm_hl7800_polte_locate(void); 452 453 /** 454 * @brief Perform a site survey. This command may return different values 455 * each time it is run (depending on what is in range). 456 * 457 * HL7800_EVENT_SITE_SURVEY is generated for each response received from modem. 458 * 459 * @retval negative error code, 0 on success 460 */ 461 int32_t mdm_hl7800_perform_site_survey(void); 462 463 #ifdef __cplusplus 464 } 465 #endif 466 467 #endif /* ZEPHYR_INCLUDE_DRIVERS_MODEM_HL7800_H_ */ 468