| 15 | } |
| 16 | |
| 17 | pub fn get_serialnum() -> Option<SerialnumStruct> { |
| 18 | // Flash is mapped into memory, just read it from there |
| 19 | let ptr: *const u8 = (FLASH_OFFSET + LAST_4K_BLOCK) as *const u8; |
| 20 | let sn_raw_ptr = ptr as *const SerialnumStructRaw; |
| 21 | let sn_raw = unsafe { sn_raw_ptr.as_ref()? }; |
| 22 | |
| 23 | // Only rev 1 supported |
| 24 | if sn_raw.sn_rev != 1 { |
| 25 | return None; |
| 26 | } |
| 27 | |
| 28 | let crc: crc::Crc<u32> = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC); |
| 29 | let mut digest = crc.digest(); |
| 30 | digest.update(&[sn_raw.sn_rev]); |
| 31 | digest.update(&sn_raw.serialnum); |
| 32 | let calc_checksum = digest.finalize(); |
| 33 | |
| 34 | let actual_checksum = u32::from_le_bytes(sn_raw.crc32); |
| 35 | // Checksum invalid, serial fall back to default serial number |
| 36 | if calc_checksum != actual_checksum { |
| 37 | return None; |
| 38 | } |
| 39 | |
| 40 | Some(SerialnumStruct { |
| 41 | serialnum: core::str::from_utf8(&sn_raw.serialnum).ok()?, |
| 42 | }) |
| 43 | } |
| 44 | |
| 45 | /// Get the firmware version in a format for USB Device Release |
| 46 | /// The value is in binary coded decimal with a format of 0xJJMN where JJ is the major version number, M is the minor version number and N is the sub minor version number. e.g. USB 2.0 is reported as 0x0200, USB 1.1 as 0x0110 and USB 1.0 as 0x0100. |