Compare commits

..

3 Commits

Author SHA1 Message Date
Nik
16eebea2fb patterns: Added USB Descriptor pattern 2022-10-09 12:46:29 +02:00
Florian Limberger
6cb208d975 patterns: Added pattern for ID3 tags (#48)
* Add naive first implementation of ID3 patterns

* Refine string handling a bit

* Optimize structs using the static keyword

* Add MIME type pragma and update README
2022-10-09 12:26:34 +02:00
Nik
665c50b914 patterns: Fixed minidump pattern formatting 2022-10-08 11:20:46 +02:00
5 changed files with 567 additions and 140 deletions

View File

@@ -45,6 +45,7 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed
| BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format |
| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format |
| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files |
| ID3 | `audio/mpeg` | [`patterns/id3tag.hexpat`](patterns/id3tag.hexpat) | ID3 tags in MP3 files |
### Scripts

156
patterns/id3.hexpat Normal file
View File

@@ -0,0 +1,156 @@
#pragma MIME audio/mpeg
#include <std/mem.pat>
namespace v1 {
struct Tag {
char header[3];
char title[30];
char artist[30];
char album[30];
char year[4];
char comment[30];
u8 zero;
u8 track;
u8 genre;
} [[static]];
}
namespace v2 {
struct SyncSafeInt {
u8 bytes[4];
} [[sealed, static, format("v2::ssi_value"), transform("v2::ssi_value")]];
fn ssi_value(ref SyncSafeInt n) {
u32 result = 0;
for (u8 i = 0, i < 4, i = i + 1) {
u8 byteval = n.bytes[i] & 0x7F;
u8 shift = 7 * (4 - i - 1);
result = result | (byteval << shift);
}
return result;
};
struct TagVersion {
u8 major;
u8 revision;
};
bitfield TagHeaderFlags {
unsynchronized : 1;
extended : 1;
experimental : 1;
footer : 1;
padding : 4;
};
struct TagHeader {
char identifier[3];
TagVersion version;
TagHeaderFlags flags;
SyncSafeInt size;
} [[static]];
bitfield ExtendedFlag {
padding : 1;
update : 1;
crcpresent : 1;
restrictions : 1;
padding : 4;
};
struct TagExtendedHeader {
SyncSafeInt size;
u8 nflagbytes;
ExtendedFlag flags[nflagbytes];
u8 data[size];
};
struct TagFooter {
char identifier[3];
TagVersion version;
TagHeaderFlags flags;
SyncSafeInt size;
} [[static]];
bitfield FrameFlags {
padding : 1;
tagalterpreservation : 1;
filealterpreservation : 1;
readonly : 1;
padding : 5;
groupid : 1;
padding : 2;
compressed : 1;
encrypted : 1;
unzynchronized : 1;
datalengthindicator : 1;
};
enum TextEncoding : u8 {
ISO88591 = 0x00,
UTF16BOM = 0x01,
UTF16BE = 0x02,
UTF8 = 0x03,
};
struct StringData {
TextEncoding encoding;
if (encoding == TextEncoding::UTF16BOM) {
u16 bom;
char16 data[(parent.size - 3) / 2];
} else if (encoding == TextEncoding::UTF16BE)
be char16 data[(parent.size - 1) / 2];
else
char data[parent.size - 1];
};
// Hack to work around the fact, that chars may not be compared
union FrameId {
char cdata[4];
u8 ndata[4];
} [[sealed, static, format("v2::impl::format_frame_id")]];
namespace impl {
fn format_frame_id(ref FrameId id) {
return id.cdata;
};
}
struct Frame {
FrameId id;
SyncSafeInt size;
FrameFlags flags;
if (id.ndata[0] == 'T')
StringData data;
else
u8 data[size];
};
fn has_next_frame(u32 size) {
bool hasnext = $ < size;
if (hasnext) {
hasnext = std::mem::read_unsigned($, 1) != 0;
$ = $ - 1;
}
return hasnext;
};
struct Tag {
TagHeader header;
if (header.flags.extended)
TagExtendedHeader extendedheader;
Frame frames[while(v2::has_next_frame(header.size))];
if (header.flags.footer)
TagFooter footer;
};
}
v2::Tag tag @ 0;
v1::Tag oldtag @ std::mem::size() - 128;

View File

@@ -8,50 +8,50 @@ using RVA = ULONG32;
using RVA64 = ULONG64;
enum MINIDUMP_STREAM_TYPE : ULONG32 {
UnusedStream = 0,
ReservedStream0 = 1,
ReservedStream1 = 2,
ThreadListStream = 3,
ModuleListStream = 4,
MemoryListStream = 5,
ExceptionStream = 6,
SystemInfoStream = 7,
ThreadExListStream = 8,
Memory64ListStream = 9,
CommentStreamA = 10,
CommentStreamW = 11,
HandleDataStream = 12,
FunctionTableStream = 13,
UnloadedModuleListStream = 14,
MiscInfoStream = 15,
MemoryInfoListStream = 16,
ThreadInfoListStream = 17,
HandleOperationListStream = 18,
TokenStream = 19,
JavaScriptDataStream = 20,
SystemMemoryInfoStream = 21,
ProcessVmCountersStream = 22,
IptTraceStream = 23,
ThreadNamesStream = 24,
ceStreamNull = 0x8000,
ceStreamSystemInfo = 0x8001,
ceStreamException = 0x8002,
ceStreamModuleList = 0x8003,
ceStreamProcessList = 0x8004,
ceStreamThreadList = 0x8005,
ceStreamThreadContextList = 0x8006,
ceStreamThreadCallStackList = 0x8007,
ceStreamMemoryVirtualList = 0x8008,
ceStreamMemoryPhysicalList = 0x8009,
ceStreamBucketParameters = 0x800A,
ceStreamProcessModuleMap = 0x800B,
ceStreamDiagnosisList = 0x800C,
LastReservedStream = 0xFFFF
UnusedStream = 0,
ReservedStream0 = 1,
ReservedStream1 = 2,
ThreadListStream = 3,
ModuleListStream = 4,
MemoryListStream = 5,
ExceptionStream = 6,
SystemInfoStream = 7,
ThreadExListStream = 8,
Memory64ListStream = 9,
CommentStreamA = 10,
CommentStreamW = 11,
HandleDataStream = 12,
FunctionTableStream = 13,
UnloadedModuleListStream = 14,
MiscInfoStream = 15,
MemoryInfoListStream = 16,
ThreadInfoListStream = 17,
HandleOperationListStream = 18,
TokenStream = 19,
JavaScriptDataStream = 20,
SystemMemoryInfoStream = 21,
ProcessVmCountersStream = 22,
IptTraceStream = 23,
ThreadNamesStream = 24,
ceStreamNull = 0x8000,
ceStreamSystemInfo = 0x8001,
ceStreamException = 0x8002,
ceStreamModuleList = 0x8003,
ceStreamProcessList = 0x8004,
ceStreamThreadList = 0x8005,
ceStreamThreadContextList = 0x8006,
ceStreamThreadCallStackList = 0x8007,
ceStreamMemoryVirtualList = 0x8008,
ceStreamMemoryPhysicalList = 0x8009,
ceStreamBucketParameters = 0x800A,
ceStreamProcessModuleMap = 0x800B,
ceStreamDiagnosisList = 0x800C,
LastReservedStream = 0xFFFF
};
struct MINIDUMP_LOCATION_DESCRIPTOR {
type::Size32 DataSize;
RVA Rva;
type::Size32 DataSize;
RVA Rva;
};
struct MINIDUMP_MEMORY_DESCRIPTOR {
@@ -70,24 +70,24 @@ struct MINIDUMP_THREAD {
};
struct MINIDUMP_THREAD_LIST {
ULONG32 NumberOfThreads;
MINIDUMP_THREAD Threads[NumberOfThreads];
ULONG32 NumberOfThreads;
MINIDUMP_THREAD Threads[NumberOfThreads];
};
struct VS_FIXEDFILEINFO {
DWORD dwSignature;
DWORD dwStrucVersion;
DWORD dwFileVersionMS;
DWORD dwFileVersionLS;
DWORD dwProductVersionMS;
DWORD dwProductVersionLS;
DWORD dwFileFlagsMask;
DWORD dwFileFlags;
DWORD dwFileOS;
DWORD dwFileType;
DWORD dwFileSubtype;
DWORD dwFileDateMS;
DWORD dwFileDateLS;
DWORD dwSignature;
DWORD dwStrucVersion;
DWORD dwFileVersionMS;
DWORD dwFileVersionLS;
DWORD dwProductVersionMS;
DWORD dwProductVersionLS;
DWORD dwFileFlagsMask;
DWORD dwFileFlags;
DWORD dwFileOS;
DWORD dwFileType;
DWORD dwFileSubtype;
DWORD dwFileDateMS;
DWORD dwFileDateLS;
};
struct MINIDUMP_MODULE {
@@ -101,12 +101,12 @@ struct MINIDUMP_MODULE {
MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
ULONG64 Reserved0;
ULONG64 Reserved1;
char16 ModuleName[] @ ModuleNameRva + 4 [[hidden]];
} [[format("format_module")]];
fn format_module(ref MINIDUMP_MODULE module) {
return module.ModuleName;
return module.ModuleName;
};
struct MINIDUMP_MODULE_LIST {
@@ -137,10 +137,10 @@ struct MINIDUMP_EXCEPTION_STREAM {
};
struct CPU_INFORMATION {
ULONG32 VendorId[3];
ULONG32 VersionInformation;
ULONG32 FeatureInformation;
ULONG32 AMDExtendedCpuFeatures;
ULONG32 VendorId[3];
ULONG32 VersionInformation;
ULONG32 FeatureInformation;
ULONG32 AMDExtendedCpuFeatures;
};
struct MINIDUMP_SYSTEM_INFO {
@@ -235,7 +235,7 @@ struct MINIDUMP_FUNCTION_TABLE_STREAM {
type::Size32 SizeOfFunctionEntry;
ULONG32 NumberOfDescriptors;
ULONG32 SizeOfAlignPad;
MINIDUMP_FUNCTION_TABLE_DESCRIPTOR FunctionDescriptors[NumberOfDescriptors];
};
@@ -245,19 +245,19 @@ struct MINIDUMP_UNLOADED_MODULE {
ULONG32 CheckSum;
ULONG32 TimeDateStamp;
RVA ModuleNameRva;
char16 ModuleName[] @ ModuleNameRva + 4 [[hidden]];
} [[format("format_unloaded_module")]];
fn format_unloaded_module(ref MINIDUMP_UNLOADED_MODULE module) {
return module.ModuleName;
return module.ModuleName;
};
struct MINIDUMP_UNLOADED_MODULE_LIST {
ULONG32 SizeOfHeader;
ULONG32 SizeOfEntry;
ULONG32 NumberOfEntries;
if (SizeOfHeader > 12)
padding[header.SizeOfHeader - 12];
@@ -271,7 +271,7 @@ struct MINIDUMP_MISC_INFO {
ULONG32 ProcessCreateTime;
ULONG32 ProcessUserTime;
ULONG32 ProcessKernelTime;
if (SizeOfInfo > 24) {
ULONG32 ProcessorMaxMhz;
ULONG32 ProcessorCurrentMhz;
@@ -297,7 +297,7 @@ struct MINIDUMP_MEMORY_INFO_LIST {
ULONG SizeOfHeader;
ULONG SizeOfEntry;
ULONG64 NumberOfEntries;
if (SizeOfHeader > 16)
padding[SizeOfHeader - 16];
@@ -321,7 +321,7 @@ struct MINIDUMP_THREAD_INFO_LIST {
ULONG SizeOfHeader;
ULONG SizeOfEntry;
ULONG NumberOfEntries;
if (SizeOfHeader > 12)
padding[SizeOfHeader - 12];
@@ -336,88 +336,88 @@ struct MINIDUMP_HANDLE_OPERATION_LIST {
};
struct MINIDUMP_DIRECTORY {
MINIDUMP_STREAM_TYPE StreamType;
MINIDUMP_LOCATION_DESCRIPTOR Location;
if (StreamType == MINIDUMP_STREAM_TYPE::ThreadListStream)
MINIDUMP_THREAD_LIST ThreadList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ModuleListStream)
MINIDUMP_MODULE_LIST ModuleList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MemoryListStream)
MINIDUMP_MEMORY_LIST MemoryList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ExceptionStream)
MINIDUMP_EXCEPTION_STREAM ExceptionInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::SystemInfoStream)
MINIDUMP_SYSTEM_INFO SystemInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ThreadExListStream)
MINIDUMP_THREAD_EX_LIST ThreadExList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::Memory64ListStream)
MINIDUMP_MEMORY64_LIST Mem64List @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::CommentStreamA)
char Comment[] @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::CommentStreamW)
char16 Comment[] @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::HandleDataStream)
MINIDUMP_HANDLE_DATA_STREAM HandleData @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::FunctionTableStream)
MINIDUMP_FUNCTION_TABLE_STREAM FunctionTable @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::UnloadedModuleListStream)
MINIDUMP_UNLOADED_MODULE_LIST UnloadModuleList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MiscInfoStream)
MINIDUMP_MISC_INFO MiscInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MemoryInfoListStream)
MINIDUMP_MEMORY_INFO_LIST MemInfoList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ThreadInfoListStream)
MINIDUMP_THREAD_INFO_LIST ThreadInfoList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::HandleOperationListStream)
MINIDUMP_HANDLE_OPERATION_LIST HandleOperList @ Location.Rva;
MINIDUMP_STREAM_TYPE StreamType;
MINIDUMP_LOCATION_DESCRIPTOR Location;
if (StreamType == MINIDUMP_STREAM_TYPE::ThreadListStream)
MINIDUMP_THREAD_LIST ThreadList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ModuleListStream)
MINIDUMP_MODULE_LIST ModuleList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MemoryListStream)
MINIDUMP_MEMORY_LIST MemoryList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ExceptionStream)
MINIDUMP_EXCEPTION_STREAM ExceptionInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::SystemInfoStream)
MINIDUMP_SYSTEM_INFO SystemInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ThreadExListStream)
MINIDUMP_THREAD_EX_LIST ThreadExList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::Memory64ListStream)
MINIDUMP_MEMORY64_LIST Mem64List @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::CommentStreamA)
char Comment[] @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::CommentStreamW)
char16 Comment[] @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::HandleDataStream)
MINIDUMP_HANDLE_DATA_STREAM HandleData @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::FunctionTableStream)
MINIDUMP_FUNCTION_TABLE_STREAM FunctionTable @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::UnloadedModuleListStream)
MINIDUMP_UNLOADED_MODULE_LIST UnloadModuleList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MiscInfoStream)
MINIDUMP_MISC_INFO MiscInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MemoryInfoListStream)
MINIDUMP_MEMORY_INFO_LIST MemInfoList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ThreadInfoListStream)
MINIDUMP_THREAD_INFO_LIST ThreadInfoList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::HandleOperationListStream)
MINIDUMP_HANDLE_OPERATION_LIST HandleOperList @ Location.Rva;
};
bitfield MINIDUMP_TYPE {
MiniDumpWithDataSegs : 1;
MiniDumpWithFullMemory : 1;
MiniDumpWithHandleData : 1;
MiniDumpFilterMemory : 1;
MiniDumpScanMemory : 1;
MiniDumpWithUnloadedModules : 1;
MiniDumpWithIndirectlyReferencedMemory : 1;
MiniDumpFilterModulePaths : 1;
MiniDumpWithProcessThreadData : 1;
MiniDumpWithPrivateReadWriteMemory : 1;
MiniDumpWithoutOptionalData : 1;
MiniDumpWithFullMemoryInfo : 1;
MiniDumpWithThreadInfo : 1;
MiniDumpWithCodeSegs : 1;
MiniDumpWithoutAuxiliaryState : 1;
MiniDumpWithFullAuxiliaryState : 1;
MiniDumpWithPrivateWriteCopyMemory : 1;
MiniDumpIgnoreInaccessibleMemory : 1;
MiniDumpWithTokenInformation : 1;
MiniDumpWithModuleHeaders : 1;
MiniDumpFilterTriage : 1;
MiniDumpWithAvxXStateContext : 1;
MiniDumpWithIptTrace : 1;
MiniDumpScanInaccessiblePartialPages : 1;
padding : 40;
MiniDumpWithDataSegs : 1;
MiniDumpWithFullMemory : 1;
MiniDumpWithHandleData : 1;
MiniDumpFilterMemory : 1;
MiniDumpScanMemory : 1;
MiniDumpWithUnloadedModules : 1;
MiniDumpWithIndirectlyReferencedMemory : 1;
MiniDumpFilterModulePaths : 1;
MiniDumpWithProcessThreadData : 1;
MiniDumpWithPrivateReadWriteMemory : 1;
MiniDumpWithoutOptionalData : 1;
MiniDumpWithFullMemoryInfo : 1;
MiniDumpWithThreadInfo : 1;
MiniDumpWithCodeSegs : 1;
MiniDumpWithoutAuxiliaryState : 1;
MiniDumpWithFullAuxiliaryState : 1;
MiniDumpWithPrivateWriteCopyMemory : 1;
MiniDumpIgnoreInaccessibleMemory : 1;
MiniDumpWithTokenInformation : 1;
MiniDumpWithModuleHeaders : 1;
MiniDumpFilterTriage : 1;
MiniDumpWithAvxXStateContext : 1;
MiniDumpWithIptTrace : 1;
MiniDumpScanInaccessiblePartialPages : 1;
padding : 40;
} [[right_to_left]];
struct MINIDUMP_HEADER {
char Signature[4];
ULONG32 Version;
ULONG32 NumberOfStreams;
RVA StreamDirectoryRva;
ULONG32 Checksum;
type::time32_t TimeDateStamp;
MINIDUMP_TYPE Flags;
char Signature[4];
ULONG32 Version;
ULONG32 NumberOfStreams;
RVA StreamDirectoryRva;
ULONG32 Checksum;
type::time32_t TimeDateStamp;
MINIDUMP_TYPE Flags;
};
struct MINIDUMP {
MINIDUMP_HEADER Header;
MINIDUMP_DIRECTORY Streams[Header.NumberOfStreams] [[format_entries("format_stream")]];
MINIDUMP_HEADER Header;
MINIDUMP_DIRECTORY Streams[Header.NumberOfStreams] [[format_entries("format_stream")]];
};
fn format_stream(ref MINIDUMP_DIRECTORY stream) {
return stream.StreamType;
return stream.StreamType;
};
MINIDUMP MiniDump @ 0x00;
MINIDUMP MiniDump @ 0x00;

270
patterns/usb.hexpat Normal file
View File

@@ -0,0 +1,270 @@
#include <std/io.pat>
#include <std/mem.pat>
#include <std/string.pat>
enum DescriptorType : u8 {
DeviceDescriptor = 0x01,
ConfigDescriptor = 0x02,
StringDescriptor = 0x03,
InterfaceDescriptor = 0x04,
EndpointDescriptor = 0x05,
DeviceQualifierDescriptor = 0x06,
OtherSpeedConfigurationDescriptor = 0x07,
InterfacePowerDescriptor = 0x08,
OTGDescriptor = 0x09,
DebugDescriptor = 0x0A,
InterfaceAssociationDescriptor = 0x0B,
HIDDescriptor = 0x21,
ReportDescriptor = 0x22,
PhysicalDescriptor = 0x23
};
enum InterfaceClass : u8 {
UseClassInformationInInterfaceDescriptors = 0x00,
Audio = 0x01,
CommunicationAndCDCControl = 0x02,
HID = 0x03,
Physical = 0x05,
Image = 0x06,
Printer = 0x07,
MassStorage = 0x08,
Hub = 0x09,
CDCData = 0x0A,
SmartCard = 0x0B,
ContentSecurity = 0x0C,
Video = 0x0E,
PersonalHealthcare = 0x0F,
AudioVideoDevice = 0x10,
BillboardDevice = 0x11,
USBTypeCBridge = 0x12,
I3CDevice = 0x3C,
DiagnosticDevice = 0xDC,
WirelessController = 0xE0,
Miscellaneous = 0xEF,
ApplicationSpecific = 0xFE,
VendorSpecific = 0xFF
};
enum CountryCode : u8 {
NotSupported = 0,
Arabic = 1,
Belgian = 2,
CanadianBilingual = 3,
CanadianFrench = 4,
CzechRepublic = 5,
Danish = 6,
Finnish = 7,
French = 8,
German = 9,
Greek = 10,
Hebrew = 11,
Hungary = 12,
International = 13,
Italian = 14,
JapanKatakana = 15,
Korean = 16,
LatinAmerican = 17,
Dutch = 18,
Norwegian = 19,
PersianFarsi = 20,
Polish = 21,
Portuguese = 22,
Russian = 23,
Slovakian = 24,
Spanish = 25,
Swedish = 26,
SwissFrench = 27,
SwissGerman = 28,
Switzerland = 29,
Taiwan = 30,
TurkishQ = 31,
EnglishUK = 32,
EnglishUS = 33,
Yugoslavian = 34,
TurkishF = 35,
Reserved = 36 ... 255
};
enum HubInterfaceSubClass : u8 {
Hub = 0x00
};
enum AudioVideoDeviceSubClass : u8 {
AVControlInterface = 0x01,
AVDataVideoStreamingInterface = 0x02,
AVDataAudioStreamingInterface = 0x03
};
enum HubInterfaceProtocol : u8 {
FullSpeedHub = 0x00,
HiSpeedHubWithSingleTT = 0x01,
HiSpeedHubWithMultipleTTs = 0x02
};
struct Ampere {
u8 amps;
} [[sealed, format("format_ampere")]];
fn format_ampere(Ampere ampere) {
return std::format("{} mA", ampere.amps * 2);
};
bitfield ConfigAttributes {
padding : 1;
SelfPowered : 1;
RemoteWakeup : 1;
padding : 5;
} [[left_to_right]];
struct BCD<auto Size> {
u8 bytes[Size];
} [[sealed, format("format_bcd")]];
fn format_bcd(ref auto bcd) {
str result;
for (s8 i = sizeof(bcd.bytes) - 1, i >= 0, i -= 1)
result += std::format("{:X}.", bcd.bytes[i]);
return std::string::substr(result, 0, std::string::length(result) - 1);
};
struct DeviceDescriptor {
BCD<2> bcdUSB;
InterfaceClass bDeviceClass;
if (bDeviceClass == InterfaceClass::Hub) {
HubInterfaceSubClass bDeviceSubClass;
if (bDeviceSubClass == HubInterfaceSubClass::Hub)
HubInterfaceProtocol bDeviceSubClass;
else
u8 bDeviceSubClass;
} else if (bDeviceClass == InterfaceClass::AudioVideoDevice) {
AudioVideoDeviceSubClass bDeviceSubClass;
u8 bDeviceSubClass;
} else {
u8 bDeviceSubClass;
u8 bDeviceSubClass;
}
};
struct ConfigDescriptor {
u16 wTotalLength;
u8 bNumInterfaces;
u8 bConfigurationValue;
u8 iConfiguration;
ConfigAttributes bmAttributes;
Ampere bMaxPower;
};
struct StringDescriptor {
char bString[parent.bLength - 2];
};
struct InterfaceDescriptor {
u8 bInterfaceNumber;
u8 bAlternateSetting;
u8 bNumEndpoints;
InterfaceClass bInterfaceClass;
if (bInterfaceClass == InterfaceClass::Hub) {
HubInterfaceSubClass bInterfaceSubClass;
if (bInterfaceSubClass == HubInterfaceSubClass::Hub)
HubInterfaceProtocol bInterfaceProtocol;
else
u8 bInterfaceProtocol;
} else if (bInterfaceClass == InterfaceClass::AudioVideoDevice) {
AudioVideoDeviceSubClass bInterfaceSubClass;
u8 bInterfaceProtocol;
} else {
u8 bInterfaceSubClass;
u8 bInterfaceProtocol;
}
u8 iInterface;
};
enum EndpointDirection : u8 {
OUT = 0,
IN = 1
};
fn format_direction(u8 value) {
EndpointDirection direction;
direction = value;
return direction;
};
bitfield EndpointAddress {
Direction : 1 [[format("format_direction")]];
padding : 3;
EndpointNumber : 4;
} [[left_to_right]];
bitfield EndpointAttributes {
TransferType : 2;
SynchronizationType : 2;
UsageType : 2;
} [[right_to_left]];
struct EndpointDescriptor {
EndpointAddress bEndPointAddress;
EndpointAttributes bmAttributes;
u16 wMaxPacketSize;
u8 bInterval;
};
struct OtherSpeedConfigurationDescriptor {
ConfigDescriptor content [[inline]];
};
struct DeviceQualifierDescriptor {
DeviceDescriptor deviceDescriptor [[inline]];
u8 bMaxPacketSize0;
u8 bNumConfigurations;
padding[1];
};
bitfield OTGAttributes {
SRPSupport : 1;
HNPSupport : 1;
} [[right_to_left]];
struct OTGDescriptor {
OTGAttributes bmAttributes;
};
struct HIDDescriptor {
BCD<2> bcdVersion;
CountryCode bCountryCode;
u8 bNumDescriptors;
DescriptorType bDescriptorType;
u16 wDescriptorLength;
};
struct USBDescriptor {
u8 bLength;
DescriptorType bDescriptorType;
if (bDescriptorType == DescriptorType::DeviceDescriptor)
DeviceDescriptor deviceDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::ConfigDescriptor)
ConfigDescriptor configDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::StringDescriptor)
StringDescriptor stringDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::InterfaceDescriptor)
InterfaceDescriptor interfaceDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::EndpointDescriptor)
EndpointDescriptor endpointDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::OtherSpeedConfigurationDescriptor)
OtherSpeedConfigurationDescriptor otherSpeedConfigurationDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::DeviceQualifierDescriptor)
DeviceQualifierDescriptor deviceQualifierDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::OTGDescriptor)
OTGDescriptor otgDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::HIDDescriptor)
HIDDescriptor hidDescriptor [[inline]];
padding[bLength - ($ - addressof(this))];
};
USBDescriptor descriptors[while(!std::mem::eof())] @ 0x00;

Binary file not shown.