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