blob: 967d53e89b40953cb09aaf6d14f2b2cdf52cf931 [file] [log] [blame]
/*
* Copyright (c) 2023 Bjarki Arge Andreasen
* Copyright (c) 2023 Lucas Denefle
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @ingroup cellular_interface
* @brief Main header file for cellular modem driver API.
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_CELLULAR_H_
#define ZEPHYR_INCLUDE_DRIVERS_CELLULAR_H_
/**
* @brief Interfaces for cellular modems.
* @defgroup cellular_interface Cellular
* @ingroup io_interfaces
* @{
*/
#include <zephyr/types.h>
#include <zephyr/device.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Cellular access technologies (3GPP TS 27.007 AcT) */
enum cellular_access_technology {
/** Global System for Mobile communications (2G, 3GPP Rel 99) */
CELLULAR_ACCESS_TECHNOLOGY_GSM = 0,
/** Bandwidth & Spectrum limited variant of GSM (2G, 3GPP Rel 99) */
CELLULAR_ACCESS_TECHNOLOGY_GSM_COMPACT = 1,
/** UMTS Terrestrial Radio Access Network (3G, 3GPP Rel 99) */
CELLULAR_ACCESS_TECHNOLOGY_UTRAN = 2,
/** GSM Enhanced General Packet Radio Service (2.5G, 3GPP Rel 99) */
CELLULAR_ACCESS_TECHNOLOGY_GSM_EGPRS = 3,
/** UTRAN with High Speed Downlink Packet Access (3.5G, 3GPP Rel 5) */
CELLULAR_ACCESS_TECHNOLOGY_UTRAN_HSDPA = 4,
/** UTRAN with High Speed Uplink Packet Access (3.75G, 3GPP Rel 6) */
CELLULAR_ACCESS_TECHNOLOGY_UTRAN_HSUPA = 5,
/** UTRAN with HSDPA and HSUDP (HSPA) (3.75G, 3GPP Rel 6) */
CELLULAR_ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA = 6,
/** Evolved UTRAN (4G, 3GPP Rel 8) */
CELLULAR_ACCESS_TECHNOLOGY_E_UTRAN = 7,
/** Extended Coverage GSM for IoT (2G, 3GPP Rel 13) */
CELLULAR_ACCESS_TECHNOLOGY_EC_GSM_IOT = 8,
/** EUTRAN Narrowband-IoT (4G, 3GPP Rel 13) */
CELLULAR_ACCESS_TECHNOLOGY_E_UTRAN_NB_S1 = 9,
/** LTE/E-UTRA connected to 5G Core Network (5G, 3GPP Rel 15) */
CELLULAR_ACCESS_TECHNOLOGY_E_UTRA_5G_CN = 10,
/** New Radio with 5G Core Network (5G, 3GPP Rel 15) */
CELLULAR_ACCESS_TECHNOLOGY_NR_5G_CN = 11,
/** Next Generation RAN (5G, 3GPP Rel 15) */
CELLULAR_ACCESS_TECHNOLOGY_NG_RAN = 12,
/** LTE/E-UTRA & NR dual connectivity (5G, 3GPP Rel 15) */
CELLULAR_ACCESS_TECHNOLOGY_E_UTRA_NR_DUAL = 13,
/** Narrowband-IoT over Satellite (4G, 3GPP Rel 17) */
CELLULAR_ACCESS_TECHNOLOGY_E_UTRAN_NB_S1_SAT = 14,
/** LTE (wideband) over Satellite (4G, 3GPP Rel 17) */
CELLULAR_ACCESS_TECHNOLOGY_E_UTRAN_WB_S1_SAT = 15,
/** Next Generation RAN over Satellite (5G, 3GPP Rel 17) */
CELLULAR_ACCESS_TECHNOLOGY_NG_RAN_SAT = 16,
/** Unknown access technology */
CELLULAR_ACCESS_TECHNOLOGY_UNKNOWN = 255,
};
/** Cellular network structure */
struct cellular_network {
/** Cellular access technology */
enum cellular_access_technology technology;
/**
* List of bands, as defined by the specified cellular access technology,
* to enables. All supported bands are enabled if none are provided.
*/
uint16_t *bands;
/** Size of bands */
uint16_t size;
};
/** Cellular signal type */
enum cellular_signal_type {
CELLULAR_SIGNAL_RSSI,
CELLULAR_SIGNAL_RSRP,
CELLULAR_SIGNAL_RSRQ,
};
/** Cellular modem info type */
enum cellular_modem_info_type {
/** International Mobile Equipment Identity */
CELLULAR_MODEM_INFO_IMEI,
/** Modem model ID */
CELLULAR_MODEM_INFO_MODEL_ID,
/** Modem manufacturer */
CELLULAR_MODEM_INFO_MANUFACTURER,
/** Modem fw version */
CELLULAR_MODEM_INFO_FW_VERSION,
/** International Mobile Subscriber Identity */
CELLULAR_MODEM_INFO_SIM_IMSI,
/** Integrated Circuit Card Identification Number (SIM) */
CELLULAR_MODEM_INFO_SIM_ICCID,
};
/** Cellular registration status (3GPP TS 27.007) */
enum cellular_registration_status {
/** Not registered, not searching */
CELLULAR_REGISTRATION_NOT_REGISTERED = 0,
/** Registered, home network */
CELLULAR_REGISTRATION_REGISTERED_HOME = 1,
/** Not registered, searching for an operator */
CELLULAR_REGISTRATION_SEARCHING = 2,
/** Registration denied */
CELLULAR_REGISTRATION_DENIED = 3,
/** Unknown (e.g. out of coverage) */
CELLULAR_REGISTRATION_UNKNOWN = 4,
/** Registered, roaming */
CELLULAR_REGISTRATION_REGISTERED_ROAMING = 5,
/** Registered for "SMS only", home network */
CELLULAR_REGISTRATION_SMS_ONLY_HOME = 6,
/** Registered for "SMS only", roaming network */
CELLULAR_REGISTRATION_SMS_ONLY_ROAMING = 7,
/** Attached for emergency bearer services only */
CELLULAR_REGISTRATION_EMERGENCY_ONLY = 8,
/** Registered for "CSFB not preferred", home network */
CELLULAR_REGISTRATION_CSFB_NOT_PREFERRED_HOME = 9,
/** Registered for "CSFB not preferred", roaming network */
CELLULAR_REGISTRATION_CSFB_NOT_PREFERRED_ROAMING = 10,
/** Attached for access to "Restricted Local Operator Services" */
CELLULAR_REGISTRATION_RLOS = 11,
};
/** Events emitted asynchronously by a cellular driver */
enum cellular_event {
/** One or more modem-info field changed (e.g. IMSI became available). */
CELLULAR_EVENT_MODEM_INFO_CHANGED = BIT(0),
/** Cellular network registration status changed */
CELLULAR_EVENT_REGISTRATION_STATUS_CHANGED = BIT(1),
};
/* Opaque bit-mask large enough for all current & future events */
typedef uint32_t cellular_event_mask_t;
/** Payload for @ref CELLULAR_EVENT_MODEM_INFO_CHANGED. */
struct cellular_evt_modem_info {
enum cellular_modem_info_type field; /**< Which field changed */
};
/** Payload for @ref CELLULAR_EVENT_REGISTRATION_STATUS_CHANGED. */
struct cellular_evt_registration_status {
enum cellular_registration_status status; /**< New registration status */
};
/**
* @brief Prototype for cellular event callbacks.
*
* @param dev Cellular device that generated the event
* @param event Which @ref cellular_event occurred
* @param payload Pointer to the kind-specific payload
* (`NULL` if the kind defines no payload).
* @param user_data Pointer supplied when the callback was registered
*
* @note The driver calls the callback directly from its own context.
* Off-load heavy processing to a work-queue if required.
*/
typedef void (*cellular_event_cb_t)(const struct device *dev, enum cellular_event event,
const void *payload, void *user_data);
/** API for configuring networks */
typedef int (*cellular_api_configure_networks)(const struct device *dev,
const struct cellular_network *networks,
uint8_t size);
/** API for getting supported networks */
typedef int (*cellular_api_get_supported_networks)(const struct device *dev,
const struct cellular_network **networks,
uint8_t *size);
/** API for getting network signal strength */
typedef int (*cellular_api_get_signal)(const struct device *dev,
const enum cellular_signal_type type, int16_t *value);
/** API for getting modem information */
typedef int (*cellular_api_get_modem_info)(const struct device *dev,
const enum cellular_modem_info_type type, char *info,
size_t size);
/** API for getting registration status */
typedef int (*cellular_api_get_registration_status)(const struct device *dev,
enum cellular_access_technology tech,
enum cellular_registration_status *status);
/** API for programming APN */
typedef int (*cellular_api_set_apn)(const struct device *dev, const char *apn);
/** API for registering an asynchronous callback */
typedef int (*cellular_api_set_callback)(const struct device *dev, cellular_event_mask_t mask,
cellular_event_cb_t cb, void *user_data);
/** Cellular driver API */
__subsystem struct cellular_driver_api {
cellular_api_configure_networks configure_networks;
cellular_api_get_supported_networks get_supported_networks;
cellular_api_get_signal get_signal;
cellular_api_get_modem_info get_modem_info;
cellular_api_get_registration_status get_registration_status;
cellular_api_set_apn set_apn;
cellular_api_set_callback set_callback;
};
/**
* @brief Configure cellular networks for the device
*
* @details Cellular network devices support at least one cellular access technology.
* Each cellular access technology defines a set of bands, of which the cellular device
* will support all or a subset of.
*
* The cellular device can only use one cellular network technology at a time. It must
* exclusively use the cellular network configurations provided, and will prioritize
* the cellular network configurations in the order they are provided in case there are
* multiple (the first cellular network configuration has the highest priority).
*
* @param dev Cellular network device instance.
* @param networks List of cellular network configurations to apply.
* @param size Size of list of cellular network configurations.
*
* @retval 0 if successful.
* @retval -EINVAL if any provided cellular network configuration is invalid or unsupported.
* @retval -ENOTSUP if API is not supported by cellular network device.
* @retval Negative errno-code otherwise.
*/
static inline int cellular_configure_networks(const struct device *dev,
const struct cellular_network *networks, uint8_t size)
{
const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
if (api->configure_networks == NULL) {
return -ENOSYS;
}
return api->configure_networks(dev, networks, size);
}
/**
* @brief Get supported cellular networks for the device
*
* @param dev Cellular network device instance
* @param networks Pointer to list of supported cellular network configurations.
* @param size Size of list of cellular network configurations.
*
* @retval 0 if successful.
* @retval -ENOTSUP if API is not supported by cellular network device.
* @retval Negative errno-code otherwise.
*/
static inline int cellular_get_supported_networks(const struct device *dev,
const struct cellular_network **networks,
uint8_t *size)
{
const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
if (api->get_supported_networks == NULL) {
return -ENOSYS;
}
return api->get_supported_networks(dev, networks, size);
}
/**
* @brief Get signal for the device
*
* @param dev Cellular network device instance
* @param type Type of the signal information requested
* @param value Signal strength destination (one of RSSI, RSRP, RSRQ)
*
* @retval 0 if successful.
* @retval -ENOTSUP if API is not supported by cellular network device.
* @retval -ENODATA if device is not in a state where signal can be polled
* @retval Negative errno-code otherwise.
*/
static inline int cellular_get_signal(const struct device *dev,
const enum cellular_signal_type type, int16_t *value)
{
const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
if (api->get_signal == NULL) {
return -ENOSYS;
}
return api->get_signal(dev, type, value);
}
/**
* @brief Get modem info for the device
*
* @param dev Cellular network device instance
* @param type Type of the modem info requested
* @param info Info string destination
* @param size Info string size
*
* @retval 0 if successful.
* @retval -ENOTSUP if API is not supported by cellular network device.
* @retval -ENODATA if modem does not provide info requested
* @retval Negative errno-code from chat module otherwise.
*/
static inline int cellular_get_modem_info(const struct device *dev,
const enum cellular_modem_info_type type, char *info,
size_t size)
{
const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
if (api->get_modem_info == NULL) {
return -ENOSYS;
}
return api->get_modem_info(dev, type, info, size);
}
/**
* @brief Get network registration status for the device
*
* @param dev Cellular network device instance
* @param tech Which access technology to get status for
* @param status Registration status for given access technology
*
* @retval 0 if successful.
* @retval -ENOSYS if API is not supported by cellular network device.
* @retval -ENODATA if modem does not provide info requested
* @retval Negative errno-code from chat module otherwise.
*/
static inline int cellular_get_registration_status(const struct device *dev,
enum cellular_access_technology tech,
enum cellular_registration_status *status)
{
const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
if (api->get_registration_status == NULL) {
return -ENOSYS;
}
return api->get_registration_status(dev, tech, status);
}
/**
* @brief Set the APN used for PDP context
*
* @details Drivers are expected to copy the string immediately and return
* once the request has been queued internally.
*
* @param dev Cellular device
* @param apn Zero-terminated APN string (max length is driver-specific)
*
* @retval 0 if successful.
* @retval -ENOSYS if API is not supported by cellular network device.
* @retval -EINVAL if APN string invalid or too long.
* @retval -EALREADY if APN identical to current one, nothing to do
* @retval -EBUSY if modem is already dialled, APN cannot be changed
* @retval Negative errno-code otherwise.
*/
static inline int cellular_set_apn(const struct device *dev, const char *apn)
{
const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
if (api->set_apn == NULL) {
return -ENOSYS;
}
return api->set_apn(dev, apn);
}
/**
* @brief Subscribe to asynchronous cellular events.
*
* @param dev Cellular device
* @param mask Event mask to subscribe to
* @param cb Callback to call when the event occurs, or NULL to unsubscribe
* @param user_data Pointer to user data that will be passed to the callback
*
* @retval 0 Success
* @retval -ENOSYS Driver does not support event callbacks
* @retval -EINVAL Bad parameters
* @retval -ENOMEM No space left for another subscriber
* @retval <0 Driver-specific error
*/
static inline int cellular_set_callback(const struct device *dev, cellular_event_mask_t mask,
cellular_event_cb_t cb, void *user_data)
{
const struct cellular_driver_api *api = (const struct cellular_driver_api *)dev->api;
if (api->set_callback == NULL) {
return -ENOSYS;
}
return api->set_callback(dev, mask, cb, user_data);
}
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* ZEPHYR_INCLUDE_DRIVERS_CELLULAR_H_ */