/****************************************************************************/
/*                             hostusb.cpp                                  */
/****************************************************************************/
/* libusb interface for WinUAE                                              */
/****************************************************************************/
/* Modification history                                                     */
/* ====================                                                     */
/* 14-Jan-2013 Add LIBUSB_CALL __stdcall for libusbx                        */
/* 10-Jan-2013 More traces                                                  */
/* 18-Dec-2012 Add more libusbx functions                                   */
/* 16-Oct-2012 Add libusbx functions                                        */
/* 01-Aug-2012 Add all libusb functions                                     */
/* 21-Jun-2012 Creation                                                     */
/****************************************************************************/

#include "stdafx.h"
#include "hostusb.h"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include "lusb0_usb.h"

#define MYTRACE 1

#ifndef ENOFILE
#define ENOFILE -2
#endif

#define _CRT_SECURE_NO_WARNINGS 1

#ifdef _MANAGED
#pragma managed(push, off)
#endif

void usb_exit_dll(void) ;
void libusb_exit_dll(void) ;


static int dllcount      = 0 ;
HINSTANCE husbhandle     = NULL ;
HINSTANCE hlibusbxhandle = NULL ;

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved )
{
  switch (ul_reason_for_call)
  {
    case DLL_PROCESS_ATTACH:
    {
      dllcount ++ ;
#if MYTRACE
      FILE *f = fopen("hostusb.trace", "a") ;

      if (f)
      {
        fprintf(f, "DllMain() DLL_PROCESS_ATTACH (cnt=%ld)\n", dllcount) ;
        fclose(f) ;
      }
#endif
      break ;
    }

    case DLL_THREAD_ATTACH:
    {
#if MYTRACE
      FILE *f = fopen("hostusb.trace", "a") ;

      if (f)
      {
        fprintf(f, "DllMain() DLL_THREAD_ATTACH (cnt=%ld)\n", dllcount) ;
        fclose(f) ;
      }
#endif
      break ;
    }

    case DLL_THREAD_DETACH:
    {
#if MYTRACE
      FILE *f = fopen("hostusb.trace", "a") ;

      if (f)
      {
        fprintf(f, "DllMain() DLL_THREAD_DETACH (cnt=%ld)\n", dllcount) ;
        fclose(f) ;
      }
#endif
      break ;
    }

    case DLL_PROCESS_DETACH:
    {
      dllcount -- ;
#if MYTRACE
      FILE *f = fopen("hostusb.trace", "a") ;

      if (f)
      {
        fprintf(f, "DllMain() DLL_PROCESS_DETACH (cnt=%ld)\n", dllcount) ;
        fclose(f) ;
      }
#endif
      if (dllcount == 0)
      {
        usb_exit_dll() ;
        libusb_exit_dll() ;
      }
      break;
    }
  }

  return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif


//
void fdump(FILE *f, char *buffer, int len)
{
  int i ;

  if (f != NULL)
  {
    for ( i = 0 ; i < len ; i++ )
    {
      fprintf(f, "%02lx", buffer[i]) ;
      if ((i != 0) && (i % 16 == 0))
      {
        fprintf(f, "\n") ;
      }
    }
  }
}

int debug = 0 ;

HOSTUSB_API void HostDebug(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;

  debug = stk->d1 ;

  return ;
}

HOSTUSB_API void HostNoDebug(void)
{
  debug = 0 ;
  return ;
}

#if 1
HOSTUSB_API int func1(unsigned long *a)
{
  FILE *f = NULL ;
  struct StackFrame *stk = (struct StackFrame *)&a ;

  f = fopen("function1.trace", "a") ;
  if (f != NULL)
  {
    fprintf(f, "func1\n"
               "a7=%08lx\n"
               "a6=%08lx\n"
               "a5=%08lx\n"
               "a4=%08lx\n"
               "a3=%08lx\n"
               "a2=%08lx\n"
               "a1=%08lx\n"
               "d7=%08lx\n"
               "d6=%08lx\n"
               "d5=%08lx\n"
               "d4=%08lx\n"
               "d3=%08lx\n"
               "d2=%08lx\n"
               "d1=%08lx\n",
               stk->a7,
               stk->a6,
               stk->a5,
               stk->a4,
               stk->a3,
               stk->a2,
               stk->a1,
               stk->d7,
               stk->d6,
               stk->d5,
               stk->d4,
               stk->d3,
               stk->d2,
               stk->d1) ;

    fclose(f) ;
  }

	return 1 ;
}

HOSTUSB_API int func2(unsigned long *a)
{
  FILE *f = NULL ;
  struct StackFrame *stk = (struct StackFrame *)&a ;

  f = fopen("function2.trace", "a") ;
  if (f != NULL)
  {
    fprintf(f, "func2\n"
               "a7=%08lx\n"
               "a6=%08lx\n"
               "a5=%08lx\n"
               "a4=%08lx\n"
               "a3=%08lx\n"
               "a2=%08lx\n"
               "a1=%08lx\n"
               "d7=%08lx\n"
               "d6=%08lx\n"
               "d5=%08lx\n"
               "d4=%08lx\n"
               "d3=%08lx\n"
               "d2=%08lx\n"
               "d1=%08lx\n",
               stk->a7,
               stk->a6,
               stk->a5,
               stk->a4,
               stk->a3,
               stk->a2,
               stk->a1,
               stk->d7,
               stk->d6,
               stk->d5,
               stk->d4,
               stk->d3,
               stk->d2,
               stk->d1) ;

    fclose(f) ;
  }

  return 2 ;
}
#endif

HOSTUSB_API int HostFOpen(unsigned long *a)
{
  FILE *f = NULL ;
  FILE *file = NULL ;
  struct StackFrame *stk = (struct StackFrame *)&a ;
  char *name  = (char *)stk->d1 ;
  char *mode  = (char *)stk->d2 ;

  file = fopen(name, mode) ;

  if (debug)
  {
    f = fopen("Open.trace", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "FOpen(\"%s\", \"%s\") => %08lx\n", name, mode, file) ;
    fclose(f) ;
  }

  return (unsigned long)file ;
}

HOSTUSB_API int HostOpen(unsigned long *a)
{
  FILE *f = NULL ;
  FILE *file = NULL ;
  struct StackFrame *stk = (struct StackFrame *)&a ;
  char *name  = (char *)stk->d1 ;
  unsigned long access = (unsigned long)stk->d2 ;
  char *mode ;

  switch (access)
  {
    case 1004 : mode = "rb+" ; break ; /* MODE_READWRITE */
    case 1005 : mode = "rb+" ; break ; /* MODE_OLDFILE */
    case 1006 : mode = "wb+" ; break ; /* MODE_NEWFILE */
  }

  file = fopen(name, mode) ;

  if (debug)
  {
    f = fopen("Open.trace", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "Open(\"%s\", %ld) => %08lx\n", name, access, file) ;
    fclose(f) ;
  }

  return (unsigned long)file ;
}

HOSTUSB_API int HostClose(unsigned long *a)
{
  FILE *f = NULL ;
  struct StackFrame *stk = (struct StackFrame *)&a ;
  FILE *file = (FILE *)stk->d1 ;

  if (file != NULL)
  {
    fclose(file) ;
  }

  if (debug)
  {
    f = fopen("Close.trace", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "Close (%08lx)\n", stk->d1) ;
    fclose(f) ;
  }

  return 0 ;
}

HOSTUSB_API int HostRead(unsigned long *a)
{
  int readsize = -1 ;
  FILE *f = NULL ;
  struct StackFrame *stk = (struct StackFrame *)&a ;
  FILE *file = (FILE *)stk->d1 ;
  unsigned char *buffer = (unsigned char *)stk->d2 ;
  unsigned long size = (unsigned long)stk->d3 ;

  readsize = fread(buffer, 1, size, file) ;

  if (debug)
  {
    f = fopen("Read.trace", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "Read (%08lx, %08lx, %08lx) => %ld\n", file, buffer, size, readsize) ;
    if (debug > 1)
    {
      fdump(f, (char *)buffer, size) ;
    }
    fclose(f) ;
  }

  return readsize ;
}

HOSTUSB_API int HostWrite(unsigned long *a)
{
  int writesize = -1 ;
  FILE *f = NULL ;
  struct StackFrame *stk = (struct StackFrame *)&a ;
  FILE *file = (FILE *)stk->d1 ;
  unsigned char *buffer = (unsigned char *)stk->d2 ;
  unsigned long size = (unsigned long)stk->d3 ;

  writesize = fwrite(buffer, 1, size, file) ;

  if (debug)
  {
    f = fopen("Write.trace", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "Write (%08lx, %08lx, %08lx) => %ld\n", file, buffer, size, writesize) ;
    if (debug > 1)
    {
      fdump(f, (char *)buffer, size) ;
    }
    fclose(f) ;
  }

  return writesize ;
}

HOSTUSB_API int HostSeek(unsigned long *a)
{
  FILE *f = NULL ;
  struct StackFrame *stk = (struct StackFrame *)&a ;
  FILE *file             = (FILE *)stk->d1 ;
  unsigned long position = (unsigned long)stk->d2 ;
  long mode              = (long)stk->d3 ;
  unsigned long oldposition ;
  long realmode          = 0 ;
  
  switch (mode)
  {
    case -1 : realmode = 0 ; break ; // seek set
    case  0 : realmode = 1 ; break ; // seek current 
    case  1 : realmode = 2 ; break ; // seek end
  }

  oldposition = ftell(file) ;
  fseek(file, position, realmode) ;
 
  if (debug)
  {
    f = fopen("Seek.trace", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "Seek (%08lx, %08lx (%08lx), %08lx) => %ld\n", file, position, mode, realmode, oldposition) ;
    fclose(f) ;
  }

  return oldposition ;
}

HOSTUSB_API void HostCopyMem(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;

  /* struct usb_bus * d1 src */
  /* struct usb_bus * d2 dst */
  /* unsigned long    d3 len */
  memcpy((char *)stk->d2, (char *)stk->d1, stk->d3) ;
}

/* libusb */
typedef usb_dev_handle *(*usb_open_t)(struct usb_device *dev) ;
typedef int (*usb_close_t)(usb_dev_handle *dev) ;
typedef int (*usb_get_string_t)(usb_dev_handle *dev, int index, int langid, char *buf, size_t buflen) ;
typedef int (*usb_get_string_simple_t)(usb_dev_handle *dev, int index, char *buf, size_t buflen) ;
typedef int (*usb_get_descriptor_by_endpoint_t)(usb_dev_handle *udev, int ep,
        unsigned char type,
        unsigned char index,
        void *buf, int size);
typedef int (*usb_get_descriptor_t)(usb_dev_handle *udev, unsigned char type,
                                    unsigned char index, void *buf, int size);
typedef int (*usb_bulk_write_t)(usb_dev_handle *dev, int ep, char *bytes,
                                int size, int timeout);
typedef int (*usb_bulk_read_t)(usb_dev_handle *dev, int ep, char *bytes,
                               int size, int timeout);
typedef int (*usb_interrupt_write_t)(usb_dev_handle *dev, int ep, char *bytes,
                                     int size, int timeout);
typedef int (*usb_interrupt_read_t)(usb_dev_handle *dev, int ep, char *bytes,
                                    int size, int timeout);
typedef int (*usb_control_msg_t)(usb_dev_handle *dev, int requesttype,
                                 int request, int value, int index,
                                 char *bytes, int size, int timeout);
typedef int (*usb_set_configuration_t)(usb_dev_handle *dev, int configuration);
typedef int (*usb_claim_interface_t)(usb_dev_handle *dev, int interface);
typedef int (*usb_release_interface_t)(usb_dev_handle *dev, int interface);
typedef int (*usb_set_altinterface_t)(usb_dev_handle *dev, int alternate);
typedef int (*usb_resetep_t)(usb_dev_handle *dev, unsigned int ep);
typedef int (*usb_clear_halt_t)(usb_dev_handle *dev, unsigned int ep);
typedef int (*usb_reset_t)(usb_dev_handle *dev);
typedef int (*usb_reset_ex_t)(usb_dev_handle *dev, unsigned int reset_type);
typedef char * (*usb_strerror_t)(void);
typedef void (*usb_init_t)(void);
typedef void (*usb_set_debug_t)(int level);
typedef int (*usb_find_busses_t)(void);
typedef int (*usb_find_devices_t)(void);
typedef struct usb_device * (*usb_device_t)(usb_dev_handle *dev);
typedef struct usb_bus * (*usb_get_busses_t)(void);
typedef int (*usb_install_service_np_t)(void);
typedef int (*usb_uninstall_service_np_t)(void);
typedef int (*usb_install_driver_np_t)(const char *inf_file);
typedef const struct usb_version * (*usb_get_version_t)(void);
typedef int (*usb_isochronous_setup_async_t)(usb_dev_handle *dev,
        void **context,
        unsigned char ep, int pktsize);
typedef int (*usb_bulk_setup_async_t)(usb_dev_handle *dev, void **context,
                                      unsigned char ep);
typedef int (*usb_interrupt_setup_async_t)(usb_dev_handle *dev, void **context,
        unsigned char ep);
typedef int (*usb_submit_async_t)(void *context, char *bytes, int size);
typedef int (*usb_reap_async_t)(void *context, int timeout);
typedef int (*usb_free_async_t)(void **context);

static usb_open_t _usb_open = NULL;
static usb_close_t _usb_close = NULL;
static usb_get_string_t _usb_get_string = NULL;
static usb_get_string_simple_t _usb_get_string_simple = NULL;
static usb_get_descriptor_by_endpoint_t _usb_get_descriptor_by_endpoint = NULL;
static usb_get_descriptor_t _usb_get_descriptor = NULL;
static usb_bulk_write_t _usb_bulk_write = NULL;
static usb_bulk_read_t _usb_bulk_read = NULL;
static usb_interrupt_write_t _usb_interrupt_write = NULL;
static usb_interrupt_read_t _usb_interrupt_read = NULL;
static usb_control_msg_t _usb_control_msg = NULL;
static usb_set_configuration_t _usb_set_configuration = NULL;
static usb_claim_interface_t _usb_claim_interface = NULL;
static usb_release_interface_t _usb_release_interface = NULL;
static usb_set_altinterface_t _usb_set_altinterface = NULL;
static usb_resetep_t _usb_resetep = NULL;
static usb_clear_halt_t _usb_clear_halt = NULL;
static usb_reset_t _usb_reset = NULL;
static usb_reset_ex_t _usb_reset_ex = NULL;
static usb_strerror_t _usb_strerror = NULL;
static usb_init_t _usb_init = NULL;
static usb_set_debug_t _usb_set_debug = NULL;
static usb_find_busses_t _usb_find_busses = NULL;
static usb_find_devices_t _usb_find_devices = NULL;
static usb_device_t _usb_device = NULL;
static usb_get_busses_t _usb_get_busses = NULL;
static usb_install_service_np_t _usb_install_service_np = NULL;
static usb_uninstall_service_np_t _usb_uninstall_service_np = NULL;
static usb_install_driver_np_t _usb_install_driver_np = NULL;
static usb_get_version_t _usb_get_version = NULL;
static usb_isochronous_setup_async_t _usb_isochronous_setup_async = NULL;
static usb_bulk_setup_async_t _usb_bulk_setup_async = NULL;
static usb_interrupt_setup_async_t _usb_interrupt_setup_async = NULL;
static usb_submit_async_t _usb_submit_async = NULL;
static usb_reap_async_t _usb_reap_async = NULL;
static usb_free_async_t _usb_free_async = NULL;

/* libusbx */
typedef int (LIBUSB_CALL *libusb_init_t)(libusb_context **ctx);
typedef void (LIBUSB_CALL *libusb_exit_t)(libusb_context *ctx);
typedef void (LIBUSB_CALL *libusb_set_debug_t)(libusb_context *ctx, int level);
typedef const struct libusb_version * (LIBUSB_CALL *libusb_get_version_t)(void);
typedef int (LIBUSB_CALL *libusb_has_capability_t)(uint32_t capability) ;
typedef const char * (LIBUSB_CALL *libusb_error_name_t)(int errcode) ;
typedef ssize_t (LIBUSB_CALL *libusb_get_device_list_t)(libusb_context *ctx, libusb_device ***list) ;
typedef void (LIBUSB_CALL *libusb_free_device_list_t)(libusb_device **list, int unref_devices) ;
typedef libusb_device * (LIBUSB_CALL *libusb_ref_device_t)(libusb_device *dev) ;
typedef void (LIBUSB_CALL *libusb_unref_device_t)(libusb_device *dev) ;
typedef int (LIBUSB_CALL *libusb_get_configuration_t)(libusb_device_handle *dev,	int *config) ;
typedef int (LIBUSB_CALL *libusb_get_device_descriptor_t)(libusb_device *dev, struct libusb_device_descriptor *desc) ;
typedef int (LIBUSB_CALL *libusb_get_active_config_descriptor_t)(libusb_device *dev, struct libusb_config_descriptor **config) ;
typedef int (LIBUSB_CALL *libusb_get_config_descriptor_t)(libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config) ;
typedef int (LIBUSB_CALL *libusb_get_config_descriptor_by_value_t)(libusb_device *dev, uint8_t bConfigurationValue, struct libusb_config_descriptor **config);
typedef void (LIBUSB_CALL *libusb_free_config_descriptor_t)(struct libusb_config_descriptor *config) ;
typedef uint8_t (LIBUSB_CALL *libusb_get_bus_number_t)(libusb_device *dev) ;
typedef uint8_t (LIBUSB_CALL *libusb_get_port_number_t)(libusb_device *dev) ;
typedef libusb_device * (LIBUSB_CALL *libusb_get_parent_t)(libusb_device *dev) ;
typedef int (LIBUSB_CALL *libusb_get_port_path_t)(libusb_context *ctx, libusb_device *dev, uint8_t* path, uint8_t path_length) ;
typedef uint8_t (LIBUSB_CALL *libusb_get_device_address_t)(libusb_device *dev) ;
typedef int (LIBUSB_CALL *libusb_get_device_speed_t)(libusb_device *dev) ;
typedef int (LIBUSB_CALL *libusb_get_max_packet_size_t)(libusb_device *dev, unsigned char endpoint) ;
typedef int (LIBUSB_CALL *libusb_get_max_iso_packet_size_t)(libusb_device *dev, unsigned char endpoint) ;
typedef int (LIBUSB_CALL *libusb_open_t)(libusb_device *dev, libusb_device_handle **handle) ;
typedef void (LIBUSB_CALL *libusb_close_t)(libusb_device_handle *dev_handle) ;
typedef libusb_device * (LIBUSB_CALL *libusb_get_device_t)(libusb_device_handle *dev_handle) ;
typedef int (LIBUSB_CALL *libusb_set_configuration_t)(libusb_device_handle *dev, int configuration) ;
typedef int (LIBUSB_CALL *libusb_claim_interface_t)(libusb_device_handle *dev, int interface_number) ;
typedef int (LIBUSB_CALL *libusb_release_interface_t)(libusb_device_handle *dev, int interface_number) ;
typedef libusb_device_handle * (LIBUSB_CALL *libusb_open_device_with_vid_pid_t)(libusb_context *ctx, uint16_t vendor_id, uint16_t product_id);
typedef int (LIBUSB_CALL *libusb_set_interface_alt_setting_t)(libusb_device_handle *dev, int interface_number, int alternate_setting) ;
typedef int (LIBUSB_CALL *libusb_clear_halt_t)(libusb_device_handle *dev, unsigned char endpoint) ;
typedef int (LIBUSB_CALL *libusb_reset_device_t)(libusb_device_handle *dev) ;
typedef int (LIBUSB_CALL *libusb_kernel_driver_active_t)(libusb_device_handle *dev, int interface_number) ;
typedef int (LIBUSB_CALL *libusb_detach_kernel_driver_t)(libusb_device_handle *dev, int interface_number) ;
typedef int (LIBUSB_CALL *libusb_attach_kernel_driver_t)(libusb_device_handle *dev, int interface_number) ;

typedef int (LIBUSB_CALL *libusb_control_transfer_t)(libusb_device_handle *dev_handle,
	uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
	unsigned char *data, uint16_t wLength, unsigned int timeout);
typedef int (LIBUSB_CALL *libusb_bulk_transfer_t)(libusb_device_handle *dev_handle,
	unsigned char endpoint, unsigned char *data, int length,
	int *actual_length, unsigned int timeout);
typedef int (LIBUSB_CALL *libusb_interrupt_transfer_t)(libusb_device_handle *dev_handle,
	unsigned char endpoint, unsigned char *data, int length,
	int *actual_length, unsigned int timeout);


static libusb_init_t _libusb_init = NULL ;
static libusb_exit_t _libusb_exit = NULL ;
static libusb_set_debug_t _libusb_set_debug = NULL ;
static libusb_get_version_t _libusb_get_version = NULL ;
static libusb_has_capability_t _libusb_has_capability = NULL ;
static libusb_error_name_t _libusb_error_name = NULL ;
static libusb_get_device_list_t _libusb_get_device_list = NULL ;
static libusb_free_device_list_t _libusb_free_device_list = NULL ;
static libusb_ref_device_t _libusb_ref_device = NULL ;
static libusb_unref_device_t _libusb_unref_device = NULL ;
static libusb_get_configuration_t _libusb_get_configuration = NULL ;
static libusb_get_device_descriptor_t _libusb_get_device_descriptor  = NULL ;
static libusb_get_active_config_descriptor_t _libusb_get_active_config_descriptor = NULL ;
static libusb_get_config_descriptor_t _libusb_get_config_descriptor = NULL ;
static libusb_get_config_descriptor_by_value_t _libusb_get_config_descriptor_by_value = NULL ;
static libusb_free_config_descriptor_t _libusb_free_config_descriptor = NULL ;
static libusb_get_bus_number_t _libusb_get_bus_number = NULL ;
static libusb_get_port_number_t _libusb_get_port_number = NULL ;
static libusb_get_parent_t _libusb_get_parent = NULL ;
static libusb_get_port_path_t _libusb_get_port_path = NULL ;
static libusb_get_device_address_t _libusb_get_device_address = NULL ;
static libusb_get_device_speed_t _libusb_get_device_speed = NULL ;
static libusb_get_max_packet_size_t _libusb_get_max_packet_size = NULL ;
static libusb_get_max_iso_packet_size_t _libusb_get_max_iso_packet_size = NULL ;
static libusb_open_t _libusb_open = NULL ;
static libusb_close_t _libusb_close = NULL ;
static libusb_get_device_t _libusb_get_device = NULL ;
static libusb_set_configuration_t _libusb_set_configuration = NULL ;
static libusb_claim_interface_t _libusb_claim_interface = NULL ;
static libusb_release_interface_t _libusb_release_interface = NULL ;
static libusb_open_device_with_vid_pid_t _libusb_open_device_with_vid_pid = NULL ;
static libusb_set_interface_alt_setting_t _libusb_set_interface_alt_setting = NULL ;
static libusb_clear_halt_t _libusb_clear_halt = NULL ;
static libusb_reset_device_t _libusb_reset_device = NULL ;
static libusb_kernel_driver_active_t _libusb_kernel_driver_active = NULL ;
static libusb_detach_kernel_driver_t _libusb_detach_kernel_driver = NULL ;
static libusb_attach_kernel_driver_t _libusb_attach_kernel_driver = NULL ;

static libusb_control_transfer_t _libusb_control_transfer = NULL ;
static libusb_bulk_transfer_t _libusb_bulk_transfer = NULL ;
static libusb_interrupt_transfer_t _libusb_interrupt_transfer = NULL ;

void usb_init_dll(void)
{
  if (husbhandle == NULL)
  {
    husbhandle = LoadLibrary("libusb0.dll") ;
#if MYTRACE
    if (1)
    {
      FILE *f = fopen("hostusb.trace", "a") ;

      if (f)
      {
        fprintf(f, "LoadLibrary(\"libusb0.dll\") => 0x%08lx\n", husbhandle) ;
        fclose(f) ;
      }
    }
#endif
    if (husbhandle != NULL)
    {
      // pfff.. pointer conversion 
      _usb_open = (usb_open_t)                GetProcAddress(husbhandle, "usb_open");
      _usb_close = (usb_close_t)              GetProcAddress(husbhandle, "usb_close");
      _usb_get_string = (usb_get_string_t)    GetProcAddress(husbhandle, "usb_get_string");
      _usb_get_string_simple = (usb_get_string_simple_t) GetProcAddress(husbhandle, "usb_get_string_simple");
      _usb_get_descriptor_by_endpoint = (usb_get_descriptor_by_endpoint_t) GetProcAddress(husbhandle, "usb_get_descriptor_by_endpoint");
      _usb_get_descriptor = (usb_get_descriptor_t) GetProcAddress(husbhandle, "usb_get_descriptor");
      _usb_bulk_write = (usb_bulk_write_t)    GetProcAddress(husbhandle, "usb_bulk_write");
      _usb_bulk_read = (usb_bulk_read_t)      GetProcAddress(husbhandle, "usb_bulk_read");
      _usb_interrupt_write = (usb_interrupt_write_t) GetProcAddress(husbhandle, "usb_interrupt_write");
      _usb_interrupt_read = (usb_interrupt_read_t) GetProcAddress(husbhandle, "usb_interrupt_read");
      _usb_control_msg = (usb_control_msg_t)  GetProcAddress(husbhandle, "usb_control_msg");
      _usb_set_configuration = (usb_set_configuration_t) GetProcAddress(husbhandle, "usb_set_configuration");
      _usb_claim_interface = (usb_claim_interface_t) GetProcAddress(husbhandle, "usb_claim_interface");
      _usb_release_interface = (usb_release_interface_t) GetProcAddress(husbhandle, "usb_release_interface");
      _usb_set_altinterface = (usb_set_altinterface_t) GetProcAddress(husbhandle, "usb_set_altinterface");
      _usb_resetep = (usb_resetep_t)           GetProcAddress(husbhandle, "usb_resetep");
      _usb_clear_halt = (usb_clear_halt_t)     GetProcAddress(husbhandle, "usb_clear_halt");
      _usb_reset = (usb_reset_t)               GetProcAddress(husbhandle, "usb_reset");
      _usb_reset_ex = (usb_reset_ex_t)         GetProcAddress(husbhandle, "usb_reset_ex");
      _usb_strerror = (usb_strerror_t)         GetProcAddress(husbhandle, "usb_strerror");
      _usb_init = (usb_init_t)                 GetProcAddress(husbhandle, "usb_init");
      _usb_set_debug = (usb_set_debug_t)       GetProcAddress(husbhandle, "usb_set_debug");
      _usb_find_busses = (usb_find_busses_t)   GetProcAddress(husbhandle, "usb_find_busses");
      _usb_find_devices = (usb_find_devices_t) GetProcAddress(husbhandle, "usb_find_devices");
      _usb_device = (usb_device_t)             GetProcAddress(husbhandle, "usb_device");
      _usb_get_busses = (usb_get_busses_t)     GetProcAddress(husbhandle, "usb_get_busses");
      _usb_install_service_np = (usb_install_service_np_t) GetProcAddress(husbhandle, "usb_install_service_np");
      _usb_uninstall_service_np = (usb_uninstall_service_np_t) GetProcAddress(husbhandle, "usb_uninstall_service_np");
      _usb_install_driver_np = (usb_install_driver_np_t) GetProcAddress(husbhandle, "usb_install_driver_np");
      _usb_get_version = (usb_get_version_t)   GetProcAddress(husbhandle, "usb_get_version");
      _usb_isochronous_setup_async = (usb_isochronous_setup_async_t) GetProcAddress(husbhandle, "usb_isochronous_setup_async");
      _usb_bulk_setup_async = (usb_bulk_setup_async_t) GetProcAddress(husbhandle, "usb_bulk_setup_async");
      _usb_interrupt_setup_async = (usb_interrupt_setup_async_t) GetProcAddress(husbhandle, "usb_interrupt_setup_async");
      _usb_submit_async = (usb_submit_async_t) GetProcAddress(husbhandle, "usb_submit_async");
      _usb_reap_async = (usb_reap_async_t)     GetProcAddress(husbhandle, "usb_reap_async");
      _usb_free_async = (usb_free_async_t)     GetProcAddress(husbhandle, "usb_free_async");
    }
  }
}

void usb_exit_dll(void)
{

#if MYTRACE
  if (1)
  {
    FILE *f = fopen("hostusb.trace", "a") ;

    if (f)
    {
      fprintf(f, "FreeLibrary(0x%08lx)\n", husbhandle) ;
      fclose(f) ;
    }
  }
#endif

  if (husbhandle != NULL)
  {
    FreeLibrary(husbhandle) ;
    husbhandle = NULL ;
  }

  _usb_open                       = NULL ;
  _usb_close                      = NULL ;
  _usb_get_string                 = NULL ;
  _usb_get_string_simple          = NULL ;
  _usb_get_descriptor_by_endpoint = NULL ;
  _usb_get_descriptor             = NULL ;
  _usb_bulk_write                 = NULL ;
  _usb_bulk_read                  = NULL ;
  _usb_interrupt_write            = NULL ;
  _usb_interrupt_read             = NULL ;
  _usb_control_msg                = NULL ;
  _usb_set_configuration          = NULL ;
  _usb_claim_interface            = NULL ;
  _usb_release_interface          = NULL ;
  _usb_set_altinterface           = NULL ;
  _usb_resetep                    = NULL ;
  _usb_clear_halt                 = NULL ;
  _usb_reset                      = NULL ;
  _usb_reset_ex                   = NULL ;
  _usb_strerror                   = NULL ;
  _usb_init                       = NULL ;
  _usb_set_debug                  = NULL ;
  _usb_find_busses                = NULL ;
  _usb_find_devices               = NULL ;
  _usb_device                     = NULL ;
  _usb_get_busses                 = NULL ;
  _usb_install_service_np         = NULL ;
  _usb_uninstall_service_np       = NULL ;
  _usb_install_driver_np          = NULL ;
  _usb_get_version                = NULL ;
  _usb_isochronous_setup_async    = NULL ;
  _usb_bulk_setup_async           = NULL ;
  _usb_interrupt_setup_async      = NULL ;
  _usb_submit_async               = NULL ;
  _usb_reap_async                 = NULL ;
  _usb_free_async                 = NULL ;
}

HOSTUSB_API int usb_init(unsigned long *a)
{
  /* void */
  FILE *f = NULL ;
  
  usb_init_dll() ;

#if MYTRACE
  f = fopen("hostusb.trace", "a") ;
#endif

  if (f)
  {
      fprintf(f, "USB %08lx\n", husbhandle) ;

//    fprintf(f, "FUNCTION POINTERS\n") ;
//    fprintf(f, "usb_init         %08lx\n", _usb_init) ;
//    fprintf(f, "usb_set_debug    %08lx\n", _usb_set_debug) ;
//    fprintf(f, "usb_find_busses  %08lx\n", _usb_find_busses) ;
//    fprintf(f, "usb_find_devices %08lx\n", _usb_find_devices) ;
//    fprintf(f, "usb_device       %08lx\n", _usb_device) ;
//    fprintf(f, "usb_get_busses   %08lx\n", _usb_get_busses) ;
//    fprintf(f, "usb_get_version  %08lx\n", _usb_get_version) ;

    fclose(f) ;
  }

  if (_usb_init != NULL)
  {
    _usb_init() ;
    return 0 ;
  }

  return -1 ;
}

HOSTUSB_API void usb_set_debug(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;

  /* int level d1 */

  if (_usb_set_debug != NULL)
  {
    _usb_set_debug(stk->d1) ;
  }
}

HOSTUSB_API int usb_find_busses(unsigned long *a)
{
  /* void */

  if (_usb_find_busses != NULL)
  {
    return _usb_find_busses() ;
  }
  return -ENOFILE ;
}

HOSTUSB_API int usb_find_devices(unsigned long *a)
{
  /* void */

  if (_usb_find_devices != NULL)
  {
    return _usb_find_devices() ;
  }
  return -ENOFILE ;
}

HOSTUSB_API struct usb_device * usb_device(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;

  /* usb_dev_handle *dev */

  if (_usb_device != NULL)
  {
    return _usb_device((usb_dev_handle *)stk->d1) ;
  }
  return NULL ;
}

HOSTUSB_API struct usb_bus * usb_get_busses(unsigned long *a)
{
  /* void */

  if (_usb_get_busses != NULL)
  {
    return _usb_get_busses() ;
  }
  return NULL ;
}

HOSTUSB_API struct usb_bus * usb_get_next_bus(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;

  /* struct usb_bus * d1 */

  return ((struct usb_bus *)(stk->d1))->next ;
}

HOSTUSB_API const struct usb_version * usb_get_version(unsigned long *a)
{
  /* void */
  FILE *f = NULL ;
  
  usb_init_dll() ;

#if MYTRACE
  f = fopen("hostusb.trace", "a") ;
#endif
  if (f)
  {
    fprintf(f, "USB (from usb_get_version()) %08lx\n", husbhandle) ;
    fclose(f) ;
  }

  if (_usb_get_version != NULL)
  {
    return _usb_get_version() ;
  }

  return NULL ;
}

HOSTUSB_API void usb_get_version2(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_init_dll() ;

  /* struct usb_version * d1 */

  if (_usb_get_version != NULL)
  {
    if (stk->d1 != 0)
    {
      memcpy((char *)stk->d1, _usb_get_version(), sizeof(struct usb_version)) ;
    }
  }
}

HOSTUSB_API usb_dev_handle *usb_open(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  struct usb_device *dev = (struct usb_device *)stk->d1 ;

  if (_usb_open)
    return _usb_open(dev) ;

  return NULL ;
}

HOSTUSB_API int usb_close(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *)stk->d1 ;

  if (_usb_close)
    return _usb_close(dev);

  return -ENOFILE;
}

HOSTUSB_API int usb_get_string(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle*)stk->d1 ;
  int index           = (int)stk->d2 ;
  int langid          = (int)stk->d3 ;
  char *buf           = (char *)stk->d4 ;
  size_t buflen       = (size_t)stk->d5 ;

  if (_usb_get_string)
    return _usb_get_string(dev, index, langid, buf, buflen) ;

  return -ENOFILE ;
}

HOSTUSB_API int usb_get_string2(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle*)stk->d1 ;
  int index           = (int)stk->d2 ;
  int langid          = (int)stk->d3 ;
  char *buf           = (char *)stk->d4 ;
  size_t buflen       = (size_t)stk->d5 ;

  // trick to trap the usb_control_message issue
  if (_usb_control_msg)
    return _usb_control_msg(dev,
                            USB_ENDPOINT_IN,
                            USB_REQ_GET_DESCRIPTOR,
                            (USB_DT_STRING << 8) + index,
                            langid,
                            buf,
                            (int)buflen,
                            1000) ;

  return -ENOFILE ;
}

HOSTUSB_API int usb_get_string_simple(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle*)stk->d1 ;
  int index           = (int)stk->d2 ;
  char *buf           = (char *)stk->d3 ;
  size_t buflen       = (size_t)stk->d4 ;

  if (_usb_get_string_simple)
    return _usb_get_string_simple(dev, index, buf, buflen);

  return -ENOFILE ;
}

HOSTUSB_API int usb_get_descriptor_by_endpoint(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *udev = (usb_dev_handle*)stk->d1 ;
  int ep               = (int)stk->d2 ;
  unsigned char type   = (unsigned char)stk->d3 ;
  unsigned char index  = (unsigned char)stk->d4 ;
  void *buf            = (void*)stk->d5 ;
  int size             = (int)stk->d6 ;

  if (_usb_get_descriptor_by_endpoint)
    return _usb_get_descriptor_by_endpoint(udev, ep, type, index, buf, size);

  return -ENOFILE ;
}

HOSTUSB_API int usb_get_descriptor(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *udev = (usb_dev_handle*)stk->d1 ;
  unsigned char type   = (unsigned char)stk->d2 ;
  unsigned char index  = (unsigned char)stk->d3 ;
  void *buf            = (void *)stk->d4 ;
  int size             = (int)stk->d5 ;
  int ret              = -ENOFILE ;

  if (_usb_get_descriptor)
  {
    ret = _usb_get_descriptor(udev, type, index, buf, size) ;
  }

  return ret ;
}

HOSTUSB_API int usb_bulk_write(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *)stk->d1 ;
  int ep              = (int) stk->d2 ;
  char *bytes         = (char *)stk->d3 ;
  int size            = (int) stk->d4 ;
  int timeout         = (int) stk->d5 ;
  int ret             = -ENOFILE ;
  FILE *f             = NULL ;

  if (_usb_bulk_write)
  {
    ret = _usb_bulk_write(dev, ep, bytes, size, timeout);
  }

  if (debug)
  {
    f = fopen("usb_bulk.txt", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "usb_bulk_write(%08lx, /* dev */\n"
               "               %08lx, /* ep */\n"
               "               %08lx, /* bytes */\n"
               "               %08lx, /* size */\n"
               "               %08lx) /* timeout */ => %ld\n",
            dev,
            ep,
            bytes,
            size,
            timeout,
            ret) ;
    fclose(f) ;
  }

  return ret ;
}

HOSTUSB_API int usb_bulk_read(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  int ep              = (int) stk->d2 ;
  char *bytes         = (char *) stk->d3 ;
  int size            = (int) stk->d4 ;
  int timeout         = (int) stk->d5 ;
  int ret             = -ENOFILE ;
  FILE *f             = NULL ;

  if (_usb_bulk_read)
  {
    ret = _usb_bulk_read(dev, ep, bytes, size, timeout) ;
  }

  if (debug)
  {
    f = fopen("usb_bulk.txt", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "usb_bulk_read(%08lx, /* dev */\n"
               "              %08lx, /* ep */\n"
               "              %08lx, /* bytes */\n"
               "              %08lx, /* size */\n"
               "              %08lx) /* timeout */ => %ld\n",
            dev,
            ep,
            bytes,
            size,
            timeout,
            ret) ;
    fclose(f) ;
  }

  return ret ;
}

HOSTUSB_API int usb_interrupt_write(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  int ep              = (int) stk->d2 ;
  char *bytes         = (char *) stk->d3 ;
  int size            = (int) stk->d4 ;
  int timeout         = (int) stk->d5 ;

  if (_usb_interrupt_write)
    return _usb_interrupt_write(dev, ep, bytes, size, timeout);

  return -ENOFILE ;
}

HOSTUSB_API int usb_interrupt_read(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  int ep              = (int) stk->d2 ;
  char *bytes         = (char *) stk->d3 ;
  int size            = (int) stk->d4 ;
  int timeout         = (int) stk->d5 ;

  if (_usb_interrupt_read)
    return _usb_interrupt_read(dev, ep, bytes, size, timeout);

  return -ENOFILE ;
}

HOSTUSB_API int usb_control_msg(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  int requesttype     = (int) stk->d2 ;
  int request         = (int) stk->d3 ;
  int value           = (int) stk->d4 ;
  int index           = (int) stk->d5 ;
  char *bytes         = (char *) stk->d6 ;
  int size            = (int) stk->d7 ;
  int timeout         = (int) stk->a1 ;
  int ret = -ENOFILE ;
  FILE *f = NULL ;

  if (_usb_control_msg)
    ret = _usb_control_msg(dev, requesttype, request, value, index, bytes,
                                size, timeout);

  if (debug)
  {
    f = fopen("usb_control_msg.trace", "a") ;
  }

  if (f != NULL)
  {
    fprintf(f, "usb_control_msg(%08lx, /* dev */\n"
               "                %08lx, /* requesttype */\n"
               "                %08lx, /* request */\n"
               "                %08lx, /* value */\n"
               "                %08lx, /* index */\n"
               "                %08lx, /* bytes */\n"
               "                %08lx, /* size */\n"
               "                %08lx  /* timeout */) => %ld\n",
            dev,
            requesttype,
            request,
            value,
            index,
            bytes,
            size,
            timeout,
            ret) ;
    fclose(f) ;
  }

  return ret ;
}

HOSTUSB_API int usb_set_configuration(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  int configuration   = (int) stk->d2 ;

  if (_usb_set_configuration)
    return _usb_set_configuration(dev, configuration);

  return -ENOFILE;
}

HOSTUSB_API int usb_claim_interface(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  int interface       = (int) stk->d2 ;

  if (_usb_claim_interface)
    return _usb_claim_interface(dev, interface);

  return -ENOFILE;
}

HOSTUSB_API int usb_release_interface(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  int interface       = (int) stk->d2 ;

  if (_usb_release_interface)
    return _usb_release_interface(dev, interface);

  return -ENOFILE;
}

HOSTUSB_API int usb_set_altinterface(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  int alternate       = (int) stk->d2 ;

  if (_usb_set_altinterface)
    return _usb_set_altinterface(dev, alternate);

  return -ENOFILE;
}

HOSTUSB_API int usb_resetep(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  unsigned int ep     = (unsigned int) stk->d2 ;

  if (_usb_resetep)
    return _usb_resetep(dev, ep);

  return -ENOFILE;
}

HOSTUSB_API int usb_clear_halt(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  unsigned int ep     = (unsigned int) stk->d2 ;

  if (_usb_clear_halt)
    return _usb_clear_halt(dev, ep);

  return -ENOFILE;
}

HOSTUSB_API int usb_reset(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;

  if (_usb_reset)
    return _usb_reset(dev);

  return -ENOFILE;
}

HOSTUSB_API int usb_reset_ex(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  unsigned int reset_type = (unsigned int) stk->d2 ;

  if (_usb_reset_ex)
    return _usb_reset_ex(dev, reset_type);

  return -ENOFILE;
}

HOSTUSB_API char *usb_strerror(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  if (_usb_strerror)
    return _usb_strerror();

  return NULL;
}

#if 0
HOSTUSB_API void usb_set_debug(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  int level = (int) stk->d1 ;

  if (_usb_set_debug)
    _usb_set_debug(level);
}

HOSTUSB_API int usb_find_busses(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  if (_usb_find_busses)
    return _usb_find_busses();

  return -ENOFILE;
}

HOSTUSB_API int usb_find_devices(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  if (_usb_find_devices)
    return _usb_find_devices();

  return -ENOFILE;
}

HOSTUSB_API struct usb_device *usb_device(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;

  if (_usb_device)
    return _usb_device(dev);

  return NULL;
}

HOSTUSB_API struct usb_bus *usb_get_busses(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  if (_usb_get_busses)
    return _usb_get_busses();

  return NULL;
}
#endif

HOSTUSB_API int usb_install_service_np(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  if (_usb_install_service_np)
    return _usb_install_service_np();

  return -ENOFILE;
}

HOSTUSB_API int usb_uninstall_service_np(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  if (_usb_uninstall_service_np)
    return _usb_uninstall_service_np();

  return -ENOFILE;
}

HOSTUSB_API int usb_install_driver_np(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  const char *inf_file = (const char *) stk->d1 ;

  if (_usb_install_driver_np)
    return _usb_install_driver_np(inf_file);

  return -ENOFILE;
}

HOSTUSB_API int usb_isochronous_setup_async(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  void **context      = (void **) stk->d2 ;
  unsigned char ep    = (unsigned char) stk->d3 ;
  int pktsize         = (int) stk->d4 ;

  if (_usb_isochronous_setup_async)
    return _usb_isochronous_setup_async(dev, context, ep, pktsize);

  return -ENOFILE;
}

HOSTUSB_API int usb_bulk_setup_async(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  void **context      = (void **) stk->d2 ;
  unsigned char ep    = (unsigned char) stk->d3 ;

  if (_usb_bulk_setup_async)
    return _usb_bulk_setup_async(dev, context, ep);

  return -ENOFILE;
}

HOSTUSB_API int usb_interrupt_setup_async(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  usb_dev_handle *dev = (usb_dev_handle *) stk->d1 ;
  void **context      = (void**) stk->d2 ;
  unsigned char ep    = (unsigned char) stk->d3 ;

  if (_usb_interrupt_setup_async)
    return _usb_interrupt_setup_async(dev, context, ep);

  return -ENOFILE;
}

HOSTUSB_API int usb_submit_async(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  void *context = (void *) stk->d1 ;
  char *bytes   = (char *) stk->d2 ;
  int size      = (int) stk->d3 ;

  if (_usb_submit_async)
    return _usb_submit_async(context, bytes, size);

  return -ENOFILE;
}

HOSTUSB_API int usb_reap_async(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  void *context = (void *)stk->d1 ;
  int timeout   = (int) stk->d2 ;

  if (_usb_reap_async)
    return _usb_reap_async(context, timeout);

  return -ENOFILE;
}

HOSTUSB_API int usb_free_async(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;

  void **context = (void **)stk->d1 ;

  if (_usb_free_async)
    return _usb_free_async(context);

  return -ENOFILE;
}

/*********************************************************************************/
/* libusbx functions                                                             */
/*********************************************************************************/

void libusb_init_dll(void)
{
  if (hlibusbxhandle == NULL)
  {
    hlibusbxhandle = LoadLibrary("libusb-1.0.dll") ;

#if MYTRACE
    if (1)
    {
      FILE *f = fopen("hostusb.trace", "a") ;

      if (f)
      {
        fprintf(f, "LoadLibrary(\"libusb-1.0.dll\") => 0x%08lx\n", hlibusbxhandle) ;
        fclose(f) ;
      }
    }
#endif

    if (hlibusbxhandle != NULL)
    {
      _libusb_init = (libusb_init_t)                GetProcAddress(hlibusbxhandle, "libusb_init") ;
      _libusb_exit = (libusb_exit_t)                GetProcAddress(hlibusbxhandle, "libusb_exit") ;
      _libusb_set_debug = (libusb_set_debug_t)      GetProcAddress(hlibusbxhandle, "libusb_set_debug") ;
      _libusb_get_version = (libusb_get_version_t)  GetProcAddress(hlibusbxhandle, "libusb_get_version") ;
      _libusb_has_capability = (libusb_has_capability_t) GetProcAddress(hlibusbxhandle, "libusb_has_capability") ;
      _libusb_error_name = (libusb_error_name_t) GetProcAddress(hlibusbxhandle, "libusb_error_name") ;
      _libusb_get_device_list = (libusb_get_device_list_t) GetProcAddress(hlibusbxhandle, "libusb_get_device_list")  ;
      _libusb_free_device_list = (libusb_free_device_list_t) GetProcAddress(hlibusbxhandle, "libusb_free_device_list")  ;
      _libusb_ref_device = (libusb_ref_device_t) GetProcAddress(hlibusbxhandle, "libusb_ref_device") ;
      _libusb_unref_device = (libusb_unref_device_t) GetProcAddress(hlibusbxhandle, "libusb_unref_device") ;
      _libusb_get_configuration = (libusb_get_configuration_t) GetProcAddress(hlibusbxhandle, "libusb_get_configuration") ;
      _libusb_get_device_descriptor = (libusb_get_device_descriptor_t) GetProcAddress(hlibusbxhandle, "libusb_get_device_descriptor") ;
      _libusb_get_active_config_descriptor = (libusb_get_active_config_descriptor_t) GetProcAddress(hlibusbxhandle, "libusb_get_active_config_descriptor") ;
      _libusb_get_config_descriptor = (libusb_get_config_descriptor_t) GetProcAddress(hlibusbxhandle, "libusb_get_config_descriptor") ;
      _libusb_get_config_descriptor_by_value = (libusb_get_config_descriptor_by_value_t) GetProcAddress(hlibusbxhandle, "libusb_get_config_descriptor_by_value")  ;
      _libusb_free_config_descriptor = (libusb_free_config_descriptor_t) GetProcAddress(hlibusbxhandle, "libusb_free_config_descriptor") ;
      _libusb_get_bus_number = (libusb_get_bus_number_t) GetProcAddress(hlibusbxhandle, "libusb_get_bus_number") ;
      _libusb_get_port_number = (libusb_get_port_number_t) GetProcAddress(hlibusbxhandle, "libusb_get_port_number") ;
      _libusb_get_parent = (libusb_get_parent_t) GetProcAddress(hlibusbxhandle, "libusb_get_parent") ;
      _libusb_get_port_path = (libusb_get_port_path_t) GetProcAddress(hlibusbxhandle, "libusb_get_port_path") ;
      _libusb_get_device_address = (libusb_get_device_address_t) GetProcAddress(hlibusbxhandle, "libusb_get_device_address") ;
      _libusb_get_device_speed = (libusb_get_device_speed_t) GetProcAddress(hlibusbxhandle, "libusb_get_device_speed") ;
      _libusb_get_max_packet_size = (libusb_get_max_packet_size_t) GetProcAddress(hlibusbxhandle, "libusb_get_max_packet_size") ;
      _libusb_get_max_iso_packet_size = (libusb_get_max_iso_packet_size_t) GetProcAddress(hlibusbxhandle, "libusb_get_max_iso_packet_size") ;
      _libusb_open = (libusb_open_t) GetProcAddress(hlibusbxhandle, "libusb_open") ;
      _libusb_close = (libusb_close_t) GetProcAddress(hlibusbxhandle, "libusb_close") ;
      _libusb_get_device = (libusb_get_device_t) GetProcAddress(hlibusbxhandle, "libusb_get_device") ;
      _libusb_set_configuration = (libusb_set_configuration_t) GetProcAddress(hlibusbxhandle, "libusb_set_configuration") ;
      _libusb_claim_interface = (libusb_claim_interface_t) GetProcAddress(hlibusbxhandle, "libusb_claim_interface") ;
      _libusb_release_interface = (libusb_release_interface_t) GetProcAddress(hlibusbxhandle, "libusb_release_interface") ;
      _libusb_open_device_with_vid_pid = (libusb_open_device_with_vid_pid_t) GetProcAddress(hlibusbxhandle, "libusb_open_device_with_vid_pid") ;
      _libusb_set_interface_alt_setting = (libusb_set_interface_alt_setting_t) GetProcAddress(hlibusbxhandle, "libusb_set_interface_alt_setting") ;
      _libusb_clear_halt = (libusb_clear_halt_t) GetProcAddress(hlibusbxhandle, "libusb_clear_halt") ;
      _libusb_reset_device = (libusb_reset_device_t) GetProcAddress(hlibusbxhandle, "libusb_reset_device") ;
      _libusb_kernel_driver_active = (libusb_kernel_driver_active_t) GetProcAddress(hlibusbxhandle, "libusb_kernel_driver_active") ;
      _libusb_detach_kernel_driver = (libusb_detach_kernel_driver_t) GetProcAddress(hlibusbxhandle, "libusb_detach_kernel_driver") ;
      _libusb_attach_kernel_driver = (libusb_attach_kernel_driver_t) GetProcAddress(hlibusbxhandle, "libusb_attach_kernel_driver") ;
      _libusb_control_transfer = (libusb_control_transfer_t) GetProcAddress(hlibusbxhandle, "libusb_control_transfer") ;
      _libusb_bulk_transfer = (libusb_bulk_transfer_t) GetProcAddress(hlibusbxhandle, "libusb_bulk_transfer") ;
      _libusb_interrupt_transfer = (libusb_interrupt_transfer_t) GetProcAddress(hlibusbxhandle, "libusb_interrupt_transfer") ;
    }
  }
}

void libusb_exit_dll(void)
{
#if MYTRACE
    if (1)
    {
      FILE *f = fopen("hostusb.trace", "a") ;

      if (f)
      {
        fprintf(f, "FreeLibrary(0x%08lx)\n", hlibusbxhandle) ;
        fclose(f) ;
      }
    }
#endif

  if (hlibusbxhandle != NULL)
  {
    FreeLibrary(hlibusbxhandle) ;
    hlibusbxhandle = NULL ; 
  }

  _libusb_init                           = NULL ;
  _libusb_exit                           = NULL ;
  _libusb_set_debug                      = NULL ;
  _libusb_get_version                    = NULL ;
  _libusb_has_capability                 = NULL ;
  _libusb_error_name                     = NULL ;
  _libusb_get_device_list                = NULL ;
  _libusb_free_device_list               = NULL ;
  _libusb_ref_device                     = NULL ;
  _libusb_unref_device                   = NULL ;
  _libusb_get_configuration              = NULL ;
  _libusb_get_device_descriptor          = NULL ;
  _libusb_get_active_config_descriptor   = NULL ;
  _libusb_get_config_descriptor          = NULL ;
  _libusb_get_config_descriptor_by_value = NULL ;
  _libusb_free_config_descriptor         = NULL ;
  _libusb_get_bus_number                 = NULL ;
  _libusb_get_port_number                = NULL ;
  _libusb_get_parent                     = NULL ;
  _libusb_get_port_path                  = NULL ;
  _libusb_get_device_address             = NULL ;
  _libusb_get_device_speed               = NULL ;
  _libusb_get_max_packet_size            = NULL ;
  _libusb_get_max_iso_packet_size        = NULL ;
  _libusb_open                           = NULL ;
  _libusb_close                          = NULL ;
  _libusb_get_device                     = NULL ;
  _libusb_set_configuration              = NULL ;
  _libusb_claim_interface                = NULL ;
  _libusb_release_interface              = NULL ;
  _libusb_open_device_with_vid_pid       = NULL ;
  _libusb_set_interface_alt_setting      = NULL ;
  _libusb_clear_halt                     = NULL ;
  _libusb_reset_device                   = NULL ;
  _libusb_kernel_driver_active           = NULL ;
  _libusb_detach_kernel_driver           = NULL ;
  _libusb_attach_kernel_driver           = NULL ;
  _libusb_control_transfer               = NULL ;
  _libusb_bulk_transfer                  = NULL ;
  _libusb_interrupt_transfer             = NULL ;
}

HOSTUSB_API int libusb_init(unsigned long *a)
{
  struct StackFrame  *stk = (struct StackFrame *)&a ;
  libusb_context **ctx = (libusb_context **)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;
#endif

  libusb_init_dll() ;

#if MYTRACE
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_init(%08lx)\n", ctx) ;
    fclose(f) ;
  }
#endif

  if (_libusb_init)
    return _libusb_init(ctx) ;
  
  return -ENOFILE ;
}

HOSTUSB_API void libusb_exit(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_context *ctx = (libusb_context *)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;

  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_exit(%08lx)\n", ctx) ;
    fclose(f) ;
  }
#endif  

  if (_libusb_exit)
    _libusb_exit(ctx) ;
}

HOSTUSB_API void libusb_set_debug(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_context *ctx = (libusb_context*)stk->d1 ;
  int level           = (int)stk->d2 ;

  if (_libusb_set_debug)
    _libusb_set_debug(ctx, level) ;
}

HOSTUSB_API const struct libusb_version * libusb_get_version(unsigned long *a)
{
  /* void */
#if MYTRACE
  FILE *f = NULL ;
#endif
  
  libusb_init_dll() ;

#if MYTRACE
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "LIBUSB (from libusb_get_version()) %08lx\n", hlibusbxhandle) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_version)
    return _libusb_get_version() ;
  return NULL ;
}

HOSTUSB_API int libusb_has_capability(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  uint32_t capability = (uint32_t) stk->d1 ;

  if (_libusb_has_capability)
    return _libusb_has_capability(capability) ;
  return -1 ;
}

HOSTUSB_API const char * libusb_error_name(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  int errcode = (int) stk->d1 ;

  if (_libusb_error_name)
    return _libusb_error_name(errcode) ;
  return NULL ;
}

HOSTUSB_API ssize_t libusb_get_device_list(unsigned long *a)
{
  ssize_t ret = 0 ;
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_context *ctx   = (libusb_context *)stk->d1 ;
  libusb_device ***list = (libusb_device ***)stk->d2 ;
#if MYTRACE
  FILE *f = NULL ;
#endif

  if (_libusb_get_device_list)
  {
    ret = _libusb_get_device_list(ctx, list) ;
  }

#if MYTRACE
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_device_list(%08lx,%08lx) => %ld (%08lx)\n", ctx, list, ret, (list != NULL)? *list : NULL) ;
    fclose(f) ;
  }
#endif

  return ret ;
}

HOSTUSB_API void libusb_free_device_list(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device **list   = (libusb_device **) stk->d1 ;
  int unref_devices      = (int) stk->d2 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_free_device_list(%08lx,%08lx)\n", list, unref_devices) ;
    fclose(f) ;
  }
#endif

  if (_libusb_free_device_list)
    _libusb_free_device_list(list, unref_devices) ;
}

HOSTUSB_API libusb_device * libusb_ref_device(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *) stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_ref_device(%08lx)\n", dev) ;
    fclose(f) ;
  }
#endif

  if (_libusb_ref_device)
    return _libusb_ref_device(dev) ;

  return NULL ;
}

HOSTUSB_API void libusb_unref_device(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_unref_device(%08lx)\n", dev) ;
    fclose(f) ;
  }
#endif

  if (_libusb_unref_device)
    _libusb_unref_device(dev) ;
}

HOSTUSB_API int libusb_get_configuration(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  int *config               = (int *)stk->d2 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_configuration(%08lx,%08lx)\n", dev, config) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_configuration)
    return _libusb_get_configuration(dev, config) ;
  return -1 ;
}

HOSTUSB_API int libusb_get_device_descriptor(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev  = (libusb_device *) stk->d1 ;
  struct libusb_device_descriptor *desc = (struct libusb_device_descriptor *) stk->d2 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_device_descriptor(%08lx,%08lx)\n", dev, desc) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_device_descriptor)
    return _libusb_get_device_descriptor(dev, desc) ;
  return -1 ;
}

HOSTUSB_API int libusb_get_active_config_descriptor(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
  struct libusb_config_descriptor **config = (struct libusb_config_descriptor **)stk->d2 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_active_config_descriptor(%08lx,%08lx)\n", dev, config) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_active_config_descriptor)
    return _libusb_get_active_config_descriptor(dev, config) ;
  return -1 ;
}

HOSTUSB_API int libusb_get_config_descriptor(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev    =(libusb_device *)stk->d1 ;
  uint8_t config_index  = (uint8_t)stk->d2 ;
  struct libusb_config_descriptor **config = (struct libusb_config_descriptor **)stk->d3 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_config_descriptor(%08lx,%08lx,%08lx)\n", dev, config_index, config) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_config_descriptor)
    return _libusb_get_config_descriptor(dev, config_index, config) ; 
  return -1 ;
}

HOSTUSB_API int libusb_get_config_descriptor_by_value(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *) stk->d1 ;
  uint8_t bConfigurationValue = (uint8_t)stk->d2 ;
  struct libusb_config_descriptor **config = (struct libusb_config_descriptor **)stk->d3 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_config_descriptor_by_value(%08lx,%08lx,%08lx)\n", dev, bConfigurationValue, config) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_config_descriptor_by_value)
    return _libusb_get_config_descriptor_by_value(dev, bConfigurationValue, config) ;
  return -1 ;
}

HOSTUSB_API void libusb_free_config_descriptor(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  struct libusb_config_descriptor *config = (struct libusb_config_descriptor *)stk->d1 ;

  if (_libusb_free_config_descriptor)
    _libusb_free_config_descriptor(config) ;
}

HOSTUSB_API uint8_t libusb_get_bus_number(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_bus_number(%08lx)\n", dev) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_bus_number)
    return _libusb_get_bus_number(dev) ;
  return -1 ;
}

HOSTUSB_API uint8_t libusb_get_port_number(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;
  
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_port_number(%08lx)\n", dev) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_port_number)
    return _libusb_get_port_number(dev) ;
  return -1 ;
}

HOSTUSB_API libusb_device * libusb_get_parent(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;

  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_parent(%08lx)\n", dev) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_parent)
    return _libusb_get_parent(dev) ;
  return NULL ;
}

HOSTUSB_API int libusb_get_port_path(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_context *ctx = (libusb_context *)stk->d1 ;
  libusb_device *dev  = (libusb_device *)stk->d2 ;
  uint8_t* path       = (uint8_t*)stk->d3 ;
  uint8_t path_length = (uint8_t)stk->d4 ;

  if (_libusb_get_port_path)
    return _libusb_get_port_path(ctx, dev, path, path_length) ;
  return -1 ;
}

HOSTUSB_API uint8_t libusb_get_device_address(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;
  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_device_address(%08lx)\n", dev) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_device_address)
    return _libusb_get_device_address(dev) ;
  return -1 ;
}

HOSTUSB_API int libusb_get_device_speed(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;

  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_get_device_speed(%08lx)\n", dev) ;
    fclose(f) ;
  }
#endif

  if (_libusb_get_device_speed)
    return _libusb_get_device_speed(dev) ;
  return -1 ;
}

HOSTUSB_API int libusb_get_max_packet_size(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
  unsigned char endpoint = (unsigned char )stk->d2 ;

  if (_libusb_get_max_packet_size)
    return _libusb_get_max_packet_size(dev, endpoint) ;
  return -1 ;
}

HOSTUSB_API int libusb_get_max_iso_packet_size(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
  unsigned char endpoint = (unsigned char )stk->d2 ;

  if (_libusb_get_max_iso_packet_size)
    return _libusb_get_max_iso_packet_size(dev, endpoint) ;
  return -1 ;  
}

HOSTUSB_API int libusb_open(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device *dev = (libusb_device *)stk->d1 ;
  libusb_device_handle **handle = (libusb_device_handle **)stk->d2 ;
#if MYTRACE
  FILE *f = NULL ;

  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_open(%08lx,%08lx)\n", dev, handle) ;
    fclose(f) ;
  }
#endif

  if (_libusb_open)
    return _libusb_open(dev, handle) ;
  return -1 ;  
}

HOSTUSB_API void libusb_close(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev_handle = (libusb_device_handle *)stk->d1 ;
#if MYTRACE
  FILE *f = NULL ;

  f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "libusb_close(%08lx)\n", dev_handle) ;
    fclose(f) ;
  }
#endif

  if (_libusb_close)
    _libusb_close(dev_handle) ;  
}

HOSTUSB_API libusb_device * libusb_get_device(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev_handle = (libusb_device_handle *)stk->d1 ;

  if (_libusb_get_device)
    return _libusb_get_device(dev_handle) ;
  return NULL ; 
}

HOSTUSB_API int libusb_set_configuration(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  int configuration = (int)stk->d2 ;

  if (_libusb_set_configuration)
    return _libusb_set_configuration(dev, configuration) ;
  return -1 ; 
}

HOSTUSB_API int libusb_claim_interface(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev  = (libusb_device_handle *)stk->d1 ;
  int interface_number = (int)stk->d2 ;

  if (_libusb_claim_interface)
    return _libusb_claim_interface(dev, interface_number) ;
  return -1 ; 
}

HOSTUSB_API int libusb_release_interface(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  int interface_number = (int) stk->d2 ;

  if (_libusb_release_interface)
    return _libusb_release_interface(dev, interface_number) ;
  return -1 ; 
}

HOSTUSB_API libusb_device_handle * libusb_open_device_with_vid_pid(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_context *ctx = (libusb_context *)stk->d1 ;
  uint16_t vendor_id  = (uint16_t)stk->d2 ;
  uint16_t product_id = (uint16_t)stk->d3 ;

  if (_libusb_open_device_with_vid_pid)
    return _libusb_open_device_with_vid_pid(ctx, vendor_id, product_id) ;
  return NULL ; 
}

HOSTUSB_API int libusb_set_interface_alt_setting(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  int interface_number      = (int)stk->d2 ;
  int alternate_setting     = (int)stk->d3 ;

  if (_libusb_set_interface_alt_setting)
    return _libusb_set_interface_alt_setting(dev, interface_number, alternate_setting) ;
  return -1 ; 
}

HOSTUSB_API int libusb_clear_halt(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  unsigned char endpoint    = (unsigned char)stk->d2 ;

  if (_libusb_clear_halt)
    return _libusb_clear_halt(dev, endpoint) ;
  return -1 ; 
}

HOSTUSB_API int libusb_reset_device(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;

  if (_libusb_reset_device)
    return _libusb_reset_device(dev) ;
  return -1 ; 
}

HOSTUSB_API int libusb_kernel_driver_active(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  int interface_number = (int)stk->d2 ;

  if (_libusb_kernel_driver_active)
    return _libusb_kernel_driver_active(dev, interface_number) ;
  return -1 ; 
}

HOSTUSB_API int libusb_detach_kernel_driver(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  int interface_number      = (int)stk->d2 ;

  if (_libusb_detach_kernel_driver)
    return _libusb_detach_kernel_driver(dev, interface_number) ;
  return -1 ; 
}

HOSTUSB_API int libusb_attach_kernel_driver(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  int interface_number      = (int)stk->d2 ;

  if (_libusb_attach_kernel_driver)
    return _libusb_attach_kernel_driver(dev, interface_number) ;
  return -1 ; 
}

HOSTUSB_API int libusb_control_transfer(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev_handle = (libusb_device_handle *)stk->d1 ;
  uint8_t request_type = (uint8_t)stk->d2 ;
  uint8_t bRequest = (uint8_t)stk->d3 ;
  uint16_t wValue = (uint16_t)stk->d4 ;
  uint16_t wIndex = (uint16_t)stk->d5 ;
  unsigned char *data = (unsigned char *)stk->d6 ;
  uint16_t wLength = (uint16_t)stk->d7 ;
  unsigned int timeout = (unsigned int)stk->a1 ;

  if (_libusb_control_transfer)
    return _libusb_control_transfer(dev_handle, request_type, bRequest, wValue, wIndex, data, wLength, timeout) ;
  return -1 ;
}

HOSTUSB_API int libusb_bulk_transfer(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev_handle = (libusb_device_handle *)stk->d1 ;
  unsigned char endpoint = (unsigned char)stk->d2 ;
  unsigned char *data = (unsigned char *)stk->d3 ;
  int length = (int)stk->d4 ;
  int *actual_length = (int *)stk->d5 ;
  unsigned int timeout = (unsigned int)stk->d6 ;

  if (_libusb_bulk_transfer)
    return _libusb_bulk_transfer(dev_handle, endpoint, data, length, actual_length, timeout) ;
  return -1 ;
}

HOSTUSB_API int libusb_interrupt_transfer(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev_handle = (libusb_device_handle *) stk->d1 ;
  unsigned char endpoint = (unsigned char)stk->d2 ;
  unsigned char *data = (unsigned char *)stk->d3 ;
  int length = (int)stk->d4 ;
  int *actual_length = (int *)stk->d5 ;
  unsigned int timeout = (unsigned int)stk->d6 ;

  if (_libusb_interrupt_transfer)
    return _libusb_interrupt_transfer(dev_handle, endpoint, data, length, actual_length, timeout) ;
  return -1 ;
}

HOSTUSB_API int libusb_get_descriptor(unsigned long *a)
{
  struct StackFrame *stk = (struct StackFrame *)&a ;
  libusb_device_handle *dev = (libusb_device_handle *)stk->d1 ;
  uint8_t desc_type = (uint8_t)stk->d2 ;
  uint8_t desc_index = (uint8_t)stk->d3 ;
  unsigned char *data = (unsigned char *)stk->d4 ;
  int length = (int)stk->d5 ;

  if (_libusb_control_transfer)
    return _libusb_control_transfer(dev,
                                    LIBUSB_ENDPOINT_IN,
                                    LIBUSB_REQUEST_GET_DESCRIPTOR,
                                    (desc_type << 8) | desc_index,
                                    0,
                                    data,
                                    (uint16_t) length,
                                    1000) ;
  return -1 ;
}

// This is the constructor of a class that has been exported.
// see hostusb.h for the class definition
Chostusb::Chostusb()
{
#if MYTRACE
  FILE *f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "Chostusb::Chostusb()\n") ;
    fclose(f) ;
  }
#endif
}

Chostusb::~Chostusb()
{
#if MYTRACE
  FILE *f = fopen("hostusb.trace", "a") ;

  if (f)
  {
    fprintf(f, "Chostusb::~Chostusb()\n") ;
    fclose(f) ;
  }
#endif
}
