@@ -73,23 +73,20 @@ typedef unsigned char byte_t;
7373
7474#define TREE_NULL (canard_tree_t){ NULL, { NULL, NULL }, 0 }
7575
76- typedef enum format_t
76+ typedef enum kind_t
7777{
78- format_1v1_message = 0 ,
79- format_1v0_message = 1 ,
80- format_1v0_response = 2 ,
81- format_1v0_request = 3 ,
78+ kind_1v1_message = 0 ,
79+ kind_1v0_message = 1 ,
80+ kind_1v0_response = 2 ,
81+ kind_1v0_request = 3 ,
8282 // v0.1
83- format_0v1_message = 4 ,
84- format_0v1_response = 5 ,
85- format_0v1_request = 6 ,
86- } format_t ;
87- static_assert (CANARD_FORMAT_COUNT == format_0v1_request + 1 , "" );
83+ kind_0v1_message = 4 ,
84+ kind_0v1_response = 5 ,
85+ kind_0v1_request = 6 ,
86+ } kind_t ;
87+ static_assert (CANARD_KIND_COUNT == kind_0v1_request + 1 , "" );
8888
89- static bool format_is_v0 (const format_t kind )
90- {
91- return (kind == format_0v1_message ) || (kind == format_0v1_request ) || (kind == format_0v1_response );
92- }
89+ static bool kind_is_v1 (const kind_t kind ) { return kind < kind_0v1_message ; }
9390
9491#define KILO 1000LL
9592#define MEGA (KILO * KILO)
@@ -1055,7 +1052,7 @@ bool canard_0v1_respond(canard_t* const self,
10551052typedef struct
10561053{
10571054 canard_prio_t priority ;
1058- format_t format ;
1055+ kind_t kind ;
10591056
10601057 uint32_t port_id ; // in v0 this stores the data type ID.
10611058
@@ -1125,17 +1122,17 @@ static byte_t rx_parse(const uint32_t can_id,
11251122 out_v1 -> dst = (byte_t )((can_id >> 7U ) & CANARD_NODE_ID_MAX );
11261123 out_v1 -> port_id = (can_id >> 14U ) & CANARD_SERVICE_ID_MAX ;
11271124 const bool req = (can_id & (UINT32_C (1 ) << 24U )) != 0U ;
1128- out_v1 -> format = req ? format_1v0_request : format_1v0_response ;
1125+ out_v1 -> kind = req ? kind_1v0_request : kind_1v0_response ;
11291126 } else {
11301127 out_v1 -> dst = CANARD_NODE_ID_ANONYMOUS ;
11311128 const bool is_1v1 = (can_id & (UINT32_C (1 ) << 7U )) != 0U ;
11321129 if (is_1v1 ) {
11331130 out_v1 -> port_id = (can_id >> 8U ) & CANARD_SUBJECT_ID_MAX ;
1134- out_v1 -> format = format_1v1_message ;
1131+ out_v1 -> kind = kind_1v1_message ;
11351132 } else {
11361133 is_v1 = is_v1 && !bit_23 ;
11371134 out_v1 -> port_id = (can_id >> 8U ) & CANARD_SUBJECT_ID_MAX_1v0 ;
1138- out_v1 -> format = format_1v0_message ;
1135+ out_v1 -> kind = kind_1v0_message ;
11391136 if ((can_id & (UINT32_C (1 ) << 24U )) != 0U ) {
11401137 out_v1 -> src = CANARD_NODE_ID_ANONYMOUS ;
11411138 is_v1 = is_v1 && start && end ; // anonymous can only be single-frame
@@ -1158,11 +1155,11 @@ static byte_t rx_parse(const uint32_t can_id,
11581155 out_v0 -> dst = dst ;
11591156 out_v0 -> port_id = (can_id >> 16U ) & 0xFFU ;
11601157 const bool req = (can_id & (UINT32_C (1 ) << 15U )) != 0U ;
1161- out_v0 -> format = req ? format_0v1_request : format_0v1_response ;
1158+ out_v0 -> kind = req ? kind_0v1_request : kind_0v1_response ;
11621159 } else {
11631160 out_v0 -> dst = CANARD_NODE_ID_ANONYMOUS ;
11641161 out_v0 -> port_id = (can_id >> 8U ) & 0xFFFFU ;
1165- out_v0 -> format = format_0v1_message ;
1162+ out_v0 -> kind = kind_0v1_message ;
11661163 if (src == 0 ) {
11671164 out_v0 -> src = CANARD_NODE_ID_ANONYMOUS ;
11681165 is_v0 = is_v0 && start && end ; // anonymous can only be single-frame
@@ -1243,16 +1240,15 @@ static_assert((sizeof(void*) > 4) || (sizeof(rx_session_t) <= 120), "too large")
12431240static rx_slot_t * rx_slot_new (const canard_subscription_t * const sub ,
12441241 const canard_us_t start_ts ,
12451242 const byte_t transfer_id ,
1246- const byte_t iface_index ,
1247- const bool v1 )
1243+ const byte_t iface_index )
12481244{
12491245 rx_slot_t * const slot = mem_alloc (sub -> owner -> mem .rx_payload , RX_SLOT_OVERHEAD + sub -> extent );
12501246 if (slot != NULL ) {
12511247 memset (slot , 0 , RX_SLOT_OVERHEAD );
12521248 slot -> start_ts = start_ts ;
12531249 slot -> crc = sub -> crc_seed ;
12541250 slot -> transfer_id = transfer_id & CANARD_TRANSFER_ID_MAX ;
1255- slot -> expected_toggle = v1 ? 1 : 0 ;
1251+ slot -> expected_toggle = kind_is_v1 ( sub -> kind ) ? 1 : 0 ;
12561252 slot -> iface_index = iface_index & ((1U << IFACE_INDEX_BIT_LENGTH ) - 1U );
12571253 }
12581254 return slot ;
@@ -1281,13 +1277,12 @@ static canard_tree_t* rx_session_factory(void* const user)
12811277 if (ses == NULL ) {
12821278 return NULL ;
12831279 }
1284- ses -> index = TREE_NULL ;
1285- ses -> list_animation = LIST_NULL ;
12861280 FOREACH_SLOT (i ) {
12871281 ses -> slots [i ] = NULL ;
12881282 }
12891283 ses -> owner = ctx -> owner ;
12901284 ses -> node_id = ctx -> node_id ;
1285+ enlist_tail (& ctx -> owner -> owner -> rx .list_session_by_animation , & ses -> list_animation );
12911286 return & ses -> index ;
12921287}
12931288
@@ -1336,21 +1331,63 @@ static void rx_slot_write_payload(const rx_session_t* const ses, rx_slot_t* cons
13361331}
13371332
13381333// Returns false on OOM, no other failure modes.
1339- static bool rx_session_update (canard_subscription_t * const sub , const canard_us_t ts , const frame_t * const frame )
1334+ static bool rx_session_update (canard_subscription_t * const sub ,
1335+ const canard_us_t ts ,
1336+ const frame_t * const frame ,
1337+ const byte_t iface_index )
13401338{
13411339 CANARD_ASSERT ((sub != NULL ) && (frame != NULL ) && (frame -> payload .data != NULL ) && (ts >= 0 ));
13421340 CANARD_ASSERT (frame -> end || (frame -> payload .size >= 7 ));
13431341
13441342 rx_session_factory_context_t factory_context = { .owner = sub , .node_id = frame -> src };
1345- rx_session_t * const ses = CAVL2_TO_OWNER (
1346- cavl2_find_or_insert (& sub -> sessions , & frame -> src , rx_session_cavl_compare , & factory_context , rx_session_factory ),
1347- rx_session_t ,
1348- index );
1343+ rx_session_t * const ses =
1344+ CAVL2_TO_OWNER (frame -> start ? cavl2_find_or_insert (& sub -> sessions , //
1345+ & frame -> src ,
1346+ rx_session_cavl_compare ,
1347+ & factory_context ,
1348+ rx_session_factory )
1349+ : cavl2_find (sub -> sessions , & frame -> src , rx_session_cavl_compare ),
1350+ rx_session_t ,
1351+ index );
13491352 if (ses == NULL ) {
1350- return false;
1353+ sub -> owner -> err .oom += frame -> start ;
1354+ return !frame -> start ;
1355+ }
1356+
1357+ // Frame admittance state machine. A highly complex piece, redesigned after v4 to support priority preemption.
1358+ // TID forward difference illustration: f(2,3)==31, f(2,2)==0, f(2,1)==1
1359+ const bool tid_new = rx_transfer_id_forward_difference (ses -> last_admitted_transfer_id , frame -> transfer_id ) > 1 ;
1360+ const canard_us_t timed_out = (ts - ses -> last_admitted_start_ts ) > ses -> owner -> transfer_id_timeout ;
1361+ bool accept = false;
1362+ if (!frame -> start ) {
1363+ const rx_slot_t * const slot = ses -> slots [frame -> priority ];
1364+ accept = (slot != NULL ) && (slot -> transfer_id == frame -> transfer_id ) && (slot -> iface_index == iface_index ) &&
1365+ (slot -> expected_toggle == frame -> toggle );
1366+ } else {
1367+ const rx_slot_t * const slot = ses -> slots [frame -> priority ];
1368+ accept = (slot == NULL ) || (slot -> transfer_id != frame -> transfer_id ) || tid_new || timed_out ; // --
13511369 }
1352- ses -> last_admitted_transfer_id ++ ; // TODO stub
1353- (void )ts ;
1370+ if (!accept ) {
1371+ return true; // Frame not needed; not a failure to accept.
1372+ }
1373+
1374+ // The frame must be accepted. If this is the start of a new transfer, we must update state.
1375+ enlist_tail (& sub -> owner -> rx .list_session_by_animation , & ses -> list_animation );
1376+ if (frame -> start ) {
1377+ ses -> last_admitted_start_ts = ts ;
1378+ ses -> last_admitted_transfer_id = frame -> transfer_id ;
1379+ rx_slot_destroy (sub , ses -> slots [frame -> priority ]);
1380+ ses -> slots [frame -> priority ] = NULL ;
1381+ if (!frame -> end ) { // more frames to follow, must store in-progress state
1382+ ses -> slots [frame -> priority ] = rx_slot_new (sub , ts , frame -> transfer_id , iface_index );
1383+ if (ses -> slots [frame -> priority ] == NULL ) {
1384+ sub -> owner -> err .oom ++ ;
1385+ return false;
1386+ }
1387+ }
1388+ }
1389+
1390+ // TODO acceptance
13541391
13551392 return false;
13561393}
0 commit comments