Subversion Repositories Kolibri OS

Rev

Rev 5036 | Rev 5038 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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