1 /*
2  * Copyright (c) 2020 Siddharth Chandrasekaran <siddharth@embedjournal.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef _OSDP_COMMON_H_
8 #define _OSDP_COMMON_H_
9 
10 #include <zephyr/mgmt/osdp.h>
11 #include <zephyr/sys/__assert.h>
12 
13 #define OSDP_RESP_TOUT_MS              (200)
14 #define OSDP_ONLINE_RETRY_WAIT_MAX_MS  (300 * 1000)
15 #define OSDP_PACKET_BUF_SIZE           CONFIG_OSDP_UART_BUFFER_LENGTH
16 #define OSDP_PD_SC_TIMEOUT_MS          (800)
17 #define OSDP_ONLINE_RETRY_WAIT_MAX_MS  (300 * 1000)
18 #define OSDP_PD_MAX                    CONFIG_OSDP_NUM_CONNECTED_PD
19 
20 #define OSDP_QUEUE_SLAB_SIZE \
21 	(sizeof(union osdp_ephemeral_data) * CONFIG_OSDP_PD_COMMAND_QUEUE_SIZE)
22 
23 #define ISSET_FLAG(p, f)               (((p)->flags & (f)) == (f))
24 #define SET_FLAG(p, f)                 ((p)->flags |= (f))
25 #define CLEAR_FLAG(p, f)               ((p)->flags &= ~(f))
26 
27 #define BYTE_0(x)                      (uint8_t)(((x) >>  0) & 0xFF)
28 #define BYTE_1(x)                      (uint8_t)(((x) >>  8) & 0xFF)
29 #define BYTE_2(x)                      (uint8_t)(((x) >> 16) & 0xFF)
30 #define BYTE_3(x)                      (uint8_t)(((x) >> 24) & 0xFF)
31 
32 #define GET_CURRENT_PD(p)              ((p)->current_pd)
33 #define SET_CURRENT_PD(p, i)                                    \
34 	do {                                                    \
35 		(p)->current_pd = osdp_to_pd(p, i);             \
36 	} while (0)
37 #define PD_MASK(ctx) \
38 	(uint32_t)((1 << ((ctx)->num_pd)) - 1)
39 #define AES_PAD_LEN(x)                 ((x + 16 - 1) & (~(16 - 1)))
40 #define NUM_PD(ctx)                    ((ctx)->num_pd)
41 
42 /**
43  * @brief OSDP reserved commands
44  */
45 #define CMD_POLL                0x60
46 #define CMD_ID                  0x61
47 #define CMD_CAP                 0x62
48 #define CMD_DIAG                0x63
49 #define CMD_LSTAT               0x64
50 #define CMD_ISTAT               0x65
51 #define CMD_OSTAT               0x66
52 #define CMD_RSTAT               0x67
53 #define CMD_OUT                 0x68
54 #define CMD_LED                 0x69
55 #define CMD_BUZ                 0x6A
56 #define CMD_TEXT                0x6B
57 #define CMD_RMODE               0x6C
58 #define CMD_TDSET               0x6D
59 #define CMD_COMSET              0x6E
60 #define CMD_DATA                0x6F
61 #define CMD_XMIT                0x70
62 #define CMD_PROMPT              0x71
63 #define CMD_SPE                 0x72
64 #define CMD_BIOREAD             0x73
65 #define CMD_BIOMATCH            0x74
66 #define CMD_KEYSET              0x75
67 #define CMD_CHLNG               0x76
68 #define CMD_SCRYPT              0x77
69 #define CMD_CONT                0x79
70 #define CMD_ABORT               0x7A
71 #define CMD_MAXREPLY            0x7B
72 #define CMD_MFG                 0x80
73 #define CMD_SCDONE              0xA0
74 #define CMD_XWR                 0xA1
75 
76 /**
77  * @brief OSDP reserved responses
78  */
79 #define REPLY_ACK               0x40
80 #define REPLY_NAK               0x41
81 #define REPLY_PDID              0x45
82 #define REPLY_PDCAP             0x46
83 #define REPLY_LSTATR            0x48
84 #define REPLY_ISTATR            0x49
85 #define REPLY_OSTATR            0x4A
86 #define REPLY_RSTATR            0x4B
87 #define REPLY_RAW               0x50
88 #define REPLY_FMT               0x51
89 #define REPLY_PRES              0x52
90 #define REPLY_KEYPPAD           0x53
91 #define REPLY_COM               0x54
92 #define REPLY_SCREP             0x55
93 #define REPLY_SPER              0x56
94 #define REPLY_BIOREADR          0x57
95 #define REPLY_BIOMATCHR         0x58
96 #define REPLY_CCRYPT            0x76
97 #define REPLY_RMAC_I            0x78
98 #define REPLY_MFGREP            0x90
99 #define REPLY_BUSY              0x79
100 #define REPLY_XRD               0xB1
101 
102 /**
103  * @brief secure block types
104  */
105 #define SCS_11                  0x11    /* CP -> PD -- CMD_CHLNG */
106 #define SCS_12                  0x12    /* PD -> CP -- REPLY_CCRYPT */
107 #define SCS_13                  0x13    /* CP -> PD -- CMD_SCRYPT */
108 #define SCS_14                  0x14    /* PD -> CP -- REPLY_RMAC_I */
109 
110 #define SCS_15                  0x15    /* CP -> PD -- packets w MAC w/o ENC */
111 #define SCS_16                  0x16    /* PD -> CP -- packets w MAC w/o ENC */
112 #define SCS_17                  0x17    /* CP -> PD -- packets w MAC w ENC*/
113 #define SCS_18                  0x18    /* PD -> CP -- packets w MAC w ENC*/
114 
115 /* PD Flags */
116 #define PD_FLAG_SC_CAPABLE      0x00000001 /* PD secure channel capable */
117 #define PD_FLAG_TAMPER          0x00000002 /* local tamper status */
118 #define PD_FLAG_POWER           0x00000004 /* local power status */
119 #define PD_FLAG_R_TAMPER        0x00000008 /* remote tamper status */
120 #define PD_FLAG_AWAIT_RESP      0x00000020 /* set after command is sent */
121 #define PD_FLAG_SKIP_SEQ_CHECK  0x00000040 /* disable seq checks (debug) */
122 #define PD_FLAG_SC_USE_SCBKD    0x00000080 /* in this SC attempt, use SCBKD */
123 #define PD_FLAG_SC_ACTIVE       0x00000100 /* secure channel is active */
124 #define PD_FLAG_SC_SCBKD_DONE   0x00000200 /* SCBKD check is done */
125 #define PD_FLAG_PKT_HAS_MARK    0x00000400 /* Packet has mark byte */
126 #define PD_FLAG_PKT_SKIP_MARK   0x00000800 /* CONFIG_OSDP_SKIP_MARK_BYTE */
127 #define PD_FLAG_HAS_SCBK        0x00001000 /* PD has a dedicated SCBK */
128 #define PD_FLAG_INSTALL_MODE    0x40000000 /* PD is in install mode */
129 #define PD_FLAG_PD_MODE         0x80000000 /* device is setup as PD */
130 
131 enum osdp_pd_nak_code_e {
132 	/**
133 	 * @brief Dummy
134 	 */
135 	OSDP_PD_NAK_NONE,
136 	/**
137 	 * @brief Message check character(s) error (bad cksum/crc)
138 	 */
139 	OSDP_PD_NAK_MSG_CHK,
140 	/**
141 	 * @brief Command length error
142 	 */
143 	OSDP_PD_NAK_CMD_LEN,
144 	/**
145 	 * @brief Unknown Command Code – Command not implemented by PD
146 	 */
147 	OSDP_PD_NAK_CMD_UNKNOWN,
148 	/**
149 	 * @brief Unexpected sequence number detected in the header
150 	 */
151 	OSDP_PD_NAK_SEQ_NUM,
152 	/**
153 	 * @brief Unexpected sequence number detected in the header
154 	 */
155 	OSDP_PD_NAK_SC_UNSUP,
156 	/**
157 	 * @brief unsupported security block or security conditions not met
158 	 */
159 	OSDP_PD_NAK_SC_COND,
160 	/**
161 	 * @brief BIO_TYPE not supported
162 	 */
163 	OSDP_PD_NAK_BIO_TYPE,
164 	/**
165 	 * @brief BIO_FORMAT not supported
166 	 */
167 	OSDP_PD_NAK_BIO_FMT,
168 	/**
169 	 * @brief Unable to process command record
170 	 */
171 	OSDP_PD_NAK_RECORD,
172 	/**
173 	 * @brief Dummy
174 	 */
175 	OSDP_PD_NAK_SENTINEL
176 };
177 
178 enum osdp_pd_state_e {
179 	OSDP_PD_STATE_IDLE,
180 	OSDP_PD_STATE_SEND_REPLY,
181 	OSDP_PD_STATE_ERR,
182 };
183 
184 enum osdp_cp_phy_state_e {
185 	OSDP_CP_PHY_STATE_IDLE,
186 	OSDP_CP_PHY_STATE_SEND_CMD,
187 	OSDP_CP_PHY_STATE_REPLY_WAIT,
188 	OSDP_CP_PHY_STATE_WAIT,
189 	OSDP_CP_PHY_STATE_ERR,
190 };
191 
192 enum osdp_cp_state_e {
193 	OSDP_CP_STATE_INIT,
194 	OSDP_CP_STATE_IDREQ,
195 	OSDP_CP_STATE_CAPDET,
196 	OSDP_CP_STATE_SC_INIT,
197 	OSDP_CP_STATE_SC_CHLNG,
198 	OSDP_CP_STATE_SC_SCRYPT,
199 	OSDP_CP_STATE_SET_SCBK,
200 	OSDP_CP_STATE_ONLINE,
201 	OSDP_CP_STATE_OFFLINE
202 };
203 
204 enum osdp_pkt_errors_e {
205 	OSDP_ERR_PKT_NONE = 0,
206 	/**
207 	 * Fatal packet formatting issues. The phy layer was unable to find a
208 	 * valid OSDP packet or the length of the packet was too long/incorrect.
209 	 */
210 	OSDP_ERR_PKT_FMT = -1,
211 	/**
212 	 * Not enough data in buffer; wait for more data (or timeout).
213 	 */
214 	OSDP_ERR_PKT_WAIT = -2,
215 	/**
216 	 * Message to/from an foreign device that can be safely ignored
217 	 * without altering the state of this PD.
218 	 */
219 	OSDP_ERR_PKT_SKIP = -3,
220 	/**
221 	 * Packet was valid but does not match some conditions. ie., only this
222 	 * packet is faulty, rest of the buffer may still be intact.
223 	 */
224 	OSDP_ERR_PKT_CHECK = -4,
225 	/**
226 	 * Discovered a busy packet. In CP mode, it should retry this command
227 	 * after some time.
228 	 */
229 	OSDP_ERR_PKT_BUSY = -5,
230 	/**
231 	 * Phy layer found a reason to send NACK to the CP that produced
232 	 * this packet; pd->reply_id is set REPLY_NAK and the reason code is
233 	 * also filled.
234 	 */
235 	OSDP_ERR_PKT_NACK = -6,
236 };
237 
238 /**
239  * @brief Various PD capability function codes.
240  */
241 enum osdp_pd_cap_function_code_e {
242 	/**
243 	 * @brief Dummy.
244 	 */
245 	OSDP_PD_CAP_UNUSED,
246 
247 	/**
248 	 * @brief This function indicates the ability to monitor the status of a
249 	 * switch using a two-wire electrical connection between the PD and the
250 	 * switch. The on/off position of the switch indicates the state of an
251 	 * external device.
252 	 *
253 	 * The PD may simply resolve all circuit states to an open/closed
254 	 * status, or it may implement supervision of the monitoring circuit.
255 	 * A supervised circuit is able to indicate circuit fault status in
256 	 * addition to open/closed status.
257 	 */
258 	OSDP_PD_CAP_CONTACT_STATUS_MONITORING,
259 
260 	/**
261 	 * @brief This function provides a switched output, typically in the
262 	 * form of a relay. The Output has two states: active or inactive. The
263 	 * Control Panel (CP) can directly set the Output's state, or, if the PD
264 	 * supports timed operations, the CP can specify a time period for the
265 	 * activation of the Output.
266 	 */
267 	OSDP_PD_CAP_OUTPUT_CONTROL,
268 
269 	/**
270 	 * @brief This capability indicates the form of the card data is
271 	 * presented to the Control Panel.
272 	 */
273 	OSDP_PD_CAP_CARD_DATA_FORMAT,
274 
275 	/**
276 	 * @brief This capability indicates the presence of and type of LEDs.
277 	 */
278 	OSDP_PD_CAP_READER_LED_CONTROL,
279 
280 	/**
281 	 * @brief This capability indicates the presence of and type of an
282 	 * Audible Annunciator (buzzer or similar tone generator)
283 	 */
284 	OSDP_PD_CAP_READER_AUDIBLE_OUTPUT,
285 
286 	/**
287 	 * @brief This capability indicates that the PD supports a text display
288 	 * emulating character-based display terminals.
289 	 */
290 	OSDP_PD_CAP_READER_TEXT_OUTPUT,
291 
292 	/**
293 	 * @brief This capability indicates that the type of date and time
294 	 * awareness or time keeping ability of the PD.
295 	 */
296 	OSDP_PD_CAP_TIME_KEEPING,
297 
298 	/**
299 	 * @brief All PDs must be able to support the checksum mode. This
300 	 * capability indicates if the PD is capable of supporting CRC mode.
301 	 */
302 	OSDP_PD_CAP_CHECK_CHARACTER_SUPPORT,
303 
304 	/**
305 	 * @brief This capability indicates the extent to which the PD supports
306 	 * communication security (Secure Channel Communication)
307 	 */
308 	OSDP_PD_CAP_COMMUNICATION_SECURITY,
309 
310 	/**
311 	 * @brief This capability indicates the maximum size single message the
312 	 * PD can receive.
313 	 */
314 	OSDP_PD_CAP_RECEIVE_BUFFERSIZE,
315 
316 	/**
317 	 * @brief This capability indicates the maximum size multi-part message
318 	 * which the PD can handle.
319 	 */
320 	OSDP_PD_CAP_LARGEST_COMBINED_MESSAGE_SIZE,
321 
322 	/**
323 	 * @brief This capability indicates whether the PD supports the
324 	 * transparent mode used for communicating directly with a smart card.
325 	 */
326 	OSDP_PD_CAP_SMART_CARD_SUPPORT,
327 
328 	/**
329 	 * @brief This capability indicates the number of credential reader
330 	 * devices present. Compliance levels are bit fields to be assigned as
331 	 * needed.
332 	 */
333 	OSDP_PD_CAP_READERS,
334 
335 	/**
336 	 * @brief This capability indicates the ability of the reader to handle
337 	 * biometric input
338 	 */
339 	OSDP_PD_CAP_BIOMETRICS,
340 
341 	/**
342 	 * @brief Capability Sentinel
343 	 */
344 	OSDP_PD_CAP_SENTINEL
345 };
346 
347 /* Unused type only to estimate ephemeral_data size */
348 union osdp_ephemeral_data {
349 	struct osdp_cmd cmd;
350 	struct osdp_event event;
351 };
352 #define OSDP_EPHEMERAL_DATA_MAX_LEN sizeof(union osdp_ephemeral_data)
353 
354 /**
355  * @brief PD capability structure. Each PD capability has a 3 byte
356  * representation.
357  *
358  * @param function_code One of enum osdp_pd_cap_function_code_e.
359  * @param compliance_level A function_code dependent number that indicates what
360  *                         the PD can do with this capability.
361  * @param num_items Number of such capability entities in PD.
362  */
363 struct osdp_pd_cap {
364 	uint8_t function_code;
365 	uint8_t compliance_level;
366 	uint8_t num_items;
367 };
368 
369 /**
370  * @brief PD ID information advertised by the PD.
371  *
372  * @param version 3-bytes IEEE assigned OUI
373  * @param model 1-byte Manufacturer's model number
374  * @param vendor_code 1-Byte Manufacturer's version number
375  * @param serial_number 4-byte serial number for the PD
376  * @param firmware_version 3-byte version (major, minor, build)
377  */
378 struct osdp_pd_id {
379 	int version;
380 	int model;
381 	uint32_t vendor_code;
382 	uint32_t serial_number;
383 	uint32_t firmware_version;
384 };
385 
386 struct osdp_channel {
387 	/**
388 	 * @brief pointer to a block of memory that will be passed to the
389 	 * send/receive method. This is optional and can be left empty.
390 	 */
391 	void *data;
392 
393 	/**
394 	 * @brief pointer to function that copies received bytes into buffer
395 	 * @param data for use by underlying layers. channel_s::data is passed
396 	 * @param buf byte array copy incoming data
397 	 * @param len sizeof `buf`. Can copy utmost `len` bytes into `buf`
398 	 *
399 	 * @retval +ve: number of bytes copied on to `bug`. Must be <= `len`
400 	 * @retval -ve on errors
401 	 */
402 	int (*recv)(void *data, uint8_t *buf, int maxlen);
403 
404 	/**
405 	 * @brief pointer to function that sends byte array into some channel
406 	 * @param data for use by underlying layers. channel_s::data is passed
407 	 * @param buf byte array to be sent
408 	 * @param len number of bytes in `buf`
409 	 *
410 	 * @retval +ve: number of bytes sent. must be <= `len`
411 	 * @retval -ve on errors
412 	 */
413 	int (*send)(void *data, uint8_t *buf, int len);
414 
415 	/**
416 	 * @brief pointer to function that drops all bytes in TX/RX fifo
417 	 * @param data for use by underlying layers. channel_s::data is passed
418 	 */
419 	void (*flush)(void *data);
420 };
421 
422 struct osdp_queue {
423 	sys_slist_t queue;
424 	struct k_mem_slab slab;
425 	uint8_t slab_buf[OSDP_QUEUE_SLAB_SIZE];
426 };
427 
428 #ifdef CONFIG_OSDP_SC_ENABLED
429 struct osdp_secure_channel {
430 	uint8_t scbk[16];
431 	uint8_t s_enc[16];
432 	uint8_t s_mac1[16];
433 	uint8_t s_mac2[16];
434 	uint8_t r_mac[16];
435 	uint8_t c_mac[16];
436 	uint8_t cp_random[8];
437 	uint8_t pd_random[8];
438 	uint8_t pd_client_uid[8];
439 	uint8_t cp_cryptogram[16];
440 	uint8_t pd_cryptogram[16];
441 };
442 #endif
443 
444 struct osdp_pd {
445 	void *osdp_ctx;
446 	int idx;
447 	uint32_t flags;
448 
449 	/* OSDP specified data */
450 	int baud_rate;
451 	int address;
452 	int seq_number;
453 	struct osdp_pd_cap cap[OSDP_PD_CAP_SENTINEL];
454 	struct osdp_pd_id id;
455 
456 	/* PD state management */
457 #ifdef CONFIG_OSDP_MODE_PD
458 	enum osdp_pd_state_e state;
459 #else
460 	enum osdp_cp_state_e state;
461 	enum osdp_cp_phy_state_e phy_state;
462 	uint32_t wait_ms;
463 	int64_t phy_tstamp;
464 #endif
465 	int64_t tstamp;
466 	uint8_t rx_buf[OSDP_PACKET_BUF_SIZE];
467 	int rx_buf_len;
468 
469 	int cmd_id;
470 	int reply_id;
471 	uint8_t ephemeral_data[OSDP_EPHEMERAL_DATA_MAX_LEN];
472 
473 	struct osdp_channel channel;
474 
475 	union {
476 		struct osdp_queue cmd;    /* Command queue (CP Mode only) */
477 		struct osdp_queue event;  /* Command queue (PD Mode only) */
478 	};
479 
480 	/* PD command callback to app with opaque arg pointer as passed by app */
481 	void *command_callback_arg;
482 	pd_command_callback_t command_callback;
483 
484 #ifdef CONFIG_OSDP_SC_ENABLED
485 	int64_t sc_tstamp;
486 	struct osdp_secure_channel sc;
487 #endif
488 };
489 
490 struct osdp {
491 	int magic;
492 	uint32_t flags;
493 	int num_pd;
494 	struct osdp_pd *current_pd;	/* current operational pd's pointer */
495 	struct osdp_pd *pd;
496 #ifdef CONFIG_OSDP_SC_ENABLED
497 	uint8_t sc_master_key[16];
498 #endif
499 	/* CP event callback to app with opaque arg pointer as passed by app */
500 	void *event_callback_arg;
501 	cp_event_callback_t event_callback;
502 };
503 
504 #ifdef CONFIG_OSDP_MODE_PD
cp_keyset_complete(struct osdp_pd * pd)505 static inline void cp_keyset_complete(struct osdp_pd *pd) { }
506 #else
507 void cp_keyset_complete(struct osdp_pd *pd);
508 #endif
509 
510 void osdp_keyset_complete(struct osdp_pd *pd);
511 
512 /* from osdp_phy.c */
513 int osdp_phy_packet_init(struct osdp_pd *p, uint8_t *buf, int max_len);
514 int osdp_phy_packet_finalize(struct osdp_pd *p, uint8_t *buf,
515 			     int len, int max_len);
516 int osdp_phy_check_packet(struct osdp_pd *pd, uint8_t *buf, int len,
517 			  int *one_pkt_len);
518 int osdp_phy_decode_packet(struct osdp_pd *p, uint8_t *buf, int len,
519 			   uint8_t **pkt_start);
520 void osdp_phy_state_reset(struct osdp_pd *pd);
521 int osdp_phy_packet_get_data_offset(struct osdp_pd *p, const uint8_t *buf);
522 uint8_t *osdp_phy_packet_get_smb(struct osdp_pd *p, const uint8_t *buf);
523 
524 /* from osdp_common.c */
525 int64_t osdp_millis_now(void);
526 int64_t osdp_millis_since(int64_t last);
527 void osdp_dump(const char *head, uint8_t *buf, int len);
528 uint16_t osdp_compute_crc16(const uint8_t *buf, size_t len);
529 
530 /* from osdp.c */
531 struct osdp *osdp_get_ctx();
532 
533 /* from osdp_cp.c */
534 #ifdef CONFIG_OSDP_MODE_CP
535 int osdp_extract_address(int *address);
536 #endif
537 
538 #ifdef CONFIG_OSDP_SC_ENABLED
539 void osdp_encrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len);
540 void osdp_decrypt(uint8_t *key, uint8_t *iv, uint8_t *data, int len);
541 #endif
542 
543 /* from osdp_sc.c */
544 void osdp_compute_scbk(struct osdp_pd *pd, uint8_t *master_key, uint8_t *scbk);
545 void osdp_compute_session_keys(struct osdp_pd *pd);
546 void osdp_compute_cp_cryptogram(struct osdp_pd *pd);
547 int osdp_verify_cp_cryptogram(struct osdp_pd *pd);
548 void osdp_compute_pd_cryptogram(struct osdp_pd *pd);
549 int osdp_verify_pd_cryptogram(struct osdp_pd *pd);
550 void osdp_compute_rmac_i(struct osdp_pd *pd);
551 int osdp_decrypt_data(struct osdp_pd *pd, int is_cmd, uint8_t *data, int len);
552 int osdp_encrypt_data(struct osdp_pd *pd, int is_cmd, uint8_t *data, int len);
553 int osdp_compute_mac(struct osdp_pd *pd, int is_cmd,
554 		     const uint8_t *data, int len);
555 void osdp_sc_setup(struct osdp_pd *pd);
556 void osdp_fill_random(uint8_t *buf, int len);
557 
558 /* must be implemented by CP or PD */
559 int osdp_setup(struct osdp *ctx, uint8_t *key);
560 void osdp_update(struct osdp *ctx);
561 
pd_to_osdp(struct osdp_pd * pd)562 static inline struct osdp *pd_to_osdp(struct osdp_pd *pd)
563 {
564 	return pd->osdp_ctx;
565 }
566 
osdp_to_pd(struct osdp * ctx,int pd_idx)567 static inline struct osdp_pd *osdp_to_pd(struct osdp *ctx, int pd_idx)
568 {
569 	return ctx->pd + pd_idx;
570 }
571 
is_pd_mode(struct osdp_pd * pd)572 static inline bool is_pd_mode(struct  osdp_pd *pd)
573 {
574 	return ISSET_FLAG(pd, PD_FLAG_PD_MODE);
575 }
576 
is_cp_mode(struct osdp_pd * pd)577 static inline bool is_cp_mode(struct  osdp_pd *pd)
578 {
579 	return !ISSET_FLAG(pd, PD_FLAG_PD_MODE);
580 }
581 
sc_is_capable(struct osdp_pd * pd)582 static inline bool sc_is_capable(struct osdp_pd *pd)
583 {
584 	return ISSET_FLAG(pd, PD_FLAG_SC_CAPABLE);
585 }
586 
sc_is_active(struct osdp_pd * pd)587 static inline bool sc_is_active(struct osdp_pd *pd)
588 {
589 	return ISSET_FLAG(pd, PD_FLAG_SC_ACTIVE);
590 }
591 
sc_activate(struct osdp_pd * pd)592 static inline void sc_activate(struct osdp_pd *pd)
593 {
594 	SET_FLAG(pd, PD_FLAG_SC_ACTIVE);
595 }
596 
sc_deactivate(struct osdp_pd * pd)597 static inline void sc_deactivate(struct osdp_pd *pd)
598 {
599 	CLEAR_FLAG(pd, PD_FLAG_SC_ACTIVE);
600 }
601 
602 #endif	/* _OSDP_COMMON_H_ */
603