Line data Source code
1 1 : /*
2 : * Copyright (c) 2023 Bjarki Arge Andreasen
3 : * Copyright (c) 2023 Lucas Denefle
4 : *
5 : * SPDX-License-Identifier: Apache-2.0
6 : */
7 :
8 : /**
9 : * @file
10 : * @ingroup cellular_interface
11 : * @brief Main header file for cellular modem driver API.
12 : */
13 :
14 : #ifndef ZEPHYR_INCLUDE_DRIVERS_CELLULAR_H_
15 : #define ZEPHYR_INCLUDE_DRIVERS_CELLULAR_H_
16 :
17 : /**
18 : * @brief Interfaces for cellular modems.
19 : * @defgroup cellular_interface Cellular
20 : * @ingroup io_interfaces
21 : * @{
22 : */
23 :
24 : #include <zephyr/types.h>
25 : #include <zephyr/device.h>
26 : #include <errno.h>
27 :
28 : #ifdef __cplusplus
29 : extern "C" {
30 : #endif
31 :
32 : /** Cellular access technologies */
33 0 : enum cellular_access_technology {
34 : CELLULAR_ACCESS_TECHNOLOGY_GSM = 0,
35 : CELLULAR_ACCESS_TECHNOLOGY_GPRS,
36 : CELLULAR_ACCESS_TECHNOLOGY_UMTS,
37 : CELLULAR_ACCESS_TECHNOLOGY_EDGE,
38 : CELLULAR_ACCESS_TECHNOLOGY_LTE,
39 : CELLULAR_ACCESS_TECHNOLOGY_LTE_CAT_M1,
40 : CELLULAR_ACCESS_TECHNOLOGY_LTE_CAT_M2,
41 : CELLULAR_ACCESS_TECHNOLOGY_NB_IOT,
42 : };
43 :
44 : /** Cellular network structure */
45 1 : struct cellular_network {
46 : /** Cellular access technology */
47 1 : enum cellular_access_technology technology;
48 : /**
49 : * List of bands, as defined by the specified cellular access technology,
50 : * to enables. All supported bands are enabled if none are provided.
51 : */
52 1 : uint16_t *bands;
53 : /** Size of bands */
54 1 : uint16_t size;
55 : };
56 :
57 : /** Cellular signal type */
58 0 : enum cellular_signal_type {
59 : CELLULAR_SIGNAL_RSSI,
60 : CELLULAR_SIGNAL_RSRP,
61 : CELLULAR_SIGNAL_RSRQ,
62 : };
63 :
64 : /** Cellular modem info type */
65 1 : enum cellular_modem_info_type {
66 : /** International Mobile Equipment Identity */
67 : CELLULAR_MODEM_INFO_IMEI,
68 : /** Modem model ID */
69 : CELLULAR_MODEM_INFO_MODEL_ID,
70 : /** Modem manufacturer */
71 : CELLULAR_MODEM_INFO_MANUFACTURER,
72 : /** Modem fw version */
73 : CELLULAR_MODEM_INFO_FW_VERSION,
74 : /** International Mobile Subscriber Identity */
75 : CELLULAR_MODEM_INFO_SIM_IMSI,
76 : /** Integrated Circuit Card Identification Number (SIM) */
77 : CELLULAR_MODEM_INFO_SIM_ICCID,
78 : };
79 :
80 0 : enum cellular_registration_status {
81 : CELLULAR_REGISTRATION_NOT_REGISTERED = 0,
82 : CELLULAR_REGISTRATION_REGISTERED_HOME,
83 : CELLULAR_REGISTRATION_SEARCHING,
84 : CELLULAR_REGISTRATION_DENIED,
85 : CELLULAR_REGISTRATION_UNKNOWN,
86 : CELLULAR_REGISTRATION_REGISTERED_ROAMING,
87 : };
88 :
89 : /** Events emitted asynchronously by a cellular driver */
90 1 : enum cellular_event {
91 : /** One or more modem-info field changed (e.g. IMSI became available). */
92 : CELLULAR_EVENT_MODEM_INFO_CHANGED = BIT(0),
93 : /** Cellular network registration status changed */
94 : CELLULAR_EVENT_REGISTRATION_STATUS_CHANGED = BIT(1),
95 : };
96 :
97 : /* Opaque bit-mask large enough for all current & future events */
98 0 : typedef uint32_t cellular_event_mask_t;
99 :
100 : /** Payload for @ref CELLULAR_EVENT_MODEM_INFO_CHANGED. */
101 1 : struct cellular_evt_modem_info {
102 1 : enum cellular_modem_info_type field; /**< Which field changed */
103 : };
104 :
105 : /** Payload for @ref CELLULAR_EVENT_REGISTRATION_STATUS_CHANGED. */
106 1 : struct cellular_evt_registration_status {
107 1 : enum cellular_registration_status status; /**< New registration status */
108 : };
109 :
110 : /**
111 : * @brief Prototype for cellular event callbacks.
112 : *
113 : * @param dev Cellular device that generated the event
114 : * @param event Which @ref cellular_event occurred
115 : * @param payload Pointer to the kind-specific payload
116 : * (`NULL` if the kind defines no payload).
117 : * @param user_data Pointer supplied when the callback was registered
118 : *
119 : * @note The driver calls the callback directly from its own context.
120 : * Off-load heavy processing to a work-queue if required.
121 : */
122 1 : typedef void (*cellular_event_cb_t)(const struct device *dev, enum cellular_event event,
123 : const void *payload, void *user_data);
124 :
125 : /** API for configuring networks */
126 1 : typedef int (*cellular_api_configure_networks)(const struct device *dev,
127 : const struct cellular_network *networks,
128 : uint8_t size);
129 :
130 : /** API for getting supported networks */
131 1 : typedef int (*cellular_api_get_supported_networks)(const struct device *dev,
132 : const struct cellular_network **networks,
133 : uint8_t *size);
134 :
135 : /** API for getting network signal strength */
136 1 : typedef int (*cellular_api_get_signal)(const struct device *dev,
137 : const enum cellular_signal_type type, int16_t *value);
138 :
139 : /** API for getting modem information */
140 1 : typedef int (*cellular_api_get_modem_info)(const struct device *dev,
141 : const enum cellular_modem_info_type type, char *info,
142 : size_t size);
143 :
144 : /** API for getting registration status */
145 1 : typedef int (*cellular_api_get_registration_status)(const struct device *dev,
146 : enum cellular_access_technology tech,
147 : enum cellular_registration_status *status);
148 :
149 : /** API for programming APN */
150 1 : typedef int (*cellular_api_set_apn)(const struct device *dev, const char *apn);
151 :
152 : /** API for registering an asynchronous callback */
153 1 : typedef int (*cellular_api_set_callback)(const struct device *dev, cellular_event_mask_t mask,
154 : cellular_event_cb_t cb, void *user_data);
155 :
156 : /** Cellular driver API */
157 1 : __subsystem struct cellular_driver_api {
158 0 : cellular_api_configure_networks configure_networks;
159 0 : cellular_api_get_supported_networks get_supported_networks;
160 0 : cellular_api_get_signal get_signal;
161 0 : cellular_api_get_modem_info get_modem_info;
162 0 : cellular_api_get_registration_status get_registration_status;
163 0 : cellular_api_set_apn set_apn;
164 0 : cellular_api_set_callback set_callback;
165 : };
166 :
167 : /**
168 : * @brief Configure cellular networks for the device
169 : *
170 : * @details Cellular network devices support at least one cellular access technology.
171 : * Each cellular access technology defines a set of bands, of which the cellular device
172 : * will support all or a subset of.
173 : *
174 : * The cellular device can only use one cellular network technology at a time. It must
175 : * exclusively use the cellular network configurations provided, and will prioritize
176 : * the cellular network configurations in the order they are provided in case there are
177 : * multiple (the first cellular network configuration has the highest priority).
178 : *
179 : * @param dev Cellular network device instance.
180 : * @param networks List of cellular network configurations to apply.
181 : * @param size Size of list of cellular network configurations.
182 : *
183 : * @retval 0 if successful.
184 : * @retval -EINVAL if any provided cellular network configuration is invalid or unsupported.
185 : * @retval -ENOTSUP if API is not supported by cellular network device.
186 : * @retval Negative errno-code otherwise.
187 : */
188 1 : static inline int cellular_configure_networks(const struct device *dev,
189 : const struct cellular_network *networks, uint8_t size)
190 : {
191 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
192 :
193 : if (api->configure_networks == NULL) {
194 : return -ENOSYS;
195 : }
196 :
197 : return api->configure_networks(dev, networks, size);
198 : }
199 :
200 : /**
201 : * @brief Get supported cellular networks for the device
202 : *
203 : * @param dev Cellular network device instance
204 : * @param networks Pointer to list of supported cellular network configurations.
205 : * @param size Size of list of cellular network configurations.
206 : *
207 : * @retval 0 if successful.
208 : * @retval -ENOTSUP if API is not supported by cellular network device.
209 : * @retval Negative errno-code otherwise.
210 : */
211 1 : static inline int cellular_get_supported_networks(const struct device *dev,
212 : const struct cellular_network **networks,
213 : uint8_t *size)
214 : {
215 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
216 :
217 : if (api->get_supported_networks == NULL) {
218 : return -ENOSYS;
219 : }
220 :
221 : return api->get_supported_networks(dev, networks, size);
222 : }
223 :
224 : /**
225 : * @brief Get signal for the device
226 : *
227 : * @param dev Cellular network device instance
228 : * @param type Type of the signal information requested
229 : * @param value Signal strength destination (one of RSSI, RSRP, RSRQ)
230 : *
231 : * @retval 0 if successful.
232 : * @retval -ENOTSUP if API is not supported by cellular network device.
233 : * @retval -ENODATA if device is not in a state where signal can be polled
234 : * @retval Negative errno-code otherwise.
235 : */
236 1 : static inline int cellular_get_signal(const struct device *dev,
237 : const enum cellular_signal_type type, int16_t *value)
238 : {
239 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
240 :
241 : if (api->get_signal == NULL) {
242 : return -ENOSYS;
243 : }
244 :
245 : return api->get_signal(dev, type, value);
246 : }
247 :
248 : /**
249 : * @brief Get modem info for the device
250 : *
251 : * @param dev Cellular network device instance
252 : * @param type Type of the modem info requested
253 : * @param info Info string destination
254 : * @param size Info string size
255 : *
256 : * @retval 0 if successful.
257 : * @retval -ENOTSUP if API is not supported by cellular network device.
258 : * @retval -ENODATA if modem does not provide info requested
259 : * @retval Negative errno-code from chat module otherwise.
260 : */
261 1 : static inline int cellular_get_modem_info(const struct device *dev,
262 : const enum cellular_modem_info_type type, char *info,
263 : size_t size)
264 : {
265 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
266 :
267 : if (api->get_modem_info == NULL) {
268 : return -ENOSYS;
269 : }
270 :
271 : return api->get_modem_info(dev, type, info, size);
272 : }
273 :
274 : /**
275 : * @brief Get network registration status for the device
276 : *
277 : * @param dev Cellular network device instance
278 : * @param tech Which access technology to get status for
279 : * @param status Registration status for given access technology
280 : *
281 : * @retval 0 if successful.
282 : * @retval -ENOSYS if API is not supported by cellular network device.
283 : * @retval -ENODATA if modem does not provide info requested
284 : * @retval Negative errno-code from chat module otherwise.
285 : */
286 1 : static inline int cellular_get_registration_status(const struct device *dev,
287 : enum cellular_access_technology tech,
288 : enum cellular_registration_status *status)
289 : {
290 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
291 :
292 : if (api->get_registration_status == NULL) {
293 : return -ENOSYS;
294 : }
295 :
296 : return api->get_registration_status(dev, tech, status);
297 : }
298 :
299 : /**
300 : * @brief Set the APN used for PDP context
301 : *
302 : * @details Drivers are expected to copy the string immediately and return
303 : * once the request has been queued internally.
304 : *
305 : * @param dev Cellular device
306 : * @param apn Zero-terminated APN string (max length is driver-specific)
307 : *
308 : * @retval 0 if successful.
309 : * @retval -ENOSYS if API is not supported by cellular network device.
310 : * @retval -EINVAL if APN string invalid or too long.
311 : * @retval -EALREADY if APN identical to current one, nothing to do
312 : * @retval -EBUSY if modem is already dialled, APN cannot be changed
313 : * @retval Negative errno-code otherwise.
314 : */
315 1 : static inline int cellular_set_apn(const struct device *dev, const char *apn)
316 : {
317 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
318 :
319 : if (api->set_apn == NULL) {
320 : return -ENOSYS;
321 : }
322 :
323 : return api->set_apn(dev, apn);
324 : }
325 :
326 : /**
327 : * @brief Subscribe to asynchronous cellular events.
328 : *
329 : * @param dev Cellular device
330 : * @param mask Event mask to subscribe to
331 : * @param cb Callback to call when the event occurs, or NULL to unsubscribe
332 : * @param user_data Pointer to user data that will be passed to the callback
333 : *
334 : * @retval 0 Success
335 : * @retval -ENOSYS Driver does not support event callbacks
336 : * @retval -EINVAL Bad parameters
337 : * @retval -ENOMEM No space left for another subscriber
338 : * @retval <0 Driver-specific error
339 : */
340 1 : static inline int cellular_set_callback(const struct device *dev, cellular_event_mask_t mask,
341 : cellular_event_cb_t cb, void *user_data)
342 : {
343 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
344 :
345 : if (api->set_callback == NULL) {
346 : return -ENOSYS;
347 : }
348 :
349 : return api->set_callback(dev, mask, cb, user_data);
350 : }
351 :
352 : #ifdef __cplusplus
353 : }
354 : #endif
355 :
356 : /**
357 : * @}
358 : */
359 :
360 : #endif /* ZEPHYR_INCLUDE_DRIVERS_CELLULAR_H_ */
|