summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2024-01-15 13:27:21 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2024-01-15 13:27:21 +0000
commit416944548903d786b4841a2b8c615aa28202d902 (patch)
tree0a463b2598340e15f8914fc78cb84f36dc7c6f20 /sys/arch
parentf56d6fefdc6d5285d1cab101ccb013da51cf2cab (diff)
Fetch touchpad dimensions from firmware instead of hardcoding the values
for the original 13" M1 MacBook. ok mlarkin@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/arm64/dev/aplhidev.c114
1 files changed, 98 insertions, 16 deletions
diff --git a/sys/arch/arm64/dev/aplhidev.c b/sys/arch/arm64/dev/aplhidev.c
index db6feb6bcca..97d00a8878a 100644
--- a/sys/arch/arm64/dev/aplhidev.c
+++ b/sys/arch/arm64/dev/aplhidev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aplhidev.c,v 1.12 2023/07/02 21:44:04 bru Exp $ */
+/* $OpenBSD: aplhidev.c,v 1.13 2024/01/15 13:27:20 kettenis Exp $ */
/*
* Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
* Copyright (c) 2013-2014 joshua stein <jcs@openbsd.org>
@@ -62,6 +62,16 @@
#define APLHIDEV_SET_MODE 0x0252
#define APLHIDEV_MODE_HID 0x00
#define APLHIDEV_MODE_RAW 0x01
+#define APLHIDEV_GET_DIMENSIONS 0xd932
+
+struct aplhidev_dim {
+ uint32_t width;
+ uint32_t height;
+ int16_t x_min;
+ int16_t y_min;
+ int16_t x_max;
+ int16_t y_max;
+};
struct aplhidev_attach_args {
uint8_t aa_reportid;
@@ -144,6 +154,14 @@ struct aplhidev_softc {
struct device *sc_ms;
uint8_t sc_tpdesc[APLHIDEV_DESC_MAX];
size_t sc_tpdesclen;
+ uint8_t sc_dimdesc[APLHIDEV_DESC_MAX];
+ size_t sc_dimdesclen;
+ int sc_x_min;
+ int sc_x_max;
+ int sc_y_min;
+ int sc_y_max;
+ int sc_h_res;
+ int sc_v_res;
};
int aplhidev_match(struct device *, void *, void *);
@@ -161,6 +179,7 @@ void aplhidev_get_info(struct aplhidev_softc *);
void aplhidev_get_descriptor(struct aplhidev_softc *, uint8_t);
void aplhidev_set_leds(struct aplhidev_softc *, uint8_t);
void aplhidev_set_mode(struct aplhidev_softc *, uint8_t);
+void aplhidev_get_dimensions(struct aplhidev_softc *);
int aplhidev_intr(void *);
void aplkbd_intr(struct device *, uint8_t *, size_t);
@@ -183,6 +202,7 @@ aplhidev_attach(struct device *parent, struct device *self, void *aux)
struct aplhidev_softc *sc = (struct aplhidev_softc *)self;
struct spi_attach_args *sa = aux;
struct aplhidev_attach_args aa;
+ struct aplhidev_dim dim;
int retry;
sc->sc_spi_tag = sa->sa_tag;
@@ -248,8 +268,26 @@ aplhidev_attach(struct device *parent, struct device *self, void *aux)
break;
}
+ aplhidev_get_dimensions(sc);
+ for (retry = 10; retry > 0; retry--) {
+ aplhidev_intr(sc);
+ delay(1000);
+ if (sc->sc_dimdesclen > 0)
+ break;
+ }
+
printf("\n");
+ if (sc->sc_dimdesclen == sizeof(dim) + 1) {
+ memcpy(&dim, &sc->sc_dimdesc[1], sizeof(dim));
+ sc->sc_x_min = dim.x_min;
+ sc->sc_x_max = dim.x_max;
+ sc->sc_y_min = dim.y_min;
+ sc->sc_y_max = dim.y_max;
+ sc->sc_h_res = (100 * (dim.x_max - dim.x_min)) / dim.width;
+ sc->sc_v_res = (100 * (dim.y_max - dim.y_min)) / dim.height;
+ }
+
if (sc->sc_kbddesclen > 0) {
aa.aa_reportid = APLHIDEV_KBD_DEVICE;
aa.aa_desc = sc->sc_kbddesc;
@@ -406,6 +444,39 @@ aplhidev_set_mode(struct aplhidev_softc *sc, uint8_t mode)
delay(1000);
}
+void
+aplhidev_get_dimensions(struct aplhidev_softc *sc)
+{
+ struct aplhidev_spi_packet packet;
+ struct aplhidev_get_desc *msg;
+ struct aplhidev_spi_status status;
+
+ memset(&packet, 0, sizeof(packet));
+ packet.flags = APLHIDEV_WRITE_PACKET;
+ packet.device = APLHIDEV_TP_DEVICE;
+ packet.len = sizeof(*msg);
+
+ msg = (void *)&packet.data[0];
+ msg->hdr.type = APLHIDEV_GET_DIMENSIONS;
+ msg->hdr.device = 0;
+ msg->hdr.msgid = sc->sc_msgid++;
+ msg->hdr.cmdlen = 0;
+ msg->hdr.rsplen = APLHIDEV_DESC_MAX;
+ msg->crc = crc16(0, (void *)msg, sizeof(*msg) - 2);
+
+ packet.crc = crc16(0, (void *)&packet, sizeof(packet) - 2);
+
+ spi_acquire_bus(sc->sc_spi_tag, 0);
+ spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
+ spi_transfer(sc->sc_spi_tag, (char *)&packet, NULL, sizeof(packet),
+ SPI_KEEP_CS);
+ delay(100);
+ spi_read(sc->sc_spi_tag, (char *)&status, sizeof(status));
+ spi_release_bus(sc->sc_spi_tag, 0);
+
+ delay(1000);
+}
+
int
aplhidev_intr(void *arg)
{
@@ -476,6 +547,13 @@ aplhidev_intr(void *arg)
sc->sc_mode = APLHIDEV_MODE_RAW;
return 1;
}
+ if (packet.flags == APLHIDEV_WRITE_PACKET &&
+ packet.device == APLHIDEV_TP_DEVICE &&
+ hdr->type == APLHIDEV_GET_DIMENSIONS) {
+ memcpy(sc->sc_dimdesc, &packet.data[8], hdr->cmdlen);
+ sc->sc_dimdesclen = hdr->cmdlen;
+ return 1;
+ }
/* Valid, but unrecognized packet; ignore for now. */
return 1;
@@ -688,17 +766,18 @@ static struct wsmouse_param aplms_wsmousecfg[] = {
};
struct aplms_softc {
- struct device sc_dev;
- struct device *sc_wsmousedev;
+ struct device sc_dev;
+ struct aplhidev_softc *sc_hidev;
+ struct device *sc_wsmousedev;
- int sc_enabled;
+ int sc_enabled;
- int tp_offset;
- int tp_fingerpad;
+ int tp_offset;
+ int tp_fingerpad;
- struct mtpoint frame[UBCMTP_MAX_FINGERS];
- int contacts;
- int btn;
+ struct mtpoint frame[UBCMTP_MAX_FINGERS];
+ int contacts;
+ int btn;
};
int aplms_enable(void *);
@@ -738,6 +817,8 @@ aplms_attach(struct device *parent, struct device *self, void *aux)
struct aplms_softc *sc = (struct aplms_softc *)self;
struct wsmousedev_attach_args aa;
+ sc->sc_hidev = (struct aplhidev_softc *)parent;
+
printf("\n");
sc->tp_offset = UBCMTP_TYPE4_TPOFF;
@@ -756,13 +837,14 @@ aplms_configure(struct aplms_softc *sc)
{
struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev);
- /* The values below are for the MacBookPro17,1 */
hw->type = WSMOUSE_TYPE_TOUCHPAD;
hw->hw_type = WSMOUSEHW_CLICKPAD;
- hw->x_min = -6046;
- hw->x_max = 6536;
- hw->y_min = -164;
- hw->y_max = 7439;
+ hw->x_min = sc->sc_hidev->sc_x_min;
+ hw->x_max = sc->sc_hidev->sc_x_max;
+ hw->y_min = sc->sc_hidev->sc_y_min;
+ hw->y_max = sc->sc_hidev->sc_y_max;
+ hw->h_res = sc->sc_hidev->sc_h_res;
+ hw->v_res = sc->sc_hidev->sc_v_res;
hw->mt_slots = UBCMTP_MAX_FINGERS;
hw->flags = WSMOUSEHW_MT_TRACKING;
@@ -846,8 +928,8 @@ aplms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
wsmc->miny = hw->y_min;
wsmc->maxy = hw->y_max;
wsmc->swapxy = 0;
- wsmc->resx = 0;
- wsmc->resy = 0;
+ wsmc->resx = hw->h_res;
+ wsmc->resy = hw->v_res;
break;
case WSMOUSEIO_SETMODE: