Subversion Repositories Kolibri OS

Rev

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