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