Input: bcm5974 - Add support for the Macbook 5 (Unibody)
This patch adds support for the new unibody Macbook, with physically integrated button and trackpad. Since the integrated button changes the logic for touch-and-click, a device capability bit mask is now reported in input_id.version, which can be picked up by user space via a EVIOCGID call. Signed-off-by: Henrik Rydberg <rydberg@euromail.se> Tested-by: David M. Lary <dmlary@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
committed by
Dmitry Torokhov
parent
6916d97f6e
commit
158e928741
@@ -51,6 +51,10 @@
|
|||||||
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
|
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
|
||||||
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
|
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
|
||||||
#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
|
#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
|
||||||
|
/* Macbook5,1 (unibody), aka wellspring3 */
|
||||||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
|
||||||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
|
||||||
|
#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
|
||||||
|
|
||||||
#define BCM5974_DEVICE(prod) { \
|
#define BCM5974_DEVICE(prod) { \
|
||||||
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
|
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
|
||||||
@@ -72,6 +76,10 @@ static const struct usb_device_id bcm5974_table[] = {
|
|||||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
|
||||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
|
||||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
|
||||||
|
/* Macbook5,1 */
|
||||||
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
|
||||||
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
|
||||||
|
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
|
||||||
/* Terminating entry */
|
/* Terminating entry */
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
@@ -98,11 +106,19 @@ struct bt_data {
|
|||||||
|
|
||||||
/* trackpad header types */
|
/* trackpad header types */
|
||||||
enum tp_type {
|
enum tp_type {
|
||||||
TYPE1 /* plain trackpad */
|
TYPE1, /* plain trackpad */
|
||||||
|
TYPE2 /* button integrated in trackpad */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* trackpad finger data offsets, le16-aligned */
|
/* trackpad finger data offsets, le16-aligned */
|
||||||
#define FINGER_TYPE1 (13 * sizeof(__le16))
|
#define FINGER_TYPE1 (13 * sizeof(__le16))
|
||||||
|
#define FINGER_TYPE2 (15 * sizeof(__le16))
|
||||||
|
|
||||||
|
/* trackpad button data offsets */
|
||||||
|
#define BUTTON_TYPE2 15
|
||||||
|
|
||||||
|
/* list of device capability bits */
|
||||||
|
#define HAS_INTEGRATED_BUTTON 1
|
||||||
|
|
||||||
/* trackpad finger structure, le16-aligned */
|
/* trackpad finger structure, le16-aligned */
|
||||||
struct tp_finger {
|
struct tp_finger {
|
||||||
@@ -135,6 +151,7 @@ struct bcm5974_param {
|
|||||||
/* device-specific configuration */
|
/* device-specific configuration */
|
||||||
struct bcm5974_config {
|
struct bcm5974_config {
|
||||||
int ansi, iso, jis; /* the product id of this device */
|
int ansi, iso, jis; /* the product id of this device */
|
||||||
|
int caps; /* device capability bitmask */
|
||||||
int bt_ep; /* the endpoint of the button interface */
|
int bt_ep; /* the endpoint of the button interface */
|
||||||
int bt_datalen; /* data length of the button interface */
|
int bt_datalen; /* data length of the button interface */
|
||||||
int tp_ep; /* the endpoint of the trackpad interface */
|
int tp_ep; /* the endpoint of the trackpad interface */
|
||||||
@@ -184,6 +201,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
|||||||
USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
|
USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
|
||||||
USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
|
USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
|
||||||
USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
|
USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
|
||||||
|
0,
|
||||||
0x84, sizeof(struct bt_data),
|
0x84, sizeof(struct bt_data),
|
||||||
0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
|
0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
|
||||||
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
|
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
|
||||||
@@ -195,6 +213,7 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
|||||||
USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
|
USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
|
||||||
USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
|
USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
|
||||||
USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
|
USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
|
||||||
|
0,
|
||||||
0x84, sizeof(struct bt_data),
|
0x84, sizeof(struct bt_data),
|
||||||
0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
|
0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
|
||||||
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
|
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
|
||||||
@@ -202,6 +221,18 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
|||||||
{ DIM_X, DIM_X / SN_COORD, -4824, 4824 },
|
{ DIM_X, DIM_X / SN_COORD, -4824, 4824 },
|
||||||
{ DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
|
{ DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI,
|
||||||
|
USB_DEVICE_ID_APPLE_WELLSPRING3_ISO,
|
||||||
|
USB_DEVICE_ID_APPLE_WELLSPRING3_JIS,
|
||||||
|
HAS_INTEGRATED_BUTTON,
|
||||||
|
0x84, sizeof(struct bt_data),
|
||||||
|
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
|
||||||
|
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
|
||||||
|
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
|
||||||
|
{ DIM_X, DIM_X / SN_COORD, -4460, 5166 },
|
||||||
|
{ DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
|
||||||
|
},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -281,7 +312,7 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||||||
const struct tp_finger *f;
|
const struct tp_finger *f;
|
||||||
struct input_dev *input = dev->input;
|
struct input_dev *input = dev->input;
|
||||||
int raw_p, raw_w, raw_x, raw_y, raw_n;
|
int raw_p, raw_w, raw_x, raw_y, raw_n;
|
||||||
int ptest = 0, origin = 0, nmin = 0, nmax = 0;
|
int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0;
|
||||||
int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
|
int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
|
||||||
|
|
||||||
if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
|
if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
|
||||||
@@ -304,6 +335,10 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||||||
|
|
||||||
ptest = int2bound(&c->p, raw_p);
|
ptest = int2bound(&c->p, raw_p);
|
||||||
origin = raw2int(f->origin);
|
origin = raw2int(f->origin);
|
||||||
|
|
||||||
|
/* set the integrated button if applicable */
|
||||||
|
if (c->tp_type == TYPE2)
|
||||||
|
ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* while tracking finger still valid, count all fingers */
|
/* while tracking finger still valid, count all fingers */
|
||||||
@@ -347,6 +382,10 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* type 2 reports button events via ibt only */
|
||||||
|
if (c->tp_type == TYPE2)
|
||||||
|
input_report_key(input, BTN_LEFT, ibt);
|
||||||
|
|
||||||
input_sync(input);
|
input_sync(input);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -656,6 +695,8 @@ static int bcm5974_probe(struct usb_interface *iface,
|
|||||||
input_dev->name = "bcm5974";
|
input_dev->name = "bcm5974";
|
||||||
input_dev->phys = dev->phys;
|
input_dev->phys = dev->phys;
|
||||||
usb_to_input_id(dev->udev, &input_dev->id);
|
usb_to_input_id(dev->udev, &input_dev->id);
|
||||||
|
/* report driver capabilities via the version field */
|
||||||
|
input_dev->id.version = cfg->caps;
|
||||||
input_dev->dev.parent = &iface->dev;
|
input_dev->dev.parent = &iface->dev;
|
||||||
|
|
||||||
input_set_drvdata(input_dev, dev);
|
input_set_drvdata(input_dev, dev);
|
||||||
|
Reference in New Issue
Block a user