Lines Matching full:pd

65 		1, /* The PD supports the 16-bit CRC-16 mode */
117 static struct osdp_event *pd_event_alloc(struct osdp_pd *pd) in pd_event_alloc() argument
121 if (k_mem_slab_alloc(&pd->event.slab, (void **)&event, K_MSEC(100))) { in pd_event_alloc()
128 static void pd_event_free(struct osdp_pd *pd, struct osdp_event *event) in pd_event_free() argument
130 k_mem_slab_free(&pd->event.slab, (void *)event); in pd_event_free()
133 static void pd_event_enqueue(struct osdp_pd *pd, struct osdp_event *event) in pd_event_enqueue() argument
135 sys_slist_append(&pd->event.queue, &event->node); in pd_event_enqueue()
138 static int pd_event_dequeue(struct osdp_pd *pd, struct osdp_event **event) in pd_event_dequeue() argument
142 node = sys_slist_peek_head(&pd->event.queue); in pd_event_dequeue()
146 sys_slist_remove(&pd->event.queue, NULL, node); in pd_event_dequeue()
151 static int pd_translate_event(struct osdp_pd *pd, struct osdp_event *event) in pd_translate_event() argument
178 memcpy(pd->ephemeral_data, event, sizeof(struct osdp_event)); in pd_translate_event()
182 static bool do_command_callback(struct osdp_pd *pd, struct osdp_cmd *cmd) in do_command_callback() argument
186 ret = pd->command_callback(pd->command_callback_arg, cmd); in do_command_callback()
188 pd->reply_id = REPLY_NAK; in do_command_callback()
189 pd->ephemeral_data[0] = OSDP_PD_NAK_RECORD; in do_command_callback()
195 static int pd_cmd_cap_ok(struct osdp_pd *pd, struct osdp_cmd *cmd) in pd_cmd_cap_ok() argument
199 /* Validate the cmd_id against a PD capabilities where applicable */ in pd_cmd_cap_ok()
200 switch (pd->cmd_id) { in pd_cmd_cap_ok()
202 cap = &pd->cap[OSDP_PD_CAP_CONTACT_STATUS_MONITORING]; in pd_cmd_cap_ok()
208 cap = &pd->cap[OSDP_PD_CAP_OUTPUT_CONTROL]; in pd_cmd_cap_ok()
214 cap = &pd->cap[OSDP_PD_CAP_OUTPUT_CONTROL]; in pd_cmd_cap_ok()
221 cap = &pd->cap[OSDP_PD_CAP_READER_LED_CONTROL]; in pd_cmd_cap_ok()
228 cap = &pd->cap[OSDP_PD_CAP_READER_AUDIBLE_OUTPUT]; in pd_cmd_cap_ok()
234 cap = &pd->cap[OSDP_PD_CAP_READER_TEXT_OUTPUT]; in pd_cmd_cap_ok()
242 cap = &pd->cap[OSDP_PD_CAP_COMMUNICATION_SECURITY]; in pd_cmd_cap_ok()
244 pd->reply_id = REPLY_NAK; in pd_cmd_cap_ok()
245 pd->ephemeral_data[0] = OSDP_PD_NAK_SC_UNSUP; in pd_cmd_cap_ok()
251 pd->reply_id = REPLY_NAK; in pd_cmd_cap_ok()
252 pd->ephemeral_data[0] = OSDP_PD_NAK_CMD_UNKNOWN; in pd_cmd_cap_ok()
253 LOG_ERR("PD is not capable of handling CMD(%02x); " in pd_cmd_cap_ok()
254 "Reply with NAK_CMD_UNKNOWN", pd->cmd_id); in pd_cmd_cap_ok()
258 static int pd_decode_command(struct osdp_pd *pd, uint8_t *buf, int len) in pd_decode_command() argument
265 pd->reply_id = 0; in pd_decode_command()
266 pd->cmd_id = cmd.id = buf[pos++]; in pd_decode_command()
269 switch (pd->cmd_id) { in pd_decode_command()
275 if (pd_event_dequeue(pd, &event) == 0) { in pd_decode_command()
276 ret = pd_translate_event(pd, event); in pd_decode_command()
277 pd->reply_id = ret; in pd_decode_command()
278 pd_event_free(pd, event); in pd_decode_command()
280 pd->reply_id = REPLY_ACK; in pd_decode_command()
288 pd->reply_id = REPLY_LSTATR; in pd_decode_command()
295 if (!pd_cmd_cap_ok(pd, NULL)) { in pd_decode_command()
299 pd->reply_id = REPLY_ISTATR; in pd_decode_command()
306 if (!pd_cmd_cap_ok(pd, NULL)) { in pd_decode_command()
310 pd->reply_id = REPLY_OSTATR; in pd_decode_command()
317 pd->reply_id = REPLY_RSTATR; in pd_decode_command()
325 pd->reply_id = REPLY_PDID; in pd_decode_command()
333 pd->reply_id = REPLY_PDCAP; in pd_decode_command()
337 if (len != CMD_OUT_DATA_LEN || !pd->command_callback) { in pd_decode_command()
346 if (!pd_cmd_cap_ok(pd, &cmd)) { in pd_decode_command()
349 if (!do_command_callback(pd, &cmd)) { in pd_decode_command()
352 pd->reply_id = REPLY_ACK; in pd_decode_command()
356 if (len != CMD_LED_DATA_LEN || !pd->command_callback) { in pd_decode_command()
377 if (!pd_cmd_cap_ok(pd, &cmd)) { in pd_decode_command()
380 if (!do_command_callback(pd, &cmd)) { in pd_decode_command()
383 pd->reply_id = REPLY_ACK; in pd_decode_command()
387 if (len != CMD_BUZ_DATA_LEN || !pd->command_callback) { in pd_decode_command()
397 if (!pd_cmd_cap_ok(pd, &cmd)) { in pd_decode_command()
400 if (!do_command_callback(pd, &cmd)) { in pd_decode_command()
403 pd->reply_id = REPLY_ACK; in pd_decode_command()
407 if (len < CMD_TEXT_DATA_LEN || !pd->command_callback) { in pd_decode_command()
424 if (!pd_cmd_cap_ok(pd, &cmd)) { in pd_decode_command()
427 if (!do_command_callback(pd, &cmd)) { in pd_decode_command()
430 pd->reply_id = REPLY_ACK; in pd_decode_command()
434 if (len != CMD_COMSET_DATA_LEN || !pd->command_callback) { in pd_decode_command()
450 cmd.comset.address = pd->address; in pd_decode_command()
451 cmd.comset.baud_rate = pd->baud_rate; in pd_decode_command()
454 if (!do_command_callback(pd, &cmd)) { in pd_decode_command()
458 memcpy(pd->ephemeral_data, &cmd, sizeof(struct osdp_cmd)); in pd_decode_command()
459 pd->reply_id = REPLY_COM; in pd_decode_command()
474 if (!pd_cmd_cap_ok(pd, NULL)) { in pd_decode_command()
478 * For CMD_KEYSET to be accepted, PD must be in pd_decode_command()
481 if (!sc_is_active(pd)) { in pd_decode_command()
482 pd->reply_id = REPLY_NAK; in pd_decode_command()
483 pd->ephemeral_data[0] = OSDP_PD_NAK_SC_COND; in pd_decode_command()
491 if (!pd->command_callback) { in pd_decode_command()
493 "SCBK will be lost when the PD reboots."); in pd_decode_command()
494 } else if (!do_command_callback(pd, &cmd)) { in pd_decode_command()
497 memcpy(pd->sc.scbk, cmd.keyset.data, 16); in pd_decode_command()
498 CLEAR_FLAG(pd, PD_FLAG_SC_USE_SCBKD); in pd_decode_command()
499 CLEAR_FLAG(pd, PD_FLAG_INSTALL_MODE); in pd_decode_command()
500 sc_deactivate(pd); in pd_decode_command()
501 pd->reply_id = REPLY_ACK; in pd_decode_command()
509 if (!pd_cmd_cap_ok(pd, NULL)) { in pd_decode_command()
512 sc_deactivate(pd); in pd_decode_command()
513 osdp_sc_setup(pd); in pd_decode_command()
514 memcpy(pd->sc.cp_random, buf + pos, 8); in pd_decode_command()
515 pd->reply_id = REPLY_CCRYPT; in pd_decode_command()
523 if (!pd_cmd_cap_ok(pd, NULL)) { in pd_decode_command()
526 if (sc_is_active(pd)) { in pd_decode_command()
527 pd->reply_id = REPLY_NAK; in pd_decode_command()
528 pd->ephemeral_data[0] = OSDP_PD_NAK_SC_COND; in pd_decode_command()
532 memcpy(pd->sc.cp_cryptogram, buf + pos, CMD_SCRYPT_DATA_LEN); in pd_decode_command()
533 pd->reply_id = REPLY_RMAC_I; in pd_decode_command()
538 LOG_ERR("Unknown CMD(%02x)", pd->cmd_id); in pd_decode_command()
539 pd->reply_id = REPLY_NAK; in pd_decode_command()
540 pd->ephemeral_data[0] = OSDP_PD_NAK_CMD_UNKNOWN; in pd_decode_command()
546 pd->cmd_id, len, ret); in pd_decode_command()
547 pd->reply_id = REPLY_NAK; in pd_decode_command()
548 pd->ephemeral_data[0] = OSDP_PD_NAK_CMD_LEN; in pd_decode_command()
552 if (pd->cmd_id != CMD_POLL) { in pd_decode_command()
553 LOG_DBG("CMD: %02x REPLY: %02x", pd->cmd_id, pd->reply_id); in pd_decode_command()
573 static int pd_build_reply(struct osdp_pd *pd, uint8_t *buf, int max_len) in pd_build_reply() argument
579 int data_off = osdp_phy_packet_get_data_offset(pd, buf); in pd_build_reply()
581 uint8_t *smb = osdp_phy_packet_get_smb(pd, buf); in pd_build_reply()
586 switch (pd->reply_id) { in pd_build_reply()
591 buf[len++] = pd->reply_id; in pd_build_reply()
598 buf[len++] = pd->reply_id; in pd_build_reply()
600 buf[len++] = BYTE_0(pd->id.vendor_code); in pd_build_reply()
601 buf[len++] = BYTE_1(pd->id.vendor_code); in pd_build_reply()
602 buf[len++] = BYTE_2(pd->id.vendor_code); in pd_build_reply()
604 buf[len++] = pd->id.model; in pd_build_reply()
605 buf[len++] = pd->id.version; in pd_build_reply()
607 buf[len++] = BYTE_0(pd->id.serial_number); in pd_build_reply()
608 buf[len++] = BYTE_1(pd->id.serial_number); in pd_build_reply()
609 buf[len++] = BYTE_2(pd->id.serial_number); in pd_build_reply()
610 buf[len++] = BYTE_3(pd->id.serial_number); in pd_build_reply()
612 buf[len++] = BYTE_3(pd->id.firmware_version); in pd_build_reply()
613 buf[len++] = BYTE_2(pd->id.firmware_version); in pd_build_reply()
614 buf[len++] = BYTE_1(pd->id.firmware_version); in pd_build_reply()
621 buf[len++] = pd->reply_id; in pd_build_reply()
623 if (pd->cap[i].function_code != i) { in pd_build_reply()
631 buf[len++] = pd->cap[i].compliance_level; in pd_build_reply()
632 buf[len++] = pd->cap[i].num_items; in pd_build_reply()
641 buf[len++] = pd->reply_id; in pd_build_reply()
642 buf[len++] = ISSET_FLAG(pd, PD_FLAG_TAMPER); in pd_build_reply()
643 buf[len++] = ISSET_FLAG(pd, PD_FLAG_POWER); in pd_build_reply()
650 buf[len++] = pd->reply_id; in pd_build_reply()
651 buf[len++] = ISSET_FLAG(pd, PD_FLAG_R_TAMPER); in pd_build_reply()
655 event = (struct osdp_event *)pd->ephemeral_data; in pd_build_reply()
659 buf[len++] = pd->reply_id; in pd_build_reply()
669 event = (struct osdp_event *)pd->ephemeral_data; in pd_build_reply()
674 buf[len++] = pd->reply_id; in pd_build_reply()
685 event = (struct osdp_event *)pd->ephemeral_data; in pd_build_reply()
689 buf[len++] = pd->reply_id; in pd_build_reply()
702 * If COMSET succeeds, the PD must reply with the old params and in pd_build_reply()
706 * pd->addr/pd->baud_rate. in pd_build_reply()
708 * TODO: Persist pd->address and pd->baud_rate via in pd_build_reply()
711 cmd = (struct osdp_cmd *)pd->ephemeral_data; in pd_build_reply()
712 buf[len++] = pd->reply_id; in pd_build_reply()
719 pd->address = (int)cmd->comset.address; in pd_build_reply()
720 pd->baud_rate = (int)cmd->comset.baud_rate; in pd_build_reply()
721 LOG_INF("COMSET Succeeded! New PD-Addr: %d; Baud: %d", in pd_build_reply()
722 pd->address, pd->baud_rate); in pd_build_reply()
729 buf[len++] = pd->reply_id; in pd_build_reply()
730 buf[len++] = pd->ephemeral_data[0]; in pd_build_reply()
741 osdp_fill_random(pd->sc.pd_random, 8); in pd_build_reply()
742 osdp_compute_session_keys(pd); in pd_build_reply()
743 osdp_compute_pd_cryptogram(pd); in pd_build_reply()
744 buf[len++] = pd->reply_id; in pd_build_reply()
745 memcpy(buf + len, pd->sc.pd_client_uid, 8); in pd_build_reply()
746 memcpy(buf + len + 8, pd->sc.pd_random, 8); in pd_build_reply()
747 memcpy(buf + len + 16, pd->sc.pd_cryptogram, 16); in pd_build_reply()
751 smb[2] = ISSET_FLAG(pd, PD_FLAG_SC_USE_SCBKD) ? 0 : 1; in pd_build_reply()
761 osdp_compute_rmac_i(pd); in pd_build_reply()
762 buf[len++] = pd->reply_id; in pd_build_reply()
763 memcpy(buf + len, pd->sc.r_mac, 16); in pd_build_reply()
767 if (osdp_verify_cp_cryptogram(pd) == 0) { in pd_build_reply()
769 sc_activate(pd); in pd_build_reply()
770 pd->sc_tstamp = osdp_millis_now(); in pd_build_reply()
771 if (ISSET_FLAG(pd, PD_FLAG_SC_USE_SCBKD)) { in pd_build_reply()
786 if (smb && (smb[1] > SCS_14) && sc_is_active(pd)) { in pd_build_reply()
795 pd->reply_id); in pd_build_reply()
807 static int pd_send_reply(struct osdp_pd *pd) in pd_send_reply() argument
812 len = osdp_phy_packet_init(pd, pd->rx_buf, sizeof(pd->rx_buf)); in pd_send_reply()
818 ret = pd_build_reply(pd, pd->rx_buf, sizeof(pd->rx_buf)); in pd_send_reply()
825 len = osdp_phy_packet_finalize(pd, pd->rx_buf, len, sizeof(pd->rx_buf)); in pd_send_reply()
831 if (pd->channel.flush) { in pd_send_reply()
832 pd->channel.flush(pd->channel.data); in pd_send_reply()
835 ret = pd->channel.send(pd->channel.data, pd->rx_buf, len); in pd_send_reply()
842 if (pd->cmd_id != CMD_POLL) { in pd_send_reply()
843 osdp_dump("PD sent", pd->rx_buf, len); in pd_send_reply()
850 static int pd_decode_packet(struct osdp_pd *pd, int *one_pkt_len) in pd_decode_packet() argument
855 err = osdp_phy_check_packet(pd, pd->rx_buf, pd->rx_buf_len, one_pkt_len); in pd_decode_packet()
857 /* Translate phy error codes to PD errors */ in pd_decode_packet()
873 len = osdp_phy_decode_packet(pd, pd->rx_buf, *one_pkt_len, &buf); in pd_decode_packet()
881 return pd_decode_command(pd, buf, len); in pd_decode_packet()
884 static int pd_receive_and_process_command(struct osdp_pd *pd) in pd_receive_and_process_command() argument
889 buf = pd->rx_buf + pd->rx_buf_len; in pd_receive_and_process_command()
890 remaining = sizeof(pd->rx_buf) - pd->rx_buf_len; in pd_receive_and_process_command()
892 len = pd->channel.recv(pd->channel.data, buf, remaining); in pd_receive_and_process_command()
898 * We received some data on the bus; update pd->tstamp. A rouge CP can in pd_receive_and_process_command()
903 pd->tstamp = osdp_millis_now(); in pd_receive_and_process_command()
904 pd->rx_buf_len += len; in pd_receive_and_process_command()
912 if (pd->rx_buf_len > 8 && in pd_receive_and_process_command()
913 pd->rx_buf[6] != CMD_POLL && pd->rx_buf[8] != CMD_POLL) { in pd_receive_and_process_command()
914 osdp_dump("PD received", pd->rx_buf, pd->rx_buf_len); in pd_receive_and_process_command()
918 err = pd_decode_packet(pd, &len); in pd_receive_and_process_command()
925 remaining = pd->rx_buf_len - len; in pd_receive_and_process_command()
927 memmove(pd->rx_buf, pd->rx_buf + len, remaining); in pd_receive_and_process_command()
934 pd->rx_buf_len = remaining; in pd_receive_and_process_command()
939 static inline void pd_error_reset(struct osdp_pd *pd) in pd_error_reset() argument
941 sc_deactivate(pd); in pd_error_reset()
942 if (pd->channel.flush) { in pd_error_reset()
943 pd->channel.flush(pd->channel.data); in pd_error_reset()
945 pd->rx_buf_len = 0; in pd_error_reset()
951 struct osdp_pd *pd = osdp_to_pd(ctx, 0); in osdp_update() local
958 if (sc_is_active(pd) && in osdp_update()
959 osdp_millis_since(pd->sc_tstamp) > OSDP_PD_SC_TIMEOUT_MS) { in osdp_update()
960 LOG_INF("PD SC session timeout!"); in osdp_update()
961 sc_deactivate(pd); in osdp_update()
965 ret = pd_receive_and_process_command(pd); in osdp_update()
972 if (pd->rx_buf_len == 0 || in osdp_update()
973 osdp_millis_since(pd->tstamp) < OSDP_RESP_TOUT_MS) { in osdp_update()
976 LOG_DBG("rx_buf: %d", pd->rx_buf_len); in osdp_update()
977 osdp_dump("Buf", pd->rx_buf, pd->rx_buf_len); in osdp_update()
982 pd_error_reset(pd); in osdp_update()
987 if (ret == OSDP_PD_ERR_NONE && sc_is_active(pd)) { in osdp_update()
988 pd->sc_tstamp = osdp_millis_now(); in osdp_update()
992 ret = pd_send_reply(pd); in osdp_update()
995 * PD received and decoded a valid command from CP but failed to in osdp_update()
1006 static void osdp_pd_set_attributes(struct osdp_pd *pd, struct osdp_pd_cap *cap, in osdp_pd_set_attributes() argument
1015 pd->cap[fc].function_code = cap->function_code; in osdp_pd_set_attributes()
1016 pd->cap[fc].compliance_level = cap->compliance_level; in osdp_pd_set_attributes()
1017 pd->cap[fc].num_items = cap->num_items; in osdp_pd_set_attributes()
1021 memcpy(&pd->id, id, sizeof(struct osdp_pd_id)); in osdp_pd_set_attributes()
1028 struct osdp_pd *pd; in osdp_setup() local
1033 pd = osdp_to_pd(ctx, 0); in osdp_setup()
1034 osdp_pd_set_attributes(pd, osdp_pd_cap, &osdp_pd_id); in osdp_setup()
1035 SET_FLAG(pd, PD_FLAG_PD_MODE); in osdp_setup()
1038 LOG_WRN("SCBK not provided. PD is in INSTALL_MODE"); in osdp_setup()
1039 SET_FLAG(pd, PD_FLAG_INSTALL_MODE); in osdp_setup()
1041 memcpy(pd->sc.scbk, key, 16); in osdp_setup()
1043 SET_FLAG(pd, PD_FLAG_SC_CAPABLE); in osdp_setup()
1052 struct osdp_pd *pd = osdp_to_pd(osdp_get_ctx(), 0); in osdp_pd_set_command_callback() local
1054 pd->command_callback_arg = arg; in osdp_pd_set_command_callback()
1055 pd->command_callback = cb; in osdp_pd_set_command_callback()
1061 struct osdp_pd *pd = osdp_to_pd(osdp_get_ctx(), 0); in osdp_pd_notify_event() local
1063 ev = pd_event_alloc(pd); in osdp_pd_notify_event()
1069 pd_event_enqueue(pd, ev); in osdp_pd_notify_event()