1 /* 2 * Copyright (c) 2020 Siddharth Chandrasekaran <siddharth@embedjournal.com> 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * @brief Open Supervised Device Protocol (OSDP) public API header file. 10 */ 11 12 #ifndef _OSDP_H_ 13 #define _OSDP_H_ 14 15 #include <zephyr/kernel.h> 16 #include <stdint.h> 17 18 #include <zephyr/sys/slist.h> 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 #define OSDP_CMD_TEXT_MAX_LEN 32 /**< Max length of text for text command */ 25 #define OSDP_CMD_KEYSET_KEY_MAX_LEN 32 /**< Max length of key data for keyset command */ 26 #define OSDP_EVENT_MAX_DATALEN 64 /**< Max length of event data */ 27 28 /** 29 * @brief Command sent from CP to Control digital output of PD. 30 */ 31 struct osdp_cmd_output { 32 /** 33 * Output number. 34 * 35 * 0 = First Output, 1 = Second Output, etc. 36 */ 37 uint8_t output_no; 38 /** 39 * Control code. 40 * 41 * - 0 - NOP – do not alter this output 42 * - 1 - set the permanent state to OFF, abort timed operation (if any) 43 * - 2 - set the permanent state to ON, abort timed operation (if any) 44 * - 3 - set the permanent state to OFF, allow timed operation to complete 45 * - 4 - set the permanent state to ON, allow timed operation to complete 46 * - 5 - set the temporary state to ON, resume perm state on timeout 47 * - 6 - set the temporary state to OFF, resume permanent state on timeout 48 */ 49 uint8_t control_code; 50 /** 51 * Time in units of 100 ms 52 */ 53 uint16_t timer_count; 54 }; 55 56 /** 57 * @brief LED Colors as specified in OSDP for the on_color/off_color parameters. 58 */ 59 enum osdp_led_color_e { 60 OSDP_LED_COLOR_NONE, /**< No color */ 61 OSDP_LED_COLOR_RED, /**< Red */ 62 OSDP_LED_COLOR_GREEN, /**< Green */ 63 OSDP_LED_COLOR_AMBER, /**< Amber */ 64 OSDP_LED_COLOR_BLUE, /**< Blue */ 65 OSDP_LED_COLOR_SENTINEL /**< Max value */ 66 }; 67 68 /** 69 * @brief LED params sub-structure. Part of LED command. See @ref osdp_cmd_led. 70 */ 71 struct osdp_cmd_led_params { 72 /** Control code. 73 * 74 * Temporary Control Code: 75 * - 0 - NOP - do not alter this LED's temporary settings. 76 * - 1 - Cancel any temporary operation and display this LED's permanent state immediately. 77 * - 2 - Set the temporary state as given and start timer immediately. 78 * 79 * Permanent Control Code: 80 * - 0 - NOP - do not alter this LED's permanent settings. 81 * - 1 - Set the permanent state as given. 82 */ 83 uint8_t control_code; 84 /** 85 * The ON duration of the flash, in units of 100 ms. 86 */ 87 uint8_t on_count; 88 /** 89 * The OFF duration of the flash, in units of 100 ms. 90 */ 91 uint8_t off_count; 92 /** 93 * Color to set during the ON timer (see @ref osdp_led_color_e). 94 */ 95 uint8_t on_color; 96 /** 97 * Color to set during the OFF timer (see @ref osdp_led_color_e). 98 */ 99 uint8_t off_color; 100 /** 101 * Time in units of 100 ms (only for temporary mode). 102 */ 103 uint16_t timer_count; 104 }; 105 106 /** 107 * @brief Sent from CP to PD to control the behaviour of it's on-board LEDs 108 */ 109 struct osdp_cmd_led { 110 /** 111 * Reader number. 0 = First Reader, 1 = Second Reader, etc. 112 */ 113 uint8_t reader; 114 /** 115 * LED number. 0 = first LED, 1 = second LED, etc. 116 */ 117 uint8_t led_number; 118 /** 119 * Ephemeral LED status descriptor. 120 */ 121 struct osdp_cmd_led_params temporary; 122 /** 123 * Permanent LED status descriptor. 124 */ 125 struct osdp_cmd_led_params permanent; 126 }; 127 128 /** 129 * @brief Sent from CP to control the behaviour of a buzzer in the PD. 130 */ 131 struct osdp_cmd_buzzer { 132 /** 133 * Reader number. 0 = First Reader, 1 = Second Reader, etc. 134 */ 135 uint8_t reader; 136 /** 137 * Control code. 138 * - 0 - no tone 139 * - 1 - off 140 * - 2 - default tone 141 * - 3+ - TBD 142 */ 143 uint8_t control_code; 144 /** 145 * The ON duration of the sound, in units of 100 ms. 146 */ 147 uint8_t on_count; 148 /** 149 * The OFF duration of the sound, in units of 100 ms. 150 */ 151 uint8_t off_count; 152 /** 153 * The number of times to repeat the ON/OFF cycle; 0: forever. 154 */ 155 uint8_t rep_count; 156 }; 157 158 /** 159 * @brief Command to manipulate any display units that the PD supports. 160 */ 161 struct osdp_cmd_text { 162 /** 163 * Reader number. 0 = First Reader, 1 = Second Reader, etc. 164 */ 165 uint8_t reader; 166 /** 167 * Control code. 168 * - 1 - permanent text, no wrap 169 * - 2 - permanent text, with wrap 170 * - 3 - temp text, no wrap 171 * - 4 - temp text, with wrap 172 */ 173 uint8_t control_code; 174 /** 175 * Duration to display temporary text, in seconds 176 */ 177 uint8_t temp_time; 178 /** 179 * Row to display the first character (1-indexed) 180 */ 181 uint8_t offset_row; 182 /** 183 * Column to display the first character (1-indexed) 184 */ 185 uint8_t offset_col; 186 /** 187 * Number of characters in the string 188 */ 189 uint8_t length; 190 /** 191 * The string to display 192 */ 193 uint8_t data[OSDP_CMD_TEXT_MAX_LEN]; 194 }; 195 196 /** 197 * @brief Sent in response to a COMSET command. Set communication parameters to 198 * PD. Must be stored in PD non-volatile memory. 199 */ 200 struct osdp_cmd_comset { 201 /** 202 * Unit ID to which this PD will respond after the change takes effect. 203 */ 204 uint8_t address; 205 /** 206 * Baud rate. 207 * 208 * Valid values: 9600, 19200, 38400, 115200, 230400. 209 */ 210 uint32_t baud_rate; 211 }; 212 213 /** 214 * @brief This command transfers an encryption key from the CP to a PD. 215 * 216 * @param type Type of keys: 217 * - 0x01 – Secure Channel Base Key 218 * @param length Number of bytes of key data - (Key Length in bits + 7) / 8 219 * @param data Key data 220 */ 221 struct osdp_cmd_keyset { 222 /** 223 * Type of keys: 224 * - 0x01 – Secure Channel Base Key 225 */ 226 uint8_t type; 227 /** 228 * Number of bytes of key data - (Key Length in bits + 7) / 8 229 */ 230 uint8_t length; 231 /** 232 * Key data 233 */ 234 uint8_t data[OSDP_CMD_KEYSET_KEY_MAX_LEN]; 235 }; 236 237 /** 238 * @brief OSDP application exposed commands 239 */ 240 enum osdp_cmd_e { 241 OSDP_CMD_OUTPUT = 1, /**< Output control command */ 242 OSDP_CMD_LED, /**< Reader LED control command */ 243 OSDP_CMD_BUZZER, /**< Reader buzzer control command */ 244 OSDP_CMD_TEXT, /**< Reader text output command */ 245 OSDP_CMD_KEYSET, /**< Encryption Key Set Command */ 246 OSDP_CMD_COMSET, /**< PD Communication Configuration Command */ 247 OSDP_CMD_SENTINEL /**< Max command value */ 248 }; 249 250 /** 251 * @brief OSDP Command Structure. This is a wrapper for all individual OSDP 252 * commands. 253 */ 254 struct osdp_cmd { 255 /** @cond INTERNAL_HIDDEN */ 256 sys_snode_t node; 257 /** @endcond */ 258 /** 259 * Command ID. 260 * Used to select specific commands in union. 261 */ 262 enum osdp_cmd_e id; 263 /** Command */ 264 union { 265 struct osdp_cmd_led led; /**< LED command structure */ 266 struct osdp_cmd_buzzer buzzer; /**< Buzzer command structure */ 267 struct osdp_cmd_text text; /**< Text command structure */ 268 struct osdp_cmd_output output; /**< Output command structure */ 269 struct osdp_cmd_comset comset; /**< Comset command structure */ 270 struct osdp_cmd_keyset keyset; /**< Keyset command structure */ 271 }; 272 }; 273 274 /** 275 * @brief Various card formats that a PD can support. This is sent to CP 276 * when a PD must report a card read. 277 */ 278 enum osdp_event_cardread_format_e { 279 OSDP_CARD_FMT_RAW_UNSPECIFIED, /**< Unspecified card format */ 280 OSDP_CARD_FMT_RAW_WIEGAND, /**< Wiegand card format */ 281 OSDP_CARD_FMT_ASCII, /**< ASCII card format */ 282 OSDP_CARD_FMT_SENTINEL /**< Max card format value */ 283 }; 284 285 /** 286 * @brief OSDP event cardread 287 * 288 * @note When @a format is set to OSDP_CARD_FMT_RAW_UNSPECIFIED or 289 * OSDP_CARD_FMT_RAW_WIEGAND, the length is expressed in bits. OTOH, when it is 290 * set to OSDP_CARD_FMT_ASCII, the length is in bytes. The number of bytes to 291 * read from the @a data field must be interpreted accordingly. 292 */ 293 struct osdp_event_cardread { 294 /** 295 * Reader number. 0 = First Reader, 1 = Second Reader, etc. 296 */ 297 int reader_no; 298 /** 299 * Format of the card being read. 300 */ 301 enum osdp_event_cardread_format_e format; 302 /** 303 * Direction of data in @a data array. 304 * - 0 - Forward 305 * - 1 - Backward 306 */ 307 int direction; 308 /** 309 * Length of card data in bytes or bits depending on @a format 310 */ 311 int length; 312 /** 313 * Card data of @a length bytes or bits bits depending on @a format 314 */ 315 uint8_t data[OSDP_EVENT_MAX_DATALEN]; 316 }; 317 318 /** 319 * @brief OSDP Event Keypad 320 */ 321 struct osdp_event_keypress { 322 /** 323 * Reader number. 324 * In context of readers attached to current PD, this number indicated this number. This is 325 * not supported by LibOSDP. 326 */ 327 int reader_no; 328 /** 329 * Length of keypress data in bytes 330 */ 331 int length; 332 /** 333 * Keypress data of @a length bytes 334 */ 335 uint8_t data[OSDP_EVENT_MAX_DATALEN]; 336 }; 337 338 /** 339 * @brief OSDP PD Events 340 */ 341 enum osdp_event_type { 342 OSDP_EVENT_CARDREAD, /**< Card read event */ 343 OSDP_EVENT_KEYPRESS, /**< Keypad press event */ 344 OSDP_EVENT_SENTINEL /**< Max event value */ 345 }; 346 347 /** 348 * @brief OSDP Event structure. 349 */ 350 struct osdp_event { 351 /** @cond INTERNAL_HIDDEN */ 352 sys_snode_t node; 353 /** @endcond */ 354 /** 355 * Event type. 356 * Used to select specific event in union. 357 */ 358 enum osdp_event_type type; 359 /** Event */ 360 union { 361 struct osdp_event_keypress keypress; /**< Keypress event structure */ 362 struct osdp_event_cardread cardread; /**< Card read event structure */ 363 }; 364 }; 365 366 /** 367 * @brief Callback for PD command notifications. After it has been registered 368 * with `osdp_pd_set_command_callback`, this method is invoked when the PD 369 * receives a command from the CP. 370 * 371 * @param arg pointer that will was passed to the arg param of 372 * `osdp_pd_set_command_callback`. 373 * @param cmd pointer to the received command. 374 * 375 * @retval 0 if LibOSDP must send a `osdp_ACK` response 376 * @retval -ve if LibOSDP must send a `osdp_NAK` response 377 * @retval +ve and modify the passed `struct osdp_cmd *cmd` if LibOSDP must send 378 * a specific response. This is useful for sending manufacturer specific 379 * reply ``osdp_MFGREP``. 380 */ 381 typedef int (*pd_command_callback_t)(void *arg, struct osdp_cmd *cmd); 382 383 /** 384 * @brief Callback for CP event notifications. After it has been registered with 385 * `osdp_cp_set_event_callback`, this method is invoked when the CP receives an 386 * event from the PD. 387 * 388 * @param arg Opaque pointer provided by the application during callback 389 * registration. 390 * @param pd the offset (0-indexed) of this PD in kconfig `OSDP_PD_ADDRESS_LIST` 391 * @param ev pointer to osdp_event struct (filled by libosdp). 392 * 393 * @retval 0 on handling the event successfully. 394 * @retval -ve on errors. 395 */ 396 typedef int (*cp_event_callback_t)(void *arg, int pd, struct osdp_event *ev); 397 398 #if defined(CONFIG_OSDP_MODE_PD) || defined(__DOXYGEN__) 399 400 /** 401 * @name Peripheral Device mode APIs 402 * @note These are only available when @kconfig{CONFIG_OSDP_MODE_PD} is enabled. 403 * @{ 404 */ 405 406 /** 407 * @brief Set callback method for PD command notification. This callback is 408 * invoked when the PD receives a command from the CP. 409 * 410 * @param cb The callback function's pointer 411 * @param arg A pointer that will be passed as the first argument of `cb` 412 */ 413 void osdp_pd_set_command_callback(pd_command_callback_t cb, void *arg); 414 415 /** 416 * @brief API to notify PD events to CP. These events are sent to the CP as an 417 * alternate response to a POLL command. 418 * 419 * @param event pointer to event struct. Must be filled by application. 420 * 421 * @retval 0 on success 422 * @retval -1 on failure 423 */ 424 int osdp_pd_notify_event(const struct osdp_event *event); 425 426 /** 427 * @} 428 */ 429 430 #else /* CONFIG_OSDP_MODE_PD */ 431 432 /** 433 * @brief Generic command enqueue API. 434 * 435 * @param pd the offset (0-indexed) of this PD in kconfig `OSDP_PD_ADDRESS_LIST` 436 * @param cmd command pointer. Must be filled by application. 437 * 438 * @retval 0 on success 439 * @retval -1 on failure 440 * 441 * @note This method only adds the command on to a particular PD's command 442 * queue. The command itself can fail due to various reasons. 443 */ 444 int osdp_cp_send_command(int pd, struct osdp_cmd *cmd); 445 446 447 /** 448 * @brief Set callback method for CP event notification. This callback is 449 * invoked when the CP receives an event from the PD. 450 * 451 * @param cb The callback function's pointer 452 * @param arg A pointer that will be passed as the first argument of `cb` 453 */ 454 void osdp_cp_set_event_callback(cp_event_callback_t cb, void *arg); 455 456 #endif /* CONFIG_OSDP_MODE_PD */ 457 458 #if defined(CONFIG_OSDP_SC_ENABLED) || defined(__DOXYGEN__) 459 460 /** 461 * @name OSDP Secure Channel APIs 462 * @note These are only available when @kconfig{CONFIG_OSDP_SC_ENABLED} is 463 * enabled. 464 * @{ 465 */ 466 467 /** 468 * Get the current SC status mask. 469 * @return SC status mask 470 */ 471 uint32_t osdp_get_sc_status_mask(void); 472 473 /** 474 * @} 475 */ 476 477 #endif 478 479 #ifdef __cplusplus 480 } 481 #endif 482 483 #endif /* _OSDP_H_ */ 484