home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / usbd0906.zip / usb_20020906.zip / usbcalls / usbcalls.cpp < prev    next >
C/C++ Source or Header  |  2002-06-01  |  28KB  |  1,021 lines

  1. #define INCL_DOSERRORS
  2. #define INCL_DOSMEMMGR
  3. #define INCL_DOSSEMAPHORES
  4. #define INCL_DOSDEVICES
  5. #define INCL_DOSDEVIOCTL
  6. #include <OS2.h>
  7. //#include <stdlib.h>
  8. //#include <stdio.h>
  9.  
  10. #include "usbcalls.h"
  11.  
  12. #define  IOCAT_USBRES            0x000000A0  // USB Resource device control
  13. #define  IOCTLF_NUMDEVICE        0x00000031  // Get Number of pluged in Devices
  14. #define  IOCTLF_GETINFO          0x00000032  // Get Info About a device
  15. #define  IOCTLF_AQUIREDEVICE     0x00000033
  16. #define  IOCTLF_RELEASEDEVICE    0x00000034
  17. #define  IOCTLF_GETSTRING        0x00000035
  18. #define  IOCTLF_SENDCONTROLURB   0x00000036
  19. #define  IOCTLF_SENDBULKURB      0x00000037  // Send
  20. #define  IOCTLF_START_IRQ_PROC   0x00000038  // Start IRQ polling in a buffer
  21. #define  IOCTLF_GETDEVINFO       0x00000039  // Get information about device
  22. #define  IOCTLF_STOP_IRQ_PROC    0x0000003A  // Stop IRQ Polling
  23. #define  IOCTLF_START_ISO_PROC   0x0000003B  // Start ISO buffering in a Ringbuffer
  24. #define  IOCTLF_STOP_ISO_PROC    0x0000003C  // Stop ISO buffering
  25. #define  IOCTLF_CANCEL_IORB      0x0000003D  // Abord an IO;
  26. #define  IOCTLF_REG_STATUSSEM    0x00000041  // Register Semaphore for general Statuschange
  27. #define  IOCTLF_DEREG_STATUSSEM  0x00000042  // Deregister Semaphore
  28. #define  IOCTLF_REG_DEVICESEM    0x00000043  // Register Semaphore for a vendor&deviceID
  29. #define  IOCTLF_DEREG_DEVICESEM  0x00000044  // Deregister Semaphore
  30.  
  31.  
  32. #define NOTIFY_FREE   0
  33. #define NOTIFY_CHANGE 1
  34. #define NOTIFY_DEVICE 2
  35. #define MAX_NOTIFICATIONS 256
  36.  
  37. typedef struct
  38. {
  39.   HEV hDeviceAdded;
  40.   HEV hDeviceRemoved;
  41.   USHORT usFlags;
  42.   USHORT usVendor;
  43.   USHORT usProduct;
  44.   USHORT usBCDDevice;
  45. }NOTIFYENTRY, *PNOTIFYENTRY;
  46.  
  47. #define DEV_SEM_ADD       0x00000001
  48. #define DEV_SEM_REMOVE    0x00000002
  49. #define DEV_SEM_MASK      0x00000003
  50. #define DEV_SEM_VENDORID  0x00000004
  51. #define DEV_SEM_PRODUCTID 0x00000008
  52. #define DEV_SEM_BCDDEVICE 0x00000010
  53.  
  54. typedef struct{
  55.   ULONG  ulSize;
  56.   ULONG  ulCaps;
  57.   ULONG  ulSemDeviceAdd;
  58.   ULONG  ulSemDeviceRemove;
  59. } STATUSEVENTSET, * PSTATUSEVENTSET;
  60.  
  61.  
  62. typedef struct{
  63.   ULONG  ulSize;
  64.   ULONG  ulCaps;
  65.   ULONG  ulSemDeviceAdd;
  66.   ULONG  ulSemDeviceRemove;
  67.   USHORT usVendorID;
  68.   USHORT usProductID;
  69.   USHORT usBCDDevice;
  70.   USHORT usReserved;
  71. } DEVEVENTSET, * PDEVEVENTSET;
  72.  
  73. typedef struct
  74. {
  75.   USHORT usVendorID;
  76.   USHORT usProductID;
  77.   USHORT usBCDDevice;
  78.   USHORT usDeviceNumber; // Get the usDeviceNumber device in the system fi. if 2 aquire the 2nd device
  79.                          // 0 means first not aquired device.
  80. }AQUIREDEV,  *PAQUIREDEV;
  81.  
  82. typedef struct
  83. {
  84.   ULONG  ulDevHandle;
  85.   ULONG  ulEventDone;
  86.   UCHAR  ucEndpoint;
  87.   UCHAR  ucInterface;
  88.   USHORT usDataProcessed;
  89.   USHORT usDataRemain;
  90.   USHORT usStatus;
  91. }USBCALLS_BULK_REQ, *PUSBCALLS_BULK_REQ;
  92.  
  93. typedef struct
  94. {
  95.   UCHAR  bRequestType;
  96.   UCHAR  bRequest;
  97.   USHORT wValue;
  98.   USHORT wIndex;
  99.   USHORT wLength;
  100.   ULONG  ulTimeout; /* in milliseconds */
  101. }SETUPPACKET, *PSETUPPACKET;
  102.  
  103. typedef struct
  104. {
  105.   ULONG  ulHandle;
  106.   UCHAR  bRequestType;
  107.   UCHAR  bRequest;
  108.   USHORT wValue;
  109.   USHORT wIndex;
  110.   USHORT wLength;
  111.   ULONG  ulTimeout; /* in milliseconds */
  112. }USBCALLS_CTRL_REQ, *PUSBCALLS_CTRL_REQ;
  113.  
  114. typedef struct
  115. {
  116.   ULONG  ulDevHandle;
  117.   ULONG  ulIrqEvent;
  118.   UCHAR  ucEndpoint;
  119.   UCHAR  ucInterface;
  120. }USBCALLS_IRQ_START, *NPUSBCALLS_IRQ_START, FAR *PUSBCALLS_IRQ_START;
  121.  
  122. typedef struct
  123. {
  124.   ULONG ulDevHandle;
  125.   UCHAR ucEndpoint;
  126.   UCHAR ucInterface;
  127. }USBCALLS_ISO_START, *NPUSBCALLS_ISO_START, FAR *PUSBCALLS_ISO_START;
  128.  
  129. #define ISO_DIRMASK 0x80
  130. typedef struct
  131. {
  132.   ULONG  hSemAccess;        // Syncronise access to the Pos values
  133.   ULONG  hDevice;
  134.   USHORT usPosWrite;
  135.   USHORT usPosRead;
  136.   USHORT usBufSize;
  137.   UCHAR  ucEndpoint;
  138.   UCHAR  ucInterface;
  139.   UCHAR  ucBuffer[16*1023];
  140. }ISORINGBUFFER, * PISORINGBUFFER;
  141.  
  142. typedef USBCALLS_ISO_START USBCALLS_ISO_STOP, * NPUSBCALLS_ISO_STOP, FAR *PUSBCALLS_ISO_STOP;
  143. typedef USBCALLS_ISO_START USBCALLS_IRQ_STOP, * NPUSBCALLS_IRQ_STOP, FAR *PUSBCALLS_IRQ_STOP;
  144.  
  145.  
  146. HFILE g_hUSBDrv;
  147. BOOL  g_fInit;
  148. ULONG g_ulFreeNotifys;
  149. HMTX  g_hSemNotifytable;
  150. NOTIFYENTRY g_Notifications[MAX_NOTIFICATIONS];
  151.  
  152. HMTX  g_hSemRingBuffers;
  153. PISORINGBUFFER g_pIsoRingBuffers;
  154. ULONG g_ulNumIsoRingBuffers;
  155.  
  156. void InitUsbCalls()
  157. {
  158.   ULONG ulAction;
  159.   APIRET rc;
  160.  
  161.   rc = DosOpen( "USBRESM$",
  162.                 &g_hUSBDrv,
  163.                 &ulAction,
  164.                 0,
  165.                 FILE_NORMAL,
  166.                 OPEN_ACTION_OPEN_IF_EXISTS,
  167.                 OPEN_ACCESS_READWRITE |
  168.                 OPEN_FLAGS_NOINHERIT |
  169.                 OPEN_SHARE_DENYNONE,
  170.                 0 );
  171.   if(rc)
  172.   {
  173.     g_hUSBDrv = 0;
  174.     g_fInit   = FALSE;
  175.  
  176.   }
  177.   else
  178.   {
  179.     // @@ToDO Add EnvVar or INI for dynamically setting the number
  180.     g_ulNumIsoRingBuffers = 8;
  181.     for(int i=0;i<MAX_NOTIFICATIONS;i++)
  182.     {
  183.       g_Notifications[i].usFlags        = NOTIFY_FREE;
  184.       g_Notifications[i].hDeviceAdded   = 0;
  185.       g_Notifications[i].hDeviceRemoved = 0;
  186.       g_Notifications[i].usVendor       = 0;
  187.       g_Notifications[i].usProduct      = 0;
  188.       g_Notifications[i].usBCDDevice    = 0;
  189.     }
  190.     rc = DosAllocMem( (PPVOID)&g_pIsoRingBuffers,
  191.                       g_ulNumIsoRingBuffers * sizeof(ISORINGBUFFER),
  192.                       PAG_WRITE | PAG_COMMIT | OBJ_TILE);
  193.     if(!rc)
  194.     {
  195.       PISORINGBUFFER pIter = g_pIsoRingBuffers;
  196.       for(ULONG i=0;i< g_ulNumIsoRingBuffers;i++,pIter++)
  197.       {
  198.         pIter->hDevice     = 0;
  199.         pIter->hSemAccess  = 0;      // Syncronise access to the Pos values
  200.         pIter->usPosWrite  = 0;
  201.         pIter->usPosRead   = 0;
  202.         pIter->usBufSize   = 16*1023;
  203.         pIter->ucEndpoint  = 0;
  204.         pIter->ucInterface = 0;
  205.  
  206.         //pIter->ucBuffer
  207.       }
  208.       rc=DosCreateMutexSem(NULL,&g_hSemRingBuffers,DC_SEM_SHARED,FALSE);
  209.       if(!rc)
  210.       {
  211.         rc=DosCreateMutexSem(NULL,&g_hSemNotifytable,DC_SEM_SHARED,FALSE);
  212.         if(rc)
  213.         {
  214.           DosCloseMutexSem(g_hSemRingBuffers);
  215.           DosFreeMem(g_pIsoRingBuffers);
  216.         }
  217.       }
  218.       else
  219.       {
  220.         DosFreeMem(g_pIsoRingBuffers);
  221.       }
  222.     }
  223.  
  224.     if(rc)
  225.     {
  226.       DosClose(g_hUSBDrv);
  227.       g_hUSBDrv = 0;
  228.       g_fInit   = FALSE;
  229.     }
  230.     else
  231.       g_fInit = TRUE;
  232.   }
  233. }
  234.  
  235. BOOL IsBadReadPointer(PVOID pBase, ULONG ulSize)
  236. {
  237.   APIRET rc;
  238.   ULONG ulFlags;
  239.   rc = DosQueryMem(pBase, &ulSize, &ulFlags);
  240.  
  241.   return rc!=0?TRUE:(ulFlags&PAG_READ)&&(ulFlags&PAG_COMMIT)?FALSE:TRUE;
  242. }
  243.  
  244. BOOL IsBadWritePointer(PVOID pBase, ULONG ulSize)
  245. {
  246.   APIRET rc;
  247.   ULONG ulFlags;
  248.   rc = DosQueryMem(pBase, &ulSize, &ulFlags);
  249.  
  250.   return rc!=0?TRUE:((ulFlags&PAG_WRITE)==PAG_WRITE&&(ulFlags&PAG_COMMIT)==PAG_COMMIT)?FALSE:TRUE;
  251. }
  252.  
  253. #ifdef __cplusplus
  254.   extern "C" {
  255. #endif
  256.  
  257. APIRET APIENTRY UsbQueryNumberDevices( ULONG *pulNumDev)
  258. {
  259.   APIRET rc;
  260.   ULONG ulLength;
  261.   if(!g_fInit)
  262.     return USB_NOT_INIT;
  263.  
  264.   if( IsBadWritePointer(pulNumDev,sizeof(ULONG)) )
  265.     return ERROR_INVALID_PARAMETER;
  266.   ulLength=sizeof(ULONG);
  267.   *pulNumDev = 0;
  268.   rc = DosDevIOCtl( g_hUSBDrv,
  269.                     IOCAT_USBRES, IOCTLF_NUMDEVICE,
  270.                     NULL, 0, NULL,
  271.                     pulNumDev, ulLength, &ulLength);
  272.   return rc;
  273. }
  274.  
  275. APIRET APIENTRY UsbQueryDeviceReport( ULONG ulDevNumber,
  276.                              ULONG *pulBufLen,
  277.                              CHAR *pData)
  278. {
  279.   APIRET rc;
  280.   ULONG ulParmLen;
  281.  
  282.   if(!g_fInit)
  283.     return USB_NOT_INIT;
  284.  
  285.   if( IsBadWritePointer(pulBufLen, sizeof(ULONG)) )
  286.     return ERROR_INVALID_PARAMETER;
  287.  
  288.   if( pData!=NULL && IsBadWritePointer(pData,*pulBufLen) )
  289.     return ERROR_INVALID_PARAMETER;
  290.   if(pData==NULL)
  291.    *pulBufLen = 0;
  292.   ulParmLen = sizeof(ulDevNumber);
  293.   rc = DosDevIOCtl( g_hUSBDrv,
  294.                     IOCAT_USBRES, IOCTLF_GETINFO,
  295.                      (PVOID)&ulDevNumber, ulParmLen, &ulParmLen,
  296.                     pData, *pulBufLen, pulBufLen);
  297.   return rc;
  298. }
  299.  
  300. APIRET APIENTRY UsbRegisterChangeNotification( PUSBNOTIFY pNotifyID,
  301.                                       HEV hDeviceAdded,
  302.                                       HEV hDeviceRemoved)
  303. {
  304.   APIRET rc;
  305.   int i;
  306.   STATUSEVENTSET EventSet;
  307.   ULONG ulSize;
  308.  
  309.   if(!g_fInit)
  310.     return USB_NOT_INIT;
  311.  
  312.   if( IsBadWritePointer(pNotifyID, sizeof(ULONG)) ||
  313.       (hDeviceAdded==0 && hDeviceRemoved==0) )
  314.     return ERROR_INVALID_PARAMETER;
  315.  
  316.   ulSize = sizeof(EventSet);
  317.   EventSet.ulSize = ulSize;
  318.  
  319.   if(hDeviceAdded!=0)
  320.   {
  321.     ULONG ulCnt;
  322.     rc = DosQueryEventSem(hDeviceAdded,&ulCnt);
  323.     if(rc)
  324.       return rc;
  325.     EventSet.ulCaps         = DEV_SEM_ADD;
  326.     EventSet.ulSemDeviceAdd = hDeviceAdded;
  327.   }
  328.  
  329.   if(hDeviceRemoved!=0)
  330.   {
  331.     ULONG ulCnt;
  332.     rc = DosQueryEventSem(hDeviceRemoved,&ulCnt);
  333.     if(rc)
  334.       return rc;
  335.     EventSet.ulCaps            |= DEV_SEM_REMOVE;
  336.     EventSet.ulSemDeviceRemove = hDeviceRemoved;
  337.   }
  338.  
  339.   rc = DosRequestMutexSem(g_hSemNotifytable,SEM_INDEFINITE_WAIT);
  340.   if(rc)
  341.     return rc;
  342.  
  343.   for(i=0;i<MAX_NOTIFICATIONS;i++)
  344.   {
  345.     if( g_Notifications[i].usFlags == NOTIFY_FREE)
  346.     {
  347.       g_Notifications[i].usFlags = NOTIFY_CHANGE;
  348.       g_Notifications[i].hDeviceAdded   = hDeviceAdded;
  349.       g_Notifications[i].hDeviceRemoved = hDeviceRemoved;
  350.       g_Notifications[i].usVendor       = 0;
  351.       g_Notifications[i].usProduct      = 0;
  352.       g_Notifications[i].usBCDDevice    = 0;
  353.       break;
  354.     }
  355.   }
  356.   DosReleaseMutexSem(g_hSemNotifytable);
  357.   if(i==MAX_NOTIFICATIONS)
  358.     return USB_ERROR_NO_MORE_NOTIFICATIONS;
  359.  
  360.   // @@ToDo come up with a better way to generate IDs
  361.   *pNotifyID = (USBNOTIFY) (&g_Notifications[i]);
  362.   rc = DosDevIOCtl( g_hUSBDrv,
  363.                     IOCAT_USBRES, IOCTLF_REG_STATUSSEM,
  364.                     NULL, 0, NULL,
  365.                     &EventSet,ulSize, &ulSize);
  366.   if(rc)
  367.   {
  368.     g_Notifications[i].usFlags = NOTIFY_FREE;
  369.     *pNotifyID = 0;
  370.   }
  371.   return rc;
  372. }
  373.  
  374. APIRET APIENTRY UsbRegisterDeviceNotification( PUSBNOTIFY pNotifyID,
  375.                                       HEV hDeviceAdded,
  376.                                       HEV hDeviceRemoved,
  377.                                       USHORT usVendor,
  378.                                       USHORT usProduct,
  379.                                       USHORT usBCDVersion)
  380. {
  381.   APIRET rc;
  382.   ULONG ulCnt,ulSize;
  383.   int i;
  384.   DEVEVENTSET EventSet;
  385.  
  386.   if(!g_fInit)
  387.     return USB_NOT_INIT;
  388.  
  389.   if( IsBadWritePointer(pNotifyID, sizeof(ULONG)) ||
  390.       hDeviceAdded==0 || hDeviceRemoved==0 ||
  391.       usVendor  == 0  || usVendor  == 0xFFFF ||
  392.       usProduct == 0  || usProduct == 0xFFFF )
  393.     return ERROR_INVALID_PARAMETER;
  394.  
  395.  
  396.   rc = DosQueryEventSem(hDeviceAdded,&ulCnt);
  397.   if(rc)
  398.     return rc;
  399.   rc = DosQueryEventSem(hDeviceRemoved,&ulCnt);
  400.   if(rc)
  401.     return rc;
  402.  
  403.   ulSize = sizeof(EventSet);
  404.   EventSet.ulSize            = ulSize;
  405.   EventSet.ulCaps            = DEV_SEM_ADD | DEV_SEM_REMOVE |
  406.                                DEV_SEM_VENDORID | DEV_SEM_PRODUCTID |
  407.                                DEV_SEM_BCDDEVICE ;
  408.   EventSet.ulSemDeviceAdd    = hDeviceAdded;
  409.   EventSet.ulSemDeviceRemove = hDeviceRemoved;
  410.   EventSet.usVendorID        = usVendor;
  411.   EventSet.usProductID       = usProduct;
  412.   EventSet.usBCDDevice       = usBCDVersion;
  413.   EventSet.usReserved  = 0;
  414.  
  415.   rc = DosRequestMutexSem(g_hSemNotifytable,SEM_INDEFINITE_WAIT);
  416.   if(rc)
  417.     return rc;
  418.  
  419.   for(i=0;i<MAX_NOTIFICATIONS;i++)
  420.   {
  421.     if( g_Notifications[i].usFlags == NOTIFY_FREE)
  422.     {
  423.       g_Notifications[i].usFlags = NOTIFY_DEVICE;
  424.       g_Notifications[i].hDeviceAdded   = hDeviceAdded;
  425.       g_Notifications[i].hDeviceRemoved = hDeviceRemoved;
  426.       g_Notifications[i].usVendor       = usVendor;
  427.       g_Notifications[i].usProduct      = usProduct;
  428.       g_Notifications[i].usBCDDevice    = usBCDVersion;
  429.       break;
  430.     }
  431.   }
  432.   DosReleaseMutexSem(g_hSemNotifytable);
  433.   if(i==MAX_NOTIFICATIONS)
  434.     return USB_ERROR_NO_MORE_NOTIFICATIONS;
  435.  
  436.   // @@ToDo come up with a better way to generate IDs
  437.   *pNotifyID = (USBNOTIFY) (&g_Notifications[i]);
  438.   rc = DosDevIOCtl( g_hUSBDrv,
  439.                     IOCAT_USBRES, IOCTLF_REG_DEVICESEM,
  440.                     NULL, 0, NULL,
  441.                     &EventSet,ulSize, &ulSize);
  442.   if(rc)
  443.   {
  444.     g_Notifications[i].usFlags = NOTIFY_FREE;
  445.     *pNotifyID = 0;
  446.   }
  447.   return rc;
  448. }
  449.  
  450. APIRET APIENTRY UsbDeregisterNotification( USBNOTIFY NotifyID)
  451. {
  452.   APIRET rc;
  453.   USBNOTIFY MinID,MaxID;
  454.   ULONG Index, ulFunction, ulSize;
  455.   DEVEVENTSET EventSet;
  456.  
  457.   if(!g_fInit)
  458.     return USB_NOT_INIT;
  459.  
  460.   MinID = (USBNOTIFY) (&g_Notifications[0]);
  461.   MaxID = (USBNOTIFY) (&g_Notifications[MAX_NOTIFICATIONS-1]);
  462.  
  463.   if(NotifyID<MinID || NotifyID>MaxID)
  464.     return ERROR_INVALID_PARAMETER;
  465.  
  466.   Index = NotifyID - MinID;
  467.  
  468.   if(Index % sizeof(NOTIFYENTRY))
  469.     return ERROR_INVALID_PARAMETER;
  470.  
  471.   Index /= sizeof(NOTIFYENTRY);
  472.  
  473.   rc = DosRequestMutexSem(g_hSemNotifytable,SEM_INDEFINITE_WAIT);
  474.  
  475.   switch(g_Notifications[Index].usFlags)
  476.   {
  477.     case NOTIFY_FREE:
  478.       DosReleaseMutexSem(g_hSemNotifytable);
  479.       return ERROR_INVALID_PARAMETER;
  480.     case NOTIFY_CHANGE:
  481.       ulFunction  = IOCTLF_DEREG_STATUSSEM;
  482.       ulSize = sizeof(STATUSEVENTSET);
  483.       EventSet.ulSize            = ulSize;
  484.       EventSet.ulCaps            = DEV_SEM_ADD | DEV_SEM_REMOVE;
  485.       EventSet.ulSemDeviceAdd    = g_Notifications[Index].hDeviceAdded;
  486.       EventSet.ulSemDeviceRemove = g_Notifications[Index].hDeviceRemoved;
  487.       break;
  488.     case NOTIFY_DEVICE:
  489.       ulFunction = IOCTLF_DEREG_DEVICESEM;
  490.       ulSize = sizeof(DEVEVENTSET);
  491.       EventSet.ulSize            = ulSize;
  492.       EventSet.ulCaps            = DEV_SEM_ADD | DEV_SEM_REMOVE |
  493.                                    DEV_SEM_VENDORID | DEV_SEM_PRODUCTID |
  494.                                    DEV_SEM_BCDDEVICE ;
  495.       EventSet.ulSemDeviceAdd    = g_Notifications[Index].hDeviceAdded;
  496.       EventSet.ulSemDeviceRemove = g_Notifications[Index].hDeviceRemoved;
  497.       EventSet.usVendorID        = g_Notifications[Index].usVendor;
  498.       EventSet.usProductID       = g_Notifications[Index].usProduct;
  499.       EventSet.usBCDDevice       = g_Notifications[Index].usBCDDevice;
  500.       EventSet.usReserved  = 0;
  501.       break;
  502.     default:
  503.       DosReleaseMutexSem(g_hSemNotifytable);
  504.       return ERROR_GEN_FAILURE;
  505.   }
  506.  
  507.   rc = DosDevIOCtl( g_hUSBDrv,
  508.                     IOCAT_USBRES, ulFunction,
  509.                     NULL, 0, NULL,
  510.                     &EventSet,ulSize, &ulSize);
  511.   if(0==rc)
  512.   {
  513.     g_Notifications[Index].usFlags        = NOTIFY_FREE;
  514.     g_Notifications[Index].hDeviceAdded   = 0;
  515.     g_Notifications[Index].hDeviceRemoved = 0;
  516.     g_Notifications[Index].usVendor       = 0;
  517.     g_Notifications[Index].usProduct      = 0;
  518.     g_Notifications[Index].usBCDDevice    = 0;
  519.   }
  520.   DosReleaseMutexSem(g_hSemNotifytable);
  521.  
  522.   return rc;
  523. }
  524.  
  525. APIRET APIENTRY UsbOpen( PUSBHANDLE pHandle,
  526.                 USHORT usVendor,
  527.                 USHORT usProduct,
  528.                 USHORT usBCDDevice,
  529.                 USHORT usEnumDevice)
  530. {
  531.   APIRET rc;
  532.   AQUIREDEV Aquire;
  533.   ULONG   ulParmLen, ulDataLen;
  534.  
  535.   if(!g_fInit)
  536.     return USB_NOT_INIT;
  537.   if(IsBadWritePointer(pHandle,sizeof(USBHANDLE)) )
  538.     return ERROR_INVALID_PARAMETER;
  539.  
  540.   Aquire.usVendorID     = usVendor;
  541.   Aquire.usProductID    = usProduct;
  542.   Aquire.usBCDDevice    = usBCDDevice;
  543.   Aquire.usDeviceNumber = usEnumDevice;
  544.   ULONG ulCat, ulFunc;
  545.   ulCat  = 0xA0;
  546.   ulFunc = 0x33;
  547.   ulParmLen = sizeof(Aquire);
  548.   ulDataLen = sizeof(USBHANDLE);
  549.   rc = DosDevIOCtl( g_hUSBDrv,
  550.                     ulCat,ulFunc, //IOCAT_USBRES, IOCTLF_AQUIREDEVICE,
  551.                     &Aquire, ulParmLen, &ulParmLen,
  552.                     pHandle, ulDataLen, &ulDataLen);
  553.  
  554.   // @@ ToDO maybe gether some info about device here (endpoints etc for savety checks)
  555.   return rc;
  556.  
  557. }
  558.  
  559. APIRET APIENTRY UsbClose( USBHANDLE Handle)
  560. {
  561.   APIRET rc;
  562.   ULONG ulDataLen,ulParmLen;
  563.   if(!g_fInit)
  564.     return USB_NOT_INIT;
  565.  
  566.   ulParmLen = sizeof(USBHANDLE);
  567.   ulDataLen = 0;
  568.  
  569.   rc = DosDevIOCtl( g_hUSBDrv,
  570.                     IOCAT_USBRES, IOCTLF_RELEASEDEVICE,
  571.                     (PVOID)&Handle, ulParmLen, &ulParmLen,
  572.                     NULL, ulDataLen, &ulDataLen);
  573.   return rc;
  574. }
  575.  
  576. APIRET APIENTRY UsbCtrlMessage( USBHANDLE Handle,
  577.                        UCHAR  ucRequestType,
  578.                        UCHAR  ucRequest,
  579.                        USHORT usValue,
  580.                        USHORT usIndex,
  581.                        USHORT usLength,
  582.                        UCHAR  *pData,
  583.                        ULONG  ulTimeout)
  584. {
  585.   APIRET rc;
  586.   USBCALLS_CTRL_REQ CtrlRequest;
  587.   ULONG   ulParmLen, ulDataLen;
  588.  
  589.   if(!g_fInit)
  590.     return USB_NOT_INIT;
  591.  
  592.   ulParmLen = sizeof(USBCALLS_CTRL_REQ);
  593.   CtrlRequest.ulHandle     = Handle;
  594.   CtrlRequest.bRequestType = ucRequestType;
  595.   CtrlRequest.bRequest     = ucRequest;
  596.   CtrlRequest.wValue       = usValue;
  597.   CtrlRequest.wIndex       = usIndex;
  598.   CtrlRequest.wLength      = usLength;
  599.   CtrlRequest.ulTimeout    = ulTimeout;
  600.   ulDataLen = usLength;
  601.  
  602.   rc = DosDevIOCtl( g_hUSBDrv,
  603.                     IOCAT_USBRES, IOCTLF_SENDCONTROLURB,
  604.                     (PVOID)&CtrlRequest, ulParmLen, &ulParmLen,
  605.                     ulDataLen>0?(PVOID)pData:NULL,
  606.                     ulDataLen,
  607.                     ulDataLen>0?&ulDataLen:NULL);
  608.   return rc;
  609. }
  610.  
  611. APIRET APIENTRY UsbBulkRead( USBHANDLE Handle,
  612.                     UCHAR  Endpoint,
  613.                     UCHAR  Interface,
  614.                     USHORT *usNumBytes,
  615.                     UCHAR  *pData,
  616.                     ULONG  ulTimeout)
  617. {
  618.   APIRET rc;
  619.   ULONG ulParmLen, ulDataLen;
  620.   USBCALLS_BULK_REQ BulkRequest;
  621.  
  622.  
  623.   if(!g_fInit)
  624.     return USB_NOT_INIT;
  625.  
  626.   //  @@ToDo Add Endpoint checks here or in DD
  627.  
  628.   ulParmLen = sizeof(USBCALLS_BULK_REQ);
  629.  
  630.   rc = DosCreateEventSem( NULL,
  631.                          (PHEV)&BulkRequest.ulEventDone,
  632.                          DC_SEM_SHARED,
  633.                          FALSE);
  634.   if(rc)
  635.      return rc;
  636.   BulkRequest.ulDevHandle = Handle;
  637.   BulkRequest.ucEndpoint  = Endpoint;
  638.   BulkRequest.ucInterface = Interface;
  639.   BulkRequest.usDataProcessed = 0;
  640.   ulDataLen = *usNumBytes;
  641.  
  642.   rc = DosDevIOCtl( g_hUSBDrv,
  643.                     IOCAT_USBRES, IOCTLF_SENDBULKURB,
  644.                     (PVOID)&BulkRequest, ulParmLen, &ulParmLen,
  645.                     ulDataLen>0?(PVOID)pData:NULL,
  646.                     ulDataLen,
  647.                     ulDataLen>0?&ulDataLen:NULL);
  648.   if(rc==NO_ERROR)
  649.   {
  650.     rc = DosWaitEventSem( (HEV)BulkRequest.ulEventDone,
  651.                           ulTimeout==0?0xFFFFFFFF:ulTimeout);
  652.     if(rc==ERROR_TIMEOUT)
  653.     {
  654.       DosDevIOCtl( g_hUSBDrv,
  655.                    IOCAT_USBRES, IOCTLF_CANCEL_IORB,
  656.                    (PVOID)&BulkRequest, ulParmLen, &ulParmLen,
  657.                    NULL, 0, NULL);
  658.  
  659.     }
  660.   }
  661.   DosCloseEventSem( (HEV)BulkRequest.ulEventDone);
  662.  
  663. //  if(!rc)
  664.     *usNumBytes = BulkRequest.usDataProcessed;
  665. //  else
  666. //    *usNumBytes = 0;
  667.  
  668.   return rc;
  669. }
  670.  
  671. APIRET APIENTRY UsbBulkWrite( USBHANDLE Handle,
  672.                      UCHAR  Endpoint,
  673.                      UCHAR  Interface,
  674.                      USHORT usNumBytes,
  675.                      UCHAR  *pData,
  676.                      ULONG  ulTimeout)
  677. {
  678.   APIRET rc;
  679.   ULONG ulParmLen, ulDataLen;
  680.   USBCALLS_BULK_REQ BulkRequest;
  681.  
  682.   if(!g_fInit)
  683.     return USB_NOT_INIT;
  684.  
  685.   //  @@ToDo Add Endpoint checks here or in DD
  686.  
  687.   ulParmLen = sizeof(USBCALLS_BULK_REQ);
  688.  
  689.   rc = DosCreateEventSem( NULL,
  690.                          (PHEV)&BulkRequest.ulEventDone,
  691.                          DC_SEM_SHARED,
  692.                          FALSE);
  693.   if(rc)
  694.      return rc;
  695.   BulkRequest.ulDevHandle = Handle;
  696.   BulkRequest.ucEndpoint  = Endpoint;
  697.   BulkRequest.ucInterface = Interface;
  698.   BulkRequest.usDataProcessed = 0;
  699.  
  700.   ulDataLen = usNumBytes;
  701.  
  702.   rc = DosDevIOCtl( g_hUSBDrv,
  703.                     IOCAT_USBRES, IOCTLF_SENDBULKURB,
  704.                     (PVOID)&BulkRequest, ulParmLen, &ulParmLen,
  705.                     ulDataLen>0?(PVOID)pData:NULL,
  706.                     ulDataLen,
  707.                     ulDataLen>0?&ulDataLen:NULL);
  708.   if(rc==NO_ERROR)
  709.   {
  710.  
  711. //    ULONG ulRC,ulEvtCnt;
  712. //    ulRC = DosQueryEventSem(
  713.     rc = DosWaitEventSem( (HEV)BulkRequest.ulEventDone,
  714.                           ulTimeout==0?0xFFFFFFFF:ulTimeout);
  715.     if(rc==ERROR_TIMEOUT)
  716.     {
  717.       DosDevIOCtl( g_hUSBDrv,
  718.                    IOCAT_USBRES, IOCTLF_CANCEL_IORB,
  719.                    (PVOID)&BulkRequest, ulParmLen, &ulParmLen,
  720.                    NULL, 0, NULL);
  721.  
  722.     }
  723.   }
  724.   DosCloseEventSem( (HEV)BulkRequest.ulEventDone);
  725.   return rc;
  726. }
  727.  
  728. APIRET APIENTRY UsbIrqStart( USBHANDLE Handle,
  729.                     UCHAR  Endpoint,
  730.                     UCHAR  Interface,
  731.                     USHORT usNumBytes,
  732.                     UCHAR  *pData,
  733.                     PHEV   pHevModified)
  734. {
  735.   APIRET rc;
  736.   ULONG ulParmLen, ulDataLen;
  737.   USBCALLS_IRQ_START IrqStart;
  738.   HEV hEvent;
  739.  
  740.   if(!g_fInit)
  741.     return USB_NOT_INIT;
  742.  
  743.   if(0==usNumBytes || IsBadWritePointer(pData, usNumBytes))
  744.     return ERROR_INVALID_PARAMETER;
  745.  
  746.   rc = DosCreateEventSem( NULL,
  747.                           &hEvent,
  748.                           DC_SEM_SHARED,
  749.                           FALSE);
  750.   if(rc)
  751.     return rc;
  752.  
  753.   IrqStart.ulDevHandle = Handle;
  754.   IrqStart.ulIrqEvent  = hEvent;
  755.   IrqStart.ucEndpoint  = Endpoint;
  756.   IrqStart.ucInterface = Interface;
  757.   ulParmLen = sizeof(IrqStart);
  758.   ulDataLen = usNumBytes;
  759.  
  760.   rc = DosDevIOCtl( g_hUSBDrv,
  761.                     IOCAT_USBRES, IOCTLF_START_IRQ_PROC,
  762.                     (PVOID)&IrqStart, ulParmLen, &ulParmLen,
  763.                     pData, ulDataLen,&ulDataLen);
  764.   if(rc)
  765.     DosCloseEventSem(hEvent);
  766.   else
  767.     *pHevModified = hEvent;
  768.   return rc;
  769. }
  770.  
  771. APIRET APIENTRY UsbIrqStop(  USBHANDLE Handle,
  772.                     HEV       HevModified)
  773. {
  774.   APIRET rc;
  775.   ULONG ulParmLen, ulDataLen;
  776.  
  777.   if(!g_fInit)
  778.     return USB_NOT_INIT;
  779.  
  780.   ulParmLen = sizeof(Handle);
  781.   ulDataLen = sizeof(HevModified);
  782.   rc = DosDevIOCtl( g_hUSBDrv,
  783.                     IOCAT_USBRES, IOCTLF_STOP_IRQ_PROC,
  784.                     (PVOID)&Handle, ulParmLen, &ulParmLen,
  785.                     &HevModified, ulDataLen, &ulDataLen);
  786.   if(!rc)
  787.     DosCloseEventSem(HevModified);
  788.  
  789.   return rc;
  790. }
  791.  
  792. APIRET APIENTRY UsbIsoStart( USBHANDLE Handle,
  793.                     UCHAR  Endpoint,
  794.                     UCHAR  Interface,
  795.                     ISOHANDLE *phIso)
  796. {
  797.   APIRET rc;
  798.   PISORINGBUFFER pIter = g_pIsoRingBuffers;
  799.   USBCALLS_ISO_START IsoStart;
  800.   ULONG ulParmLen, ulDataLen;
  801.  
  802.   if(!g_fInit)
  803.     return USB_NOT_INIT;
  804.  
  805.   rc = DosRequestMutexSem(g_hSemRingBuffers,SEM_INDEFINITE_WAIT);
  806.   if(rc)
  807.     return rc;
  808.  
  809.   for(ULONG i=0;i< g_ulNumIsoRingBuffers;i++,pIter++)
  810.   {
  811.     if (pIter->hDevice==0)
  812.     {
  813.       pIter->hDevice = Handle;
  814.       break;
  815.     }
  816.   }
  817.   DosReleaseMutexSem(g_hSemRingBuffers);
  818.  
  819.   if(i==g_ulNumIsoRingBuffers)
  820.     return USB_ERROR_OUTOF_RESOURCES;
  821.  
  822.   IsoStart.ulDevHandle = Handle;
  823.   IsoStart.ucEndpoint  = Endpoint;
  824.   IsoStart.ucInterface = Interface;
  825.   ulParmLen = sizeof(IsoStart);
  826.   ulDataLen = sizeof(ISORINGBUFFER);
  827.  
  828.   rc = DosDevIOCtl( g_hUSBDrv,
  829.                     IOCAT_USBRES, IOCTLF_STOP_IRQ_PROC,
  830.                     (PVOID)&IsoStart, ulParmLen, &ulParmLen,
  831.                     pIter, ulDataLen, &ulDataLen);
  832.   if(rc)
  833.   {
  834.     pIter->hDevice = 0;
  835.     *phIso = 0;
  836.   }
  837.   else
  838.   {
  839.     pIter->ucEndpoint  = Endpoint;
  840.     pIter->ucInterface = Interface;
  841.   }
  842.   return rc;
  843. }
  844.  
  845. APIRET IsInvalidIsoHandle(const ISOHANDLE hIso)
  846. {
  847.   PISORINGBUFFER pIter;
  848.   ULONG i;
  849.   pIter = g_pIsoRingBuffers;
  850.  
  851.   for(i=0;i<g_ulNumIsoRingBuffers;i++,pIter++)
  852.   {
  853.     if(pIter==(PISORINGBUFFER)hIso && pIter->hDevice)
  854.       return 0;
  855.   }
  856.   return ERROR_INVALID_PARAMETER;
  857. }
  858.  
  859. APIRET APIENTRY UsbIsoStop( ISOHANDLE hIso)
  860. {
  861.  
  862.   APIRET rc;
  863.   if(!g_fInit)
  864.     return USB_NOT_INIT;
  865.  
  866. //  rc = DosDevIOCtl( g_hUSBDrv,
  867.   return rc;
  868. }
  869.  
  870. APIRET APIENTRY UsbIsoDequeue( ISOHANDLE hIso,
  871.                       UCHAR * pBuffer,
  872.                       ULONG ulNumBytes)
  873. {
  874.   APIRET rc;
  875.   PISORINGBUFFER pRB = (PISORINGBUFFER)hIso;
  876.  
  877.   rc = IsInvalidIsoHandle(hIso);
  878.   if(rc)
  879.     return rc;
  880.   if(!(pRB->ucEndpoint & ISO_DIRMASK))
  881.     return ERROR_INVALID_PARAMETER;
  882.  
  883.   return rc;
  884. }
  885.  
  886. APIRET APIENTRY UsbIsoPeekQueue( ISOHANDLE hIso,
  887.                         UCHAR * pByte,
  888.                         ULONG ulOffset)
  889. {
  890.   APIRET rc;
  891.   PISORINGBUFFER pRB = (PISORINGBUFFER)hIso;
  892.  
  893.   rc = IsInvalidIsoHandle(hIso);
  894.   if(rc)
  895.     return rc;
  896.   if(!(pRB->ucEndpoint & ISO_DIRMASK))
  897.     return ERROR_INVALID_PARAMETER;
  898.   return rc;
  899. }
  900.  
  901. APIRET APIENTRY UsbIsoEnqueue( ISOHANDLE hIso,
  902.                       const UCHAR * pBuffer,
  903.                       ULONG ulNumBytes)
  904. {
  905.   APIRET rc;
  906.   PISORINGBUFFER pRB = (PISORINGBUFFER)hIso;
  907.  
  908.   rc = IsInvalidIsoHandle(hIso);
  909.   if(rc)
  910.     return rc;
  911.   if(pRB->ucEndpoint & ISO_DIRMASK)
  912.     return ERROR_INVALID_PARAMETER;
  913.  
  914.   return rc;
  915. }
  916.  
  917. APIRET APIENTRY UsbIsoGetLength( ISOHANDLE hIso,
  918.                         ULONG *pulLength)
  919. {
  920.   APIRET rc;
  921.   PISORINGBUFFER pRB = (PISORINGBUFFER) hIso;
  922.   USHORT ri,wi;
  923.  
  924.   rc = IsInvalidIsoHandle(hIso);
  925.   if(rc)
  926.     return rc;
  927.   wi = pRB->usPosWrite;
  928.   ri = pRB->usPosRead;
  929.  
  930.   if (ri == wi)
  931.     *pulLength = 0;
  932.   else if (ri < wi)
  933.     *pulLength =  wi - ri;
  934.   else
  935.     *pulLength = wi + (pRB->usBufSize - ri);
  936.  
  937.   return 0;
  938. }
  939.  
  940.  
  941.  
  942.  /*+-------------------------------------------------------------------+*/
  943.  /*| _CRT_init is the C run-time environment initialization function.  |*/
  944.  /*|It will return 0 to indicate success and -1 to indicate failure.   |*/
  945.  /*+-------------------------------------------------------------------+*/
  946.  
  947. // int _CRT_init (void);
  948.  
  949.  /*+-------------------------------------------------------------------+*/
  950.  /*| _CRT_term is the C run-time environment termination function.     |*/
  951.  /*+-------------------------------------------------------------------+*/
  952.  
  953. // void _CRT_term (unsigned long);
  954.  
  955.  /*+-------------------------------------------------------------------+*/
  956.  /*| _DLL_InitTerm is the function that gets called by the operating   |*/
  957.  /*| system loader when it loads and frees this DLL for each process   |*/
  958.  /*| that accesses this DLL.  However, it only gets called the first   |*/
  959.  /*| time the DLL is loaded and the last time it is freed for a        |*/
  960.  /*| particular process.  The system linkage convention must be used   |*/
  961.  /*| because the operating system loader is calling this function.     |*/
  962.  /*+-------------------------------------------------------------------+*/
  963.  
  964. int _CRT_init (void);
  965. #ifdef STATIC_LINK
  966. void  _CRT_term(0UL);
  967. #endif
  968.  
  969. ULONG _System _DLL_InitTerm (unsigned long modhandle, unsigned long flag)
  970. {
  971.  
  972.   /* If flag is zero then the DLL is being loaded so initialization  */
  973.   /* should be performed.  If flag is 1 then the DLL is being freed  */
  974.   /* so termination should be performed.                             */
  975.  
  976.   switch (flag)
  977.   {
  978.     case 0:
  979.     /* The C run-time environment initialization function must   */
  980.     /* be called before any calls to C run-time functions that   */
  981.     /* are not inlined.                                          */
  982.  
  983.       if (_CRT_init () == -1)
  984.          return 0UL;
  985.       InitUsbCalls();
  986.       break;
  987.  
  988.     case 1:
  989.       if(g_fInit)
  990.       {
  991.         for(int i=0;i<MAX_NOTIFICATIONS;i++)
  992.         {
  993.           if( g_Notifications[i].usFlags != NOTIFY_FREE);
  994.           {
  995.  
  996.             // @@ ToDo deregister all Eventes in the driver on unload
  997.           }
  998.         }
  999.         DosClose(g_hUSBDrv);
  1000.       }
  1001.  
  1002. #ifdef STATIC_LINK
  1003.       _CRT_term(0UL);
  1004. #endif
  1005.       break;
  1006.  
  1007.     default:
  1008.       return 0UL;
  1009.  
  1010.   }
  1011.  
  1012.   /* A nonzero value must be returned to indicate success. */
  1013.   return 1UL;
  1014. }
  1015.  
  1016. #ifdef __cplusplus
  1017. } // extern "C"
  1018. #endif
  1019.  
  1020.  
  1021.