diff --git a/drivers/serial/common.inc b/drivers/serial/common.inc index 7a4cd1715..8da4f91e4 100755 --- a/drivers/serial/common.inc +++ b/drivers/serial/common.inc @@ -1,3 +1,5 @@ +SERIAL_COMPATIBLE_API_VER = 0 ; increments in case of breaking changes + SERIAL_API_GET_VERSION = 0 SERIAL_API_SRV_ADD_PORT = 1 SERIAL_API_SRV_REMOVE_PORT = 2 @@ -21,14 +23,18 @@ SERIAL_CONF_PARITY_ODD = 2 SERIAL_CONF_PARITY_MARK = 3 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 struct SP_DRIVER size dd ? ; size of this struct - startup dd ? ; void __stdcall (*startup)(void *drv_data, const struct serial_conf *conf); - shutdown dd ? ; void __stdcall (*shutdown)(void *drv_data); - reconf dd ? ; void __stdcall (*reconf)(void *drv_data, const struct serial_conf *conf); - tx dd ? ; void __stdcall (*tx)(void *drv_data); + startup dd ? ; int __stdcall (*startup)(void *drv_data, const struct serial_conf *conf); + shutdown dd ? ; int __stdcall (*shutdown)(void *drv_data); + reconf dd ? ; int __stdcall (*reconf)(void *drv_data, const struct serial_conf *conf); + tx dd ? ; int __stdcall (*tx)(void *drv_data); ends struct SP_CONF @@ -123,6 +129,30 @@ proc serial_port_init ret 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 locals .handler dd ? diff --git a/drivers/serial/serial.asm b/drivers/serial/serial.asm index 0155207b4..f48f301ee 100755 --- a/drivers/serial/serial.asm +++ b/drivers/serial/serial.asm @@ -9,8 +9,6 @@ __DEBUG_LEVEL__ = L_DBG SERIAL_RING_BUF_SIZE = 32768 -API_VERSION = 1 - section '.flat' readable writable executable include '../struct.inc' @@ -23,6 +21,9 @@ include 'common.inc' include 'ring_buf.inc' include 'uart16550.inc' +CURRENT_API = 0x0001 +API_VERSION = (SERIAL_COMPATIBLE_API_VER shl 16) + CURRENT_API + struct SERIAL_OBJ magic dd ? destroy dd ? @@ -45,7 +46,7 @@ struct SERIAL_PORT conf SP_CONF ends -proc START c, reason:dword +proc START c, reason:dword, cmdline:dword cmp [reason], DRV_ENTRY jne .fail @@ -347,15 +348,12 @@ proc sp_validate_conf mov eax, [ecx + SP_CONF.baudrate] test eax, eax 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] - cmp al, 1 - jne .fail ; TODO implement different stop bits count + cmp al, SERIAL_CONF_STOP_BITS_2 + ja .fail mov al, [ecx + SP_CONF.parity] - cmp al, SERIAL_CONF_PARITY_NONE - jne .fail ; TODO implement parity + cmp al, SERIAL_CONF_PARITY_SPACE + ja .fail mov al, [ecx + SP_CONF.flow_ctrl] cmp al, SERIAL_CONF_FLOW_CTRL_NONE jne .fail ; TODO implement flow control @@ -550,7 +548,6 @@ proc sp_setup mov eax, [edi + SERIAL_PORT.drv] mov ecx, [edi + SERIAL_PORT.drv_data] stdcall dword [eax + SP_DRIVER.reconf], ecx, esi - xor eax, eax push eax test eax, eax jnz @f diff --git a/drivers/serial/uart16550.inc b/drivers/serial/uart16550.inc index 5c8a431e0..b7d5c12e9 100755 --- a/drivers/serial/uart16550.inc +++ b/drivers/serial/uart16550.inc @@ -350,10 +350,10 @@ endl ; calc stop bits mov bx, LCR_STOP_1 mov al, [esi + SP_CONF.stop_bits] - cmp al, 1 + cmp al, SERIAL_CONF_STOP_BITS_1 je .stop_bits_ok or bx, LCR_STOP_2 - cmp al, 2 + cmp al, SERIAL_CONF_STOP_BITS_2 jne .fail .stop_bits_ok: or [lcr], bx diff --git a/drivers/usb/usbftdi/usbftdi.asm b/drivers/usb/usbftdi/usbftdi.asm index c7336994a..99a56182b 100644 --- a/drivers/usb/usbftdi/usbftdi.asm +++ b/drivers/usb/usbftdi/usbftdi.asm @@ -1123,11 +1123,53 @@ proc uart_shutdown stdcall uses ebx, data:dword ret endp -proc uart_reconf stdcall uses ebx esi, dev:dword, conf:dword - mov ebx, [dev] +proc uart_reconf stdcall uses esi, dev:dword, conf:dword +locals +ConfPacket rb 8 +endl mov esi, [conf] - stdcall ftdi_set_baudrate, ebx, [esi + SP_CONF.baudrate] - ; TODO set word_size, parity, etc. + xor edx, edx + 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 endp @@ -1204,17 +1246,10 @@ proc uart_rx stdcall uses ebx esi, data:dword ret 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 -ConfPacket rb 10 -EventData rd 3 +ConfPacket rb 8 endl - xor esi, esi - xor ecx, ecx - invoke CreateEvent - mov [EventData], eax - mov [EventData + 4], edx - mov ebx, [dev] cmp [ebx + ftdi_context.chipType], TYPE_2232H jl .c_clk @@ -1257,7 +1292,7 @@ endl jmp .calcend .c_nextbaud2: - cmp dword [edi + 8], C_CLK / (2 * 16) + cmp dword [baud], C_CLK / (2 * 16) jl .c_nextbaud3 mov edx, 2 mov ecx, C_CLK / (2 * 16) @@ -1348,23 +1383,51 @@ endl mov word [ConfPacket + 4], cx 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] - invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\ + invoke USBControlTransferAsync, [eax + ftdi_context.nullP], esi, 0,\ 0, control_callback, edi, 0 test eax, eax jz .error + mov eax, [EventData] mov ebx, [EventData + 4] invoke WaitEvent + cmp [EventData + 8], 0 ; USB_STATUS_OK + jne .error + mov eax, [EventData] mov ebx, [EventData + 4] invoke DestroyEvent xor eax, eax ret - .error: + .error: + mov eax, [EventData] + mov ebx, [EventData + 4] + invoke DestroyEvent + .exit: or eax, -1 ret endp