blob: b73314aece2c5ce58cd7568eecf14ff8aba9f79d [file] [log] [blame]
/*
* Copyright (c) 2020 Siddharth Chandrasekaran <siddharth@embedjournal.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Open Supervised Device Protocol (OSDP) public API header file.
*/
#ifndef _OSDP_H_
#define _OSDP_H_
#include <zephyr/kernel.h>
#include <stdint.h>
#include <zephyr/sys/slist.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSDP_CMD_TEXT_MAX_LEN 32 /**< Max length of text for text command */
#define OSDP_CMD_KEYSET_KEY_MAX_LEN 32 /**< Max length of key data for keyset command */
#define OSDP_EVENT_MAX_DATALEN 64 /**< Max length of event data */
/**
* @brief Command sent from CP to Control digital output of PD.
*/
struct osdp_cmd_output {
/**
* Output number.
*
* 0 = First Output, 1 = Second Output, etc.
*/
uint8_t output_no;
/**
* Control code.
*
* - 0 - NOP – do not alter this output
* - 1 - set the permanent state to OFF, abort timed operation (if any)
* - 2 - set the permanent state to ON, abort timed operation (if any)
* - 3 - set the permanent state to OFF, allow timed operation to complete
* - 4 - set the permanent state to ON, allow timed operation to complete
* - 5 - set the temporary state to ON, resume perm state on timeout
* - 6 - set the temporary state to OFF, resume permanent state on timeout
*/
uint8_t control_code;
/**
* Time in units of 100 ms
*/
uint16_t timer_count;
};
/**
* @brief LED Colors as specified in OSDP for the on_color/off_color parameters.
*/
enum osdp_led_color_e {
OSDP_LED_COLOR_NONE, /**< No color */
OSDP_LED_COLOR_RED, /**< Red */
OSDP_LED_COLOR_GREEN, /**< Green */
OSDP_LED_COLOR_AMBER, /**< Amber */
OSDP_LED_COLOR_BLUE, /**< Blue */
OSDP_LED_COLOR_SENTINEL /**< Max value */
};
/**
* @brief LED params sub-structure. Part of LED command. See @ref osdp_cmd_led.
*/
struct osdp_cmd_led_params {
/** Control code.
*
* Temporary Control Code:
* - 0 - NOP - do not alter this LED's temporary settings.
* - 1 - Cancel any temporary operation and display this LED's permanent state immediately.
* - 2 - Set the temporary state as given and start timer immediately.
*
* Permanent Control Code:
* - 0 - NOP - do not alter this LED's permanent settings.
* - 1 - Set the permanent state as given.
*/
uint8_t control_code;
/**
* The ON duration of the flash, in units of 100 ms.
*/
uint8_t on_count;
/**
* The OFF duration of the flash, in units of 100 ms.
*/
uint8_t off_count;
/**
* Color to set during the ON timer (see @ref osdp_led_color_e).
*/
uint8_t on_color;
/**
* Color to set during the OFF timer (see @ref osdp_led_color_e).
*/
uint8_t off_color;
/**
* Time in units of 100 ms (only for temporary mode).
*/
uint16_t timer_count;
};
/**
* @brief Sent from CP to PD to control the behaviour of it's on-board LEDs
*/
struct osdp_cmd_led {
/**
* Reader number. 0 = First Reader, 1 = Second Reader, etc.
*/
uint8_t reader;
/**
* LED number. 0 = first LED, 1 = second LED, etc.
*/
uint8_t led_number;
/**
* Ephemeral LED status descriptor.
*/
struct osdp_cmd_led_params temporary;
/**
* Permanent LED status descriptor.
*/
struct osdp_cmd_led_params permanent;
};
/**
* @brief Sent from CP to control the behaviour of a buzzer in the PD.
*/
struct osdp_cmd_buzzer {
/**
* Reader number. 0 = First Reader, 1 = Second Reader, etc.
*/
uint8_t reader;
/**
* Control code.
* - 0 - no tone
* - 1 - off
* - 2 - default tone
* - 3+ - TBD
*/
uint8_t control_code;
/**
* The ON duration of the sound, in units of 100 ms.
*/
uint8_t on_count;
/**
* The OFF duration of the sound, in units of 100 ms.
*/
uint8_t off_count;
/**
* The number of times to repeat the ON/OFF cycle; 0: forever.
*/
uint8_t rep_count;
};
/**
* @brief Command to manipulate any display units that the PD supports.
*/
struct osdp_cmd_text {
/**
* Reader number. 0 = First Reader, 1 = Second Reader, etc.
*/
uint8_t reader;
/**
* Control code.
* - 1 - permanent text, no wrap
* - 2 - permanent text, with wrap
* - 3 - temp text, no wrap
* - 4 - temp text, with wrap
*/
uint8_t control_code;
/**
* Duration to display temporary text, in seconds
*/
uint8_t temp_time;
/**
* Row to display the first character (1-indexed)
*/
uint8_t offset_row;
/**
* Column to display the first character (1-indexed)
*/
uint8_t offset_col;
/**
* Number of characters in the string
*/
uint8_t length;
/**
* The string to display
*/
uint8_t data[OSDP_CMD_TEXT_MAX_LEN];
};
/**
* @brief Sent in response to a COMSET command. Set communication parameters to
* PD. Must be stored in PD non-volatile memory.
*/
struct osdp_cmd_comset {
/**
* Unit ID to which this PD will respond after the change takes effect.
*/
uint8_t address;
/**
* Baud rate.
*
* Valid values: 9600, 19200, 38400, 115200, 230400.
*/
uint32_t baud_rate;
};
/**
* @brief This command transfers an encryption key from the CP to a PD.
*
* @param type Type of keys:
* - 0x01 – Secure Channel Base Key
* @param length Number of bytes of key data - (Key Length in bits + 7) / 8
* @param data Key data
*/
struct osdp_cmd_keyset {
/**
* Type of keys:
* - 0x01 – Secure Channel Base Key
*/
uint8_t type;
/**
* Number of bytes of key data - (Key Length in bits + 7) / 8
*/
uint8_t length;
/**
* Key data
*/
uint8_t data[OSDP_CMD_KEYSET_KEY_MAX_LEN];
};
/**
* @brief OSDP application exposed commands
*/
enum osdp_cmd_e {
OSDP_CMD_OUTPUT = 1, /**< Output control command */
OSDP_CMD_LED, /**< Reader LED control command */
OSDP_CMD_BUZZER, /**< Reader buzzer control command */
OSDP_CMD_TEXT, /**< Reader text output command */
OSDP_CMD_KEYSET, /**< Encryption Key Set Command */
OSDP_CMD_COMSET, /**< PD Communication Configuration Command */
OSDP_CMD_SENTINEL /**< Max command value */
};
/**
* @brief OSDP Command Structure. This is a wrapper for all individual OSDP
* commands.
*/
struct osdp_cmd {
/** @cond INTERNAL_HIDDEN */
sys_snode_t node;
/** @endcond */
/**
* Command ID.
* Used to select specific commands in union.
*/
enum osdp_cmd_e id;
/** Command */
union {
struct osdp_cmd_led led; /**< LED command structure */
struct osdp_cmd_buzzer buzzer; /**< Buzzer command structure */
struct osdp_cmd_text text; /**< Text command structure */
struct osdp_cmd_output output; /**< Output command structure */
struct osdp_cmd_comset comset; /**< Comset command structure */
struct osdp_cmd_keyset keyset; /**< Keyset command structure */
};
};
/**
* @brief Various card formats that a PD can support. This is sent to CP
* when a PD must report a card read.
*/
enum osdp_event_cardread_format_e {
OSDP_CARD_FMT_RAW_UNSPECIFIED, /**< Unspecified card format */
OSDP_CARD_FMT_RAW_WIEGAND, /**< Wiegand card format */
OSDP_CARD_FMT_ASCII, /**< ASCII card format */
OSDP_CARD_FMT_SENTINEL /**< Max card format value */
};
/**
* @brief OSDP event cardread
*
* @note When @a format is set to OSDP_CARD_FMT_RAW_UNSPECIFIED or
* OSDP_CARD_FMT_RAW_WIEGAND, the length is expressed in bits. OTOH, when it is
* set to OSDP_CARD_FMT_ASCII, the length is in bytes. The number of bytes to
* read from the @a data field must be interpreted accordingly.
*/
struct osdp_event_cardread {
/**
* Reader number. 0 = First Reader, 1 = Second Reader, etc.
*/
int reader_no;
/**
* Format of the card being read.
*/
enum osdp_event_cardread_format_e format;
/**
* Direction of data in @a data array.
* - 0 - Forward
* - 1 - Backward
*/
int direction;
/**
* Length of card data in bytes or bits depending on @a format
*/
int length;
/**
* Card data of @a length bytes or bits bits depending on @a format
*/
uint8_t data[OSDP_EVENT_MAX_DATALEN];
};
/**
* @brief OSDP Event Keypad
*/
struct osdp_event_keypress {
/**
* Reader number.
* In context of readers attached to current PD, this number indicated this number. This is
* not supported by LibOSDP.
*/
int reader_no;
/**
* Length of keypress data in bytes
*/
int length;
/**
* Keypress data of @a length bytes
*/
uint8_t data[OSDP_EVENT_MAX_DATALEN];
};
/**
* @brief OSDP PD Events
*/
enum osdp_event_type {
OSDP_EVENT_CARDREAD, /**< Card read event */
OSDP_EVENT_KEYPRESS, /**< Keypad press event */
OSDP_EVENT_SENTINEL /**< Max event value */
};
/**
* @brief OSDP Event structure.
*/
struct osdp_event {
/** @cond INTERNAL_HIDDEN */
sys_snode_t node;
/** @endcond */
/**
* Event type.
* Used to select specific event in union.
*/
enum osdp_event_type type;
/** Event */
union {
struct osdp_event_keypress keypress; /**< Keypress event structure */
struct osdp_event_cardread cardread; /**< Card read event structure */
};
};
/**
* @brief Callback for PD command notifications. After it has been registered
* with `osdp_pd_set_command_callback`, this method is invoked when the PD
* receives a command from the CP.
*
* @param arg pointer that will was passed to the arg param of
* `osdp_pd_set_command_callback`.
* @param cmd pointer to the received command.
*
* @retval 0 if LibOSDP must send a `osdp_ACK` response
* @retval -ve if LibOSDP must send a `osdp_NAK` response
* @retval +ve and modify the passed `struct osdp_cmd *cmd` if LibOSDP must send
* a specific response. This is useful for sending manufacturer specific
* reply ``osdp_MFGREP``.
*/
typedef int (*pd_command_callback_t)(void *arg, struct osdp_cmd *cmd);
/**
* @brief Callback for CP event notifications. After it has been registered with
* `osdp_cp_set_event_callback`, this method is invoked when the CP receives an
* event from the PD.
*
* @param arg Opaque pointer provided by the application during callback
* registration.
* @param pd the offset (0-indexed) of this PD in kconfig `OSDP_PD_ADDRESS_LIST`
* @param ev pointer to osdp_event struct (filled by libosdp).
*
* @retval 0 on handling the event successfully.
* @retval -ve on errors.
*/
typedef int (*cp_event_callback_t)(void *arg, int pd, struct osdp_event *ev);
#if defined(CONFIG_OSDP_MODE_PD) || defined(__DOXYGEN__)
/**
* @name Peripheral Device mode APIs
* @note These are only available when @kconfig{CONFIG_OSDP_MODE_PD} is enabled.
* @{
*/
/**
* @brief Set callback method for PD command notification. This callback is
* invoked when the PD receives a command from the CP.
*
* @param cb The callback function's pointer
* @param arg A pointer that will be passed as the first argument of `cb`
*/
void osdp_pd_set_command_callback(pd_command_callback_t cb, void *arg);
/**
* @brief API to notify PD events to CP. These events are sent to the CP as an
* alternate response to a POLL command.
*
* @param event pointer to event struct. Must be filled by application.
*
* @retval 0 on success
* @retval -1 on failure
*/
int osdp_pd_notify_event(const struct osdp_event *event);
/**
* @}
*/
#else /* CONFIG_OSDP_MODE_PD */
/**
* @brief Generic command enqueue API.
*
* @param pd the offset (0-indexed) of this PD in kconfig `OSDP_PD_ADDRESS_LIST`
* @param cmd command pointer. Must be filled by application.
*
* @retval 0 on success
* @retval -1 on failure
*
* @note This method only adds the command on to a particular PD's command
* queue. The command itself can fail due to various reasons.
*/
int osdp_cp_send_command(int pd, struct osdp_cmd *cmd);
/**
* @brief Set callback method for CP event notification. This callback is
* invoked when the CP receives an event from the PD.
*
* @param cb The callback function's pointer
* @param arg A pointer that will be passed as the first argument of `cb`
*/
void osdp_cp_set_event_callback(cp_event_callback_t cb, void *arg);
#endif /* CONFIG_OSDP_MODE_PD */
#if defined(CONFIG_OSDP_SC_ENABLED) || defined(__DOXYGEN__)
/**
* @name OSDP Secure Channel APIs
* @note These are only available when @kconfig{CONFIG_OSDP_SC_ENABLED} is
* enabled.
* @{
*/
/**
* Get the current SC status mask.
* @return SC status mask
*/
uint32_t osdp_get_sc_status_mask(void);
/**
* @}
*/
#endif
#ifdef __cplusplus
}
#endif
#endif /* _OSDP_H_ */