@@ -842,14 +842,13 @@ bool canard_new(canard_t* const self,
842842 const size_t filter_count ,
843843 canard_filter_t * const filter_storage )
844844{
845- const bool has_valid_node_id = (node_id <= CANARD_NODE_ID_MAX ) || (node_id == CANARD_NODE_ID_ANONYMOUS );
846- bool ok = (self != NULL ) && (vtable != NULL ) && (vtable -> now != NULL ) && (vtable -> tx != NULL ) &&
845+ bool ok = (self != NULL ) && (vtable != NULL ) && (vtable -> now != NULL ) && (vtable -> tx != NULL ) &&
847846 (vtable -> filter != NULL ) && mem_valid (memory .tx_transfer ) && mem_valid (memory .tx_frame ) &&
848847 mem_valid (memory .rx_session ) && mem_valid (memory .rx_payload ) &&
849- ((filter_count == 0U ) || (filter_storage != NULL )) && has_valid_node_id ;
848+ ((filter_count == 0U ) || (filter_storage != NULL )) && ( node_id <= CANARD_NODE_ID_MAX ) ;
850849 if (ok ) {
851850 (void )memset (self , 0 , sizeof (* self ));
852- self -> node_id = (node_id <= CANARD_NODE_ID_MAX ) ? node_id : 0U ;
851+ self -> node_id = (node_id <= CANARD_NODE_ID_MAX ) ? node_id : CANARD_NODE_ID_ANONYMOUS ;
853852 self -> tx .fd = true;
854853 self -> tx .queue_capacity = tx_queue_capacity ;
855854 self -> rx .filter_count = filter_count ;
@@ -900,6 +899,17 @@ uint_least8_t canard_pending_ifaces(const canard_t* const self)
900899 return out ;
901900}
902901
902+ // Common Cyphal v1.0 service TX path for both request and response.
903+ static bool tx_1v0_service (canard_t * const self ,
904+ const canard_us_t deadline ,
905+ const canard_prio_t priority ,
906+ const uint16_t service_id ,
907+ const uint_least8_t destination_node_id ,
908+ const bool request_not_response ,
909+ const uint_least8_t transfer_id ,
910+ const canard_bytes_chain_t payload ,
911+ const canard_user_context_t context );
912+
903913bool canard_publish (canard_t * const self ,
904914 const canard_us_t deadline ,
905915 const uint_least8_t iface_bitmap ,
@@ -928,16 +938,21 @@ bool canard_unicast(canard_t* const self,
928938 const canard_bytes_chain_t payload ,
929939 const canard_user_context_t context )
930940{
941+ // Keep transfer-ID map behavior: increment only if basic argument validation succeeds.
931942 bool ok = (self != NULL ) && (priority < CANARD_PRIO_COUNT ) && bytes_chain_valid (payload ) &&
932943 (destination_node_id <= CANARD_NODE_ID_MAX );
933944 if (ok ) {
934- const byte_t tr_id = (byte_t )self -> unicast_transfer_id [destination_node_id ]++ ;
935- const uint32_t can_id = (((uint32_t )priority ) << PRIO_SHIFT ) |
936- (((uint32_t )CANARD_SERVICE_ID_UNICAST ) << 14U ) | //
937- (1UL << 23U ) | // request
938- (((uint32_t )destination_node_id ) << 7U );
939- canard_txfer_t * const tr = txfer_new (self , deadline , tr_id , can_id , self -> tx .fd , context );
940- ok = (tr != NULL ) && tx_push (self , tr , false, CANARD_IFACE_BITMAP_ALL , payload , CRC_INITIAL );
945+ const byte_t tr_id = (byte_t )self -> unicast_transfer_id [destination_node_id ]++ ;
946+ // Per Cyphal v1.1, unicast is a service request with fixed service-ID 511.
947+ ok = tx_1v0_service (self ,
948+ deadline ,
949+ priority ,
950+ (uint16_t )CANARD_SERVICE_ID_UNICAST ,
951+ destination_node_id ,
952+ true,
953+ tr_id ,
954+ payload ,
955+ context );
941956 }
942957 return ok ;
943958}
@@ -963,6 +978,53 @@ bool canard_1v0_publish(canard_t* const self,
963978 return ok ;
964979}
965980
981+ static bool tx_1v0_service (canard_t * const self ,
982+ const canard_us_t deadline ,
983+ const canard_prio_t priority ,
984+ const uint16_t service_id ,
985+ const uint_least8_t destination_node_id ,
986+ const bool request_not_response ,
987+ const uint_least8_t transfer_id ,
988+ const canard_bytes_chain_t payload ,
989+ const canard_user_context_t context )
990+ {
991+ bool ok = (self != NULL ) && (priority < CANARD_PRIO_COUNT ) && bytes_chain_valid (payload ) &&
992+ (service_id <= CANARD_SERVICE_ID_MAX ) && (destination_node_id <= CANARD_NODE_ID_MAX );
993+ if (ok ) {
994+ const uint32_t can_id = (((uint32_t )priority ) << PRIO_SHIFT ) | //
995+ (1UL << 25U ) | // service
996+ (request_not_response ? (1UL << 24U ) : 0U ) | (((uint32_t )service_id ) << 14U ) |
997+ (((uint32_t )destination_node_id ) << 7U );
998+ canard_txfer_t * const tr = txfer_new (self , deadline , transfer_id , can_id , self -> tx .fd , context );
999+ ok = (tr != NULL ) && tx_push (self , tr , false, CANARD_IFACE_BITMAP_ALL , payload , CRC_INITIAL );
1000+ }
1001+ return ok ;
1002+ }
1003+
1004+ bool canard_1v0_request (canard_t * const self ,
1005+ const canard_us_t deadline ,
1006+ const canard_prio_t priority ,
1007+ const uint16_t service_id ,
1008+ const uint_least8_t server_node_id ,
1009+ const uint_least8_t transfer_id ,
1010+ const canard_bytes_chain_t payload ,
1011+ const canard_user_context_t context )
1012+ {
1013+ return tx_1v0_service (self , deadline , priority , service_id , server_node_id , true, transfer_id , payload , context );
1014+ }
1015+
1016+ bool canard_1v0_respond (canard_t * const self ,
1017+ const canard_us_t deadline ,
1018+ const canard_prio_t priority ,
1019+ const uint16_t service_id ,
1020+ const uint_least8_t client_node_id ,
1021+ const uint_least8_t transfer_id ,
1022+ const canard_bytes_chain_t payload ,
1023+ const canard_user_context_t context )
1024+ {
1025+ return tx_1v0_service (self , deadline , priority , service_id , client_node_id , false, transfer_id , payload , context );
1026+ }
1027+
9661028bool canard_0v1_publish (canard_t * const self ,
9671029 const canard_us_t deadline ,
9681030 const uint_least8_t iface_bitmap ,
@@ -985,6 +1047,57 @@ bool canard_0v1_publish(canard_t* const self,
9851047 return ok ;
9861048}
9871049
1050+ static bool tx_0v1_service (canard_t * const self ,
1051+ const canard_us_t deadline ,
1052+ const canard_prio_t priority ,
1053+ const uint_least8_t data_type_id ,
1054+ const uint16_t crc_seed ,
1055+ const uint_least8_t destination_node_id ,
1056+ const bool request_not_response ,
1057+ const uint_least8_t transfer_id ,
1058+ const canard_bytes_chain_t payload ,
1059+ const canard_user_context_t context )
1060+ {
1061+ bool ok = (self != NULL ) && (priority < CANARD_PRIO_COUNT ) && bytes_chain_valid (payload ) && (self -> node_id != 0U ) &&
1062+ (destination_node_id > 0U ) && (destination_node_id <= CANARD_NODE_ID_MAX );
1063+ if (ok ) {
1064+ const uint32_t can_id = (((((uint32_t )priority ) << 2U ) | 3UL ) << 24U ) | //
1065+ (((uint32_t )data_type_id ) << 16U ) | (request_not_response ? (1UL << 15U ) : 0U ) |
1066+ (((uint32_t )destination_node_id ) << 8U ) | (1UL << 7U ); // service
1067+ canard_txfer_t * const tr = txfer_new (self , deadline , transfer_id , can_id , false, context );
1068+ ok = (tr != NULL ) && tx_push (self , tr , true, CANARD_IFACE_BITMAP_ALL , payload , crc_seed );
1069+ }
1070+ return ok ;
1071+ }
1072+
1073+ bool canard_0v1_request (canard_t * const self ,
1074+ const canard_us_t deadline ,
1075+ const canard_prio_t priority ,
1076+ const uint_least8_t data_type_id ,
1077+ const uint16_t crc_seed ,
1078+ const uint_least8_t server_node_id ,
1079+ const uint_least8_t transfer_id ,
1080+ const canard_bytes_chain_t payload ,
1081+ const canard_user_context_t context )
1082+ {
1083+ return tx_0v1_service (
1084+ self , deadline , priority , data_type_id , crc_seed , server_node_id , true, transfer_id , payload , context );
1085+ }
1086+
1087+ bool canard_0v1_respond (canard_t * const self ,
1088+ const canard_us_t deadline ,
1089+ const canard_prio_t priority ,
1090+ const uint_least8_t data_type_id ,
1091+ const uint16_t crc_seed ,
1092+ const uint_least8_t client_node_id ,
1093+ const uint_least8_t transfer_id ,
1094+ const canard_bytes_chain_t payload ,
1095+ const canard_user_context_t context )
1096+ {
1097+ return tx_0v1_service (
1098+ self , deadline , priority , data_type_id , crc_seed , client_node_id , false, transfer_id , payload , context );
1099+ }
1100+
9881101uint16_t canard_0v1_crc_seed_from_data_type_signature (const uint64_t data_type_signature )
9891102{
9901103 uint16_t crc = CRC_INITIAL ;
0 commit comments