summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostDrivers/VBoxUSB/os2/usbcalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostDrivers/VBoxUSB/os2/usbcalls.c')
-rw-r--r--src/VBox/HostDrivers/VBoxUSB/os2/usbcalls.c1278
1 files changed, 1278 insertions, 0 deletions
diff --git a/src/VBox/HostDrivers/VBoxUSB/os2/usbcalls.c b/src/VBox/HostDrivers/VBoxUSB/os2/usbcalls.c
new file mode 100644
index 00000000..5950cc6f
--- /dev/null
+++ b/src/VBox/HostDrivers/VBoxUSB/os2/usbcalls.c
@@ -0,0 +1,1278 @@
+#define INCL_DOSERRORS
+#define INCL_DOSMEMMGR
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSDEVICES
+#define INCL_DOSDEVIOCTL
+#define INCL_DOSMODULEMGR
+#include <os2.h>
+
+#if !defined(__GNUC__) || defined(STATIC_USBCALLS)
+#include <string.h>
+#else
+#define memcpy __builtin_memcpy
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+
+#define LOG_GROUP LOG_GROUP_DRV_USBPROXY
+#include <VBox/log.h>
+
+#ifdef __GNUC__
+# define APIEXPORT __declspec(dllexport)
+#else
+# define APIEXPORT
+#endif
+
+#ifndef ERROR_USER_DEFINED_BASE
+/*#define ERROR_USER_DEFINED_BASE 0xFF00 */
+
+#define ERROR_I24_WRITE_PROTECT 0
+#define ERROR_I24_BAD_UNIT 1
+#define ERROR_I24_NOT_READY 2
+#define ERROR_I24_BAD_COMMAND 3
+#define ERROR_I24_CRC 4
+#define ERROR_I24_BAD_LENGTH 5
+#define ERROR_I24_SEEK 6
+#define ERROR_I24_NOT_DOS_DISK 7
+#define ERROR_I24_SECTOR_NOT_FOUND 8
+#define ERROR_I24_OUT_OF_PAPER 9
+#define ERROR_I24_WRITE_FAULT 10
+#define ERROR_I24_READ_FAULT 11
+#define ERROR_I24_GEN_FAILURE 12
+#define ERROR_I24_DISK_CHANGE 13
+#define ERROR_I24_WRONG_DISK 15
+#define ERROR_I24_UNCERTAIN_MEDIA 16
+#define ERROR_I24_CHAR_CALL_INTERRUPTED 17
+#define ERROR_I24_NO_MONITOR_SUPPORT 18
+#define ERROR_I24_INVALID_PARAMETER 19
+#define ERROR_I24_DEVICE_IN_USE 20
+#define ERROR_I24_QUIET_INIT_FAIL 21
+#endif
+
+#include "usbcalls.h"
+
+#define IOCAT_USBRES 0x000000A0 /* USB Resource device control */
+#define IOCTLF_NUMDEVICE 0x00000031 /* Get Number of plugged in Devices */
+#define IOCTLF_GETINFO 0x00000032 /* Get Info About a device */
+#define IOCTLF_AQUIREDEVICE 0x00000033
+#define IOCTLF_RELEASEDEVICE 0x00000034
+#define IOCTLF_GETSTRING 0x00000035
+#define IOCTLF_SENDCONTROLURB 0x00000036
+#define IOCTLF_SENDBULKURB 0x00000037 /* Send */
+#define IOCTLF_START_IRQ_PROC 0x00000038 /* Start IRQ polling in a buffer */
+#define IOCTLF_GETDEVINFO 0x00000039 /* Get information about device */
+#define IOCTLF_STOP_IRQ_PROC 0x0000003A /* Stop IRQ Polling */
+#define IOCTLF_START_ISO_PROC 0x0000003B /* Start ISO buffering in a Ringbuffer */
+#define IOCTLF_STOP_ISO_PROC 0x0000003C /* Stop ISO buffering */
+#define IOCTLF_CANCEL_IORB 0x0000003D /* Abort an IORB; */
+#define IOCTLF_SELECT_BULKPIPE 0x0000003E /* Select which Bulk endpoints can be used via Read/Write */
+#define IOCTLF_SENDIRQURB 0x0000003F /* Start IRQ polling in a buffer */
+#define IOCTLF_FIXUPDEVUCE 0x00000040 /* Fixup USB device configuration data */
+#define IOCTLF_REG_STATUSSEM 0x00000041 /* Register Semaphore for general Statuschange */
+#define IOCTLF_DEREG_STATUSSEM 0x00000042 /* Deregister Semaphore */
+#define IOCTLF_REG_DEVICESEM 0x00000043 /* Register Semaphore for a vendor&deviceID */
+#define IOCTLF_DEREG_DEVICESEM 0x00000044 /* Deregister Semaphore */
+
+
+#define NOTIFY_FREE 0
+#define NOTIFY_CHANGE 1
+#define NOTIFY_DEVICE 2
+#define MAX_NOTIFICATIONS 256
+
+#pragma pack(1)
+
+typedef struct
+{
+ HEV hDeviceAdded;
+ HEV hDeviceRemoved;
+ USHORT usFlags;
+ USHORT usVendor;
+ USHORT usProduct;
+ USHORT usBCDDevice;
+} NOTIFYENTRY, *PNOTIFYENTRY;
+
+#define DEV_SEM_ADD 0x00000001
+#define DEV_SEM_REMOVE 0x00000002
+#define DEV_SEM_MASK 0x00000003
+#define DEV_SEM_VENDORID 0x00000004
+#define DEV_SEM_PRODUCTID 0x00000008
+#define DEV_SEM_BCDDEVICE 0x00000010
+
+typedef struct{
+ ULONG ulSize;
+ ULONG ulCaps;
+ ULONG ulSemDeviceAdd;
+ ULONG ulSemDeviceRemove;
+} STATUSEVENTSET, * PSTATUSEVENTSET;
+
+
+typedef struct{
+ ULONG ulSize;
+ ULONG ulCaps;
+ ULONG ulSemDeviceAdd;
+ ULONG ulSemDeviceRemove;
+ USHORT usVendorID;
+ USHORT usProductID;
+ USHORT usBCDDevice;
+ USHORT usStatus;
+} DEVEVENTSET, * PDEVEVENTSET;
+
+typedef struct
+{
+ USHORT usVendorID;
+ USHORT usProductID;
+ USHORT usBCDDevice;
+ USHORT usDeviceNumber; /* Get the usDeviceNumber device in the system fi. if 2 acquire the 2nd device
+ 0 means first not acquired device. */
+} AQUIREDEV, *PAQUIREDEV;
+
+typedef struct
+{
+ UCHAR bRequestType;
+ UCHAR bRequest;
+ USHORT wValue;
+ USHORT wIndex;
+ USHORT wLength;
+ ULONG ulTimeout; /* in milliseconds */
+} SETUPPACKET, *PSETUPPACKET;
+
+typedef struct
+{
+ ULONG ulHandle;
+ UCHAR bRequestType;
+ UCHAR bRequest;
+ USHORT wValue;
+ USHORT wIndex;
+ USHORT wLength;
+ ULONG ulTimeout; /* in milliseconds */
+ USHORT usStatus;
+} USBCALLS_CTRL_REQ, *PUSBCALLS_CTRL_REQ;
+
+typedef struct
+{
+ ULONG ulDevHandle;
+ UCHAR ucEndpoint;
+ UCHAR ucAltInterface;
+ USHORT usStatus;
+ ULONG ulEvent;
+ ULONG ulID;
+} USBCALLS_ISO_START, *NPUSBCALLS_ISO_START, FAR *PUSBCALLS_ISO_START,
+ USBCALLS_IRQ_START, *NPUSBCALLS_IRQ_START, FAR *PUSBCALLS_IRQ_START,
+ USBCALLS_CANCEL_REQ, *NPUSBCALLS_CANCEL_REQ, FAR *PUSBCALLS_CANCEL_REQ;
+
+#define ISO_DIRMASK 0x80
+typedef struct
+{
+ ULONG hSemAccess; /* Synchronise access to the Pos values */
+ ULONG hDevice;
+ USHORT usPosWrite;
+ USHORT usPosRead;
+ USHORT usBufSize;
+ UCHAR ucEndpoint;
+ UCHAR ucAltInterface;
+ UCHAR ucBuffer[16*1023];
+} ISORINGBUFFER, *PISORINGBUFFER;
+
+typedef USBCALLS_ISO_START USBCALLS_ISO_STOP, * NPUSBCALLS_ISO_STOP, FAR *PUSBCALLS_ISO_STOP;
+typedef USBCALLS_ISO_START USBCALLS_IRQ_STOP, * NPUSBCALLS_IRQ_STOP, FAR *PUSBCALLS_IRQ_STOP;
+
+#define USB_TRANSFER_FULL_SIZE 0x01
+
+typedef struct
+{
+ ULONG ulDevHandle;
+ UCHAR ucEndpoint;
+ UCHAR ucAltInterface;
+ USHORT usStatus;
+ ULONG ulEvent;
+/* ULONG ulID; - yeah, right */
+ ULONG ulTimeout;
+ USHORT usDataProcessed;
+ USHORT usDataRemain;
+ USHORT usFlags;
+} USBCALLS_BULK_REQ, *PUSBCALLS_BULK_REQ;
+
+typedef struct
+{
+ ULONG ulDevHandle;
+ UCHAR ucEndpoint;
+ UCHAR ucAltInterface;
+ USHORT usStatus;
+ ULONG ulEvent;
+ ULONG ulID;
+ ULONG ulTimeout;
+ USHORT usDataLen;
+} LIBUSB_IRQ_REQ, *NPLIBUSB_IRQ_REQ, FAR *PLIBUSB_IRQ_REQ;
+
+typedef struct
+{
+ ULONG ulDevHandle;
+ UCHAR ucConfiguration;
+ UCHAR ucAltInterface;
+ USHORT usStatus;
+} LIBUSB_FIXUP, *NPLIBUSB_FIXUP, FAR *PLIBUSB_FIXUP;
+
+#pragma pack()
+
+/******************************************************************************/
+
+HFILE g_hUSBDrv;
+ULONG g_cInit;
+ULONG g_ulFreeNotifys;
+HMTX g_hSemNotifytable;
+NOTIFYENTRY g_Notifications[MAX_NOTIFICATIONS];
+
+HMTX g_hSemRingBuffers;
+PISORINGBUFFER g_pIsoRingBuffers;
+ULONG g_ulNumIsoRingBuffers;
+
+APIEXPORT APIRET APIENTRY
+InitUsbCalls(void)
+{
+ int i;
+ ULONG ulAction;
+ APIRET rc;
+
+ if (++g_cInit > 1)
+ return NO_ERROR;
+
+ rc = DosOpen( (PCSZ)"USBRESM$",
+ &g_hUSBDrv,
+ &ulAction,
+ 0,
+ FILE_NORMAL,
+ OPEN_ACTION_OPEN_IF_EXISTS,
+ OPEN_ACCESS_READWRITE |
+ OPEN_FLAGS_NOINHERIT |
+ OPEN_SHARE_DENYNONE,
+ 0 );
+ if(rc)
+ {
+ g_hUSBDrv = 0;
+ g_cInit = 0;
+
+ }
+ else
+ {
+ /* @@ToDO Add EnvVar or INI for dynamically setting the number */
+ g_ulNumIsoRingBuffers = 8;
+ for(i=0;i<MAX_NOTIFICATIONS;i++)
+ {
+ g_Notifications[i].usFlags = NOTIFY_FREE;
+ g_Notifications[i].hDeviceAdded = 0;
+ g_Notifications[i].hDeviceRemoved = 0;
+ g_Notifications[i].usVendor = 0;
+ g_Notifications[i].usProduct = 0;
+ g_Notifications[i].usBCDDevice = 0;
+ }
+ rc = DosAllocMem( (PPVOID)&g_pIsoRingBuffers,
+ g_ulNumIsoRingBuffers * sizeof(ISORINGBUFFER),
+ PAG_WRITE | PAG_COMMIT | OBJ_TILE);
+ if(!rc)
+ {
+ PISORINGBUFFER pIter = g_pIsoRingBuffers;
+ for(i=0;i< g_ulNumIsoRingBuffers;i++,pIter++)
+ {
+ pIter->hDevice = 0;
+ pIter->hSemAccess = 0; /* Synchronise access to the Pos values */
+ pIter->usPosWrite = 0;
+ pIter->usPosRead = 0;
+ pIter->usBufSize = 16*1023;
+ pIter->ucEndpoint = 0;
+ pIter->ucAltInterface = 0;
+ /*pIter->ucBuffer */
+ }
+ rc=DosCreateMutexSem(NULL,&g_hSemRingBuffers,DC_SEM_SHARED,FALSE);
+ if(!rc)
+ {
+ rc=DosCreateMutexSem(NULL,&g_hSemNotifytable,DC_SEM_SHARED,FALSE);
+ if(rc)
+ {
+ DosCloseMutexSem(g_hSemRingBuffers);
+ DosFreeMem(g_pIsoRingBuffers);
+ }
+ }
+ else
+ {
+ DosFreeMem(g_pIsoRingBuffers);
+ }
+ }
+
+ if(rc)
+ {
+ DosClose(g_hUSBDrv);
+ g_hUSBDrv = 0;
+ g_cInit = 0;
+ }
+ }
+ return g_cInit ? NO_ERROR : rc ? rc : ERROR_GEN_FAILURE;
+}
+
+APIEXPORT APIRET APIENTRY
+TermUsbCalls(void)
+{
+ if (!g_cInit)
+ return ERROR_GEN_FAILURE;
+ if(!--g_cInit)
+ {
+ int i;
+ for(i=0;i<MAX_NOTIFICATIONS;i++)
+ if( g_Notifications[i].usFlags != NOTIFY_FREE);
+ UsbDeregisterNotification((USBNOTIFY)(&g_Notifications[i]));
+
+ DosClose(g_hUSBDrv);
+ g_hUSBDrv = NULLHANDLE;
+
+ if (g_pIsoRingBuffers)
+ DosFreeMem(g_pIsoRingBuffers);
+
+ DosCloseMutexSem(g_hSemRingBuffers);
+ g_hSemRingBuffers = NULLHANDLE;
+ DosCloseMutexSem(g_hSemNotifytable);
+ g_hSemNotifytable = NULLHANDLE;
+ }
+ return NO_ERROR;
+}
+
+
+#ifdef VBOX /* complete wast of time */
+# define IsBadReadPointer(pBase, ulSize) (FALSE)
+# define IsBadWritePointer(pBase, ulSize) (FALSE)
+#else
+static BOOL IsBadReadPointer(PVOID pBase, ULONG ulSize)
+{
+ APIRET rc;
+ ULONG ulFlags;
+ rc = DosQueryMem(pBase, &ulSize, &ulFlags);
+
+ return rc!=0?TRUE:(ulFlags&PAG_READ)&&(ulFlags&PAG_COMMIT)?FALSE:TRUE;
+}
+
+static BOOL IsBadWritePointer(PVOID pBase, ULONG ulSize)
+{
+ APIRET rc;
+ ULONG ulFlags;
+ rc = DosQueryMem(pBase, &ulSize, &ulFlags);
+
+ return rc!=0?TRUE:((ulFlags&PAG_WRITE)==PAG_WRITE&&(ulFlags&PAG_COMMIT)==PAG_COMMIT)?FALSE:TRUE;
+}
+#endif
+
+APIEXPORT APIRET APIENTRY
+UsbQueryNumberDevices(ULONG *pulNumDev)
+{
+ APIRET rc;
+ ULONG ulLength;
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ if( IsBadWritePointer(pulNumDev,sizeof(ULONG)) )
+ return ERROR_INVALID_PARAMETER;
+ ulLength=sizeof(ULONG);
+ *pulNumDev = 0;
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_NUMDEVICE,
+ NULL, 0, NULL,
+ pulNumDev, ulLength, &ulLength);
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbQueryDeviceReport(ULONG ulDevNumber, ULONG *pulBufLen, PVOID pData)
+{
+ APIRET rc;
+ ULONG ulParmLen;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ if( IsBadWritePointer(pulBufLen, sizeof(ULONG)) )
+ return ERROR_INVALID_PARAMETER;
+
+ if( pData!=NULL && IsBadWritePointer(pData,*pulBufLen) )
+ return ERROR_INVALID_PARAMETER;
+ if(pData==NULL)
+ *pulBufLen = 0;
+ ulParmLen = sizeof(ulDevNumber);
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_GETINFO,
+ (PVOID)&ulDevNumber, ulParmLen, &ulParmLen,
+ pData, *pulBufLen, pulBufLen);
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbRegisterChangeNotification( PUSBNOTIFY pNotifyID,
+ HEV hDeviceAdded,
+ HEV hDeviceRemoved)
+{
+ APIRET rc;
+ int i;
+ STATUSEVENTSET EventSet;
+ ULONG ulSize;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ if( IsBadWritePointer(pNotifyID, sizeof(ULONG)) ||
+ (hDeviceAdded==0 && hDeviceRemoved==0) )
+ return ERROR_INVALID_PARAMETER;
+
+ ulSize = sizeof(EventSet);
+ EventSet.ulSize = ulSize;
+ EventSet.ulCaps = 0;
+
+ if(hDeviceAdded!=0)
+ {
+ ULONG ulCnt;
+ rc = DosQueryEventSem(hDeviceAdded,&ulCnt);
+ if(rc)
+ return rc;
+ EventSet.ulCaps |= DEV_SEM_ADD;
+ EventSet.ulSemDeviceAdd = hDeviceAdded;
+ }
+
+ if(hDeviceRemoved!=0)
+ {
+ ULONG ulCnt;
+ rc = DosQueryEventSem(hDeviceRemoved,&ulCnt);
+ if(rc)
+ return rc;
+ EventSet.ulCaps |= DEV_SEM_REMOVE;
+ EventSet.ulSemDeviceRemove = hDeviceRemoved;
+ }
+
+ rc = DosRequestMutexSem(g_hSemNotifytable,SEM_INDEFINITE_WAIT);
+ if(rc)
+ return rc;
+
+ for(i=0;i<MAX_NOTIFICATIONS;i++)
+ {
+ if( g_Notifications[i].usFlags == NOTIFY_FREE)
+ {
+ g_Notifications[i].usFlags = NOTIFY_CHANGE;
+ g_Notifications[i].hDeviceAdded = hDeviceAdded;
+ g_Notifications[i].hDeviceRemoved = hDeviceRemoved;
+ g_Notifications[i].usVendor = 0;
+ g_Notifications[i].usProduct = 0;
+ g_Notifications[i].usBCDDevice = 0;
+ break;
+ }
+ }
+ DosReleaseMutexSem(g_hSemNotifytable);
+ if(i==MAX_NOTIFICATIONS)
+ return USB_ERROR_NO_MORE_NOTIFICATIONS;
+
+ /* @@ToDo come up with a better way to generate IDs */
+ *pNotifyID = (USBNOTIFY) (&g_Notifications[i]);
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_REG_STATUSSEM,
+ NULL, 0, NULL,
+ &EventSet,ulSize, &ulSize);
+ if(rc)
+ {
+ g_Notifications[i].usFlags = NOTIFY_FREE;
+ *pNotifyID = 0;
+ }
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbRegisterDeviceNotification( PUSBNOTIFY pNotifyID,
+ HEV hDeviceAdded,
+ HEV hDeviceRemoved,
+ USHORT usVendor,
+ USHORT usProduct,
+ USHORT usBCDVersion)
+{
+ DEVEVENTSET EventSet;
+ ULONG ulCnt,ulSize;
+ int i;
+ APIRET rc;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ if( IsBadWritePointer(pNotifyID, sizeof(ULONG)) ||
+ hDeviceAdded==0 || hDeviceRemoved==0 ||
+ usVendor == 0 || usVendor == 0xFFFF ||
+ usProduct == 0 || usProduct == 0xFFFF )
+ return ERROR_INVALID_PARAMETER;
+
+
+ rc = DosQueryEventSem(hDeviceAdded,&ulCnt);
+ if(rc)
+ return rc;
+ rc = DosQueryEventSem(hDeviceRemoved,&ulCnt);
+ if(rc)
+ return rc;
+
+ ulSize = sizeof(EventSet);
+ EventSet.ulSize = ulSize;
+ EventSet.ulCaps = DEV_SEM_ADD | DEV_SEM_REMOVE |
+ DEV_SEM_VENDORID | DEV_SEM_PRODUCTID |
+ DEV_SEM_BCDDEVICE ;
+ EventSet.ulSemDeviceAdd = hDeviceAdded;
+ EventSet.ulSemDeviceRemove = hDeviceRemoved;
+ EventSet.usVendorID = usVendor;
+ EventSet.usProductID = usProduct;
+ EventSet.usBCDDevice = usBCDVersion;
+ EventSet.usStatus = 0;
+
+ rc = DosRequestMutexSem(g_hSemNotifytable,SEM_INDEFINITE_WAIT);
+
+ if(rc)
+ return rc;
+
+ for(i=0;i<MAX_NOTIFICATIONS;i++)
+ {
+ if( g_Notifications[i].usFlags == NOTIFY_FREE)
+ {
+ g_Notifications[i].usFlags = NOTIFY_DEVICE;
+ g_Notifications[i].hDeviceAdded = hDeviceAdded;
+ g_Notifications[i].hDeviceRemoved = hDeviceRemoved;
+ g_Notifications[i].usVendor = usVendor;
+ g_Notifications[i].usProduct = usProduct;
+ g_Notifications[i].usBCDDevice = usBCDVersion;
+ break;
+ }
+ }
+ DosReleaseMutexSem(g_hSemNotifytable);
+ if(i==MAX_NOTIFICATIONS)
+ return USB_ERROR_NO_MORE_NOTIFICATIONS;
+
+ /* @@ToDo come up with a better way to generate IDs */
+ *pNotifyID = (USBNOTIFY) (&g_Notifications[i]);
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_REG_DEVICESEM,
+ NULL, 0, NULL,
+ &EventSet,ulSize, &ulSize);
+ if(rc)
+ {
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_INVALID_PARAMETER) )
+ rc= ERROR_INVALID_PARAMETER;
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_GEN_FAILURE) )
+ rc= EventSet.usStatus;
+
+ g_Notifications[i].usFlags = NOTIFY_FREE;
+ *pNotifyID = 0;
+ }
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbDeregisterNotification( USBNOTIFY NotifyID )
+{
+ DEVEVENTSET EventSet;
+ USBNOTIFY MinID,MaxID;
+ ULONG Index, ulFunction, ulSize;
+ APIRET rc;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ MinID = (USBNOTIFY) (&g_Notifications[0]);
+ MaxID = (USBNOTIFY) (&g_Notifications[MAX_NOTIFICATIONS-1]);
+
+ if(NotifyID<MinID || NotifyID>MaxID)
+ return ERROR_INVALID_PARAMETER;
+
+ Index = NotifyID - MinID;
+
+ if(Index % sizeof(NOTIFYENTRY))
+ return ERROR_INVALID_PARAMETER;
+
+ Index /= sizeof(NOTIFYENTRY);
+
+ rc = DosRequestMutexSem(g_hSemNotifytable,SEM_INDEFINITE_WAIT);
+
+ switch(g_Notifications[Index].usFlags)
+ {
+ case NOTIFY_FREE:
+ DosReleaseMutexSem(g_hSemNotifytable);
+ return ERROR_INVALID_PARAMETER;
+ case NOTIFY_CHANGE:
+ ulFunction = IOCTLF_DEREG_STATUSSEM;
+ ulSize = sizeof(STATUSEVENTSET);
+ EventSet.ulSize = ulSize;
+ EventSet.ulCaps = DEV_SEM_ADD | DEV_SEM_REMOVE;
+ EventSet.ulSemDeviceAdd = g_Notifications[Index].hDeviceAdded;
+ EventSet.ulSemDeviceRemove = g_Notifications[Index].hDeviceRemoved;
+ break;
+ case NOTIFY_DEVICE:
+ ulFunction = IOCTLF_DEREG_DEVICESEM;
+ ulSize = sizeof(DEVEVENTSET);
+ EventSet.ulSize = ulSize;
+ EventSet.ulCaps = DEV_SEM_ADD | DEV_SEM_REMOVE |
+ DEV_SEM_VENDORID | DEV_SEM_PRODUCTID |
+ DEV_SEM_BCDDEVICE ;
+ EventSet.ulSemDeviceAdd = g_Notifications[Index].hDeviceAdded;
+ EventSet.ulSemDeviceRemove = g_Notifications[Index].hDeviceRemoved;
+ EventSet.usVendorID = g_Notifications[Index].usVendor;
+ EventSet.usProductID = g_Notifications[Index].usProduct;
+ EventSet.usBCDDevice = g_Notifications[Index].usBCDDevice;
+ EventSet.usStatus = 0;
+ break;
+ default:
+ DosReleaseMutexSem(g_hSemNotifytable);
+ return ERROR_GEN_FAILURE;
+ }
+
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, ulFunction,
+ NULL, 0, NULL,
+ &EventSet,ulSize, &ulSize);
+ if(0==rc)
+ {
+ g_Notifications[Index].usFlags = NOTIFY_FREE;
+ g_Notifications[Index].hDeviceAdded = 0;
+ g_Notifications[Index].hDeviceRemoved = 0;
+ g_Notifications[Index].usVendor = 0;
+ g_Notifications[Index].usProduct = 0;
+ g_Notifications[Index].usBCDDevice = 0;
+ } else
+ {
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_INVALID_PARAMETER) )
+ rc= ERROR_INVALID_PARAMETER;
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_GEN_FAILURE) )
+ rc= EventSet.usStatus;
+ }
+ DosReleaseMutexSem(g_hSemNotifytable);
+
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbOpen( PUSBHANDLE pHandle,
+ USHORT usVendor,
+ USHORT usProduct,
+ USHORT usBCDDevice,
+ USHORT usEnumDevice)
+{
+ ULONG ulCat, ulFunc;
+ ULONG ulParmLen, ulDataLen;
+ AQUIREDEV Aquire;
+ APIRET rc;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+ if(IsBadWritePointer(pHandle,sizeof(USBHANDLE)) )
+ return ERROR_INVALID_PARAMETER;
+
+ Aquire.usVendorID = usVendor;
+ Aquire.usProductID = usProduct;
+ Aquire.usBCDDevice = usBCDDevice;
+ Aquire.usDeviceNumber = usEnumDevice;
+ ulCat = 0xA0;
+ ulFunc = 0x33;
+ ulParmLen = sizeof(Aquire);
+ ulDataLen = sizeof(USBHANDLE);
+ rc = DosDevIOCtl( g_hUSBDrv,
+ ulCat,ulFunc, /*IOCAT_USBRES, IOCTLF_AQUIREDEVICE, */
+ &Aquire, ulParmLen, &ulParmLen,
+ pHandle, ulDataLen, &ulDataLen);
+
+ /* @@ ToDO maybe gether some info about device here (endpoints etc for safety checks) */
+ return rc;
+
+}
+
+APIEXPORT APIRET APIENTRY
+UsbClose( USBHANDLE Handle)
+{
+ APIRET rc;
+ ULONG ulDataLen,ulParmLen;
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ ulParmLen = sizeof(USBHANDLE);
+ ulDataLen = 0;
+
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_RELEASEDEVICE,
+ (PVOID)&Handle, ulParmLen, &ulParmLen,
+ NULL, ulDataLen, &ulDataLen);
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbCtrlMessage( USBHANDLE Handle,
+ UCHAR ucRequestType,
+ UCHAR ucRequest,
+ USHORT usValue,
+ USHORT usIndex,
+ USHORT usLength,
+ PVOID pData,
+ ULONG ulTimeout)
+{
+ APIRET rc;
+ USBCALLS_CTRL_REQ CtrlRequest;
+ ULONG ulParmLen, ulDataLen;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ ulParmLen = sizeof(USBCALLS_CTRL_REQ);
+ CtrlRequest.ulHandle = Handle;
+ CtrlRequest.bRequestType = ucRequestType;
+ CtrlRequest.bRequest = ucRequest;
+ CtrlRequest.wValue = usValue;
+ CtrlRequest.wIndex = usIndex;
+ CtrlRequest.wLength = usLength;
+ CtrlRequest.ulTimeout = ulTimeout;
+ ulDataLen = usLength;
+
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_SENDCONTROLURB,
+ (PVOID)&CtrlRequest, ulParmLen, &ulParmLen,
+ ulDataLen>0?(PVOID)pData:NULL,
+ ulDataLen,
+ ulDataLen>0?&ulDataLen:NULL);
+ if( rc != NO_ERROR )
+ {
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_INVALID_PARAMETER) )
+ rc= ERROR_INVALID_PARAMETER;
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_GEN_FAILURE) )
+ rc= CtrlRequest.usStatus;
+ }
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbBulkRead( USBHANDLE Handle,
+ UCHAR Endpoint,
+ UCHAR AltInterface,
+ ULONG *ulNumBytes,
+ PVOID pvData,
+ ULONG ulTimeout)
+{
+ return UsbBulkRead2(Handle, Endpoint, AltInterface, TRUE /* fShortOk */, ulNumBytes, pvData, ulTimeout);
+}
+
+APIEXPORT APIRET APIENTRY
+UsbBulkRead2( USBHANDLE Handle,
+ UCHAR Endpoint,
+ UCHAR AltInterface,
+ BOOL fShortOk,
+ ULONG *ulNumBytes,
+ PVOID pvData,
+ ULONG ulTimeout)
+{
+ APIRET rc;
+ ULONG ulParmLen, ulDataLen, ulToProcess, ulTotalProcessed;
+ USBCALLS_BULK_REQ BulkRequest;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ if(*ulNumBytes==0)
+ return 0;
+
+ /* just require this */
+ if ((ULONG)pvData & 0xfff)
+ return ERROR_INVALID_ADDRESS;
+ if ((ULONG)pvData >= 0x20000000)
+ return ERROR_INVALID_ADDRESS;
+
+ ulToProcess = *ulNumBytes;
+ ulTotalProcessed = 0;
+
+ do
+ {
+ /* Process up to 64k, making sure we're working on segments. */
+ ulDataLen = 0x10000 - ((ULONG)pvData & 0xffff);
+ if (ulDataLen > ulToProcess)
+ ulDataLen = ulToProcess;
+
+ ulParmLen = sizeof(USBCALLS_BULK_REQ);
+
+ memset(&BulkRequest, 0, sizeof(BulkRequest));
+ BulkRequest.ulDevHandle = Handle;
+ BulkRequest.ucEndpoint = Endpoint;
+ BulkRequest.ucAltInterface = AltInterface;
+ BulkRequest.usStatus = 0;
+ BulkRequest.ulEvent = 0;
+ //BulkRequest.ulID = (ULONG)pvData;
+ BulkRequest.ulTimeout = ulTimeout;
+ BulkRequest.usDataProcessed = 0;
+ BulkRequest.usDataRemain = ulDataLen;
+ BulkRequest.usFlags = fShortOk && ulDataLen == ulToProcess ? 0 : USB_TRANSFER_FULL_SIZE;
+
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_SENDBULKURB,
+ (PVOID)&BulkRequest, ulParmLen, &ulParmLen,
+ pvData, ulDataLen, &ulDataLen);
+ Log(("BulkRead: usStatus=%d rc=%ld usDataProcessed=%d usDataRemain=%d ulDataLen=%ld\n",
+ BulkRequest.usStatus, rc, BulkRequest.usDataProcessed, BulkRequest.usDataRemain, ulDataLen));
+
+ if (rc != NO_ERROR)
+ {
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_INVALID_PARAMETER) )
+ rc= ERROR_INVALID_PARAMETER;
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_GEN_FAILURE) )
+ rc= BulkRequest.usStatus;
+ break;
+ }
+
+ /* Adjust count and source pointer */
+ ulToProcess -= ulDataLen;
+ pvData = (PBYTE)pvData + ulDataLen;
+ ulTotalProcessed += BulkRequest.usDataProcessed;
+
+ if (BulkRequest.usDataProcessed != ulDataLen)
+ {
+ /* Transferred less than we wanted? so something is wrong,
+ or device doesn't wish to send more, exit loop */
+ rc = USB_ERROR_LESSTRANSFERED;
+ break;
+ }
+ } while( ulToProcess>0 );
+
+ *ulNumBytes = ulTotalProcessed;
+
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbBulkWrite( USBHANDLE Handle,
+ UCHAR Endpoint,
+ UCHAR AltInterface,
+ ULONG ulNumBytes,
+ PVOID pvData,
+ ULONG ulTimeout)
+{
+ return UsbBulkWrite2(Handle, Endpoint, AltInterface, FALSE /* fShortOk */, ulNumBytes, pvData, ulTimeout);
+}
+
+APIEXPORT APIRET APIENTRY
+UsbBulkWrite2( USBHANDLE Handle,
+ UCHAR Endpoint,
+ UCHAR AltInterface,
+ BOOL fShortOk,
+ ULONG ulNumBytes,
+ PVOID pvData,
+ ULONG ulTimeout)
+{
+ APIRET rc;
+ ULONG ulParmLen, ulDataLen;
+ USBCALLS_BULK_REQ BulkRequest;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ /* just require this */
+ if ((ULONG)pvData & 0xfff)
+ return ERROR_INVALID_ADDRESS;
+ if ((ULONG)pvData >= 0x20000000)
+ return ERROR_INVALID_ADDRESS;
+
+ do
+ {
+ /* Process up to 64k, making sure we're working on segments. */
+ ulDataLen = 0x10000 - ((ULONG)pvData & 0xffff);
+ if (ulDataLen > ulNumBytes)
+ ulDataLen = ulNumBytes;
+
+ ulParmLen = sizeof(USBCALLS_BULK_REQ);
+
+ memset(&BulkRequest, 0, sizeof(BulkRequest));
+ BulkRequest.ulDevHandle = Handle;
+ BulkRequest.ucEndpoint = Endpoint;
+ BulkRequest.ucAltInterface = AltInterface;
+ BulkRequest.usStatus = 0;
+ BulkRequest.ulEvent = 0;
+ //BulkRequest.ulID = (ULONG)pvData;
+ BulkRequest.ulTimeout = ulTimeout;
+ BulkRequest.usDataProcessed = 0;
+ BulkRequest.usDataRemain = ulDataLen;
+ BulkRequest.usFlags = fShortOk && ulDataLen == ulNumBytes ? 0 : USB_TRANSFER_FULL_SIZE;
+
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_SENDBULKURB,
+ &BulkRequest, ulParmLen, &ulParmLen,
+ pvData, ulDataLen, &ulDataLen );
+ Log(("BulkWrite: usStatus=%d rc=%ld usDataProcessed=%d usDataRemain=%d ulDataLen=%ld\n",
+ BulkRequest.usStatus, rc, BulkRequest.usDataProcessed, BulkRequest.usDataRemain, ulDataLen));
+ if (rc != NO_ERROR)
+ {
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_INVALID_PARAMETER) )
+ rc= ERROR_INVALID_PARAMETER;
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_GEN_FAILURE) )
+ rc= BulkRequest.usStatus;
+ break;
+ }
+ /* Adjust count and source pointer */
+ ulNumBytes -= ulDataLen;
+ pvData = (PBYTE)pvData + ulDataLen;
+ } while( ulNumBytes > 0 );
+
+ return rc;
+}
+
+APIRET APIENTRY
+UsbIrqStart( USBHANDLE Handle,
+ UCHAR Endpoint,
+ UCHAR AltInterface,
+ USHORT ulNumBytes,
+ PVOID pData,
+ PHEV pHevModified)
+{
+ APIRET rc;
+ ULONG ulParmLen, ulDataLen;
+ USBCALLS_IRQ_START IrqStart;
+ HEV hEvent;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ if(0==ulNumBytes || IsBadWritePointer(pData, ulNumBytes))
+ return ERROR_INVALID_PARAMETER;
+
+ rc = DosCreateEventSem( NULL,
+ &hEvent,
+ DC_SEM_SHARED,
+ FALSE);
+ if(rc)
+ return rc;
+
+ IrqStart.ulDevHandle = Handle;
+ IrqStart.ucEndpoint = Endpoint;
+ IrqStart.ucAltInterface = AltInterface;
+ IrqStart.usStatus = 0;
+ IrqStart.ulEvent = hEvent;
+ ulParmLen = sizeof(IrqStart);
+ ulDataLen = ulNumBytes;
+
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_START_IRQ_PROC,
+ (PVOID)&IrqStart, ulParmLen, &ulParmLen,
+ pData, ulDataLen,&ulDataLen);
+ if(rc)
+ DosCloseEventSem(hEvent);
+ else
+ *pHevModified = hEvent;
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbIrqStop( USBHANDLE Handle,
+ HEV HevModified)
+{
+ APIRET rc;
+ ULONG ulParmLen, ulDataLen;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ ulParmLen = sizeof(Handle);
+ ulDataLen = sizeof(HevModified);
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_STOP_IRQ_PROC,
+ (PVOID)&Handle, ulParmLen, &ulParmLen,
+ &HevModified, ulDataLen, &ulDataLen);
+ if(!rc)
+ DosCloseEventSem(HevModified);
+
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbIsoStart( USBHANDLE Handle,
+ UCHAR Endpoint,
+ UCHAR AltInterface,
+ ISOHANDLE *phIso)
+{
+ APIRET rc;
+ PISORINGBUFFER pIter = g_pIsoRingBuffers;
+ USBCALLS_ISO_START IsoStart;
+ ULONG ulParmLen, ulDataLen;
+ int i;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ rc = DosRequestMutexSem(g_hSemRingBuffers,SEM_INDEFINITE_WAIT);
+ if(rc)
+ return rc;
+
+ for(i=0;i< g_ulNumIsoRingBuffers;i++,pIter++)
+ {
+ if (pIter->hDevice==0)
+ {
+ pIter->hDevice = Handle;
+ break;
+ }
+ }
+ DosReleaseMutexSem(g_hSemRingBuffers);
+
+ if(i==g_ulNumIsoRingBuffers)
+ return USB_ERROR_OUTOF_RESOURCES;
+
+ IsoStart.ulDevHandle = Handle;
+ IsoStart.ucEndpoint = Endpoint;
+ IsoStart.ucAltInterface = AltInterface;
+ ulParmLen = sizeof(IsoStart);
+ ulDataLen = sizeof(ISORINGBUFFER);
+
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_STOP_IRQ_PROC,
+ (PVOID)&IsoStart, ulParmLen, &ulParmLen,
+ pIter, ulDataLen, &ulDataLen);
+ if(rc)
+ {
+ pIter->hDevice = 0;
+ *phIso = 0;
+ }
+ else
+ {
+ pIter->ucEndpoint = Endpoint;
+ pIter->ucAltInterface = AltInterface;
+ }
+ return rc;
+}
+
+static APIRET IsInvalidIsoHandle(const ISOHANDLE hIso)
+{
+ PISORINGBUFFER pIter;
+ ULONG i;
+ pIter = g_pIsoRingBuffers;
+
+ for(i=0;i<g_ulNumIsoRingBuffers;i++,pIter++)
+ {
+ if(pIter==(PISORINGBUFFER)hIso && pIter->hDevice)
+ return 0;
+ }
+ return ERROR_INVALID_PARAMETER;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbIsoStop( ISOHANDLE hIso)
+{
+
+ APIRET rc = NO_ERROR;
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+/* rc = DosDevIOCtl( g_hUSBDrv, */
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbIsoDequeue( ISOHANDLE hIso,
+ PVOID pBuffer,
+ ULONG ulNumBytes)
+{
+ APIRET rc;
+ PISORINGBUFFER pRB = (PISORINGBUFFER)hIso;
+
+ rc = IsInvalidIsoHandle(hIso);
+ if(rc)
+ return rc;
+ if(!(pRB->ucEndpoint & ISO_DIRMASK))
+ return ERROR_INVALID_PARAMETER;
+
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbIsoPeekQueue( ISOHANDLE hIso,
+ UCHAR * pByte,
+ ULONG ulOffset)
+{
+ APIRET rc;
+ PISORINGBUFFER pRB = (PISORINGBUFFER)hIso;
+
+ rc = IsInvalidIsoHandle(hIso);
+ if(rc)
+ return rc;
+ if(!(pRB->ucEndpoint & ISO_DIRMASK))
+ return ERROR_INVALID_PARAMETER;
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbIsoEnqueue( ISOHANDLE hIso,
+ const UCHAR * pBuffer,
+ ULONG ulNumBytes)
+{
+ APIRET rc;
+ PISORINGBUFFER pRB = (PISORINGBUFFER)hIso;
+
+ rc = IsInvalidIsoHandle(hIso);
+ if(rc)
+ return rc;
+ if(pRB->ucEndpoint & ISO_DIRMASK)
+ return ERROR_INVALID_PARAMETER;
+
+ return rc;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbIsoGetLength( ISOHANDLE hIso,
+ ULONG *pulLength)
+{
+ APIRET rc;
+ PISORINGBUFFER pRB = (PISORINGBUFFER) hIso;
+ USHORT ri,wi;
+
+ rc = IsInvalidIsoHandle(hIso);
+ if(rc)
+ return rc;
+ wi = pRB->usPosWrite;
+ ri = pRB->usPosRead;
+
+ if (ri == wi)
+ *pulLength = 0;
+ else if (ri < wi)
+ *pulLength = wi - ri;
+ else
+ *pulLength = wi + (pRB->usBufSize - ri);
+
+ return 0;
+}
+
+APIEXPORT APIRET APIENTRY
+UsbIrqRead( USBHANDLE Handle,
+ UCHAR Endpoint,
+ UCHAR AltInterface,
+ ULONG *ulNumBytes,
+ PVOID pData,
+ ULONG ulTimeout)
+{
+ APIRET rc;
+ ULONG ulParmLen, ulDataLen;
+ LIBUSB_IRQ_REQ IrqRequest;
+
+ if(!g_cInit)
+ return USB_NOT_INIT;
+
+ /* 10 01 2003 - KIEWITZ -> Still @@ToDo Add Endpoint check based on descriptors
+ We currently only allow Endpoint-addresses 80h->8Fh here */
+ if ((Endpoint<0x80) || (Endpoint>0x8F))
+ return USB_ERROR_INVALID_ENDPOINT;
+
+ if(*ulNumBytes==0)
+ return 0;
+
+ IrqRequest.ulDevHandle = Handle;
+ IrqRequest.ucEndpoint = Endpoint;
+ IrqRequest.ucAltInterface = AltInterface;
+ IrqRequest.usStatus = 0;
+ IrqRequest.ulEvent = 0;
+ IrqRequest.ulTimeout = ulTimeout;
+ ulParmLen = sizeof(LIBUSB_IRQ_REQ);
+ ulDataLen = *ulNumBytes;
+
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_SENDIRQURB,
+ (PVOID)&IrqRequest, ulParmLen, &ulParmLen,
+ pData, ulDataLen, &ulDataLen);
+
+ if( rc == NO_ERROR )
+ {
+ *ulNumBytes = IrqRequest.usDataLen;
+ } else
+ {
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_INVALID_PARAMETER) )
+ rc= ERROR_INVALID_PARAMETER;
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_GEN_FAILURE) )
+ rc= IrqRequest.usStatus;
+ }
+ return rc;
+}
+
+
+APIEXPORT APIRET APIENTRY
+UsbFixupDevice( USBHANDLE Handle,
+ UCHAR ucConfiguration,
+ UCHAR *pucConfigurationData,
+ ULONG ulConfigurationLen )
+{
+ LIBUSB_FIXUP request;
+ ULONG ulParmLen;
+ APIRET rc;
+
+ request.ulDevHandle= Handle;
+ request.ucConfiguration= ucConfiguration;
+ request.usStatus= 0;
+ ulParmLen= sizeof(LIBUSB_FIXUP);
+ rc = DosDevIOCtl( g_hUSBDrv,
+ IOCAT_USBRES, IOCTLF_FIXUPDEVUCE,
+ (PVOID)&request, ulParmLen, &ulParmLen,
+ pucConfigurationData, ulConfigurationLen, &ulConfigurationLen);
+ if( rc != NO_ERROR )
+ {
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_INVALID_PARAMETER) )
+ rc= ERROR_INVALID_PARAMETER;
+ if( rc == (ERROR_USER_DEFINED_BASE|ERROR_I24_GEN_FAILURE) )
+ rc= request.usStatus;
+ }
+ return rc;
+}
+
+#ifndef STATIC_USBCALLS
+ /*+-------------------------------------------------------------------+*/
+ /*| _CRT_init is the C run-time environment initialization function. |*/
+ /*|It will return 0 to indicate success and -1 to indicate failure. |*/
+ /*+-------------------------------------------------------------------+*/
+
+/* int _CRT_init (void); */
+
+ /*+-------------------------------------------------------------------+*/
+ /*| _CRT_term is the C run-time environment termination function. |*/
+ /*+-------------------------------------------------------------------+*/
+
+/* void _CRT_term (unsigned long);*/
+
+ /*+-------------------------------------------------------------------+*/
+ /*| _DLL_InitTerm is the function that gets called by the operating |*/
+ /*| system loader when it loads and frees this DLL for each process |*/
+ /*| that accesses this DLL. However, it only gets called the first |*/
+ /*| time the DLL is loaded and the last time it is freed for a |*/
+ /*| particular process. The system linkage convention must be used |*/
+ /*| because the operating system loader is calling this function. |*/
+ /*+-------------------------------------------------------------------+*/
+
+#ifdef STATIC_LINK
+int _CRT_init (void);
+void _CRT_term(0UL);
+#endif
+
+unsigned long _System _DLL_InitTerm (unsigned long modhandle, unsigned long flag)
+{
+
+ /* If flag is zero then the DLL is being loaded so initialization */
+ /* should be performed. If flag is 1 then the DLL is being freed */
+ /* so termination should be performed. */
+
+ switch (flag)
+ {
+ case 0:
+ /* The C run-time environment initialization function must */
+ /* be called before any calls to C run-time functions that */
+ /* are not inlined. */
+
+#ifdef STATIC_LINK
+ if (_CRT_init () == -1)
+ return 0UL;
+#endif
+ InitUsbCalls();
+ break;
+
+ case 1:
+ TermUsbCalls();
+#ifdef STATIC_LINK
+ _CRT_term(0UL);
+#endif
+ break;
+
+ default:
+ return 0UL;
+
+ }
+
+ /* A nonzero value must be returned to indicate success. */
+ return 1UL;
+}
+#endif /* !STATIC_USBCALLS */
+