Logo Search packages:      
Sourcecode: wacom-tools version File versions

wacomcfg.c

/*****************************************************************************
** wacomcfg.c
**
** Copyright (C) 2003-2004 - John E. Joganic
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
**
** REVISION HISTORY
**   2003-05-02 0.0.1 - JEJ - created
**   2004-05-28 0.0.2 - PC - updated WacomConfigListDevices
**
****************************************************************************/

#include "wacomcfg.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h> /* debugging only, we've got no business output text */
#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <memory.h>
#include <assert.h>

/*****************************************************************************
** XInput
*****************************************************************************/

#include <X11/Xlib.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XIproto.h>

#include "Xwacom.h" /* Hopefully it will be included in XFree86 someday, but
                     * in the meantime, we are expecting it in the local
                     * directory. */

/*****************************************************************************
** Internal structures
*****************************************************************************/

typedef struct _CONFIG CONFIG;
typedef struct _DEVICE DEVICE;

struct _CONFIG
{
      Display* pDisp;
      WACOMERRORFUNC pfnError;
      XDeviceInfoPtr pDevs;
      int nDevCnt;
};

struct _DEVICE
{
      CONFIG* pCfg;
      XDevice* pDev;
};

/*****************************************************************************
** Library operations
*****************************************************************************/

static int CfgError(CONFIG* pCfg, int err, const char* pszText)
{
      /* report error */
      if (pCfg->pfnError)
            (*pCfg->pfnError)(err,pszText);

      /* set and return */
      errno = err;
      return -1;
}

static int CfgGetDevs(CONFIG* pCfg)
{
      /* request device list */
      pCfg->pDevs = (XDeviceInfoPtr) XListInputDevices(pCfg->pDisp,
                  &pCfg->nDevCnt);
      if (!pCfg->pDevs)
            return CfgError(pCfg,EIO,"CfgGetDevs: failed to get devices");

      return 0;
}

/*****************************************************************************
** Library initialization, termination
*****************************************************************************/

WACOMCONFIG WacomConfigInit(Display* pDisplay, WACOMERRORFUNC pfnErrorHandler)
{
      CONFIG* pCfg;
      int nMajor, nFEV, nFER;

      /* check for XInput extension */
      if (!XQueryExtension(pDisplay,INAME,&nMajor,&nFEV,&nFER))
      {
            if (pfnErrorHandler)
                  (*pfnErrorHandler)(EINVAL,"XInput not supported.");
            return NULL;
      }

      /* allocate configuration structure */
      pCfg = (CONFIG*)malloc(sizeof(CONFIG));
      if (!pCfg)
      {
            if (pfnErrorHandler)
                  (*pfnErrorHandler)(errno,strerror(errno));
            return NULL;
      }

      memset(pCfg,0,sizeof(*pCfg));
      pCfg->pDisp = pDisplay;
      pCfg->pfnError = pfnErrorHandler;
      return (WACOMCONFIG)pCfg;
}

void WacomConfigTerm(WACOMCONFIG hConfig)
{
      CONFIG* pCfg = (CONFIG*)hConfig;
      if (!pCfg) return;
      free(pCfg);
}

int WacomConfigListDevices(WACOMCONFIG hConfig, WACOMDEVICEINFO** ppInfo,
      unsigned int* puCount)
{
      int i, j, nSize, nPos, nLen, nCount;
      unsigned char* pReq;
      WACOMDEVICEINFO* pInfo;
      CONFIG* pCfg = (CONFIG*)hConfig;
      char devName[64];

      if (!pCfg || !ppInfo || !puCount)
            { errno=EINVAL; return -1; }

      /* load devices, if not already in memory */
      if (!pCfg->pDevs && CfgGetDevs(pCfg))
            return -1;

      /* estimate size of memory needed to hold structures */
      nSize = nCount = 0;
      for (i=0; i<pCfg->nDevCnt; ++i)
      {
            if (pCfg->pDevs[i].use != IsXExtensionDevice) continue;
            nSize += sizeof(WACOMDEVICEINFO);
            nSize += strlen(pCfg->pDevs[i].name) + 1;
            ++nCount;
      }

      /* allocate memory and zero */
      pReq = (unsigned char*)malloc(nSize);
      if (!pReq) return CfgError(pCfg,errno,
            "WacomConfigListDevices: failed to allocate memory");
      memset(pReq,0,nSize);

      /* populate data */
      pInfo = (WACOMDEVICEINFO*)pReq;
      nPos = nCount * sizeof(WACOMDEVICEINFO);
      nCount = 0;
      for (i=0; i<pCfg->nDevCnt; ++i)
      {
            /* ignore non-extension devices */
            if (pCfg->pDevs[i].use != IsXExtensionDevice) continue;

            /* copy name */
            nLen = strlen(pCfg->pDevs[i].name);
            pInfo->pszName = (char*)(pReq + nPos);
            memcpy(pReq+nPos,pCfg->pDevs[i].name,nLen+1);
            nPos += nLen + 1;

            /* guess type for now - discard unknowns */
            for (j=0; j<strlen(pInfo->pszName); j++)
                  devName[j] = tolower(pInfo->pszName[j]);
            devName[j] = '\0';
            if (strstr(devName,"cursor") != NULL)
                  pInfo->type = WACOMDEVICETYPE_CURSOR;
            else if (strstr(devName,"stylus") != NULL)
                  pInfo->type = WACOMDEVICETYPE_STYLUS;
            else if (strstr(devName,"eraser") != NULL)
                  pInfo->type = WACOMDEVICETYPE_ERASER;
            else
                  pInfo->type = WACOMDEVICETYPE_UNKNOWN;

            if ( pInfo->type != WACOMDEVICETYPE_UNKNOWN )
            {
                  ++pInfo;
                  ++nCount;
            }
      }

      /* double check our work */
      assert(nPos == nSize);
      
      *ppInfo = (WACOMDEVICEINFO*)pReq;
      *puCount = nCount;
      return 0;
}

WACOMDEVICE WacomConfigOpenDevice(WACOMCONFIG hConfig,
      const char* pszDeviceName)
{
      int i;
      DEVICE* pInt;
      XDevice* pDev;
      XDeviceInfoPtr pDevInfo = NULL;
      CONFIG* pCfg = (CONFIG*)hConfig;

      /* sanity check input */
      if (!pCfg || !pszDeviceName) { errno=EINVAL; return NULL; }

      /* load devices, if not already in memory */
      if (!pCfg->pDevs && CfgGetDevs(pCfg))
            return NULL;

      /* find device in question */
      for (i=0; i<pCfg->nDevCnt; ++i)
            if (strcmp(pCfg->pDevs[i].name, pszDeviceName) == 0)
                  pDevInfo = pCfg->pDevs + i;

      /* no device, bail. */
      if (!pDevInfo)
      {
            CfgError(pCfg,ENOENT,"WacomConfigOpenDevice: No such device");
            return NULL;
      }

      /* Open the device. */
      pDev = XOpenDevice(pCfg->pDisp,pDevInfo->id);
      if (!pDev)
      {
            CfgError(pCfg,EIO,"WacomConfigOpenDevice: "
                  "Failed to open device");
            return NULL;
      }

      /* allocate device structure and return */
      pInt = (DEVICE*)malloc(sizeof(DEVICE));
      memset(pInt,0,sizeof(*pInt));
      pInt->pCfg = pCfg;
      pInt->pDev = pDev;

      return (WACOMDEVICE)pInt;
}

int WacomConfigCloseDevice(WACOMDEVICE hDevice)
{
      DEVICE* pInt = (DEVICE*)hDevice;
      if (!pInt) { errno=EINVAL; return -1; }

      (void)XCloseDevice(pInt->pCfg->pDisp,pInt->pDev);
      free(pInt);
      return 0;
}

int WacomConfigSetRawParam(WACOMDEVICE hDevice, int nParam, int nValue)
{
      int nReturn;
      DEVICE* pInt = (DEVICE*)hDevice;
      int nValues[2];
      XDeviceResolutionControl c;
      XDeviceResolutionControl* cp = &c;
      XDeviceControl* dc = (XDeviceControl*)cp;

      nValues[0] = nParam;
      nValues[1] = nValue;
      if (!pInt || !nParam) { errno=EINVAL; return -1; }

      c.control = DEVICE_RESOLUTION;
      c.length = sizeof(c);
      if ( nParam == XWACOM_PARAM_FILEOPTION ) c.first_valuator = 0;
      else if ( nParam == XWACOM_PARAM_FILEMODEL ) c.first_valuator = 1;
      else c.first_valuator = 4;
      c.num_valuators = 2;
      c.resolutions = nValues;

      /* Dispatch request */
      nReturn = XChangeDeviceControl(
            pInt->pCfg->pDisp,
            pInt->pDev,
            DEVICE_RESOLUTION,
            dc);

      /* Convert error codes */
      if (nReturn == BadValue)
            return CfgError(pInt->pCfg,EINVAL,
                  "WacomConfigSetRawParam: Bad value");
      else if (nReturn != Success)
            return CfgError(pInt->pCfg,EIO,
                  "WacomConfigSetRawParam: Unknown X error");
      return 0;
}

void WacomConfigFree(void* pvData)
{
      /* JEJ - if in the future, more context is needed, make an alloc
       *       function that places the context before the data.
       *       In the meantime, free is good enough. */

      free(pvData);
}

Generated by  Doxygen 1.6.0   Back to index