Subversion Repositories Kolibri OS

Rev

Rev 4997 | Rev 5018 | 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. readBufChunkSize        dd      ?
  126. writeBufChunkSize       dd      ?
  127. interface               dd      ?
  128. index                   dd      ?
  129. inEP                    dd      ?
  130. outEP                   dd      ?
  131. nullP                   dd      ?
  132. lockPID                 dd      ?
  133. next_context            dd      ?
  134. ends
  135.  
  136. struct IOCTL
  137. handle                  dd      ?
  138. io_code                 dd      ?
  139. input                   dd      ?
  140. inp_size                dd      ?
  141. output                  dd      ?
  142. out_size                dd      ?
  143. ends
  144.  
  145. struct usb_descr
  146. bLength                 db      ?
  147. bDescriptorType         db      ?
  148. bcdUSB                  dw      ?
  149. bDeviceClass            db      ?
  150. bDeviceSubClass         db      ?
  151. bDeviceProtocol         db      ?
  152. bMaxPacketSize0         db      ?
  153. idVendor                dw      ?
  154. idProduct               dw      ?
  155. bcdDevice               dw      ?
  156. iManufacturer           db      ?
  157. iProduct                db      ?
  158. iSerialNumber           db      ?
  159. bNumConfigurations      db      ?
  160. ends
  161.  
  162. struct conf_packet
  163. bmRequestType           db      ?
  164. bRequest                db      ?
  165. wValue                  dw      ?
  166. wIndex                  dw      ?
  167. wLength                 dw      ?
  168. ends
  169.  
  170. section '.flat' code readable align 16
  171. ; The start procedure.
  172. proc START stdcall, .reason:DWORD
  173.  
  174.         xor     eax, eax        ; initialize return value
  175.         cmp     [.reason], 1    ; compare the argument
  176.         jnz     .nothing                
  177.         stdcall RegUSBDriver, my_driver, service_proc, usb_functions
  178.  
  179. .nothing:
  180.         ret
  181. endp
  182.  
  183.  
  184. proc AddDevice stdcall uses ebx esi, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
  185.        
  186.         stdcall USBGetParam, [.config_pipe], 0
  187.         mov     edx, eax
  188.         DEBUGF 1,'K : Device detected Vendor: %x\n', [eax+usb_descr.idVendor]
  189.         cmp     word[eax+usb_descr.idVendor], 0x0403
  190.         jnz     .notftdi
  191.         DEBUGF 1,'K : FTDI USB device detected\n'
  192.         movi    eax, sizeof.ftdi_context
  193.         call    Kmalloc
  194.         test    eax, eax
  195.         jnz     @f
  196.         mov     esi, nomemory_msg
  197.         call    SysMsgBoardStr
  198.         jmp     .nothing
  199.   @@:
  200.         DEBUGF 1,'K : Adding struct to list %x\n', eax
  201.         call    linkedlist_add
  202.        
  203.         mov     ebx, [.config_pipe]
  204.         mov     [eax + ftdi_context.nullP], ebx
  205.         mov     [eax + ftdi_context.index], 0
  206.         mov     [eax + ftdi_context.lockPID], 0
  207.         mov     [eax + ftdi_context.readBufChunkSize], 64
  208.         mov     [eax + ftdi_context.writeBufChunkSize], 64
  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.         mov     eax, ebx
  247.         ret        
  248.            
  249.   .notftdi:
  250.         DEBUGF 1,'K : Skipping not FTDI device\n'
  251.   .nothing:        
  252.         xor     eax, eax
  253.         ret
  254. endp
  255.  
  256.  
  257. handle     equ  IOCTL.handle
  258. io_code    equ  IOCTL.io_code
  259. input      equ  IOCTL.input
  260. inp_size   equ  IOCTL.inp_size
  261. output     equ  IOCTL.output
  262. out_size   equ  IOCTL.out_size
  263.  
  264. align 4
  265. proc service_proc stdcall uses ebx esi edi, ioctl:DWORD
  266. locals
  267. ConfPacket  rb  8
  268. EventData   rd  3
  269. endl
  270.         mov     edi, [ioctl]
  271.         mov     eax, [edi+io_code]
  272.         DEBUGF 1,'K : FTDI got the request: %d\n', eax
  273.         test    eax, eax           ;0
  274.         jz      .version
  275.         dec     eax                 ;1
  276.         jz      .ftdi_get_list
  277.        
  278.         push    eax
  279.         mov     esi, [edi+input]
  280.         mov     eax, [esi+4]
  281.         call    linkedlist_isvalid
  282.         test    eax, eax
  283.         pop     eax        
  284.         jnz     .endswitch
  285.        
  286.         dec     eax
  287.         jz      .ftdi_lock      ;2
  288.         dec     eax
  289.         jz      .ftdi_unlock    ;3
  290.        
  291.         mov     ebx, [esi+4]
  292.         mov     ecx, [ebx + ftdi_context.lockPID]    
  293.         cmp     ecx, [esi]
  294.         jz      .pid_ok
  295.         mov     esi, [edi+output]
  296.         mov     dword[esi], 'LCKD'
  297.         jmp     .endswitch
  298.        
  299.   .pid_ok:  
  300.         push    eax edi
  301.         mov     ecx, 0x80000000
  302.         cmp     eax, 17
  303.         je     .bulkevent
  304.         cmp     eax, 18
  305.         je      .bulkevent
  306.         xor     ecx, ecx
  307.   .bulkevent:                
  308.         xor     esi, esi
  309.         call    CreateEvent        
  310.         mov     [EventData], eax
  311.         mov     [EventData+4], edx
  312.         pop     edi eax
  313.        
  314.         dec     eax                 ;4
  315.         jz      .ftdi_set_bitmode
  316.         dec     eax                 ;5
  317.         jz      .ftdi_setrtshigh  
  318.         dec     eax                 ;6
  319.         jz      .ftdi_setrtslow  
  320.         dec     eax                 ;7
  321.         jz      .ftdi_setdtrhigh
  322.         dec     eax                 ;8
  323.         jz      .ftdi_setdtrlow
  324.         dec     eax                 ;9
  325.         jz      .ftdi_usb_reset
  326.         dec     eax                 ;10
  327.         jz      .ftdi_setflowctrl
  328.         dec     eax                 ;11
  329.         jz      .ftdi_set_event_char
  330.         dec     eax                 ;12
  331.         jz      .ftdi_set_error_char
  332.         dec     eax                 ;13
  333.         jz      .ftdi_set_latency_timer
  334.         dec     eax                 ;14
  335.         jz      .ftdi_get_latency_timer
  336.         dec     eax                 ;15
  337.         jz      .ftdi_read_pins
  338.         dec     eax                 ;16
  339.         jz      .ftdi_poll_modem_status
  340.         dec     eax                 ;17
  341.         jz      .ftdi_write_data
  342.         dec     eax                 ;18
  343.         jz      .ftdi_read_data
  344.         dec     eax                 ;19
  345.         jz      .ftdi_set_baudrate
  346.         dec     eax                 ;20
  347.         jz      .ftdi_set_line_property
  348.         dec     eax                 ;21
  349.         jz      .ftdi_purge_rx_buf
  350.         dec     eax                 ;22
  351.         jz      .ftdi_purge_tx_buf
  352.                
  353.   .version:    
  354.   .endswitch:
  355.         xor     eax, eax
  356.             ret
  357.        
  358.   .ftdi_out_control_transfer:
  359.         mov     ebx, [edi]
  360.         mov     cx, word[ebx + ftdi_context.index]
  361.         mov     word[ConfPacket+4], cx
  362.         xor     cx, cx
  363.         mov     word[ConfPacket+6], cx
  364.   .own_index:
  365.         mov    ebx, [edi+4]
  366.         DEBUGF 1,'K : ConfPacket %x %x\n', [ConfPacket], [ConfPacket+4]          
  367.         lea     esi, [ConfPacket]
  368.         lea     edi, [EventData]        
  369.         stdcall USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, 0, 0, control_callback, edi, 0
  370.         DEBUGF 1, 'K : Returned value is %d\n', eax
  371.         mov     eax, [EventData]
  372.         mov     ebx, [EventData+4]
  373.         call    WaitEvent    
  374.         jmp     .endswitch
  375.        
  376.   .ftdi_set_bitmode:
  377.         DEBUGF 1,'K : FTDI Seting bitmode\n'                  
  378.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_BITMODE_REQUEST shl 8)
  379.         mov     edi, [edi+input]        
  380.         mov     dx, word[edi+8]                
  381.         mov     word[ConfPacket+2], dx                                        
  382.         jmp     .ftdi_out_control_transfer    
  383.  
  384.   .ftdi_setrtshigh:
  385.         DEBUGF 1,'K : FTDI Setting RTS pin HIGH\n'                    
  386.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_MODEM_CTRL_REQUEST shl 8) + (SIO_SET_RTS_HIGH shl 16)
  387.         jmp     .ftdi_out_control_transfer        
  388.  
  389.   .ftdi_setrtslow:
  390.         DEBUGF 1,'K : FTDI Setting RTS pin LOW\n'            
  391.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_MODEM_CTRL_REQUEST shl 8) + (SIO_SET_RTS_LOW shl 16)
  392.         jmp     .ftdi_out_control_transfer        
  393.        
  394.   .ftdi_setdtrhigh:
  395.         DEBUGF 1,'K : FTDI Setting DTR pin HIGH\n'                    
  396.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_MODEM_CTRL_REQUEST shl 8) + (SIO_SET_DTR_HIGH shl 16)
  397.         jmp     .ftdi_out_control_transfer        
  398.  
  399.   .ftdi_setdtrlow:
  400.         DEBUGF 1,'K : FTDI Setting DTR pin LOW\n'            
  401.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_MODEM_CTRL_REQUEST shl 8) + (SIO_SET_DTR_LOW shl 16)
  402.         jmp     .ftdi_out_control_transfer        
  403.        
  404.   .ftdi_usb_reset:
  405.         DEBUGF 1,'K : FTDI Reseting\n'
  406.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_RESET_REQUEST shl 8) + (SIO_RESET_SIO shl 16)
  407.         jmp     .ftdi_out_control_transfer
  408.        
  409.   .ftdi_purge_rx_buf:
  410.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_RESET_REQUEST shl 8) + (SIO_RESET_PURGE_RX shl 16)
  411.         jmp     .ftdi_out_control_transfer
  412.        
  413.   .ftdi_purge_tx_buf:
  414.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_RESET_REQUEST shl 8) + (SIO_RESET_PURGE_TX shl 16)
  415.         jmp     .ftdi_out_control_transfer
  416.  
  417. H_CLK = 120000000
  418. C_CLK = 48000000        
  419.   .ftdi_set_baudrate:
  420.         mov     edi, [edi+input]
  421.         mov     ebx, [edi]
  422.         cmp     [ebx + ftdi_context.chipType], TYPE_2232H
  423.         jl      .c_clk        
  424.         imul    eax, [edi+8], 10
  425.         cmp     eax, H_CLK / 0x3FFF        
  426.         jle     .c_clk
  427.   .h_clk:      
  428.         cmp     dword[edi+8], H_CLK/10
  429.         jl      .h_nextbaud1
  430.         xor     edx, edx
  431.         mov     ecx, H_CLK/10
  432.         jmp     .calcend
  433.        
  434.   .c_clk:
  435.         cmp     dword[edi+8], C_CLK/10
  436.         jl      .c_nextbaud1
  437.         xor     edx, edx
  438.         mov     ecx, C_CLK/10
  439.         jmp     .calcend  
  440.  
  441.   .h_nextbaud1:
  442.         cmp     dword[edi+8], H_CLK/(10 + 10/2)
  443.         jl      .h_nextbaud2
  444.         mov     edx, 1
  445.         mov     ecx, H_CLK/(10 + 10/2)
  446.         jmp     .calcend
  447.        
  448.   .c_nextbaud1:
  449.         cmp     dword[edi+8], C_CLK/(10 + 10/2)
  450.         jl      .c_nextbaud2
  451.         mov     edx, 1
  452.         mov     ecx, C_CLK/(10 + 10/2)
  453.         jmp     .calcend        
  454.        
  455.   .h_nextbaud2:      
  456.         cmp     dword[edi+8], H_CLK/(2*10)
  457.         jl      .h_nextbaud3
  458.         mov     edx, 2
  459.         mov     ecx, H_CLK/(2*10)
  460.         jmp     .calcend
  461.        
  462.   .c_nextbaud2:      
  463.         cmp     dword[edi+8], C_CLK/(2*10)
  464.         jl      .c_nextbaud3
  465.         mov     edx, 2
  466.         mov     ecx, C_CLK/(2*10)
  467.         jmp     .calcend        
  468.        
  469.   .h_nextbaud3:
  470.         mov     eax, H_CLK*16/10  ; eax - best_divisor
  471.         div     dword[edi+8]      ; [edi+8] - baudrate
  472.         push    eax
  473.         and     eax, 1
  474.         pop     eax
  475.         shr     eax, 1
  476.         jz      .h_rounddowndiv     ; jump by result of and eax, 1
  477.         inc     eax
  478.   .h_rounddowndiv:
  479.         cmp     eax, 0x20000
  480.         jle     .h_best_divok
  481.         mov     eax, 0x1FFFF
  482.   .h_best_divok:
  483.         mov     ecx, eax        
  484.         mov     eax, H_CLK*16/10
  485.         div     ecx
  486.         xchg    ecx, eax            ; ecx - best_baud
  487.         push    ecx
  488.         and     ecx, 1
  489.         pop     ecx
  490.         shr     ecx, 1
  491.         jz      .rounddownbaud
  492.         inc     ecx
  493.         jmp     .rounddownbaud
  494.        
  495.   .c_nextbaud3:
  496.         mov     eax, C_CLK*16/10  ; eax - best_divisor
  497.         div     dword[edi+8]      ; [edi+8] - baudrate
  498.         push    eax
  499.         and     eax, 1
  500.         pop     eax
  501.         shr     eax, 1
  502.         jz      .c_rounddowndiv     ; jump by result of and eax, 1
  503.         inc     eax
  504.   .c_rounddowndiv:
  505.         cmp     eax, 0x20000
  506.         jle     .c_best_divok
  507.         mov     eax, 0x1FFFF
  508.   .c_best_divok:
  509.         mov     ecx, eax        
  510.         mov     eax, C_CLK*16/10
  511.         div     ecx
  512.         xchg    ecx, eax            ; ecx - best_baud
  513.         push    ecx
  514.         and     ecx, 1
  515.         pop     ecx
  516.         shr     ecx, 1
  517.         jz      .rounddownbaud
  518.         inc     ecx
  519.        
  520.   .rounddownbaud:
  521.         mov     edx, eax            ; edx - encoded_divisor
  522.         shr     edx, 3
  523.         and     eax, 0x7
  524.         push    esp
  525.         push    7 6 5 1 4 2 3 0
  526.         mov     eax, [esp+eax*4]
  527.         shl     eax, 14
  528.         or      edx, eax
  529.         mov     esp, [esp+36]
  530.        
  531.   .calcend:
  532.         mov     eax, edx        ; eax - *value
  533.         mov     ecx, edx        ; ecx - *index
  534.         and     eax, 0xFFFF
  535.         cmp     [ebx + ftdi_context.chipType], TYPE_2232H
  536.         jge     .foxyindex        
  537.         shr     ecx, 16
  538.         jmp     .preparepacket
  539.   .foxyindex:
  540.         shr     ecx, 8
  541.         and     ecx, 0xFF00
  542.         or      ecx, [ebx + ftdi_context.index]
  543.        
  544.   .preparepacket:
  545.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_BAUDRATE_REQUEST shl 8)
  546.         mov     word[ConfPacket+2], ax
  547.         mov     word[ConfPacket+4], cx
  548.         mov     word[ConfPacket+6], 0
  549.         jmp     .own_index
  550.      
  551.   .ftdi_set_line_property:
  552.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_DATA_REQUEST shl 8)
  553.         mov     edi, [edi+input]        
  554.         mov     dx, word[edi+8]                
  555.         mov     word[ConfPacket+2], dx
  556.         jmp     .ftdi_out_control_transfer
  557.        
  558.   .ftdi_set_latency_timer:
  559.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_LATENCY_TIMER_REQUEST shl 8)
  560.         mov     edi, [edi+input]        
  561.         mov     dx, word[edi+8]                
  562.         mov     word[ConfPacket+2], dx        
  563.         jmp     .ftdi_out_control_transfer
  564.        
  565.   .ftdi_set_event_char:
  566.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_EVENT_CHAR_REQUEST shl 8)
  567.         mov     edi, [edi+input]        
  568.         mov     dx, word[edi+8]                
  569.         mov     word[ConfPacket+2], dx
  570.         jmp     .ftdi_out_control_transfer
  571.  
  572.   .ftdi_set_error_char:
  573.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_ERROR_CHAR_REQUEST shl 8)
  574.         mov     edi, [edi+input]        
  575.         mov     dx, word[edi+8]                
  576.         mov     word[ConfPacket+2], dx
  577.         jmp     .ftdi_out_control_transfer
  578.        
  579.   .ftdi_setflowctrl:
  580.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)      
  581.         mov     edi, [edi+input]
  582.         mov     ebx, [edi]
  583.         mov     cx, word[edi+8]  
  584.         or      ecx, [ebx + ftdi_context.index]
  585.         mov     word[ConfPacket+4], cx
  586.         xor     cx, cx
  587.         mov     word[ConfPacket+6], cx
  588.         jmp     .own_index
  589.  
  590.   .ftdi_read_pins:
  591.         DEBUGF 1,'K : FTDI Reading pins\n'
  592.         mov     edi, [edi+input]                                  
  593.         mov     ebx, [edi]
  594.         mov     dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE + (SIO_READ_PINS_REQUEST shl 8) + (0 shl 16)
  595.         mov     ecx, [ebx + ftdi_context.index]
  596.         mov     word[ConfPacket+4], cx
  597.         mov     word[ConfPacket+6], 1
  598.         lea     esi, [ConfPacket]
  599.         lea     edi, [EventData]
  600.         mov     ecx, [ioctl]
  601.         mov     ecx, [ecx+output]
  602.         stdcall USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, ecx, 1, control_callback, edi, 0
  603.         DEBUGF 1, 'K : Returned value is %d\n', eax
  604.         mov     eax, [EventData]
  605.         mov     ebx, [EventData+4]
  606.         call    WaitEvent    
  607.         jmp     .endswitch
  608.  
  609.   .ftdi_write_data:
  610.         mov     edi, [edi+input]        
  611.         mov     ebx, [edi+4]
  612.         xor     ecx, ecx        ; ecx - offset    
  613.   .dataleft:        
  614.         mov     edx, [ebx + ftdi_context.writeBufChunkSize] ; edx - write_size
  615.         push    ecx
  616.         add     ecx, edx
  617.         cmp     ecx, [edi+8]    ; [edi+8] - size
  618.         pop     ecx
  619.         jle     .morethanchunk_write
  620.         mov     edx, [edi+8]          
  621.         sub     edx, ecx
  622.   .morethanchunk_write:
  623.         lea     eax, [EventData]
  624.         stdcall USBNormalTransferAsync, [ebx + ftdi_context.inEP], [edi+12+ecx], edx, bulk_callback, eax, 1
  625.         push    ebx edi edx ecx
  626.         mov     eax, [EventData]
  627.         mov     ebx, [EventData+4]
  628.         call    WaitEvent
  629.         pop     ecx edx edi ebx
  630.         cmp     [EventData+8], -1
  631.         jz      .endswitch;jz      .error
  632.         add     ecx, [EventData+8]
  633.         cmp     ecx, [edi+8]
  634.         jl      .dataleft
  635.         jmp     .endswitch
  636.        
  637.   .ftdi_read_data:
  638.         mov     esi, [edi+input]
  639.         mov     edi, [edi+output]
  640.         mov     ebx, [esi+4]        
  641.         xor     ecx, ecx
  642.   .read_loop:
  643.         mov     edx, [esi+8]
  644.         sub     edx, ecx
  645.         test    edx, edx
  646.         jz      .endswitch
  647.         cmp     edx, [ebx + ftdi_context.readBufChunkSize]
  648.         jl      .lessthanchunk_read
  649.         mov     edx, [ebx + ftdi_context.readBufChunkSize]    
  650.   .lessthanchunk_read:
  651.         lea     eax, [EventData]
  652.         stdcall USBNormalTransferAsync, [ebx + ftdi_context.outEP], [edi+ecx], edx, bulk_callback, eax, 1        
  653.         push    esi edi ecx ebx
  654.         mov     eax, [EventData]
  655.         mov     ebx, [EventData+4]        
  656.         call    WaitEvent
  657.         pop     ebx ecx edi esi
  658.         cmp     [EventData+8], -1
  659.         jz      .endswitch;jz      .error
  660.         add     ecx, [EventData+8]
  661.         jmp     .read_loop
  662.        
  663.   .ftdi_poll_modem_status:
  664.         mov     edi, [edi+input]                                  
  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.         DEBUGF 1, 'K : Returned value is %d\n', eax
  676.         mov     eax, [EventData]
  677.         mov     ebx, [EventData+4]
  678.         call    WaitEvent
  679.         mov     ax, word[ecx]
  680.         xchg    ah, al
  681.         and     ah, 0xFF
  682.         mov     word[ecx], ax
  683.         jmp     .endswitch
  684.        
  685.   .ftdi_get_latency_timer:
  686.         mov     edi, [edi+input]                                  
  687.         mov     ebx, [edi+4]
  688.         mov     dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE + (SIO_GET_LATENCY_TIMER_REQUEST shl 8) + (0 shl 16)
  689.         mov     ecx, [ebx + ftdi_context.index]
  690.         mov     word[ConfPacket+4], cx
  691.         mov     word[ConfPacket+6], 1
  692.         lea     esi, [ConfPacket]
  693.         lea     edi, [EventData]
  694.         mov     ecx, [ioctl]
  695.         mov     ecx, [ecx+output]
  696.         stdcall USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, ecx, 2, control_callback, edi, 0
  697.         DEBUGF 1, 'K : Returned value is %d\n', eax
  698.         mov     eax, [EventData]
  699.         mov     ebx, [EventData+4]
  700.         call    WaitEvent
  701.         jmp     .endswitch
  702.                
  703.   .ftdi_get_list:
  704.         call    linkedlist_gethead                        
  705.         mov     edi, [edi+output]
  706.         push    edi
  707.         add     edi, 4
  708.         xor     ecx, ecx
  709.   .nextdev:
  710.         inc     ecx
  711.         cmp     [eax + ftdi_context.lockPID], 0
  712.         jnz      .dev_is_locked        
  713.         mov     dword[edi], 'NLKD'
  714.         jmp     .nextfields
  715.   .dev_is_locked:
  716.         mov     dword[edi], 'LCKD'
  717.   .nextfields:
  718.         mov     bl, [eax + ftdi_context.chipType]
  719.         mov     [edi+4], ebx
  720.         mov     [edi+8], eax
  721.         add     edi, 12
  722.         mov     eax, [eax + ftdi_context.next_context]
  723.         test    eax, eax
  724.         jnz     .nextdev
  725.         pop     edi
  726.         mov     [edi], ecx
  727.         jmp     .endswitch
  728.                    
  729.   .ftdi_lock:
  730.         DEBUGF 1, 'K : FTDI lock attempt\n'
  731.         mov     esi, [edi+input]
  732.         mov     ebx, [esi+4]
  733.         mov     eax, [ebx + ftdi_context.lockPID]
  734.         test    eax, eax
  735.         jnz     .lockedby
  736.         DEBUGF 1, 'K : Lock success\n'
  737.         mov     eax, [esi]
  738.         mov     [ebx + ftdi_context.lockPID], eax
  739.   .lockedby:
  740.         mov     edi, [edi+output]
  741.         mov     [edi], eax
  742.         jmp     .endswitch
  743.        
  744.   .ftdi_unlock:
  745.         mov     esi, [edi+input]
  746.         mov     edi, [edi+output]
  747.         mov     ebx, [esi+4]
  748.         mov     eax, [ebx + ftdi_context.lockPID]
  749.         cmp     eax, [esi]
  750.         jnz     .unlockimp
  751.         mov     [ebx + ftdi_context.lockPID], 0
  752.         mov     dword[edi], 0
  753.         jmp     .endswitch  
  754.   .unlockimp:    
  755.         mov     [edi], eax
  756.         jmp     .endswitch  
  757.        
  758. endp
  759. restore   handle
  760. restore   io_code
  761. restore   input
  762. restore   inp_size
  763. restore   output
  764. restore   out_size
  765.  
  766.  
  767. align 4
  768. proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, .buffer:DWORD, .length:DWORD, .calldata:DWORD  
  769.    
  770.         DEBUGF 1, 'K : status is %d\n', [.status]
  771.         mov     ecx, [.calldata]
  772.         mov     eax, [ecx]
  773.         mov     ebx, [ecx+4]
  774.         mov     edx, [.status]
  775.         mov     [ecx+8], edx
  776.         xor     esi, esi
  777.         xor     edx, edx
  778.         call    RaiseEvent              
  779.         ret
  780. endp
  781.  
  782. proc bulk_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, .buffer:DWORD, .length:DWORD, .calldata:DWORD
  783.  
  784.         DEBUGF 1, 'K : status is %d\n', [.status]        
  785.         mov     ecx, [.calldata]
  786.         mov     eax, [ecx]
  787.         mov     ebx, [ecx+4]
  788.         cmp     [.status], 0
  789.         jg      .error?
  790.   .error?:
  791.         cmp     [.status], 9
  792.         jne     .error
  793.         mov     edx, [.length]
  794.         mov     [ecx+8], edx
  795.         jmp     .ok
  796.   .error:
  797.         mov     [ecx+8], dword -1
  798.   .ok:
  799.         xor     esi, esi
  800.         xor     edx, edx
  801.         ;mov     edx, 0x80000000
  802.         call    RaiseEvent            
  803.         ret
  804. endp
  805.  
  806. proc DeviceDisconnected stdcall uses  ebx esi edi, .device_data:DWORD
  807.  
  808.         DEBUGF 1, 'K : FTDI deleting device data %x\n', [.device_data]
  809.         mov     eax, [.device_data]
  810.         call    linkedlist_delete
  811.         ret          
  812. endp
  813.  
  814. include 'linkedlist.inc'
  815.        
  816. ; Exported variable: kernel API version.
  817. align 4
  818. version dd      50005h
  819. ; Structure with callback functions.
  820. usb_functions:
  821.         dd      12
  822.         dd      AddDevice
  823.         dd      DeviceDisconnected
  824.  
  825. ;for DEBUGF macro
  826. include_debug_strings
  827.  
  828.  
  829.  
  830.  
  831. ; for uninitialized data
  832. ;section '.data' data readable writable align 16
  833.