Livt packages
Livt.Usb
Version 0.0.5
USB 2.0 low/full-speed PHY, host transfers, device discovery, HID keyboard, and read-only mass storage for Livt.
Published files (57)
src/packets/PacketIntegrity.lvt
namespace Livt.Usb.Packets
using Livt.Usb
/**
* USB-specific checksum conventions and final packet-shape validation.
* CRC calculation itself belongs to Livt.Utils.Hashing.Crc.
*/
component PacketIntegrity
{
// USB uses reflected CRCs with all-ones initialization and final XOR.
public const TOKEN_INITIAL: logic[5] = 0x1F
public const TOKEN_FINAL_XOR: logic[5] = 0x1F
public const DATA_INITIAL: logic[16] = 0xFFFF
public const DATA_FINAL_XOR: logic[16] = 0xFFFF
public const DATA_RESIDUE: logic[16] = 0xB001
public const TOKEN_BITS: int = 11
public const TOKEN_BYTES: uint = 3
public const DATA_OVERHEAD: uint = 3
public const LOW_SPEED_PAYLOAD_LIMIT: uint = 8
/**
* Validates an admitted PID's final byte count and checksum. Count includes
* PID/CRC; expectedToken is computed over exactly the eleven token field bits.
*/
public static fn Validate[](pid: byte, count: uint, speed: UsbSpeed,
checksum: logic[16], tokenWord: logic[16], expectedToken: logic[5]) PacketError
{
if (count == 0) {
return PacketError.Length
}
if (PacketPid.IsData(pid)) {
if (count < DATA_OVERHEAD
|| (speed == UsbSpeed.Low && count > LOW_SPEED_PAYLOAD_LIMIT + DATA_OVERHEAD)) {
return PacketError.Length
}
if (checksum != DATA_RESIDUE) {
return PacketError.Checksum
}
} elif (PacketPid.IsToken(pid)) {
if (count != TOKEN_BYTES) {
return PacketError.Length
}
if ((tokenWord >> TOKEN_BITS) != (expectedToken as logic[16])) {
return PacketError.Checksum
}
} elif (count != 1) {
return PacketError.Length
}
return PacketError.None
}
}