Implement serial reconf

This commit is contained in:
Alexey Ryabov 2025-05-22 21:26:05 +05:00
parent 7e63294b5e
commit 2dfb3ddff3
No known key found for this signature in database
GPG Key ID: B0DED46F6BB8B3DC
4 changed files with 124 additions and 34 deletions

View File

@ -1,3 +1,5 @@
SERIAL_COMPATIBLE_API_VER = 0 ; increments in case of breaking changes
SERIAL_API_GET_VERSION = 0 SERIAL_API_GET_VERSION = 0
SERIAL_API_SRV_ADD_PORT = 1 SERIAL_API_SRV_ADD_PORT = 1
SERIAL_API_SRV_REMOVE_PORT = 2 SERIAL_API_SRV_REMOVE_PORT = 2
@ -21,14 +23,18 @@ SERIAL_CONF_PARITY_ODD = 2
SERIAL_CONF_PARITY_MARK = 3 SERIAL_CONF_PARITY_MARK = 3
SERIAL_CONF_PARITY_SPACE = 4 SERIAL_CONF_PARITY_SPACE = 4
SERIAL_CONF_STOP_BITS_1 = 0
SERIAL_CONF_STOP_BITS_1_5 = 1
SERIAL_CONF_STOP_BITS_2 = 2
SERIAL_CONF_FLOW_CTRL_NONE = 0 SERIAL_CONF_FLOW_CTRL_NONE = 0
struct SP_DRIVER struct SP_DRIVER
size dd ? ; size of this struct size dd ? ; size of this struct
startup dd ? ; void __stdcall (*startup)(void *drv_data, const struct serial_conf *conf); startup dd ? ; int __stdcall (*startup)(void *drv_data, const struct serial_conf *conf);
shutdown dd ? ; void __stdcall (*shutdown)(void *drv_data); shutdown dd ? ; int __stdcall (*shutdown)(void *drv_data);
reconf dd ? ; void __stdcall (*reconf)(void *drv_data, const struct serial_conf *conf); reconf dd ? ; int __stdcall (*reconf)(void *drv_data, const struct serial_conf *conf);
tx dd ? ; void __stdcall (*tx)(void *drv_data); tx dd ? ; int __stdcall (*tx)(void *drv_data);
ends ends
struct SP_CONF struct SP_CONF
@ -123,6 +129,30 @@ proc serial_port_init
ret ret
endp endp
proc serial_port_get_version stdcall, version:dword
locals
.handler dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
endl
mov eax, [serial_drv_handle]
mov [.handler], eax
mov dword [.io_code], SERIAL_API_GET_VERSION
mov [.input], 0
mov dword [.inp_size], 0
mov eax, [version]
mov [.output], eax
mov dword [.out_size], 4
lea ecx, [.handler]
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
ret
endp
proc serial_port_open stdcall uses ebx, port_id:dword, conf:dword, handle:dword proc serial_port_open stdcall uses ebx, port_id:dword, conf:dword, handle:dword
locals locals
.handler dd ? .handler dd ?

View File

@ -9,8 +9,6 @@ __DEBUG_LEVEL__ = L_DBG
SERIAL_RING_BUF_SIZE = 32768 SERIAL_RING_BUF_SIZE = 32768
API_VERSION = 1
section '.flat' readable writable executable section '.flat' readable writable executable
include '../struct.inc' include '../struct.inc'
@ -23,6 +21,9 @@ include 'common.inc'
include 'ring_buf.inc' include 'ring_buf.inc'
include 'uart16550.inc' include 'uart16550.inc'
CURRENT_API = 0x0001
API_VERSION = (SERIAL_COMPATIBLE_API_VER shl 16) + CURRENT_API
struct SERIAL_OBJ struct SERIAL_OBJ
magic dd ? magic dd ?
destroy dd ? destroy dd ?
@ -45,7 +46,7 @@ struct SERIAL_PORT
conf SP_CONF conf SP_CONF
ends ends
proc START c, reason:dword proc START c, reason:dword, cmdline:dword
cmp [reason], DRV_ENTRY cmp [reason], DRV_ENTRY
jne .fail jne .fail
@ -347,15 +348,12 @@ proc sp_validate_conf
mov eax, [ecx + SP_CONF.baudrate] mov eax, [ecx + SP_CONF.baudrate]
test eax, eax test eax, eax
jz .fail jz .fail
mov al, [ecx + SP_CONF.word_size]
cmp al, 8
jne .fail ; TODO implement different word size
mov al, [ecx + SP_CONF.stop_bits] mov al, [ecx + SP_CONF.stop_bits]
cmp al, 1 cmp al, SERIAL_CONF_STOP_BITS_2
jne .fail ; TODO implement different stop bits count ja .fail
mov al, [ecx + SP_CONF.parity] mov al, [ecx + SP_CONF.parity]
cmp al, SERIAL_CONF_PARITY_NONE cmp al, SERIAL_CONF_PARITY_SPACE
jne .fail ; TODO implement parity ja .fail
mov al, [ecx + SP_CONF.flow_ctrl] mov al, [ecx + SP_CONF.flow_ctrl]
cmp al, SERIAL_CONF_FLOW_CTRL_NONE cmp al, SERIAL_CONF_FLOW_CTRL_NONE
jne .fail ; TODO implement flow control jne .fail ; TODO implement flow control
@ -550,7 +548,6 @@ proc sp_setup
mov eax, [edi + SERIAL_PORT.drv] mov eax, [edi + SERIAL_PORT.drv]
mov ecx, [edi + SERIAL_PORT.drv_data] mov ecx, [edi + SERIAL_PORT.drv_data]
stdcall dword [eax + SP_DRIVER.reconf], ecx, esi stdcall dword [eax + SP_DRIVER.reconf], ecx, esi
xor eax, eax
push eax push eax
test eax, eax test eax, eax
jnz @f jnz @f

View File

@ -350,10 +350,10 @@ endl
; calc stop bits ; calc stop bits
mov bx, LCR_STOP_1 mov bx, LCR_STOP_1
mov al, [esi + SP_CONF.stop_bits] mov al, [esi + SP_CONF.stop_bits]
cmp al, 1 cmp al, SERIAL_CONF_STOP_BITS_1
je .stop_bits_ok je .stop_bits_ok
or bx, LCR_STOP_2 or bx, LCR_STOP_2
cmp al, 2 cmp al, SERIAL_CONF_STOP_BITS_2
jne .fail jne .fail
.stop_bits_ok: .stop_bits_ok:
or [lcr], bx or [lcr], bx

View File

@ -1123,11 +1123,53 @@ proc uart_shutdown stdcall uses ebx, data:dword
ret ret
endp endp
proc uart_reconf stdcall uses ebx esi, dev:dword, conf:dword proc uart_reconf stdcall uses esi, dev:dword, conf:dword
mov ebx, [dev] locals
ConfPacket rb 8
endl
mov esi, [conf] mov esi, [conf]
stdcall ftdi_set_baudrate, ebx, [esi + SP_CONF.baudrate] xor edx, edx
; TODO set word_size, parity, etc. mov al, [esi + SP_CONF.word_size]
cmp al, 7
jb .invalid
cmp al, 8
ja .invalid
mov dl, al
; odd and even parities are different from serial api
; serial api: even=1 odd=2
; ft232x api: odd=1 even=2
movzx eax, [esi + SP_CONF.parity]
cmp al, SERIAL_CONF_PARITY_SPACE
ja .invalid
cmp al, SERIAL_CONF_PARITY_ODD
ja .parity_ok
cmp al, SERIAL_CONF_PARITY_EVEN
jb .parity_ok
; swap bits
xor al, 0x3
.parity_ok:
shl eax, 8 ; parity offset
or edx, eax
movzx eax, [esi + SP_CONF.stop_bits]
cmp al, SERIAL_CONF_STOP_BITS_2
ja .invalid
shl eax, 11 ; stop bits offset
or edx, eax
mov word [ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_DATA shl 8)
mov word [ConfPacket + 2], dx
mov word [ConfPacket + 4], 0
mov word [ConfPacket + 6], 0
lea edx, [ConfPacket]
stdcall ftdi_blocking_ctrl_tranfser, [dev], edx
test eax, eax
jnz .exit
stdcall ftdi_set_baudrate, [dev], [esi + SP_CONF.baudrate]
ret
.invalid:
or eax, -1
.exit:
ret ret
endp endp
@ -1204,17 +1246,10 @@ proc uart_rx stdcall uses ebx esi, data:dword
ret ret
endp endp
proc ftdi_set_baudrate stdcall uses ebx esi edi, dev:dword, baud:dword proc ftdi_set_baudrate stdcall uses ebx, dev:dword, baud:dword
locals locals
ConfPacket rb 10 ConfPacket rb 8
EventData rd 3
endl endl
xor esi, esi
xor ecx, ecx
invoke CreateEvent
mov [EventData], eax
mov [EventData + 4], edx
mov ebx, [dev] mov ebx, [dev]
cmp [ebx + ftdi_context.chipType], TYPE_2232H cmp [ebx + ftdi_context.chipType], TYPE_2232H
jl .c_clk jl .c_clk
@ -1257,7 +1292,7 @@ endl
jmp .calcend jmp .calcend
.c_nextbaud2: .c_nextbaud2:
cmp dword [edi + 8], C_CLK / (2 * 16) cmp dword [baud], C_CLK / (2 * 16)
jl .c_nextbaud3 jl .c_nextbaud3
mov edx, 2 mov edx, 2
mov ecx, C_CLK / (2 * 16) mov ecx, C_CLK / (2 * 16)
@ -1348,16 +1383,40 @@ endl
mov word [ConfPacket + 4], cx mov word [ConfPacket + 4], cx
mov word [ConfPacket + 6], 0 mov word [ConfPacket + 6], 0
lea esi, [ConfPacket] lea ebx, [ConfPacket]
stdcall ftdi_blocking_ctrl_tranfser, [dev], ebx
ret
endp
proc ftdi_blocking_ctrl_tranfser stdcall uses ebx esi edi, dev:dword, conf:dword
; conf is a pointer to values: bmRequestType, bRequest, wValue, wIndex, wLength
locals
EventData rd 3
endl
xor esi, esi
xor ecx, ecx
invoke CreateEvent
test eax, eax
jz .exit
mov [EventData], eax
mov [EventData + 4], edx
mov eax, [dev]
mov esi, [conf]
lea edi, [EventData] lea edi, [EventData]
invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\ invoke USBControlTransferAsync, [eax + ftdi_context.nullP], esi, 0,\
0, control_callback, edi, 0 0, control_callback, edi, 0
test eax, eax test eax, eax
jz .error jz .error
mov eax, [EventData] mov eax, [EventData]
mov ebx, [EventData + 4] mov ebx, [EventData + 4]
invoke WaitEvent invoke WaitEvent
cmp [EventData + 8], 0 ; USB_STATUS_OK
jne .error
mov eax, [EventData] mov eax, [EventData]
mov ebx, [EventData + 4] mov ebx, [EventData + 4]
invoke DestroyEvent invoke DestroyEvent
@ -1365,6 +1424,10 @@ endl
ret ret
.error: .error:
mov eax, [EventData]
mov ebx, [EventData + 4]
invoke DestroyEvent
.exit:
or eax, -1 or eax, -1
ret ret
endp endp