226 lines
6.1 KiB
C
226 lines
6.1 KiB
C
/*
|
|
* Copyright 2010 by Red Hat, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU 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.
|
|
*/
|
|
|
|
|
|
#ifndef ISDV4_H
|
|
#define ISDV4_H
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
#define ISDV4_QUERY "*" /* ISDV4 query command */
|
|
#define ISDV4_RESET "&" /* ISDV4 touch panel reset command */
|
|
#define ISDV4_TOUCH_QUERY "%" /* ISDV4 touch query command */
|
|
#define ISDV4_STOP "0" /* ISDV4 stop command */
|
|
#define ISDV4_SAMPLING "1" /* ISDV4 sampling command */
|
|
|
|
/* packet length for individual models */
|
|
#define ISDV4_PKGLEN_TOUCH93 5
|
|
#define ISDV4_PKGLEN_TOUCH9A 7
|
|
#define ISDV4_PKGLEN_TPCPEN 9
|
|
#define ISDV4_PKGLEN_TPCCTL 11
|
|
#define ISDV4_PKGLEN_TOUCH2FG 13
|
|
|
|
#define HEADER_BIT 0x80
|
|
#define CONTROL_BIT 0x40
|
|
#define DATA_ID_MASK 0x3F
|
|
#define TOUCH_CONTROL_BIT 0x10
|
|
|
|
/* Only for touch devices: use serial ID as index to get packet length for device */
|
|
int ISDV4PacketLengths[] = {
|
|
/* 0x00 => */ ISDV4_PKGLEN_TOUCH93,
|
|
/* 0x01 => */ ISDV4_PKGLEN_TOUCH9A,
|
|
/* 0x02 => */ ISDV4_PKGLEN_TOUCH93,
|
|
/* 0x03 => */ ISDV4_PKGLEN_TOUCH9A,
|
|
/* 0x04 => */ ISDV4_PKGLEN_TOUCH9A,
|
|
/* 0x05 => */ ISDV4_PKGLEN_TOUCH2FG
|
|
};
|
|
|
|
/* ISDV4 protocol parsing structs. */
|
|
|
|
/* Query reply data */
|
|
typedef struct {
|
|
unsigned char data_id; /* always 00H */
|
|
uint16_t x_max;
|
|
uint16_t y_max;
|
|
uint16_t pressure_max;
|
|
uint8_t tilt_x_max;
|
|
uint8_t tilt_y_max;
|
|
uint16_t version;
|
|
} ISDV4QueryReply;
|
|
|
|
/* Touch Query reply data */
|
|
typedef struct {
|
|
uint8_t data_id; /* always 01H */
|
|
uint8_t panel_resolution;
|
|
uint8_t sensor_id;
|
|
uint16_t x_max;
|
|
uint16_t y_max;
|
|
uint8_t capacity_resolution;
|
|
uint16_t version;
|
|
} ISDV4TouchQueryReply;
|
|
|
|
/* Touch Data format. Note that capacity and finger2 are only set for some
|
|
* devices (0 on all others) */
|
|
typedef struct {
|
|
uint8_t status; /* touch down/up */
|
|
uint16_t x;
|
|
uint16_t y;
|
|
uint16_t capacity;
|
|
struct {
|
|
uint8_t status; /* touch down/up */
|
|
uint16_t x;
|
|
uint16_t y;
|
|
} finger2;
|
|
} ISDV4TouchData;
|
|
|
|
/* Coordinate data format */
|
|
typedef struct {
|
|
uint8_t proximity; /* in proximity? */
|
|
uint8_t tip; /* tip/eraser pressed? */
|
|
uint8_t side; /* side switch pressed? */
|
|
uint8_t eraser; /* eraser pressed? */
|
|
uint16_t x;
|
|
uint16_t y;
|
|
uint16_t pressure;
|
|
uint8_t tilt_x;
|
|
uint8_t tilt_y;
|
|
} ISDV4CoordinateData;
|
|
|
|
static inline int isdv4ParseQuery(const unsigned char *buffer, const size_t len,
|
|
ISDV4QueryReply *reply)
|
|
{
|
|
int header, control;
|
|
|
|
if (!reply || len < ISDV4_PKGLEN_TPCCTL)
|
|
return 0;
|
|
|
|
header = !!(buffer[0] & HEADER_BIT);
|
|
control = !!(buffer[0] & CONTROL_BIT);
|
|
|
|
if (!header || !control)
|
|
return -1;
|
|
|
|
reply->data_id = buffer[0] & DATA_ID_MASK;
|
|
|
|
/* FIXME: big endian? */
|
|
reply->x_max = (buffer[1] << 9) | (buffer[2] << 2) | ((buffer[6] >> 5) & 0x3);
|
|
reply->y_max = (buffer[3] << 9) | (buffer[4] << 2) | ((buffer[6] >> 3) & 0x3);
|
|
reply->pressure_max = (buffer[6] & 0x7) << 7 | buffer[5];
|
|
reply->tilt_y_max = buffer[7];
|
|
reply->tilt_x_max = buffer[8];
|
|
reply->version = buffer[9] << 7 | buffer[10];
|
|
|
|
return ISDV4_PKGLEN_TPCCTL;
|
|
}
|
|
|
|
static inline int isdv4ParseTouchQuery(const unsigned char *buffer, const size_t len,
|
|
ISDV4TouchQueryReply *reply)
|
|
{
|
|
int header, control;
|
|
|
|
if (!reply || len < ISDV4_PKGLEN_TPCCTL)
|
|
return 0;
|
|
|
|
header = !!(buffer[0] & HEADER_BIT);
|
|
control = !!(buffer[0] & CONTROL_BIT);
|
|
|
|
if (!header || !control)
|
|
return -1;
|
|
|
|
reply->data_id = buffer[0] & DATA_ID_MASK;
|
|
reply->sensor_id = buffer[2] & 0x7;
|
|
reply->panel_resolution = buffer[1];
|
|
/* FIXME: big endian? */
|
|
reply->x_max = (buffer[3] << 9) | (buffer[4] << 2) | ((buffer[2] >> 5) & 0x3);
|
|
reply->y_max = (buffer[5] << 9) | (buffer[6] << 2) | ((buffer[2] >> 3) & 0x3);
|
|
reply->capacity_resolution = buffer[7];
|
|
reply->version = buffer[9] << 7 | buffer[10];
|
|
|
|
return ISDV4_PKGLEN_TPCCTL;
|
|
}
|
|
|
|
/* pktlen defines what touch type we parse */
|
|
static inline int isdv4ParseTouchData(const unsigned char *buffer, const size_t buff_len,
|
|
const size_t pktlen, ISDV4TouchData *touchdata)
|
|
{
|
|
int header, touch;
|
|
|
|
if (!touchdata || buff_len < pktlen)
|
|
return 0;
|
|
|
|
header = !!(buffer[0] & HEADER_BIT);
|
|
touch = !!(buffer[0] & TOUCH_CONTROL_BIT);
|
|
|
|
if (header != 1 || touch != 1)
|
|
return -1;
|
|
|
|
memset(touchdata, 0, sizeof(*touchdata));
|
|
|
|
touchdata->status = buffer[0] & 0x1;
|
|
/* FIXME: big endian */
|
|
touchdata->x = buffer[1] << 7 | buffer[2];
|
|
touchdata->y = buffer[3] << 7 | buffer[4];
|
|
if (pktlen == ISDV4_PKGLEN_TOUCH9A)
|
|
touchdata->capacity = buffer[5] << 7 | buffer[6];
|
|
|
|
if (pktlen == ISDV4_PKGLEN_TOUCH2FG)
|
|
{
|
|
touchdata->finger2.x = buffer[7] << 7 | buffer[8];
|
|
touchdata->finger2.y = buffer[9] << 7 | buffer[10];
|
|
touchdata->finger2.status = !!(buffer[0] & 0x2);
|
|
/* FIXME: is there a fg2 capacity? */
|
|
}
|
|
|
|
return pktlen;
|
|
}
|
|
|
|
static inline int isdv4ParseCoordinateData(const unsigned char *buffer, const size_t len,
|
|
ISDV4CoordinateData *coord)
|
|
{
|
|
int header, control;
|
|
|
|
if (!coord || len < ISDV4_PKGLEN_TPCPEN)
|
|
return 0;
|
|
|
|
header = !!(buffer[0] & HEADER_BIT);
|
|
control = !!(buffer[0] & TOUCH_CONTROL_BIT);
|
|
|
|
if (header != 1 || control != 0)
|
|
return -1;
|
|
|
|
coord->proximity = (buffer[0] >> 5) & 0x1;
|
|
coord->tip = buffer[0] & 0x1;
|
|
coord->side = (buffer[0] >> 1) & 0x1;
|
|
coord->eraser = (buffer[0] >> 2) & 0x1;
|
|
/* FIXME: big endian */
|
|
coord->x = (buffer[1] << 9) | (buffer[2] << 2) | ((buffer[6] >> 5) & 0x3);
|
|
coord->y = (buffer[3] << 9) | (buffer[4] << 2) | ((buffer[6] >> 3) & 0x3);
|
|
|
|
coord->pressure = ((buffer[6] & 0x7) << 7) | buffer[5];
|
|
coord->tilt_x = buffer[7];
|
|
coord->tilt_y = buffer[8];
|
|
|
|
return ISDV4_PKGLEN_TPCPEN;
|
|
}
|
|
|
|
#endif /* ISDV4_H */
|
|
|
|
/* vim: set noexpandtab tabstop=8 shiftwidth=8: */
|