diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 15ffa2dd3..a9ed44d8a 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -820,3 +820,147 @@ foreign kernel32 { HandlerRoutine :: proc "stdcall" (dwCtrlType: DWORD) -> BOOL PHANDLER_ROUTINE :: HandlerRoutine + + + + +DCB_Config :: struct { + fParity: bool, + fOutxCtsFlow: bool, + fOutxDsrFlow: bool, + fDtrControl: DTR_Control, + fDsrSensitivity: bool, + fTXContinueOnXoff: bool, + fOutX: bool, + fInX: bool, + fErrorChar: bool, + fNull: bool, + fRtsControl: RTS_Control, + fAbortOnError: bool, + BaudRate: DWORD, + ByteSize: BYTE, + Parity: Parity, + StopBits: Stop_Bits, + XonChar: byte, + XoffChar: byte, + ErrorChar: byte, + EvtChar: byte, +} +DTR_Control :: enum byte { + Disable = 0, + Enable = 1, + Handshake = 2, +} +RTS_Control :: enum byte { + Disable = 0, + Enable = 1, + Handshake = 2, + Toggle = 3, +} +Parity :: enum byte { + None = 0, + Odd = 1, + Even = 2, + Mark = 3, + Space = 4, +} +Stop_Bits :: enum byte { + One = 0, + One_And_A_Half = 1, + Two = 2, +} + +// A helper procedure to set the values of a DCB structure. +init_dcb_with_config :: proc "contextless" (dcb: ^DCB, config: DCB_Config) { + out: u32 + + // NOTE(tetra, 2022-09-21): On both Clang 14 on Windows, and MSVC, the bits in the bitfield + // appear to be defined from LSB to MSB order. + // i.e: `fBinary` (the first bitfield in the C source) is the LSB in the `settings` u32. + + out |= u32(1) << 0 // fBinary must always be true on Windows. + + out |= u32(config.fParity) << 1 + out |= u32(config.fOutxCtsFlow) << 2 + out |= u32(config.fOutxDsrFlow) << 3 + + out |= u32(config.fDtrControl) << 4 + + out |= u32(config.fDsrSensitivity) << 6 + out |= u32(config.fTXContinueOnXoff) << 7 + out |= u32(config.fOutX) << 8 + out |= u32(config.fInX) << 9 + out |= u32(config.fErrorChar) << 10 + out |= u32(config.fNull) << 11 + + out |= u32(config.fRtsControl) << 12 + + out |= u32(config.fAbortOnError) << 14 + + dcb.settings = out + + dcb.BaudRate = config.BaudRate + dcb.ByteSize = config.ByteSize + dcb.Parity = config.Parity + dcb.StopBits = config.StopBits + dcb.XonChar = config.XonChar + dcb.XoffChar = config.XoffChar + dcb.ErrorChar = config.ErrorChar + dcb.EvtChar = config.EvtChar + + dcb.DCBlength = size_of(DCB) +} +get_dcb_config :: proc "contextless" (dcb: DCB) -> (config: DCB_Config) { + config.fParity = bool((dcb.settings >> 1) & 0x01) + config.fOutxCtsFlow = bool((dcb.settings >> 2) & 0x01) + config.fOutxDsrFlow = bool((dcb.settings >> 3) & 0x01) + + config.fDtrControl = DTR_Control((dcb.settings >> 4) & 0x02) + + config.fDsrSensitivity = bool((dcb.settings >> 6) & 0x01) + config.fTXContinueOnXoff = bool((dcb.settings >> 7) & 0x01) + config.fOutX = bool((dcb.settings >> 8) & 0x01) + config.fInX = bool((dcb.settings >> 9) & 0x01) + config.fErrorChar = bool((dcb.settings >> 10) & 0x01) + config.fNull = bool((dcb.settings >> 11) & 0x01) + + config.fRtsControl = RTS_Control((dcb.settings >> 12) & 0x02) + + config.fAbortOnError = bool((dcb.settings >> 14) & 0x01) + + config.BaudRate = dcb.BaudRate + config.ByteSize = dcb.ByteSize + config.Parity = dcb.Parity + config.StopBits = dcb.StopBits + config.XonChar = dcb.XonChar + config.XoffChar = dcb.XoffChar + config.ErrorChar = dcb.ErrorChar + config.EvtChar = dcb.EvtChar + + return +} + +// NOTE(tetra): See get_dcb_config() and init_dcb_with_config() for help with initializing this. +DCB :: struct { + DCBlength: DWORD, // NOTE(tetra): Must be set to size_of(DCB). + BaudRate: DWORD, + settings: u32, // NOTE(tetra): These are bitfields in the C struct. + wReserved: WORD, + XOnLim: WORD, + XOffLim: WORD, + ByteSize: BYTE, + Parity: Parity, + StopBits: Stop_Bits, + XonChar: byte, + XoffChar: byte, + ErrorChar: byte, + EofChar: byte, + EvtChar: byte, + wReserved1: WORD, +} + +@(default_calling_convention="stdcall") +foreign kernel32 { + GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL --- + SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL --- +} \ No newline at end of file