Permalink
Browse files

bthidd: Add Apple Magic Trackpad evdev support

  • Loading branch information...
myfreeweb committed Dec 20, 2017
1 parent 2706f94 commit 0c06a324311309228a8e2def334c603a390fac4f
@@ -52,6 +52,15 @@
#include "bthidd.h"
#include "btuinput.h"
#define AMT_DIMENSION_X 13000.0f
#define AMT_MIN_X -2909
#define AMT_MAX_X 3167
#define AMT_RES_X ((AMT_MAX_X - AMT_MIN_X) / (AMT_DIMENSION_X / 100))
#define AMT_DIMENSION_Y 11000.0f
#define AMT_MIN_Y -2456
#define AMT_MAX_Y 2565
#define AMT_RES_Y ((AMT_MAX_Y - AMT_MIN_Y) / (AMT_DIMENSION_Y / 100))
static int16_t const mbuttons[8] = {
BTN_LEFT,
BTN_MIDDLE,
@@ -338,7 +347,7 @@ uinput_open_common(hid_device_p const p, bdaddr_p local, const uint8_t *name)
* TODO: bring in more feature detection code from ums
*/
int32_t
uinput_open_mouse(hid_device_p const p, bdaddr_p local)
uinput_open_mouse(hid_device_p const p, bdaddr_p local, int is_apple_trackpad)
{
size_t i;
int32_t fd;
@@ -348,21 +357,136 @@ uinput_open_mouse(hid_device_p const p, bdaddr_p local)
if ((fd = uinput_open_common(p, local, "Bluetooth Mouse")) < 0)
goto bail_out;
/* Advertise events and axes */
if (ioctl(fd, UI_SET_EVBIT, EV_SYN) < 0 ||
ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0 ||
ioctl(fd, UI_SET_EVBIT, EV_REL) < 0 ||
ioctl(fd, UI_SET_RELBIT, REL_X) < 0 ||
ioctl(fd, UI_SET_RELBIT, REL_Y) < 0 ||
(p->has_wheel && ioctl(fd, UI_SET_RELBIT, REL_WHEEL) < 0) ||
(p->has_hwheel && ioctl(fd, UI_SET_RELBIT, REL_HWHEEL) < 0))
goto bail_out;
/* Advertice multi-touch support */
if (is_apple_trackpad) {
if (ioctl(fd, UI_SET_EVBIT, EV_ABS) < 0 ||
ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0 ||
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT) < 0 ||
ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_FINGER) < 0 ||
ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_DOUBLETAP) < 0 ||
ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_TRIPLETAP) < 0 ||
ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_QUADTAP) < 0 ||
ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_QUINTTAP) < 0 ||
ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH) < 0 ||
ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_POINTER) < 0 ||
ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_BUTTONPAD) < 0)
goto bail_out;
struct uinput_abs_setup abs_x;
abs_x.code = ABS_X;
abs_x.absinfo.value = 0;
abs_x.absinfo.minimum = AMT_MIN_X;
abs_x.absinfo.maximum = AMT_MAX_X;
abs_x.absinfo.resolution = AMT_RES_X;
abs_x.absinfo.fuzz = 4;
abs_x.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_x) < 0)
goto bail_out;
struct uinput_abs_setup abs_y;
abs_y.code = ABS_Y;
abs_y.absinfo.value = 0;
abs_y.absinfo.minimum = AMT_MIN_Y;
abs_y.absinfo.maximum = AMT_MAX_Y;
abs_y.absinfo.resolution = AMT_RES_Y;
abs_y.absinfo.fuzz = 4;
abs_y.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_y) < 0)
goto bail_out;
struct uinput_abs_setup abs_x_mt;
abs_x_mt.code = ABS_MT_POSITION_X;
abs_x_mt.absinfo.value = 0;
abs_x_mt.absinfo.minimum = AMT_MIN_X;
abs_x_mt.absinfo.maximum = AMT_MAX_X;
abs_x_mt.absinfo.resolution = AMT_RES_X;
abs_x_mt.absinfo.fuzz = 4;
abs_x_mt.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_x_mt) < 0)
goto bail_out;
/* Advertise mouse buttons */
for (i = 0; i < nitems(mbuttons); i++)
if (ioctl(fd, UI_SET_KEYBIT, mbuttons[i]) < 0)
struct uinput_abs_setup abs_y_mt;
abs_y_mt.code = ABS_MT_POSITION_Y;
abs_y_mt.absinfo.value = 0;
abs_y_mt.absinfo.minimum = AMT_MIN_Y;
abs_y_mt.absinfo.maximum = AMT_MAX_Y;
abs_y_mt.absinfo.resolution = AMT_RES_Y;
abs_y_mt.absinfo.fuzz = 4;
abs_y_mt.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_y_mt) < 0)
goto bail_out;
struct uinput_abs_setup abs_slot;
abs_slot.code = ABS_MT_SLOT;
abs_slot.absinfo.value = 0;
abs_slot.absinfo.minimum = 0;
abs_slot.absinfo.maximum = 15;
abs_slot.absinfo.resolution = 0;
abs_slot.absinfo.fuzz = 0;
abs_slot.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_slot) < 0)
goto bail_out;
struct uinput_abs_setup abs_track;
abs_track.code = ABS_MT_TRACKING_ID;
abs_track.absinfo.value = 0;
abs_track.absinfo.minimum = 0;
abs_track.absinfo.maximum = 0xffff;
abs_track.absinfo.resolution = 0;
abs_track.absinfo.fuzz = 0;
abs_track.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_track) < 0)
goto bail_out;
struct uinput_abs_setup abs_touch_major;
abs_touch_major.code = ABS_MT_TOUCH_MAJOR;
abs_touch_major.absinfo.value = 0;
abs_touch_major.absinfo.minimum = 0;
abs_touch_major.absinfo.maximum = 255 << 2;
abs_touch_major.absinfo.resolution = 0;
abs_touch_major.absinfo.fuzz = 4;
abs_touch_major.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_touch_major) < 0)
goto bail_out;
struct uinput_abs_setup abs_touch_minor;
abs_touch_minor.code = ABS_MT_TOUCH_MINOR;
abs_touch_minor.absinfo.value = 0;
abs_touch_minor.absinfo.minimum = 0;
abs_touch_minor.absinfo.maximum = 255 << 2;
abs_touch_minor.absinfo.resolution = 0;
abs_touch_minor.absinfo.fuzz = 4;
abs_touch_minor.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_touch_minor) < 0)
goto bail_out;
struct uinput_abs_setup abs_orientation;
abs_orientation.code = ABS_MT_ORIENTATION;
abs_orientation.absinfo.value = 0;
abs_orientation.absinfo.minimum = -31;
abs_orientation.absinfo.maximum = 32;
abs_orientation.absinfo.resolution = 0;
abs_orientation.absinfo.fuzz = 1;
abs_orientation.absinfo.flat = 0;
if (ioctl(fd, UI_ABS_SETUP, &abs_orientation) < 0)
goto bail_out;
} else {
/* Advertise events and axes */
if (ioctl(fd, UI_SET_EVBIT, EV_SYN) < 0 ||
ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0 ||
ioctl(fd, UI_SET_EVBIT, EV_REL) < 0 ||
ioctl(fd, UI_SET_RELBIT, REL_X) < 0 ||
ioctl(fd, UI_SET_RELBIT, REL_Y) < 0 ||
(p->has_wheel && ioctl(fd, UI_SET_RELBIT, REL_WHEEL) < 0) ||
(p->has_hwheel && ioctl(fd, UI_SET_RELBIT, REL_HWHEEL) < 0))
goto bail_out;
/* Advertise mouse buttons */
for (i = 0; i < nitems(mbuttons); i++)
if (ioctl(fd, UI_SET_KEYBIT, mbuttons[i]) < 0)
goto bail_out;
}
if (ioctl(fd, UI_DEV_CREATE) >= 0)
return (fd); /* SUCCESS */
@@ -471,6 +595,17 @@ uinput_write_event(int32_t fd, uint16_t type, uint16_t code, int32_t value)
return (write(fd, &ie, sizeof(ie)));
}
int32_t
uinput_rep_sync(int32_t fd) {
assert(fd >= 0);
if (uinput_write_event(fd, EV_SYN, SYN_REPORT, 0) < 0)
return (-1);
return (0);
}
int32_t
uinput_rep_mouse(int32_t fd, int32_t x, int32_t y, int32_t z, int32_t t,
int32_t buttons, int32_t obuttons)
@@ -511,6 +646,96 @@ uinput_rep_mouse(int32_t fd, int32_t x, int32_t y, int32_t z, int32_t t,
return (0);
}
/*
* Translate and report trackpad multi-touch events
*/
int32_t
uinput_rep_multi_touch(int32_t fd, int32_t id, int32_t x, int32_t y,
int32_t orientation, int32_t touch_major, int32_t touch_minor, int32_t state)
{
assert(fd >= 0);
if (uinput_write_event(fd, EV_ABS, ABS_MT_SLOT, id) < 0)
return (-1);
if (state != 0) {
if (uinput_write_event(fd, EV_ABS, ABS_MT_TRACKING_ID, id) < 0)
return (-1);
if (uinput_write_event(fd, EV_ABS, ABS_MT_TOUCH_MAJOR, touch_major << 2) < 0)
return (-1);
if (uinput_write_event(fd, EV_ABS, ABS_MT_TOUCH_MINOR, touch_minor << 2) < 0)
return (-1);
if (uinput_write_event(fd, EV_ABS, ABS_MT_ORIENTATION, -orientation) < 0)
return (-1);
if (uinput_write_event(fd, EV_ABS, ABS_MT_POSITION_X, x) < 0)
return (-1);
if (uinput_write_event(fd, EV_ABS, ABS_MT_POSITION_Y, y) < 0)
return (-1);
} else {
if (uinput_write_event(fd, EV_ABS, ABS_MT_TRACKING_ID, -1) < 0)
return (-1);
}
return (0);
}
/*
* Translate and report trackpad single-touch events
*/
int32_t
uinput_rep_single_touch(int32_t fd, int32_t x, int32_t y, int32_t state)
{
assert(fd >= 0);
if (uinput_write_event(fd, EV_ABS, ABS_X, x) < 0)
return (-1);
if (uinput_write_event(fd, EV_ABS, ABS_Y, y) < 0)
return (-1);
if (uinput_write_event(fd, EV_KEY, BTN_TOUCH, state != 0) < 0)
return (-1);
return (0);
}
/*
* Translate and report trackpad finger count events
*/
static uint16_t fngmap[] = {
BTN_TOOL_FINGER,
BTN_TOOL_DOUBLETAP,
BTN_TOOL_TRIPLETAP,
BTN_TOOL_QUADTAP,
BTN_TOOL_QUINTTAP,
};
int32_t
uinput_rep_fingers(int32_t fd, int32_t nfingers)
{
assert(fd >= 0);
for (int i = 0; i < 5; i++)
if (uinput_write_event(fd, EV_KEY, fngmap[i], nfingers == i + 1) < 0)
return (-1);
return (0);
}
/*
* Translate and report trackpad (clickpad) click events
*/
int32_t
uinput_rep_click(int32_t fd, int32_t clicked)
{
assert(fd >= 0);
if (uinput_write_event(fd, EV_KEY, BTN_LEFT, clicked) < 0)
return (-1);
return (0);
}
/*
* Translate and report keyboard page key events
*/
@@ -29,10 +29,16 @@
#ifndef _UINPUT_H_
#define _UINPUT_H_
int32_t uinput_open_mouse(hid_device_p const d, bdaddr_p local);
int32_t uinput_open_mouse(hid_device_p const d, bdaddr_p local, int is_apple_trackpad);
int32_t uinput_open_keyboard(hid_device_p const d, bdaddr_p local);
int32_t uinput_rep_sync(int32_t fd);
int32_t uinput_rep_mouse(int32_t fd, int32_t x, int32_t y, int32_t z,
int32_t t, int32_t buttons, int32_t obuttons);
int32_t uinput_rep_multi_touch(int32_t fd, int32_t id, int32_t x, int32_t y,
int32_t orientation, int32_t touch_major, int32_t touch_minor, int32_t state);
int32_t uinput_rep_single_touch(int32_t fd, int32_t x, int32_t y, int32_t state);
int32_t uinput_rep_fingers(int32_t fd, int32_t nfingers);
int32_t uinput_rep_click(int32_t fd, int32_t clicked);
int32_t uinput_rep_key(int32_t fd, int32_t key, int32_t make);
int32_t uinput_rep_cons(int32_t fd, int32_t key, int32_t make);
int32_t uinput_rep_leds(int32_t fd, int state, int mask);
Oops, something went wrong.

0 comments on commit 0c06a32

Please sign in to comment.