Subversion Repositories Kolibri OS

Rev

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