Subversion Repositories f9daq

Rev

Rev 5 | Blame | Compare with Previous | Last modification | View Log | RSS feed


// libxxusb.cpp : Defines the entry point for the DLL application.
//



#include <string.h>
#include <malloc.h>
#include "usb.h"
#include "libxxusb.h"
#include <time.h>
#include "stdio.h"



// 03/09/06 Release 3.00 changes
// 07/28/06     correction CAMAC write for F to be in range 16...23
// 10/09/06     correction CAMAC read for F to be in range <16 OR >23
// 10/16/06     CAMAC DGG corrected
// 12/28/07     Open corrected for bug when calling register after opening
/*
******** xxusb_longstack_execute ************************

  Executes stack array passed to the function and returns the data read from the VME bus

  Paramters:
    hdev: USB device handle returned from an open function
    DataBuffer: pointer to the dual use buffer
                when calling , DataBuffer contains (unsigned short) stack data, with first word serving
                as a placeholder
                upon successful return, DataBuffer contains (unsigned short) VME data
    lDataLen: The number of bytes to be fetched from VME bus - not less than the actual number
                expected, or the function will return -5 code. For stack consisting only of write operations,
                lDataLen may be set to 1.
    timeout: The time in ms that should be spent tryimg to write data.
   
  Returns:
    When Successful, the number of bytes read from xxusb.
    Upon failure, a negative number

  Note:
        The function must pass a pointer to an array of unsigned integer stack data, in which the first word
        is left empty to serve as a placeholder.
        The function is intended for executing Uint32_t stacks, up to 4 MBytes Uint32_t, both "write" and "read"
        oriented, such as using multi-block transfer operations.
        Structure upon call:
                DataBuffer(0) = 0(don't care place holder)
                DataBuffer(1) = (unsigned short)StackLength bits 0-15
                DataBuffer(2) = (unsigned short)StackLength bits 16-20
                DataBuffer(3 - StackLength +2)  (unsigned short) stack data
            StackLength represents the number of words following DataBuffer(1) word, thus the total number
                of words is StackLength+2
        Structure upon return:
                DataBuffer(0 - (ReturnValue/2-1)) - (unsigned short)array of returned data when ReturnValue>0
*/


int xxusb_longstack_execute(usb_dev_handle *hDev, void *DataBuffer, int lDataLen, int timeout)
{
    int ret;
    char *cbuf;
        unsigned short *usbuf;
    int bufsize;
         
        cbuf = (char *)DataBuffer;
        usbuf = (unsigned short *)DataBuffer;
    cbuf[0]=12;
    cbuf[1]=0;
        bufsize = 2*(usbuf[1]+0x10000*usbuf[2])+4;
    ret=usb_bulk_write(hDev, XXUSB_ENDPOINT_OUT, cbuf, bufsize, timeout);
    if (ret>0)
        ret=usb_bulk_read(hDev, XXUSB_ENDPOINT_IN, cbuf, lDataLen, timeout);
       
    return ret;
}

/*
******** xxusb_bulk_read ************************

  Reads the content of the usbfifo whenever "FIFO full" flag is set,
    otherwise times out.
   
  Paramters:
    hdev: USB device handle returned from an open function
    DataBuffer: pointer to an array to store data that is read from the VME bus;
                the array may be declared as byte, unsigned short, or unsigned Uint32_t
    lDatalen: The number of bytes to read from xxusb
    timeout: The time in ms that should be spent waiting for data.
   
  Returns:
    When Successful, the number of bytes read from xxusb.
    Upon failure, a negative number

  Note:
        Depending upon the actual need, the function may be used to return the data in a form
        of an array of bytes, unsigned short integers (16 bits), or unsigned Uint32_t integers (32 bits).
        The latter option of passing a pointer to an array of unsigned Uint32_t integers is meaningful when
        xxusb data buffering option is used (bit 7=128 of the global register) that requires data
        32-bit data alignment.

*/

int   xxusb_bulk_read(usb_dev_handle *hDev, void *DataBuffer, int lDataLen, int timeout)
{
int ret;
char *cbuf;
cbuf = (char *)DataBuffer;
    ret = usb_bulk_read(hDev, XXUSB_ENDPOINT_IN, cbuf, lDataLen, timeout);
    return ret;
}

/*
******** xxusb_bulk_write ************************

  Writes the content of an array of bytes, unsigned short integers, or unsigned Uint32_t integers
  to the USB port fifo; times out when the USB fifo is full (e.g., when xxusb is busy).
   
  Paramters:
    hdev: USB device handle returned from an open function
    DataBuffer: pointer to an array storing the data to be sent;
                the array may be declared as byte, unsigned short, or unsigned Uint32_t
    lDatalen: The number of bytes to to send to xxusb
    timeout: The time in ms that should be spent waiting for data.
   
  Returns:
    When Successful, the number of bytes passed to xxusb.
    Upon failure, a negative number

  Note:
        Depending upon the actual need, the function may be used to pass to xxusb the data in a form
        of an array of bytes, unsigned short integers (16 bits), or unsigned Uint32_t integers (32 bits).
*/

int   xxusb_bulk_write(usb_dev_handle *hDev, void *DataBuffer, int lDataLen, int timeout)
{
int ret;
char *cbuf;
cbuf = (char *)DataBuffer;
    ret = usb_bulk_write(hDev, XXUSB_ENDPOINT_OUT, cbuf, lDataLen, timeout);
    return ret;
}

/*
******** xxusb_usbfifo_read ************************

  Reads data stored in the xxusb fifo and packs them in an array of Uint32_t integers.
 
  Paramters:
    hdev: USB device handle returned from an open function
    DataBuffer: pointer to an array of Uint32_t to store data that is read
                the data occupy only the least significant 16 bits of the 32-bit data words
    lDatalen: The number of bytes to read from the xxusb
    timeout: The time in ms that should be spent waiting for data.
   
  Returns:
    When Successful, the number of bytes read from xxusb.
    Upon failure, a negative number
       
  Note:
        The function is not economical as it wastes half of the space required for storing
        the data received. Also, it is relatively slow, as it performs extensive data repacking.
        It is recommended to use xxusb_bulk_read with a pointer to an array of unsigned short
        integers.
*/

int   xxusb_usbfifo_read(usb_dev_handle *hDev, int *DataBuffer, int lDataLen, int timeout)
{
int ret;
char *cbuf;
unsigned short *usbuf;
int i;

cbuf = (char *)DataBuffer;
usbuf = (unsigned short *)DataBuffer;

    ret = usb_bulk_read(hDev, XXUSB_ENDPOINT_IN, cbuf, lDataLen, timeout);
    if (ret > 0)
        for (i=ret/2-1; i >= 0; i=i-1)
                {
                        usbuf[i*2]=usbuf[i];
                        usbuf[i*2+1]=0;
                }
    return ret;
}


//******************************************************//
//******************* GENERAL XX_USB *******************//
//******************************************************//
// The following are functions used for both VM_USB & CC_USB


/*
******** xxusb_register_write ************************

  Writes Data to the xxusb register selected by RedAddr.  For
    acceptable values for RegData and RegAddr see the manual
    the module you are using.
   
  Parameters:
    hdev: usb device handle returned from open device
    RegAddr: The internal address if the xxusb
    RegData: The Data to be written to the register
   
  Returns:
    Number of bytes sent to xxusb if successful
    0 if the register is write only
    Negative numbers if the call fails
*/

short   xxusb_register_write(usb_dev_handle *hDev, short RegAddr, Uint32_t RegData)
{
    Uint32_t RegD;
    char buf[8]={5,0,0,0,0,0,0,0};
    int ret;
    int lDataLen;
    int timeout;
    if ((RegAddr==0) || (RegAddr==12) || (RegAddr==15))
        return 0;
    buf[2]=(char)(RegAddr & 15);
    buf[4]=(char)(RegData & 255);

    RegD = RegData >> 8;
    buf[5]=(char)(RegD & 255);
        RegD = RegD >>8;
        if (RegAddr==8)
        {
                buf[6]=(char)(RegD & 255);
                lDataLen=8;
        }
        else
                lDataLen=6;
        timeout=10;
        ret=xxusb_bulk_write(hDev, buf, lDataLen, timeout);
        return ret;
}

/*
******** xxusb_stack_write ************************

  Writes a stack of VME/CAMAC calls to the VM_USB/CC_USB
    to be executed upon trigger.
   
  Parameters:
    hdev: usb device handle returned from an open function
    StackAddr: internal register to which the stack should be written
    lpStackData: Pointer to an array holding the stack
 
  Returns:
    The number of Bytes written to the xxusb when successful
    A negative number upon failure
*/

short   xxusb_stack_write(usb_dev_handle *hDev, short StackAddr, Uint32_t *intbuf)
{
  int timeout;
    short ret;
    short lDataLen;
    char buf[2000];
    short i;
    int bufsize;
     
    buf[0]=(char)((StackAddr & 51) + 4);
    buf[1]=0;
    lDataLen=(short)(intbuf[0] & 0xFFF);
    buf[2]=(char)(lDataLen & 255);
    lDataLen = lDataLen >> 8;
    buf[3] = (char)(lDataLen & 255);
    bufsize=intbuf[0]*2+4;
    if (intbuf[0]==0)
      return 0;
    for (i=1; i <= intbuf[0]; i++)
      {
        buf[2+2*i] = (char)(intbuf[i] & 255);
        buf[3+2*i] = (char)((intbuf[i] >>8) & 255);
      }
    timeout=50;
    ret=usb_bulk_write(hDev, XXUSB_ENDPOINT_OUT, buf, bufsize, timeout);
    return ret;
}

/*
******** xxusb_stack_execute **********************

  Writes, executes and returns the value of a DAQ stack.
 
  Parameters:
    hdev: USB device handle returned from an open function
    intbuf: Pointer to an array holding the values stack.  Upon return
            Pointer value is the Data returned from the stack.
 
  Returns:
    When successful, the number of Bytes read from xxusb
    Upon Failure, a negative number.
*/

short   xxusb_stack_execute(usb_dev_handle *hDev, Uint32_t *intbuf)
{
  int timeout;
    short ret;
    short lDataLen;
    char buf[26700];
    short i;
    int bufsize;
    int ii = 0;
         
    buf[0]=12;
    buf[1]=0;
    lDataLen=(short)(intbuf[0] & 0xFFF);
    buf[2]=(char)(lDataLen & 255);
    lDataLen = lDataLen >> 8;
    buf[3] = (char)(lDataLen & 15);
    bufsize=intbuf[0]*2+4;
    if (intbuf[0]==0)
      return 0;
    for (i=1; i <= intbuf[0]; i++)
      {
        buf[2+2*i] = (char)(intbuf[i] & 255);
        buf[3+2*i] = (char)((intbuf[i] >>8) & 255);
      }
    timeout=2000;
    ret=usb_bulk_write(hDev, XXUSB_ENDPOINT_OUT, buf, bufsize, timeout);
    if (ret>0)
        {
        lDataLen=26700;
        timeout=6000;
        ret=usb_bulk_read(hDev, XXUSB_ENDPOINT_IN, buf, lDataLen, timeout);
        if (ret>0)
        for (i=0; i < ret; i=i+2)
          intbuf[ii++]=(UCHAR)(buf[i]) +(UCHAR)( buf[i+1])*256;
        }
    return ret;
}

/*
******** xxusb_stack_read ************************

  Reads the current DAQ stack stored by xxusb
 
  Parameters:
    hdev: USB device handle returned by an open function
    StackAddr: Indicates which stack to read, primary or secondary
    intbuf: Pointer to a array where the stack can be stored

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   xxusb_stack_read(usb_dev_handle *hDev, short StackAddr, Uint32_t *intbuf)
{
  int timeout;
    short ret;
    short lDataLen;
    short bufsize;
    char buf[1600];
    int i;

    buf[0]=(char)(StackAddr & 51);
    buf[1]=0;
    lDataLen = 2;
    timeout=100;
    ret=usb_bulk_write(hDev, XXUSB_ENDPOINT_OUT, buf, lDataLen, timeout);
    if (ret < 0)
        return ret;
    else
      bufsize=1600;
    int ii=0;
      {
        ret=usb_bulk_read(hDev, XXUSB_ENDPOINT_IN, buf, bufsize, timeout);
        if (ret>0)
        for (i=0; i < ret; i=i+2)
          intbuf[ii++]=(UCHAR)(buf[i]) + (UCHAR)(buf[i+1])*256;
        return ret;
         
      }    
}

/*
******** xxusb_register_read ************************

  Reads the current contents of an internal xxusb register
 
  Parameters:
    hdev: USB device handle returned from an open function
    RegAddr: The internal address of the register from which to read
    RegData: Pointer to a Uint32_t to hold the data.
   
  Returns:
    When Successful, the number of bytes read from xxusb.
    Upon failure, a negative number
*/

short   xxusb_register_read(usb_dev_handle *hDev, short RegAddr, Uint32_t *RegData)
{
//Uint32_t RegD;
int timeout;
        char buf[4]={1,0,0,0};
        int ret;
        int lDataLen;

        buf[2]=(char)(RegAddr & 15);   
        timeout=10;
        lDataLen=4;
        ret=xxusb_bulk_write(hDev, buf, lDataLen, timeout);
        if (ret < 0)
                return (short)ret;
        else
        {
            lDataLen=8;
            timeout=100;
            ret=xxusb_bulk_read(hDev, buf, lDataLen, timeout);
            if (ret<0)
              return (short)ret;
            else
              {
                *RegData=(UCHAR)(buf[0])+256*(UCHAR)(buf[1]);
                if (ret==4)
                 *RegData=*RegData+0x10000*(UCHAR)(buf[2]);
                return (short)ret;
                }
        }
}

/*
******** xxusb_reset_toggle ************************

  Toggles the reset state of the FPGA while the xxusb in programming mode
 
  Parameters
    hdev: US B device handle returned from an open function
   
  Returns:
    Upon failure, a negative number  
*/

short   xxusb_reset_toggle(usb_dev_handle *hDev)
{
  short ret;
  char buf[2] = {(char)255,(char)255};
  int lDataLen=2;
  int timeout=1000;
  ret = usb_bulk_write(hDev, XXUSB_ENDPOINT_OUT, buf,lDataLen, timeout);
  return (short)ret;
}

/*
******** xxusb_devices_find ************************

  Determines the number and parameters of all xxusb devices attched to
    the computer.
   
  Parameters:
    xxdev: pointer to an array on which the device parameters are stored

  Returns:
    Upon success, returns the number of devices found
    Upon Failure returns a negative number
*/

short   xxusb_devices_find(xxusb_device_type *xxdev)
{
  short DevFound = 0;
  usb_dev_handle *udev;
  struct usb_bus *bus;
  struct usb_device *dev;  
struct usb_bus *usb_busses;
  char string[256];
  short ret;
   usb_init();
   usb_find_busses();
   usb_busses=usb_get_busses();
  usb_find_devices();
   for (bus=usb_busses; bus; bus = bus->next)
   {
       for (dev = bus->devices; dev; dev= dev->next)
       {
           if (dev->descriptor.idVendor==XXUSB_WIENER_VENDOR_ID)
           {
               udev = usb_open(dev);
               if (udev)
               {
                   ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string, sizeof(string));
                   if (ret >0 )  
                     {
                       xxdev[DevFound].usbdev=dev;
                       strcpy(xxdev[DevFound].SerialString, string);
                       DevFound++;
                     }
                   usb_close(udev);
                }
                   else return -1;
           }
       }
    }
  return DevFound;
}

/*
******** xxusb_device_close ************************

  Closes an xxusb device
 
  Parameters:
    hdev: USB device handle returned from an open function

  Returns:  1
*/

short   xxusb_device_close(usb_dev_handle *hDev)
{
    short ret;
    ret=usb_release_interface(hDev,0);
    usb_close(hDev);
    return 1;
}

/*
******** xxusb_device_open ************************

  Opens an xxusb device found by xxusb_device_find
 
  Parameters:
    dev: a usb device
   
  Returns:
    A USB device handle
*/

usb_dev_handle*   xxusb_device_open(struct usb_device *dev)
{
    short ret;
    Uint32_t val;
    int count =0;
    usb_dev_handle *udev;
    udev = usb_open(dev);
    ret = usb_set_configuration(udev,1);
    ret = usb_claim_interface(udev,0);
// RESET USB (added 10/16/06 Andreas Ruben)
        ret=xxusb_register_write(udev, 10, 0x04);
// Loop to find known state (added 12/28/07 TH / AR)
        ret =-1;
        while ((ret <0) && (count <10))
        {
            xxusb_register_read(udev, 0, &val);
            count++;
        }

    return udev;
}

/*
******** xxusb_flash_program ************************

    --Untested and therefore uncommented--
*/

short   xxusb_flash_program(usb_dev_handle *hDev, char *config, short nsect)
{
        int i=0;
        int k=0;
        short ret=0;
        time_t t1,t2;

        char *pconfig;
        char *pbuf;
        pconfig=config;
        char buf[518] ={(char)0xAA,(char)0xAA,(char)0x55,(char)0x55,(char)0xA0,(char)0xA0};
        while (*pconfig++ != -1);
        for (i=0; i<nsect; i++)
        {
                pbuf=buf+6;
                for (k=0; k<256; k++)
                {
                        *(pbuf++)=*(pconfig);
                        *(pbuf++)=*(pconfig++);
                }
                ret = usb_bulk_write(hDev, XXUSB_ENDPOINT_OUT, buf, 518, 2000);
                if (ret<0)
                        return ret;
                t1=clock()+(time_t)(0.03*CLOCKS_PER_SEC);
                while (t1>clock());
                t2=clock();
        }
        return ret;
}

/*
******** xxusb_flashblock_program ************************

      --Untested and therefore uncommented--  
*/

short   xxusb_flashblock_program(usb_dev_handle *hDev, UCHAR *config)
{
        int k=0;
        short ret=0;

        UCHAR *pconfig;
        char *pbuf;
        pconfig=config;
        char buf[518] ={(char)0xAA,(char)0xAA,(char)0x55,(char)0x55,(char)0xA0,(char)0xA0};
        pbuf=buf+6;
        for (k=0; k<256; k++)
        {
                *(pbuf++)=(UCHAR)(*(pconfig));
                *(pbuf++)=(UCHAR)(*(pconfig++));
        }
        ret = usb_bulk_write(hDev, XXUSB_ENDPOINT_OUT, buf, 518, 2000);
        return ret;
}

/*
******** xxusb_serial_open ************************

  Opens a xxusb device whose serial number is given
 
  Parameters:
    SerialString: a char string that gives the serial number of
                  the device you wish to open.  It takes the form:
                  VM0009 - for a vm_usb with serial number 9 or
                  CC0009 - for a cc_usb with serial number 9

  Returns:
    A USB device handle
*/

usb_dev_handle*   xxusb_serial_open(char *SerialString)
{
  short DevFound = 0;
  usb_dev_handle *udev = NULL;
  struct usb_bus *bus;
  struct usb_device *dev;  
struct usb_bus *usb_busses;
char string[20];
  short ret;
  //usb_set_debug(4);
  usb_init();
   usb_find_busses();
  usb_busses=usb_get_busses();
   usb_find_devices();
   for (bus=usb_busses; bus; bus = bus->next)
   {
       for (dev = bus->devices; dev; dev= dev->next)
       {
           if (dev->descriptor.idVendor==XXUSB_WIENER_VENDOR_ID)
           {
               printf("id %04x\n",dev->descriptor.idVendor);
               udev = xxusb_device_open(dev);
               if (udev)
               {
                   ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string, sizeof(string));
                                        printf("iSerial %04x string %s\n",dev->descriptor.iSerialNumber,string);
                                        if (ret >0 )  
                                                {
                                                        printf(" Device with %s\n",SerialString);

                                                        if (strcmp(string,SerialString)==0){
                                                                printf(" Device with %s found\n",SerialString);
                                                                return udev;
                                                        }
                                                } else {
                                                        printf(" Device returned  %d\n",ret);
                                                }
                                                usb_close(udev);
                                }
           }
       }
    }
   udev = NULL;
   return udev;
}


//******************************************************//
//****************** EZ_VME Functions ******************//
//******************************************************//
// The following are functions used to perform simple
// VME Functions with the VM_USB

/*
******** VME_write_32 ************************

  Writes a 32 bit data word to the VME bus
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Address_Modifier: VME address modifier for the VME call
    VME_Address: Address to write the data to
    Data: 32 bit data word to be written to VME_Address

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   VME_write_32(usb_dev_handle *hdev, short Address_Modifier, Uint32_t VME_Address, Uint32_t Data)
{
    Uint32_t intbuf[1000];
    short ret;
    intbuf[0]=7;
    intbuf[1]=0;
    intbuf[2]=Address_Modifier;
    intbuf[3]=0;
    intbuf[4]=(VME_Address & 0xffff);
    intbuf[5]=((VME_Address >>16) & 0xffff);
    intbuf[6]=(Data & 0xffff);
    intbuf[7]=((Data >> 16) & 0xffff);
    ret = xxusb_stack_execute(hdev, intbuf);
    return ret;
}

/*
******** VME_read_32 ************************


  Reads a 32 bit data word from a VME address
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Address_Modifier: VME address modifier for the VME call
    VME_Address: Address to read the data from
    Data: 32 bit data word read from VME_Address

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   VME_read_32(usb_dev_handle *hdev, short Address_Modifier, Uint32_t VME_Address, Uint32_t *Data)
{
    Uint32_t intbuf[1000];
    short ret;
    intbuf[0]=5;
    intbuf[1]=0;
    intbuf[2]=Address_Modifier +0x100;
    intbuf[3]=0;
    intbuf[4]=(VME_Address & 0xffff);
    intbuf[5]=((VME_Address >>16) & 0xffff);
    ret = xxusb_stack_execute(hdev, intbuf);
    *Data=intbuf[0] + (intbuf[1] * 0x10000);
    return ret;
}

/*
******** VME_write_16 ************************

  Writes a 16 bit data word to the VME bus
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Address_Modifier: VME address modifier for the VME call
    VME_Address: Address to write the data to
    Data: word to be written to VME_Address

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   VME_write_16(usb_dev_handle *hdev, short Address_Modifier, Uint32_t VME_Address, Uint32_t Data)
{
    Uint32_t intbuf[1000];
    short ret;
    intbuf[0]=7;
    intbuf[1]=0;
    intbuf[2]=Address_Modifier;
    intbuf[3]=0;
    intbuf[4]=(VME_Address & 0xffff)+ 0x01;
    intbuf[5]=((VME_Address >>16) & 0xffff);
    intbuf[6]=(Data & 0xffff);
    intbuf[7]=0;
    ret = xxusb_stack_execute(hdev, intbuf);
    return ret;
}

/*
******** VME_read_16 ************************

  Reads a 16 bit data word from a VME address
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Address_Modifier: VME address modifier for the VME call
    VME_Address: Address to read the data from
    Data: word read from VME_Address

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   VME_read_16(usb_dev_handle *hdev,short Address_Modifier, Uint32_t VME_Address, Uint32_t *Data)
{
    Uint32_t intbuf[1000];
    short ret;
    intbuf[0]=5;
    intbuf[1]=0;
    intbuf[2]=Address_Modifier +0x100;
    intbuf[3]=0;
    intbuf[4]=(VME_Address & 0xffff)+ 0x01;
    intbuf[5]=((VME_Address >>16) & 0xffff);
    ret = xxusb_stack_execute(hdev, intbuf);
    *Data=intbuf[0];
    return ret;
}

/*
******** VME_BLT_read_32 ************************

  Performs block transfer of 32 bit words from a VME address
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Address_Modifier: VME address modifier for the VME call
    count: number of data words to read
    VME_Address: Address to read the data from
    Data: pointer to an array to hold the data words

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   VME_BLT_read_32(usb_dev_handle *hdev, short Adress_Modifier, int count, Uint32_t VME_Address, Uint32_t Data[])
{
    Uint32_t intbuf[1000];
    short ret;
    int i=0;
    if (count > 255) return -1;
    intbuf[0]=5;
    intbuf[1]=0;
    intbuf[2]=Adress_Modifier +0x100;
    intbuf[3]=(count << 8);
    intbuf[4]=(VME_Address & 0xffff);
    intbuf[5]=((VME_Address >>16) & 0xffff);
    ret = xxusb_stack_execute(hdev, intbuf);
    int j=0;
    for (i=0;i<(2*count);i=i+2)
    {
        Data[j]=intbuf[i] + (intbuf[i+1] * 0x10000);
        j++;
    }
    return ret;
}

//******************************************************//
//****************** VM_USB Registers ******************//
//******************************************************//
// The following are functions used to set the registers
// in the VM_USB

/*
******** VME_register_write ************************

  Writes to the vmusb registers that are accessible through
  VME style calls
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    VME_Address: The VME Address of the internal register
    Data: Data to be written to VME_Address

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number  
*/

short   VME_register_write(usb_dev_handle *hdev, Uint32_t VME_Address, Uint32_t Data)
{
    Uint32_t intbuf[1000];
    short ret;

    intbuf[0]=7;
    intbuf[1]=0;
    intbuf[2]=0x1000;
    intbuf[3]=0;
    intbuf[4]=(VME_Address & 0xffff);
    intbuf[5]=((VME_Address >>16) & 0xffff);
    intbuf[6]=(Data & 0xffff);
    intbuf[7]=((Data >> 16) & 0xffff);
    ret = xxusb_stack_execute(hdev, intbuf);
    return ret;
}

/*
******** VME_register_read ************************

  Reads from the vmusb registers that are accessible trough VME style calls
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    VME_Address: The VME Address of the internal register
    Data: Data read from VME_Address

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   VME_register_read(usb_dev_handle *hdev, Uint32_t VME_Address, Uint32_t *Data)
{
    Uint32_t intbuf[1000];
    short ret;

    intbuf[0]=5;
    intbuf[1]=0;
    intbuf[2]=0x1100;
    intbuf[3]=0;
    intbuf[4]=(VME_Address & 0xffff);
    intbuf[5]=((VME_Address >>16) & 0xffff);
    ret = xxusb_stack_execute(hdev, intbuf);
    *Data=intbuf[0] + (intbuf[1] * 0x10000);
    return ret;
}

/*
******** VME_LED_settings ************************

  Sets the vmusb LED's
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    LED: The number which corresponds to an LED values are:
            0 - for Top YELLOW LED
                        1 - for RED LED
            2 - for GREEN LED
            3 - for Bottom YELLOW LED
    code: The LED aource selector code, valid values for each LED
          are listed in the manual
    invert: to invert the LED lighting
    latch: sets LED latch bit

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   VME_LED_settings(usb_dev_handle *hdev, int LED, int code, int invert, int latch)
{
    short ret;
//    Uint32_t internal;
    Uint32_t Data;
   
    if( (LED <0) ||(LED > 3) || (code < 0) || (code > 7))  return -1;
     
    VME_register_read(hdev,0xc,&Data);  
    if(LED == 0)  
    {
        Data = Data & 0xFFFFFF00;
        Data = Data | code;
        if (invert == 1 && latch == 1)   Data = Data | 0x18;
        if (invert == 1 && latch == 0)   Data = Data | 0x08;
        if (invert == 0 && latch == 1)   Data = Data | 0x10;
    }
    if(LED == 1)  
    {
        Data = Data & 0xFFFF00FF;
        Data = Data | (code * 0x0100);
        if (invert == 1 && latch == 1)  Data = Data | 0x1800;
        if (invert == 1 && latch == 0)  Data = Data | 0x0800;
        if (invert == 0 && latch == 1)  Data = Data | 0x1000;
    }  
    if(LED == 2)
    {
        Data = Data & 0xFF00FFFF;
        Data = Data | (code * 0x10000);
        if (invert == 1 && latch == 1) Data = Data | 0x180000;
        if (invert == 1 && latch == 0) Data = Data | 0x080000;
        if (invert == 0 && latch == 1) Data = Data | 0x100000;
    }
    if(LED == 3)
    {
        Data = Data & 0x00FFFFFF;
        Data = Data | (code * 0x10000);
        if (invert == 1 && latch == 1)  Data = Data | 0x18000000;
        if (invert == 1 && latch == 0)  Data = Data | 0x08000000;
        if (invert == 0 && latch == 1)  Data = Data | 0x10000000;
    }
    ret = VME_register_write(hdev, 0xc, Data);
    return ret;
}

/*
******** VME_DGG ************************

  Sets the parameters for Gate & Delay channel A of vmusb
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    channel: Which DGG channel to use Valid Values are:
              0 - For DGG A
                          1 - For DGG B
    trigger:  Determines what triggers the start of the DGG Valid values are:
              0 - Channel disabled
              1 - NIM input 1
              2 - NIM input 2
              3 - Event Trigger
              4 - End of Event
              5 - USB Trigger
              6 - Pulser
    output: Determines which NIM output to use for the channel, Vaild values are:
              0 - for NIM O1
              1 - for NIM O2
    delay: 32 bit word consisting of
                        lower 16 bits: Delay_fine in steps of 12.5ns between trigger and start of gate
                        upper 16 bits: Delay_coarse in steps of 81.7us between trigger and start of gate
    gate: the time the gate should  stay open in steps of 12.5ns
    invert: is 1 if you wish to invert the DGG channel output
    latch: is 1 if you wish to run the DGG channel latched

  Returns:
    Returns 1 when successful
    Upon failure, a negative number
*/

short   VME_DGG(usb_dev_handle *hdev, unsigned short channel, unsigned short trigger, unsigned short output,
                                                Uint32_t delay, unsigned short gate, unsigned short invert, unsigned short latch)
{
    Uint32_t Data, DGData, Delay_ext;
    Uint32_t internal;
    short ret;


    ret = VME_register_read(hdev, 0x10,  &Data);
    // check and correct values
    if(ret<=0) return -1;

    if(channel >1) channel =1;
    if(invert >1) invert =1;
    if(latch >1) latch =1;
        if(output >1) output =1;
        if(trigger >6) trigger =0;

    // define Delay and Gate data
    DGData = gate * 0x10000;
    DGData += (unsigned short) delay;

        // Set channel, output, invert, latch
        if (output == 0)
    {
                Data = Data & 0xFFFFFF00;
                Data += 0x04 + channel +0x08*invert + 0x10*latch;
    }
        if (output == 1)
    {
                Data = Data & 0xFFFF00FF;
                Data += (0x04 + channel +0x08*invert + 0x10*latch)*0x100;
    }

    // Set trigger, delay, gate

    if(channel ==0) // CHANNEL DGG_A
    {
            internal = (trigger * 0x1000000) ;
            Data= Data & 0xF0FFFFFF;
            Data += internal;
            ret = VME_register_write(hdev,0x10,Data);
                if(ret<=0) return -1;
                ret=VME_register_write(hdev,0x14,DGData);
                if(ret<=0) return -1;
    // Set coarse delay in DGG_Extended register
            ret = VME_register_read(hdev,0x38,&Data);
                Delay_ext= (Data & 0xffff0000);
                Delay_ext+= ((delay/0x10000) & 0xffff);
            ret = VME_register_write(hdev,0x38,Delay_ext);
        }
        if( channel ==1)  // CHANNEL DGG_B
        {
                internal = (trigger * 0x10000000) ;
                Data= Data & 0x0FFFFFFF;
                Data += internal;
            ret = VME_register_write(hdev,0x10,Data);
                if(ret<=0) return -1;
                ret=VME_register_write(hdev,0x18,DGData);
                if(ret<=0) return -1;
    // Set coarse delay in DGG_Extended register
            ret = VME_register_read(hdev,0x38,&Data);
                Delay_ext= (Data & 0x0000ffff);
                Delay_ext+= (delay & 0xffff0000);
            ret = VME_register_write(hdev,0x38,Delay_ext);
    }
        return 1;
       
}

/*
******** VME_Output_settings ************************

  Sets the vmusb NIM output register
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Channel: The number which corresponds to an output:
            1 - for Output 1
            2 - for Output 2
    code: The Output selector code, valid values
          are listed in the manual
    invert: to invert the output
    latch: sets latch bit

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   VME_Output_settings(usb_dev_handle *hdev, int Channel, int code, int invert, int latch)
{

    short ret;
//    Uint32_t internal;
    Uint32_t Data;
   
    if( (Channel <1) ||(Channel > 2) || (code < 0) || (code > 7)) return -1;    
    VME_register_read(hdev,0x10,&Data);  
    if(Channel == 1)  
    {
        Data = Data & 0xFFFF00;
        Data = Data | code;
        if (invert == 1 && latch == 1)   Data = Data | 0x18;
        if (invert == 1 && latch == 0)   Data = Data | 0x08;
        if (invert == 0 && latch == 1)   Data = Data | 0x10;
    }
    if(Channel == 2)  
    {
        Data = Data & 0xFF00FF;
        Data = Data | (code * 0x0100);
        if (invert == 1 && latch == 1)   Data = Data | 0x1800;
        if (invert == 1 && latch == 0)   Data = Data | 0x0800;
        if (invert == 0 && latch == 1)   Data = Data | 0x1000;
    }  
    ret = VME_register_write(hdev, 0x10, Data);
    return ret;
}


//******************************************************//
//****************** CC_USB Registers ******************//
//******************************************************//
// The following are functions used to set the registers
// in the CAMAC_USB

/*
******** CAMAC_register_write *****************

  Performs a CAMAC write to CC_USB register
 
  Parameters:
    hdev: USB device handle returned from an open function
    A: CAMAC Subaddress
    F: CAMAC Function
    Data: data to be written
   
  Returns:
    Number of bytes written to xxusb when successful
    Upon failure, a negative number
*/

short   CAMAC_register_write(usb_dev_handle *hdev, int A, Uint32_t Data)
{
    int F = 16;
    int N = 25;
    Uint32_t intbuf[4];  
    int ret;

    intbuf[0]=1;
    intbuf[1]=(Uint32_t)(F+A*32+N*512 + 0x4000);       
        intbuf[0]=3;
        intbuf[2]=(Data & 0xffff);
        intbuf[3]=((Data >>16) & 0xffff);
        ret = xxusb_stack_execute(hdev, intbuf);

    return ret;
}

/*
******** CAMAC_register_read ************************

  Performs a CAMAC read from CC_USB register
 
  Parameters:
    hdev: USB device handle returned from an open function
    N: CAMAC Station Number
    A: CAMAC Subaddress
    F: CAMAC Function
    Q: The Q response from the CAMAC dataway
    X: The comment accepted response from CAMAC dataway
   
  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   CAMAC_register_read(usb_dev_handle *hdev, int A, Uint32_t *Data)
{
    int F = 0;
    int N = 25;
    Uint32_t intbuf[4];  
    int ret;

    intbuf[0]=1;
    intbuf[1]=(Uint32_t)(F+A*32+N*512 + 0x4000);
    ret = xxusb_stack_execute(hdev, intbuf);
    *Data=intbuf[0] + (intbuf[1] * 0x10000);

    return ret;
}

/*
******** CAMAC_DGG ************************

  Sets the parameters for Gate & Delay channel A of CC_USB
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    channel: Which DGG channel to use Valid Values are:
              0 - For DGG A
                                                        1 - For DGG B
    trigger:  Determines what triggers the start of the DGG Valid values are:
              0 - Channel disabled
              1 - NIM input 1
              2 - NIM input 2
              3 - NIM input 2
              4 - Event Trigger
                                                  5 - End of Event
                                      6 - USB Trigger
                                                        7 - Pulser
    output: Determines which NIM output to use for the channel, Vaild values are:
              1 - for NIM O1
              2 - for NIM O2
              3 - for NIM O3
    delay: Delay in steps of 12.5ns between trigger and start of gate
    gate: the time the gate should  stay open in steps of 12.5ns
    invert: is 1 if you wish to invert the DGG channel output
    latch: is 1 if you wish to run the DGG channel latched

  Returns:
    Returns 1 when successful
    Upon failure, a negative number
*/

short   CAMAC_DGG(usb_dev_handle *hdev, short channel, short trigger, short output,
                                    int delay, int gate, short invert, short latch)



{
//    short channel_ID;
    Uint32_t Data;
    Uint32_t internal;
    short ret;
                Uint32_t Delay_ext;

    ret = CAMAC_register_read(hdev,5,&Data);
    //Set trigger
    if((output < 1 ) || (output >3) || (channel < 0 ) || (channel > 1))
        return -1;
    if(output ==1)
    {
      if(channel ==0)
      {
          internal = 0x03;      
      } else {
          internal = 0x04;
      }
    }
    if(output ==2)
    {
        if(channel ==0)
        {
          internal = 0x04;      
        } else {
          internal = 0x05;
        }
    }
    if(output ==3)
    {
        if(channel ==0)
        {
          internal = 0x05;      
        } else {
          internal = 0x06;
        }
    }


// Set invert bit
    if(invert ==1)
      internal = internal | 0x10;
    else
      internal = internal & 0x0F;
    // Set Latch Bit
    if(latch==1)
        internal = internal | 0x20;
    else
        internal = internal & 0x1F;
// Add new data to old
    if(output == 1)
    {
        Data = Data & 0xFFFF00;
        Data = Data | internal;
    }
    if(output == 2)
    {
        Data = Data & 0xFF00FF;
        Data = Data |(internal * 0x100);
    }
    if(output == 3)
    {
        Data = Data & 0x00FFFF;
        Data = Data | (internal * 0x10000) ;
    }
    CAMAC_register_write(hdev, 5, Data);
    ret = CAMAC_register_read(hdev,6,&Data);  
//Set Trigger
    if(trigger <0 || trigger > 7)
        return -1;
    if(channel ==0)
    {
        Data = Data & 0xFF00FFFF;
        internal = trigger * 0x10000;
        Data = Data | internal;
    } else {
        Data = Data & 0x00FFFFFF;
        internal = trigger * 0x1000000;
        Data = Data | internal;
    }
    ret = CAMAC_register_write(hdev, 6, Data);
    if(channel == 0)
    {
// Write Delay and Gate info
                ret = CAMAC_register_read(hdev,13,&Data);  
                Delay_ext= (Data & 0xffff0000);
                Delay_ext+= ((delay/0x10000) & 0xffff);
                internal = gate * 0x10000;
                Data = internal + (delay & 0xffff);
                ret=CAMAC_register_write(hdev,7,Data);
// Set coarse delay in DGG_Extended register
                ret=CAMAC_register_write(hdev,13,Delay_ext);
    }
        else
        {
                ret=CAMAC_register_write(hdev,8,Data);
                ret = CAMAC_register_read(hdev,13,&Data);  
                Delay_ext= (Data & 0x0000ffff);
                Delay_ext+= (delay & 0xffff0000);
                internal = gate * 0x10000;
                Data = internal + (delay & 0xffff);
// Set coarse delay in DGG_Extended register
                ret=CAMAC_register_write(hdev,13,Delay_ext);
    }
    return 1;
}

/*
******** CAMAC_LED_settings ************************

  Writes a data word to the vmusb LED register
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    LED: The number which corresponds to an LED values are:
            1 - for RED LED
            2 - for GREEN LED
            3 - for Yellow LED
    code: The LED aource selector code, valid values for each LED
          are listed in the manual
    invert: to invert the LED lighting
    latch: sets LED latch bit

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   CAMAC_LED_settings(usb_dev_handle *hdev, int LED, int code, int invert, int latch)
{

    short ret;
//    Uint32_t internal;
    Uint32_t Data;
   
    if( (LED <1) ||(LED > 3) || (code < 0) || (code > 7))
        return -1;
       
    CAMAC_register_read(hdev,4,&Data);  
 
    if(LED == 1)  
    {
        Data = Data & 0xFFFF00;
        Data = Data | code;
        if (invert == 1 && latch == 1)  
            Data = Data | 0x30;
        if (invert == 1 && latch == 0)
            Data = Data | 0x10;
        if (invert == 0 && latch == 1)
            Data = Data | 0x20;
    }
    if(LED == 2)  
    {
        Data = Data & 0xFF00FF;
        Data = Data | (code * 0x0100);
        if (invert == 1 && latch == 1)  
            Data = Data | 0x3000;
        if (invert == 1 && latch == 0)
            Data = Data | 0x1000;
        if (invert == 0 && latch == 1)
            Data = Data | 0x2000;
    }      
    if(LED == 3)
    {
        Data = Data & 0x00FFFF;
        Data = Data | (code * 0x10000);
        if (invert == 1 && latch == 1)  
            Data = Data | 0x300000;
        if (invert == 1 && latch == 0)
            Data = Data | 0x100000;
        if (invert == 0 && latch == 1)
            Data = Data | 0x200000;
    }  
    ret = CAMAC_register_write(hdev, 4, Data);
    return ret;
}

/*
******** CAMAC_Output_settings ************************

  Writes a data word to the vmusb LED register
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Channel: The number which corresponds to an output:
            1 - for Output 1
            2 - for Output 2
            3 - for Output 3
    code: The Output selector code, valid values
          are listed in the manual
    invert: to invert the output
    latch: sets latch bit

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   CAMAC_Output_settings(usb_dev_handle *hdev, int Channel, int code, int invert, int latch)
{
    short ret;
//    Uint32_t internal;
    Uint32_t Data;
   
    if( (Channel <1) ||(Channel > 3) || (code < 0) || (code > 7))
        return -1;
       
    CAMAC_register_read(hdev,5,&Data);  
 
    if(Channel == 1)  
    {
        Data = Data & 0xFFFF00;
        Data = Data | code;
        if (invert == 1 && latch == 1)  
            Data = Data | 0x30;
        if (invert == 1 && latch == 0)
            Data = Data | 0x10;
        if (invert == 0 && latch == 1)
            Data = Data | 0x20;
    }    
    if(Channel == 2)  
    {
        Data = Data & 0xFF00FF;
        Data = Data | (code * 0x0100);
        if (invert == 1 && latch == 1)  
            Data = Data | 0x3000;
        if (invert == 1 && latch == 0)
            Data = Data | 0x1000;
        if (invert == 0 && latch == 1)
            Data = Data | 0x2000;
    }  
    if(Channel == 3)
    {
        Data = Data & 0x00FFFF;
        Data = Data | (code * 0x10000);
        if (invert == 1 && latch == 1)  
            Data = Data | 0x300000;
        if (invert == 1 && latch == 0)
            Data = Data | 0x100000;
        if (invert == 0 && latch == 1)
            Data = Data | 0x200000;
    }
    ret = CAMAC_register_write(hdev, 5, Data);
    return ret;
}

/*
******** CAMAC_write_LAM_mask ************************

  Writes the data word to the LAM mask register
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Data: LAM mask to write

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   CAMAC_write_LAM_mask(usb_dev_handle *hdev, Uint32_t Data)
{
    short ret;
    ret = CAMAC_register_write(hdev, 9, Data);

    return ret;
}

/*
******** CAMAC_read_LAM_mask ************************

  Writes the data word to the LAM mask register
 
  Parameters:
    hdev: USB devcie handle returned from an open function
    Data: LAM mask to write

  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number
*/

short   CAMAC_read_LAM_mask(usb_dev_handle *hdev, Uint32_t *Data)
{
    Uint32_t intbuf[4];  
    int ret;
    int N = 25;
    int F = 0;
    int A = 9;

    // CAMAC direct read function
    intbuf[0]=1;
    intbuf[1]=(Uint32_t)(F+A*32+N*512 + 0x4000);
    ret = xxusb_stack_execute(hdev, intbuf);
    *Data=intbuf[0] + (intbuf[1] & 255) * 0x10000;    
        return ret;
}


//******************************************************//
//**************** EZ_CAMAC Functions ******************//
//******************************************************//
// The following are functions used to perform simple
// CAMAC Functions with the CC_USB


/*
******** CAMAC_write ************************

  Performs a CAMAC write using NAF comments
 
  Parameters:
    hdev: USB device handle returned from an open function
    N: CAMAC Station Number
    A: CAMAC Subaddress
    F: CAMAC Function (16...23)
    Q: The Q response from the CAMAC dataway
    X: The comment accepted response from CAMAC dataway
   
  Returns:
    Number of bytes written to xxusb when successful
    Upon failure, a negative number    
*/

short   CAMAC_write(usb_dev_handle *hdev, int N, int A, int F, Uint32_t Data, int *Q, int *X)
{
    Uint32_t intbuf[4];  
    int ret;
// CAMAC direct write function
    intbuf[0]=1;
    intbuf[1]=(Uint32_t)(F+A*32+N*512 + 0x4000);
    if ((F > 15) && (F < 24))
    {  
        intbuf[0]=3;
        intbuf[2]=(Data & 0xffff);
        intbuf[3]=((Data >>16) & 255);
        ret = xxusb_stack_execute(hdev, intbuf);
        *Q = (intbuf[0] & 1);
        *X = ((intbuf[0] >> 1) & 1);
    }  
    return ret;
}

/*
******** CAMAC_read ************************

  Performs a CAMAC read using NAF comments
 
  Parameters:
    hdev: USB device handle returned from an open function
    N: CAMAC Station Number
    A: CAMAC Subaddress
    F: CAMAC Function (F<16 or F>23)
    Q: The Q response from the CAMAC dataway
    X: The comment accepted response from CAMAC dataway
   
  Returns:
    Number of bytes read from xxusb when successful
    Upon failure, a negative number  
*/

short   CAMAC_read(usb_dev_handle *hdev, int N, int A, int F, Uint32_t *Data, int *Q, int *X)
{
    Uint32_t intbuf[4];  
    int ret;
    // CAMAC direct read function
    intbuf[0]=1;
    intbuf[1]=(Uint32_t)(F+A*32+N*512 + 0x4000);
    ret = xxusb_stack_execute(hdev, intbuf);
    if ((F < 16) || (F >23))
    {
        *Data=intbuf[0] + (intbuf[1] & 255) * 0x10000;   //24-bit word
        *Q = ((intbuf[1] >> 8) & 1);
        *X = ((intbuf[1] >> 9) & 1);
    }  
    return ret;
}

/*
******** CAMAC_Z ************************

  Performs a CAMAC init
 
  Parameters:
    hdev: USB device handle returned from an open function
 
  Returns:
    Number of bytes written to xxusb when successful
    Upon failure, a negative number    
*/

short   CAMAC_Z(usb_dev_handle *hdev)
{
    Uint32_t intbuf[4];  
    int  ret;
//  CAMAC Z = N(28) A(8) F(29)
    intbuf[0]=1;
    intbuf[1]=(Uint32_t)(29+8*32+28*512 + 0x4000);
    ret = xxusb_stack_execute(hdev, intbuf);
    return ret;
}

/*
******** CAMAC_C ************************

  Performs a CAMAC clear
 
  Parameters:
    hdev: USB device handle returned from an open function
 
  Returns:
    Number of bytes written to xxusb when successful
    Upon failure, a negative number    
*/

short   CAMAC_C(usb_dev_handle *hdev)
{
    Uint32_t intbuf[4];  
    int ret;
    intbuf[0]=1;
    intbuf[1]=(Uint32_t)(29+9*32+28*512 + 0x4000);
    ret = xxusb_stack_execute(hdev, intbuf);
    return ret;
}

/*
******** CAMAC_I ************************

  Set CAMAC inhibit
 
  Parameters:
    hdev: USB device handle returned from an open function
 
  Returns:
    Number of bytes written to xxusb when successful
    Upon failure, a negative number    
*/

short   CAMAC_I(usb_dev_handle *hdev, int inhibit)
{
    Uint32_t intbuf[4];  
    int  ret;
    intbuf[0]=1;
    if (inhibit) intbuf[1]=(Uint32_t)(24+9*32+29*512 + 0x4000);
    else intbuf[1]=(Uint32_t)(26+9*32+29*512 + 0x4000);
    ret = xxusb_stack_execute(hdev, intbuf);
    return ret;
}