1 /*
2 * Copyright (c) 2020 Siddharth Chandrasekaran <siddharth@embedjournal.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/init.h>
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/uart.h>
11 #include <zephyr/sys/ring_buffer.h>
12 #include <zephyr/logging/log.h>
13
14 #include "osdp_common.h"
15
16 LOG_MODULE_REGISTER(osdp, CONFIG_OSDP_LOG_LEVEL);
17
18 #ifdef CONFIG_OSDP_SC_ENABLED
19 #ifdef CONFIG_OSDP_MODE_PD
20 #define OSDP_KEY_STRING CONFIG_OSDP_PD_SCBK
21 #else
22 #define OSDP_KEY_STRING CONFIG_OSDP_MASTER_KEY
23 #endif
24 #else
25 #define OSDP_KEY_STRING ""
26 #endif /* CONFIG_OSDP_SC_ENABLED */
27
28 struct osdp_device {
29 struct ring_buf rx_buf;
30 struct ring_buf tx_buf;
31 #ifdef CONFIG_OSDP_MODE_PD
32 int rx_event_data;
33 struct k_fifo rx_event_fifo;
34 #endif
35 uint8_t rx_fbuf[OSDP_PACKET_BUF_SIZE];
36 uint8_t tx_fbuf[OSDP_PACKET_BUF_SIZE];
37 struct uart_config dev_config;
38 const struct device *dev;
39 int wait_for_mark;
40 uint8_t last_byte;
41 };
42
43 static struct osdp osdp_ctx;
44 static struct osdp_pd osdp_pd_ctx[CONFIG_OSDP_NUM_CONNECTED_PD];
45 static struct osdp_device osdp_device;
46 static struct k_thread osdp_refresh_thread;
47 static K_THREAD_STACK_DEFINE(osdp_thread_stack, CONFIG_OSDP_THREAD_STACK_SIZE);
48
osdp_handle_in_byte(struct osdp_device * p,uint8_t * buf,int len)49 static void osdp_handle_in_byte(struct osdp_device *p, uint8_t *buf, int len)
50 {
51 if (p->wait_for_mark) {
52 /* Check for new packet beginning with [FF,53,...] sequence */
53 if (p->last_byte == 0xFF && buf[0] == 0x53) {
54 buf[0] = 0xFF;
55 ring_buf_put(&p->rx_buf, buf, 1); /* put last byte */
56 buf[0] = 0x53;
57 ring_buf_put(&p->rx_buf, buf, len); /* put rest */
58 p->wait_for_mark = 0; /* Mark found. Clear flag */
59 }
60 p->last_byte = buf[0];
61 return;
62 }
63 ring_buf_put(&p->rx_buf, buf, len);
64 }
65
osdp_uart_isr(const struct device * dev,void * user_data)66 static void osdp_uart_isr(const struct device *dev, void *user_data)
67 {
68 size_t len;
69 uint8_t buf[64];
70 struct osdp_device *p = user_data;
71
72 while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
73
74 if (uart_irq_rx_ready(dev)) {
75 len = uart_fifo_read(dev, buf, sizeof(buf));
76 if (len > 0) {
77 osdp_handle_in_byte(p, buf, len);
78 }
79 }
80
81 if (uart_irq_tx_ready(dev)) {
82 len = ring_buf_get(&p->tx_buf, buf, 1);
83 if (!len) {
84 uart_irq_tx_disable(dev);
85 } else {
86 uart_fifo_fill(dev, buf, 1);
87 }
88 }
89 }
90 #ifdef CONFIG_OSDP_MODE_PD
91 if (p->wait_for_mark == 0) {
92 /* wake osdp_refresh thread */
93 k_fifo_put(&p->rx_event_fifo, &p->rx_event_data);
94 }
95 #endif
96 }
97
osdp_uart_receive(void * data,uint8_t * buf,int len)98 static int osdp_uart_receive(void *data, uint8_t *buf, int len)
99 {
100 struct osdp_device *p = data;
101
102 return (int)ring_buf_get(&p->rx_buf, buf, len);
103 }
104
osdp_uart_send(void * data,uint8_t * buf,int len)105 static int osdp_uart_send(void *data, uint8_t *buf, int len)
106 {
107 int sent = 0;
108 struct osdp_device *p = data;
109
110 sent = (int)ring_buf_put(&p->tx_buf, buf, len);
111 uart_irq_tx_enable(p->dev);
112 return sent;
113 }
114
osdp_uart_flush(void * data)115 static void osdp_uart_flush(void *data)
116 {
117 struct osdp_device *p = data;
118
119 p->wait_for_mark = 1;
120 ring_buf_reset(&p->tx_buf);
121 ring_buf_reset(&p->rx_buf);
122 }
123
osdp_get_ctx()124 struct osdp *osdp_get_ctx()
125 {
126 return &osdp_ctx;
127 }
128
osdp_build_ctx(struct osdp_channel * channel)129 static struct osdp *osdp_build_ctx(struct osdp_channel *channel)
130 {
131 int i;
132 struct osdp *ctx;
133 struct osdp_pd *pd;
134 int pd_adddres[CONFIG_OSDP_NUM_CONNECTED_PD] = {0};
135
136 #ifdef CONFIG_OSDP_MODE_PD
137 pd_adddres[0] = CONFIG_OSDP_PD_ADDRESS;
138 #else
139 if (osdp_extract_address(pd_adddres)) {
140 return NULL;
141 }
142 #endif
143 ctx = &osdp_ctx;
144 ctx->num_pd = CONFIG_OSDP_NUM_CONNECTED_PD;
145 ctx->pd = &osdp_pd_ctx[0];
146 SET_CURRENT_PD(ctx, 0);
147
148 for (i = 0; i < CONFIG_OSDP_NUM_CONNECTED_PD; i++) {
149 pd = osdp_to_pd(ctx, i);
150 pd->idx = i;
151 pd->seq_number = -1;
152 pd->osdp_ctx = ctx;
153 pd->address = pd_adddres[i];
154 pd->baud_rate = CONFIG_OSDP_UART_BAUD_RATE;
155 if (IS_ENABLED(CONFIG_OSDP_SKIP_MARK_BYTE)) {
156 SET_FLAG(pd, PD_FLAG_PKT_SKIP_MARK);
157 }
158 memcpy(&pd->channel, channel, sizeof(struct osdp_channel));
159 k_mem_slab_init(&pd->cmd.slab, pd->cmd.slab_buf, sizeof(union osdp_ephemeral_data),
160 CONFIG_OSDP_PD_COMMAND_QUEUE_SIZE);
161 }
162 return ctx;
163 }
164
osdp_refresh(void * arg1,void * arg2,void * arg3)165 void osdp_refresh(void *arg1, void *arg2, void *arg3)
166 {
167 struct osdp *ctx = osdp_get_ctx();
168
169 while (1) {
170 #ifdef CONFIG_OSDP_MODE_PD
171 k_fifo_get(&osdp_device.rx_event_fifo, K_FOREVER);
172 #else
173 k_msleep(50);
174 #endif
175 osdp_update(ctx);
176 }
177 }
178
osdp_init(void)179 static int osdp_init(void)
180 {
181 int len;
182 uint8_t c, *key = NULL, key_buf[16];
183 struct osdp *ctx;
184 struct osdp_device *p = &osdp_device;
185 struct osdp_channel channel = {
186 .send = osdp_uart_send,
187 .recv = osdp_uart_receive,
188 .flush = osdp_uart_flush,
189 .data = &osdp_device,
190 };
191
192 #ifdef CONFIG_OSDP_MODE_PD
193 k_fifo_init(&p->rx_event_fifo);
194 #endif
195
196 ring_buf_init(&p->rx_buf, sizeof(p->rx_fbuf), p->rx_fbuf);
197 ring_buf_init(&p->tx_buf, sizeof(p->tx_fbuf), p->tx_fbuf);
198
199 /* init OSDP uart device */
200 p->dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_osdp_uart));
201 if (!device_is_ready(p->dev)) {
202 LOG_ERR("UART dev is not ready");
203 k_panic();
204 }
205
206 /* configure uart device to 8N1 */
207 p->dev_config.baudrate = CONFIG_OSDP_UART_BAUD_RATE;
208 p->dev_config.data_bits = UART_CFG_DATA_BITS_8;
209 p->dev_config.parity = UART_CFG_PARITY_NONE;
210 p->dev_config.stop_bits = UART_CFG_STOP_BITS_1;
211 p->dev_config.flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
212 uart_configure(p->dev, &p->dev_config);
213
214 uart_irq_rx_disable(p->dev);
215 uart_irq_tx_disable(p->dev);
216 uart_irq_callback_user_data_set(p->dev, osdp_uart_isr, p);
217
218 /* Drain UART fifo and set channel to wait for mark byte */
219 while (uart_irq_rx_ready(p->dev)) {
220 uart_fifo_read(p->dev, &c, 1);
221 }
222 p->wait_for_mark = 1;
223
224 /* Both TX and RX are interrupt driven */
225 uart_irq_rx_enable(p->dev);
226
227 /* setup OSDP */
228 ctx = osdp_build_ctx(&channel);
229 if (ctx == NULL) {
230 LOG_ERR("OSDP build ctx failed!");
231 k_panic();
232 }
233
234 if (IS_ENABLED(CONFIG_OSDP_SC_ENABLED)) {
235 if (strcmp(OSDP_KEY_STRING, "NONE") != 0) {
236 len = strlen(OSDP_KEY_STRING);
237 if (len != 32) {
238 LOG_ERR("Key string length must be 32");
239 k_panic();
240 }
241 len = hex2bin(OSDP_KEY_STRING, 32, key_buf, 16);
242 if (len != 16) {
243 LOG_ERR("Failed to parse key buffer");
244 k_panic();
245 }
246 key = key_buf;
247 }
248 }
249
250 if (osdp_setup(ctx, key)) {
251 LOG_ERR("Failed to setup OSDP device!");
252 k_panic();
253 }
254
255 LOG_INF("OSDP init okay!");
256
257 /* kick off refresh thread */
258 k_thread_create(&osdp_refresh_thread, osdp_thread_stack,
259 CONFIG_OSDP_THREAD_STACK_SIZE, osdp_refresh,
260 NULL, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT);
261 return 0;
262 }
263
264 SYS_INIT(osdp_init, POST_KERNEL, 10);
265