Subversion Repositories Kolibri OS

Rev

Rev 5363 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;  FTDI chips driver for KolibriOS                             ;;
  7. ;;                                                              ;;
  8. ;;   Written by gtament@gmail.com                               ;;
  9. ;;                                                              ;;
  10. ;;         GNU GENERAL PUBLIC LICENSE                           ;;
  11. ;;          Version 2, June 1991                                ;;
  12. ;;                                                              ;;
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. format PE DLL native 0.05
  16. entry START
  17.  
  18. DEBUG = 1
  19.  
  20. __DEBUG__ = 1
  21. __DEBUG_LEVEL__ = 1
  22.  
  23. node equ ftdi_context
  24. node.next equ ftdi_context.next_context
  25.  
  26. include '../../proc32.inc'
  27. include '../../peimport.inc'
  28. include '../../fdo.inc'
  29. include '../../struct.inc'
  30.  
  31. ; USB constants
  32. DEVICE_DESCR_TYPE           = 1
  33. CONFIG_DESCR_TYPE           = 2
  34. STRING_DESCR_TYPE           = 3
  35. INTERFACE_DESCR_TYPE        = 4
  36. ENDPOINT_DESCR_TYPE         = 5
  37. DEVICE_QUALIFIER_DESCR_TYPE = 6
  38.  
  39. CONTROL_PIPE     = 0
  40. ISOCHRONOUS_PIPE = 1
  41. BULK_PIPE        = 2
  42. INTERRUPT_PIPE   = 3
  43.  
  44. ; USB HID constants
  45. HID_DESCR_TYPE      = 21h
  46. REPORT_DESCR_TYPE   = 22h
  47. PHYSICAL_DESCR_TYPE = 23h
  48.  
  49. ; LibUSB constatnts
  50. LIBUSB_REQUEST_TYPE_STANDARD = (0x00 shl 5)
  51. LIBUSB_REQUEST_TYPE_CLASS = (0x01 shl 5)
  52. LIBUSB_REQUEST_TYPE_VENDOR = (0x02 shl 5)
  53. LIBUSB_REQUEST_TYPE_RESERVED = (0x03 shl 5)
  54.  
  55. LIBUSB_RECIPIENT_DEVICE = 0x00
  56. LIBUSB_RECIPIENT_INTERFACE = 0x01
  57. LIBUSB_RECIPIENT_ENDPOINT = 0x02
  58. LIBUSB_RECIPIENT_OTHER = 0x03
  59.  
  60. LIBUSB_ENDPOINT_IN = 0x80
  61. LIBUSB_ENDPOINT_OUT = 0x00
  62.  
  63. ; FTDI Constants
  64. FTDI_DEVICE_OUT_REQTYPE = (LIBUSB_REQUEST_TYPE_VENDOR or LIBUSB_RECIPIENT_DEVICE or LIBUSB_ENDPOINT_OUT)
  65. FTDI_DEVICE_IN_REQTYPE = (LIBUSB_REQUEST_TYPE_VENDOR or LIBUSB_RECIPIENT_DEVICE or LIBUSB_ENDPOINT_IN)
  66.  
  67. ; Requests
  68. ;Definitions for flow control
  69. SIO_RESET         =0  ;Reset the port
  70. SIO_MODEM_CTRL    =1  ;Set the modem control register
  71. SIO_SET_FLOW_CTRL =2  ;Set flow control register
  72. SIO_SET_BAUD_RATE =3  ;Set baud rate
  73. SIO_SET_DATA      =4  ;Set the data characteristics of the port
  74.  
  75. SIO_RESET_REQUEST            =SIO_RESET
  76. SIO_SET_BAUDRATE_REQUEST     =SIO_SET_BAUD_RATE
  77. SIO_SET_DATA_REQUEST         =SIO_SET_DATA
  78. SIO_SET_FLOW_CTRL_REQUEST    =SIO_SET_FLOW_CTRL
  79. SIO_SET_MODEM_CTRL_REQUEST   =SIO_MODEM_CTRL
  80. SIO_POLL_MODEM_STATUS_REQUEST=0x05
  81. SIO_SET_EVENT_CHAR_REQUEST   =0x06
  82. SIO_SET_ERROR_CHAR_REQUEST   =0x07
  83. SIO_SET_LATENCY_TIMER_REQUEST=0x09
  84. SIO_GET_LATENCY_TIMER_REQUEST=0x0A
  85. SIO_SET_BITMODE_REQUEST      =0x0B
  86. SIO_READ_PINS_REQUEST        =0x0C
  87. SIO_READ_EEPROM_REQUEST      =0x90
  88. SIO_WRITE_EEPROM_REQUEST     =0x91
  89. SIO_ERASE_EEPROM_REQUEST     =0x92
  90.  
  91.  
  92. SIO_RESET_SIO=0
  93. SIO_RESET_PURGE_RX=1
  94. SIO_RESET_PURGE_TX=2
  95.  
  96. SIO_DISABLE_FLOW_CTRL=0x0
  97. SIO_RTS_CTS_HS =(0x1 shl 8)
  98. SIO_DTR_DSR_HS =(0x2 shl 8)
  99. SIO_XON_XOFF_HS=(0x4 shl 8)
  100.  
  101. SIO_SET_DTR_MASK=0x1
  102. SIO_SET_DTR_HIGH=( 1 or ( SIO_SET_DTR_MASK  shl 8))
  103. SIO_SET_DTR_LOW =( 0 or ( SIO_SET_DTR_MASK  shl 8))
  104. SIO_SET_RTS_MASK=0x2
  105. SIO_SET_RTS_HIGH=( 2 or ( SIO_SET_RTS_MASK shl 8 ))
  106. SIO_SET_RTS_LOW =( 0 or ( SIO_SET_RTS_MASK shl 8 ))
  107.  
  108. SIO_RTS_CTS_HS =(0x1 shl 8)
  109.  
  110. ;FTDI chip type
  111. TYPE_AM=0
  112. TYPE_BM=1
  113. TYPE_2232C=2
  114. TYPE_R=3
  115. TYPE_2232H=4
  116. TYPE_4232H=5
  117. TYPE_232H=6
  118. TYPE_230X=7
  119.  
  120. ;strings
  121. my_driver       db      'usbother',0
  122. nomemory_msg    db      'K : no memory',13,10,0
  123.  
  124. ; Structures
  125. struct ftdi_context
  126. chipType                db      ?
  127. baudrate                dd      ?
  128. bitbangEnabled          db      ?
  129. readBufChunkSize        dd      ?
  130. writeBufChunkSize       dd      ?
  131. readBufPtr              dd      ?
  132. writeBufPtr             dd      ?
  133. readBufSize             dd      ?
  134. writeBufSize            dd      ?
  135. maxPacketSize           dd      ?
  136. interface               dd      ?
  137. index                   dd      ?
  138. inEP                    dd      ?
  139. outEP                   dd      ?
  140. nullP                   dd      ?
  141. lockPID                 dd      ?
  142. next_context            dd      ?
  143. ends
  144.  
  145. struct IOCTL
  146. handle                  dd      ?
  147. io_code                 dd      ?
  148. input                   dd      ?
  149. inp_size                dd      ?
  150. output                  dd      ?
  151. out_size                dd      ?
  152. ends
  153.  
  154. struct usb_descr
  155. bLength                 db      ?
  156. bDescriptorType         db      ?
  157. bcdUSB                  dw      ?
  158. bDeviceClass            db      ?
  159. bDeviceSubClass         db      ?
  160. bDeviceProtocol         db      ?
  161. bMaxPacketSize0         db      ?
  162. idVendor                dw      ?
  163. idProduct               dw      ?
  164. bcdDevice               dw      ?
  165. iManufacturer           db      ?
  166. iProduct                db      ?
  167. iSerialNumber           db      ?
  168. bNumConfigurations      db      ?
  169. ends
  170.  
  171. struct conf_packet
  172. bmRequestType           db      ?
  173. bRequest                db      ?
  174. wValue                  dw      ?
  175. wIndex                  dw      ?
  176. wLength                 dw      ?
  177. ends
  178.  
  179. section '.flat' code readable executable
  180. ; The start procedure.
  181. proc START c, .reason:DWORD, .cmdline:DWORD
  182.  
  183.         xor     eax, eax        ; initialize return value
  184.         cmp     [.reason], 1    ; compare the argument
  185.         jnz     .nothing                
  186.         invoke  RegUSBDriver, my_driver, service_proc, usb_functions
  187.  
  188. .nothing:
  189.         ret
  190. endp
  191.  
  192.  
  193. proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
  194.        
  195.         invoke  USBGetParam, [.config_pipe], 0
  196.         mov     edx, eax
  197.         DEBUGF 2,'K : Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
  198.         cmp     word[eax+usb_descr.idVendor], 0x0403
  199.         jnz     .notftdi
  200.         mov     eax, sizeof.ftdi_context
  201.         invoke  Kmalloc
  202.         test    eax, eax
  203.         jnz     @f
  204.         mov     esi, nomemory_msg
  205.         invoke  SysMsgBoardStr
  206.         jmp     .nothing
  207.   @@:
  208.         DEBUGF 2,'K : Adding struct to list 0x%x\n', eax
  209.         call    linkedlist_add
  210.        
  211.         mov     ebx, [.config_pipe]
  212.         mov     [eax + ftdi_context.nullP], ebx
  213.         mov     [eax + ftdi_context.index], 0
  214.         mov     [eax + ftdi_context.lockPID], 0
  215.         mov     [eax + ftdi_context.maxPacketSize], 64      
  216.         mov     [eax + ftdi_context.readBufChunkSize], 64
  217.         mov     [eax + ftdi_context.writeBufChunkSize], 64
  218.  
  219.         mov     [eax + ftdi_context.chipType], TYPE_R
  220.         jmp     .slow
  221.        
  222.         mov     cx, [edx+usb_descr.bcdDevice]
  223.         DEBUGF 2, 'K : Chip type 0x%x\n', ecx
  224.         cmp     cx, 0x400
  225.         jnz     @f
  226.         mov     [eax + ftdi_context.chipType], TYPE_BM
  227.         jmp     .slow
  228.   @@:      
  229.         cmp     cx, 0x200
  230.         jnz     @f
  231.         mov     [eax + ftdi_context.chipType], TYPE_AM
  232.         jmp     .slow
  233.   @@:    
  234.         cmp     cx, 0x500
  235.         jnz     @f
  236.         mov     [eax + ftdi_context.chipType], TYPE_2232C
  237.         jmp     .slow
  238.   @@:      
  239.         cmp     cx, 0x600
  240.         jnz     @f
  241.         mov     [eax + ftdi_context.chipType], TYPE_R
  242.         jmp     .slow
  243.   @@:      
  244.         cmp     cx, 0x700
  245.         jnz     @f
  246.         mov     [eax + ftdi_context.chipType], TYPE_2232H
  247.         jmp     .fast
  248.   @@:      
  249.         cmp     cx, 0x900
  250.         jnz     @f
  251.         mov     [eax + ftdi_context.chipType], TYPE_232H
  252.         jmp     .fast
  253.   @@:      
  254.         cmp     cx, 0x1000
  255.         jnz     .slow
  256.         mov     [eax + ftdi_context.chipType], TYPE_230X
  257.         jmp     .fast
  258.        
  259.   .fast:
  260.         add     [eax + ftdi_context.maxPacketSize], 512-64
  261.   .slow:    
  262.         mov     ebx, eax
  263.         invoke  USBOpenPipe, [.config_pipe], 0x81, \
  264.                             [ebx + ftdi_context.maxPacketSize],  BULK_PIPE, 0
  265.         test    eax, eax
  266.         jz      .nothing
  267.         mov     [ebx + ftdi_context.outEP], eax
  268.         invoke  USBOpenPipe, [.config_pipe], 0x02, \
  269.                             [ebx + ftdi_context.maxPacketSize],  BULK_PIPE, 0
  270.         test    eax, eax
  271.         jz      .nothing
  272.         mov     [ebx + ftdi_context.inEP], eax
  273.         mov     eax, ebx
  274.         ret        
  275.            
  276.   .notftdi:
  277.         DEBUGF 1,'K : Skipping not FTDI device\n'
  278.   .nothing:        
  279.         xor     eax, eax
  280.         ret
  281. endp
  282.  
  283.  
  284. handle     equ  IOCTL.handle
  285. io_code    equ  IOCTL.io_code
  286. input      equ  IOCTL.input
  287. inp_size   equ  IOCTL.inp_size
  288. output     equ  IOCTL.output
  289. out_size   equ  IOCTL.out_size
  290.  
  291. proc service_proc stdcall uses ebx esi edi, ioctl:DWORD
  292. locals
  293. ConfPacket  rb  10
  294. EventData   rd  3
  295. endl
  296.         mov     edi, [ioctl]
  297.         mov     eax, [edi+io_code]
  298.         DEBUGF 1,'K : FTDI got the request: %d\n', eax
  299.         test    eax, eax            ;0
  300.         jz      .version
  301.         dec     eax                 ;1
  302.         jz      .ftdi_get_list
  303.        
  304.         push    eax
  305.         mov     esi, [edi+input]
  306.         mov     eax, [esi+4]
  307.         call    linkedlist_isvalid
  308.         test    eax, eax
  309.         pop     eax        
  310.         jnz     .endswitch
  311.        
  312.         dec     eax
  313.         jz      .ftdi_lock      ;2
  314.         dec     eax
  315.         jz      .ftdi_unlock    ;3
  316.        
  317.         mov     ebx, [esi+4]
  318.         mov     ecx, [ebx + ftdi_context.lockPID]
  319.         cmp     dword[esi], 0
  320.         jz      .error
  321.         cmp     ecx, [esi]
  322.         jz      .pid_ok
  323.         mov     esi, [edi+output]
  324.         mov     dword[esi], 'LCKD'
  325.         jmp     .endswitch
  326.        
  327.   .pid_ok:
  328.         dec     eax
  329.         jz      .ftdi_get_wchunksize    ;4
  330.         dec     eax
  331.         jz      .ftdi_get_rchunksize    ;5        
  332.        
  333.         mov     edi, [edi+input]
  334.        
  335.         dec     eax
  336.         jz      .ftdi_set_rchunksize    ;6
  337.         dec     eax
  338.         jz      .ftdi_set_wchunksize    ;7
  339.  
  340.         push    eax edi
  341.         mov     ecx, 0x80000000
  342.         cmp     eax, 8-7
  343.         je      .bulkevent
  344.         cmp     eax, 9-7
  345.         je      .bulkevent
  346.         xor     ecx, ecx
  347.   .bulkevent:                
  348.         xor     esi, esi
  349.         invoke  CreateEvent        
  350.         mov     [EventData], eax
  351.         mov     [EventData+4], edx
  352.         pop     edi eax
  353.        
  354.         dec     eax                 ;8
  355.         jz      .ftdi_write_data
  356.         dec     eax                 ;9
  357.         jz      .ftdi_read_data
  358.         dec     eax                 ;10
  359.         jz      .ftdi_set_baudrate
  360.         dec     eax                 ;11
  361.         jz      .ftdi_set_bitmode
  362.         dec     eax                 ;12
  363.         jz      .ftdi_setrtshigh  
  364.         dec     eax                 ;13
  365.         jz      .ftdi_setrtslow  
  366.         dec     eax                 ;14
  367.         jz      .ftdi_setdtrhigh
  368.         dec     eax                 ;15
  369.         jz      .ftdi_setdtrlow
  370.         dec     eax                 ;16
  371.         jz      .ftdi_usb_reset
  372.         dec     eax                 ;17
  373.         jz      .ftdi_setflowctrl
  374.         dec     eax                 ;18
  375.         jz      .ftdi_set_event_char
  376.         dec     eax                 ;19
  377.         jz      .ftdi_set_error_char
  378.         dec     eax                 ;20
  379.         jz      .ftdi_set_latency_timer
  380.         dec     eax                 ;21
  381.         jz      .ftdi_get_latency_timer
  382.         dec     eax                 ;22
  383.         jz      .ftdi_read_pins
  384.         dec     eax                 ;23
  385.         jz      .ftdi_poll_modem_status        
  386.         dec     eax                 ;24
  387.         jz      .ftdi_set_line_property
  388.         dec     eax                 ;25
  389.         jz      .ftdi_purge_rx_buf
  390.         dec     eax                 ;26
  391.         jz      .ftdi_purge_tx_buf
  392.         jmp     .error
  393.                  
  394.   .version:    
  395.         jmp     .endswitch
  396.   .error:
  397.         DEBUGF 1, 'K : FTDI error occured! %d\n', eax
  398.         ;mov     esi, [edi+output]
  399.         ;mov     [esi], dword 'ERR0'
  400.         ;or      [esi], eax
  401.         ret
  402.   .endswitch:
  403.         xor     eax, eax
  404.         ret
  405.        
  406.   .eventdestroy:
  407.         ;---Dirty hack begin
  408.         test    eax, eax
  409.         jz      @f
  410.         mov     eax, dword[ConfPacket]
  411.         invoke  Kfree
  412.   @@:
  413.         ;---Dirty hack end
  414.         mov     eax, [EventData]
  415.         mov     ebx, [EventData+4]
  416.         invoke  DestroyEvent
  417.         jmp     .endswitch
  418.        
  419.   .ftdi_out_control_transfer_withinp:              
  420.         mov     dx, word[edi+8]
  421.         mov     word[ConfPacket+2], dx
  422.   .ftdi_out_control_transfer_noinp:
  423.         mov     ebx, [edi+4]
  424.         mov     cx, word[ebx + ftdi_context.index]
  425.         mov     word[ConfPacket+4], cx
  426.         xor     cx, cx
  427.         mov     word[ConfPacket+6], cx
  428.   .own_index:
  429.         mov     ebx, [edi+4]
  430.         DEBUGF 2,'K : ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]          
  431.         lea     esi, [ConfPacket]
  432.         lea     edi, [EventData]        
  433.         invoke  USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, 0,\
  434.                                             0, control_callback, edi, 0
  435.         test    eax, eax        
  436.         jz      .error
  437.         mov     eax, [EventData]
  438.         mov     ebx, [EventData+4]
  439.         invoke  WaitEvent
  440.         mov     eax, [EventData+8]
  441.         test    eax, eax
  442.         jz      .endswitch
  443.         jmp     .error
  444.        
  445.   .ftdi_setrtshigh:
  446.         DEBUGF 2,'K : FTDI Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
  447.                                                                         [edi+4]
  448.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  449.                                  + (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
  450.                                  + (SIO_SET_RTS_HIGH shl 16)
  451.         jmp     .ftdi_out_control_transfer_noinp        
  452.  
  453.   .ftdi_setrtslow:
  454.         DEBUGF 2,'K : FTDI Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
  455.                                                                         [edi+4]
  456.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  457.                                  + (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
  458.                                  + (SIO_SET_RTS_LOW shl 16)
  459.         jmp     .ftdi_out_control_transfer_noinp          
  460.        
  461.   .ftdi_setdtrhigh:
  462.         DEBUGF 2,'K : FTDI Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
  463.                                                                         [edi+4]
  464.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  465.                                  + (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
  466.                                  + (SIO_SET_DTR_HIGH shl 16)
  467.         jmp     .ftdi_out_control_transfer_noinp          
  468.  
  469.   .ftdi_setdtrlow:
  470.         DEBUGF 2,'K : FTDI Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
  471.                                                                         [edi+4]
  472.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  473.                                  + (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
  474.                                  + (SIO_SET_DTR_LOW shl 16)
  475.         jmp     .ftdi_out_control_transfer_noinp          
  476.        
  477.   .ftdi_usb_reset:
  478.         DEBUGF 2,'K : FTDI Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
  479.                                                                         [edi+4]
  480.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  481.                                  + (SIO_RESET_REQUEST shl 8) \
  482.                                  + (SIO_RESET_SIO shl 16)
  483.         jmp     .ftdi_out_control_transfer_noinp  
  484.        
  485.   .ftdi_purge_rx_buf:
  486.         DEBUGF 2, 'K : FTDI Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
  487.                                                                         [edi+4]
  488.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  489.                                  + (SIO_RESET_REQUEST shl 8) \
  490.                                  + (SIO_RESET_PURGE_RX shl 16)
  491.         jmp     .ftdi_out_control_transfer_noinp  
  492.        
  493.   .ftdi_purge_tx_buf:
  494.         DEBUGF 2, 'K : FTDI Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
  495.                                                                         [edi+4]
  496.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  497.                                  + (SIO_RESET_REQUEST shl 8) \
  498.                                  + (SIO_RESET_PURGE_TX shl 16)
  499.         jmp     .ftdi_out_control_transfer_noinp  
  500.        
  501.   .ftdi_set_bitmode:
  502.         DEBUGF 2, 'K : FTDI Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
  503.                                                [edi+8]:2,[edi+10]:2,[edi],[edi+4]
  504.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  505.                                 + (SIO_SET_BITMODE_REQUEST shl 8)                                      
  506.         jmp     .ftdi_out_control_transfer_withinp        
  507.      
  508.   .ftdi_set_line_property:
  509.         DEBUGF 2, 'K : FTDI Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
  510.                                                           [edi+8]:4,[edi],[edi+4]
  511.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  512.                                 + (SIO_SET_DATA_REQUEST shl 8)
  513.         jmp     .ftdi_out_control_transfer_withinp
  514.        
  515.   .ftdi_set_latency_timer:
  516.         DEBUGF 2, 'K : FTDI Set latency %d PID: %d Dev handler 0x0x%x\n', \
  517.                                                           [edi+8],[edi],[edi+4]
  518.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  519.                                 + (SIO_SET_LATENCY_TIMER_REQUEST shl 8)        
  520.         jmp     .ftdi_out_control_transfer_withinp
  521.        
  522.   .ftdi_set_event_char:
  523.         DEBUGF 2, 'K : FTDI Set event char %c PID: %d Dev handler 0x0x%x\n', \
  524.                                                           [edi+8],[edi],[edi+4]
  525.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  526.                                 + (SIO_SET_EVENT_CHAR_REQUEST shl 8)
  527.         jmp     .ftdi_out_control_transfer_withinp
  528.  
  529.   .ftdi_set_error_char:
  530.         DEBUGF 2, 'K : FTDI Set error char %c PID: %d Dev handler 0x0x%x\n', \
  531.                                                           [edi+8],[edi],[edi+4]
  532.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  533.                                 + (SIO_SET_ERROR_CHAR_REQUEST shl 8)
  534.         jmp     .ftdi_out_control_transfer_withinp
  535.        
  536.   .ftdi_setflowctrl:
  537.         DEBUGF 2, 'K : FTDI Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
  538.                                                                         [edi+4]
  539.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  540.                                  + (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)
  541.         mov     ebx, [edi+4]
  542.         mov     cx, word[edi+8]  
  543.         or      ecx, [ebx + ftdi_context.index]
  544.         mov     word[ConfPacket+4], cx
  545.         xor     cx, cx
  546.         mov     word[ConfPacket+6], cx
  547.         jmp     .own_index
  548.  
  549.   .ftdi_read_pins:
  550.         DEBUGF 2, 'K : FTDI Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
  551.                                                                      [edi+4]
  552.         mov     ebx, [edi+4]
  553.         mov     dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
  554.                                  + (SIO_READ_PINS_REQUEST shl 8) + (0 shl 16)
  555.         mov     ecx, [ebx + ftdi_context.index]
  556.         mov     word[ConfPacket+4], cx
  557.         mov     word[ConfPacket+6], 1
  558.         lea     esi, [ConfPacket]
  559.         lea     edi, [EventData]
  560.         mov     ecx, esi
  561.         add     ecx, 8
  562.         mov     word[ConfPacket+8], 0
  563.         invoke  USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, ecx, \
  564.                                             1, control_callback, edi, 0
  565.         mov     eax, [EventData]
  566.         mov     ebx, [EventData+4]
  567.         invoke  WaitEvent
  568.         xor     ebx, ebx
  569.         mov     bx, word[ConfPacket+8]
  570.         mov     ecx, [ioctl]
  571.         mov     ecx, [ecx+output]
  572.         mov     [ecx], ebx
  573.         mov     eax, [EventData+8]
  574.         test    eax, eax
  575.         jz      .endswitch
  576.         jmp     .error
  577.        
  578.   .ftdi_set_wchunksize:
  579.         DEBUGF 2, 'K : FTDI Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
  580.                                                     [edi+8], [edi], [edi+4]
  581.         mov     ebx, [edi+4]
  582.         mov     ecx, [edi+8]
  583.         cmp     [ebx + ftdi_context.maxPacketSize], ecx
  584.         jg      .error
  585.         mov     [ebx + ftdi_context.writeBufChunkSize], ecx
  586.         jmp     .endswitch
  587.    
  588.   .ftdi_get_wchunksize:
  589.         DEBUGF 2, 'K : FTDI Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
  590.                                                                         [edi+4]
  591.         mov     esi, [edi+output]
  592.         mov     edi, [edi+input]
  593.         mov     ebx, [edi+4]
  594.         mov     ecx, [ebx + ftdi_context.writeBufChunkSize]
  595.         mov     [esi], ecx
  596.         jmp     .endswitch
  597.  
  598.   .ftdi_set_rchunksize:
  599.         DEBUGF 2, 'K : FTDI Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
  600.                                                     [edi+8], [edi], [edi+4]
  601.         mov     ebx, [edi+4]
  602.         mov     ecx, [edi+8]
  603.         cmp     [ebx + ftdi_context.maxPacketSize], ecx
  604.         jg      .error
  605.         mov     [ebx + ftdi_context.readBufChunkSize], ecx
  606.         jmp     .endswitch
  607.  
  608.   .ftdi_get_rchunksize:
  609.         DEBUGF 2, 'K : FTDI Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
  610.                                                                         [edi+4]
  611.         mov     esi, [edi+output]
  612.         mov     edi, [edi+input]
  613.         mov     ebx, [edi+4]
  614.         mov     ecx, [ebx + ftdi_context.readBufChunkSize]
  615.         mov     [esi], ecx
  616.         jmp     .endswitch        
  617.  
  618.   .ftdi_write_data:
  619.         DEBUGF 2, 'K : FTDI Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
  620.                                                             [edi], [edi+4]
  621.         mov     esi, edi
  622.         add     esi, 12        
  623.         mov     ebx, [edi+4]
  624.         ;---Dirty hack begin
  625.         mov     eax, [edi+8]
  626.         invoke  Kmalloc
  627.         test    eax, eax
  628.         jnz     @f
  629.         mov     esi, nomemory_msg
  630.         invoke  SysMsgBoardStr
  631.         jmp     .eventdestroy
  632.   @@:
  633.         mov     dword[ConfPacket], eax
  634.         mov     ecx, [edi+8]
  635.         push    edi
  636.         mov     edi, eax
  637.         rep movsb
  638.         pop     edi
  639.         mov     esi, dword[ConfPacket]
  640.         ;---Dirty hack end        
  641.         xor     ecx, ecx        ; ecx - offset      
  642.   .write_loop:
  643.         mov     edx, [edi+8]    ; edx - write_size
  644.         sub     edx, ecx
  645.         cmp     edx, [ebx + ftdi_context.writeBufChunkSize]
  646.         jle     .lessthanchunk_write
  647.         mov     edx, [ebx + ftdi_context.writeBufChunkSize]
  648.   .lessthanchunk_write:
  649.         add     esi, ecx
  650.         lea     eax, [EventData]
  651.         push    ecx ebx esi edi
  652.         invoke USBNormalTransferAsync, [ebx + ftdi_context.inEP], esi, edx, \
  653.                                             bulk_callback, eax, 1
  654.         mov     eax, [EventData]
  655.         mov     ebx, [EventData+4]
  656.         invoke  WaitEvent
  657.         pop     edi esi ebx ecx
  658.         cmp     [EventData+8], -1
  659.         jz      .error
  660.         add     ecx, [EventData+8]
  661.         cmp     ecx, [edi+8]
  662.         jge     .eventdestroy
  663.         jmp     .write_loop
  664.        
  665.   .ftdi_read_data:
  666.         DEBUGF 2, 'K : FTDI Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
  667.                                                             [edi], [edi+4]
  668.         mov     edi, [ioctl]
  669.         mov     esi, [edi+input]
  670.         mov     edi, [edi+output]
  671.         mov     ebx, [esi+4]    
  672.         ;---Dirty hack begin
  673.         mov     eax, [esi+8]
  674.         invoke  Kmalloc
  675.         test    eax, eax
  676.         jnz     @f
  677.         mov     esi, nomemory_msg
  678.         invoke  SysMsgBoardStr
  679.         jmp     .eventdestroy
  680.   @@:
  681.         mov     edi, eax
  682.         ; push    edi eax
  683.         ; mov     ecx, [esi+8]
  684.         ; xor     eax, eax
  685.         ; rep     stosb
  686.         ; pop     eax edi
  687.         mov     dword[ConfPacket], eax ; Store in ConfPacket ptr to allocated memory
  688.         ;---Dirty hack end        
  689.         xor     ecx, ecx
  690.   .read_loop:
  691.         mov     edx, [esi+8]
  692.         cmp     ecx, edx
  693.         jge     .read_end;jge     .eventdestroy ;part of Dirty hack
  694.         sub     edx, ecx
  695.         cmp     edx, [ebx + ftdi_context.readBufChunkSize]
  696.         jl      .lessthanchunk_read
  697.         mov     edx, [ebx + ftdi_context.readBufChunkSize]    
  698.   .lessthanchunk_read:
  699.         lea     eax, [EventData]
  700.         add     edi, ecx
  701.         push    esi edi ecx ebx
  702.         invoke  USBNormalTransferAsync, [ebx + ftdi_context.outEP], edi, edx, \
  703.                                             bulk_callback, eax, 1        
  704.         mov     eax, [EventData]
  705.         mov     ebx, [EventData+4]        
  706.         invoke  WaitEvent
  707.         pop     ebx ecx edi esi
  708.         cmp     [EventData+8], -1        
  709.         jz      .error
  710.         add     ecx, [EventData+8]
  711.         jmp     .read_loop
  712.         ;---Dirty hack begin        
  713.   .read_end:
  714.         mov     esi, dword[ConfPacket]
  715.         mov     edi, [ioctl]
  716.         mov     ecx, [edi+input]
  717.         mov     ecx, [ecx+8]
  718.         mov     edi, [edi+output]
  719.         rep     movsb
  720.         jmp     .eventdestroy
  721.         ;---Dirty hack end
  722.        
  723.   .ftdi_poll_modem_status:
  724.         DEBUGF 2, 'K : FTDI Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
  725.                                                                         [edi+4]
  726.         mov     ebx, [edi+4]
  727.         mov     dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
  728.                                  + (SIO_POLL_MODEM_STATUS_REQUEST shl 8) + (0 shl 16)
  729.         mov     ecx, [ebx + ftdi_context.index]
  730.         mov     word[ConfPacket+4], cx
  731.         mov     word[ConfPacket+6], 1
  732.         lea     esi, [ConfPacket]
  733.         lea     edi, [EventData]
  734.         mov     ecx, [ioctl]
  735.         mov     ecx, [ecx+output]
  736.         invoke  USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, ecx, \
  737.                                             2, control_callback, edi, 0
  738.         mov     eax, [EventData]
  739.         mov     ebx, [EventData+4]
  740.         invoke  WaitEvent
  741.         mov     ax, word[ecx]
  742.         xchg    ah, al
  743.         and     ah, 0xFF
  744.         mov     word[ecx], ax
  745.         jmp     .endswitch
  746.        
  747.   .ftdi_get_latency_timer:
  748.         DEBUGF 2, 'K : FTDI Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
  749.                                                                         [edi+4]
  750.         mov     ebx, [edi+4]
  751.         mov     dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE \
  752.                                 + (SIO_GET_LATENCY_TIMER_REQUEST shl 8) + (0 shl 16)
  753.         mov     ecx, [ebx + ftdi_context.index]
  754.         mov     word[ConfPacket+4], cx
  755.         mov     word[ConfPacket+6], 1
  756.         lea     esi, [ConfPacket]
  757.         lea     edi, [EventData]
  758.         mov     ecx, [ioctl]
  759.         mov     ecx, [ecx+output]
  760.         invoke  USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, ecx, \
  761.                                             2, control_callback, edi, 0
  762.         mov     eax, [EventData]
  763.         mov     ebx, [EventData+4]
  764.         invoke  WaitEvent
  765.         jmp     .endswitch
  766.                
  767.   .ftdi_get_list:
  768.         DEBUGF 2, 'K : FTDI devices list request\n'  
  769.         mov     edi, [edi+output]
  770.         xor     ecx, ecx
  771.         call    linkedlist_gethead
  772.         test    eax, eax
  773.         jz      .emptylist
  774.         push    edi
  775.         add     edi, 4        
  776.   .nextdev:
  777.         inc     ecx
  778.         cmp     [eax + ftdi_context.lockPID], 0
  779.         jnz      .dev_is_locked        
  780.         mov     dword[edi], 'NLKD'
  781.         jmp     .nextfields
  782.   .dev_is_locked:
  783.         mov     dword[edi], 'LCKD'
  784.   .nextfields:
  785.         mov     bl, [eax + ftdi_context.chipType]
  786.         mov     [edi+4], ebx
  787.         mov     [edi+8], eax
  788.         add     edi, 12
  789.         mov     eax, [eax + ftdi_context.next_context]
  790.         test    eax, eax
  791.         jnz     .nextdev
  792.         pop     edi
  793.   .emptylist:
  794.         mov     [edi], ecx
  795.         jmp     .endswitch
  796.  
  797.   .ftdi_lock:
  798.         DEBUGF 2, 'K : FTDI Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]  
  799.         mov     esi, [edi+input]
  800.         mov     ebx, [esi+4]
  801.         mov     eax, [ebx + ftdi_context.lockPID]
  802.         test    eax, eax
  803.         jnz     .lockedby
  804.         mov     eax, [esi]
  805.         mov     [ebx + ftdi_context.lockPID], eax
  806.   .lockedby:
  807.         mov     edi, [edi+output]
  808.         mov     [edi], eax
  809.         jmp     .endswitch
  810.        
  811.   .ftdi_unlock:
  812.         DEBUGF 2, 'K : FTDI Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
  813.         mov     esi, [edi+input]
  814.         mov     edi, [edi+output]
  815.         mov     ebx, [esi+4]
  816.         mov     eax, [ebx + ftdi_context.lockPID]
  817.         cmp     eax, [esi]
  818.         jnz     .unlockimp
  819.         mov     [ebx + ftdi_context.lockPID], 0
  820.         mov     dword[edi], 0
  821.         jmp     .endswitch  
  822.   .unlockimp:    
  823.         mov     [edi], eax
  824.         jmp     .endswitch
  825.  
  826. H_CLK = 120000000
  827. C_CLK = 48000000        
  828.   .ftdi_set_baudrate:
  829.         DEBUGF 2, 'K : FTDI Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
  830.                    [edi+8], [edi], [edi+4]
  831.         mov     ebx, [edi+4]
  832.         cmp     [ebx + ftdi_context.chipType], TYPE_2232H
  833.         jl      .c_clk        
  834.         imul    eax, [edi+8], 10
  835.         cmp     eax, H_CLK / 0x3FFF        
  836.         jle     .c_clk
  837.   .h_clk:
  838.         cmp     dword[edi+8], H_CLK/10
  839.         jl      .h_nextbaud1
  840.         xor     edx, edx
  841.         mov     ecx, H_CLK/10
  842.         jmp     .calcend
  843.        
  844.   .c_clk:
  845.         cmp     dword[edi+8], C_CLK/16
  846.         jl      .c_nextbaud1
  847.         xor     edx, edx
  848.         mov     ecx, C_CLK/16
  849.         jmp     .calcend  
  850.  
  851.   .h_nextbaud1:
  852.         cmp     dword[edi+8], H_CLK/(10 + 10/2)
  853.         jl      .h_nextbaud2
  854.         mov     edx, 1
  855.         mov     ecx, H_CLK/(10 + 10/2)
  856.         jmp     .calcend
  857.        
  858.   .c_nextbaud1:
  859.         cmp     dword[edi+8], C_CLK/(16 + 16/2)
  860.         jl      .c_nextbaud2
  861.         mov     edx, 1
  862.         mov     ecx, C_CLK/(16 + 16/2)
  863.         jmp     .calcend        
  864.        
  865.   .h_nextbaud2:
  866.         cmp     dword[edi+8], H_CLK/(2*10)
  867.         jl      .h_nextbaud3
  868.         mov     edx, 2
  869.         mov     ecx, H_CLK/(2*10)
  870.         jmp     .calcend
  871.        
  872.   .c_nextbaud2:  
  873.         cmp     dword[edi+8], C_CLK/(2*16)
  874.         jl      .c_nextbaud3
  875.         mov     edx, 2
  876.         mov     ecx, C_CLK/(2*16)
  877.         jmp     .calcend        
  878.        
  879.   .h_nextbaud3:
  880.         mov     eax, H_CLK*16/10  ; eax - best_divisor
  881.         xor     edx, edx
  882.         div     dword[edi+8]      ; [edi+8] - baudrate
  883.         push    eax
  884.         and     eax, 1
  885.         pop     eax
  886.         shr     eax, 1
  887.         jz      .h_rounddowndiv     ; jump by result of and eax, 1
  888.         inc     eax
  889.   .h_rounddowndiv:
  890.         cmp     eax, 0x20000
  891.         jle     .h_best_divok
  892.         mov     eax, 0x1FFFF
  893.   .h_best_divok:
  894.         mov     ecx, eax        
  895.         mov     eax, H_CLK*16/10
  896.         xor     edx, edx
  897.         div     ecx
  898.         xchg    ecx, eax            ; ecx - best_baud
  899.         push    ecx
  900.         and     ecx, 1
  901.         pop     ecx
  902.         shr     ecx, 1
  903.         jz      .rounddownbaud
  904.         inc     ecx
  905.         jmp     .rounddownbaud
  906.        
  907.   .c_nextbaud3:
  908.         mov     eax, C_CLK        ; eax - best_divisor
  909.         xor     edx, edx
  910.         div     dword[edi+8]      ; [edi+8] - baudrate
  911.         push    eax
  912.         and     eax, 1
  913.         pop     eax
  914.         shr     eax, 1
  915.         jnz     .c_rounddowndiv     ; jump by result of and eax, 1
  916.         inc     eax
  917.   .c_rounddowndiv:
  918.         cmp     eax, 0x20000
  919.         jle     .c_best_divok
  920.         mov     eax, 0x1FFFF
  921.   .c_best_divok:
  922.         mov     ecx, eax        
  923.         mov     eax, C_CLK
  924.         xor     edx, edx
  925.         div     ecx
  926.         xchg    ecx, eax            ; ecx - best_baud
  927.         push    ecx
  928.         and     ecx, 1
  929.         pop     ecx
  930.         shr     ecx, 1
  931.         jnz     .rounddownbaud
  932.         inc     ecx
  933.        
  934.   .rounddownbaud:
  935.         mov     edx, eax            ; edx - encoded_divisor
  936.         shr     edx, 3
  937.         and     eax, 0x7      
  938.         push    7 6 5 1 4 2 3 0              
  939.         mov     eax, [esp+eax*4]
  940.         shl     eax, 14
  941.         or      edx, eax        
  942.         add     esp, 32
  943.        
  944.   .calcend:
  945.         mov     eax, edx        ; eax - *value
  946.         mov     ecx, edx        ; ecx - *index
  947.         and     eax, 0xFFFF
  948.         cmp     [ebx + ftdi_context.chipType], TYPE_2232H
  949.         jge     .foxyindex        
  950.         shr     ecx, 16
  951.         jmp     .preparepacket
  952.   .foxyindex:
  953.         shr     ecx, 8
  954.         and     ecx, 0xFF00
  955.         or      ecx, [ebx + ftdi_context.index]
  956.        
  957.   .preparepacket:
  958.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
  959.                                 + (SIO_SET_BAUDRATE_REQUEST shl 8)
  960.         mov     word[ConfPacket+2], ax
  961.         mov     word[ConfPacket+4], cx
  962.         mov     word[ConfPacket+6], 0
  963.         jmp     .own_index        
  964.        
  965. endp
  966. restore   handle
  967. restore   io_code
  968. restore   input
  969. restore   inp_size
  970. restore   output
  971. restore   out_size
  972.  
  973.  
  974. proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
  975.                                .buffer:DWORD, .length:DWORD, .calldata:DWORD  
  976.    
  977.         DEBUGF 1, 'K : status is %d\n', [.status]
  978.         mov     ecx, [.calldata]
  979.         mov     eax, [ecx]
  980.         mov     ebx, [ecx+4]
  981.         mov     edx, [.status]
  982.         mov     [ecx+8], edx
  983.         xor     esi, esi
  984.         xor     edx, edx
  985.         invoke  RaiseEvent              
  986.         ret
  987. endp
  988.  
  989. proc bulk_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
  990.                             .buffer:DWORD, .length:DWORD, .calldata:DWORD
  991.  
  992.         DEBUGF 1, 'K : status is %d\n', [.status]        
  993.         mov     ecx, [.calldata]
  994.         mov     eax, [ecx]
  995.         mov     ebx, [ecx+4]
  996.         cmp     [.status], 0
  997.         jz      .normal
  998.         cmp     [.status], 9
  999.         jne     .error
  1000.   .normal:
  1001.         mov     edx, [.length]
  1002.         mov     [ecx+8], edx
  1003.         jmp     .ok
  1004.   .error:
  1005.         mov     [ecx+8], dword -1
  1006.   .ok:    
  1007.         xor     esi, esi
  1008.         xor     edx, edx
  1009.         invoke  RaiseEvent            
  1010.         ret
  1011. endp
  1012.  
  1013. proc DeviceDisconnected stdcall uses  ebx esi edi, .device_data:DWORD
  1014.  
  1015.         DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.device_data]
  1016.         mov     eax, [.device_data]
  1017.         call    linkedlist_unlink
  1018.         invoke  Kfree
  1019.         ret          
  1020. endp
  1021.  
  1022. include 'linkedlist.inc'
  1023.  
  1024. align 4
  1025.  
  1026. ; Structure with callback functions.
  1027. usb_functions:
  1028.         dd      12
  1029.         dd      AddDevice
  1030.         dd      DeviceDisconnected
  1031.  
  1032. data fixups
  1033. end data        
  1034.        
  1035. ;for DEBUGF macro
  1036. include_debug_strings