@@ -1075,6 +1075,10 @@ impl AsRef<can_frame> for CanErrorFrame {
1075
1075
///
1076
1076
/// This is highly compatible with the `canfd_frame` from libc.
1077
1077
/// ([ref](https://docs.rs/libc/latest/libc/struct.canfd_frame.html))
1078
+ ///
1079
+ /// Payload data that is greater than 8 bytes and whose data length does
1080
+ /// not match a valid CANFD data length is padded with 0 bytes to the
1081
+ /// next higher valid CANFD data length.
1078
1082
#[ derive( Clone , Copy ) ]
1079
1083
pub struct CanFdFrame ( canfd_frame ) ;
1080
1084
@@ -1095,9 +1099,20 @@ impl CanFdFrame {
1095
1099
nif n <=CANFD_MAX_DLEN =>{
1096
1100
let mut frame =canfd_frame_default ( ) ;
1097
1101
frame. can_id = can_id;
1098
- frame. len = nas u8 ;
1099
1102
frame. flags = fd_flags. bits ( ) ;
1100
- frame. data [ ..n] . copy_from_slice ( data) ;
1103
+ if n >8 && !CanFdFrame :: is_valid_data_len ( n) {
1104
+ // data must be 0 padded to the next valid DataLength
1105
+ let new_len =CanFdFrame :: next_valid_ext_dlen ( n) ;
1106
+ let mut padded_data: Vec < u8 > =Vec :: from ( data) ;
1107
+ padded_data. resize ( new_len, 0 ) ;
1108
+ frame. len = new_lenas u8 ;
1109
+ frame. data [ ..new_len] . copy_from_slice ( & padded_data) ;
1110
+ } else {
1111
+ // payload length is a valid CANFD data length so no padding is required
1112
+ frame. len = nas u8 ;
1113
+ frame. data [ ..n] . copy_from_slice ( data) ;
1114
+ }
1115
+
1101
1116
Ok ( Self ( frame) )
1102
1117
}
1103
1118
_ =>Err ( ConstructionError :: TooMuchData ) ,
@@ -1140,6 +1155,28 @@ impl CanFdFrame {
1140
1155
self . 0 . flags &= !CANFD_ESI as u8 ;
1141
1156
}
1142
1157
}
1158
+
1159
+ /// Checks whether a given length is a valid CANFD data length.
1160
+ ///
1161
+ /// Valid values are `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`,
1162
+ /// `12`, `16`, `20`, `24`, `32`, `48` or `64`.
1163
+ fn is_valid_data_len ( len : usize ) ->bool {
1164
+ ( 0 ..=8 ) . contains ( & len) ||[ 12 , 16 , 20 , 24 , 32 , 48 , 64 ] . contains ( & len)
1165
+ }
1166
+
1167
+ /// Returns the next larger valid CANFD extended data length into which the given
1168
+ /// length fits, up to a maximum of CANFD_MAX_DLEN.
1169
+ fn next_valid_ext_dlen ( len : usize ) ->usize {
1170
+ let valid_ext_dlengths: [ usize ; 7 ] =[ 12 , 16 , 20 , 24 , 32 , 48 , 64 ] ;
1171
+
1172
+ for valid_ext_lenin valid_ext_dlengths{
1173
+ if valid_ext_len >= len{
1174
+ return valid_ext_len;
1175
+ }
1176
+ }
1177
+ // return CANFD_MAX_DLEN if len > CANFD_MAX_DLEN
1178
+ CANFD_MAX_DLEN
1179
+ }
1143
1180
}
1144
1181
1145
1182
impl AsPtr for CanFdFrame {
@@ -1187,7 +1224,19 @@ impl EmbeddedFrame for CanFdFrame {
1187
1224
1188
1225
/// Data length code
1189
1226
fn dlc ( & self ) ->usize {
1190
- self . 0 . len as usize
1227
+ match self . 0 . len {
1228
+ 0 ..=8 =>self . 0 . len as usize ,
1229
+ 12 =>0x09 ,
1230
+ 16 =>0x0A ,
1231
+ 20 =>0x0B ,
1232
+ 24 =>0x0C ,
1233
+ 32 =>0x0D ,
1234
+ 48 =>0x0E ,
1235
+ 64 =>0x0F ,
1236
+ // invalid data length, should never occur as the data is
1237
+ // padded to a valid CANFD data length on frame creation
1238
+ _ =>0x00 ,
1239
+ }
1191
1240
}
1192
1241
1193
1242
/// A slice into the actual data.
@@ -1213,8 +1262,17 @@ impl Frame for CanFdFrame {
1213
1262
fn set_data ( & mut self , data : & [ u8 ] ) ->Result < ( ) , ConstructionError > {
1214
1263
match data. len ( ) {
1215
1264
nif n <=CANFD_MAX_DLEN =>{
1216
- self . 0 . len = nas u8 ;
1217
- self . 0 . data [ ..n] . copy_from_slice ( data) ;
1265
+ if n >8 && !CanFdFrame :: is_valid_data_len ( n) {
1266
+ // data must be 0 padded to the next valid DataLength
1267
+ let new_len =CanFdFrame :: next_valid_ext_dlen ( n) ;
1268
+ let mut padded_data: Vec < u8 > =Vec :: from ( data) ;
1269
+ padded_data. resize ( new_len, 0 ) ;
1270
+ self . 0 . len = new_lenas u8 ;
1271
+ self . 0 . data [ ..new_len] . copy_from_slice ( & padded_data) ;
1272
+ } else {
1273
+ self . 0 . len = nas u8 ;
1274
+ self . 0 . data [ ..n] . copy_from_slice ( data) ;
1275
+ }
1218
1276
Ok ( ( ) )
1219
1277
}
1220
1278
_ =>Err ( ConstructionError :: TooMuchData ) ,
@@ -1285,6 +1343,16 @@ mod tests {
1285
1343
const DATA : & [ u8 ] =& [ 0 , 1 , 2 , 3 ] ;
1286
1344
const DATA_LEN : usize =DATA . len ( ) ;
1287
1345
1346
+ const EXT_DATA : & [ u8 ] =& [ 0xAB ; 32 ] ;
1347
+ const EXT_DATA_DLC : usize =0x0D ;
1348
+
1349
+ const EXT_DATA_INVALID_DLEN : & [ u8 ] =
1350
+ & [ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 0x99 , 0xAA ] ;
1351
+ const EXT_DATA_PADDED : & [ u8 ] =& [
1352
+ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 0x99 , 0xAA , 0x00 , 0x00 ,
1353
+ ] ;
1354
+ const EXT_DATA_PADDED_DLC : usize =0x09 ;
1355
+
1288
1356
const EMPTY_DATA : & [ u8 ] =& [ ] ;
1289
1357
const ZERO_DATA : & [ u8 ] =& [ 0u8 ; DATA_LEN ] ;
1290
1358
@@ -1526,6 +1594,17 @@ mod tests {
1526
1594
assert_eq ! ( EXT_LOW_ID , frame. id( ) ) ;
1527
1595
assert ! ( !frame. is_standard( ) ) ;
1528
1596
assert ! ( frame. is_extended( ) ) ;
1597
+
1598
+ let mut frame =CanFdFrame :: new ( STD_ID , EXT_DATA ) . unwrap ( ) ;
1599
+ assert_eq ! ( frame. dlc( ) , EXT_DATA_DLC ) ;
1600
+ assert_eq ! ( frame. data( ) , EXT_DATA ) ;
1601
+ frame. set_data ( EXT_DATA_INVALID_DLEN ) . unwrap ( ) ;
1602
+ assert_eq ! ( frame. data( ) , EXT_DATA_PADDED ) ;
1603
+ assert_eq ! ( frame. dlc( ) , EXT_DATA_PADDED_DLC ) ;
1604
+
1605
+ let frame =CanFdFrame :: new ( STD_ID , EXT_DATA_INVALID_DLEN ) . unwrap ( ) ;
1606
+ assert_eq ! ( frame. data( ) , EXT_DATA_PADDED ) ;
1607
+ assert_eq ! ( frame. dlc( ) , EXT_DATA_PADDED_DLC ) ;
1529
1608
}
1530
1609
1531
1610
#[ test]