Line data Source code
1 0 : /*
2 : * Copyright (c) 2025 Netfeasa Ltd.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 : #ifndef ZEPHYR_INCLUDE_DRIVERS_HL78XX_APIS_H_
7 : #define ZEPHYR_INCLUDE_DRIVERS_HL78XX_APIS_H_
8 :
9 : #include <zephyr/types.h>
10 : #include <zephyr/device.h>
11 : #include <errno.h>
12 : #include <stddef.h>
13 : #include <zephyr/modem/chat.h>
14 : #include <zephyr/drivers/cellular.h>
15 :
16 : #ifdef __cplusplus
17 : extern "C" {
18 : #endif
19 :
20 : /* Magic constants */
21 0 : #define CSQ_RSSI_UNKNOWN (99)
22 0 : #define CESQ_RSRP_UNKNOWN (255)
23 0 : #define CESQ_RSRQ_UNKNOWN (255)
24 : /* Magic numbers to units conversions */
25 0 : #define CSQ_RSSI_TO_DB(v) (-113 + (2 * (v)))
26 0 : #define CESQ_RSRP_TO_DB(v) (-140 + (v))
27 0 : #define CESQ_RSRQ_TO_DB(v) (-20 + ((v) / 2))
28 : /** Monitor is paused. */
29 1 : #define PAUSED 1
30 : /** Monitor is active, default */
31 1 : #define ACTIVE 0
32 0 : #define MDM_MANUFACTURER_LENGTH 20
33 0 : #define MDM_MODEL_LENGTH 32
34 0 : #define MDM_REVISION_LENGTH 64
35 0 : #define MDM_IMEI_LENGTH 16
36 0 : #define MDM_IMSI_LENGTH 23
37 0 : #define MDM_ICCID_LENGTH 22
38 0 : #define MDM_APN_MAX_LENGTH 64
39 0 : #define MDM_MAX_CERT_LENGTH 4096
40 0 : #define MDM_MAX_HOSTNAME_LEN 128
41 : /**
42 : * @brief Define an Event monitor to receive notifications in the system workqueue thread.
43 : *
44 : * @param name The monitor name.
45 : * @param _handler The monitor callback.
46 : * @param ... Optional monitor initial state (@c PAUSED or @c ACTIVE).
47 : * The default initial state of a monitor is active.
48 : */
49 1 : #define HL78XX_EVT_MONITOR(name, _handler, ...) \
50 : static STRUCT_SECTION_ITERABLE(hl78xx_evt_monitor_entry, name) = { \
51 : .handler = _handler, \
52 : .next = NULL, \
53 : .flags.direct = false, \
54 : COND_CODE_1(__VA_ARGS__, (.flags.paused = __VA_ARGS__,), ()) }
55 :
56 : /** Cellular radio access technologies */
57 0 : enum hl78xx_cell_rat_mode {
58 : HL78XX_RAT_CAT_M1 = 0,
59 : HL78XX_RAT_NB1,
60 : #ifdef CONFIG_MODEM_HL78XX_12
61 : HL78XX_RAT_GSM,
62 : #ifdef CONFIG_MODEM_HL78XX_12_FW_R6
63 : HL78XX_RAT_NBNTN,
64 : #endif
65 : #endif
66 : #ifdef CONFIG_MODEM_HL78XX_AUTORAT
67 : HL78XX_RAT_MODE_AUTO,
68 : #endif
69 : HL78XX_RAT_MODE_NONE,
70 : HL78XX_RAT_COUNT = HL78XX_RAT_MODE_NONE
71 : };
72 :
73 : /** Phone functionality modes */
74 0 : enum hl78xx_phone_functionality {
75 : HL78XX_SIM_POWER_OFF,
76 : HL78XX_FULLY_FUNCTIONAL,
77 : HL78XX_AIRPLANE = 4,
78 : };
79 : /** Module status codes */
80 0 : enum hl78xx_module_status {
81 : HL78XX_MODULE_READY = 0,
82 : HL78XX_MODULE_WAITING_FOR_ACCESS_CODE,
83 : HL78XX_MODULE_SIM_NOT_PRESENT,
84 : HL78XX_MODULE_SIMLOCK,
85 : HL78XX_MODULE_UNRECOVERABLE_ERROR,
86 : HL78XX_MODULE_UNKNOWN_STATE,
87 : HL78XX_MODULE_INACTIVE_SIM
88 : };
89 :
90 : /** Cellular modem info type */
91 0 : enum hl78xx_modem_info_type {
92 : /* <APN> Access Point Name */
93 : HL78XX_MODEM_INFO_APN,
94 : /* <Current RAT> */
95 : HL78XX_MODEM_INFO_CURRENT_RAT,
96 : /* <Network Operator> */
97 : HL78XX_MODEM_INFO_NETWORK_OPERATOR,
98 : };
99 :
100 : /** Cellular network structure */
101 1 : struct hl78xx_network {
102 : /** Cellular access technology */
103 1 : enum hl78xx_cell_rat_mode technology;
104 : /**
105 : * List of bands, as defined by the specified cellular access technology,
106 : * to enables. All supported bands are enabled if none are provided.
107 : */
108 1 : uint16_t *bands;
109 : /** Size of bands */
110 1 : uint16_t size;
111 : };
112 :
113 0 : enum hl78xx_evt_type {
114 : HL78XX_LTE_RAT_UPDATE,
115 : HL78XX_LTE_REGISTRATION_STAT_UPDATE,
116 : HL78XX_LTE_SIM_REGISTRATION,
117 : HL78XX_LTE_MODEM_STARTUP,
118 : };
119 :
120 0 : struct hl78xx_evt {
121 0 : enum hl78xx_evt_type type;
122 :
123 : union {
124 0 : enum cellular_registration_status reg_status;
125 0 : enum hl78xx_cell_rat_mode rat_mode;
126 0 : bool status;
127 0 : int value;
128 0 : } content;
129 : };
130 : /** API for configuring networks */
131 1 : typedef int (*hl78xx_api_configure_networks)(const struct device *dev,
132 : const struct hl78xx_network *networks, uint8_t size);
133 :
134 : /** API for getting supported networks */
135 1 : typedef int (*hl78xx_api_get_supported_networks)(const struct device *dev,
136 : const struct hl78xx_network **networks,
137 : uint8_t *size);
138 :
139 : /** API for getting network signal strength */
140 1 : typedef int (*hl78xx_api_get_signal)(const struct device *dev, const enum cellular_signal_type type,
141 : int16_t *value);
142 :
143 : /** API for getting modem information */
144 1 : typedef int (*hl78xx_api_get_modem_info)(const struct device *dev,
145 : const enum cellular_modem_info_type type, char *info,
146 : size_t size);
147 :
148 : /** API for getting registration status */
149 1 : typedef int (*hl78xx_api_get_registration_status)(const struct device *dev,
150 : enum cellular_access_technology tech,
151 : enum cellular_registration_status *status);
152 :
153 : /** API for setting apn */
154 1 : typedef int (*hl78xx_api_set_apn)(const struct device *dev, const char *apn, uint16_t size);
155 :
156 : /** API for set phone functionality */
157 1 : typedef int (*hl78xx_api_set_phone_functionality)(const struct device *dev,
158 : enum hl78xx_phone_functionality functionality,
159 : bool reset);
160 :
161 : /** API for get phone functionality */
162 1 : typedef int (*hl78xx_api_get_phone_functionality)(const struct device *dev,
163 : enum hl78xx_phone_functionality *functionality);
164 :
165 : /** API for get phone functionality */
166 1 : typedef int (*hl78xx_api_send_at_cmd)(const struct device *dev, const char *cmd, uint16_t cmd_size,
167 : const struct modem_chat_match *response_matches,
168 : uint16_t matches_size);
169 :
170 : /**< Event monitor entry */
171 : struct hl78xx_evt_monitor_entry; /* forward declaration */
172 : /* Event monitor dispatcher */
173 0 : typedef void (*hl78xx_evt_monitor_dispatcher_t)(struct hl78xx_evt *notif);
174 : /* Event monitor handler */
175 0 : typedef void (*hl78xx_evt_monitor_handler_t)(struct hl78xx_evt *notif,
176 : struct hl78xx_evt_monitor_entry *mon);
177 :
178 0 : struct hl78xx_evt_monitor_entry {
179 : /** Monitor callback. */
180 1 : const hl78xx_evt_monitor_handler_t handler;
181 : /* link for runtime list */
182 0 : struct hl78xx_evt_monitor_entry *next;
183 : struct {
184 0 : uint8_t paused: 1; /* Monitor is paused. */
185 0 : uint8_t direct: 1; /* Dispatch in ISR. */
186 0 : } flags;
187 : };
188 : /**
189 : * @brief hl78xx_api_func_set_phone_functionality
190 : * @param dev Cellular network device instance
191 : * @param functionality phone functionality mode to set
192 : * @param reset If true, the modem will be reset as part of applying the functionality change.
193 : * @return 0 if successful.
194 : */
195 1 : int hl78xx_api_func_set_phone_functionality(const struct device *dev,
196 : enum hl78xx_phone_functionality functionality,
197 : bool reset);
198 : /**
199 : * @brief hl78xx_api_func_get_phone_functionality
200 : * @param dev Cellular network device instance
201 : * @param functionality Pointer to store the current phone functionality mode
202 : * @return 0 if successful.
203 : */
204 1 : int hl78xx_api_func_get_phone_functionality(const struct device *dev,
205 : enum hl78xx_phone_functionality *functionality);
206 : /**
207 : * @brief hl78xx_api_func_get_signal - Brief description of the function.
208 : * @param dev Cellular network device instance
209 : * @param type Type of the signal to retrieve
210 : * @param value Pointer to store the signal value
211 : * @return 0 if successful.
212 : */
213 1 : int hl78xx_api_func_get_signal(const struct device *dev, const enum cellular_signal_type type,
214 : int16_t *value);
215 : /**
216 : * @brief hl78xx_api_func_get_modem_info_vendor - Brief description of the function.
217 : * @param dev Cellular network device instance
218 : * @param type Type of the modem info to retrieve
219 : * @param info Pointer to store the modem info
220 : * @param size Size of the info buffer
221 : * @return 0 if successful.
222 : */
223 1 : int hl78xx_api_func_get_modem_info_vendor(const struct device *dev,
224 : enum hl78xx_modem_info_type type, void *info,
225 : size_t size);
226 : /**
227 : * @brief hl78xx_api_func_modem_dynamic_cmd_send - Brief description of the function.
228 : * @param dev Cellular network device instance
229 : * @param cmd AT command to send
230 : * @param cmd_size Size of the AT command
231 : * @param response_matches Expected response patterns
232 : * @param matches_size Size of the response patterns
233 : * @return 0 if successful.
234 : */
235 1 : int hl78xx_api_func_modem_dynamic_cmd_send(const struct device *dev, const char *cmd,
236 : uint16_t cmd_size,
237 : const struct modem_chat_match *response_matches,
238 : uint16_t matches_size);
239 : /**
240 : * @brief Get modem info for the device
241 : *
242 : * @param dev Cellular network device instance
243 : * @param type Type of the modem info requested
244 : * @param info Info string destination
245 : * @param size Info string size
246 : *
247 : * @retval 0 if successful.
248 : * @retval -ENOTSUP if API is not supported by cellular network device.
249 : * @retval -ENODATA if modem does not provide info requested
250 : * @retval Negative errno-code from chat module otherwise.
251 : */
252 1 : static inline int hl78xx_get_modem_info(const struct device *dev,
253 : const enum hl78xx_modem_info_type type, void *info,
254 : size_t size)
255 : {
256 : return hl78xx_api_func_get_modem_info_vendor(dev, type, info, size);
257 : }
258 : /**
259 : * @brief Set the modem phone functionality mode.
260 : *
261 : * Configures the operational state of the modem (e.g., full, airplane, or minimum functionality).
262 : * Optionally, the modem can be reset during this transition.
263 : *
264 : * @param dev Pointer to the modem device instance.
265 : * @param functionality Desired phone functionality mode to be set.
266 : * (e.g., full, airplane, minimum – see enum hl78xx_phone_functionality)
267 : * @param reset If true, the modem will be reset as part of applying the functionality change.
268 : *
269 : * @retval 0 on success.
270 : * @retval -EINVAL if an invalid parameter is passed.
271 : * @retval -EIO on communication or command failure with the modem.
272 : */
273 1 : static inline int hl78xx_set_phone_functionality(const struct device *dev,
274 : enum hl78xx_phone_functionality functionality,
275 : bool reset)
276 : {
277 : return hl78xx_api_func_set_phone_functionality(dev, functionality, reset);
278 : }
279 : /**
280 : * @brief Get the current phone functionality mode of the modem.
281 : *
282 : * Queries the modem to retrieve its current operational mode, such as
283 : * full functionality, airplane mode, or minimum functionality.
284 : *
285 : * @param dev Pointer to the modem device instance.
286 : * @param functionality Pointer to store the retrieved functionality mode.
287 : * (see enum hl78xx_phone_functionality)
288 : *
289 : * @retval 0 on success.
290 : * @retval -EINVAL if the input parameters are invalid.
291 : * @retval -EIO if the modem fails to respond or returns an error.
292 : */
293 1 : static inline int hl78xx_get_phone_functionality(const struct device *dev,
294 : enum hl78xx_phone_functionality *functionality)
295 : {
296 : return hl78xx_api_func_get_phone_functionality(dev, functionality);
297 : }
298 : /**
299 : * @brief Send an AT command to the modem and wait for a matched response.
300 : *
301 : * Transmits the specified AT command to the modem and waits for a response that matches
302 : * one of the expected patterns defined in the response match table.
303 : *
304 : * @param dev Pointer to the modem device instance.
305 : * @param cmd Pointer to the AT command string to be sent.
306 : * @param cmd_size Length of the AT command string in bytes.
307 : * @param response_matches Pointer to an array of expected response patterns.
308 : * (see struct modem_chat_match)
309 : * @param matches_size Number of response patterns in the array.
310 : *
311 : * @retval 0 on successful command transmission and response match.
312 : * @retval -EINVAL if any parameter is invalid.
313 : * @retval -ETIMEDOUT if the modem did not respond in the expected time.
314 : * @retval -EIO on communication failure or if response did not match.
315 : */
316 1 : static inline int hl78xx_modem_cmd_send(const struct device *dev, const char *cmd,
317 : uint16_t cmd_size,
318 : const struct modem_chat_match *response_matches,
319 : uint16_t matches_size)
320 : {
321 :
322 : return hl78xx_api_func_modem_dynamic_cmd_send(dev, cmd, cmd_size, response_matches,
323 : matches_size);
324 : }
325 : /**
326 : * @brief Convert raw RSSI value from the modem to dBm.
327 : *
328 : * Parses the RSSI value reported by the modem (typically from an AT command response)
329 : * and converts it to a corresponding signal strength in dBm, as defined by 3GPP TS 27.007.
330 : *
331 : * @param rssi Raw RSSI value (0–31 or 99 for not known or not detectable).
332 : * @param value Pointer to store the converted RSSI in dBm.
333 : *
334 : * @retval 0 on successful conversion.
335 : * @retval -EINVAL if the RSSI value is out of valid range or unsupported.
336 : */
337 1 : static inline int hl78xx_parse_rssi(uint8_t rssi, int16_t *value)
338 : {
339 : /* AT+CSQ returns a response +CSQ: <rssi>,<ber> where:
340 : * - rssi is a integer from 0 to 31 whose values describes a signal strength
341 : * between -113 dBm for 0 and -51dbM for 31 or unknown for 99
342 : * - ber is an integer from 0 to 7 that describes the error rate, it can also
343 : * be 99 for an unknown error rate
344 : */
345 : if (rssi == CSQ_RSSI_UNKNOWN) {
346 : return -EINVAL;
347 : }
348 :
349 : *value = (int16_t)CSQ_RSSI_TO_DB(rssi);
350 : return 0;
351 : }
352 : /**
353 : * @brief Convert raw RSRP value from the modem to dBm.
354 : *
355 : * Parses the Reference Signal Received Power (RSRP) value reported by the modem
356 : * and converts it into a corresponding signal strength in dBm, typically based on
357 : * 3GPP TS 36.133 specifications.
358 : *
359 : * @param rsrp Raw RSRP value (commonly in the range 0–97, or 255 if unknown).
360 : * @param value Pointer to store the converted RSRP in dBm.
361 : *
362 : * @retval 0 on successful conversion.
363 : * @retval -EINVAL if the RSRP value is out of range or represents an unknown value.
364 : */
365 1 : static inline int hl78xx_parse_rsrp(uint8_t rsrp, int16_t *value)
366 : {
367 : /* AT+CESQ returns a response
368 : * +CESQ: <rxlev>,<ber>,<rscp>,<ecn0>,<rsrq>,<rsrp> where:
369 : * rsrq is a integer from 0 to 34 whose values describes the Reference
370 : * Signal Receive Quality between -20 dB for 0 and -3 dB for 34
371 : * (0.5 dB steps), or unknown for 255
372 : * rsrp is an integer from 0 to 97 that describes the Reference Signal
373 : * Receive Power between -140 dBm for 0 and -44 dBm for 97 (1 dBm steps),
374 : * or unknown for 255
375 : */
376 : if (rsrp == CESQ_RSRP_UNKNOWN) {
377 : return -EINVAL;
378 : }
379 :
380 : *value = (int16_t)CESQ_RSRP_TO_DB(rsrp);
381 : return 0;
382 : }
383 : /**
384 : * @brief Convert raw RSRQ value from the modem to dB.
385 : *
386 : * Parses the Reference Signal Received Quality (RSRQ) value provided by the modem
387 : * and converts it into a signal quality measurement in decibels (dB), as specified
388 : * by 3GPP TS 36.133.
389 : *
390 : * @param rsrq Raw RSRQ value (typically 0–34, or 255 if unknown).
391 : * @param value Pointer to store the converted RSRQ in dB.
392 : *
393 : * @retval 0 on successful conversion.
394 : * @retval -EINVAL if the RSRQ value is out of valid range or indicates unknown.
395 : */
396 1 : static inline int hl78xx_parse_rsrq(uint8_t rsrq, int16_t *value)
397 : {
398 : if (rsrq == CESQ_RSRQ_UNKNOWN) {
399 : return -EINVAL;
400 : }
401 :
402 : *value = (int16_t)CESQ_RSRQ_TO_DB(rsrq);
403 : return 0;
404 : }
405 : /**
406 : * @brief Pause monitor.
407 : *
408 : * Pause monitor @p mon from receiving notifications.
409 : *
410 : * @param mon The monitor to pause.
411 : */
412 1 : static inline void hl78xx_evt_monitor_pause(struct hl78xx_evt_monitor_entry *mon)
413 : {
414 : mon->flags.paused = true;
415 : }
416 : /**
417 : * @brief Resume monitor.
418 : *
419 : * Resume forwarding notifications to monitor @p mon.
420 : *
421 : * @param mon The monitor to resume.
422 : */
423 1 : static inline void hl78xx_evt_monitor_resume(struct hl78xx_evt_monitor_entry *mon)
424 : {
425 : mon->flags.paused = false;
426 : }
427 : /**
428 : * @brief Set the event notification handler for HL78xx modem events.
429 : *
430 : * Registers a callback handler to receive asynchronous event notifications
431 : * from the HL78xx modem, such as network registration changes, GNSS updates,
432 : * or other modem-generated events.
433 : *
434 : * @param handler Function pointer to the event monitor callback.
435 : * Pass NULL to clear the existing handler.
436 : *
437 : * @retval 0 on success.
438 : * @retval -EINVAL if the handler parameter is invalid.
439 : */
440 1 : int hl78xx_evt_notif_handler_set(hl78xx_evt_monitor_dispatcher_t handler);
441 : /**
442 : * @brief Register an event monitor to receive HL78xx modem event notifications.
443 : */
444 1 : int hl78xx_evt_monitor_register(struct hl78xx_evt_monitor_entry *mon);
445 : /**
446 : * @brief Unregister an event monitor from receiving HL78xx modem event notifications.
447 : */
448 1 : int hl78xx_evt_monitor_unregister(struct hl78xx_evt_monitor_entry *mon);
449 : /**
450 : * @brief Convert HL78xx RAT mode to standard cellular API.
451 : */
452 1 : enum cellular_access_technology hl78xx_rat_to_access_tech(enum hl78xx_cell_rat_mode rat_mode);
453 :
454 : #ifdef __cplusplus
455 : }
456 : #endif
457 :
458 : #endif /* ZEPHYR_INCLUDE_DRIVERS_HL78XX_APIS_H_ */
|