Subversion Repositories Kolibri OS

Rev

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