ps/2 elantech: trackpoint support (untested)
Threat trackpoint packets to mouse_movement values instead of touchpad_movement. This required changes on ioctl handling effectely making this as kind of hybrid device which reports back MS_READ events for touchpad and MS_READ_TOUCHPAD for touchpad related processed packets. The logic is similar to the ioctl and movement handling funtions of the Haiku ps/2 alps driver. Packet descriptions based on FreeBSD 14.3 psm driver. Constant bit checks based on FreeBSD 14.3 psm driver. Packet processing code based on OpenBSD 7.8 pms driver with variable naming adjustments to match FreeBSD and Haiku. Change-Id: I42b62ccbb410060cceba4f17d299c7daf0c38b66 Reviewed-on: https://review.haiku-os.org/c/haiku/+/9956 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
cf37429032
commit
494ae23c3d
@@ -99,6 +99,9 @@ elantech_process_packet_v3(elantech_cookie *cookie, touchpad_movement *_event,
|
||||
static status_t
|
||||
elantech_process_packet_v4(elantech_cookie *cookie, touchpad_movement *_event,
|
||||
uint8 packet[PS2_PACKET_ELANTECH]);
|
||||
static status_t
|
||||
elantech_process_packet_trackpoint(elantech_cookie *cookie, mouse_movement *_movement,
|
||||
uint8 packet[PS2_PACKET_ELANTECH]);
|
||||
|
||||
|
||||
/* Common legend
|
||||
@@ -111,14 +114,18 @@ elantech_process_packet_v4(elantech_cookie *cookie, touchpad_movement *_event,
|
||||
* P: pressure
|
||||
*/
|
||||
static status_t
|
||||
get_elantech_movement(elantech_cookie *cookie, touchpad_movement *_event, bigtime_t timeout)
|
||||
get_elantech_movement(elantech_cookie *cookie, touchpad_read *_read)
|
||||
{
|
||||
touchpad_movement event = {};
|
||||
mouse_movement movement {};
|
||||
uint8 packet[PS2_PACKET_ELANTECH];
|
||||
|
||||
status_t status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT,
|
||||
timeout);
|
||||
if (status < B_OK)
|
||||
_read->timeout);
|
||||
if (status < B_OK) {
|
||||
TRACE("ELANTECH: acquire_sem_etc err or timeout.\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!cookie->dev->active) {
|
||||
TRACE("ELANTECH: read_event: Error device no longer active\n");
|
||||
@@ -132,25 +139,33 @@ get_elantech_movement(elantech_cookie *cookie, touchpad_movement *_event, bigtim
|
||||
}
|
||||
|
||||
if ((cookie->capabilities[0] & 0x80) != 0 && (packet[3] & 0x0f) == 0x06) {
|
||||
status = IGNORE_EVENT;
|
||||
status = elantech_process_packet_trackpoint(cookie, &movement, packet);
|
||||
if (status == B_OK) {
|
||||
_read->event = MS_READ;
|
||||
_read->u.mouse = movement;
|
||||
}
|
||||
} else {
|
||||
switch (cookie->version) {
|
||||
case 1:
|
||||
status = elantech_process_packet_v1(cookie, _event, packet);
|
||||
status = elantech_process_packet_v1(cookie, &event, packet);
|
||||
break;
|
||||
case 2:
|
||||
status = elantech_process_packet_v2(cookie, _event, packet);
|
||||
status = elantech_process_packet_v2(cookie, &event, packet);
|
||||
break;
|
||||
case 3:
|
||||
status = elantech_process_packet_v3(cookie, _event, packet);
|
||||
status = elantech_process_packet_v3(cookie, &event, packet);
|
||||
break;
|
||||
case 4:
|
||||
status = elantech_process_packet_v4(cookie, _event, packet);
|
||||
status = elantech_process_packet_v4(cookie, &event, packet);
|
||||
break;
|
||||
default:
|
||||
TRACE("ELANTECH: Unknown version %d.\n", cookie->version);
|
||||
return B_ERROR;
|
||||
}
|
||||
if (status == B_OK) {
|
||||
_read->event = MS_READ_TOUCHPAD;
|
||||
_read->u.touchpad = event;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -785,6 +800,64 @@ elantech_process_packet_v4(elantech_cookie *cookie, touchpad_movement *_event,
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
elantech_process_packet_trackpoint(elantech_cookie *cookie, mouse_movement *_movement,
|
||||
uint8 packet[PS2_PACKET_ELANTECH])
|
||||
{
|
||||
/* 7 6 5 4 3 2 1 0 (LSB)
|
||||
* -------------------------------------------
|
||||
* ipacket[0]: 0 0 SY SX 0 M R L
|
||||
* ipacket[1]: ~SX 0 0 0 0 0 0 0
|
||||
* ipacket[2]: ~SY 0 0 0 0 0 0 0
|
||||
* ipacket[3]: 0 0 ~SY ~SX 0 1 1 0
|
||||
* ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0
|
||||
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
|
||||
* -------------------------------------------
|
||||
* X and Y are written in two's complement spread
|
||||
* over 9 bits with SX/SY the relative top bit and
|
||||
* X7..X0 and Y7..Y0 the lower bits.
|
||||
*/
|
||||
int32 x, y;
|
||||
uint8 buttons;
|
||||
|
||||
if (!(!(packet[0] & 0xC8) && !(packet[1] & 0x7F)
|
||||
&& !(packet[2] & 0x7F) && !(packet[3] & 0xC9)
|
||||
&& !(packet[0] & 0x10) != !(packet[1] & 0x80)
|
||||
&& !(packet[0] & 0x10) != !(packet[3] & 0x10)
|
||||
&& !(packet[0] & 0x20) != !(packet[2] & 0x80)
|
||||
&& !(packet[0] & 0x20) != !(packet[3] & 0x20)))
|
||||
return IGNORE_EVENT;
|
||||
|
||||
/*
|
||||
* This firmware misreport coordinates for trackpoint
|
||||
* occasionally. Discard packets outside of [-127, 127] range
|
||||
* to prevent cursor jumps.
|
||||
*/
|
||||
if (packet[4] == 0x80 || packet[5] == 0x80
|
||||
|| packet[1] >> 7 == packet[4] >> 7
|
||||
|| packet[2] >> 7 == packet[5] >> 7)
|
||||
return IGNORE_EVENT;
|
||||
|
||||
x = packet[4] - 0x100 + (packet[1] << 1);
|
||||
y = packet[5] - 0x100 + (packet[2] << 1);
|
||||
|
||||
buttons = packet[0] & 7;
|
||||
|
||||
mouse_movement movement = {
|
||||
.buttons = buttons,
|
||||
.xdelta = x,
|
||||
.ydelta = y,
|
||||
.timestamp = system_time(),
|
||||
.wheel_ydelta = 0,
|
||||
.wheel_xdelta = 0,
|
||||
};
|
||||
|
||||
*_movement = movement;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
synaptics_dev_send_command(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count)
|
||||
{
|
||||
@@ -1363,13 +1436,22 @@ elantech_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
|
||||
return user_memcpy(buffer, &gHardwareSpecs, sizeof(gHardwareSpecs));
|
||||
|
||||
case MS_READ_TOUCHPAD:
|
||||
TRACE("ELANTECH: MS_READ get event\n");
|
||||
TRACE("ELANTECH: MS_READ_TOUCHPAD get event\n");
|
||||
if (user_memcpy(&read.timeout, &(((touchpad_read*)buffer)->timeout),
|
||||
sizeof(bigtime_t)) != B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
if ((status = get_elantech_movement(cookie, &read.u.touchpad, read.timeout)) != B_OK)
|
||||
if ((status = get_elantech_movement(cookie, &read)) != B_OK) {
|
||||
TRACE("ELANTECH: ioctl error with status: %s\n", strerror(status));
|
||||
return status;
|
||||
read.event = MS_READ_TOUCHPAD;
|
||||
}
|
||||
#ifdef TRACE_PS2_ELANTECH
|
||||
if (read.event = MS_READ_TOUCHPAD) {
|
||||
TRACE("ELANTECH: ioctl touchpad fingers: 0x%x\n", (int)read.u.touchpad.fingers);
|
||||
TRACE("ELANTECH: ioctl touchpad buttons: %d\n", (int)read.u.touchpad.buttons);
|
||||
} else if (read.event = MS_READ) {
|
||||
TRACE("ELANTECH: ioctl mouse buttons: %d\n", (int)read.u.mouse.buttons);
|
||||
}
|
||||
#endif
|
||||
return user_memcpy(buffer, &read, sizeof(read));
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user