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 (3GPP TS 27.007 AcT) */
33 1 : enum cellular_access_technology {
34 : /** Global System for Mobile communications (2G, 3GPP Rel 99) */
35 : CELLULAR_ACCESS_TECHNOLOGY_GSM = 0,
36 : /** Bandwidth & Spectrum limited variant of GSM (2G, 3GPP Rel 99) */
37 : CELLULAR_ACCESS_TECHNOLOGY_GSM_COMPACT = 1,
38 : /** UMTS Terrestrial Radio Access Network (3G, 3GPP Rel 99) */
39 : CELLULAR_ACCESS_TECHNOLOGY_UTRAN = 2,
40 : /** GSM Enhanced General Packet Radio Service (2.5G, 3GPP Rel 99) */
41 : CELLULAR_ACCESS_TECHNOLOGY_GSM_EGPRS = 3,
42 : /** UTRAN with High Speed Downlink Packet Access (3.5G, 3GPP Rel 5) */
43 : CELLULAR_ACCESS_TECHNOLOGY_UTRAN_HSDPA = 4,
44 : /** UTRAN with High Speed Uplink Packet Access (3.75G, 3GPP Rel 6) */
45 : CELLULAR_ACCESS_TECHNOLOGY_UTRAN_HSUPA = 5,
46 : /** UTRAN with HSDPA and HSUDP (HSPA) (3.75G, 3GPP Rel 6) */
47 : CELLULAR_ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA = 6,
48 : /** Evolved UTRAN (4G, 3GPP Rel 8) */
49 : CELLULAR_ACCESS_TECHNOLOGY_E_UTRAN = 7,
50 : /** Extended Coverage GSM for IoT (2G, 3GPP Rel 13) */
51 : CELLULAR_ACCESS_TECHNOLOGY_EC_GSM_IOT = 8,
52 : /** EUTRAN Narrowband-IoT (4G, 3GPP Rel 13) */
53 : CELLULAR_ACCESS_TECHNOLOGY_E_UTRAN_NB_S1 = 9,
54 : /** LTE/E-UTRA connected to 5G Core Network (5G, 3GPP Rel 15) */
55 : CELLULAR_ACCESS_TECHNOLOGY_E_UTRA_5G_CN = 10,
56 : /** New Radio with 5G Core Network (5G, 3GPP Rel 15) */
57 : CELLULAR_ACCESS_TECHNOLOGY_NR_5G_CN = 11,
58 : /** Next Generation RAN (5G, 3GPP Rel 15) */
59 : CELLULAR_ACCESS_TECHNOLOGY_NG_RAN = 12,
60 : /** LTE/E-UTRA & NR dual connectivity (5G, 3GPP Rel 15) */
61 : CELLULAR_ACCESS_TECHNOLOGY_E_UTRA_NR_DUAL = 13,
62 : /** Narrowband-IoT over Satellite (4G, 3GPP Rel 17) */
63 : CELLULAR_ACCESS_TECHNOLOGY_E_UTRAN_NB_S1_SAT = 14,
64 : /** LTE (wideband) over Satellite (4G, 3GPP Rel 17) */
65 : CELLULAR_ACCESS_TECHNOLOGY_E_UTRAN_WB_S1_SAT = 15,
66 : /** Next Generation RAN over Satellite (5G, 3GPP Rel 17) */
67 : CELLULAR_ACCESS_TECHNOLOGY_NG_RAN_SAT = 16,
68 : /** Unknown access technology */
69 : CELLULAR_ACCESS_TECHNOLOGY_UNKNOWN = 255,
70 : };
71 :
72 : /** Cellular network structure */
73 1 : struct cellular_network {
74 : /** Cellular access technology */
75 1 : enum cellular_access_technology technology;
76 : /**
77 : * List of bands, as defined by the specified cellular access technology,
78 : * to enables. All supported bands are enabled if none are provided.
79 : */
80 1 : uint16_t *bands;
81 : /** Size of bands */
82 1 : uint16_t size;
83 : };
84 :
85 : /** Cellular signal type */
86 0 : enum cellular_signal_type {
87 : CELLULAR_SIGNAL_RSSI,
88 : CELLULAR_SIGNAL_RSRP,
89 : CELLULAR_SIGNAL_RSRQ,
90 : };
91 :
92 : /** Cellular modem info type */
93 1 : enum cellular_modem_info_type {
94 : /** International Mobile Equipment Identity */
95 : CELLULAR_MODEM_INFO_IMEI,
96 : /** Modem model ID */
97 : CELLULAR_MODEM_INFO_MODEL_ID,
98 : /** Modem manufacturer */
99 : CELLULAR_MODEM_INFO_MANUFACTURER,
100 : /** Modem fw version */
101 : CELLULAR_MODEM_INFO_FW_VERSION,
102 : /** International Mobile Subscriber Identity */
103 : CELLULAR_MODEM_INFO_SIM_IMSI,
104 : /** Integrated Circuit Card Identification Number (SIM) */
105 : CELLULAR_MODEM_INFO_SIM_ICCID,
106 : };
107 :
108 : /** Cellular registration status (3GPP TS 27.007) */
109 1 : enum cellular_registration_status {
110 : /** Not registered, not searching */
111 : CELLULAR_REGISTRATION_NOT_REGISTERED = 0,
112 : /** Registered, home network */
113 : CELLULAR_REGISTRATION_REGISTERED_HOME = 1,
114 : /** Not registered, searching for an operator */
115 : CELLULAR_REGISTRATION_SEARCHING = 2,
116 : /** Registration denied */
117 : CELLULAR_REGISTRATION_DENIED = 3,
118 : /** Unknown (e.g. out of coverage) */
119 : CELLULAR_REGISTRATION_UNKNOWN = 4,
120 : /** Registered, roaming */
121 : CELLULAR_REGISTRATION_REGISTERED_ROAMING = 5,
122 : /** Registered for "SMS only", home network */
123 : CELLULAR_REGISTRATION_SMS_ONLY_HOME = 6,
124 : /** Registered for "SMS only", roaming network */
125 : CELLULAR_REGISTRATION_SMS_ONLY_ROAMING = 7,
126 : /** Attached for emergency bearer services only */
127 : CELLULAR_REGISTRATION_EMERGENCY_ONLY = 8,
128 : /** Registered for "CSFB not preferred", home network */
129 : CELLULAR_REGISTRATION_CSFB_NOT_PREFERRED_HOME = 9,
130 : /** Registered for "CSFB not preferred", roaming network */
131 : CELLULAR_REGISTRATION_CSFB_NOT_PREFERRED_ROAMING = 10,
132 : /** Attached for access to "Restricted Local Operator Services" */
133 : CELLULAR_REGISTRATION_RLOS = 11,
134 : };
135 :
136 : /** Events emitted asynchronously by a cellular driver */
137 1 : enum cellular_event {
138 : /** One or more modem-info field changed (e.g. IMSI became available). */
139 : CELLULAR_EVENT_MODEM_INFO_CHANGED = BIT(0),
140 : /** Cellular network registration status changed */
141 : CELLULAR_EVENT_REGISTRATION_STATUS_CHANGED = BIT(1),
142 : };
143 :
144 : /* Opaque bit-mask large enough for all current & future events */
145 0 : typedef uint32_t cellular_event_mask_t;
146 :
147 : /** Payload for @ref CELLULAR_EVENT_MODEM_INFO_CHANGED. */
148 1 : struct cellular_evt_modem_info {
149 1 : enum cellular_modem_info_type field; /**< Which field changed */
150 : };
151 :
152 : /** Payload for @ref CELLULAR_EVENT_REGISTRATION_STATUS_CHANGED. */
153 1 : struct cellular_evt_registration_status {
154 1 : enum cellular_registration_status status; /**< New registration status */
155 : };
156 :
157 : /**
158 : * @brief Prototype for cellular event callbacks.
159 : *
160 : * @param dev Cellular device that generated the event
161 : * @param event Which @ref cellular_event occurred
162 : * @param payload Pointer to the kind-specific payload
163 : * (`NULL` if the kind defines no payload).
164 : * @param user_data Pointer supplied when the callback was registered
165 : *
166 : * @note The driver calls the callback directly from its own context.
167 : * Off-load heavy processing to a work-queue if required.
168 : */
169 1 : typedef void (*cellular_event_cb_t)(const struct device *dev, enum cellular_event event,
170 : const void *payload, void *user_data);
171 :
172 : /** API for configuring networks */
173 1 : typedef int (*cellular_api_configure_networks)(const struct device *dev,
174 : const struct cellular_network *networks,
175 : uint8_t size);
176 :
177 : /** API for getting supported networks */
178 1 : typedef int (*cellular_api_get_supported_networks)(const struct device *dev,
179 : const struct cellular_network **networks,
180 : uint8_t *size);
181 :
182 : /** API for getting network signal strength */
183 1 : typedef int (*cellular_api_get_signal)(const struct device *dev,
184 : const enum cellular_signal_type type, int16_t *value);
185 :
186 : /** API for getting modem information */
187 1 : typedef int (*cellular_api_get_modem_info)(const struct device *dev,
188 : const enum cellular_modem_info_type type, char *info,
189 : size_t size);
190 :
191 : /** API for getting registration status */
192 1 : typedef int (*cellular_api_get_registration_status)(const struct device *dev,
193 : enum cellular_access_technology tech,
194 : enum cellular_registration_status *status);
195 :
196 : /** API for programming APN */
197 1 : typedef int (*cellular_api_set_apn)(const struct device *dev, const char *apn);
198 :
199 : /** API for registering an asynchronous callback */
200 1 : typedef int (*cellular_api_set_callback)(const struct device *dev, cellular_event_mask_t mask,
201 : cellular_event_cb_t cb, void *user_data);
202 :
203 : /** Cellular driver API */
204 1 : __subsystem struct cellular_driver_api {
205 0 : cellular_api_configure_networks configure_networks;
206 0 : cellular_api_get_supported_networks get_supported_networks;
207 0 : cellular_api_get_signal get_signal;
208 0 : cellular_api_get_modem_info get_modem_info;
209 0 : cellular_api_get_registration_status get_registration_status;
210 0 : cellular_api_set_apn set_apn;
211 0 : cellular_api_set_callback set_callback;
212 : };
213 :
214 : /**
215 : * @brief Configure cellular networks for the device
216 : *
217 : * @details Cellular network devices support at least one cellular access technology.
218 : * Each cellular access technology defines a set of bands, of which the cellular device
219 : * will support all or a subset of.
220 : *
221 : * The cellular device can only use one cellular network technology at a time. It must
222 : * exclusively use the cellular network configurations provided, and will prioritize
223 : * the cellular network configurations in the order they are provided in case there are
224 : * multiple (the first cellular network configuration has the highest priority).
225 : *
226 : * @param dev Cellular network device instance.
227 : * @param networks List of cellular network configurations to apply.
228 : * @param size Size of list of cellular network configurations.
229 : *
230 : * @retval 0 if successful.
231 : * @retval -EINVAL if any provided cellular network configuration is invalid or unsupported.
232 : * @retval -ENOTSUP if API is not supported by cellular network device.
233 : * @retval Negative errno-code otherwise.
234 : */
235 1 : static inline int cellular_configure_networks(const struct device *dev,
236 : const struct cellular_network *networks, uint8_t size)
237 : {
238 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
239 :
240 : if (api->configure_networks == NULL) {
241 : return -ENOSYS;
242 : }
243 :
244 : return api->configure_networks(dev, networks, size);
245 : }
246 :
247 : /**
248 : * @brief Get supported cellular networks for the device
249 : *
250 : * @param dev Cellular network device instance
251 : * @param networks Pointer to list of supported cellular network configurations.
252 : * @param size Size of list of cellular network configurations.
253 : *
254 : * @retval 0 if successful.
255 : * @retval -ENOTSUP if API is not supported by cellular network device.
256 : * @retval Negative errno-code otherwise.
257 : */
258 1 : static inline int cellular_get_supported_networks(const struct device *dev,
259 : const struct cellular_network **networks,
260 : uint8_t *size)
261 : {
262 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
263 :
264 : if (api->get_supported_networks == NULL) {
265 : return -ENOSYS;
266 : }
267 :
268 : return api->get_supported_networks(dev, networks, size);
269 : }
270 :
271 : /**
272 : * @brief Get signal for the device
273 : *
274 : * @param dev Cellular network device instance
275 : * @param type Type of the signal information requested
276 : * @param value Signal strength destination (one of RSSI, RSRP, RSRQ)
277 : *
278 : * @retval 0 if successful.
279 : * @retval -ENOTSUP if API is not supported by cellular network device.
280 : * @retval -ENODATA if device is not in a state where signal can be polled
281 : * @retval Negative errno-code otherwise.
282 : */
283 1 : static inline int cellular_get_signal(const struct device *dev,
284 : const enum cellular_signal_type type, int16_t *value)
285 : {
286 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
287 :
288 : if (api->get_signal == NULL) {
289 : return -ENOSYS;
290 : }
291 :
292 : return api->get_signal(dev, type, value);
293 : }
294 :
295 : /**
296 : * @brief Get modem info for the device
297 : *
298 : * @param dev Cellular network device instance
299 : * @param type Type of the modem info requested
300 : * @param info Info string destination
301 : * @param size Info string size
302 : *
303 : * @retval 0 if successful.
304 : * @retval -ENOTSUP if API is not supported by cellular network device.
305 : * @retval -ENODATA if modem does not provide info requested
306 : * @retval Negative errno-code from chat module otherwise.
307 : */
308 1 : static inline int cellular_get_modem_info(const struct device *dev,
309 : const enum cellular_modem_info_type type, char *info,
310 : size_t size)
311 : {
312 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
313 :
314 : if (api->get_modem_info == NULL) {
315 : return -ENOSYS;
316 : }
317 :
318 : return api->get_modem_info(dev, type, info, size);
319 : }
320 :
321 : /**
322 : * @brief Get network registration status for the device
323 : *
324 : * @param dev Cellular network device instance
325 : * @param tech Which access technology to get status for
326 : * @param status Registration status for given access technology
327 : *
328 : * @retval 0 if successful.
329 : * @retval -ENOSYS if API is not supported by cellular network device.
330 : * @retval -ENODATA if modem does not provide info requested
331 : * @retval Negative errno-code from chat module otherwise.
332 : */
333 1 : static inline int cellular_get_registration_status(const struct device *dev,
334 : enum cellular_access_technology tech,
335 : enum cellular_registration_status *status)
336 : {
337 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
338 :
339 : if (api->get_registration_status == NULL) {
340 : return -ENOSYS;
341 : }
342 :
343 : return api->get_registration_status(dev, tech, status);
344 : }
345 :
346 : /**
347 : * @brief Set the APN used for PDP context
348 : *
349 : * @details Drivers are expected to copy the string immediately and return
350 : * once the request has been queued internally.
351 : *
352 : * @param dev Cellular device
353 : * @param apn Zero-terminated APN string (max length is driver-specific)
354 : *
355 : * @retval 0 if successful.
356 : * @retval -ENOSYS if API is not supported by cellular network device.
357 : * @retval -EINVAL if APN string invalid or too long.
358 : * @retval -EALREADY if APN identical to current one, nothing to do
359 : * @retval -EBUSY if modem is already dialled, APN cannot be changed
360 : * @retval Negative errno-code otherwise.
361 : */
362 1 : static inline int cellular_set_apn(const struct device *dev, const char *apn)
363 : {
364 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
365 :
366 : if (api->set_apn == NULL) {
367 : return -ENOSYS;
368 : }
369 :
370 : return api->set_apn(dev, apn);
371 : }
372 :
373 : /**
374 : * @brief Subscribe to asynchronous cellular events.
375 : *
376 : * @param dev Cellular device
377 : * @param mask Event mask to subscribe to
378 : * @param cb Callback to call when the event occurs, or NULL to unsubscribe
379 : * @param user_data Pointer to user data that will be passed to the callback
380 : *
381 : * @retval 0 Success
382 : * @retval -ENOSYS Driver does not support event callbacks
383 : * @retval -EINVAL Bad parameters
384 : * @retval -ENOMEM No space left for another subscriber
385 : * @retval <0 Driver-specific error
386 : */
387 1 : static inline int cellular_set_callback(const struct device *dev, cellular_event_mask_t mask,
388 : cellular_event_cb_t cb, void *user_data)
389 : {
390 : const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
391 :
392 : if (api->set_callback == NULL) {
393 : return -ENOSYS;
394 : }
395 :
396 : return api->set_callback(dev, mask, cb, user_data);
397 : }
398 :
399 : #ifdef __cplusplus
400 : }
401 : #endif
402 :
403 : /**
404 : * @}
405 : */
406 :
407 : #endif /* ZEPHYR_INCLUDE_DRIVERS_CELLULAR_H_ */
|