busmust_sys/types.rs
1use std::ffi::c_void;
2use std::os::raw::c_char;
3use bitfield_struct::bitfield;
4
5/// Size (in bytes) of an error description string.
6pub const BM_ERROR_DESC_MAX_SIZE: usize = 255;
7
8/// Size (in bytes) of BM Data header, which contains type, routing, length and timestamp.
9pub const BM_DATA_HEADER_SIZE: usize = 8;
10
11/// Size (in bytes) of BM Data payload, which contains a concrete message in `CAN-FD` | `LIN` | `FLEXRAY` | `...` type.
12pub const BM_DATA_PAYLOAD_MAX_SIZE: usize = 72;
13
14/// Size (in bytes) of BM Data, which contains a header and payload.
15pub const BM_DATA_MAX_SIZE: usize = BM_DATA_HEADER_SIZE + BM_DATA_PAYLOAD_MAX_SIZE;
16
17/// Busmust library log level, see [super::api::BM_SetLogLevel] for details.
18#[repr(u32)]
19pub enum BMLogLevel {
20 /// Show nothing on debug console
21 None = 0,
22 /// Show only ERR level messages on debug console, note this is the default level for release versions
23 Error = 1,
24 /// Show ERR and WRN level messages on debug console
25 Warning = 2,
26 /// Show ERR|WRN|INF level messages on debug console
27 Info = 3,
28 /// Show all messages on debug console, including debug messages, note this is NOT available for release versions
29 Debug = 4
30}
31
32bitflags!{
33 /// Busmust Device capability flags, retrieved when enumerating devices using [super::api::BM_Enumerate].
34 #[repr(transparent)]
35 pub struct BMCapability: u16 {
36 /// No capability
37 const NONE = 0x0000;
38 /// The device is capable of handling LIN messages
39 const LIN = 0x0001;
40 /// The device is capable of handling CAN messages
41 const CAN = 0x0002;
42 /// The device is capable of handling CAN-FD (and CAN) messages
43 const CAN_FD = 0x0004;
44 /// The device is capable of handling FlexRay messages
45 const FLEXRAY = 0x0008;
46 /// The device is capable of handling ModBus messages
47 const MODBUS = 0x0010;
48 /// The device is capable of handling Ethernet messages
49 const ETHERNET = 0x0020;
50 /// Typically used for masking the CAP fields when programming
51 const ALL = 0xFFFF;
52 }
53}
54
55/// Busmust data type flags, must be given in [BMData].
56#[repr(u8)]
57#[derive(Debug, Copy, Clone)]
58pub enum BMDataType {
59 /// Unknown data type
60 Unknown = 0,
61 /// LIN message data type
62 Lin = 1,
63 /// CAN or CAN-FD message data type (check FDF flag further)
64 Can = 2,
65 /// FlexRay message data type
66 FlexRay = 3,
67 /// MODBUS message data type
68 ModBus = 4,
69 /// Ethernet message data type
70 Ethernet = 5,
71 /// ACK from bus, which indicates `TXCMPLT` event if this is [BMDataType::Can]
72 Ack = 8
73}
74
75
76/// Busmust device & operation status, most APIs would return a status code to indicate the result of an operation
77#[repr(u32)]
78#[derive(Debug, Copy, Clone)]
79pub enum BMStatus {
80 /// SUCCESS: No error occurred
81 Ok = 0x00000,
82 /// Low level Transmit buffer is full
83 XmtFull = 0x00001,
84 /// Bus overrun (the device cannot keep up with the high bus throughput)
85 Overrun = 0x00002,
86 /// CAN Bus communication is light, see ISO11898 for details
87 BusLight = 0x00004,
88 /// CAN Bus communication is in warning state, see ISO11898 for details
89 BusWarning = 0x00008,
90 /// CAN node is in passive state, see ISO11898 for details
91 BusPassive = 0x40000,
92 /// CAN node failed to transmit message within specified time, the node might be in PASSIVE or BUS-OFF state
93 BusTimeout = 0x80000,
94 /// CAN bus is in BUS-OFF state, see ISO11898 for details
95 BusOff = 0x00010,
96 /// CAN bus error occurred
97 AnyBusError = 0x00008 | 0x00004 | 0x00010 | 0x40000,
98 /// Receive buffer is empty, this might NOT be an error if you use BM API in polling mode
99 ReceiveBufferEmpty = 0x00020,
100 /// BM API internal queue overrun
101 QueueOverrun = 0x00040,
102 /// High level Transmit queue is full
103 TransmitQueueFull = 0x00080,
104 /// Reserved
105 RegTest = 0x00100,
106 /// Reserved
107 NoDriver = 0x00200,
108 /// Hardware is in use (opened by another application)
109 HardwareInUse = 0x00400,
110 /// Reserved
111 NetInUse = 0x00800,
112 /// Hardware error or invalid hardware handle
113 HardwareError = 0x01400,
114 /// Invalid bus
115 InvalidBus = 0x01800,
116 /// Invalid client
117 InvalidClient = 0x01C00,
118 /// Out of resources
119 OutOfResources = 0x02000,
120 /// Invalid parameter type in API call
121 InvalidParameterType = 0x04000,
122 /// Invalid parameter value in API call
123 InvalidParameterValue = 0x08000,
124 /// Unknown error
125 Unknown = 0x10000,
126 /// Invalid data received/transmitted
127 InvalidData = 0x20000,
128 /// Reserved
129 Caution = 0x2000000,
130 /// The device/library is not initialized
131 NotInitialized = 0x4000000,
132 /// Invalid operation
133 InvalidOperation = 0x8000000
134}
135
136#[repr(u32)]
137#[derive(Debug, Copy, Clone)]
138/// CAN mode IDs, used by [super::api::BM_SetCanMode] to change the operation mode of CAN device.
139pub enum BMCanMode {
140 /// The device is running normally (with the capability to handle CAN and CAN-FD messages
141 Normal = 0x00,
142 /// The device is logically disconnected from CAN bus
143 BufOff = 0x01,
144 /// The device is looping back messages internally without impacting the physical CAN bus
145 InternalLoopback = 0x02,
146 /// The device is receiving messages without impacting the physical CAN bus (do not send ACKs to the bus)
147 ListenOnly = 0x03,
148 /// The device is under configuration and temporarily disconnected from CAN bus, For Internal usage only
149 Configuration = 0x04,
150 /// The device is looping back messages externally, all transmitted messages are echoed by the device itself
151 ExternalLoopback = 0x05,
152 /// The device is running normally (with the capability to handle only classical CAN2.0 messages
153 Classic = 0x06,
154 /// Reserved
155 Restricted = 0x07
156}
157
158/// Terminal resistor values, used by [super::api::BM_SetTerminalRegister] to change the terminal resistor of CAN device.
159#[repr(u32)]
160#[derive(Debug, Copy, Clone)]
161pub enum BMTerminalResistor {
162 /// Reserved, currently unsupported
163 Auto = 0,
164 /// Currently unsupported
165 Enabled60 = 60,
166 /// 120Ohm
167 Enabled120 = 120,
168 /// Disable terminal resistor
169 Disabled = 0xFFFF
170}
171
172/// CAN Message type flags, used in [BMCanMessage]
173#[repr(u8)]
174pub enum BMMessageFlags {
175 /// Normal CAN message
176 Normal = 0,
177 /// Extended CAN message
178 Extended = 1,
179 /// Remote CAN message
180 Remote = 2,
181 /// CAN-FD bitrate switching is enabled
182 BitRateSwitching = 4,
183 /// CAN-FD message
184 CanFD = 8,
185 /// Reserved for gateways
186 Esi = 16
187}
188
189/// CAN RX filter type IDs, used in [BMRxFilter]
190#[repr(u32)]
191pub enum BMRxFilterType {
192 /// Invalid (unused) RX filter entry
193 Invalid = 0,
194 /// Basic RX filter, traditional acceptance filter based on message ID mask
195 Basic = 1,
196 /// Busmust advanced RX filter, check both message ID and message payload
197 Advanced = 2,
198 /// Busmust E2E RX filter, accept only messages that passed E2E checking
199 E2EPass = 3,
200 /// Busmust E2E RX filter, accept only messages that failed E2E checking (for debugging purpose)
201 E2EFail = 4
202}
203
204/// CAN TX task type IDs, used in [BMTxTask].
205#[repr(u32)]
206pub enum BMTxTaskType {
207 /// Invalid (unused) TX task entry
208 Invalid = 0,
209 /// Basic TX task, send fixed ID and fixed payload
210 Fixed = 1,
211 /// Self-increment Data TX task
212 IncData = 2,
213 /// Self-increment ID TX task
214 IncId = 3,
215 /// Random Data TX task
216 RandomData = 4,
217 /// Random ID TX task
218 RandomId = 5
219}
220
221/// CAN runtime statistics item IDs, used in [super::api::BM_GetStatus].
222#[repr(u32)]
223pub enum BMStatType {
224 /// Invalid statistics item
225 None = 0,
226 /// Number of TX messages
227 TxMessage = 1,
228 /// Number of RX messages
229 RxMessage = 2,
230 /// Number of TX bytes
231 TxByte = 3,
232 /// Number of RX bytes
233 RxByte = 4,
234 /// Number of TX errors
235 TxError = 5,
236 /// Number of RX errors
237 RxError = 6
238}
239
240/// ISO-TP operation mode.
241#[repr(u32)]
242pub enum BMIsotpMode {
243 /// Default mode: normal (non-extended-addressing) UDS client(tester)
244 NormalTester = 0,
245 /// Normal (non-extended-addressing) UDS server(ECU)
246 NormalEcu = 1,
247 /// Currently unsupported: extended-addressing UDS client(tester)
248 ExtendedTester = 2,
249 /// Currently unsupported: extended-addressing UDS server(ECU)
250 ExtendedEcu = 3
251}
252
253/// Busmust data header, each BMData contains a header which indicates payload information.
254#[bitfield(u16)]
255#[derive(Default)]
256pub struct BMDataHeader {
257 /// Data type, see BMDataType for details.
258 #[bits(4)]
259 pub kind: u8,
260 /// Reserved flags, keep 0
261 #[bits(4)]
262 pub flags: u8,
263 /// Destination channel ID, starting from zero, used by TX data to indicate the hardware about the target port.
264 #[bits(4)]
265 pub dchn: u8,
266 /// Source channel ID, starting from zero, used by RX data to indicate the application about the source port.
267 #[bits(4)]
268 pub schn: u8,
269}
270
271/// Busmust data, abstract structure which holds concrete payload messages of various types (i.e. CAN messages).
272#[repr(C)]
273pub struct BMData {
274 /// Data header, see [BMDataHeader] for details.
275 pub header: BMDataHeader,
276 /// Length in bytes of the payload only (header excluded).
277 pub length: u16,
278 /// 32-bit device local high precision timestamp in microseconds.
279 pub timestamp: u32,
280 /// Buffer holding concrete message payload (i.e. a CAN message in [BMCanMessage] format).
281 pub payload: [u8; BM_DATA_PAYLOAD_MAX_SIZE],
282}
283
284/// Busmust CAN Message ID.
285/// You could also use an `u32`, but please take care of memory alignments.
286#[bitfield(u32)]
287pub struct BMMessageId {
288 /// Standard ID
289 #[bits(11)]
290 pub sid: u16,
291 /// Extended ID
292 #[bits(18)]
293 pub eid: u32,
294 /// Reserved
295 #[bits(1)]
296 pub reserved1: bool,
297 /// Reserved
298 #[bits(2)]
299 pub reserved2: u8,
300}
301
302/// Busmust TX CAN Message control fields.
303/// The first few fields (until FDF) are bit compatible with [BMRxMessageCtrl].
304#[bitfield(u32)]
305pub struct BMTxMessageCtrl {
306 /// CAN message DLC(0-F), note this is not the message length
307 #[bits(4)]
308 pub dlc: u8,
309 /// This message is an extended CAN message
310 #[bits(1)]
311 pub ide: bool,
312 /// This message is a remote CAN message
313 #[bits(1)]
314 pub rtr: bool,
315 /// This message requires CAN-FD bitrate switching
316 #[bits(1)]
317 pub brs: bool,
318 /// This message is a CAN-FD CAN message
319 #[bits(1)]
320 pub fdf: bool,
321 /// Reserved for gateways
322 #[bits(1)]
323 pub esi: bool,
324 /// Reserved for hardware sync
325 #[bits(23)]
326 pub seq: u32,
327}
328
329/// Busmust RX CAN Message control fields.
330/// The first few fields (until FDF) are bit compatible with [BMTxMessageCtrl].
331#[bitfield(u32)]
332pub struct BMRxMessageCtrl {
333 /// CAN message DLC(0-F), note this is not the message length
334 #[bits(4)]
335 pub dlc: u8,
336 /// This message is an extended CAN message
337 #[bits(1)]
338 pub ide: bool,
339 /// This message is a remote CAN message
340 #[bits(1)]
341 pub rtr: bool,
342 /// This message requires CAN-FD bitrate switching
343 #[bits(1)]
344 pub brs: bool,
345 /// This message is a CAN-FD CAN message
346 #[bits(1)]
347 pub fdf: bool,
348 /// Reserved for gateways
349 #[bits(1)]
350 pub esi: bool,
351 /// Reserved
352 #[bits(2)]
353 pub reserved1: u8,
354 /// By which RX filter the message was accepted
355 #[bits(5)]
356 pub rx_filter: u8,
357 /// Reserved
358 #[bits(16)]
359 pub reserved2: u16,
360}
361
362/// Busmust CAN Message control fields.
363#[repr(C)]
364#[derive(Copy, Clone)]
365pub union BMMessageCtrl {
366 /// TX control
367 pub tx: BMTxMessageCtrl,
368 /// RX control
369 pub rx: BMRxMessageCtrl
370}
371
372/// Busmust CAN Message concrete type, usually used as payload of [BMData].
373/// The total length of this structure is 72B, it supports both classic and FD CAN messages.
374#[repr(C)]
375#[derive(Copy, Clone)]
376pub struct BMCanMessage {
377 /// CAN message ID, see [BMMessageId] for details.
378 pub mid: BMMessageId,
379 /// CAN message control fields, whether TX or RX is taken depends on the message direction.
380 pub ctrl: BMMessageCtrl,
381 /// CAN message payload
382 pub payload: [u8; 64]
383}
384
385/// Channel information, created when enumerating devices by [super::api::BM_Enumerate] and used when opening device by [super::api::BM_OpenEx]
386#[repr(C)]
387#[derive(Copy, Clone)]
388pub struct BMChannelInfo {
389 /// Device full name, for display purpose
390 pub name: [c_char; 64],
391 /// Device SN
392 pub sn: [u8; 16],
393 /// Device UID
394 pub uid: [u8; 12],
395 /// Device Firmware Version
396 pub version: [u8; 4],
397 /// Device VID
398 pub vid: u16,
399 /// Device PID
400 pub pid: u16,
401 /// Port ID (0-7) of the device, note a multi-port device is enumerated as multiple dedicated [BMChannelInfo] entries
402 pub port: u16,
403 /// Device Capability flags, see [BMCapability] for details.
404 pub cap: BMCapability,
405 /// Reserved
406 pub reserved: [u8; 4]
407}
408
409/// CAN channel status detailed information, retrieved by calling [super::api::BM_GetStatus], see ISO11898 for details.
410#[repr(C)]
411#[derive(Debug)]
412pub struct BMCanStatusInfo {
413 /// The CAN channel is in BUS-OFF state
414 pub tx_bus_off: u8,
415 /// Reserved
416 reserved: u8,
417 /// The CAN channel is in TX bus passive state
418 pub tx_bus_passive: u8,
419 /// The CAN channel is in RX bus passive state
420 pub rx_bus_passive: u8,
421 /// The CAN channel is in TX warn state
422 pub tx_warn: u8,
423 /// The CAN channel is in RX warn state
424 pub rx_warn: u8,
425 /// TX Bus Error counter
426 pub tx_errors: u8,
427 /// RX Bus Error counter
428 pub rx_errors: u8
429}
430
431/// CAN channel bitrate configuration, used by [super::api::BM_SetBitrate]
432#[repr(C)]
433pub struct BMBitrate {
434 /// Nominal bitrate in kbps, default as 500, note this is the only valid bitrate in CAN CLASSIC mode.
435 pub n_bitrate: u16,
436 /// Data bitrate in kbps, default as 500, note this is ignored in CAN CLASSIC mode.
437 pub d_bitrate: u16,
438 /// Nominal sample position (percentage, 0-100, default as 75
439 pub n_sample_pos: u8,
440 /// Data sample position (percentage, 0-100, default as 75
441 pub d_sample_pos: u8,
442 // Setting any of the fields below would override the n_bitrate configuration
443 /// CAN controller clock in Mhz, default as 0
444 pub clock_freq: u8,
445 /// Reserved
446 pub reserved: u8,
447 /// Nominal BTR0 register value, note this value is calculated using clock_freq, which might not be 16MHz
448 pub n_btr0: u8,
449 /// Nominal BTR1 register value, note this value is calculated using clock_freq, which might not be 16MHz
450 pub n_btr1: u8,
451 /// Data BTR0 register value, note this value is calculated using clock_freq, which might not be 16MHz
452 pub d_btr0: u8,
453 /// Data BTR1 register value, note this value is calculated using clock_freq, which might not be 16MHz
454 pub d_btr1: u8
455}
456
457/// CAN channel RX filter item structure, used by [super::api::BM_SetRxFilters]
458/// The filter support masking ID, flags and payload according to its type,
459/// in order for a message to be accepted, all the fields are masked using AND logic:
460/// `(flags & filter.flags_mask == filter.flags_value) AND (ID & filter.id_mask == filter.id_value) AND (payload & filter.payload_mask == filter.payload_value)`
461#[repr(C)]
462pub struct BMRxFilter {
463 /// Type ID of the RX filter, see [BMRxFilterType] for details.
464 pub kind: u8,
465 /// Reserved
466 pub unused: u8,
467 /// CAN message control Flags masks, see [BMMessageFlags] for details.
468 pub flags_mask: u8,
469 /// CAN message control Flags values, see [BMMessageFlags] for details.
470 pub flags_value: u8,
471 /// Reserved
472 pub reserved: [u8; 4],
473 pub id_mask: u32,
474 /// CAN message ID values, see [BMMessageId] for details.
475 pub id_value: u32,
476 /// CAN message payload masks, for CAN-FD messages, only the first 8 bytes are checked.
477 pub payload_mask: [u8; 8],
478 /// CAN message payload values, for CAN-FD messages, only the first 8 bytes are checked.
479 pub payload_value: [u8; 8]
480
481}
482
483#[repr(C)]
484pub struct BMTxTaskIncDataPattern {
485 /// Start bit of data increment, currently only 8-bit aligned value is accepted
486 pub start_bit: u16,
487 /// Number of bits of data increment, currently only 32 is accepted
488 pub nbits: u8,
489 /// Number of bits of data increment, currently only 32 is accepted
490 pub format: u8,
491 /// Minimum value of the Increment range
492 pub min: u32,
493 /// Maximum value of the Increment range
494 pub max: u32,
495 /// Step of the Increment range
496 pub step: u32
497}
498
499#[repr(C)]
500pub struct BMTxTaskIncIdPattern {
501 /// Minimum value of the Increment range
502 pub min: u32,
503 /// Maximum value of the Increment range
504 pub max: u32,
505 /// Step of the Increment range
506 pub step: u32
507}
508
509#[repr(C)]
510pub struct BMTxTaskRndDataPattern {
511 /// Start bit of data Random, currently only 8-bit aligned value is accepted
512 pub start_bit: u16,
513 /// Number of bits of data Random, currently only 32 is accepted
514 pub nbits: u8,
515 /// 0x80=Intel, 0x00=Motorola
516 pub format: u8,
517 /// Minimum value of the Random range
518 pub min: u32,
519 /// Maximum value of the Random range
520 pub max: u32,
521 /// Seed of the Random range
522 pub seed: u32
523}
524
525#[repr(C)]
526pub struct BMTxTaskRndIdPattern {
527 /// Minimum value of the Increment range
528 pub min: u32,
529 /// Maximum value of the Increment range
530 pub max: u32,
531 /// Seed of the Random range
532 pub seed: u32
533}
534
535/// CAN channel TX task item structure, used by [super::api::BM_SetTxTasks]
536/// Once the CAN device is armed with TX tasks, it will try to parse the TX task and send CAN messages automatically.
537/// The difference with a software triggered CAN message in BusMaster is that hardware triggered CAN messages are
538/// more precise in time and could reach a higher throughput.
539#[repr(C)]
540pub struct BMTxTask {
541 /// Type ID of the TX task, see [BMTxTaskType] for details.
542 pub kind: u8,
543 /// Reserved
544 pub unused: u8,
545 /// CAN message control Flags, see [BMMessageFlags] for details.
546 pub flags: u8,
547 /// Length of payload in bytes (not DLC)
548 pub length: u8,
549 /// Index of E2E (in E2E table, currently unsupported
550 pub e2e: u8,
551 /// Reserved
552 pub reserved: u8,
553 /// ms delay between rounds
554 pub cycle: u16,
555 /// num of cycles
556 pub n_rounds: u16,
557 /// messages per round
558 pub n_messages: u16,
559 /// CAN message arbitration ID, see [BMMessageId] for details.
560 pub id: u32,
561 /// TX task pattern data
562 pub pattern: u32,
563 //TODO
564 /// Default payload data, note this is also the template payload of the unchanged part in a volatile TX task
565 pub payload: [u8; 64]
566}
567
568/// ISO-TP status report, used by ISO-TP operation callback function.
569#[repr(C)]
570pub struct BMIsoTPStatus {
571 /// Currently always 0x01
572 pub version: u8,
573 /// Current flow control status, 0=continue, 1=wait, 2=overflow, ff=timeout,
574 pub flow_control: u8,
575 /// Current flow control status, i.e. 30 00 00
576 pub st_min: u8,
577 /// Current block size
578 pub block_size: u8,
579 /// Number of transferred bytes by now.
580 pub transferred_bytes: u32,
581 /// Number of total bytes indicated by ISO-TP FF or SF.
582 pub total_bytes: u32,
583 /// Current timestamp reported by device.
584 pub timestamp: u32,
585 /// Reserved for future.
586 pub reserved: [u32; 4]
587}
588
589/// Callback type for ISO-TP status callback
590type BMIsotpCallbackHandle = extern fn(status: *const BMIsoTPStatus, arg: *const c_void);
591
592#[repr(C)]
593pub struct BMIsotpTimeoutConfig {
594 /// `A` timeout in milliseconds: `=N_As` if writing as tester or reading as ECU, otherwise `=N_Ar`
595 pub a: u16,
596 /// `B` timeout in milliseconds: `=N_Bs` if writing as tester or reading as ECU, otherwise `=N_Br`
597 pub b: u16,
598 /// `C` timeout in milliseconds: `=N_Cs` if writing as tester or reading as ECU, otherwise `=N_Cr`
599 pub c: u16
600}
601
602
603#[repr(C)]
604pub struct BMIsotpFlowControlConfig {
605 /// STmin raw value (0x00-0x7F or 0xF1-0xF9) if Busmust device is acting as UDS server
606 pub st_min: u8,
607 /// Block size if CAN card is acting as UDS server, 0 means no further FC is needed
608 pub block_size: u8,
609 /// Flow control frame length in bytes
610 pub fc_frame_length: u8,
611 /// Reserved
612 pub reserved: u8
613}
614
615#[repr(C)]
616/// ISOTP Protocol (See ISO15765-2 for details) configuration.
617pub struct BMIsotpConfig {
618 /// Currently must be set to 0x01
619 pub version: u8,
620 /// Currently only 0 is supported: normal (non-extended-addressing) UDS client(tester)
621 pub mode: u8,
622 /// Tester(UDS Client) Timeout configuration
623 pub tester_timeout: BMIsotpTimeoutConfig,
624 /// ECU(UDS Server) Timeout configuration
625 pub ecu_timeout: BMIsotpTimeoutConfig,
626 /// Current flow control status, i.e. 30 00 00
627 pub flow_control: BMIsotpFlowControlConfig,
628 /// UDS Address in Extended Addressing mode
629 pub extended_address: u8,
630 /// Enable padding for unused payload bytes
631 pub padding_enabled: u8,
632 /// Padding byte value (i.e. 0xCC) for unused payload bytes
633 pub padding_value: u8,
634 /// Enable long PDU (>4095), note if CAN message DLC>8, long PDU is enabled by default
635 pub long_pdu_enabled: u8,
636 /// Reserved for future
637 pub padding: [u8; 2],
638 /// Callback function when any progress is made, used typically by GUI to show progress bar
639 pub callback: BMIsotpCallbackHandle,
640 /// Callback user arg when any progress is made, used typically by GUI to show progress bar
641 pub callback_user_arg: *const c_void,
642 /// All tester messages will be formatted/checked using this template, configure CAN message ID and IDE/FDF flags here
643 pub tester_data_template: BMData,
644 /// All ECU messages will be formatted/checked using this template, configure CAN message ID and IDE/FDF flags here
645 pub ecu_data_template: BMData
646}