Skip to content

Commit 7380947

Browse files
sidchacarlescufi
authored andcommitted
mgmt/osdp: Add support for event delivery and notifications
The CP app sends PD a "command" and the PD responds to it. Some times, the PD has something that it wants to tell the PD which it does so in response to POLL command. Both CP and PD apps need a way to exchange these info over the OSDP bus. To archive this we will introduce what are called "events" that allow the PD app to enqueue and CP app to get notified. This is analogous to the incumbent "commands" abstraction where, the CP app enqueues a command and the PD app gets notified of it. Signed-off-by: Siddharth Chandrasekaran <[email protected]>
1 parent c7fec71 commit 7380947

File tree

7 files changed

+464
-238
lines changed

7 files changed

+464
-238
lines changed

include/zephyr/mgmt/osdp.h

Lines changed: 147 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,7 @@ extern "C" {
1818

1919
#define OSDP_CMD_TEXT_MAX_LEN 32
2020
#define OSDP_CMD_KEYSET_KEY_MAX_LEN 32
21-
22-
/**
23-
* @brief Various card formats that a PD can support. This is sent to CP
24-
* when a PD must report a card read.
25-
*/
26-
enum osdp_card_formats_e {
27-
OSDP_CARD_FMT_RAW_UNSPECIFIED,
28-
OSDP_CARD_FMT_RAW_WIEGAND,
29-
OSDP_CARD_FMT_ASCII,
30-
OSDP_CARD_FMT_SENTINEL
31-
};
21+
#define OSDP_EVENT_MAX_DATALEN 64
3222

3323
/**
3424
* @brief Command sent from CP to Control digital output of PD.
@@ -211,24 +201,162 @@ struct osdp_cmd {
211201
};
212202
};
213203

204+
/**
205+
* @brief Various card formats that a PD can support. This is sent to CP
206+
* when a PD must report a card read.
207+
*/
208+
enum osdp_event_cardread_format_e {
209+
OSDP_CARD_FMT_RAW_UNSPECIFIED,
210+
OSDP_CARD_FMT_RAW_WIEGAND,
211+
OSDP_CARD_FMT_ASCII,
212+
OSDP_CARD_FMT_SENTINEL
213+
};
214+
215+
/**
216+
* @brief OSDP event cardread
217+
*
218+
* @param reader_no In context of readers attached to current PD, this number
219+
* indicated this number. This is not supported by LibOSDP.
220+
* @param format Format of the card being read.
221+
* see `enum osdp_event_cardread_format_e`
222+
* @param direction Card read direction of PD 0 - Forward; 1 - Backward
223+
* @param length Length of card data in bytes or bits depending on `format`
224+
* (see note).
225+
* @param data Card data of `length` bytes or bits bits depending on `format`
226+
* (see note).
227+
*
228+
* @note When `format` is set to OSDP_CARD_FMT_RAW_UNSPECIFIED or
229+
* OSDP_CARD_FMT_RAW_WIEGAND, the length is expressed in bits. OTOH, when it is
230+
* set to OSDP_CARD_FMT_ASCII, the length is in bytes. The number of bytes to
231+
* read from the `data` field must be interpreted accordingly.
232+
*/
233+
struct osdp_event_cardread {
234+
int reader_no;
235+
enum osdp_event_cardread_format_e format;
236+
int direction;
237+
int length;
238+
uint8_t data[OSDP_EVENT_MAX_DATALEN];
239+
};
240+
241+
/**
242+
* @brief OSDP Event Keypad
243+
*
244+
* @param reader_no In context of readers attached to current PD, this number
245+
* indicated this number. This is not supported by LibOSDP.
246+
* @param length Length of keypress data in bytes
247+
* @param data keypress data of `length` bytes
248+
*/
249+
struct osdp_event_keypress {
250+
int reader_no;
251+
int length;
252+
uint8_t data[OSDP_EVENT_MAX_DATALEN];
253+
};
254+
255+
/**
256+
* @brief OSDP PD Events
257+
*/
258+
enum osdp_event_type {
259+
OSDP_EVENT_CARDREAD,
260+
OSDP_EVENT_KEYPRESS,
261+
OSDP_EVENT_SENTINEL
262+
};
263+
264+
/**
265+
* @brief OSDP Event structure.
266+
*
267+
* @param type used to select specific event in union. See: enum osdp_event_type
268+
* @param keypress keypress event structure
269+
* @param cardread cardread event structure
270+
*/
271+
struct osdp_event {
272+
sys_snode_t node;
273+
enum osdp_event_type type;
274+
union {
275+
struct osdp_event_keypress keypress;
276+
struct osdp_event_cardread cardread;
277+
};
278+
};
279+
280+
/**
281+
* @brief Callback for PD command notifications. After it has been registered
282+
* with `osdp_pd_set_command_callback`, this method is invoked when the PD
283+
* receives a command from the CP.
284+
*
285+
* @param arg pointer that will was passed to the arg param of
286+
* `osdp_pd_set_command_callback`.
287+
* @param cmd pointer to the received command.
288+
*
289+
* @retval 0 if LibOSDP must send a `osdp_ACK` response
290+
* @retval -ve if LibOSDP must send a `osdp_NAK` response
291+
* @retval +ve and modify the passed `struct osdp_cmd *cmd` if LibOSDP must send
292+
* a specific response. This is useful for sending manufacturer specific
293+
* reply ``osdp_MFGREP``.
294+
*/
295+
typedef int (*pd_command_callback_t)(void *arg, struct osdp_cmd *cmd);
296+
297+
/**
298+
* @brief Callback for CP event notifications. After it has been registered with
299+
* `osdp_cp_set_event_callback`, this method is invoked when the CP receives an
300+
* event from the PD.
301+
*
302+
* @param arg Opaque pointer provided by the application during callback
303+
* registration.
304+
* @param pd the offset (0-indexed) of this PD in kconfig `OSDP_PD_ADDRESS_LIST`
305+
* @param ev pointer to osdp_event struct (filled by libosdp).
306+
*
307+
* @retval 0 on handling the event successfully.
308+
* @retval -ve on errors.
309+
*/
310+
typedef int (*cp_event_callback_t)(void *arg, int pd, struct osdp_event *ev);
311+
214312
#ifdef CONFIG_OSDP_MODE_PD
215313

216314
/**
217-
* @param cmd pointer to a command structure that was received by the driver.
315+
* @brief Set callback method for PD command notification. This callback is
316+
* invoked when the PD receives a command from the CP.
218317
*
219-
* @retval 0 on success.
220-
* @retval -1 on failure.
318+
* @param cb The callback function's pointer
319+
* @param arg A pointer that will be passed as the first argument of `cb`
221320
*/
222-
int osdp_pd_get_cmd(struct osdp_cmd *cmd);
321+
void osdp_pd_set_command_callback(pd_command_callback_t cb, void *arg);
322+
323+
/**
324+
* @brief API to notify PD events to CP. These events are sent to the CP as an
325+
* alternate response to a POLL command.
326+
*
327+
* @param event pointer to event struct. Must be filled by application.
328+
*
329+
* @retval 0 on success
330+
* @retval -1 on failure
331+
*/
332+
int osdp_pd_notify_event(const struct osdp_event *event);
223333

224334
#else /* CONFIG_OSDP_MODE_PD */
225335

226-
int osdp_cp_set_callback_key_press(
227-
int (*cb)(int address, uint8_t key));
228-
int osdp_cp_set_callback_card_read(
229-
int (*cb)(int address, int format, uint8_t *data, int len));
336+
/**
337+
* @brief Generic command enqueue API.
338+
*
339+
* @param pd the offset (0-indexed) of this PD in kconfig `OSDP_PD_ADDRESS_LIST`
340+
* @param cmd command pointer. Must be filled by application.
341+
*
342+
* @retval 0 on success
343+
* @retval -1 on failure
344+
*
345+
* @note This method only adds the command on to a particular PD's command
346+
* queue. The command itself can fail due to various reasons.
347+
*/
230348
int osdp_cp_send_command(int pd, struct osdp_cmd *cmd);
231349

350+
351+
/**
352+
* @brief Set callback method for CP event notification. This callback is
353+
* invoked when the CP receives an event from the PD.
354+
*
355+
* @param cb The callback function's pointer
356+
* @param arg A pointer that will be passed as the first argument of `cb`
357+
*/
358+
void osdp_cp_set_event_callback(cp_event_callback_t cb, void *arg);
359+
232360
#endif /* CONFIG_OSDP_MODE_PD */
233361

234362
#ifdef CONFIG_OSDP_SC_ENABLED

samples/subsys/mgmt/osdp/control_panel/src/main.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ enum osdp_pd_e {
2828
OSDP_PD_SENTINEL,
2929
};
3030

31-
int key_press_callback(int pd, uint8_t key)
31+
int key_press_callback(int pd, uint8_t *data, int len)
3232
{
33-
printk("CP PD[%d] key press - data: 0x%02x\n", pd, key);
33+
printk("CP PD[%d] key press - data: 0x%02x\n", pd, data[0]);
3434
return 0;
3535
}
3636

@@ -49,6 +49,22 @@ int card_read_callback(int pd, int format, uint8_t *data, int len)
4949
return 0;
5050
}
5151

52+
int event_handler(void *unused, int pd, struct osdp_event *e)
53+
{
54+
switch (e->type) {
55+
case OSDP_EVENT_CARDREAD:
56+
card_read_callback(pd, e->cardread.format,
57+
e->cardread.data, e->cardread.length);
58+
break;
59+
case OSDP_EVENT_KEYPRESS:
60+
key_press_callback(pd, e->keypress.data, e->keypress.length);
61+
break;
62+
default:
63+
break;
64+
}
65+
return 0;
66+
}
67+
5268
void main(void)
5369
{
5470
int ret, led_state;
@@ -71,8 +87,7 @@ void main(void)
7187
return;
7288
}
7389

74-
osdp_cp_set_callback_key_press(key_press_callback);
75-
osdp_cp_set_callback_card_read(card_read_callback);
90+
osdp_cp_set_event_callback(event_handler, NULL);
7691

7792
led_state = 0;
7893
while (1) {

samples/subsys/mgmt/osdp/peripheral_device/src/main.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET_OR(LED0_NODE, gpios, {0
2121
#define SLEEP_TIME_MS (20)
2222
#define CNT_PER_SEC (1000 / SLEEP_TIME_MS)
2323

24-
int cmd_handler(struct osdp_cmd *p)
24+
int cmd_handler(void *unused, struct osdp_cmd *p)
2525
{
2626
printk("App received command %d\n", p->id);
2727
return 0;
@@ -31,7 +31,6 @@ void main(void)
3131
{
3232
int ret, led_state;
3333
uint32_t cnt = 0;
34-
struct osdp_cmd cmd;
3534

3635
if (!device_is_ready(led0.port)) {
3736
printk("LED0 GPIO port %s is not ready\n", led0.port->name);
@@ -45,15 +44,14 @@ void main(void)
4544
return;
4645
}
4746

47+
osdp_pd_set_command_callback(cmd_handler, NULL);
48+
4849
led_state = 0;
4950
while (1) {
5051
if ((cnt & 0x7f) == 0x7f) {
5152
/* show a sign of life */
5253
led_state = !led_state;
5354
}
54-
if (osdp_pd_get_cmd(&cmd) == 0) {
55-
cmd_handler(&cmd);
56-
}
5755
gpio_pin_set(led0.port, led0.pin, led_state);
5856
k_msleep(SLEEP_TIME_MS);
5957
cnt++;

subsys/mgmt/osdp/src/osdp_common.c

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -41,45 +41,6 @@ int64_t osdp_millis_since(int64_t last)
4141
return (int64_t) k_uptime_delta(&tmp);
4242
}
4343

44-
struct osdp_cmd *osdp_cmd_alloc(struct osdp_pd *pd)
45-
{
46-
struct osdp_cmd *cmd = NULL;
47-
48-
if (k_mem_slab_alloc(&pd->cmd.slab, (void **)&cmd, K_MSEC(100))) {
49-
LOG_ERR("Memory allocation time-out");
50-
return NULL;
51-
}
52-
return cmd;
53-
}
54-
55-
void osdp_cmd_free(struct osdp_pd *pd, struct osdp_cmd *cmd)
56-
{
57-
k_mem_slab_free(&pd->cmd.slab, (void **)&cmd);
58-
}
59-
60-
void osdp_cmd_enqueue(struct osdp_pd *pd, struct osdp_cmd *cmd)
61-
{
62-
sys_slist_append(&pd->cmd.queue, &cmd->node);
63-
}
64-
65-
int osdp_cmd_dequeue(struct osdp_pd *pd, struct osdp_cmd **cmd)
66-
{
67-
sys_snode_t *node;
68-
69-
node = sys_slist_peek_head(&pd->cmd.queue);
70-
if (node == NULL) {
71-
return -1;
72-
}
73-
sys_slist_remove(&pd->cmd.queue, NULL, node);
74-
*cmd = CONTAINER_OF(node, struct osdp_cmd, node);
75-
return 0;
76-
}
77-
78-
struct osdp_cmd *osdp_cmd_get_last(struct osdp_pd *pd)
79-
{
80-
return (struct osdp_cmd *)sys_slist_peek_tail(&pd->cmd.queue);
81-
}
82-
8344
#ifdef CONFIG_OSDP_SC_ENABLED
8445

8546
void osdp_encrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len)

0 commit comments

Comments
 (0)