#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <bus/smbus/smb.h>
#include <bus/smbus/smbconf.h>
#define CYAPA_MAX_MT 5
struct cyapa_regs {
uint8_t stat;
uint8_t fngr;
struct {
uint8_t xy_high;
uint8_t x_low;
uint8_t y_low;
uint8_t pressure;
uint8_t id;
} touch[CYAPA_MAX_MT];
} __packed;
struct cyapa_cap {
uint8_t prod_ida[5];
uint8_t prod_idb[6];
uint8_t prod_idc[2];
uint8_t reserved[6];
uint8_t buttons;
uint8_t gen;
uint8_t max_abs_xy_high;
uint8_t max_abs_x_low;
uint8_t max_abs_y_low;
uint8_t phy_siz_xy_high;
uint8_t phy_siz_x_low;
uint8_t phy_siz_y_low;
} __packed;
#define CYAPA_STAT_INTR 0x80
#define CYAPA_STAT_PWR_MASK 0x0C
#define CYAPA_PWR_OFF 0x00
#define CYAPA_PWR_IDLE 0x08
#define CYAPA_PWR_ACTIVE 0x0C
#define CYAPA_STAT_DEV_MASK 0x03
#define CYAPA_DEV_NORMAL 0x03
#define CYAPA_DEV_BUSY 0x01
#define CYAPA_FNGR_DATA_VALID 0x08
#define CYAPA_FNGR_MIDDLE 0x04
#define CYAPA_FNGR_RIGHT 0x02
#define CYAPA_FNGR_LEFT 0x01
#define CYAPA_FNGR_NUMFINGERS(c) (((c) >> 4) & 0x0F)
#define CYAPA_TOUCH_X(regs, i) ((((regs)->touch[i].xy_high << 4) & 0x0F00) | \
(regs)->touch[i].x_low)
#define CYAPA_TOUCH_Y(regs, i) ((((regs)->touch[i].xy_high << 8) & 0x0F00) | \
(regs)->touch[i].y_low)
#define CYAPA_TOUCH_P(regs, i) ((regs)->touch[i].pressure)
#define CMD_DEV_STATUS 0x00
#define CMD_SOFT_RESET 0x28
#define CMD_POWER_MODE 0x29
#define CMD_QUERY_CAPABILITIES 0x2A
static char bl_exit[] = { 0x00, 0xff, 0xa5, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06,
0x07 };
static char bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06,
0x07 };
int
main(int ac, char **av)
{
struct smbcmd cmd;
char buf[256];
int fd;
int r;
int i;
int len;
bzero(&cmd, sizeof(cmd));
bzero(buf, sizeof(buf));
fd = open("/dev/smb0-67", O_RDWR);
printf("fd = %d\n", fd);
cmd.slave = 0;
cmd.rbuf = buf;
cmd.cmd = CMD_DEV_STATUS;
cmd.op = SMB_TRANS_NOCNT | SMB_TRANS_7BIT;
cmd.rcount = 16;
r = ioctl(fd, SMB_TRANS, &cmd);
printf("status r = %d slave 0x%02x\n", r, cmd.slave);
for (i = 0; i < cmd.rcount; ++i)
printf(" %02x", (u_char)buf[i]);
printf("\n");
cmd.rcount = 0;
#if 1
if ((buf[0] & 0x80) == 0) {
if (buf[1] & 0x80) {
printf("X2 BL BUSY\n");
} else if (buf[2] & 0x20) {
printf("X2 BL ACTIVE\n");
cmd.cmd = 0x00;
cmd.wbuf = bl_deactivate;
cmd.wcount = sizeof(bl_deactivate);
r = ioctl(fd, SMB_TRANS, &cmd);
printf("r=%d\n", r);
} else {
printf("X2 BL IDLE\n");
cmd.cmd = 0x00;
cmd.wbuf = bl_exit;
cmd.wcount = sizeof(bl_exit);
r = ioctl(fd, SMB_TRANS, &cmd);
printf("r=%d\n", r);
}
exit(0);
}
#endif
#if 1
{
struct cyapa_cap *cap;
cmd.cmd = CMD_QUERY_CAPABILITIES;
cmd.wcount = 0;
cmd.rcount = sizeof(struct cyapa_cap);
r = ioctl(fd, SMB_TRANS, &cmd);
cap = (void *)buf;
printf("caps %5.5s-%6.6s-%2.2s left=%c midl=%c rght=%c\n",
cap->prod_ida,
cap->prod_idb,
cap->prod_idc,
((cap->buttons & CYAPA_FNGR_LEFT) ? 'y' : 'n'),
((cap->buttons & CYAPA_FNGR_MIDDLE) ? 'y' : 'n'),
((cap->buttons & CYAPA_FNGR_RIGHT) ? 'y' : 'n')
);
printf("caps pixx=%d pixy=%d\n",
(cap->max_abs_xy_high << 4 & 0x0F00) |
cap->max_abs_x_low,
(cap->max_abs_xy_high << 8 & 0x0F00) |
cap->max_abs_y_low);
}
#endif
#if 1
cmd.cmd = CMD_DEV_STATUS;
while (1) {
struct cyapa_regs *regs;
int i;
int nfingers;
cmd.rcount = sizeof(struct cyapa_regs);
r = ioctl(fd, SMB_TRANS, &cmd);
regs = (void *)buf;
nfingers = CYAPA_FNGR_NUMFINGERS(regs->fngr);
printf("stat %02x buttons %c%c%c nfngrs=%d ",
regs->stat,
((regs->fngr & CYAPA_FNGR_LEFT) ? 'L' : '-'),
((regs->fngr & CYAPA_FNGR_MIDDLE) ? 'L' : '-'),
((regs->fngr & CYAPA_FNGR_RIGHT) ? 'L' : '-'),
nfingers
);
fflush(stdout);
for (i = 0; i < nfingers; ++i) {
printf(" [x=%04d y=%04d p=%d]",
CYAPA_TOUCH_X(regs, i),
CYAPA_TOUCH_Y(regs, i),
CYAPA_TOUCH_P(regs, i));
}
printf("\n");
usleep(10000);
}
#endif
close(fd);
return 0;
}