drivers/serial: implement serial ports enumeration (#629)
Build system / Build (es_ES) (push) Successful in 3m22s
Build system / Build (en_US) (push) Successful in 3m31s
Build system / Build (ru_RU) (push) Successful in 3m39s
Build system / Publish Images (push) Successful in 2m15s

This PR adds a new enum_ports call to the serial driver's control API that lets user-mode programs list the serial ports currently registered in the system.

It also updates debug output strings, changes the USB FTDI driver's service procedure name, and removes duplicated code from the baud rate calculation.

Reviewed-on: #629
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Reviewed-by: Burer <burer@kolibrios.org>
Co-authored-by: Alexey Ryabov <alex@b00bl1k.ru>
This commit was merged in pull request #629.
This commit is contained in:
2026-08-07 04:40:23 +00:00
committed by Burer
parent da0e6f492b
commit 2515d1fa37
6 changed files with 430 additions and 324 deletions
+59 -5
View File
@@ -1,4 +1,4 @@
SERIAL_COMPATIBLE_API_VER = 0 ; increments in case of breaking changes
SERIAL_COMPATIBLE_API_VER = 1 ; increments in case of breaking changes
SERIAL_API_GET_VERSION = 0
SERIAL_API_SRV_ADD_PORT = 1
@@ -9,6 +9,7 @@ SERIAL_API_CLOSE_PORT = 5
SERIAL_API_SETUP_PORT = 6
SERIAL_API_READ = 7
SERIAL_API_WRITE = 8
SERIAL_API_ENUM_PORTS = 9
SERIAL_API_ERR_PORT_INVALID = 1
SERIAL_API_ERR_PORT_BUSY = 2
@@ -29,6 +30,9 @@ SERIAL_CONF_STOP_BITS_2 = 2
SERIAL_CONF_FLOW_CTRL_NONE = 0
SERIAL_INFO_DRIVER_LEN = 16
SERIAL_INFO_DESCR_LEN = 64
struct SP_DRIVER
size dd ? ; size of this struct
startup dd ? ; int __stdcall (*startup)(void *drv_data, const struct serial_conf *conf);
@@ -46,7 +50,20 @@ struct SP_CONF
flow_ctrl db ?
ends
proc serial_add_port stdcall, drv:dword, drv_data:dword
struct SP_PORT_INFO
size dd ? ; size of this struct
driver dd ? ; ASCIIZ driver name, e.g. "uart16550", "usb-cdc"
descr dd ? ; ASCIIZ description, may be NULL
ends
struct SP_PORT_ENUM_ENTRY
id dd ? ; unique port number (SERIAL_PORT.id)
busy dd ? ; 0 = free, non-zero = port is opened
driver rb SERIAL_INFO_DRIVER_LEN
descr rb SERIAL_INFO_DESCR_LEN
ends
proc serial_add_port stdcall, drv:dword, drv_data:dword, info:dword
locals
handler dd ?
io_code dd ?
@@ -60,7 +77,7 @@ endl
mov [io_code], SERIAL_API_SRV_ADD_PORT
lea eax, [drv]
mov [input], eax
mov [inp_size], 8
mov [inp_size], 12
xor eax, eax
mov [output], eax
mov [out_size], eax
@@ -129,7 +146,7 @@ proc serial_port_init
ret
endp
proc serial_port_get_version stdcall, version:dword
proc serial_port_get_version stdcall uses ebx, version:dword
locals
.handler dd ?
.io_code dd ?
@@ -149,7 +166,7 @@ endl
lea ecx, [.handler]
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
ret
endp
@@ -297,6 +314,43 @@ endl
ret
endp
proc serial_port_enum stdcall uses ebx, buf:dword, buf_size:dword, \
total:dword, filled:dword
locals
.handler dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
endl
push [buf_size]
push [buf]
mov eax, [serial_drv_handle]
mov [.handler], eax
mov dword [.io_code], SERIAL_API_ENUM_PORTS
mov [.input], esp
mov dword [.inp_size], 8
sub esp, 8
mov [.output], esp
mov dword [.out_size], 8
lea ecx, [.handler]
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
pop ebx edx
cmp eax, -1
je .err
mov ecx, [total]
mov [ecx], ebx
mov ecx, [filled]
mov [ecx], edx
.err:
add esp, 8
ret
endp
align 4
serial_drv_name db "SERIAL", 0
serial_drv_handle dd ?
+148 -7
View File
@@ -44,6 +44,8 @@ struct SERIAL_PORT
rx_buf RING_BUF
tx_buf RING_BUF
conf SP_CONF
driver rb SERIAL_INFO_DRIVER_LEN ; ASCIIZ, copied from SP_PORT_INFO.driver in add_port
descr rb SERIAL_INFO_DESCR_LEN ; ASCIIZ, copied from SP_PORT_INFO.descr in add_port (may be empty)
ends
proc START c, reason:dword, cmdline:dword
@@ -57,7 +59,7 @@ proc START c, reason:dword, cmdline:dword
stdcall uart_probe, 0x2f8, 3
stdcall uart_probe, 0x3e8, 4
stdcall uart_probe, 0x2e8, 3
invoke RegService, drv_name, service_proc
invoke RegService, serial_drv_name, service_proc
ret
.fail:
@@ -75,7 +77,7 @@ srv_calls:
dd service_proc.setup
dd service_proc.read
dd service_proc.write
; TODO enumeration
dd service_proc.enum_ports
srv_calls_end:
proc service_proc stdcall uses ebx esi edi, ioctl:dword
@@ -97,11 +99,13 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
; in:
; +0: driver
; +4: driver data
cmp [edx + IOCTL.inp_size], 8
; +8: port info (SP_PORT_INFO*)
cmp [edx + IOCTL.inp_size], 12
jb .err
mov ebx, [edx + IOCTL.input]
mov ecx, [ebx]
mov edx, [ebx + 4]
mov ebx, [ebx + 8]
call add_port
ret
@@ -137,6 +141,7 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
; +4 addr to SERIAL_CONF
; out:
; +0 port handle if success
; eax = 0 if success, otherwise an error code SERIAL_API_ERR_*
cmp [edx + IOCTL.inp_size], 8
jb .err
cmp [edx + IOCTL.out_size], 4
@@ -220,25 +225,60 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
mov [ebx], ecx
ret
.enum_ports:
; in:
; +0 output buffer (array of SP_PORT_ENUM_ENTRY), may be NULL
; +4 output buffer size in bytes
; out:
; +0 total number of ports in the system
; +4 number of entries actually filled into the buffer
; eax = 0 if success, -1 otherwise
cmp [edx + IOCTL.inp_size], 8
jb .err
cmp [edx + IOCTL.out_size], 8
jb .err
mov ebx, [edx + IOCTL.input]
push edx
mov eax, [ebx]
mov edx, [ebx + 4]
call sp_enum
pop edx
mov ebx, [edx + IOCTL.output]
mov [ebx], eax
mov [ebx + 4], ecx
xor eax, eax
ret
.err:
or eax, -1
ret
endp
; struct SERIAL_PORT __fastcall *add_port(const struct SP_DRIVER *drv, const void *drv_data);
align 4
; @param ecx pointer to SP_DRIVER
; @param edx driver-specific argument
; @param ebx pointer to SP_PORT_INFO
; @return SERIAL_PORT descriptor
proc add_port uses edi
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x\n", ecx, edx
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x info=%x\n", ecx, edx, ebx
mov eax, [ecx + SP_DRIVER.size]
cmp eax, sizeof.SP_DRIVER
jne .fail
test ebx, ebx
jz .fail
mov eax, [ebx + SP_PORT_INFO.size]
cmp eax, sizeof.SP_PORT_INFO
jne .fail
; alloc memory for serial port descriptor
push ecx
push edx
push ebx
movi eax, sizeof.SERIAL_PORT
invoke Kmalloc
pop ebx
pop edx
pop ecx
test eax, eax
@@ -252,6 +292,17 @@ proc add_port uses edi
invoke MutexInit
and [edi + SERIAL_PORT.con], 0
; copy port info strings
mov eax, [ebx + SP_PORT_INFO.driver]
lea edx, [edi + SERIAL_PORT.driver]
mov ecx, SERIAL_INFO_DRIVER_LEN
call copy_bounded_str
mov eax, [ebx + SP_PORT_INFO.descr]
lea edx, [edi + SERIAL_PORT.descr]
mov ecx, SERIAL_INFO_DESCR_LEN
call copy_bounded_str
mov ecx, port_list_mutex
invoke MutexLock
@@ -282,7 +333,35 @@ proc add_port uses edi
endp
align 4
; u32 __fastcall *remove_port(struct SERIAL_PORT *port);
; copies an ASCIIZ string into a fixed-size buffer: copies up to (size - 1)
; bytes or until the NUL, then zero-pads the rest of the buffer
; @param eax source ASCIIZ ptr, may be NULL
; @param edx dest buffer ptr
; @param ecx dest buffer size in bytes, must be >= 1
proc copy_bounded_str uses esi edi
mov esi, eax
mov edi, edx
dec ecx ; reserve the last byte for the NUL terminator
.copy:
test ecx, ecx
jz .pad
test esi, esi
jz .pad
lodsb
test al, al
jz .pad
stosb
dec ecx
jmp .copy
.pad:
inc ecx ; account for the reserved NUL byte
xor al, al
rep stosb
ret
endp
align 4
; @param ecx serial port descriptor
proc remove_port uses esi
mov esi, ecx
mov ecx, port_list_mutex
@@ -657,7 +736,69 @@ proc sp_write
ret
endp
drv_name db 'SERIAL', 0
align 4
; @param eax buf
; @param edx buf_size (bytes)
; @return eax total port count in the system
; ecx entries filled into buf
proc sp_enum uses ebx esi edi
mov ecx, eax
mov eax, edx
xor edx, edx
mov ebx, sizeof.SP_PORT_ENUM_ENTRY
div ebx
; eax max entries count
mov edi, ecx
imul eax, sizeof.SP_PORT_ENUM_ENTRY
add eax, ecx
mov edx, eax ; end-of-buffer boundary
xor ebx, ebx ; total port count
xor ecx, ecx ; filled count
push ecx edx
mov ecx, port_list_mutex
invoke MutexLock
pop edx ecx
mov esi, port_list
.next:
mov esi, [esi + SERIAL_PORT.fd]
cmp esi, port_list
jz .done
inc ebx
cmp edi, edx
jae .next
mov eax, [esi + SERIAL_PORT.id]
mov [edi + SP_PORT_ENUM_ENTRY.id], eax
xor eax, eax
cmp dword [esi + SERIAL_PORT.con], 0
setnz al
mov [edi + SP_PORT_ENUM_ENTRY.busy], eax
push ecx esi edi
lea esi, [esi + SERIAL_PORT.driver]
lea edi, [edi + SP_PORT_ENUM_ENTRY.driver]
mov ecx, (SERIAL_INFO_DRIVER_LEN + SERIAL_INFO_DESCR_LEN) / 4
rep movsd
pop edi esi ecx
add edi, sizeof.SP_PORT_ENUM_ENTRY
inc ecx
jmp .next
.done:
push ecx
mov ecx, port_list_mutex
invoke MutexUnlock
pop ecx
mov eax, ebx
ret
endp
include_debug_strings
align 4
+9
View File
@@ -169,6 +169,7 @@ proc uart_probe stdcall uses ebx esi edi, io_addr:dword, irqn:dword
; register port
lea ecx, [uart_drv]
mov edx, edi
lea ebx, [uart_port_info]
call add_port
test eax, eax
jz .free_desc ; TODO detach_int_handler?
@@ -406,3 +407,11 @@ uart_drv:
dd uart_reconf
dd uart_tx
uart_drv_end:
align 4
uart_port_info:
dd uart_port_end - uart_port_info
dd uart_port_name
dd 0
uart_port_end:
uart_port_name db 'uart16550', 0
+203 -310
View File
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; FTDI chips driver for KolibriOS ;;
@@ -15,10 +15,11 @@
format PE DLL native 0.05
entry START
DEBUG = 1
L_DBG = 1
L_ERR = 2
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
__DEBUG_LEVEL__ = L_ERR
node equ ftdi_context
node.next equ ftdi_context.next_context
@@ -122,9 +123,10 @@ TYPE_232H=6
TYPE_230X=7
;strings
my_driver db 'usbother',0
my_driver db 'usbftdi',0
serial_driver db 'SERIAL',0
nomemory_msg db 'K : no memory',13,10,0
nomemory_msg db 'ftdi: no memory',13,10,0
ftdi_port_name db 'ftdi',0
; Structures
struct ftdi_context
@@ -200,10 +202,13 @@ endp
proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
locals
.pinfo rb sizeof.SP_PORT_INFO
endl
invoke USBGetParam, [.config_pipe], 0
mov edx, eax
DEBUGF 2,'K : Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
DEBUGF L_DBG, 'ftdi: Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
cmp word[eax+usb_descr.idVendor], 0x0403
jnz .notftdi
mov eax, sizeof.ftdi_context
@@ -214,7 +219,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
invoke SysMsgBoardStr
jmp .nothing
@@:
DEBUGF 2,'K : Adding struct to list 0x%x\n', eax
DEBUGF L_DBG, 'ftdi: Adding struct to list 0x%x\n', eax
call linkedlist_add
mov ebx, [.config_pipe]
@@ -233,7 +238,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
jmp .slow
mov cx, [edx+usb_descr.bcdDevice]
DEBUGF 2, 'K : Chip type 0x%x\n', ecx
DEBUGF L_DBG, 'ftdi: Chip type 0x%x\n', ecx
cmp cx, 0x400
jnz @f
mov [eax + ftdi_context.chipType], TYPE_BM
@@ -287,8 +292,13 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
mov eax, [serial_drv_entry]
test eax, eax
jz @f
stdcall serial_add_port, uart_drv, ebx
DEBUGF 1, "usbftdi: add serial port with result %x\n", eax
mov dword [.pinfo + SP_PORT_INFO.size], sizeof.SP_PORT_INFO
mov dword [.pinfo + SP_PORT_INFO.driver], ftdi_port_name
; TODO obtain iManufacturer, iProduct and iSerial strings
mov dword [.pinfo + SP_PORT_INFO.descr], 0
lea ecx, [.pinfo]
stdcall serial_add_port, uart_drv, ebx, ecx
DEBUGF L_DBG, 'ftdi: add serial port with result %x\n', eax
@@:
mov [ebx + ftdi_context.port_handle], eax
@@ -296,7 +306,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
ret
.notftdi:
DEBUGF 1,'K : Skipping not FTDI device\n'
DEBUGF L_DBG, 'ftdi: Skipping not FTDI device\n'
.nothing:
xor eax, eax
ret
@@ -317,7 +327,7 @@ EventData rd 3
endl
mov edi, [ioctl]
mov eax, [edi+io_code]
DEBUGF 1,'K : FTDI got the request: %d\n', eax
DEBUGF L_DBG, 'ftdi: FTDI got the request: %d\n', eax
test eax, eax ;0
jz .version
dec eax ;1
@@ -416,7 +426,7 @@ endl
.version:
jmp .endswitch
.error:
DEBUGF 1, 'K : FTDI error occured! %d\n', eax
DEBUGF L_ERR, 'ftdi: error occured! %d\n', eax
;mov esi, [edi+output]
;mov [esi], dword 'ERR0'
;or [esi], eax
@@ -449,7 +459,7 @@ endl
mov word[ConfPacket+6], cx
.own_index:
mov ebx, [edi+4]
DEBUGF 2,'K : ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
DEBUGF L_DBG, 'ftdi: ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
lea esi, [ConfPacket]
lea edi, [EventData]
invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\
@@ -465,7 +475,7 @@ endl
jmp .error
.ftdi_setrtshigh:
DEBUGF 2,'K : FTDI Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
@@ -473,7 +483,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_setrtslow:
DEBUGF 2,'K : FTDI Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
@@ -481,7 +491,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_setdtrhigh:
DEBUGF 2,'K : FTDI Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
@@ -489,7 +499,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_setdtrlow:
DEBUGF 2,'K : FTDI Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
@@ -497,7 +507,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_usb_reset:
DEBUGF 2,'K : FTDI Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_RESET_REQUEST shl 8) \
@@ -505,7 +515,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_purge_rx_buf:
DEBUGF 2, 'K : FTDI Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_RESET_REQUEST shl 8) \
@@ -513,7 +523,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_purge_tx_buf:
DEBUGF 2, 'K : FTDI Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_RESET_REQUEST shl 8) \
@@ -521,42 +531,42 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_set_bitmode:
DEBUGF 2, 'K : FTDI Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
DEBUGF L_DBG, 'ftdi: Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
[edi+8]:2,[edi+10]:2,[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_BITMODE_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_set_line_property:
DEBUGF 2, 'K : FTDI Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
DEBUGF L_DBG, 'ftdi: Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
[edi+8]:4,[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_DATA_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_set_latency_timer:
DEBUGF 2, 'K : FTDI Set latency %d PID: %d Dev handler 0x0x%x\n', \
DEBUGF L_DBG, 'ftdi: Set latency %d PID: %d Dev handler 0x0x%x\n', \
[edi+8],[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_LATENCY_TIMER_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_set_event_char:
DEBUGF 2, 'K : FTDI Set event char %c PID: %d Dev handler 0x0x%x\n', \
DEBUGF L_DBG, 'ftdi: Set event char %c PID: %d Dev handler 0x0x%x\n', \
[edi+8],[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_EVENT_CHAR_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_set_error_char:
DEBUGF 2, 'K : FTDI Set error char %c PID: %d Dev handler 0x0x%x\n', \
DEBUGF L_DBG, 'ftdi: Set error char %c PID: %d Dev handler 0x0x%x\n', \
[edi+8],[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_ERROR_CHAR_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_setflowctrl:
DEBUGF 2, 'K : FTDI Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)
@@ -569,7 +579,7 @@ endl
jmp .own_index
.ftdi_read_pins:
DEBUGF 2, 'K : FTDI Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov ebx, [edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
@@ -598,7 +608,7 @@ endl
jmp .error
.ftdi_set_wchunksize:
DEBUGF 2, 'K : FTDI Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
DEBUGF L_DBG, 'ftdi: Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
[edi+8], [edi], [edi+4]
mov ebx, [edi+4]
mov ecx, [edi+8]
@@ -608,7 +618,7 @@ endl
jmp .endswitch
.ftdi_get_wchunksize:
DEBUGF 2, 'K : FTDI Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov esi, [edi+output]
mov edi, [edi+input]
@@ -618,7 +628,7 @@ endl
jmp .endswitch
.ftdi_set_rchunksize:
DEBUGF 2, 'K : FTDI Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
DEBUGF L_DBG, 'ftdi: Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
[edi+8], [edi], [edi+4]
mov ebx, [edi+4]
mov ecx, [edi+8]
@@ -628,7 +638,7 @@ endl
jmp .endswitch
.ftdi_get_rchunksize:
DEBUGF 2, 'K : FTDI Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov esi, [edi+output]
mov edi, [edi+input]
@@ -638,7 +648,7 @@ endl
jmp .endswitch
.ftdi_write_data:
DEBUGF 2, 'K : FTDI Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
DEBUGF L_DBG, 'ftdi: Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
[edi], [edi+4]
mov esi, edi
add esi, 12
@@ -685,7 +695,7 @@ endl
jmp .write_loop
.ftdi_read_data:
DEBUGF 2, 'K : FTDI Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
DEBUGF L_DBG, 'ftdi: Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
[edi], [edi+4]
mov edi, [ioctl]
mov esi, [edi+input]
@@ -743,7 +753,7 @@ endl
;---Dirty hack end
.ftdi_poll_modem_status:
DEBUGF 2, 'K : FTDI Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov ebx, [edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
@@ -767,7 +777,7 @@ endl
jmp .endswitch
.ftdi_get_latency_timer:
DEBUGF 2, 'K : FTDI Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF L_DBG, 'ftdi: Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov ebx, [edi+4]
mov dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE \
@@ -787,7 +797,7 @@ endl
jmp .endswitch
.ftdi_get_list:
DEBUGF 2, 'K : FTDI devices list request\n'
DEBUGF L_DBG, 'ftdi: devices list request\n'
mov edi, [edi+output]
xor ecx, ecx
call linkedlist_gethead
@@ -817,7 +827,7 @@ endl
jmp .endswitch
.ftdi_lock:
DEBUGF 2, 'K : FTDI Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
DEBUGF L_DBG, 'ftdi: Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
mov esi, [edi+input]
mov ebx, [esi+4]
mov eax, [ebx + ftdi_context.lockPID]
@@ -831,7 +841,7 @@ endl
jmp .endswitch
.ftdi_unlock:
DEBUGF 2, 'K : FTDI Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
DEBUGF L_DBG, 'ftdi: Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
mov esi, [edi+input]
mov edi, [edi+output]
mov ebx, [esi+4]
@@ -845,145 +855,19 @@ endl
mov [edi], eax
jmp .endswitch
H_CLK = 120000000
C_CLK = 48000000
.ftdi_set_baudrate:
DEBUGF 2, 'K : FTDI Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
DEBUGF L_DBG, 'ftdi: Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
[edi+8], [edi], [edi+4]
mov ebx, [edi+4]
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jl .c_clk
imul eax, [edi+8], 10
cmp eax, H_CLK / 0x3FFF
jle .c_clk
.h_clk:
cmp dword[edi+8], H_CLK/10
jl .h_nextbaud1
xor edx, edx
mov ecx, H_CLK/10
jmp .calcend
.c_clk:
cmp dword[edi+8], C_CLK/16
jl .c_nextbaud1
xor edx, edx
mov ecx, C_CLK/16
jmp .calcend
.h_nextbaud1:
cmp dword[edi+8], H_CLK/(10 + 10/2)
jl .h_nextbaud2
mov edx, 1
mov ecx, H_CLK/(10 + 10/2)
jmp .calcend
.c_nextbaud1:
cmp dword[edi+8], C_CLK/(16 + 16/2)
jl .c_nextbaud2
mov edx, 1
mov ecx, C_CLK/(16 + 16/2)
jmp .calcend
.h_nextbaud2:
cmp dword[edi+8], H_CLK/(2*10)
jl .h_nextbaud3
mov edx, 2
mov ecx, H_CLK/(2*10)
jmp .calcend
.c_nextbaud2:
cmp dword[edi+8], C_CLK/(2*16)
jl .c_nextbaud3
mov edx, 2
mov ecx, C_CLK/(2*16)
jmp .calcend
.h_nextbaud3:
mov eax, H_CLK*16/10 ; eax - best_divisor
xor edx, edx
div dword[edi+8] ; [edi+8] - baudrate
push eax
and eax, 1
pop eax
shr eax, 1
jz .h_rounddowndiv ; jump by result of and eax, 1
inc eax
.h_rounddowndiv:
cmp eax, 0x20000
jle .h_best_divok
mov eax, 0x1FFFF
.h_best_divok:
mov ecx, eax
mov eax, H_CLK*16/10
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jz .rounddownbaud
inc ecx
jmp .rounddownbaud
.c_nextbaud3:
mov eax, C_CLK ; eax - best_divisor
xor edx, edx
div dword[edi+8] ; [edi+8] - baudrate
push eax
and eax, 1
pop eax
shr eax, 1
jnz .c_rounddowndiv ; jump by result of and eax, 1
inc eax
.c_rounddowndiv:
cmp eax, 0x20000
jle .c_best_divok
mov eax, 0x1FFFF
.c_best_divok:
mov ecx, eax
mov eax, C_CLK
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jnz .rounddownbaud
inc ecx
.rounddownbaud:
mov edx, eax ; edx - encoded_divisor
shr edx, 3
and eax, 0x7
push 7 6 5 1 4 2 3 0
mov eax, [esp+eax*4]
shl eax, 14
or edx, eax
add esp, 32
.calcend:
mov eax, edx ; eax - *value
mov ecx, edx ; ecx - *index
and eax, 0xFFFF
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jge .foxyindex
shr ecx, 16
jmp .preparepacket
.foxyindex:
shr ecx, 8
and ecx, 0xFF00
or ecx, [ebx + ftdi_context.index]
.preparepacket:
mov esi, [edi+8]
call ftdi_calc_baud_divisor
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
mov word[ConfPacket+2], ax
mov word[ConfPacket+4], cx
mov word[ConfPacket+6], 0
jmp .own_index
jmp .own_index
endp
restore handle
restore io_code
@@ -993,10 +877,143 @@ restore output
restore out_size
proc ftdi_calc_baud_divisor
; in: ebx = ftdi_context pointer
; esi = baud rate
; out: ax = encoded value
; cx = encoded index
; destroys: eax, ecx, edx, esi
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jl .c_clk
imul eax, esi, 10
cmp eax, H_CLK / 0x3FFF
jle .c_clk
.h_clk:
cmp esi, H_CLK / 10
jl .h_nextbaud1
xor edx, edx
mov ecx, H_CLK / 10
jmp .calcend
.c_clk:
cmp esi, C_CLK / 16
jl .c_nextbaud1
xor edx, edx
mov ecx, C_CLK / 16
jmp .calcend
.h_nextbaud1:
cmp esi, H_CLK / (10 + 10 / 2)
jl .h_nextbaud2
mov edx, 1
mov ecx, H_CLK / (10 + 10 / 2)
jmp .calcend
.c_nextbaud1:
cmp esi, C_CLK / (16 + 16 / 2)
jl .c_nextbaud2
mov edx, 1
mov ecx, C_CLK/(16 + 16 / 2)
jmp .calcend
.h_nextbaud2:
cmp esi, H_CLK / (2 * 10)
jl .h_nextbaud3
mov edx, 2
mov ecx, H_CLK / (2 * 10)
jmp .calcend
.c_nextbaud2:
cmp esi, C_CLK / (2 * 16)
jl .c_nextbaud3
mov edx, 2
mov ecx, C_CLK / (2 * 16)
jmp .calcend
.h_nextbaud3:
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
xor edx, edx
div esi
push eax
and eax, 1
pop eax
shr eax, 1
jz .h_rounddowndiv ; jump by result of and eax, 1
inc eax
.h_rounddowndiv:
cmp eax, 0x20000
jle .h_best_divok
mov eax, 0x1FFFF
.h_best_divok:
mov ecx, eax
mov eax, H_CLK * 16 / 10
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jz .rounddownbaud
inc ecx
jmp .rounddownbaud
.c_nextbaud3:
mov eax, C_CLK ; eax - best_divisor
xor edx, edx
div esi
push eax
and eax, 1
pop eax
shr eax, 1
jnz .c_rounddowndiv ; jump by result of and eax, 1
inc eax
.c_rounddowndiv:
cmp eax, 0x20000
jle .c_best_divok
mov eax, 0x1FFFF
.c_best_divok:
mov ecx, eax
mov eax, C_CLK
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jnz .rounddownbaud
inc ecx
.rounddownbaud:
mov edx, eax ; edx - encoded_divisor
shr edx, 3
and eax, 0x7
push 7 6 5 1 4 2 3 0
mov eax, [esp + eax * 4]
shl eax, 14
or edx, eax
add esp, 32
.calcend:
mov eax, edx ; eax - *value
mov ecx, edx ; ecx - *index
and eax, 0xFFFF
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jge .foxyindex
shr ecx, 16
ret
.foxyindex:
shr ecx, 8
and ecx, 0xFF00
or ecx, [ebx + ftdi_context.index]
ret
endp
proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
.buffer:DWORD, .length:DWORD, .calldata:DWORD
DEBUGF 1, 'K : status is %d\n', [.status]
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
mov ecx, [.calldata]
mov eax, [ecx]
mov ebx, [ecx+4]
@@ -1011,7 +1028,7 @@ endp
proc bulk_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
.buffer:DWORD, .length:DWORD, .calldata:DWORD
DEBUGF 1, 'K : status is %d\n', [.status]
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
mov ecx, [.calldata]
mov eax, [ecx]
mov ebx, [ecx+4]
@@ -1034,7 +1051,7 @@ endp
proc DeviceDisconnected stdcall uses ebx esi edi, .device_data:DWORD
DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.device_data]
DEBUGF L_DBG, 'ftdi: deleting device data 0x%x\n', [.device_data]
mov esi, [.device_data]
mov eax, [esi + ftdi_context.readBufPtr]
test eax, eax
@@ -1062,7 +1079,7 @@ proc bulk_in_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
mov eax, [.status]
test eax, eax
jz @f
DEBUGF 2, 'ftdi: bulk in error %x\n', eax
DEBUGF L_ERR, 'ftdi: bulk in error %x\n', eax
@@:
mov ebx, [.calldata]
btr dword [ebx + ftdi_context.writeBufLock], 0
@@ -1075,7 +1092,7 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
mov eax, [.status]
test eax, eax
jz @f
DEBUGF 2, 'ftdi: bulk out error %x\n', eax
DEBUGF L_ERR, 'ftdi: bulk out error %x\n', eax
@@:
mov ebx, [.calldata]
mov ecx, [.length]
@@ -1092,18 +1109,18 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
endp
proc uart_startup stdcall uses ebx, data:dword, conf:dword
DEBUGF 1, "ftdi: startup %x %x\n", [data], [conf]
DEBUGF L_DBG, "ftdi: startup %x %x\n", [data], [conf]
stdcall uart_reconf, [data], [conf]
test eax, eax
jz @f
DEBUGF 2, "ftdi: uart reconf error %x\n", eax
DEBUGF L_ERR, "ftdi: uart reconf error %x\n", eax
jmp .exit
@@:
mov ebx, [data]
invoke TimerHS, 2, 2, uart_rx, ebx
test eax, eax
jnz @f
DEBUGF 2, "ftdi: timer creation error\n"
DEBUGF L_ERR, "ftdi: timer creation error\n"
or eax, -1
jmp .exit
@@:
@@ -1114,7 +1131,7 @@ proc uart_startup stdcall uses ebx, data:dword, conf:dword
endp
proc uart_shutdown stdcall uses ebx, data:dword
DEBUGF 1, "ftdi: shutdown %x\n", [data]
DEBUGF L_DBG, "ftdi: shutdown %x\n", [data]
mov ebx, [data]
cmp [ebx + ftdi_context.rx_timer], 0
jz @f
@@ -1246,137 +1263,14 @@ proc uart_rx stdcall uses ebx esi, data:dword
ret
endp
proc ftdi_set_baudrate stdcall uses ebx, dev:dword, baud:dword
proc ftdi_set_baudrate stdcall uses ebx esi, dev:dword, baud:dword
locals
ConfPacket rb 8
endl
mov ebx, [dev]
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jl .c_clk
imul eax, [baud], 10
cmp eax, H_CLK / 0x3FFF
jle .c_clk
.h_clk:
cmp dword [baud], H_CLK / 10
jl .h_nextbaud1
xor edx, edx
mov ecx, H_CLK / 10
jmp .calcend
mov esi, [baud]
call ftdi_calc_baud_divisor
.c_clk:
cmp dword [baud], C_CLK / 16
jl .c_nextbaud1
xor edx, edx
mov ecx, C_CLK / 16
jmp .calcend
.h_nextbaud1:
cmp dword [baud], H_CLK / (10 + 10 / 2)
jl .h_nextbaud2
mov edx, 1
mov ecx, H_CLK / (10 + 10 / 2)
jmp .calcend
.c_nextbaud1:
cmp dword [baud], C_CLK / (16 + 16 / 2)
jl .c_nextbaud2
mov edx, 1
mov ecx, C_CLK/(16 + 16 / 2)
jmp .calcend
.h_nextbaud2:
cmp dword [baud], H_CLK / (2 * 10)
jl .h_nextbaud3
mov edx, 2
mov ecx, H_CLK / (2 * 10)
jmp .calcend
.c_nextbaud2:
cmp dword [baud], C_CLK / (2 * 16)
jl .c_nextbaud3
mov edx, 2
mov ecx, C_CLK / (2 * 16)
jmp .calcend
.h_nextbaud3:
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
xor edx, edx
div dword [baud]
push eax
and eax, 1
pop eax
shr eax, 1
jz .h_rounddowndiv ; jump by result of and eax, 1
inc eax
.h_rounddowndiv:
cmp eax, 0x20000
jle .h_best_divok
mov eax, 0x1FFFF
.h_best_divok:
mov ecx, eax
mov eax, H_CLK * 16 / 10
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jz .rounddownbaud
inc ecx
jmp .rounddownbaud
.c_nextbaud3:
mov eax, C_CLK ; eax - best_divisor
xor edx, edx
div dword [baud]
push eax
and eax, 1
pop eax
shr eax, 1
jnz .c_rounddowndiv ; jump by result of and eax, 1
inc eax
.c_rounddowndiv:
cmp eax, 0x20000
jle .c_best_divok
mov eax, 0x1FFFF
.c_best_divok:
mov ecx, eax
mov eax, C_CLK
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jnz .rounddownbaud
inc ecx
.rounddownbaud:
mov edx, eax ; edx - encoded_divisor
shr edx, 3
and eax, 0x7
push 7 6 5 1 4 2 3 0
mov eax, [esp + eax * 4]
shl eax, 14
or edx, eax
add esp, 32
.calcend:
mov eax, edx ; eax - *value
mov ecx, edx ; ecx - *index
and eax, 0xFFFF
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jge .foxyindex
shr ecx, 16
jmp .preparepacket
.foxyindex:
shr ecx, 8
and ecx, 0xFF00
or ecx, [ebx + ftdi_context.index]
.preparepacket:
mov word [ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
mov word [ConfPacket + 2], ax
@@ -1451,10 +1345,9 @@ uart_drv:
dd uart_tx
uart_drv_end:
serial_drv_entry dd 0
include_debug_strings
data fixups
end data
;for DEBUGF macro
include_debug_strings
serial_drv_entry dd ?
+10 -1
View File
@@ -2204,6 +2204,9 @@ proc acm_arm_rx
endp
proc acm_add_device stdcall uses ebx esi edi, .pipe0:dword, .config:dword, .interface:dword
locals
.pinfo rb sizeof.SP_PORT_INFO
endl
; 1. Parse the descriptors (the ACM data interface is alt setting 0).
xor eax, eax
@@ -2264,7 +2267,12 @@ proc acm_add_device stdcall uses ebx esi edi, .pipe0:dword, .config:dword, .inte
cmp [serial_drv_entry], 0
je .no_serial
stdcall serial_add_port, acm_sp_driver, ebx
mov dword [.pinfo+SP_PORT_INFO.size], sizeof.SP_PORT_INFO
mov dword [.pinfo+SP_PORT_INFO.driver], acm_port_name
; TODO obtain iManufacturer, iProduct and iSerial strings
mov dword [.pinfo+SP_PORT_INFO.descr], 0
lea ecx, [.pinfo]
stdcall serial_add_port, acm_sp_driver, ebx, ecx
mov [ebx+acm_dev.PortHandle], eax
test eax, eax
jz .no_serial
@@ -2652,6 +2660,7 @@ endp
; strings and static data
my_service db 'usbcdc', 0
acm_port_name db 'cdc-acm', 0
netdev_name db 'USB CDC-NCM', 0
ecm_netdev_name db 'USB CDC-ECM', 0
ecm_zlp_dummy db 0 ; address for zero-length transfers
+1 -1
View File
@@ -436,7 +436,7 @@ btn_io db ?
dev dd ?
pid dd ?
flags dd ?
drv_name db 'usbother', 0
drv_name db 'usbftdi', 0
noftdi_msg db 'No FTDI connected', 0
devrdy_msg db 'First FTDI is ready', 0
devlkd_msg db 'First FTDI is locked', 0