ps/2 elantech: Initial cleanups and fixes to support input devices
- Add references for driver implementation.
References from FreeBSD 14.3, OpenBSD 7.8, Linux 6.17 sources
and Linux 4.16 documentation.
- Add pragma marks for easy navigation
- Add missing define to fetch firware info from hardware
- Reduce size of version field
- Update probe function to be able to enable supported devices
- Update open function to add missing v4 devices
- Fix enable_absolute_mode and use same snooze time as BSDs and Linux drivers
- Fix get_resolution_v4 and set sane defaults instead of failing with error
- Update license for ps2_elantech.{h,cpp}
Change-Id: I76fba3be04d7b940079fc78c3b7fe7d8bf8dfa06
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10011
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
a3f6c4d484
commit
5578783036
@@ -1,12 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013, Haiku, Inc.
|
* Copyright 2013-2025, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Hardware specs taken from the linux driver, thanks a lot!
|
* Hardware specs taken from the linux and BSDs drivers, thanks a lot!
|
||||||
* Based on ps2_alps.c
|
*
|
||||||
|
* References:
|
||||||
|
* - https://cgit.freebsd.org/src/tree/sys/dev/atkbdc/psm.c?h=releng/14.3
|
||||||
|
* - https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/dev/pckbc/?only_with_tag=OPENBSD_7_8_BASE
|
||||||
|
* - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/input/mouse/elantech.c?h=v6.17
|
||||||
|
* - https://www.kernel.org/doc/html/v4.16/input/devices/elantech.html
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Jérôme Duval <[email protected]>
|
* Jérôme Duval <[email protected]>
|
||||||
|
* Samuel Rodríguez Pérez <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -27,7 +33,6 @@
|
|||||||
# define TRACE(x...)
|
# define TRACE(x...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
const char* kElantechPath[4] = {
|
const char* kElantechPath[4] = {
|
||||||
"input/touchpad/ps2/elantech_0",
|
"input/touchpad/ps2/elantech_0",
|
||||||
"input/touchpad/ps2/elantech_1",
|
"input/touchpad/ps2/elantech_1",
|
||||||
@@ -41,13 +46,14 @@ const char* kElantechPath[4] = {
|
|||||||
#define ELANTECH_CMD_GET_CAPABILITIES 0x02
|
#define ELANTECH_CMD_GET_CAPABILITIES 0x02
|
||||||
#define ELANTECH_CMD_GET_SAMPLE 0x03
|
#define ELANTECH_CMD_GET_SAMPLE 0x03
|
||||||
#define ELANTECH_CMD_GET_RESOLUTION 0x04
|
#define ELANTECH_CMD_GET_RESOLUTION 0x04
|
||||||
|
#define ELANTECH_CMD_GET_ICBODY 0x05
|
||||||
|
|
||||||
|
|
||||||
#define ELANTECH_CMD_REGISTER_READ 0x10
|
#define ELANTECH_CMD_REGISTER_READ 0x10
|
||||||
#define ELANTECH_CMD_REGISTER_WRITE 0x11
|
#define ELANTECH_CMD_REGISTER_WRITE 0x11
|
||||||
#define ELANTECH_CMD_REGISTER_READWRITE 0x00
|
#define ELANTECH_CMD_REGISTER_READWRITE 0x00
|
||||||
#define ELANTECH_CMD_PS2_CUSTOM_CMD 0xf8
|
#define ELANTECH_CMD_PS2_CUSTOM_CMD 0xf8
|
||||||
|
|
||||||
|
|
||||||
// touchpad proportions
|
// touchpad proportions
|
||||||
#define EDGE_MOTION_WIDTH 55
|
#define EDGE_MOTION_WIDTH 55
|
||||||
|
|
||||||
@@ -94,7 +100,7 @@ get_elantech_movement(elantech_cookie *cookie, touchpad_movement *_event, bigtim
|
|||||||
TRACE("ELANTECH: bad crc buffer\n");
|
TRACE("ELANTECH: bad crc buffer\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
// https://www.kernel.org/doc/html/v4.16/input/devices/elantech.html
|
|
||||||
uint8 packet_type = packet[3] & 3;
|
uint8 packet_type = packet[3] & 3;
|
||||||
TRACE("ELANTECH: packet type %d\n", packet_type);
|
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",
|
||||||
@@ -180,6 +186,9 @@ elantech_dev_send_command(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - exported functions
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
probe_elantech(ps2_dev* dev)
|
probe_elantech(ps2_dev* dev)
|
||||||
{
|
{
|
||||||
@@ -214,22 +223,52 @@ probe_elantech(ps2_dev* dev)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 fwVersion = ((val[0] << 16) | (val[1] << 8) | val[2]);
|
||||||
|
bool v1 = fwVersion < 0x020030 || fwVersion == 0x020600;
|
||||||
|
bool v2 = (val[0] & 0xf) == 4 || ((val[0] & 0xf) == 2 && !v1);
|
||||||
|
bool v3 = (val[0] & 0xf) == 5;
|
||||||
|
bool v4 = (val[0] & 0xf) >= 6 && (val[0] & 0xf) <= 15;
|
||||||
|
|
||||||
if (val[0] == 0x0 || val[2] == 10 || val[2] == 20 || val[2] == 40
|
if (val[0] == 0x0 || val[2] == 10 || val[2] == 20 || val[2] == 40
|
||||||
|| val[2] == 60 || val[2] == 80 || val[2] == 100 || val[2] == 200) {
|
|| val[2] == 60 || val[2] == 80 || val[2] == 100 || val[2] == 200) {
|
||||||
TRACE("ELANTECH: not found (5)\n");
|
TRACE("ELANTECH: not found (5)\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("Elantech version %02X%02X%02X, under developement! Using fallback.\n",
|
// TODO: Update supported after testing all versions.
|
||||||
val[0], val[1], val[2]);
|
bool supported = !v4 || !v3 || !v2 || !v1;
|
||||||
|
|
||||||
|
if (supported && v3) {
|
||||||
|
uint8 samples[3];
|
||||||
|
if (elantech_dev_send_command(dev, ELANTECH_CMD_GET_SAMPLE, samples, 3) != B_OK) {
|
||||||
|
TRACE("ELANTECH: failed to query sample data\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samples[1] == 0x74) {
|
||||||
|
TRACE("ELANTECH: Absolute mode broken, forcing standard PS/2 protocol\n");
|
||||||
|
supported = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supported) {
|
||||||
|
INFO("Elantech version %02X%02X%02X detected.\n",
|
||||||
|
val[0], val[1], val[2]);
|
||||||
|
} else {
|
||||||
|
INFO("Elantech version %02X%02X%02X, under developement! Using fallback.\n",
|
||||||
|
val[0], val[1], val[2]);
|
||||||
|
}
|
||||||
|
|
||||||
dev->name = kElantechPath[dev->idx];
|
dev->name = kElantechPath[dev->idx];
|
||||||
dev->packet_size = PS2_PACKET_ELANTECH;
|
dev->packet_size = PS2_PACKET_ELANTECH;
|
||||||
|
|
||||||
return B_ERROR;
|
return supported ? B_OK : B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Setup functions
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
elantech_write_reg(elantech_cookie* cookie, uint8 reg, uint8 value)
|
elantech_write_reg(elantech_cookie* cookie, uint8 reg, uint8 value)
|
||||||
{
|
{
|
||||||
@@ -339,8 +378,8 @@ get_resolution_v4(elantech_cookie* cookie, uint32* x, uint32* y)
|
|||||||
if (elantech_dev_send_command(cookie->dev, ELANTECH_CMD_GET_RESOLUTION,
|
if (elantech_dev_send_command(cookie->dev, ELANTECH_CMD_GET_RESOLUTION,
|
||||||
val, 3) != B_OK)
|
val, 3) != B_OK)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
*x = (val[1] & 0xf) * 10 + 790;
|
*x = ((val[1] & 0xf) * 10 + 790) * 10 / 254;
|
||||||
*y = ((val[1] & 0xf) >> 4) * 10 + 790;
|
*y = (((val[1] & 0xf) >> 4) * 10 + 790) * 10 / 254;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,14 +455,14 @@ enable_absolute_mode(elantech_cookie* cookie)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cookie->version < 4) {
|
if (status == B_OK && cookie->version < 4) {
|
||||||
uint8 val;
|
uint8 val;
|
||||||
|
|
||||||
for (uint8 retry = 0; retry < 5; retry++) {
|
for (uint8 retry = 0; retry < 5; retry++) {
|
||||||
status = elantech_read_reg(cookie, 0x10, &val);
|
status = elantech_read_reg(cookie, 0x10, &val);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
break;
|
break;
|
||||||
snooze(100);
|
snooze(2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +470,9 @@ enable_absolute_mode(elantech_cookie* cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Device functions
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
elantech_open(const char *name, uint32 flags, void **_cookie)
|
elantech_open(const char *name, uint32 flags, void **_cookie)
|
||||||
{
|
{
|
||||||
@@ -502,8 +544,7 @@ elantech_open(const char *name, uint32 flags, void **_cookie)
|
|||||||
case 5:
|
case 5:
|
||||||
cookie->version = 3;
|
cookie->version = 3;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6 ... 15:
|
||||||
case 7:
|
|
||||||
cookie->version = 4;
|
cookie->version = 4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -541,9 +582,12 @@ elantech_open(const char *name, uint32 flags, void **_cookie)
|
|||||||
"-%" B_PRIu32 " (%" B_PRIu32 ")\n", x_min, x_max, y_min, y_max, width);
|
"-%" B_PRIu32 " (%" B_PRIu32 ")\n", x_min, x_max, y_min, y_max, width);
|
||||||
|
|
||||||
uint32 x_res, y_res;
|
uint32 x_res, y_res;
|
||||||
if (get_resolution_v4(cookie, &x_res, &y_res) != B_OK) {
|
x_res = 31;
|
||||||
TRACE("ELANTECH: get resolution failed!\n");
|
y_res = 31;
|
||||||
goto err4;
|
if (cookie->version == 4) {
|
||||||
|
if (get_resolution_v4(cookie, &x_res, &y_res) != B_OK) {
|
||||||
|
TRACE("ELANTECH: get resolution failed!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("ELANTECH: resolution x %" B_PRIu32 " y %" B_PRIu32 " (dpi)\n",
|
TRACE("ELANTECH: resolution x %" B_PRIu32 " y %" B_PRIu32 " (dpi)\n",
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013, Haiku, Inc.
|
* Copyright 2013-2025, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* The elantech_model_info struct and all the hardware specs are taken from the
|
* Hardware specs taken from the linux and BSDs drivers, thanks a lot!
|
||||||
* linux driver, thanks a lot!
|
*
|
||||||
|
* References:
|
||||||
|
* - https://cgit.freebsd.org/src/tree/sys/dev/atkbdc/psm.c?h=releng/14.3
|
||||||
|
* - https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/dev/pckbc/?only_with_tag=OPENBSD_7_8_BASE
|
||||||
|
* - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/input/mouse/elantech.c?h=v6.17
|
||||||
|
* - https://www.kernel.org/doc/html/v4.16/input/devices/elantech.html
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Jérôme Duval <[email protected]>
|
* Jérôme Duval <[email protected]>
|
||||||
|
* Samuel Rodríguez Pérez <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _PS2_ELANTECH_H
|
#ifndef _PS2_ELANTECH_H
|
||||||
#define _PS2_ELANTECH_H
|
#define _PS2_ELANTECH_H
|
||||||
|
|
||||||
@@ -25,7 +32,7 @@ typedef struct {
|
|||||||
struct packet_buffer* ring_buffer;
|
struct packet_buffer* ring_buffer;
|
||||||
size_t packet_index;
|
size_t packet_index;
|
||||||
|
|
||||||
uint32 version;
|
uint8 version;
|
||||||
uint32 fwVersion;
|
uint32 fwVersion;
|
||||||
|
|
||||||
uint32 x;
|
uint32 x;
|
||||||
|
|||||||
Reference in New Issue
Block a user