@@ -1028,6 +1028,10 @@ impl AsRef<can_frame> for CanErrorFrame {
1028
1028
///
1029
1029
/// This is highly compatible with the `canfd_frame` from libc.
1030
1030
/// ([ref](https://docs.rs/libc/latest/libc/struct.canfd_frame.html))
1031
+ ///
1032
+ /// Payload data that is greater than 8 bytes and whose data length does
1033
+ /// not match a valid CANFD data length is padded with 0 bytes to the
1034
+ /// next higher valid CANFD data length.
1031
1035
#[ derive( Clone , Copy ) ]
1032
1036
pub struct CanFdFrame ( canfd_frame ) ;
1033
1037
@@ -1048,9 +1052,20 @@ impl CanFdFrame {
1048
1052
nif n <=CANFD_MAX_DLEN =>{
1049
1053
let mut frame =canfd_frame_default ( ) ;
1050
1054
frame. can_id = can_id;
1051
- frame. len = nas u8 ;
1052
1055
frame. flags = fd_flags. bits ( ) ;
1053
- frame. data [ ..n] . copy_from_slice ( data) ;
1056
+ if n >8 && !CanFdFrame :: is_valid_data_len ( n) {
1057
+ // data must be 0 padded to the next valid DataLength
1058
+ let new_len =CanFdFrame :: next_valid_ext_dlen ( n) ;
1059
+ let mut padded_data: Vec < u8 > =Vec :: from ( data) ;
1060
+ padded_data. resize ( new_len, 0 ) ;
1061
+ frame. len = new_lenas u8 ;
1062
+ frame. data [ ..new_len] . copy_from_slice ( & padded_data) ;
1063
+ } else {
1064
+ // payload length is a valid CANFD data length so no padding is required
1065
+ frame. len = nas u8 ;
1066
+ frame. data [ ..n] . copy_from_slice ( data) ;
1067
+ }
1068
+
1054
1069
Ok ( Self ( frame) )
1055
1070
}
1056
1071
_ =>Err ( ConstructionError :: TooMuchData ) ,
@@ -1093,6 +1108,28 @@ impl CanFdFrame {
1093
1108
self . 0 . flags &= !CANFD_ESI as u8 ;
1094
1109
}
1095
1110
}
1111
+
1112
+ /// Checks whether a given length is a valid CANFD data length.
1113
+ ///
1114
+ /// Valid values are `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`,
1115
+ /// `12`, `16`, `20`, `24`, `32`, `48` or `64`.
1116
+ fn is_valid_data_len ( len : usize ) ->bool {
1117
+ ( 0 ..=8 ) . contains ( & len) ||[ 12 , 16 , 20 , 24 , 32 , 48 , 64 ] . contains ( & len)
1118
+ }
1119
+
1120
+ /// Returns the next larger valid CANFD extended data length into which the given
1121
+ /// length fits, up to a maximum of CANFD_MAX_DLEN.
1122
+ fn next_valid_ext_dlen ( len : usize ) ->usize {
1123
+ let valid_ext_dlengths: [ usize ; 7 ] =[ 12 , 16 , 20 , 24 , 32 , 48 , 64 ] ;
1124
+
1125
+ for valid_ext_lenin valid_ext_dlengths{
1126
+ if valid_ext_len >= len{
1127
+ return valid_ext_len;
1128
+ }
1129
+ }
1130
+ // return CANFD_MAX_DLEN if len > CANFD_MAX_DLEN
1131
+ CANFD_MAX_DLEN
1132
+ }
1096
1133
}
1097
1134
1098
1135
impl AsPtr for CanFdFrame {
@@ -1140,7 +1177,19 @@ impl EmbeddedFrame for CanFdFrame {
1140
1177
1141
1178
/// Data length code
1142
1179
fn dlc ( & self ) ->usize {
1143
- self . 0 . len as usize
1180
+ match self . 0 . len {
1181
+ 0 ..=8 =>self . 0 . len as usize ,
1182
+ 12 =>0x09 ,
1183
+ 16 =>0x0A ,
1184
+ 20 =>0x0B ,
1185
+ 24 =>0x0C ,
1186
+ 32 =>0x0D ,
1187
+ 48 =>0x0E ,
1188
+ 64 =>0x0F ,
1189
+ // invalid data length, should never occur as the data is
1190
+ // padded to a valid CANFD data length on frame creation
1191
+ _ =>0x00 ,
1192
+ }
1144
1193
}
1145
1194
1146
1195
/// A slice into the actual data.
@@ -1166,8 +1215,17 @@ impl Frame for CanFdFrame {
1166
1215
fn set_data ( & mut self , data : & [ u8 ] ) ->Result < ( ) , ConstructionError > {
1167
1216
match data. len ( ) {
1168
1217
nif n <=CANFD_MAX_DLEN =>{
1169
- self . 0 . len = nas u8 ;
1170
- self . 0 . data [ ..n] . copy_from_slice ( data) ;
1218
+ if n >8 && !CanFdFrame :: is_valid_data_len ( n) {
1219
+ // data must be 0 padded to the next valid DataLength
1220
+ let new_len =CanFdFrame :: next_valid_ext_dlen ( n) ;
1221
+ let mut padded_data: Vec < u8 > =Vec :: from ( data) ;
1222
+ padded_data. resize ( new_len, 0 ) ;
1223
+ self . 0 . len = new_lenas u8 ;
1224
+ self . 0 . data [ ..new_len] . copy_from_slice ( & padded_data) ;
1225
+ } else {
1226
+ self . 0 . len = nas u8 ;
1227
+ self . 0 . data [ ..n] . copy_from_slice ( data) ;
1228
+ }
1171
1229
Ok ( ( ) )
1172
1230
}
1173
1231
_ =>Err ( ConstructionError :: TooMuchData ) ,
@@ -1238,6 +1296,16 @@ mod tests {
1238
1296
const DATA : & [ u8 ] =& [ 0 , 1 , 2 , 3 ] ;
1239
1297
const DATA_LEN : usize =DATA . len ( ) ;
1240
1298
1299
+ const EXT_DATA : & [ u8 ] =& [ 0xAB ; 32 ] ;
1300
+ const EXT_DATA_DLC : usize =0x0D ;
1301
+
1302
+ const EXT_DATA_INVALID_DLEN : & [ u8 ] =
1303
+ & [ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 0x99 , 0xAA ] ;
1304
+ const EXT_DATA_PADDED : & [ u8 ] =& [
1305
+ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 0x99 , 0xAA , 0x00 , 0x00 ,
1306
+ ] ;
1307
+ const EXT_DATA_PADDED_DLC : usize =0x09 ;
1308
+
1241
1309
const EMPTY_DATA : & [ u8 ] =& [ ] ;
1242
1310
const ZERO_DATA : & [ u8 ] =& [ 0u8 ; DATA_LEN ] ;
1243
1311
@@ -1479,6 +1547,17 @@ mod tests {
1479
1547
assert_eq ! ( EXT_LOW_ID , frame. id( ) ) ;
1480
1548
assert ! ( !frame. is_standard( ) ) ;
1481
1549
assert ! ( frame. is_extended( ) ) ;
1550
+
1551
+ let mut frame =CanFdFrame :: new ( STD_ID , EXT_DATA ) . unwrap ( ) ;
1552
+ assert_eq ! ( frame. dlc( ) , EXT_DATA_DLC ) ;
1553
+ assert_eq ! ( frame. data( ) , EXT_DATA ) ;
1554
+ frame. set_data ( EXT_DATA_INVALID_DLEN ) . unwrap ( ) ;
1555
+ assert_eq ! ( frame. data( ) , EXT_DATA_PADDED ) ;
1556
+ assert_eq ! ( frame. dlc( ) , EXT_DATA_PADDED_DLC ) ;
1557
+
1558
+ let frame =CanFdFrame :: new ( STD_ID , EXT_DATA_INVALID_DLEN ) . unwrap ( ) ;
1559
+ assert_eq ! ( frame. data( ) , EXT_DATA_PADDED ) ;
1560
+ assert_eq ! ( frame. dlc( ) , EXT_DATA_PADDED_DLC ) ;
1482
1561
}
1483
1562
1484
1563
#[ test]