Subversion Repositories Kolibri OS

Rev

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