33
33
*/
34
34
35
35
#include <stdio.h>
36
+ #include <stdbool.h>
36
37
37
38
#include "ioc.h"
38
39
@@ -44,6 +45,8 @@ static int ioc_cbc_debug;
44
45
do { if (ioc_cbc_debug) printf(fmt, ##args); } while (0)
45
46
#define WPRINTF (fmt , args ...) printf(fmt, ##args)
46
47
48
+ static void cbc_send_pkt (struct cbc_pkt * pkt );
49
+
47
50
/*
48
51
* Buffer bytes of reading from the virtual UART, because the bytes maybe can
49
52
* not generate one complete CBC frame.
@@ -235,6 +238,197 @@ cbc_unpack_link(struct ioc_dev *ioc)
235
238
}
236
239
}
237
240
241
+ /*
242
+ * Find a CBC signal from CBC signal table.
243
+ */
244
+ static inline struct cbc_signal *
245
+ cbc_find_signal (uint16_t id , struct cbc_signal * table , size_t size )
246
+ {
247
+ int i ;
248
+
249
+ for (i = 0 ; i < size ; i ++ ) {
250
+ if (id == table [i ].id )
251
+ return & table [i ];
252
+ }
253
+ return NULL ;
254
+ }
255
+
256
+ /*
257
+ * Find a CBC signal group from CBC signal group table.
258
+ */
259
+ static inline struct cbc_group *
260
+ cbc_find_signal_group (uint16_t id , struct cbc_group * table , size_t size )
261
+ {
262
+ int i ;
263
+
264
+ for (i = 0 ; i < size ; i ++ ) {
265
+ if (id == table [i ].id )
266
+ return & table [i ];
267
+ }
268
+ return NULL ;
269
+ }
270
+
271
+ /*
272
+ * Signal length unit is bit in signal definition not byte,
273
+ * if the length is 3 bits then return 1 byte,
274
+ * if the length is 10 bits then return 2 bytes.
275
+ */
276
+ static int
277
+ cbc_get_signal_len (uint16_t id , struct cbc_signal * table , size_t size )
278
+ {
279
+ struct cbc_signal * p ;
280
+
281
+ p = cbc_find_signal (id , table , size );
282
+ return (p == NULL ? 0 : (p -> len + 7 )/8 );
283
+ }
284
+
285
+ /*
286
+ * Set signal flag to inactive.
287
+ */
288
+ static void
289
+ cbc_disable_signal (uint16_t id , struct cbc_signal * table , size_t size )
290
+ {
291
+ struct cbc_signal * p ;
292
+
293
+ p = cbc_find_signal (id , table , size );
294
+ if (p )
295
+ p -> flag = CBC_INACTIVE ;
296
+ }
297
+
298
+ /*
299
+ * Set signal group flag to inactive.
300
+ */
301
+ static void
302
+ cbc_disable_signal_group (uint16_t id , struct cbc_group * table , size_t size )
303
+ {
304
+ struct cbc_group * p ;
305
+
306
+ p = cbc_find_signal_group (id , table , size );
307
+ if (p )
308
+ p -> flag = CBC_INACTIVE ;
309
+ }
310
+
311
+ /*
312
+ * Whitelist verification for a signal.
313
+ */
314
+ static int
315
+ wlist_verify_signal (uint16_t id , struct wlist_signal * list , size_t size )
316
+ {
317
+ /* TODO: implementation */
318
+ return 0 ;
319
+ }
320
+
321
+ /*
322
+ * Whiltelist verification for a signal group.
323
+ */
324
+ static int
325
+ wlist_verify_group (uint16_t id , struct wlist_group * list , size_t size )
326
+ {
327
+ /* TODO: implementation */
328
+ return 0 ;
329
+ }
330
+
331
+ /*
332
+ * CBC invalidates signals/groups.
333
+ */
334
+ static void
335
+ cbc_set_invalidation (struct cbc_pkt * pkt , int type )
336
+ {
337
+ int i ;
338
+ uint8_t * payload ;
339
+ uint8_t num ;
340
+ uint16_t id ;
341
+
342
+ payload = pkt -> req -> buf + CBC_PAYLOAD_POS ;
343
+
344
+ /* Number of signals or groups */
345
+ num = payload [1 ];
346
+
347
+ /*
348
+ * Safty check.
349
+ * Each signal/group id length is 2 bytes and 2 bytes of service header,
350
+ * the service length should less than the maximum service size.
351
+ */
352
+ if ((num * 2 + 2 ) >= CBC_MAX_SERVICE_SIZE ) {
353
+ DPRINTF ("ioc cbc group number is invalid, number is %d\r\n" ,
354
+ num );
355
+ return ;
356
+ }
357
+ for (i = 0 ; i < num ; i ++ ) {
358
+ id = payload [i * 2 + 2 ] | payload [i * 2 + 3 ] << 8 ;
359
+ if (type == CBC_INVAL_T_SIGNAL )
360
+ cbc_disable_signal (id , pkt -> cfg -> cbc_sig_tbl ,
361
+ pkt -> cfg -> cbc_sig_num );
362
+ else if (type == CBC_INVAL_T_GROUP )
363
+ cbc_disable_signal_group (id , pkt -> cfg -> cbc_grp_tbl ,
364
+ pkt -> cfg -> cbc_grp_num );
365
+ else
366
+ DPRINTF ("%s" , "ioc invalidation is not defined\r\n" );
367
+ }
368
+ }
369
+
370
+ /*
371
+ * CBC multi-signal data process.
372
+ * Forwarding signal should be in whitelist, otherwise abandon the signal.
373
+ */
374
+ static void
375
+ cbc_forward_signals (struct cbc_pkt * pkt )
376
+ {
377
+ int i , j ;
378
+ int offset = 1 ;
379
+ uint8_t * payload = pkt -> req -> buf + CBC_PAYLOAD_POS ;
380
+ uint8_t num = 0 ;
381
+ uint16_t id ;
382
+ int signal_len ;
383
+ int valids = 1 ;
384
+
385
+ for (i = 0 ; i < payload [0 ]; i ++ ) {
386
+ id = payload [offset ] | payload [offset + 1 ] << 8 ;
387
+
388
+ /* The length includes two bytes of signal ID occupation */
389
+ signal_len = cbc_get_signal_len (id , pkt -> cfg -> cbc_sig_tbl ,
390
+ pkt -> cfg -> cbc_sig_num ) + 2 ;
391
+
392
+ /* Whitelist verification */
393
+ if (wlist_verify_signal (id , pkt -> cfg -> wlist_sig_tbl ,
394
+ pkt -> cfg -> wlist_sig_num ) == 0 ) {
395
+
396
+ num ++ ;
397
+ if (valids < offset ) {
398
+ for (j = 0 ; j < signal_len ; j ++ , valids ++ )
399
+ payload [valids ] = payload [offset + j ];
400
+ } else
401
+ valids += signal_len ;
402
+ }
403
+ offset += signal_len ;
404
+
405
+ /* Safty check */
406
+ if (offset + 1 > CBC_MAX_SERVICE_SIZE ) {
407
+ DPRINTF ("ioc offset=%d is error in forward signal\r\n" ,
408
+ offset );
409
+ return ;
410
+ }
411
+ }
412
+
413
+ /* Send permitted signals */
414
+ if (num > 0 ) {
415
+ /*
416
+ * Set permitted signal numbers
417
+ */
418
+ payload [0 ] = num ;
419
+
420
+ /*
421
+ * Set multi-signal value for CBC service layer header,
422
+ * one service frame is generated completely.
423
+ */
424
+ pkt -> req -> buf [CBC_SRV_POS ] = CBC_SD_MULTI_SIGNAL ;
425
+ pkt -> req -> srv_len = valids + CBC_SRV_HDR_SIZE ;
426
+
427
+ /* Send the CBC packet */
428
+ cbc_send_pkt (pkt );
429
+ }
430
+ }
431
+
238
432
/*
239
433
* Pack CBC link header includes SOF value, extension bits, frame length bits,
240
434
* tx sequence bits, link alignment paddings and checksum byte.
@@ -457,6 +651,87 @@ cbc_process_lifecycle(struct cbc_pkt *pkt)
457
651
static void
458
652
cbc_process_signal (struct cbc_pkt * pkt )
459
653
{
654
+ /*
655
+ * TODO: put the is_active into pkt structure instead local static
656
+ * variable when the cbc_process_signal is seperated.
657
+ */
658
+ static bool is_active ;
659
+ uint8_t cmd ;
660
+ uint8_t * payload ;
661
+ uint16_t id ;
662
+
663
+ payload = pkt -> req -> buf + CBC_PAYLOAD_POS ;
664
+ cmd = pkt -> req -> buf [CBC_SRV_POS ];
665
+
666
+ /*
667
+ * FIXME:seperate the logic in two functions
668
+ * link_len is 0 means the packet is transmitted to PTY(UART DM)
669
+ * if the signal channel is not active, do not transmit it to PTY
670
+ * to CBC cdevs, always forward the signals because signal channel
671
+ * status only for UOS
672
+ */
673
+ if (pkt -> req -> link_len == 0 && is_active == false &&
674
+ (cmd == CBC_SD_SINGLE_SIGNAL ||
675
+ cmd == CBC_SD_MULTI_SIGNAL ||
676
+ cmd == CBC_SD_GROUP_SIGNAL ))
677
+ return ;
678
+
679
+ switch (cmd ) {
680
+ /* Bidirectional command */
681
+ case CBC_SD_SINGLE_SIGNAL :
682
+ id = payload [0 ] | payload [1 ] << 8 ;
683
+ if (wlist_verify_signal (id , pkt -> cfg -> wlist_sig_tbl ,
684
+ pkt -> cfg -> wlist_sig_num ) == 0 )
685
+ cbc_send_pkt (pkt );
686
+ break ;
687
+ /* Bidirectional command */
688
+ case CBC_SD_MULTI_SIGNAL :
689
+ cbc_forward_signals (pkt );
690
+ break ;
691
+ /* Bidirectional command */
692
+ case CBC_SD_GROUP_SIGNAL :
693
+ id = payload [0 ] | payload [1 ] << 8 ;
694
+ if (wlist_verify_group (id , pkt -> cfg -> wlist_grp_tbl ,
695
+ pkt -> cfg -> wlist_grp_num ) == 0 )
696
+ cbc_send_pkt (pkt );
697
+ break ;
698
+ /* Bidirectional command */
699
+ case CBC_SD_INVAL_SSIG :
700
+ id = payload [0 ] | payload [1 ] << 8 ;
701
+ cbc_disable_signal (id , pkt -> cfg -> cbc_sig_tbl ,
702
+ pkt -> cfg -> cbc_sig_num );
703
+ break ;
704
+ /* Bidirectional command */
705
+ case CBC_SD_INVAL_MSIG :
706
+ cbc_set_invalidation (pkt , CBC_INVAL_T_SIGNAL );
707
+ break ;
708
+ /* Bidirectional command */
709
+ case CBC_SD_INVAL_SGRP :
710
+ id = payload [0 ] | payload [1 ] << 8 ;
711
+ cbc_disable_signal_group (id , pkt -> cfg -> cbc_grp_tbl ,
712
+ pkt -> cfg -> cbc_grp_num );
713
+ break ;
714
+ /* Bidirectional command */
715
+ case CBC_SD_INVAL_MGRP :
716
+ cbc_set_invalidation (pkt , CBC_INVAL_T_GROUP );
717
+ break ;
718
+ /*
719
+ * FIXME: seperate into rx signal process
720
+ * Open/reset/close are not bidirectional operations
721
+ * only for IOC rx thread
722
+ */
723
+ case CBC_SD_OPEN_CHANNEL :
724
+ case CBC_SD_RESET_CHANNEL :
725
+ is_active = true;
726
+ break ;
727
+ case CBC_SD_CLOSE_CHANNEL :
728
+ is_active = false;
729
+ break ;
730
+ default :
731
+ DPRINTF ("ioc got an new operation of signal channel=%d\r\n" ,
732
+ cmd );
733
+ break ;
734
+ }
460
735
}
461
736
462
737
/*
0 commit comments