PS2 Elantech mostly working still disabled

Does handle coords correctly, but two finger jumps position somewhere
We can also report actual buttons, but not sure how movementmaker handles
it.

Will do cleanup once working

To test or help out return B_OK in probe_elantech
This commit is contained in:
Fredrik Holmqvist 2018-11-03 18:07:26 +01:00
parent 586138b632
commit 3431cf5b06
2 changed files with 61 additions and 43 deletions

View File

@ -112,6 +112,9 @@ const char* kElantechPath[4] = {
#define ELANTECH_HISTORY_SIZE 256 #define ELANTECH_HISTORY_SIZE 256
#define STATUS_PACKET 0x0
#define HEAD_PACKET 0x1
#define MOTION_PACKET 0x2
static hardware_specs gHardwareSpecs; static hardware_specs gHardwareSpecs;
@ -120,7 +123,7 @@ static status_t
get_elantech_movement(elantech_cookie *cookie, mouse_movement *movement) get_elantech_movement(elantech_cookie *cookie, mouse_movement *movement)
{ {
touch_event event; touch_event event;
uint8 event_buffer[PS2_PACKET_ELANTECH]; uint8 packet[PS2_PACKET_ELANTECH];
status_t status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT, 0); status_t status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT, 0);
if (status < B_OK) if (status < B_OK)
@ -131,69 +134,75 @@ get_elantech_movement(elantech_cookie *cookie, mouse_movement *movement)
return B_ERROR; return B_ERROR;
} }
if (packet_buffer_read(cookie->ring_buffer, event_buffer, if (packet_buffer_read(cookie->ring_buffer, packet,
cookie->dev->packet_size) != cookie->dev->packet_size) { cookie->dev->packet_size) != cookie->dev->packet_size) {
TRACE("ELANTECH: error copying buffer\n"); TRACE("ELANTECH: error copying buffer\n");
return B_ERROR; return B_ERROR;
} }
if (cookie->crcEnabled && (event_buffer[3] & 0x08) != 0) { if (cookie->crcEnabled && (packet[3] & 0x08) != 0) {
TRACE("ELANTECH: bad crc buffer\n"); TRACE("ELANTECH: bad crc buffer\n");
return B_ERROR; return B_ERROR;
} else if (!cookie->crcEnabled && ((event_buffer[0] & 0x0c) != 0x04 } else if (!cookie->crcEnabled && ((packet[0] & 0x0c) != 0x04
|| (event_buffer[3] & 0x1c) != 0x10)) { || (packet[3] & 0x1c) != 0x10)) {
TRACE("ELANTECH: bad crc buffer\n"); TRACE("ELANTECH: bad crc buffer\n");
return B_ERROR; return B_ERROR;
} }
uint8 type = event_buffer[3] & 3; // https://www.kernel.org/doc/html/v4.16/input/devices/elantech.html
TRACE("ELANTECH: packet type %d\n", type); uint8 packet_type = packet[3] & 3;
TRACE("ELANTECH: packet type %d\n", packet_type);
TRACE("ELANTECH: packet content 0x%02x%02x%02x%02x%02x%02x\n", TRACE("ELANTECH: packet content 0x%02x%02x%02x%02x%02x%02x\n",
event_buffer[0], event_buffer[1], event_buffer[2], event_buffer[3], packet[0], packet[1], packet[2], packet[3],
event_buffer[4], event_buffer[5]); packet[4], packet[5]);
switch (type) { switch (packet_type) {
case 0: case STATUS_PACKET:
// fingers //fingers, no palm
cookie->fingers = event_buffer[1] & 0x1f; cookie->fingers = (packet[4] & 0x80) == 0 ? packet[1] & 0x1f: 0;
dprintf("ELANTECH: Fingers %d, raw %x (STATUS)\n", cookie->fingers, packet[1]);
break; break;
case 1: case HEAD_PACKET:
if ((((event_buffer[3] & 0xe0) >> 5) - 1) != 0) { dprintf("ELANTECH: Fingers %d, raw %x (HEAD)\n", (packet[3] & 0xe0) >>5, packet[3]);
// only process first finger // only process first finger
if ((packet[3] & 0xe0) != 0x20)
return B_OK; return B_OK;
}
event.zPressure = (event_buffer[1] & 0xf0) event.zPressure = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
| ((event_buffer[4] & 0xf0) >> 4);
cookie->previousZ = event.zPressure; cookie->previousZ = event.zPressure;
event.xPosition = ((event_buffer[1] & 0xf) << 8) | event_buffer[2]; cookie->x = event.xPosition = ((packet[1] & 0xf) << 8) | packet[2];
event.yPosition = (((event_buffer[4] & 0xf) << 8) cookie->y = event.yPosition = ((packet[4] & 0xf) << 8) | packet[5];
| event_buffer[5]); dprintf("ELANTECH: Pos: %d:%d\n (HEAD)", cookie->x, cookie->y);
TRACE("ELANTECH: buttons 0x%x x %" B_PRIu32 " y %" B_PRIu32 TRACE("ELANTECH: buttons 0x%x x %" B_PRIu32 " y %" B_PRIu32
" z %d\n", event.buttons, event.xPosition, event.yPosition, " z %d\n", event.buttons, event.xPosition, event.yPosition,
event.zPressure); event.zPressure);
break; break;
case 2: case MOTION_PACKET:
TRACE("ELANTECH: packet type motion\n"); dprintf("ELANTECH: Fingers %d, raw %x (MOTION)\n", (packet[3] & 0xe0) >>5, packet[3]); //Most likely palm
// TODO if (cookie->fingers == 0) return B_OK;
return B_OK; //handle overflow and delta values
if ((packet[0] & 0x10) == 1) {
event.xPosition = cookie->x += 5 * (int8)packet[1];
event.yPosition = cookie->y += 5 * (int8)packet[2];
} else {
event.xPosition = cookie->x += (int8)packet[1];
event.yPosition = cookie->y += (int8)packet[2];
}
dprintf("ELANTECH: Pos: %d:%d (Motion\n", cookie->x, cookie->y);
break;
default: default:
TRACE("ELANTECH: unknown packet type %d\n", type); dprintf("ELANTECH: unknown packet type %d\n", packet_type);
return B_ERROR; return B_ERROR;
} }
event.buttons = 0; event.buttons = 0;
// finger on touchpad event.wValue = cookie->fingers == 1 ? 4 :0;
if ((cookie->fingers & 1) != 0) {
// finger with normal width
event.wValue = 4;
} else {
event.wValue = 3;
}
status = cookie->movementMaker.EventToMovement(&event, movement); status = cookie->movementMaker.EventToMovement(&event, movement);
if (cookie->movementMaker.WasEdgeMotion() if (cookie->movementMaker.WasEdgeMotion()
|| cookie->movementMaker.TapDragStarted()) { || cookie->movementMaker.TapDragStarted()) {
gEventProducer.FireEvent(cookie, event_buffer); gEventProducer.FireEvent(cookie, packet);
} }
return status; return status;
@ -566,7 +575,7 @@ elantech_open(const char *name, uint32 flags, void **_cookie)
goto err4; goto err4;
} }
} }
TRACE("ELANTECH: version 0x%" B_PRIu32 " (0x%" B_PRIu32 ")\n", INFO("ELANTECH: version 0x%" B_PRIu32 " (0x%" B_PRIu32 ")\n",
cookie->version, cookie->fwVersion); cookie->version, cookie->fwVersion);
if (cookie->version >= 3) if (cookie->version >= 3)
@ -698,7 +707,7 @@ elantech_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
return B_OK; return B_OK;
case MS_SET_TOUCHPAD_SETTINGS: case MS_SET_TOUCHPAD_SETTINGS:
TRACE("ELANTECH: MS_SET_TOUCHPAD_SETTINGS"); TRACE("ELANTECH: MS_SET_TOUCHPAD_SETTINGS\n");
user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings)); user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings));
return B_OK; return B_OK;
@ -708,7 +717,7 @@ elantech_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
sizeof(bigtime_t)); sizeof(bigtime_t));
default: default:
TRACE("ELANTECH: unknown opcode: %" B_PRIu32 "\n", op); INFO("ELANTECH: unknown opcode: 0x%" B_PRIx32 "\n", op);
return B_BAD_VALUE; return B_BAD_VALUE;
} }
} }

View File

@ -27,18 +27,27 @@ typedef struct {
sem_id sem; sem_id sem;
struct packet_buffer* ring_buffer; struct packet_buffer* ring_buffer;
size_t packet_index; size_t packet_index;
uint8 buffer[PS2_PACKET_ELANTECH];
uint8 mode;
uint8 previousZ;
TouchpadMovement movementMaker; TouchpadMovement movementMaker;
touchpad_settings settings; touchpad_settings settings;
uint32 version; uint32 version;
uint32 fwVersion; uint32 fwVersion;
uint8 capabilities[3];
bool crcEnabled; uint32 x;
uint32 y;
uint32 fingers; uint32 fingers;
uint8 buffer[PS2_PACKET_ELANTECH];
uint8 capabilities[3];
uint8 previousZ;
uint8 mode;
bool crcEnabled;
status_t (*send_command)(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count); status_t (*send_command)(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count);
} elantech_cookie; } elantech_cookie;