Subversion Repositories Kolibri OS

Rev

Rev 4985 | Rev 4997 | 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. ; standard driver stuff
  9. format MS COFF
  10.  
  11. DEBUG = 1
  12.  
  13. ; this is for DEBUGF macro from 'fdo.inc'
  14. __DEBUG__ = 1
  15. __DEBUG_LEVEL__ = 1
  16.  
  17. include '../../proc32.inc'
  18. include '../../imports.inc'
  19. include '../../fdo.inc'
  20. include '../../struct.inc'
  21.  
  22. public START
  23. public version
  24.  
  25. ; USB constants
  26. DEVICE_DESCR_TYPE           = 1
  27. CONFIG_DESCR_TYPE           = 2
  28. STRING_DESCR_TYPE           = 3
  29. INTERFACE_DESCR_TYPE        = 4
  30. ENDPOINT_DESCR_TYPE         = 5
  31. DEVICE_QUALIFIER_DESCR_TYPE = 6
  32.  
  33. CONTROL_PIPE     = 0
  34. ISOCHRONOUS_PIPE = 1
  35. BULK_PIPE        = 2
  36. INTERRUPT_PIPE   = 3
  37.  
  38. ; USB HID constants
  39. HID_DESCR_TYPE      = 21h
  40. REPORT_DESCR_TYPE   = 22h
  41. PHYSICAL_DESCR_TYPE = 23h
  42.  
  43.  
  44. ; LibUSB constatnts
  45. LIBUSB_REQUEST_TYPE_STANDARD = (0x00 shl 5)
  46. LIBUSB_REQUEST_TYPE_CLASS = (0x01 shl 5)
  47. LIBUSB_REQUEST_TYPE_VENDOR = (0x02 shl 5)
  48. LIBUSB_REQUEST_TYPE_RESERVED = (0x03 shl 5)
  49.  
  50. LIBUSB_RECIPIENT_DEVICE = 0x00
  51. LIBUSB_RECIPIENT_INTERFACE = 0x01
  52. LIBUSB_RECIPIENT_ENDPOINT = 0x02
  53. LIBUSB_RECIPIENT_OTHER = 0x03
  54.  
  55. LIBUSB_ENDPOINT_IN = 0x80
  56. LIBUSB_ENDPOINT_OUT = 0x00
  57.  
  58. ; FTDI Constants
  59. FTDI_DEVICE_OUT_REQTYPE = (LIBUSB_REQUEST_TYPE_VENDOR or LIBUSB_RECIPIENT_DEVICE or LIBUSB_ENDPOINT_OUT)
  60. FTDI_DEVICE_IN_REQTYPE = (LIBUSB_REQUEST_TYPE_VENDOR or LIBUSB_RECIPIENT_DEVICE or LIBUSB_ENDPOINT_IN)
  61.  
  62. ; Requests
  63. ;Definitions for flow control
  64. SIO_RESET         =0  ;Reset the port
  65. SIO_MODEM_CTRL    =1  ;Set the modem control register
  66. SIO_SET_FLOW_CTRL =2  ;Set flow control register
  67. SIO_SET_BAUD_RATE =3  ;Set baud rate
  68. SIO_SET_DATA      =4  ;Set the data characteristics of the port
  69.  
  70. SIO_RESET_REQUEST            =SIO_RESET
  71. SIO_SET_BAUDRATE_REQUEST     =SIO_SET_BAUD_RATE
  72. SIO_SET_DATA_REQUEST         =SIO_SET_DATA
  73. SIO_SET_FLOW_CTRL_REQUEST    =SIO_SET_FLOW_CTRL
  74. SIO_SET_MODEM_CTRL_REQUEST   =SIO_MODEM_CTRL
  75. SIO_POLL_MODEM_STATUS_REQUEST=0x05
  76. SIO_SET_EVENT_CHAR_REQUEST   =0x06
  77. SIO_SET_ERROR_CHAR_REQUEST   =0x07
  78. SIO_SET_LATENCY_TIMER_REQUEST=0x09
  79. SIO_GET_LATENCY_TIMER_REQUEST=0x0A
  80. SIO_SET_BITMODE_REQUEST      =0x0B
  81. SIO_READ_PINS_REQUEST        =0x0C
  82. SIO_READ_EEPROM_REQUEST      =0x90
  83. SIO_WRITE_EEPROM_REQUEST     =0x91
  84. SIO_ERASE_EEPROM_REQUEST     =0x92
  85.  
  86.  
  87. SIO_RESET_SIO=0
  88. SIO_RESET_PURGE_RX=1
  89. SIO_RESET_PURGE_TX=2
  90.  
  91. SIO_DISABLE_FLOW_CTRL=0x0
  92. SIO_RTS_CTS_HS =(0x1 shl 8)
  93. SIO_DTR_DSR_HS =(0x2 shl 8)
  94. SIO_XON_XOFF_HS=(0x4 shl 8)
  95.  
  96. SIO_SET_DTR_MASK=0x1
  97. SIO_SET_DTR_HIGH=( 1 or ( SIO_SET_DTR_MASK  shl 8))
  98. SIO_SET_DTR_LOW =( 0 or ( SIO_SET_DTR_MASK  shl 8))
  99. SIO_SET_RTS_MASK=0x2
  100. SIO_SET_RTS_HIGH=( 2 or ( SIO_SET_RTS_MASK shl 8 ))
  101. SIO_SET_RTS_LOW =( 0 or ( SIO_SET_RTS_MASK shl 8 ))
  102.  
  103. SIO_RTS_CTS_HS =(0x1 shl 8)
  104.  
  105. ;FTDI chip type
  106. TYPE_AM=0
  107. TYPE_BM=1
  108. TYPE_2232C=2
  109. TYPE_R=3
  110. TYPE_2232H=4
  111. TYPE_4232H=5
  112. TYPE_232H=6
  113. TYPE_230X=7
  114.  
  115. ;strings
  116. my_driver       db      'usbother',0
  117. nomemory_msg    db      'K : no memory',13,10,0
  118.  
  119. ; Structures
  120. struct ftdi_context
  121. chipType                db      ?
  122. baudrate                dd      ?
  123. bitbangEnabled          db      ?
  124. readBufPtr              dd      ?
  125. readBufOffs             dd      ?
  126. readBufChunkSize        dd      ?
  127. writeBufChunkSize       dd      ?
  128. interface               dd      ?
  129. index                   dd      ?
  130. inEP                    dd      ?
  131. outEP                   dd      ?
  132. nullP                   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, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
  185.        
  186.         stdcall USBGetParam, [.config_pipe], 0
  187.         DEBUGF 1,'K : Device detected Vendor: %x\n', [eax+usb_descr.idVendor]
  188.         cmp     word[eax+usb_descr.idVendor], 0x0403
  189.         jnz     .notftdi
  190.         DEBUGF 1,'K : FTDI USB device detected\n'
  191.         movi    eax, sizeof.ftdi_context
  192.         call    Kmalloc
  193.         test    eax, eax
  194.         jnz     @f
  195.         mov     esi, nomemory_msg
  196.         call    SysMsgBoardStr
  197.         xor     eax, eax
  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.        
  207.         DEBUGF 1,'K : Open first pipe\n'
  208.         mov     ebx, eax
  209.         stdcall USBOpenPipe, [.config_pipe],  0x81,  0x40,  BULK_PIPE, 0
  210.         mov     [ebx + ftdi_context.inEP], eax
  211.         DEBUGF 1,'K : Open second pipe\n'
  212.         stdcall USBOpenPipe, [.config_pipe],  0x02,  0x40,  BULK_PIPE, 0
  213.         mov     [ebx + ftdi_context.outEP], eax        
  214.  
  215.   .nothing:
  216.         ret            
  217.   .notftdi:
  218.         DEBUGF 1,'K : Skipping not FTDI device\n'
  219.         xor     eax, eax
  220.         ret
  221. endp
  222.  
  223.  
  224. handle     equ  IOCTL.handle
  225. io_code    equ  IOCTL.io_code
  226. input      equ  IOCTL.input
  227. inp_size   equ  IOCTL.inp_size
  228. output     equ  IOCTL.output
  229. out_size   equ  IOCTL.out_size
  230.  
  231. align 4
  232. proc service_proc stdcall uses ebx esi edi, ioctl:DWORD
  233. locals
  234. ConfPacket  rb  8
  235. EventData   rd  2
  236. endl
  237.         mov     edi, [ioctl]
  238.         mov     eax, [edi + io_code]
  239.         DEBUGF 1,'K : FTDI got the request: %d\n', eax
  240.         test    eax, eax           ;0
  241.         jz      .version
  242.         dec     eax                 ;1
  243.         jz      .ftdi_get_list
  244.        
  245.         push    eax edi
  246.         xor     ecx, ecx
  247.         xor     esi, esi
  248.         call    CreateEvent        
  249.         mov     [EventData], eax
  250.         mov     [EventData+4], edx
  251.         pop     edi eax
  252.        
  253.         dec     eax                 ;2
  254.         jz      .ftdi_set_bitmode
  255.         dec     eax                 ;3
  256.         jz      .ftdi_setrtshigh  
  257.         dec     eax                 ;4
  258.         jz      .ftdi_setrtslow    
  259.        
  260.   .version:    
  261.   .endswitch:
  262.         xor     eax, eax
  263.             ret
  264.        
  265.   .ftdi_out_control_transfer:
  266.         mov     ebx, [edi]
  267.         mov     cx, word[ebx + ftdi_context.index]
  268.         mov     word[ConfPacket+4], cx
  269.         xor     cx, cx
  270.         mov     word[ConfPacket+6], cx
  271.   .own_index:
  272.         mov    ebx, [edi]
  273.         DEBUGF 1,'K : ConfPacket %x %x\n', [ConfPacket], [ConfPacket+4]          
  274.         lea     esi, [ConfPacket]
  275.         lea     edi, [EventData]        
  276.         stdcall USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, 0, 0, control_callback, edi, 0
  277.         DEBUGF 1, 'K : Returned value is %d\n', eax
  278.         mov     eax, [EventData]
  279.         mov     ebx, [EventData+4]
  280.         call    WaitEvent    
  281.         jmp     .endswitch
  282.        
  283.   .ftdi_set_bitmode:
  284.         DEBUGF 1,'K : FTDI Seting bitmode\n'                  
  285.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_BITMODE_REQUEST shl 8)
  286.         mov     edi, [edi+input]        
  287.         mov     dx, word[edi+4]                
  288.         mov     word[ConfPacket+2], dx                                        
  289.         jmp     .ftdi_out_control_transfer    
  290.  
  291.   .ftdi_setrtshigh:
  292.         DEBUGF 1,'K : FTDI Setting RTS pin HIGH\n'                    
  293.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_MODEM_CTRL_REQUEST shl 8) + (SIO_SET_RTS_HIGH shl 16)
  294.         jmp     .ftdi_out_control_transfer        
  295.  
  296.   .ftdi_setrtslow:
  297.         DEBUGF 1,'K : FTDI Setting RTS pin LOW\n'            
  298.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_MODEM_CTRL_REQUEST shl 8) + (SIO_SET_RTS_LOW shl 16)
  299.         jmp     .ftdi_out_control_transfer        
  300.        
  301.   .ftdi_setdtrhigh:
  302.         DEBUGF 1,'K : FTDI Setting DTR pin HIGH\n'                    
  303.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_MODEM_CTRL_REQUEST shl 8) + (SIO_SET_DTR_HIGH shl 16)
  304.         jmp     .ftdi_out_control_transfer        
  305.  
  306.   .ftdi_setdtrlow:
  307.         DEBUGF 1,'K : FTDI Setting DTR pin LOW\n'            
  308.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_MODEM_CTRL_REQUEST shl 8) + (SIO_SET_DTR_LOW shl 16)
  309.         jmp     .ftdi_out_control_transfer        
  310.        
  311.   .ftdi_usb_reset:
  312.         DEBUGF 1,'K : FTDI Reseting\n'
  313.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_RESET_REQUEST shl 8) + (SIO_RESET_SIO shl 16)
  314.         jmp     .ftdi_out_control_transfer
  315.        
  316.   .ftdi_purge_rx_buf:
  317.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_RESET_REQUEST shl 8) + (SIO_RESET_PURGE_RX shl 16)
  318.         jmp     .ftdi_out_control_transfer
  319.        
  320.   .ftdi_purge_tx_buf:
  321.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_RESET_REQUEST shl 8) + (SIO_RESET_PURGE_TX shl 16)
  322.         jmp     .ftdi_out_control_transfer
  323.  
  324. H_CLK = 120000000
  325. C_CLK = 48000000        
  326.   .ftdi_set_baudrate:
  327.         mov     edi, [edi+input]
  328.         mov     ebx, [edi]
  329.         cmp     [ebx + ftdi_context.chipType], TYPE_2232H
  330.         jl      .c_clk        
  331.         imul    eax, [edi+4], 10
  332.         cmp     eax, H_CLK / 0x3FFF        
  333.         jle     .c_clk
  334.   .h_clk:      
  335.         cmp     dword[edi+4], H_CLK/10
  336.         jl      .h_nextbaud1
  337.         xor     edx, edx
  338.         mov     ecx, H_CLK/10
  339.         jmp     .calcend
  340.        
  341.   .c_clk:
  342.         cmp     dword[edi+4], C_CLK/10
  343.         jl      .c_nextbaud1
  344.         xor     edx, edx
  345.         mov     ecx, C_CLK/10
  346.         jmp     .calcend  
  347.  
  348.   .h_nextbaud1:
  349.         cmp     dword[edi+4], H_CLK/(10 + 10/2)
  350.         jl      .h_nextbaud2
  351.         mov     edx, 1
  352.         mov     ecx, H_CLK/(10 + 10/2)
  353.         jmp     .calcend
  354.        
  355.   .c_nextbaud1:
  356.         cmp     dword[edi+4], C_CLK/(10 + 10/2)
  357.         jl      .c_nextbaud2
  358.         mov     edx, 1
  359.         mov     ecx, C_CLK/(10 + 10/2)
  360.         jmp     .calcend        
  361.        
  362.   .h_nextbaud2:      
  363.         cmp     dword[edi+4], H_CLK/(2*10)
  364.         jl      .h_nextbaud3
  365.         mov     edx, 2
  366.         mov     ecx, H_CLK/(2*10)
  367.         jmp     .calcend
  368.        
  369.   .c_nextbaud2:      
  370.         cmp     dword[edi+4], C_CLK/(2*10)
  371.         jl      .c_nextbaud3
  372.         mov     edx, 2
  373.         mov     ecx, C_CLK/(2*10)
  374.         jmp     .calcend        
  375.        
  376.   .h_nextbaud3:
  377.         mov     eax, H_CLK*16/10  ; eax - best_divisor
  378.         div     dword[edi+4]      ; [edi+4] - baudrate
  379.         push    eax
  380.         and     eax, 1
  381.         pop     eax
  382.         shr     eax, 1
  383.         jz      .h_rounddowndiv     ; jump by result of and eax, 1
  384.         inc     eax
  385.   .h_rounddowndiv:
  386.         cmp     eax, 0x20000
  387.         jle     .h_best_divok
  388.         mov     eax, 0x1FFFF
  389.   .h_best_divok:
  390.         mov     ecx, eax        
  391.         mov     eax, H_CLK*16/10
  392.         div     ecx
  393.         xchg    ecx, eax            ; ecx - best_baud
  394.         push    ecx
  395.         and     ecx, 1
  396.         pop     ecx
  397.         shr     ecx, 1
  398.         jz      .rounddownbaud
  399.         inc     ecx
  400.         jmp     .rounddownbaud
  401.        
  402.   .c_nextbaud3:
  403.         mov     eax, C_CLK*16/10  ; eax - best_divisor
  404.         div     dword[edi+4]      ; [edi+4] - baudrate
  405.         push    eax
  406.         and     eax, 1
  407.         pop     eax
  408.         shr     eax, 1
  409.         jz      .c_rounddowndiv     ; jump by result of and eax, 1
  410.         inc     eax
  411.   .c_rounddowndiv:
  412.         cmp     eax, 0x20000
  413.         jle     .c_best_divok
  414.         mov     eax, 0x1FFFF
  415.   .c_best_divok:
  416.         mov     ecx, eax        
  417.         mov     eax, C_CLK*16/10
  418.         div     ecx
  419.         xchg    ecx, eax            ; ecx - best_baud
  420.         push    ecx
  421.         and     ecx, 1
  422.         pop     ecx
  423.         shr     ecx, 1
  424.         jz      .rounddownbaud
  425.         inc     ecx
  426.        
  427.   .rounddownbaud:
  428.         mov     edx, eax            ; edx - encoded_divisor
  429.         shr     edx, 3
  430.         and     eax, 0x7
  431.         push    esp
  432.         push    7 6 5 1 4 2 3 0
  433.         mov     eax, [esp+eax*4]
  434.         shl     eax, 14
  435.         or      edx, eax
  436.         mov     esp, [esp+36]
  437.        
  438.   .calcend:
  439.         mov     eax, edx        ; eax - *value
  440.         mov     ecx, edx        ; ecx - *index
  441.         and     eax, 0xFFFF
  442.         cmp     [ebx + ftdi_context.chipType], TYPE_2232H
  443.         jge     .foxyindex        
  444.         shr     ecx, 16
  445.         jmp     .preparepacket
  446.   .foxyindex:
  447.         shr     ecx, 8
  448.         and     ecx, 0xFF00
  449.         or      ecx, [ebx + ftdi_context.index]
  450.        
  451.   .preparepacket:
  452.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_BAUDRATE_REQUEST shl 8)
  453.         mov     word[ConfPacket+2], ax
  454.         mov     word[ConfPacket+4], cx
  455.         mov     word[ConfPacket+6], 0
  456.         jmp     .own_index
  457.      
  458.   .ftdi_set_line_property:
  459.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_DATA_REQUEST shl 8)
  460.         mov     edi, [edi+input]        
  461.         mov     dx, word[edi+4]                
  462.         mov     word[ConfPacket+2], dx
  463.         jmp     .ftdi_out_control_transfer
  464.        
  465.   .ftdi_set_latency_timer:
  466.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_LATENCY_TIMER_REQUEST shl 8)
  467.         mov     edi, [edi+input]        
  468.         mov     dx, word[edi+4]                
  469.         mov     word[ConfPacket+2], dx        
  470.         jmp     .ftdi_out_control_transfer
  471.        
  472.   .ftdi_set_event_char:
  473.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_EVENT_CHAR_REQUEST shl 8)
  474.         mov     edi, [edi+input]        
  475.         mov     dx, word[edi+4]                
  476.         mov     word[ConfPacket+2], dx
  477.         jmp     .ftdi_out_control_transfer
  478.  
  479.   .ftdi_set_error_char:
  480.         mov     word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_ERROR_CHAR_REQUEST shl 8)
  481.         mov     edi, [edi+input]        
  482.         mov     dx, word[edi+4]                
  483.         mov     word[ConfPacket+2], dx
  484.         jmp     .ftdi_out_control_transfer
  485.        
  486.   .ftdi_setflowctrl:
  487.         mov     dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) + (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)      
  488.         mov     edi, [edi+input]
  489.         mov     ebx, [edi]
  490.         mov     cx, word[edi+4]  
  491.         or      ecx, [ebx + ftdi_context.index]
  492.         mov     word[ConfPacket+4], cx
  493.         xor     cx, cx
  494.         mov     word[ConfPacket+6], cx
  495.         jmp     .own_index
  496.  
  497.   .ftdi_read_pins:
  498.         DEBUGF 1,'K : FTDI Reading pins\n'
  499.         mov     dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE + (SIO_READ_PINS_REQUEST shl 8) + (0 shl 16)
  500.         mov     dword[ConfPacket+4], 0x00000001
  501.         mov     edi, [edi+input]                                  
  502.         mov     ebx, [edi]
  503.         lea     esi, [ConfPacket]
  504.         lea     edi, [EventData]
  505.         mov     ecx, [ioctl]
  506.         mov     ecx, [ecx+output]
  507.         stdcall USBControlTransferAsync, [ebx + ftdi_context.nullP],  esi, ecx, 1, control_callback, edi, 0
  508.         DEBUGF 1, 'K : Returned value is %d\n', eax
  509.         mov     eax, [EventData]
  510.         mov     ebx, [EventData+4]
  511.         call    WaitEvent    
  512.         jmp     .endswitch
  513.        
  514.    .ftdi_read_data:
  515.         ;stdcall USBNormalTransferAsync, [ebx + ftdi_context.inEP], [ebx + ftdi_context.readBufPtr], [ebx + 1]
  516.  
  517.    .ftdi_get_list:
  518.         call    linkedlist.gethead                        
  519.         mov     edi, [edi+output]
  520.         mov     [edi], eax
  521.         DEBUGF 1, 'K : FTDI Device pointer %x\n', [edi]
  522.         mov     eax, 4        
  523.         mov     [edi+out_size], eax
  524.         jmp     .endswitch
  525.                    
  526. endp
  527. restore   handle
  528. restore   io_code
  529. restore   input
  530. restore   inp_size
  531. restore   output
  532. restore   out_size
  533.  
  534.  
  535. align 4
  536. proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, .buffer:DWORD, .length:DWORD, .calldata:DWORD  
  537.    
  538.         DEBUGF 1, 'K : status is %d\n', [.status]
  539.         mov     ecx, [.calldata]
  540.         mov     eax, [ecx]
  541.         mov     ebx, [ecx+4]
  542.         xor     edx, edx
  543.         call    RaiseEvent
  544.              
  545.         ret
  546. endp
  547.  
  548.  
  549. proc DeviceDisconnected stdcall uses  ebx esi edi, .device_data:DWORD
  550.  
  551.         DEBUGF 1, 'K : FTDI deleting device data\n'
  552.         mov     eax, [.device_data]
  553.         call    linkedlist.delete
  554.         ret          
  555. endp
  556.  
  557. include 'linkedlist.inc'
  558.        
  559. ; Exported variable: kernel API version.
  560. align 4
  561. version dd      50005h
  562. ; Structure with callback functions.
  563. usb_functions:
  564.         dd      12
  565.         dd      AddDevice
  566.         dd      DeviceDisconnected
  567.  
  568. ;for DEBUGF macro
  569. include_debug_strings
  570.  
  571.  
  572.  
  573.  
  574. ; for uninitialized data
  575. ;section '.data' data readable writable align 16
  576.