* [PATCH 14/14] alps: Add support for v7 devices
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede
In-Reply-To: <1404919459-23561-1-git-send-email-hdegoede@redhat.com>
From: Yunkang Tang <yunkang.tang@cn.alps.com>
Such as found on the new Toshiba Portégé Z30-A and Z40-A.
Signed-off-by: Yunkang Tang <yunkang.tang@cn.alps.com>
[hdegoede@redhat.com: Remove softbutton handling, this is done in userspace]
[hdegoede@redhat.com: Report INPUT_PROP_BUTTONPAD]
[hdegoede@redhat.com: Do not report fake PRESSURE, reporting BTN_TOUCH is
enough]
[hdegoede@redhat.com: Various cleanups / refactoring]
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/input/mouse/alps.c | 257 ++++++++++++++++++++++++++++++++++++++++++++-
drivers/input/mouse/alps.h | 18 ++++
2 files changed, 272 insertions(+), 3 deletions(-)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index ad3a708..8b9b4b0 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -100,6 +100,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
6-byte ALPS packet */
#define ALPS_IS_RUSHMORE 0x100 /* device is a rushmore */
+#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -845,6 +846,177 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
alps_report_semi_mt_data(psmouse, f->fingers);
}
+static bool alps_is_valid_package_v7(struct psmouse *psmouse)
+{
+ if ((psmouse->pktcnt == 3) && ((psmouse->packet[2] & 0x40) != 0x40))
+ return false;
+ if ((psmouse->pktcnt == 4) && ((psmouse->packet[3] & 0x48) != 0x48))
+ return false;
+ if ((psmouse->pktcnt == 6) && ((psmouse->packet[5] & 0x40) != 0x0))
+ return false;
+ return true;
+}
+
+static unsigned char alps_get_packet_id_v7(char *byte)
+{
+ unsigned char packet_id;
+
+ if (byte[4] & 0x40)
+ packet_id = V7_PACKET_ID_TWO;
+ else if (byte[4] & 0x01)
+ packet_id = V7_PACKET_ID_MULTI;
+ else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
+ packet_id = V7_PACKET_ID_NEW;
+ else if (byte[1] == 0x00 && byte[4] == 0x00)
+ packet_id = V7_PACKET_ID_IDLE;
+ else
+ packet_id = V7_PACKET_ID_UNKNOWN;
+
+ return packet_id;
+}
+
+static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
+ unsigned char *pkt,
+ unsigned char pkt_id)
+{
+ mt[0].x = ((pkt[2] & 0x80) << 4);
+ mt[0].x |= ((pkt[2] & 0x3F) << 5);
+ mt[0].x |= ((pkt[3] & 0x30) >> 1);
+ mt[0].x |= (pkt[3] & 0x07);
+ mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
+
+ mt[1].x = ((pkt[3] & 0x80) << 4);
+ mt[1].x |= ((pkt[4] & 0x80) << 3);
+ mt[1].x |= ((pkt[4] & 0x3F) << 4);
+ mt[1].y = ((pkt[5] & 0x80) << 3);
+ mt[1].y |= ((pkt[5] & 0x3F) << 4);
+
+ if (pkt_id == V7_PACKET_ID_TWO) {
+ mt[1].x &= ~0x000F;
+ mt[1].y |= 0x000F;
+ } else if (pkt_id == V7_PACKET_ID_MULTI) {
+ mt[1].x &= ~0x003F;
+ mt[1].y &= ~0x0020;
+ mt[1].y |= ((pkt[4] & 0x02) << 4);
+ mt[1].y |= 0x001F;
+ } else if (pkt_id == V7_PACKET_ID_NEW) {
+ mt[1].x &= ~0x003F;
+ mt[1].x |= (pkt[0] & 0x20);
+ mt[1].y |= 0x000F;
+ }
+
+ mt[0].y = 0x7FF - mt[0].y;
+ mt[1].y = 0x7FF - mt[1].y;
+}
+
+static int alps_get_mt_count(struct input_mt_pos *mt)
+{
+ int i;
+
+ for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++)
+ ;
+
+ return i;
+}
+
+static int alps_decode_packet_v7(struct alps_fields *f,
+ unsigned char *p,
+ struct psmouse *psmouse)
+{
+ unsigned char pkt_id;
+
+ pkt_id = alps_get_packet_id_v7(p);
+ if (pkt_id == V7_PACKET_ID_IDLE)
+ return 0;
+ if (pkt_id == V7_PACKET_ID_UNKNOWN)
+ return -1;
+
+ alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
+
+ if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) {
+ f->left = (p[0] & 0x80) >> 7;
+ f->right = (p[0] & 0x20) >> 5;
+ f->middle = (p[0] & 0x10) >> 4;
+ }
+
+ if (pkt_id == V7_PACKET_ID_TWO)
+ f->fingers = alps_get_mt_count(f->mt);
+ else if (pkt_id == V7_PACKET_ID_MULTI)
+ f->fingers = 3 + (p[5] & 0x03);
+
+ return 0;
+}
+
+static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
+{
+ struct alps_data *priv = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+ struct input_dev *dev2 = priv->dev2;
+ int x, y, z, left, right, middle;
+
+ /*
+ * b7 b6 b5 b4 b3 b2 b1 b0
+ * Byte0 0 1 0 0 1 0 0 0
+ * Byte1 1 1 * * 1 M R L
+ * Byte2 X7 1 X5 X4 X3 X2 X1 X0
+ * Byte3 Z6 1 Y6 X6 1 Y2 Y1 Y0
+ * Byte4 Y7 0 Y5 Y4 Y3 1 1 0
+ * Byte5 T&P 0 Z5 Z4 Z3 Z2 Z1 Z0
+ * M / R / L: Middle / Right / Left button
+ */
+
+ x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
+ y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
+ ((packet[3] & 0x20) << 1);
+ z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
+
+ left = (packet[1] & 0x01);
+ right = (packet[1] & 0x02) >> 1;
+ middle = (packet[1] & 0x04) >> 2;
+
+ /* Divide 2 since trackpoint's speed is too fast */
+ input_report_rel(dev2, REL_X, (char)x / 2);
+ input_report_rel(dev2, REL_Y, -((char)y / 2));
+
+ input_report_key(dev2, BTN_LEFT, left);
+ input_report_key(dev2, BTN_RIGHT, right);
+ input_report_key(dev2, BTN_MIDDLE, middle);
+
+ input_sync(dev2);
+}
+
+static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
+{
+ struct alps_data *priv = psmouse->private;
+ struct input_dev *dev = psmouse->dev;
+ struct alps_fields *f = &priv->f;
+
+ memset(f, 0, sizeof(*f));
+
+ if (priv->decode_fields(f, psmouse->packet, psmouse))
+ return;
+
+ alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
+
+ input_mt_report_finger_count(dev, f->fingers);
+
+ input_report_key(dev, BTN_LEFT, f->left);
+ input_report_key(dev, BTN_RIGHT, f->right);
+ input_report_key(dev, BTN_MIDDLE, f->middle);
+
+ input_sync(dev);
+}
+
+static void alps_process_packet_v7(struct psmouse *psmouse)
+{
+ unsigned char *packet = psmouse->packet;
+
+ if ((packet[0] == 0x48) && ((packet[4] & 0x47) == 0x06))
+ alps_process_trackstick_packet_v7(psmouse);
+ else
+ alps_process_touchpad_packet_v7(psmouse);
+}
+
static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
unsigned char packet[],
bool report_buttons)
@@ -1009,6 +1181,14 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
return PSMOUSE_BAD_DATA;
}
+ if (priv->proto_version == ALPS_PROTO_V7 &&
+ !alps_is_valid_package_v7(psmouse)) {
+ psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
+ psmouse->pktcnt - 1,
+ psmouse->packet[psmouse->pktcnt - 1]);
+ return PSMOUSE_BAD_DATA;
+ }
+
if (psmouse->pktcnt == psmouse->pktsize) {
priv->process_packet(psmouse);
return PSMOUSE_FULL_PACKET;
@@ -1121,6 +1301,22 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
return 0;
}
+static int alps_check_valid_firmware_id(unsigned char id[])
+{
+ int valid = 1;
+
+ if (id[0] == 0x73)
+ valid = 1;
+ else if (id[0] == 0x88) {
+ if ((id[1] == 0x07) ||
+ (id[1] == 0x08) ||
+ ((id[1] & 0xf0) == 0xB0))
+ valid = 1;
+ }
+
+ return valid;
+}
+
static int alps_enter_command_mode(struct psmouse *psmouse)
{
unsigned char param[4];
@@ -1130,8 +1326,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse)
return -1;
}
- if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
- param[0] != 0x73) {
+ if (!alps_check_valid_firmware_id(param)) {
psmouse_dbg(psmouse,
"unknown response while entering command mode\n");
return -1;
@@ -1785,6 +1980,32 @@ static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
return 0;
}
+static int alps_hw_init_v7(struct psmouse *psmouse)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ int reg_val, ret = -1;
+
+ if (alps_enter_command_mode(psmouse) ||
+ alps_command_mode_read_reg(psmouse, 0xc2d9) == -1)
+ goto error;
+
+ if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
+ goto error;
+
+ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
+ if (reg_val == -1)
+ goto error;
+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
+ goto error;
+
+ alps_exit_command_mode(psmouse);
+ return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+
+error:
+ alps_exit_command_mode(psmouse);
+ return ret;
+}
+
static void alps_set_defaults(struct alps_data *priv)
{
priv->byte0 = 0x8f;
@@ -1843,6 +2064,21 @@ static void alps_set_defaults(struct alps_data *priv)
priv->x_max = 2047;
priv->y_max = 1535;
break;
+ case ALPS_PROTO_V7:
+ priv->hw_init = alps_hw_init_v7;
+ priv->process_packet = alps_process_packet_v7;
+ priv->decode_fields = alps_decode_packet_v7;
+ priv->set_abs_params = alps_set_abs_params_mt;
+ priv->nibble_commands = alps_v3_nibble_commands;
+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
+ priv->x_max = 0xfff;
+ priv->y_max = 0x7ff;
+ priv->byte0 = 0x48;
+ priv->mask0 = 0x48;
+
+ if (priv->fw_ver[1] != 0xba)
+ priv->flags |= ALPS_BUTTONPAD;
+ break;
}
}
@@ -1914,6 +2150,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
return -EIO;
else
return 0;
+ } else if (ec[0] == 0x88 &&
+ ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
+ priv->proto_version = ALPS_PROTO_V7;
+ alps_set_defaults(priv);
+
+ return 0;
} else if (ec[0] == 0x88 && ec[1] == 0x08) {
priv->proto_version = ALPS_PROTO_V3;
alps_set_defaults(priv);
@@ -1985,6 +2227,10 @@ static void alps_set_abs_params_mt(struct alps_data *priv,
set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
+
+ /* V7 is real multi-touch */
+ if (priv->proto_version == ALPS_PROTO_V7)
+ clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
}
int alps_init(struct psmouse *psmouse)
@@ -2030,7 +2276,9 @@ int alps_init(struct psmouse *psmouse)
dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
priv->set_abs_params(priv, dev1);
- input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
+ /* No pressure on V7 */
+ if (priv->proto_version != ALPS_PROTO_V7)
+ input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
if (priv->flags & ALPS_WHEEL) {
dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
@@ -2047,6 +2295,9 @@ int alps_init(struct psmouse *psmouse)
dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
+ } else if (priv->flags & ALPS_BUTTONPAD) {
+ set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit);
+ clear_bit(BTN_RIGHT, dev1->keybit);
} else {
dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
}
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index e3d0f09..a98ac9b 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -20,6 +20,7 @@
#define ALPS_PROTO_V4 4
#define ALPS_PROTO_V5 5
#define ALPS_PROTO_V6 6
+#define ALPS_PROTO_V7 7 /* t3btl t4s */
#define MAX_TOUCHES 2
@@ -27,6 +28,23 @@
#define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */
#define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */
+/*
+ * enum V7_PACKET_ID - defines the packet type for V7
+ * V7_PACKET_ID_IDLE: There's no finger and no button activity.
+ * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad
+ * or there's button activities.
+ * V7_PACKET_ID_MULTI: There are at least three non-resting fingers.
+ * V7_PACKET_ID_NEW: The finger position in slot is not continues from
+ * previous packet.
+*/
+enum V7_PACKET_ID {
+ V7_PACKET_ID_IDLE,
+ V7_PACKET_ID_TWO,
+ V7_PACKET_ID_MULTI,
+ V7_PACKET_ID_NEW,
+ V7_PACKET_ID_UNKNOWN,
+};
+
/**
* struct alps_model_info - touchpad ID table
* @signature: E7 response string to match.
--
2.0.0
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 13/14] alps: Cache firmware version
From: Hans de Goede @ 2014-07-09 15:24 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input, Hans de Goede
In-Reply-To: <1404919459-23561-1-git-send-email-hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/input/mouse/alps.c | 3 +++
drivers/input/mouse/alps.h | 2 ++
2 files changed, 5 insertions(+)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 140471d..ad3a708 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1901,6 +1901,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
alps_exit_command_mode(psmouse))
return -EIO;
+ /* Save the Firmware version */
+ memcpy(priv->fw_ver, ec, 3);
+
if (alps_match_table(psmouse, priv, e7, ec) == 0) {
return 0;
} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 17e3ae3..e3d0f09 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -124,6 +124,7 @@ struct alps_fields {
* known format for this model. The first byte of the report, ANDed with
* mask0, should match byte0.
* @mask0: The mask used to check the first byte of the report.
+ * @fw_ver: cached copy of firmware version (EC report)
* @flags: Additional device capabilities (passthrough port, trackstick, etc.).
* @x_max: Largest possible X position value.
* @y_max: Largest possible Y position value.
@@ -149,6 +150,7 @@ struct alps_data {
int addr_command;
unsigned char proto_version;
unsigned char byte0, mask0;
+ unsigned char fw_ver[3];
int flags;
int x_max;
int y_max;
--
2.0.0
^ permalink raw reply related
* Re: [PATCH 1/1] drivers/input/touchscreen/edt-ft5x06.c: remove unnecessary null test before debugfs_remove_recursive
From: Dmitry Torokhov @ 2014-07-09 16:46 UTC (permalink / raw)
To: Fabian Frederick; +Cc: linux-kernel, Henrik Rydberg, linux-input
In-Reply-To: <1403901512-9710-1-git-send-email-fabf@skynet.be>
On Fri, Jun 27, 2014 at 10:38:32PM +0200, Fabian Frederick wrote:
> Fix checkpatch warning:
> "WARNING: debugfs_remove_recursive(NULL) is safe this check is probably not required"
>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Henrik Rydberg <rydberg@euromail.se>
> Cc: linux-input@vger.kernel.org
> Signed-off-by: Fabian Frederick <fabf@skynet.be>
Applied, thank you.
> ---
> drivers/input/touchscreen/edt-ft5x06.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
> index d4f3399..5a6d50c 100644
> --- a/drivers/input/touchscreen/edt-ft5x06.c
> +++ b/drivers/input/touchscreen/edt-ft5x06.c
> @@ -733,8 +733,7 @@ edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
> static void
> edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
> {
> - if (tsdata->debug_dir)
> - debugfs_remove_recursive(tsdata->debug_dir);
> + debugfs_remove_recursive(tsdata->debug_dir);
> kfree(tsdata->raw_buffer);
> }
>
> --
> 1.8.4.5
>
--
Dmitry
^ permalink raw reply
* Re: [PATCH v4 2/6] input: touchscreen: imx25 tcq driver
From: Dmitry Torokhov @ 2014-07-09 16:47 UTC (permalink / raw)
To: Denis Carikli
Cc: Shawn Guo, Samuel Ortiz, Jonathan Cameron, Fabio Estevam,
Peter Meerwald, Hartmut Knaack, Eric Bénard, Sascha Hauer,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Lee Jones,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-iio-u79uwXL29TY76Z2rM5mHXA, Lars-Peter Clausen,
Markus Pargmann, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala
In-Reply-To: <1403621195-9622-2-git-send-email-denis-fO0SIAKYzcbQT0dZR+AlfA@public.gmane.org>
On Tue, Jun 24, 2014 at 04:46:31PM +0200, Denis Carikli wrote:
> From: Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>
> This is a driver for the imx25 ADC/TSC module. It controls the
> touchscreen conversion queue and creates a touchscreen input device.
> The driver currently only supports 4 wire touchscreens. The driver uses
> a simple conversion queue of precharge, touch detection, X measurement,
> Y measurement, precharge and another touch detection.
>
> This driver uses the regmap from the parent to setup some touch specific
> settings in the core driver and setup a idle configuration with touch
> detection.
>
> Signed-off-by: Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Signed-off-by: Denis Carikli <denis-fO0SIAKYzcbQT0dZR+AlfA@public.gmane.org>
Acked-by: Dmitry Torokhov <dtor-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
> ---
> Changelog v3->v4:
> - Reworked the probe to handle the IRQ and the clock removal order correctly.
> - Some code and style cleanups.
>
> Changelog v2->v3:
> - Fixed the 'Senitel' typo.
> - Fixed input_report_key to report 1 for BTN_TOUCH events.
> - Removed useless explicit casts.
> - Also disable clock when devm_request_threaded_irq failed.
> ---
> .../bindings/input/touchscreen/fsl-mx25-tcq.txt | 29 +
> drivers/input/touchscreen/Kconfig | 6 +
> drivers/input/touchscreen/Makefile | 1 +
> drivers/input/touchscreen/fsl-imx25-tcq.c | 584 ++++++++++++++++++++
> 4 files changed, 620 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt
> create mode 100644 drivers/input/touchscreen/fsl-imx25-tcq.c
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt b/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt
> new file mode 100644
> index 0000000..4214a99
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt
> @@ -0,0 +1,29 @@
> +Freescale mx25 TS conversion queue module
> +
> +mx25 touchscreen conversion queue module which controls the ADC unit of the
> +mx25 for attached touchscreens.
> +
> +Required properties:
> + - compatible: Should be "fsl,imx25-tcq".
> + - reg: Memory range of the device.
> + - interrupts: Should be the interrupt number associated with this module within
> + the tscadc unit (<0>).
> + - interrupt-parent: Should be a phandle to the tscadc unit.
> + - fsl,wires: Should be '<4>' or '<5>'
> +
> +Optional properties:
> + - fsl,pen-debounce: Pen debounce time.
> + - fsl,pen-threshold: Pen-down threshold for the touchscreen.
> + - fsl,settling-time: Settling time in nanoseconds.
> +
> +This device includes two conversion queues which can be added as subnodes.
> +The first queue is for the touchscreen, the second for general purpose ADC.
> +
> +Example:
> + tsc: tcq@50030400 {
> + compatible = "fsl,imx25-tcq";
> + reg = <0x50030400 0x60>;
> + interrupt-parent = <&tscadc>;
> + interrupts = <0>;
> + fsl,wires = <4>;
> + };
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index a23a94b..a2290b9 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -699,6 +699,12 @@ config TOUCHSCREEN_USB_COMPOSITE
> To compile this driver as a module, choose M here: the
> module will be called usbtouchscreen.
>
> +config TOUCHSCREEN_MX25
> + tristate "Freescale i.MX25 touchscreen input driver"
> + depends on MFD_MX25_TSADC
> + help
> + Enable support for touchscreen connected to your i.MX25.
> +
> config TOUCHSCREEN_MC13783
> tristate "Freescale MC13783 touchscreen input driver"
> depends on MFD_MC13XXX
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 126479d..537d591 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
> obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
> obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
> obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
> +obj-$(CONFIG_TOUCHSCREEN_MX25) += fsl-imx25-tcq.o
> obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
> obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
> obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
> diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c
> new file mode 100644
> index 0000000..5ebeff8
> --- /dev/null
> +++ b/drivers/input/touchscreen/fsl-imx25-tcq.c
> @@ -0,0 +1,584 @@
> +/*
> + * Copyright 2014 Markus Pargmann, Pengutronix <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> + * Based on driver from 2011:
> + * Juergen Beisert, Pengutronix <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + *
> + * This is the driver for the imx25 TCQ (Touchscreen Conversion Queue)
> + * connected to the imx25 ADC.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/input.h>
> +#include <linux/mfd/imx25-tsadc.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +static const char mx25_tcq_name[] = "mx25-tcq";
> +
> +enum mx25_tcq_mode {
> + MX25_TS_4WIRE,
> +};
> +
> +struct mx25_tcq_priv {
> + struct regmap *regs;
> + struct regmap *core_regs;
> + struct input_dev *idev;
> + enum mx25_tcq_mode mode;
> + unsigned int pen_threshold;
> + unsigned int sample_count;
> + unsigned int expected_samples;
> + unsigned int pen_debounce;
> + unsigned int settling_time;
> + struct clk *clk;
> + int irq;
> +};
> +
> +static struct regmap_config mx25_tcq_regconfig = {
> + .fast_io = true,
> + .max_register = 0x5c,
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +static struct of_device_id mx25_tcq_ids[] = {
> + { .compatible = "fsl,imx25-tcq", },
> + { /* Sentinel */ }
> +};
> +
> +#define TSC_4WIRE_PRE_INDEX 0
> +#define TSC_4WIRE_X_INDEX 1
> +#define TSC_4WIRE_Y_INDEX 2
> +#define TSC_4WIRE_POST_INDEX 3
> +#define TSC_4WIRE_LEAVE 4
> +
> +#define MX25_TSC_DEF_THRESHOLD 80
> +#define TSC_MAX_SAMPLES 16
> +
> +
> +enum mx25_adc_configurations {
> + MX25_CFG_PRECHARGE = 0,
> + MX25_CFG_TOUCH_DETECT,
> + MX25_CFG_X_MEASUREMENT,
> + MX25_CFG_Y_MEASUREMENT,
> +};
> +
> +#define MX25_PRECHARGE_VALUE (\
> + MX25_ADCQ_CFG_YPLL_OFF | \
> + MX25_ADCQ_CFG_XNUR_OFF | \
> + MX25_ADCQ_CFG_XPUL_HIGH | \
> + MX25_ADCQ_CFG_REFP_INT | \
> + MX25_ADCQ_CFG_IN_XP | \
> + MX25_ADCQ_CFG_REFN_NGND2 | \
> + MX25_ADCQ_CFG_IGS)
> +
> +#define MX25_TOUCH_DETECT_VALUE (\
> + MX25_ADCQ_CFG_YNLR | \
> + MX25_ADCQ_CFG_YPLL_OFF | \
> + MX25_ADCQ_CFG_XNUR_OFF | \
> + MX25_ADCQ_CFG_XPUL_OFF | \
> + MX25_ADCQ_CFG_REFP_INT | \
> + MX25_ADCQ_CFG_IN_XP | \
> + MX25_ADCQ_CFG_REFN_NGND2 | \
> + MX25_ADCQ_CFG_PENIACK)
> +
> +static void imx25_setup_queue_cfgs(struct mx25_tcq_priv *priv,
> + unsigned int settling_time)
> +{
> + u32 precharge_cfg =
> + MX25_PRECHARGE_VALUE |
> + MX25_ADCQ_CFG_SETTLING_TIME(settling_time);
> + u32 touch_detect_cfg =
> + MX25_TOUCH_DETECT_VALUE |
> + MX25_ADCQ_CFG_NOS(1) |
> + MX25_ADCQ_CFG_SETTLING_TIME(settling_time);
> +
> + regmap_write(priv->core_regs, MX25_TSC_TICR, precharge_cfg);
> +
> + /* PRECHARGE */
> + regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_PRECHARGE),
> + precharge_cfg);
> +
> + /* TOUCH_DETECT */
> + regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_TOUCH_DETECT),
> + touch_detect_cfg);
> +
> + /* X Measurement */
> + regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_X_MEASUREMENT),
> + MX25_ADCQ_CFG_YPLL_OFF |
> + MX25_ADCQ_CFG_XNUR_LOW |
> + MX25_ADCQ_CFG_XPUL_HIGH |
> + MX25_ADCQ_CFG_REFP_XP |
> + MX25_ADCQ_CFG_IN_YP |
> + MX25_ADCQ_CFG_REFN_XN |
> + MX25_ADCQ_CFG_NOS(priv->sample_count) |
> + MX25_ADCQ_CFG_SETTLING_TIME(settling_time));
> +
> + /* Y Measurement */
> + regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_Y_MEASUREMENT),
> + MX25_ADCQ_CFG_YNLR |
> + MX25_ADCQ_CFG_YPLL_HIGH |
> + MX25_ADCQ_CFG_XNUR_OFF |
> + MX25_ADCQ_CFG_XPUL_OFF |
> + MX25_ADCQ_CFG_REFP_YP |
> + MX25_ADCQ_CFG_IN_XP |
> + MX25_ADCQ_CFG_REFN_YN |
> + MX25_ADCQ_CFG_NOS(priv->sample_count) |
> + MX25_ADCQ_CFG_SETTLING_TIME(settling_time));
> +
> + /* Enable the touch detection right now */
> + regmap_write(priv->core_regs, MX25_TSC_TICR, touch_detect_cfg |
> + MX25_ADCQ_CFG_IGS);
> +}
> +
> +static int imx25_setup_queue_4wire(struct mx25_tcq_priv *priv,
> + unsigned settling_time, int *items)
> +{
> + imx25_setup_queue_cfgs(priv, settling_time);
> +
> + /* Setup the conversion queue */
> + regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0,
> + MX25_ADCQ_ITEM(0, MX25_CFG_PRECHARGE) |
> + MX25_ADCQ_ITEM(1, MX25_CFG_TOUCH_DETECT) |
> + MX25_ADCQ_ITEM(2, MX25_CFG_X_MEASUREMENT) |
> + MX25_ADCQ_ITEM(3, MX25_CFG_Y_MEASUREMENT) |
> + MX25_ADCQ_ITEM(4, MX25_CFG_PRECHARGE) |
> + MX25_ADCQ_ITEM(5, MX25_CFG_TOUCH_DETECT));
> +
> + /* We measure X/Y with 'sample_count' number of samples and execute a
> + * touch detection twice, with 1 sample each */
> + priv->expected_samples = priv->sample_count * 2 + 2;
> + *items = 6;
> +
> + return 0;
> +}
> +
> +static void mx25_tcq_disable_touch_irq(struct mx25_tcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK,
> + MX25_ADCQ_CR_PDMSK);
> +}
> +
> +static void mx25_tcq_enable_touch_irq(struct mx25_tcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK, 0);
> +}
> +
> +static void mx25_tcq_disable_fifo_irq(struct mx25_tcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_FDRY_IRQ,
> + MX25_ADCQ_MR_FDRY_IRQ);
> +}
> +
> +static void mx25_tcq_enable_fifo_irq(struct mx25_tcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_FDRY_IRQ, 0);
> +}
> +
> +static void mx25_tcq_force_queue_start(struct mx25_tcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS,
> + MX25_ADCQ_CR_FQS);
> +
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0);
> +}
> +
> +static void mx25_tcq_force_queue_stop(struct mx25_tcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0);
> +}
> +
> +static void mx25_tcq_fifo_reset(struct mx25_tcq_priv *priv)
> +{
> + u32 tcqcr;
> +
> + regmap_read(priv->regs, MX25_ADCQ_CR, &tcqcr);
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FRST,
> + MX25_ADCQ_CR_FRST);
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FRST,
> + 0);
> + regmap_write(priv->regs, MX25_ADCQ_CR, tcqcr);
> +}
> +
> +static void mx25_tcq_re_enable_touch_detection(struct mx25_tcq_priv *priv)
> +{
> + /* stop the queue from looping */
> + mx25_tcq_force_queue_stop(priv);
> +
> + /* for a clean touch detection, preload the X plane */
> + regmap_write(priv->core_regs, MX25_TSC_TICR, MX25_PRECHARGE_VALUE);
> +
> + /* waste some time now to pre-load the X plate to high voltage */
> + mx25_tcq_fifo_reset(priv);
> +
> + /* re-enable the detection right now */
> + regmap_write(priv->core_regs, MX25_TSC_TICR, MX25_TOUCH_DETECT_VALUE |
> + MX25_ADCQ_CFG_IGS);
> +
> + regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_PD,
> + MX25_ADCQ_SR_PD);
> +
> + /* enable the pen down event to be a source for the interrupt */
> + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_PD_IRQ, 0);
> +
> + /* lets fire the next IRQ if someone touches the touchscreen */
> + mx25_tcq_enable_touch_irq(priv);
> +}
> +
> +static int mx25_tcq_create_event_for_4wire(struct mx25_tcq_priv *priv,
> + u32 *sample_buf, int samples)
> +{
> + unsigned int x_pos = 0;
> + unsigned int y_pos = 0;
> + unsigned int touch_pre = 0;
> + unsigned int touch_post = 0;
> + unsigned i;
> + int ret = 0;
> +
> + for (i = 0; i < samples; i++) {
> + unsigned int index = MX25_ADCQ_FIFO_ID(sample_buf[i]);
> + unsigned int val = MX25_ADCQ_FIFO_DATA(sample_buf[i]);
> +
> + switch (index) {
> + case 1:
> + touch_pre = val;
> + break;
> + case 2:
> + x_pos = val;
> + break;
> + case 3:
> + y_pos = val;
> + break;
> + case 5:
> + touch_post = val;
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> + }
> +
> + if (ret == 0 && samples != 0) {
> + /*
> + * only if both touch measures are below a treshold,
> + * the position is valid
> + */
> + if (touch_pre < priv->pen_threshold &&
> + touch_post < priv->pen_threshold) {
> + /* valid samples, generate a report */
> + x_pos /= priv->sample_count;
> + y_pos /= priv->sample_count;
> + input_report_abs(priv->idev, ABS_X, x_pos);
> + input_report_abs(priv->idev, ABS_Y, y_pos);
> + input_report_key(priv->idev, BTN_TOUCH, 1);
> + input_sync(priv->idev);
> +
> + /* get next sample */
> + mx25_tcq_force_queue_start(priv);
> + mx25_tcq_enable_fifo_irq(priv);
> + } else if (touch_pre >= priv->pen_threshold &&
> + touch_post >= priv->pen_threshold) {
> + /*
> + * if both samples are invalid,
> + * generate a release report
> + */
> + input_report_key(priv->idev, BTN_TOUCH, 0);
> + input_sync(priv->idev);
> + mx25_tcq_re_enable_touch_detection(priv);
> + } else {
> + /*
> + * if only one of both touch measurements are
> + * below the threshold, still some bouncing
> + * happens. Take additional samples in this
> + * case to be sure
> + */
> + mx25_tcq_force_queue_start(priv);
> + mx25_tcq_enable_fifo_irq(priv);
> + }
> + }
> +
> + return ret;
> +}
> +
> +static irqreturn_t mx25_tcq_irq_thread(int irq, void *dev_id)
> +{
> + struct mx25_tcq_priv *priv = dev_id;
> + u32 sample_buf[TSC_MAX_SAMPLES];
> + int samples = 0;
> +
> + /* read all samples */
> + while (1) {
> + u32 stats;
> +
> + regmap_read(priv->regs, MX25_ADCQ_SR, &stats);
> + if (stats & MX25_ADCQ_SR_EMPT)
> + break;
> +
> + if (samples < TSC_MAX_SAMPLES) {
> + regmap_read(priv->regs, MX25_ADCQ_FIFO,
> + &sample_buf[samples]);
> + ++samples;
> + } else {
> + u32 discarded;
> + /* discard samples */
> + regmap_read(priv->regs, MX25_ADCQ_FIFO, &discarded);
> + }
> + }
> +
> + mx25_tcq_create_event_for_4wire(priv, sample_buf, samples);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t mx25_tcq_irq(int irq, void *dev_id)
> +{
> + struct mx25_tcq_priv *priv = dev_id;
> + u32 stat;
> + int ret = IRQ_HANDLED;
> +
> + regmap_read(priv->regs, MX25_ADCQ_SR, &stat);
> +
> + if (stat & (MX25_ADCQ_SR_FRR | MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR))
> + mx25_tcq_fifo_reset(priv);
> +
> + if (stat & MX25_ADCQ_SR_PD) {
> + mx25_tcq_disable_touch_irq(priv);
> + mx25_tcq_force_queue_start(priv);
> + mx25_tcq_enable_fifo_irq(priv);
> + }
> +
> + if (stat & MX25_ADCQ_SR_FDRY) {
> + mx25_tcq_disable_fifo_irq(priv);
> + ret = IRQ_WAKE_THREAD;
> + }
> +
> + regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR |
> + MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_PD |
> + MX25_ADCQ_SR_EOQ,
> + MX25_ADCQ_SR_FRR |
> + MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_PD |
> + MX25_ADCQ_SR_EOQ);
> +
> + return ret;
> +}
> +
> +/* configure the statemachine for a 4-wire touchscreen */
> +static int mx25_tcq_init(struct mx25_tcq_priv *priv)
> +{
> + u32 tgcr;
> + unsigned int ipg_div;
> + unsigned int adc_period;
> + unsigned int debounce_cnt;
> + unsigned int settling_time;
> + int itemct;
> + int ret;
> +
> + regmap_read(priv->core_regs, MX25_TSC_TGCR, &tgcr);
> + ipg_div = max_t(unsigned int, 4, MX25_TGCR_GET_ADCCLK(tgcr));
> + adc_period = clk_get_rate(priv->clk) / (ipg_div * 2 + 2);
> + debounce_cnt = DIV_ROUND_UP(priv->pen_debounce, adc_period * 8) - 1;
> + settling_time = DIV_ROUND_UP(priv->settling_time, adc_period);
> +
> +
> + /* Reset */
> + regmap_write(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QRST |
> + MX25_ADCQ_CR_FRST);
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QRST |
> + MX25_ADCQ_CR_FRST, 0);
> +
> + /* up to 128 * 8 ADC clocks are possible */
> + if (debounce_cnt > 127)
> + debounce_cnt = 127;
> +
> + ret = imx25_setup_queue_4wire(priv, 0x0, &itemct);
> + if (ret)
> + return ret;
> +
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_LITEMID_MASK |
> + MX25_ADCQ_CR_WMRK_MASK,
> + MX25_ADCQ_CR_LITEMID(itemct - 1) |
> + MX25_ADCQ_CR_WMRK(priv->expected_samples - 1));
> +
> + /* setup debounce count */
> + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR,
> + MX25_TGCR_PDBTIME_MASK,
> + MX25_TGCR_PDBTIME(debounce_cnt));
> +
> + /* enable debounce */
> + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDBEN,
> + MX25_TGCR_PDBEN);
> + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDEN,
> + MX25_TGCR_PDEN);
> +
> + /* enable the engine on demand */
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QSM_FQS,
> + MX25_ADCQ_CR_QSM_FQS);
> +
> + mx25_tcq_re_enable_touch_detection(priv);
> +
> + return 0;
> +}
> +
> +static int mx25_tcq_parse_dt(struct platform_device *pdev,
> + struct mx25_tcq_priv *priv)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + u32 wires;
> + int ret;
> +
> + /* Setup defaults */
> + priv->pen_threshold = 500;
> + priv->sample_count = 3;
> + priv->pen_debounce = 1000000;
> + priv->settling_time = 250000;
> +
> + ret = of_property_read_u32(np, "fsl,wires", &wires);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to find fsl,wires properties\n");
> + return ret;
> + }
> +
> + if (wires == 4) {
> + priv->mode = MX25_TS_4WIRE;
> + } else {
> + dev_err(&pdev->dev, "%u-wire mode not supported\n", wires);
> + return -EINVAL;
> + }
> +
> + /* These are optional, we don't care about the return values */
> + of_property_read_u32(np, "fsl,pen-threshold", &priv->pen_threshold);
> + of_property_read_u32(np, "fsl,settling-time", &priv->settling_time);
> + of_property_read_u32(np, "fsl,pen-debounce", &priv->pen_debounce);
> +
> + return 0;
> +}
> +
> +static int mx25_tcq_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct input_dev *idev;
> + struct mx25_tcq_priv *priv;
> + struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent);
> + struct resource *res;
> + void __iomem *mem;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + mem = devm_ioremap_resource(dev, res);
> + if (!mem)
> + return -ENOMEM;
> +
> + ret = mx25_tcq_parse_dt(pdev, priv);
> + if (ret)
> + return ret;
> +
> + priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_tcq_regconfig);
> + if (IS_ERR(priv->regs)) {
> + dev_err(dev, "Failed to initialize regmap\n");
> + return PTR_ERR(priv->regs);
> + }
> +
> + priv->irq = platform_get_irq(pdev, 0);
> + if (priv->irq <= 0) {
> + dev_err(dev, "Failed to get IRQ\n");
> + return priv->irq;
> + }
> +
> + idev = devm_input_allocate_device(dev);
> + if (!idev) {
> + dev_err(dev, "Failed to allocate input device\n");
> + return -ENOMEM;
> + }
> +
> + idev->name = mx25_tcq_name;
> + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> + idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> + input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
> + input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
> +
> + idev->id.bustype = BUS_HOST;
> +
> + ret = input_register_device(idev);
> + if (ret) {
> + dev_err(dev, "Failed to register input device\n");
> + return ret;
> + }
> +
> + priv->idev = idev;
> +
> + priv->core_regs = tsadc->regs;
> + if (!priv->core_regs)
> + return -EINVAL;
> +
> + priv->clk = tsadc->clk;
> + if (!priv->clk)
> + return -EINVAL;
> +
> + ret = clk_prepare_enable(priv->clk);
> + if (ret) {
> + dev_err(dev, "Failed to enable ipg clock\n");
> + return ret;
> + }
> +
> + ret = request_threaded_irq(priv->irq, mx25_tcq_irq, mx25_tcq_irq_thread,
> + IRQF_ONESHOT, pdev->name, priv);
> + if (ret) {
> + dev_err(dev, "Failed requesting IRQ\n");
> + goto err_clk_unprepare;
> + }
> +
> + ret = mx25_tcq_init(priv);
> + if (ret) {
> + dev_err(dev, "Failed to init tcq\n");
> + goto error_free_irq;
> + }
> +
> + platform_set_drvdata(pdev, priv);
> +
> + return 0;
> +
> +error_free_irq:
> + free_irq(priv->irq, priv);
> +err_clk_unprepare:
> + clk_disable_unprepare(priv->clk);
> + return ret;
> +}
> +
> +static int mx25_tcq_remove(struct platform_device *pdev)
> +{
> + struct mx25_tcq_priv *priv = platform_get_drvdata(pdev);
> +
> + free_irq(priv->irq, priv);
> + clk_disable_unprepare(priv->clk);
> +
> + return 0;
> +}
> +
> +static struct platform_driver mx25_tcq_driver = {
> + .driver = {
> + .name = "mx25-tcq",
> + .owner = THIS_MODULE,
> + .of_match_table = mx25_tcq_ids,
> + },
> + .probe = mx25_tcq_probe,
> + .remove = mx25_tcq_remove,
> +};
> +module_platform_driver(mx25_tcq_driver);
> +
> +MODULE_DESCRIPTION("TS input driver for Freescale mx25");
> +MODULE_AUTHOR("Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>");
> +MODULE_LICENSE("GPL v2");
> --
> 1.7.9.5
>
--
Dmitry
^ permalink raw reply
* Re: [PATCH] Input: Add Acer Aspire 5710 to nomux blacklist
From: Dmitry Torokhov @ 2014-07-09 16:54 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input, vojtech, hdegoede
In-Reply-To: <alpine.LNX.2.00.1406251139070.15939@pobox.suse.cz>
On Wed, Jun 25, 2014 at 11:42:43AM +0200, Jiri Kosina wrote:
> Acer Aspire needs to be added to nomux blacklist, otherwise the touchpad
> misbehaves rather randomly.
>
> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
>
> ---
>
> Hi Dmitry,
>
> I've come across this a few year old patch originating from our internal
> bugzilla, which was apparently been lost between the cracks somewhere.
> We've been carrying it in our kernel tree for quite some time ... could
> you please apply it? Thanks.
I will. I also wonder if by now we should stop defaulting to MUX mode:
all newer desktop/server boxes use USB, only laptops still use PS/2,
and quite a few of them not implement active MUX properly. I also expect
that most of external PS/2 mice are dead by now, so number of cases when
we have users with PS/2 touchpad + external PS/2 mouse + working active
MUX is exceedingly small.
Let's pull Vojtech in ;)
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] soc_button_array: fix the issue that button device can't be enumerated since 3.16-rc1
From: Dmitry Torokhov @ 2014-07-09 16:57 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: Zhang Rui, yao.jin, linux-input
In-Reply-To: <2556427.cdnVoQoSXY@vostro.rjw.lan>
On Tue, Jul 08, 2014 at 10:50:04PM +0200, Rafael J. Wysocki wrote:
> On Wednesday, July 02, 2014 10:01:53 PM Zhang Rui wrote:
> > From c2ee1886ba230d9d93d2ea2f350b1dc1a2d5ead5 Mon Sep 17 00:00:00 2001
> > From: Jin Yao <yao.jin@linux.intel.com>
> > Date: Thu, 26 Jun 2014 10:26:44 +0800
> > Subject: [PATCH] soc_button_array: fix the issue that button device can't be
> > enumerated since 3.16-rc1
>
> Hi Rui,
>
> For 3.16 I'm afraid we need to add the missing device ID to the PNP list.
> It is too late to do the conversion at this point IMO and we can do it later.
But for 3.17 this patch is the right way of doing things, right?
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] Input: Add Acer Aspire 5710 to nomux blacklist
From: Vojtech Pavlik @ 2014-07-09 17:48 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Jiri Kosina, linux-input, hdegoede
In-Reply-To: <20140709165438.GC10364@core.coreip.homeip.net>
On Wed, Jul 09, 2014 at 09:54:38AM -0700, Dmitry Torokhov wrote:
> On Wed, Jun 25, 2014 at 11:42:43AM +0200, Jiri Kosina wrote:
> > Acer Aspire needs to be added to nomux blacklist, otherwise the touchpad
> > misbehaves rather randomly.
> >
> > Signed-off-by: Jiri Kosina <jkosina@suse.cz>
> >
> > ---
> >
> > Hi Dmitry,
> >
> > I've come across this a few year old patch originating from our internal
> > bugzilla, which was apparently been lost between the cracks somewhere.
> > We've been carrying it in our kernel tree for quite some time ... could
> > you please apply it? Thanks.
>
> I will. I also wonder if by now we should stop defaulting to MUX mode:
> all newer desktop/server boxes use USB, only laptops still use PS/2,
MUX mode was only ever available on laptops - no desktop computer I'm
aware of ever had it.
> and quite a few of them not implement active MUX properly.
Do you still get reports of non-working, but advertized Active
Multiplexing mode on new laptops?
> I also expect
> that most of external PS/2 mice are dead by now, so number of cases when
One would at least hope so. Sadly, internal mice and PS/2 keyboards
aren't going to go away any soon, due to larger power consumption of USB
devices.
> we have users with PS/2 touchpad + external PS/2 mouse + working active
> MUX is exceedingly small.
>
> Let's pull Vojtech in ;)
What I'd prefer is to, based on DMI data, report but not enable by
default Active MUX mode on any machine manufactured after a certain
date. Plus have a DMI-based whitelist for machines that absolutely
needed, if any are found later.
--
Vojtech Pavlik
Director SUSE Labs
^ permalink raw reply
* Re: [PATCH] Input: Add Acer Aspire 5710 to nomux blacklist
From: Dmitry Torokhov @ 2014-07-09 19:38 UTC (permalink / raw)
To: Vojtech Pavlik; +Cc: Jiri Kosina, linux-input, hdegoede
In-Reply-To: <20140709174821.GA30912@suse.cz>
On Wed, Jul 09, 2014 at 07:48:21PM +0200, Vojtech Pavlik wrote:
> On Wed, Jul 09, 2014 at 09:54:38AM -0700, Dmitry Torokhov wrote:
> > On Wed, Jun 25, 2014 at 11:42:43AM +0200, Jiri Kosina wrote:
> > > Acer Aspire needs to be added to nomux blacklist, otherwise the touchpad
> > > misbehaves rather randomly.
> > >
> > > Signed-off-by: Jiri Kosina <jkosina@suse.cz>
> > >
> > > ---
> > >
> > > Hi Dmitry,
> > >
> > > I've come across this a few year old patch originating from our internal
> > > bugzilla, which was apparently been lost between the cracks somewhere.
> > > We've been carrying it in our kernel tree for quite some time ... could
> > > you please apply it? Thanks.
> >
> > I will. I also wonder if by now we should stop defaulting to MUX mode:
> > all newer desktop/server boxes use USB, only laptops still use PS/2,
>
> MUX mode was only ever available on laptops - no desktop computer I'm
> aware of ever had it.
Yeah, I don't recall seeing one either.
>
> > and quite a few of them not implement active MUX properly.
>
> Do you still get reports of non-working, but advertized Active
> Multiplexing mode on new laptops?
Evey now and then... Vendors seem to not normally touch that code.
>
> > I also expect
> > that most of external PS/2 mice are dead by now, so number of cases when
>
> One would at least hope so. Sadly, internal mice and PS/2 keyboards
> aren't going to go away any soon, due to larger power consumption of USB
> devices.
Right, but we are not talking about mouse vs keyboard, they use separate
ports anyway, it is touchpad plus external PS/2 mouse case where active
MUX might help.
>
> > we have users with PS/2 touchpad + external PS/2 mouse + working active
> > MUX is exceedingly small.
> >
> > Let's pull Vojtech in ;)
>
> What I'd prefer is to, based on DMI data, report but not enable by
> default Active MUX mode on any machine manufactured after a certain
> date. Plus have a DMI-based whitelist for machines that absolutely
> needed, if any are found later.
Looking at the changes to nomux blacklist sometimes even trying MUX
messes up KBC. Instead of playing date games I'd rather simply make
i8042.nomux default. I'm fine with having whitelist for boxes that
actually need and support muxing properly.
Thanks.
--
Dmitry
^ permalink raw reply
* PS3 controller and vibration
From: andrea @ 2014-07-09 19:40 UTC (permalink / raw)
To: linux-input
Hi,
I've got a PS3 controller (sixaxis written on the back)
PLAYSTATION(R)3 Controller as
/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:72/0005:054C:0268.0002/input/input10
BLUETOOTH HID v1.00 Joystick [PLAYSTATION(R)3 Controller] on 00:1a:7d:da:71:0b
using bluez 5.18 on Fedora 20, kernel 3.15.3
it is connected via bluetooth.
It does not vibrate.
I've tried to write to /dev/hidraw0 and used love2d.
I read online either than I need to enable the vibration or that the sixaxis does not support it.
I am pretty sure it has vibrated on some games on the PS3.
Does anybody know how it works?
Andrea
^ permalink raw reply
* Re: PS3 controller and vibration
From: Michael Wright @ 2014-07-09 19:47 UTC (permalink / raw)
To: andrea; +Cc: linux-input@vger.kernel.org
In-Reply-To: <lpk5ru$5ak$1@ger.gmane.org>
Check to see if it says DUALSHOCK 3 on the top. Regular SIXAXIS
controllers don't support force feedback.
On Wed, Jul 9, 2014 at 12:40 PM, andrea <mariofutire@googlemail.com> wrote:
>
> Hi,
>
> I've got a PS3 controller (sixaxis written on the back)
>
> PLAYSTATION(R)3 Controller as
> /devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.0/bluetooth/hci0/hci0:72/0005:054C:0268.0002/input/input10
> BLUETOOTH HID v1.00 Joystick [PLAYSTATION(R)3 Controller] on 00:1a:7d:da:71:0b
>
> using bluez 5.18 on Fedora 20, kernel 3.15.3
>
> it is connected via bluetooth.
>
> It does not vibrate.
> I've tried to write to /dev/hidraw0 and used love2d.
>
> I read online either than I need to enable the vibration or that the sixaxis does not support it.
> I am pretty sure it has vibrated on some games on the PS3.
>
> Does anybody know how it works?
>
> Andrea
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: PS3 controller and vibration
From: andrea @ 2014-07-09 19:51 UTC (permalink / raw)
To: Michael Wright; +Cc: linux-input@vger.kernel.org
In-Reply-To: <CALDEARhCi+0TidoTmsDoYEnVUedCc-1m2AnLypkimJbkJfWaYQ@mail.gmail.com>
On 09/07/14 20:47, Michael Wright wrote:
> Check to see if it says DUALSHOCK 3 on the top. Regular SIXAXIS
> controllers don't support force feedback.
it does not.
is vibration the same as rumble?
I must have dreamed then, I was pretty sure it did in the past.
thanks
^ permalink raw reply
* Re: [PATCH] GPIO button wth wakeup attribute is supposed to wake the system up
From: Li, Aubrey @ 2014-07-10 2:27 UTC (permalink / raw)
To: Rafael J. Wysocki, Dmitry Torokhov
Cc: linux-input@vger.kernel.org, LKML, One Thousand Gnomes,
Linux PM list
In-Reply-To: <4301161.i6ArOLmcsg@vostro.rjw.lan>
On 2014/7/9 20:45, Rafael J. Wysocki wrote:
> On Tuesday, July 08, 2014 05:54:35 PM Dmitry Torokhov wrote:
>> On Wed, Jul 09, 2014 at 02:59:33AM +0200, Rafael J. Wysocki wrote:
>>> On Tuesday, July 08, 2014 05:15:06 PM Dmitry Torokhov wrote:
>>>> On Wed, Jul 09, 2014 at 01:06:07AM +0200, Rafael J. Wysocki wrote:
>
> [cut]
>
>>>>
>>>> When device driver marks IRQ as a wakeup source I believe it is prepared
>>>> to handle it (or it would shut it off explicitly).
>>>
>>> I can agree with that.
>>>
>>> Are you suggesting that __disable_irq() should check irq_data for
>>> IRQD_WAKEUP_STATE and skip the IRQ (in the 'suspend' case) if that is set?
>>
>> Yes, something like that.
>
> OK
Many thanks to you both for the discussion.
>
> Aubrey, can you please check if the appended patch helps on the T100?
I verified this patch on T100, it works as expected, freeze can be waken
up by reverting my patch and applying this one.
Is this a final solution?
Thanks,
-Aubrey
>
> Rafael
>
> ---
> kernel/irq/manage.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> Index: linux-pm/kernel/irq/manage.c
> ===================================================================
> --- linux-pm.orig/kernel/irq/manage.c
> +++ linux-pm/kernel/irq/manage.c
> @@ -385,7 +385,8 @@ setup_affinity(unsigned int irq, struct
> void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
> {
> if (suspend) {
> - if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
> + if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
> + || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> return;
> desc->istate |= IRQS_SUSPENDED;
> }
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
>
^ permalink raw reply
* Re: [PATCH] soc_button_array: fix the issue that button device can't be enumerated since 3.16-rc1
From: Zhang Rui @ 2014-07-10 6:24 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Rafael J. Wysocki, yao.jin, linux-input
In-Reply-To: <20140709165732.GD10364@core.coreip.homeip.net>
On Wed, 2014-07-09 at 09:57 -0700, Dmitry Torokhov wrote:
> On Tue, Jul 08, 2014 at 10:50:04PM +0200, Rafael J. Wysocki wrote:
> > On Wednesday, July 02, 2014 10:01:53 PM Zhang Rui wrote:
> > > From c2ee1886ba230d9d93d2ea2f350b1dc1a2d5ead5 Mon Sep 17 00:00:00 2001
> > > From: Jin Yao <yao.jin@linux.intel.com>
> > > Date: Thu, 26 Jun 2014 10:26:44 +0800
> > > Subject: [PATCH] soc_button_array: fix the issue that button device can't be
> > > enumerated since 3.16-rc1
> >
> > Hi Rui,
> >
> > For 3.16 I'm afraid we need to add the missing device ID to the PNP list.
> > It is too late to do the conversion at this point IMO and we can do it later.
>
> But for 3.17 this patch is the right way of doing things, right?
>
yes, but it needs a bit more work to revert the "PNP0C40" id from
drivers/acpi/acpi_pnp.c.
I will send an updated one once the "Adding PNP0C40 id" patch is merged.
thanks,
rui
> Thanks.
>
^ permalink raw reply
* Re: [PATCH] Input: Add Acer Aspire 5710 to nomux blacklist
From: Hans de Goede @ 2014-07-10 7:32 UTC (permalink / raw)
To: Dmitry Torokhov, Vojtech Pavlik; +Cc: Jiri Kosina, linux-input
In-Reply-To: <20140709193830.GE10364@core.coreip.homeip.net>
Hi,
On 07/09/2014 09:38 PM, Dmitry Torokhov wrote:
> On Wed, Jul 09, 2014 at 07:48:21PM +0200, Vojtech Pavlik wrote:
>> On Wed, Jul 09, 2014 at 09:54:38AM -0700, Dmitry Torokhov wrote:
>>> On Wed, Jun 25, 2014 at 11:42:43AM +0200, Jiri Kosina wrote:
>>>> Acer Aspire needs to be added to nomux blacklist, otherwise the touchpad
>>>> misbehaves rather randomly.
>>>>
>>>> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
>>>>
>>>> ---
>>>>
>>>> Hi Dmitry,
>>>>
>>>> I've come across this a few year old patch originating from our internal
>>>> bugzilla, which was apparently been lost between the cracks somewhere.
>>>> We've been carrying it in our kernel tree for quite some time ... could
>>>> you please apply it? Thanks.
>>>
>>> I will. I also wonder if by now we should stop defaulting to MUX mode:
>>> all newer desktop/server boxes use USB, only laptops still use PS/2,
>>
>> MUX mode was only ever available on laptops - no desktop computer I'm
>> aware of ever had it.
>
> Yeah, I don't recall seeing one either.
>
>>
>>> and quite a few of them not implement active MUX properly.
>>
>> Do you still get reports of non-working, but advertized Active
>> Multiplexing mode on new laptops?
>
> Evey now and then... Vendors seem to not normally touch that code.
>
>>
>>> I also expect
>>> that most of external PS/2 mice are dead by now, so number of cases when
>>
>> One would at least hope so. Sadly, internal mice and PS/2 keyboards
>> aren't going to go away any soon, due to larger power consumption of USB
>> devices.
>
> Right, but we are not talking about mouse vs keyboard, they use separate
> ports anyway, it is touchpad plus external PS/2 mouse case where active
> MUX might help.
What about laptops with both a touchpad and a trackpoint ? I think in most
cases the trackpoint works through some sort of pass-through mode of the
touchpad (or is outright part of the touchpad ps/2 device), but are we
sure there are no cases where the trackpoint and touchpad are really
separate ps/2 devices hookedup through an active mux ?
>
>>
>>> we have users with PS/2 touchpad + external PS/2 mouse + working active
>>> MUX is exceedingly small.
>>>
>>> Let's pull Vojtech in ;)
>>
>> What I'd prefer is to, based on DMI data, report but not enable by
>> default Active MUX mode on any machine manufactured after a certain
>> date. Plus have a DMI-based whitelist for machines that absolutely
>> needed, if any are found later.
>
> Looking at the changes to nomux blacklist sometimes even trying MUX
> messes up KBC. Instead of playing date games I'd rather simply make
> i8042.nomux default. I'm fine with having whitelist for boxes that
> actually need and support muxing properly.
I'm a bit skeptical about making this change, see above.
Regards,
Hans
^ permalink raw reply
* Re: [PATCH] Input: Add Acer Aspire 5710 to nomux blacklist
From: Vojtech Pavlik @ 2014-07-10 8:45 UTC (permalink / raw)
To: Hans de Goede; +Cc: Dmitry Torokhov, Jiri Kosina, linux-input
In-Reply-To: <53BE4180.4030907@redhat.com>
On Thu, Jul 10, 2014 at 09:32:16AM +0200, Hans de Goede wrote:
> >>> I also expect
> >>> that most of external PS/2 mice are dead by now, so number of cases when
> >>
> >> One would at least hope so. Sadly, internal mice and PS/2 keyboards
> >> aren't going to go away any soon, due to larger power consumption of USB
> >> devices.
> >
> > Right, but we are not talking about mouse vs keyboard, they use separate
> > ports anyway, it is touchpad plus external PS/2 mouse case where active
> > MUX might help.
>
> What about laptops with both a touchpad and a trackpoint ? I think in most
> cases the trackpoint works through some sort of pass-through mode of the
> touchpad (or is outright part of the touchpad ps/2 device), but are we
> sure there are no cases where the trackpoint and touchpad are really
> separate ps/2 devices hookedup through an active mux ?
I'm not aware of any current machines using active multiplexing for
that. There are basically two touchpad manufacturers: Synaptics and
ALPS. Synaptics has a nearly transparent passthrough mode and
touchpoints are connected through that. ALPS basically manufactures a
touchpad+touchpoint combo device and thus doesn't need a fully
transparent passthrough.
Active multiplexing was typically used for external PS/2 ports on
laptops, because the manufacturer couldn't anticipate the protocol of
the externally connected device.
> >>> we have users with PS/2 touchpad + external PS/2 mouse + working active
> >>> MUX is exceedingly small.
> >>>
> >>> Let's pull Vojtech in ;)
> >>
> >> What I'd prefer is to, based on DMI data, report but not enable by
> >> default Active MUX mode on any machine manufactured after a certain
> >> date. Plus have a DMI-based whitelist for machines that absolutely
> >> needed, if any are found later.
> >
> > Looking at the changes to nomux blacklist sometimes even trying MUX
> > messes up KBC. Instead of playing date games I'd rather simply make
> > i8042.nomux default. I'm fine with having whitelist for boxes that
> > actually need and support muxing properly.
>
> I'm a bit skeptical about making this change, see above.
I'm not too keen about it either, as it could break existing setups.
But I have to concede that any working hardware still using both
external and internal PS/2 and thus needing Active Multiplexing is most
likely to be found in museums today.
So the risk of breakage isn't all that big.
--
Vojtech Pavlik
Director SUSE Labs
^ permalink raw reply
* Re: [PATCH] GPIO button wth wakeup attribute is supposed to wake the system up
From: Rafael J. Wysocki @ 2014-07-10 11:27 UTC (permalink / raw)
To: Li, Aubrey
Cc: Dmitry Torokhov, linux-input@vger.kernel.org, LKML,
One Thousand Gnomes, Linux PM list
In-Reply-To: <53BDFA22.2000409@linux.intel.com>
On Thursday, July 10, 2014 10:27:46 AM Li, Aubrey wrote:
> On 2014/7/9 20:45, Rafael J. Wysocki wrote:
> > On Tuesday, July 08, 2014 05:54:35 PM Dmitry Torokhov wrote:
> >> On Wed, Jul 09, 2014 at 02:59:33AM +0200, Rafael J. Wysocki wrote:
> >>> On Tuesday, July 08, 2014 05:15:06 PM Dmitry Torokhov wrote:
> >>>> On Wed, Jul 09, 2014 at 01:06:07AM +0200, Rafael J. Wysocki wrote:
> >
> > [cut]
> >
> >>>>
> >>>> When device driver marks IRQ as a wakeup source I believe it is prepared
> >>>> to handle it (or it would shut it off explicitly).
> >>>
> >>> I can agree with that.
> >>>
> >>> Are you suggesting that __disable_irq() should check irq_data for
> >>> IRQD_WAKEUP_STATE and skip the IRQ (in the 'suspend' case) if that is set?
> >>
> >> Yes, something like that.
> >
> > OK
>
> Many thanks to you both for the discussion.
> >
> > Aubrey, can you please check if the appended patch helps on the T100?
>
> I verified this patch on T100, it works as expected, freeze can be waken
> up by reverting my patch and applying this one.
Thanks!
> Is this a final solution?
I hope so. I'll resend it with a proper changelog later today.
Rafael
^ permalink raw reply
* Re: [PATCH] Input: Add Acer Aspire 5710 to nomux blacklist
From: Hans de Goede @ 2014-07-10 15:20 UTC (permalink / raw)
To: Vojtech Pavlik; +Cc: Dmitry Torokhov, Jiri Kosina, linux-input
In-Reply-To: <20140710084551.GA26864@suse.cz>
Hi,
On 07/10/2014 10:45 AM, Vojtech Pavlik wrote:
> On Thu, Jul 10, 2014 at 09:32:16AM +0200, Hans de Goede wrote:
>
>>>>> I also expect
>>>>> that most of external PS/2 mice are dead by now, so number of cases when
>>>>
>>>> One would at least hope so. Sadly, internal mice and PS/2 keyboards
>>>> aren't going to go away any soon, due to larger power consumption of USB
>>>> devices.
>>>
>>> Right, but we are not talking about mouse vs keyboard, they use separate
>>> ports anyway, it is touchpad plus external PS/2 mouse case where active
>>> MUX might help.
>>
>> What about laptops with both a touchpad and a trackpoint ? I think in most
>> cases the trackpoint works through some sort of pass-through mode of the
>> touchpad (or is outright part of the touchpad ps/2 device), but are we
>> sure there are no cases where the trackpoint and touchpad are really
>> separate ps/2 devices hookedup through an active mux ?
>
> I'm not aware of any current machines using active multiplexing for
> that. There are basically two touchpad manufacturers: Synaptics and
> ALPS.
And elantech
> Synaptics has a nearly transparent passthrough mode and
> touchpoints are connected through that. ALPS basically manufactures a
> touchpad+touchpoint combo device and thus doesn't need a fully
> transparent passthrough.
Elantech now a days also produces a combo like alps.
> Active multiplexing was typically used for external PS/2 ports on
> laptops, because the manufacturer couldn't anticipate the protocol of
> the externally connected device.
Right, but what about users who still have a laptop with an external
ps/2 port which they happen to also still use ?
>
>>>>> we have users with PS/2 touchpad + external PS/2 mouse + working active
>>>>> MUX is exceedingly small.
>>>>>
>>>>> Let's pull Vojtech in ;)
>>>>
>>>> What I'd prefer is to, based on DMI data, report but not enable by
>>>> default Active MUX mode on any machine manufactured after a certain
>>>> date. Plus have a DMI-based whitelist for machines that absolutely
>>>> needed, if any are found later.
>>>
>>> Looking at the changes to nomux blacklist sometimes even trying MUX
>>> messes up KBC. Instead of playing date games I'd rather simply make
>>> i8042.nomux default. I'm fine with having whitelist for boxes that
>>> actually need and support muxing properly.
>>
>> I'm a bit skeptical about making this change, see above.
>
> I'm not too keen about it either, as it could break existing setups.
>
> But I have to concede that any working hardware still using both
> external and internal PS/2 and thus needing Active Multiplexing is most
> likely to be found in museums today.
>
> So the risk of breakage isn't all that big.
One of the nice things about Linux is that in general we've pretty
decent support for older hardware, so if we decide to flip the nomux
default, I think we should really do so based on some BIOS cut-off
date, so as to not break older model laptops.
Regards,
Hans
>
^ permalink raw reply
* [PATCH 2/5] Input - wacom: use a specific name for the battery device
From: Benjamin Tissoires @ 2014-07-10 18:44 UTC (permalink / raw)
To: Przemo Firszt, Dmitry Torokhov, Jiri Kosina, Ping Cheng,
Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405017900-16024-1-git-send-email-benjamin.tissoires@redhat.com>
The current implementation uses "wacom_battery" as a generic name for
batteries. This prevents us to have two Wacom devices with a battery
attached as the power system will complain about the name which is already
registered.
Use a specific name for each type of battery attached.
A bug in upower prevents us to use spaces in the power name, so replace
each space by '_'.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom_sys.c | 13 ++++++++++---
drivers/input/tablet/wacom_wac.h | 1 +
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 1888709..b5d75a4 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -803,15 +803,21 @@ static int wacom_battery_get_property(struct power_supply *psy,
return ret;
}
-static int wacom_initialize_battery(struct wacom *wacom)
+static int wacom_initialize_battery(struct wacom *wacom, const char *name)
{
int error = 0;
+ int i;
if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
wacom->battery.properties = wacom_battery_props;
wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
wacom->battery.get_property = wacom_battery_get_property;
- wacom->battery.name = "wacom_battery";
+ sprintf(wacom->wacom_wac.bat_name, "%s battery", name);
+ for (i=0; i < strlen(wacom->wacom_wac.bat_name); i++) {
+ if (wacom->wacom_wac.bat_name[i] == ' ')
+ wacom->wacom_wac.bat_name[i] = '_';
+ }
+ wacom->battery.name = wacom->wacom_wac.bat_name;
wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wacom->battery.use_for_apm = 0;
@@ -1012,7 +1018,8 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_wac->shared->touch_input = wacom_wac2->input;
}
- error = wacom_initialize_battery(wacom);
+ error = wacom_initialize_battery(wacom,
+ wacom_wac1->features.name);
if (error)
goto fail;
}
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 68cf257..7565be5 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -153,6 +153,7 @@ struct wacom_shared {
struct wacom_wac {
char name[WACOM_NAME_MAX];
char pad_name[WACOM_NAME_MAX];
+ char bat_name[WACOM_NAME_MAX];
unsigned char data[WACOM_PKGLEN_MAX];
int tool[2];
int id[2];
--
2.0.0
^ permalink raw reply related
* [PATCH 3/5] Input - wacom: handle Graphire BT tablets in wacom.ko
From: Benjamin Tissoires @ 2014-07-10 18:44 UTC (permalink / raw)
To: Przemo Firszt, Dmitry Torokhov, Jiri Kosina, Ping Cheng,
Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405017900-16024-1-git-send-email-benjamin.tissoires@redhat.com>
Now that wacom is a hid driver, there is no point in having a separate
driver for bluetooth device.
First, merge the Graphire BT tablet.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/hid/hid-core.c | 1 -
drivers/hid/hid-wacom.c | 1 -
drivers/input/tablet/wacom_sys.c | 70 ++++++++++++++++++++++++++--
drivers/input/tablet/wacom_wac.c | 98 +++++++++++++++++++++++++++++++++++++++-
drivers/input/tablet/wacom_wac.h | 4 ++
5 files changed, 165 insertions(+), 9 deletions(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9db1f42..22be644 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1940,7 +1940,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index 4874f4e..967c457 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -952,7 +952,6 @@ static void wacom_remove(struct hid_device *hdev)
}
static const struct hid_device_id wacom_devices[] = {
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
{ }
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index b5d75a4..86db1dc 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -262,6 +262,54 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
return error < 0 ? error : 0;
}
+static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed,
+ struct wacom_features *features)
+{
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ int limit, ret;
+ __u8 rep_data[2];
+
+ switch (features->type) {
+ case GRAPHIRE_BT:
+ rep_data[0] = 0x03 ; rep_data[1] = 0x00;
+ limit = 3;
+ do {
+ ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
+ HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+ } while (ret < 0 && limit-- > 0);
+
+ if (ret >= 0) {
+ if (speed == 0)
+ rep_data[0] = 0x05;
+ else
+ rep_data[0] = 0x06;
+
+ rep_data[1] = 0x00;
+ limit = 3;
+ do {
+ ret = hid_hw_raw_request(hdev, rep_data[0],
+ rep_data, 2, HID_FEATURE_REPORT,
+ HID_REQ_SET_REPORT);
+ } while (ret < 0 && limit-- > 0);
+
+ if (ret >= 0) {
+ wacom->wacom_wac.bt_high_speed = speed;
+ return 0;
+ }
+ }
+
+ /*
+ * Note that if the raw queries fail, it's not a hard failure
+ * and it is safe to continue
+ */
+ hid_warn(hdev, "failed to poke device, command %d, err %d\n",
+ rep_data[0], ret);
+ break;
+ }
+
+ return 0;
+}
+
/*
* Switch the tablet into its most-capable mode. Wacom tablets are
* typically configured to power-up in a mode which sends mouse-like
@@ -272,6 +320,9 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
static int wacom_query_tablet_data(struct hid_device *hdev,
struct wacom_features *features)
{
+ if (hdev->bus == BUS_BLUETOOTH)
+ return wacom_bt_query_tablet_data(hdev, 1, features);
+
if (features->device_type == BTN_TOOL_FINGER) {
if (features->type > TABLETPC) {
/* MT Tablet PC touch */
@@ -808,7 +859,8 @@ static int wacom_initialize_battery(struct wacom *wacom, const char *name)
int error = 0;
int i;
- if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
+ if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) ||
+ (wacom->wacom_wac.features.type == GRAPHIRE_BT)) {
wacom->battery.properties = wacom_battery_props;
wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
wacom->battery.get_property = wacom_battery_get_property;
@@ -834,7 +886,8 @@ static int wacom_initialize_battery(struct wacom *wacom, const char *name)
static void wacom_destroy_battery(struct wacom *wacom)
{
- if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR &&
+ if (((wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) ||
+ (wacom->wacom_wac.features.type == GRAPHIRE_BT)) &&
wacom->battery.dev) {
power_supply_unregister(&wacom->battery);
wacom->battery.dev = NULL;
@@ -1194,10 +1247,16 @@ static int wacom_probe(struct hid_device *hdev,
if (error)
goto fail2;
+ if (!(features->quirks & WACOM_QUIRK_MONITOR)) {
+ error = wacom_initialize_battery(wacom, features->name);
+ if (error)
+ goto fail3;
+ }
+
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
error = wacom_register_inputs(wacom);
if (error)
- goto fail3;
+ goto fail4;
}
/* Note that if query fails it is not a hard failure */
@@ -1207,7 +1266,7 @@ static int wacom_probe(struct hid_device *hdev,
error = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
if (error) {
hid_err(hdev, "hw start failed\n");
- goto fail4;
+ goto fail5;
}
if (features->quirks & WACOM_QUIRK_MONITOR)
@@ -1220,7 +1279,8 @@ static int wacom_probe(struct hid_device *hdev,
return 0;
- fail4: wacom_unregister_inputs(wacom);
+ fail5: wacom_unregister_inputs(wacom);
+ fail4: wacom_destroy_battery(wacom);
fail3: wacom_destroy_leds(wacom);
fail2: wacom_remove_shared_data(wacom_wac);
fail1: kfree(wacom);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index d935f75..20fc356 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -30,6 +30,10 @@
*/
#define WACOM_CONTACT_AREA_SCALE 2607
+/*percent of battery capacity for Graphire
+ 8th value means AC online and show 100% capacity */
+static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
+
static int wacom_penpartner_irq(struct wacom_wac *wacom)
{
unsigned char *data = wacom->data;
@@ -263,11 +267,19 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
unsigned char *data = wacom->data;
struct input_dev *input = wacom->input;
struct input_dev *pad_input = wacom->pad_input;
+ int battery_capacity, ps_connected;
int prox;
int rw = 0;
int retval = 0;
- if (data[0] != WACOM_REPORT_PENABLED) {
+ if (features->type == GRAPHIRE_BT) {
+ if (data[0] != WACOM_REPORT_PENABLED_BT) {
+ dev_dbg(input->dev.parent,
+ "%s: received unknown report #%d\n", __func__,
+ data[0]);
+ goto exit;
+ }
+ } else if (data[0] != WACOM_REPORT_PENABLED) {
dev_dbg(input->dev.parent,
"%s: received unknown report #%d\n", __func__, data[0]);
goto exit;
@@ -301,7 +313,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
if (wacom->tool[0] != BTN_TOOL_MOUSE) {
- input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8));
+ if (features->type == GRAPHIRE_BT)
+ input_report_abs(input, ABS_PRESSURE, data[6] |
+ (((__u16) (data[1] & 0x08)) << 5));
+ else
+ input_report_abs(input, ABS_PRESSURE, data[6] |
+ ((data[7] & 0x03) << 8));
input_report_key(input, BTN_TOUCH, data[1] & 0x01);
input_report_key(input, BTN_STYLUS, data[1] & 0x02);
input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
@@ -312,6 +329,23 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
features->type == WACOM_MO) {
input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f);
rw = (data[7] & 0x04) - (data[7] & 0x03);
+ } else if (features->type == GRAPHIRE_BT) {
+ /* Compute distance between mouse and tablet */
+ rw = 44 - (data[6] >> 2);
+ if (rw < 0)
+ rw = 0;
+ else if (rw > 31)
+ rw = 31;
+ input_report_abs(input, ABS_DISTANCE, rw);
+ if (((data[1] >> 5) & 3) == 2) {
+ /* Mouse with wheel */
+ input_report_key(input, BTN_MIDDLE,
+ data[1] & 0x04);
+ rw = (data[6] & 0x01) ? -1 :
+ (data[6] & 0x02) ? 1 : 0;
+ } else {
+ rw = 0;
+ }
} else {
input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f);
rw = -(signed char)data[6];
@@ -358,6 +392,31 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
retval = 1;
}
break;
+ case GRAPHIRE_BT:
+ prox = data[7] & 0x03;
+ if (prox || wacom->id[1]) {
+ wacom->id[1] = PAD_DEVICE_ID;
+ input_report_key(pad_input, BTN_0, (data[7] & 0x02));
+ input_report_key(pad_input, BTN_1, (data[7] & 0x01));
+ if (!prox)
+ wacom->id[1] = 0;
+ input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
+ retval = 1;
+ }
+ break;
+ }
+
+ /* Store current battery capacity and power supply state */
+ if (features->type == GRAPHIRE_BT) {
+ rw = (data[7] >> 2 & 0x07);
+ battery_capacity = batcap_gr[rw];
+ ps_connected = rw == 7;
+ if ((wacom->battery_capacity != battery_capacity) ||
+ (wacom->ps_connected != ps_connected)) {
+ wacom->battery_capacity = battery_capacity;
+ wacom->ps_connected = ps_connected;
+ wacom_notify_battery(wacom);
+ }
}
exit:
return retval;
@@ -1418,6 +1477,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
case WACOM_G4:
case GRAPHIRE:
+ case GRAPHIRE_BT:
case WACOM_MO:
sync = wacom_graphire_irq(wacom_wac);
break;
@@ -1652,6 +1712,27 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
break;
+ case GRAPHIRE_BT:
+ __clear_bit(ABS_MISC, input_dev->absbit);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+ features->distance_max,
+ 0, 0);
+
+ input_set_capability(input_dev, EV_REL, REL_WHEEL);
+
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+ __set_bit(BTN_MIDDLE, input_dev->keybit);
+
+ __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+ __set_bit(BTN_TOOL_PEN, input_dev->keybit);
+ __set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+ __set_bit(BTN_STYLUS2, input_dev->keybit);
+
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+ break;
+
case WACOM_24HD:
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
@@ -1860,6 +1941,11 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
switch (features->type) {
+ case GRAPHIRE_BT:
+ __set_bit(BTN_0, input_dev->keybit);
+ __set_bit(BTN_1, input_dev->keybit);
+ break;
+
case WACOM_MO:
__set_bit(BTN_BACK, input_dev->keybit);
__set_bit(BTN_LEFT, input_dev->keybit);
@@ -2029,6 +2115,9 @@ static const struct wacom_features wacom_features_0x00 =
static const struct wacom_features wacom_features_0x10 =
{ "Wacom Graphire", 10206, 7422, 511, 63,
GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x81 =
+ { "Wacom Graphire BT", 16704, 12064, 511, 32,
+ GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x11 =
{ "Wacom Graphire2 4x5", 10206, 7422, 511, 63,
GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
@@ -2424,6 +2513,10 @@ static const struct wacom_features wacom_features_0x309 =
HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
.driver_data = (kernel_ulong_t)&wacom_features_##prod
+#define BT_DEVICE_WACOM(prod) \
+ HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+ .driver_data = (kernel_ulong_t)&wacom_features_##prod
+
#define USB_DEVICE_LENOVO(prod) \
HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \
.driver_data = (kernel_ulong_t)&wacom_features_##prod
@@ -2481,6 +2574,7 @@ const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x69) },
{ USB_DEVICE_WACOM(0x6A) },
{ USB_DEVICE_WACOM(0x6B) },
+ { BT_DEVICE_WACOM(0x81) },
{ USB_DEVICE_WACOM(0x84) },
{ USB_DEVICE_WACOM(0x90) },
{ USB_DEVICE_WACOM(0x93) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 7565be5..b4a2262 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -46,6 +46,7 @@
/* wacom data packet report IDs */
#define WACOM_REPORT_PENABLED 2
+#define WACOM_REPORT_PENABLED_BT 3
#define WACOM_REPORT_INTUOSREAD 5
#define WACOM_REPORT_INTUOSWRITE 6
#define WACOM_REPORT_INTUOSPAD 12
@@ -72,6 +73,7 @@
enum {
PENPARTNER = 0,
GRAPHIRE,
+ GRAPHIRE_BT,
WACOM_G4,
PTU,
PL,
@@ -167,6 +169,8 @@ struct wacom_wac {
int num_contacts_left;
int bat_charging;
int ps_connected;
+ __u8 bt_features;
+ __u8 bt_high_speed;
};
#endif
--
2.0.0
^ permalink raw reply related
* [PATCH 4/5] Input - wacom: handle Intuos 4 BT in wacom.ko
From: Benjamin Tissoires @ 2014-07-10 18:44 UTC (permalink / raw)
To: Przemo Firszt, Dmitry Torokhov, Jiri Kosina, Ping Cheng,
Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405017900-16024-1-git-send-email-benjamin.tissoires@redhat.com>
Now that wacom is a hid driver, there is no point in having a separate
driver for bluetooth devices.
Another good point of this is that now, the Intuos4 bluetooth can handle
the different tools (artpen, airbrush), and we get a common interface
between USB and BT for accessing the LEDs/OLEDs.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/hid/hid-core.c | 1 -
drivers/hid/hid-wacom.c | 1 -
drivers/input/tablet/wacom_sys.c | 22 ++++++++++--
drivers/input/tablet/wacom_wac.c | 73 ++++++++++++++++++++++++++++++++++++++++
drivers/input/tablet/wacom_wac.h | 1 +
5 files changed, 94 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 22be644..7c02e77 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1940,7 +1940,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) },
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index 967c457..db2d07d 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -952,7 +952,6 @@ static void wacom_remove(struct hid_device *hdev)
}
static const struct hid_device_id wacom_devices[] = {
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
{ }
};
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 86db1dc..c107a34 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -305,6 +305,20 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed,
hid_warn(hdev, "failed to poke device, command %d, err %d\n",
rep_data[0], ret);
break;
+ case INTUOS4WL:
+ if (speed == 1)
+ wacom->wacom_wac.bt_features &= ~0x20;
+ else
+ wacom->wacom_wac.bt_features |= 0x20;
+
+ rep_data[0] = 0x03;
+ rep_data[1] = wacom->wacom_wac.bt_features;
+
+ ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
+ HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+ if (ret >= 0)
+ wacom->wacom_wac.bt_high_speed = speed;
+ break;
}
return 0;
@@ -726,6 +740,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
switch (wacom->wacom_wac.features.type) {
case INTUOS4S:
case INTUOS4:
+ case INTUOS4WL:
case INTUOS4L:
wacom->led.select[0] = 0;
wacom->led.select[1] = 0;
@@ -792,6 +807,7 @@ static void wacom_destroy_leds(struct wacom *wacom)
switch (wacom->wacom_wac.features.type) {
case INTUOS4S:
case INTUOS4:
+ case INTUOS4WL:
case INTUOS4L:
sysfs_remove_group(&wacom->hdev->dev.kobj,
&intuos4_led_attr_group);
@@ -860,7 +876,8 @@ static int wacom_initialize_battery(struct wacom *wacom, const char *name)
int i;
if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) ||
- (wacom->wacom_wac.features.type == GRAPHIRE_BT)) {
+ (wacom->wacom_wac.features.type == GRAPHIRE_BT) ||
+ (wacom->wacom_wac.features.type == INTUOS4WL)) {
wacom->battery.properties = wacom_battery_props;
wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
wacom->battery.get_property = wacom_battery_get_property;
@@ -887,7 +904,8 @@ static int wacom_initialize_battery(struct wacom *wacom, const char *name)
static void wacom_destroy_battery(struct wacom *wacom)
{
if (((wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) ||
- (wacom->wacom_wac.features.type == GRAPHIRE_BT)) &&
+ (wacom->wacom_wac.features.type == GRAPHIRE_BT) ||
+ (wacom->wacom_wac.features.type == INTUOS4WL)) &&
wacom->battery.dev) {
power_supply_unregister(&wacom->battery);
wacom->battery.dev = NULL;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 20fc356..3101cc8 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -34,6 +34,9 @@
8th value means AC online and show 100% capacity */
static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
+/*percent of battery capacity for Intuos4 WL, AC has a separate bit*/
+static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
+
static int wacom_penpartner_irq(struct wacom_wac *wacom)
{
unsigned char *data = wacom->data;
@@ -953,6 +956,58 @@ static int int_dist(int x1, int y1, int x2, int y2)
return int_sqrt(x*x + y*y);
}
+static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
+ unsigned char *data)
+{
+ memcpy(wacom->data, data, 10);
+ wacom_intuos_irq(wacom);
+
+ input_sync(wacom->input);
+ if (wacom->pad_input)
+ input_sync(wacom->pad_input);
+}
+
+static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
+{
+ unsigned char data[WACOM_PKGLEN_MAX];
+ int i = 1;
+ unsigned power_raw, battery_capacity, bat_charging, ps_connected;
+
+ memcpy(data, wacom->data, len);
+
+ switch (data[0]) {
+ case 0x04:
+ wacom_intuos_bt_process_data(wacom, data + i);
+ i += 10;
+ /* fall through */
+ case 0x03:
+ wacom_intuos_bt_process_data(wacom, data + i);
+ i += 10;
+ wacom_intuos_bt_process_data(wacom, data + i);
+ i += 10;
+ power_raw = data[i];
+ bat_charging = (power_raw & 0x08) ? 1 : 0;
+ ps_connected = (power_raw & 0x10) ? 1 : 0;
+ battery_capacity = batcap_i4[power_raw & 0x07];
+ if ((wacom->battery_capacity != battery_capacity) ||
+ (wacom->bat_charging != bat_charging) ||
+ (wacom->ps_connected != ps_connected)) {
+ wacom->battery_capacity = battery_capacity;
+ wacom->bat_charging = bat_charging;
+ wacom->ps_connected = ps_connected;
+ wacom_notify_battery(wacom);
+ }
+
+ break;
+ default:
+ dev_dbg(wacom->input->dev.parent,
+ "Unknown report: %d,%d size:%li\n",
+ data[0], data[1], len);
+ return 0;
+ }
+ return 0;
+}
+
static int wacom_24hdt_irq(struct wacom_wac *wacom)
{
struct input_dev *input = wacom->input;
@@ -1512,6 +1567,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
sync = wacom_intuos_irq(wacom_wac);
break;
+ case INTUOS4WL:
+ sync = wacom_intuos_bt_irq(wacom_wac, len);
+ break;
+
case WACOM_24HDT:
sync = wacom_24hdt_irq(wacom_wac);
break;
@@ -1801,6 +1860,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
break;
case INTUOS4:
+ case INTUOS4WL:
case INTUOS4L:
case INTUOS4S:
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
@@ -2063,6 +2123,15 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
break;
+ case INTUOS4WL:
+ /*
+ * For Bluetooth devices, the udev rule does not work correctly
+ * for pads unless we add a stylus capability, which forces
+ * ID_INPUT_TABLET to be set.
+ */
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+ /* fall through */
+
case INTUOS4:
case INTUOS4L:
__set_bit(BTN_7, input_dev->keybit);
@@ -2277,6 +2346,9 @@ static const struct wacom_features wacom_features_0xBB =
static const struct wacom_features wacom_features_0xBC =
{ "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xBD =
+ { "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
+ INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0x26 =
{ "Wacom Intuos5 touch S", 31496, 19685, 2047, 63,
INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
@@ -2593,6 +2665,7 @@ const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xBA) },
{ USB_DEVICE_WACOM(0xBB) },
{ USB_DEVICE_WACOM(0xBC) },
+ { BT_DEVICE_WACOM(0xBD) },
{ USB_DEVICE_WACOM(0xC0) },
{ USB_DEVICE_WACOM(0xC2) },
{ USB_DEVICE_WACOM(0xC4) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index b4a2262..3b3a40c 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -85,6 +85,7 @@ enum {
INTUOS3L,
INTUOS4S,
INTUOS4,
+ INTUOS4WL,
INTUOS4L,
INTUOS5S,
INTUOS5,
--
2.0.0
^ permalink raw reply related
* [PATCH 5/5] HID: remove hid-wacom Bluetooth driver
From: Benjamin Tissoires @ 2014-07-10 18:45 UTC (permalink / raw)
To: Przemo Firszt, Dmitry Torokhov, Jiri Kosina, Ping Cheng,
Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405017900-16024-1-git-send-email-benjamin.tissoires@redhat.com>
Bluetooth Wacom tablets are now handled by the regular wacom.ko driver.
Remove the now useless hid-wacom driver.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/hid/Kconfig | 8 -
drivers/hid/Makefile | 1 -
drivers/hid/hid-wacom.c | 971 ------------------------------------------------
3 files changed, 980 deletions(-)
delete mode 100644 drivers/hid/hid-wacom.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 191637c..261e67f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -761,14 +761,6 @@ config THRUSTMASTER_FF
a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT
Rumble Force or Force Feedback Wheel.
-config HID_WACOM
- tristate "Wacom Bluetooth devices support"
- depends on HID
- depends on LEDS_CLASS
- select POWER_SUPPLY
- ---help---
- Support for Wacom Graphire Bluetooth and Intuos4 WL tablets.
-
config HID_WIIMOTE
tristate "Nintendo Wii / Wii U peripherals"
depends on HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 058b5f0..4a39680 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -116,7 +116,6 @@ obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o
obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
-obj-$(CONFIG_HID_WACOM) += hid-wacom.o
obj-$(CONFIG_HID_WALTOP) += hid-waltop.o
obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o
obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
deleted file mode 100644
index db2d07d..0000000
--- a/drivers/hid/hid-wacom.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- * Bluetooth Wacom Tablet support
- *
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
- * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
- * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
- * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
- * Copyright (c) 2011 Przemysław Firszt <przemo@firszt.eu>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/leds.h>
-#include <linux/slab.h>
-#include <linux/power_supply.h>
-
-#include "hid-ids.h"
-
-#define PAD_DEVICE_ID 0x0F
-
-#define WAC_CMD_LED_CONTROL 0x20
-#define WAC_CMD_ICON_START_STOP 0x21
-#define WAC_CMD_ICON_TRANSFER 0x26
-
-struct wacom_data {
- __u16 tool;
- __u16 butstate;
- __u8 whlstate;
- __u8 features;
- __u32 id;
- __u32 serial;
- unsigned char high_speed;
- __u8 battery_capacity;
- __u8 power_raw;
- __u8 ps_connected;
- __u8 bat_charging;
- struct power_supply battery;
- struct power_supply ac;
- __u8 led_selector;
- struct led_classdev *leds[4];
-};
-
-/*percent of battery capacity for Graphire
- 8th value means AC online and show 100% capacity */
-static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
-/*percent of battery capacity for Intuos4 WL, AC has a separate bit*/
-static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
-
-static enum power_supply_property wacom_battery_props[] = {
- POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_SCOPE,
- POWER_SUPPLY_PROP_STATUS,
-};
-
-static enum power_supply_property wacom_ac_props[] = {
- POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_ONLINE,
- POWER_SUPPLY_PROP_SCOPE,
-};
-
-static void wacom_scramble(__u8 *image)
-{
- __u16 mask;
- __u16 s1;
- __u16 s2;
- __u16 r1 ;
- __u16 r2 ;
- __u16 r;
- __u8 buf[256];
- int i, w, x, y, z;
-
- for (x = 0; x < 32; x++) {
- for (y = 0; y < 8; y++)
- buf[(8 * x) + (7 - y)] = image[(8 * x) + y];
- }
-
- /* Change 76543210 into GECA6420 as required by Intuos4 WL
- * HGFEDCBA HFDB7531
- */
- for (x = 0; x < 4; x++) {
- for (y = 0; y < 4; y++) {
- for (z = 0; z < 8; z++) {
- mask = 0x0001;
- r1 = 0;
- r2 = 0;
- i = (x << 6) + (y << 4) + z;
- s1 = buf[i];
- s2 = buf[i+8];
- for (w = 0; w < 8; w++) {
- r1 |= (s1 & mask);
- r2 |= (s2 & mask);
- s1 <<= 1;
- s2 <<= 1;
- mask <<= 2;
- }
- r = r1 | (r2 << 1);
- i = (x << 6) + (y << 4) + (z << 1);
- image[i] = 0xFF & r;
- image[i+1] = (0xFF00 & r) >> 8;
- }
- }
- }
-}
-
-static void wacom_set_image(struct hid_device *hdev, const char *image,
- __u8 icon_no)
-{
- __u8 rep_data[68];
- __u8 p[256];
- int ret, i, j;
-
- for (i = 0; i < 256; i++)
- p[i] = image[i];
-
- rep_data[0] = WAC_CMD_ICON_START_STOP;
- rep_data[1] = 0;
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- if (ret < 0)
- goto err;
-
- rep_data[0] = WAC_CMD_ICON_TRANSFER;
- rep_data[1] = icon_no & 0x07;
-
- wacom_scramble(p);
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 64; j++)
- rep_data[j + 3] = p[(i << 6) + j];
-
- rep_data[2] = i;
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 67,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- }
-
- rep_data[0] = WAC_CMD_ICON_START_STOP;
- rep_data[1] = 0;
-
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-
-err:
- return;
-}
-
-static void wacom_leds_set_brightness(struct led_classdev *led_dev,
- enum led_brightness value)
-{
- struct device *dev = led_dev->dev->parent;
- struct hid_device *hdev;
- struct wacom_data *wdata;
- unsigned char *buf;
- __u8 led = 0;
- int i;
-
- hdev = container_of(dev, struct hid_device, dev);
- wdata = hid_get_drvdata(hdev);
- for (i = 0; i < 4; ++i) {
- if (wdata->leds[i] == led_dev)
- wdata->led_selector = i;
- }
-
- led = wdata->led_selector | 0x04;
- buf = kzalloc(9, GFP_KERNEL);
- if (buf) {
- buf[0] = WAC_CMD_LED_CONTROL;
- buf[1] = led;
- buf[2] = value >> 2;
- buf[3] = value;
- /* use fixed brightness for OLEDs */
- buf[4] = 0x08;
- hid_hw_raw_request(hdev, buf[0], buf, 9, HID_FEATURE_REPORT,
- HID_REQ_SET_REPORT);
- kfree(buf);
- }
-
- return;
-}
-
-static enum led_brightness wacom_leds_get_brightness(struct led_classdev *led_dev)
-{
- struct wacom_data *wdata;
- struct device *dev = led_dev->dev->parent;
- int value = 0;
- int i;
-
- wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
-
- for (i = 0; i < 4; ++i) {
- if (wdata->leds[i] == led_dev) {
- value = wdata->leds[i]->brightness;
- break;
- }
- }
-
- return value;
-}
-
-
-static int wacom_initialize_leds(struct hid_device *hdev)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
- struct led_classdev *led;
- struct device *dev = &hdev->dev;
- size_t namesz = strlen(dev_name(dev)) + 12;
- char *name;
- int i, ret;
-
- wdata->led_selector = 0;
-
- for (i = 0; i < 4; i++) {
- led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL);
- if (!led) {
- hid_warn(hdev,
- "can't allocate memory for LED selector\n");
- ret = -ENOMEM;
- goto err;
- }
-
- name = (void *)&led[1];
- snprintf(name, namesz, "%s:selector:%d", dev_name(dev), i);
- led->name = name;
- led->brightness = 0;
- led->max_brightness = 127;
- led->brightness_get = wacom_leds_get_brightness;
- led->brightness_set = wacom_leds_set_brightness;
-
- wdata->leds[i] = led;
-
- ret = led_classdev_register(dev, wdata->leds[i]);
-
- if (ret) {
- wdata->leds[i] = NULL;
- kfree(led);
- hid_warn(hdev, "can't register LED\n");
- goto err;
- }
- }
-
-err:
- return ret;
-}
-
-static void wacom_destroy_leds(struct hid_device *hdev)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
- struct led_classdev *led;
- int i;
-
- for (i = 0; i < 4; ++i) {
- if (wdata->leds[i]) {
- led = wdata->leds[i];
- wdata->leds[i] = NULL;
- led_classdev_unregister(led);
- kfree(led);
- }
- }
-
-}
-
-static int wacom_battery_get_property(struct power_supply *psy,
- enum power_supply_property psp,
- union power_supply_propval *val)
-{
- struct wacom_data *wdata = container_of(psy,
- struct wacom_data, battery);
- int ret = 0;
-
- switch (psp) {
- case POWER_SUPPLY_PROP_PRESENT:
- val->intval = 1;
- break;
- case POWER_SUPPLY_PROP_SCOPE:
- val->intval = POWER_SUPPLY_SCOPE_DEVICE;
- break;
- case POWER_SUPPLY_PROP_CAPACITY:
- val->intval = wdata->battery_capacity;
- break;
- case POWER_SUPPLY_PROP_STATUS:
- if (wdata->bat_charging)
- val->intval = POWER_SUPPLY_STATUS_CHARGING;
- else
- if (wdata->battery_capacity == 100 && wdata->ps_connected)
- val->intval = POWER_SUPPLY_STATUS_FULL;
- else
- val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
-static int wacom_ac_get_property(struct power_supply *psy,
- enum power_supply_property psp,
- union power_supply_propval *val)
-{
- struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
- int ret = 0;
-
- switch (psp) {
- case POWER_SUPPLY_PROP_PRESENT:
- /* fall through */
- case POWER_SUPPLY_PROP_ONLINE:
- val->intval = wdata->ps_connected;
- break;
- case POWER_SUPPLY_PROP_SCOPE:
- val->intval = POWER_SUPPLY_SCOPE_DEVICE;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
-static void wacom_set_features(struct hid_device *hdev, u8 speed)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
- int limit, ret;
- __u8 rep_data[2];
-
- switch (hdev->product) {
- case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
- rep_data[0] = 0x03 ; rep_data[1] = 0x00;
- limit = 3;
- do {
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- } while (ret < 0 && limit-- > 0);
-
- if (ret >= 0) {
- if (speed == 0)
- rep_data[0] = 0x05;
- else
- rep_data[0] = 0x06;
-
- rep_data[1] = 0x00;
- limit = 3;
- do {
- ret = hid_hw_raw_request(hdev, rep_data[0],
- rep_data, 2, HID_FEATURE_REPORT,
- HID_REQ_SET_REPORT);
- } while (ret < 0 && limit-- > 0);
-
- if (ret >= 0) {
- wdata->high_speed = speed;
- return;
- }
- }
-
- /*
- * Note that if the raw queries fail, it's not a hard failure
- * and it is safe to continue
- */
- hid_warn(hdev, "failed to poke device, command %d, err %d\n",
- rep_data[0], ret);
- break;
- case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
- if (speed == 1)
- wdata->features &= ~0x20;
- else
- wdata->features |= 0x20;
-
- rep_data[0] = 0x03;
- rep_data[1] = wdata->features;
-
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- if (ret >= 0)
- wdata->high_speed = speed;
- break;
- }
-
- return;
-}
-
-static ssize_t wacom_show_speed(struct device *dev,
- struct device_attribute
- *attr, char *buf)
-{
- struct wacom_data *wdata = dev_get_drvdata(dev);
-
- return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed);
-}
-
-static ssize_t wacom_store_speed(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- int new_speed;
-
- if (sscanf(buf, "%1d", &new_speed ) != 1)
- return -EINVAL;
-
- if (new_speed == 0 || new_speed == 1) {
- wacom_set_features(hdev, new_speed);
- return strnlen(buf, PAGE_SIZE);
- } else
- return -EINVAL;
-}
-
-static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
- wacom_show_speed, wacom_store_speed);
-
-#define WACOM_STORE(OLED_ID) \
-static ssize_t wacom_oled##OLED_ID##_store(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct hid_device *hdev = container_of(dev, struct hid_device, \
- dev); \
- \
- if (count != 256) \
- return -EINVAL; \
- \
- wacom_set_image(hdev, buf, OLED_ID); \
- \
- return count; \
-} \
- \
-static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL, \
- wacom_oled##OLED_ID##_store)
-
-WACOM_STORE(0);
-WACOM_STORE(1);
-WACOM_STORE(2);
-WACOM_STORE(3);
-WACOM_STORE(4);
-WACOM_STORE(5);
-WACOM_STORE(6);
-WACOM_STORE(7);
-
-static int wacom_gr_parse_report(struct hid_device *hdev,
- struct wacom_data *wdata,
- struct input_dev *input, unsigned char *data)
-{
- int tool, x, y, rw;
-
- tool = 0;
- /* Get X & Y positions */
- x = le16_to_cpu(*(__le16 *) &data[2]);
- y = le16_to_cpu(*(__le16 *) &data[4]);
-
- /* Get current tool identifier */
- if (data[1] & 0x90) { /* If pen is in the in/active area */
- switch ((data[1] >> 5) & 3) {
- case 0: /* Pen */
- tool = BTN_TOOL_PEN;
- break;
-
- case 1: /* Rubber */
- tool = BTN_TOOL_RUBBER;
- break;
-
- case 2: /* Mouse with wheel */
- case 3: /* Mouse without wheel */
- tool = BTN_TOOL_MOUSE;
- break;
- }
-
- /* Reset tool if out of active tablet area */
- if (!(data[1] & 0x10))
- tool = 0;
- }
-
- /* If tool changed, notify input subsystem */
- if (wdata->tool != tool) {
- if (wdata->tool) {
- /* Completely reset old tool state */
- if (wdata->tool == BTN_TOOL_MOUSE) {
- input_report_key(input, BTN_LEFT, 0);
- input_report_key(input, BTN_RIGHT, 0);
- input_report_key(input, BTN_MIDDLE, 0);
- input_report_abs(input, ABS_DISTANCE,
- input_abs_get_max(input, ABS_DISTANCE));
- } else {
- input_report_key(input, BTN_TOUCH, 0);
- input_report_key(input, BTN_STYLUS, 0);
- input_report_key(input, BTN_STYLUS2, 0);
- input_report_abs(input, ABS_PRESSURE, 0);
- }
- input_report_key(input, wdata->tool, 0);
- input_sync(input);
- }
- wdata->tool = tool;
- if (tool)
- input_report_key(input, tool, 1);
- }
-
- if (tool) {
- input_report_abs(input, ABS_X, x);
- input_report_abs(input, ABS_Y, y);
-
- switch ((data[1] >> 5) & 3) {
- case 2: /* Mouse with wheel */
- input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
- rw = (data[6] & 0x01) ? -1 :
- (data[6] & 0x02) ? 1 : 0;
- input_report_rel(input, REL_WHEEL, rw);
- /* fall through */
-
- case 3: /* Mouse without wheel */
- input_report_key(input, BTN_LEFT, data[1] & 0x01);
- input_report_key(input, BTN_RIGHT, data[1] & 0x02);
- /* Compute distance between mouse and tablet */
- rw = 44 - (data[6] >> 2);
- if (rw < 0)
- rw = 0;
- else if (rw > 31)
- rw = 31;
- input_report_abs(input, ABS_DISTANCE, rw);
- break;
-
- default:
- input_report_abs(input, ABS_PRESSURE,
- data[6] | (((__u16) (data[1] & 0x08)) << 5));
- input_report_key(input, BTN_TOUCH, data[1] & 0x01);
- input_report_key(input, BTN_STYLUS, data[1] & 0x02);
- input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
- break;
- }
-
- input_sync(input);
- }
-
- /* Report the state of the two buttons at the top of the tablet
- * as two extra fingerpad keys (buttons 4 & 5). */
- rw = data[7] & 0x03;
- if (rw != wdata->butstate) {
- wdata->butstate = rw;
- input_report_key(input, BTN_0, rw & 0x02);
- input_report_key(input, BTN_1, rw & 0x01);
- input_report_key(input, BTN_TOOL_FINGER, 0xf0);
- input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
- input_sync(input);
- }
-
- /* Store current battery capacity and power supply state*/
- rw = (data[7] >> 2 & 0x07);
- if (rw != wdata->power_raw) {
- wdata->power_raw = rw;
- wdata->battery_capacity = batcap_gr[rw];
- if (rw == 7)
- wdata->ps_connected = 1;
- else
- wdata->ps_connected = 0;
- }
- return 1;
-}
-
-static void wacom_i4_parse_button_report(struct wacom_data *wdata,
- struct input_dev *input, unsigned char *data)
-{
- __u16 new_butstate;
- __u8 new_whlstate;
- __u8 sync = 0;
-
- new_whlstate = data[1];
- if (new_whlstate != wdata->whlstate) {
- wdata->whlstate = new_whlstate;
- if (new_whlstate & 0x80) {
- input_report_key(input, BTN_TOUCH, 1);
- input_report_abs(input, ABS_WHEEL, (new_whlstate & 0x7f));
- input_report_key(input, BTN_TOOL_FINGER, 1);
- } else {
- input_report_key(input, BTN_TOUCH, 0);
- input_report_abs(input, ABS_WHEEL, 0);
- input_report_key(input, BTN_TOOL_FINGER, 0);
- }
- sync = 1;
- }
-
- new_butstate = (data[3] << 1) | (data[2] & 0x01);
- if (new_butstate != wdata->butstate) {
- wdata->butstate = new_butstate;
- input_report_key(input, BTN_0, new_butstate & 0x001);
- input_report_key(input, BTN_1, new_butstate & 0x002);
- input_report_key(input, BTN_2, new_butstate & 0x004);
- input_report_key(input, BTN_3, new_butstate & 0x008);
- input_report_key(input, BTN_4, new_butstate & 0x010);
- input_report_key(input, BTN_5, new_butstate & 0x020);
- input_report_key(input, BTN_6, new_butstate & 0x040);
- input_report_key(input, BTN_7, new_butstate & 0x080);
- input_report_key(input, BTN_8, new_butstate & 0x100);
- input_report_key(input, BTN_TOOL_FINGER, 1);
- sync = 1;
- }
-
- if (sync) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
- input_sync(input);
- }
-}
-
-static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
- struct input_dev *input, unsigned char *data)
-{
- __u16 x, y, pressure;
- __u8 distance;
- __u8 tilt_x, tilt_y;
-
- switch (data[1]) {
- case 0x80: /* Out of proximity report */
- input_report_key(input, BTN_TOUCH, 0);
- input_report_abs(input, ABS_PRESSURE, 0);
- input_report_key(input, BTN_STYLUS, 0);
- input_report_key(input, BTN_STYLUS2, 0);
- input_report_key(input, wdata->tool, 0);
- input_report_abs(input, ABS_MISC, 0);
- input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
- wdata->tool = 0;
- input_sync(input);
- break;
- case 0xC2: /* Tool report */
- wdata->id = ((data[2] << 4) | (data[3] >> 4) |
- ((data[7] & 0x0f) << 20) |
- ((data[8] & 0xf0) << 12));
- wdata->serial = ((data[3] & 0x0f) << 28) +
- (data[4] << 20) + (data[5] << 12) +
- (data[6] << 4) + (data[7] >> 4);
-
- switch (wdata->id) {
- case 0x100802:
- wdata->tool = BTN_TOOL_PEN;
- break;
- case 0x10080A:
- wdata->tool = BTN_TOOL_RUBBER;
- break;
- }
- break;
- default: /* Position/pressure report */
- x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1);
- y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01);
- pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5)
- | (data[1] & 0x01);
- distance = (data[9] >> 2) & 0x3f;
- tilt_x = ((data[7] << 1) & 0x7e) | (data[8] >> 7);
- tilt_y = data[8] & 0x7f;
-
- input_report_key(input, BTN_TOUCH, pressure > 1);
-
- input_report_key(input, BTN_STYLUS, data[1] & 0x02);
- input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
- input_report_key(input, wdata->tool, 1);
- input_report_abs(input, ABS_X, x);
- input_report_abs(input, ABS_Y, y);
- input_report_abs(input, ABS_PRESSURE, pressure);
- input_report_abs(input, ABS_DISTANCE, distance);
- input_report_abs(input, ABS_TILT_X, tilt_x);
- input_report_abs(input, ABS_TILT_Y, tilt_y);
- input_report_abs(input, ABS_MISC, wdata->id);
- input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
- input_report_key(input, wdata->tool, 1);
- input_sync(input);
- break;
- }
-
- return;
-}
-
-static void wacom_i4_parse_report(struct hid_device *hdev,
- struct wacom_data *wdata,
- struct input_dev *input, unsigned char *data)
-{
- switch (data[0]) {
- case 0x00: /* Empty report */
- break;
- case 0x02: /* Pen report */
- wacom_i4_parse_pen_report(wdata, input, data);
- break;
- case 0x03: /* Features Report */
- wdata->features = data[2];
- break;
- case 0x0C: /* Button report */
- wacom_i4_parse_button_report(wdata, input, data);
- break;
- default:
- hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]);
- break;
- }
-}
-
-static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
- u8 *raw_data, int size)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
- struct hid_input *hidinput;
- struct input_dev *input;
- unsigned char *data = (unsigned char *) raw_data;
- int i;
- __u8 power_raw;
-
- if (!(hdev->claimed & HID_CLAIMED_INPUT))
- return 0;
-
- hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
- input = hidinput->input;
-
- switch (hdev->product) {
- case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
- if (data[0] == 0x03) {
- return wacom_gr_parse_report(hdev, wdata, input, data);
- } else {
- hid_err(hdev, "Unknown report: %d,%d size:%d\n",
- data[0], data[1], size);
- return 0;
- }
- break;
- case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
- i = 1;
-
- switch (data[0]) {
- case 0x04:
- wacom_i4_parse_report(hdev, wdata, input, data + i);
- i += 10;
- /* fall through */
- case 0x03:
- wacom_i4_parse_report(hdev, wdata, input, data + i);
- i += 10;
- wacom_i4_parse_report(hdev, wdata, input, data + i);
- power_raw = data[i+10];
- if (power_raw != wdata->power_raw) {
- wdata->power_raw = power_raw;
- wdata->battery_capacity = batcap_i4[power_raw & 0x07];
- wdata->bat_charging = (power_raw & 0x08) ? 1 : 0;
- wdata->ps_connected = (power_raw & 0x10) ? 1 : 0;
- }
-
- break;
- default:
- hid_err(hdev, "Unknown report: %d,%d size:%d\n",
- data[0], data[1], size);
- return 0;
- }
- }
- return 1;
-}
-
-static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
- struct hid_field *field, struct hid_usage *usage, unsigned long **bit,
- int *max)
-{
- struct input_dev *input = hi->input;
-
- __set_bit(INPUT_PROP_POINTER, input->propbit);
-
- /* Basics */
- input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
-
- __set_bit(REL_WHEEL, input->relbit);
-
- __set_bit(BTN_TOOL_PEN, input->keybit);
- __set_bit(BTN_TOUCH, input->keybit);
- __set_bit(BTN_STYLUS, input->keybit);
- __set_bit(BTN_STYLUS2, input->keybit);
- __set_bit(BTN_LEFT, input->keybit);
- __set_bit(BTN_RIGHT, input->keybit);
- __set_bit(BTN_MIDDLE, input->keybit);
-
- /* Pad */
- input_set_capability(input, EV_MSC, MSC_SERIAL);
-
- __set_bit(BTN_0, input->keybit);
- __set_bit(BTN_1, input->keybit);
- __set_bit(BTN_TOOL_FINGER, input->keybit);
-
- /* Distance, rubber and mouse */
- __set_bit(BTN_TOOL_RUBBER, input->keybit);
- __set_bit(BTN_TOOL_MOUSE, input->keybit);
-
- switch (hdev->product) {
- case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
- input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
- input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
- input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
- input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
- break;
- case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
- __set_bit(ABS_WHEEL, input->absbit);
- __set_bit(ABS_MISC, input->absbit);
- __set_bit(BTN_2, input->keybit);
- __set_bit(BTN_3, input->keybit);
- __set_bit(BTN_4, input->keybit);
- __set_bit(BTN_5, input->keybit);
- __set_bit(BTN_6, input->keybit);
- __set_bit(BTN_7, input->keybit);
- __set_bit(BTN_8, input->keybit);
- input_set_abs_params(input, ABS_WHEEL, 0, 71, 0, 0);
- input_set_abs_params(input, ABS_X, 0, 40640, 4, 0);
- input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0);
- input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0);
- input_set_abs_params(input, ABS_DISTANCE, 0, 63, 0, 0);
- input_set_abs_params(input, ABS_TILT_X, 0, 127, 0, 0);
- input_set_abs_params(input, ABS_TILT_Y, 0, 127, 0, 0);
- break;
- }
-
- return 0;
-}
-
-static int wacom_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- struct wacom_data *wdata;
- int ret;
-
- wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
- if (wdata == NULL) {
- hid_err(hdev, "can't alloc wacom descriptor\n");
- return -ENOMEM;
- }
-
- hid_set_drvdata(hdev, wdata);
-
- /* Parse the HID report now */
- ret = hid_parse(hdev);
- if (ret) {
- hid_err(hdev, "parse failed\n");
- goto err_free;
- }
-
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret) {
- hid_err(hdev, "hw start failed\n");
- goto err_free;
- }
-
- ret = device_create_file(&hdev->dev, &dev_attr_speed);
- if (ret)
- hid_warn(hdev,
- "can't create sysfs speed attribute err: %d\n", ret);
-
-#define OLED_INIT(OLED_ID) \
- do { \
- ret = device_create_file(&hdev->dev, \
- &dev_attr_oled##OLED_ID##_img); \
- if (ret) \
- hid_warn(hdev, \
- "can't create sysfs oled attribute, err: %d\n", ret);\
- } while (0)
-
-OLED_INIT(0);
-OLED_INIT(1);
-OLED_INIT(2);
-OLED_INIT(3);
-OLED_INIT(4);
-OLED_INIT(5);
-OLED_INIT(6);
-OLED_INIT(7);
-
- wdata->features = 0;
- wacom_set_features(hdev, 1);
-
- if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) {
- sprintf(hdev->name, "%s", "Wacom Intuos4 WL");
- ret = wacom_initialize_leds(hdev);
- if (ret)
- hid_warn(hdev,
- "can't create led attribute, err: %d\n", ret);
- }
-
- wdata->battery.properties = wacom_battery_props;
- wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
- wdata->battery.get_property = wacom_battery_get_property;
- wdata->battery.name = "wacom_battery";
- wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
- wdata->battery.use_for_apm = 0;
-
-
- ret = power_supply_register(&hdev->dev, &wdata->battery);
- if (ret) {
- hid_err(hdev, "can't create sysfs battery attribute, err: %d\n",
- ret);
- goto err_battery;
- }
-
- power_supply_powers(&wdata->battery, &hdev->dev);
-
- wdata->ac.properties = wacom_ac_props;
- wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
- wdata->ac.get_property = wacom_ac_get_property;
- wdata->ac.name = "wacom_ac";
- wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
- wdata->ac.use_for_apm = 0;
-
- ret = power_supply_register(&hdev->dev, &wdata->ac);
- if (ret) {
- hid_err(hdev,
- "can't create ac battery attribute, err: %d\n", ret);
- goto err_ac;
- }
-
- power_supply_powers(&wdata->ac, &hdev->dev);
- return 0;
-
-err_ac:
- power_supply_unregister(&wdata->battery);
-err_battery:
- wacom_destroy_leds(hdev);
- device_remove_file(&hdev->dev, &dev_attr_oled0_img);
- device_remove_file(&hdev->dev, &dev_attr_oled1_img);
- device_remove_file(&hdev->dev, &dev_attr_oled2_img);
- device_remove_file(&hdev->dev, &dev_attr_oled3_img);
- device_remove_file(&hdev->dev, &dev_attr_oled4_img);
- device_remove_file(&hdev->dev, &dev_attr_oled5_img);
- device_remove_file(&hdev->dev, &dev_attr_oled6_img);
- device_remove_file(&hdev->dev, &dev_attr_oled7_img);
- device_remove_file(&hdev->dev, &dev_attr_speed);
- hid_hw_stop(hdev);
-err_free:
- kfree(wdata);
- return ret;
-}
-
-static void wacom_remove(struct hid_device *hdev)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
-
- wacom_destroy_leds(hdev);
- device_remove_file(&hdev->dev, &dev_attr_oled0_img);
- device_remove_file(&hdev->dev, &dev_attr_oled1_img);
- device_remove_file(&hdev->dev, &dev_attr_oled2_img);
- device_remove_file(&hdev->dev, &dev_attr_oled3_img);
- device_remove_file(&hdev->dev, &dev_attr_oled4_img);
- device_remove_file(&hdev->dev, &dev_attr_oled5_img);
- device_remove_file(&hdev->dev, &dev_attr_oled6_img);
- device_remove_file(&hdev->dev, &dev_attr_oled7_img);
- device_remove_file(&hdev->dev, &dev_attr_speed);
- hid_hw_stop(hdev);
-
- power_supply_unregister(&wdata->battery);
- power_supply_unregister(&wdata->ac);
- kfree(hid_get_drvdata(hdev));
-}
-
-static const struct hid_device_id wacom_devices[] = {
-
- { }
-};
-MODULE_DEVICE_TABLE(hid, wacom_devices);
-
-static struct hid_driver wacom_driver = {
- .name = "hid-wacom",
- .id_table = wacom_devices,
- .probe = wacom_probe,
- .remove = wacom_remove,
- .raw_event = wacom_raw_event,
- .input_mapped = wacom_input_mapped,
-};
-module_hid_driver(wacom_driver);
-
-MODULE_DESCRIPTION("Driver for Wacom Graphire Bluetooth and Wacom Intuos4 WL");
-MODULE_LICENSE("GPL");
--
2.0.0
^ permalink raw reply related
* [PATCH 0/5] Input - wacom: battery enhancements and unifying hid-wacom and wacom
From: Benjamin Tissoires @ 2014-07-10 18:44 UTC (permalink / raw)
To: Przemo Firszt, Dmitry Torokhov, Jiri Kosina, Ping Cheng,
Jason Gerecke
Cc: linux-kernel, linux-input
Hi guys,
Continuing on the Wacom cleanup, here are 5 patches.
The first two enhance the battery reporting for the Wireless receiver by
adding the status of the battery (discharging, full, charging) - inspired by
the code found in hid-wacom.c, and also by adding notifications to the power
system so that upower knows when the battery changed.
The last three are the handling of the two Wacom Bluetooth devices in wacom.ko.
Some enhancements here:
- Intuos4 now supports other tools than just the plain stylus (mouse, artpen, ...)
- one less driver for Wacom (~700 lines of code less in total)
- unifying access to LEDs/OLEDs from Bluetooth and USB devices
However, I did not backport the speed attribute and the ac power device (which
is infered by the battery status). I don't know if there are users of those two,
so I let them aside for now. Przemo, any ideas if this is actually used?
This whole code is based on top of the previous HID conversion patches.
I pushed a branch with all I have queued on the list here:
https://github.com/bentiss/linux/commits/hid-wacom-legacy-3.16-rc4
Again, given that there has been no answer on how this can be merged upstream
(Jiri? Dmitry?), I just piled those on top of the previous.
I wouldn't to resplit the input and hid specific changes if this is the choice
that is made.
Cheers,
Benjamin
Benjamin Tissoires (5):
Input - wacom: enhance Wireless Receiver battery reporting
Input - wacom: use a specific name for the battery device
Input - wacom: handle Graphire BT tablets in wacom.ko
Input - wacom: handle Intuos 4 BT in wacom.ko
HID: remove hid-wacom Bluetooth driver
drivers/hid/Kconfig | 8 -
drivers/hid/Makefile | 1 -
drivers/hid/hid-core.c | 2 -
drivers/hid/hid-wacom.c | 973 ---------------------------------------
drivers/input/tablet/wacom.h | 6 +
drivers/input/tablet/wacom_sys.c | 114 ++++-
drivers/input/tablet/wacom_wac.c | 189 +++++++-
drivers/input/tablet/wacom_wac.h | 8 +
8 files changed, 303 insertions(+), 998 deletions(-)
delete mode 100644 drivers/hid/hid-wacom.c
--
2.0.0
^ permalink raw reply
* [PATCH 1/5] Input - wacom: enhance Wireless Receiver battery reporting
From: Benjamin Tissoires @ 2014-07-10 18:44 UTC (permalink / raw)
To: Przemo Firszt, Dmitry Torokhov, Jiri Kosina, Ping Cheng,
Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405017900-16024-1-git-send-email-benjamin.tissoires@redhat.com>
- Reports the current status of the battery (discharging, cherging, full).
- Also notify the upower daemon when there is a change in the battery
value.
- keep the battery value as a percentage, not the raw value
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom.h | 6 ++++++
drivers/input/tablet/wacom_sys.c | 13 ++++++++++++-
drivers/input/tablet/wacom_wac.c | 18 +++++++++++++++---
drivers/input/tablet/wacom_wac.h | 2 ++
4 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index a678f82..99516ba 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -128,6 +128,12 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
schedule_work(&wacom->work);
}
+static inline void wacom_notify_battery(struct wacom_wac *wacom_wac)
+{
+ struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+ power_supply_changed(&wacom->battery);
+}
+
extern const struct hid_device_id wacom_ids[];
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index fb2958e..1888709 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -766,6 +766,7 @@ static void wacom_destroy_leds(struct wacom *wacom)
}
static enum power_supply_property wacom_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_SCOPE,
POWER_SUPPLY_PROP_CAPACITY
};
@@ -783,7 +784,16 @@ static int wacom_battery_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval =
- wacom->wacom_wac.battery_capacity * 100 / 31;
+ wacom->wacom_wac.battery_capacity;
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ if (wacom->wacom_wac.bat_charging)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (wacom->wacom_wac.battery_capacity == 100 &&
+ wacom->wacom_wac.ps_connected)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break;
default:
ret = -EINVAL;
@@ -944,6 +954,7 @@ static void wacom_wireless_work(struct work_struct *work)
if (wacom_wac->pid == 0) {
hid_info(wacom->hdev, "wireless tablet disconnected\n");
+ wacom_wac1->shared->type = 0;
} else {
const struct hid_device_id *id = wacom_ids;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index cd91521..d935f75 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1365,7 +1365,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
connected = data[1] & 0x01;
if (connected) {
- int pid, battery;
+ int pid, battery, ps_connected;
if ((wacom->shared->type == INTUOSHT) &&
wacom->shared->touch_max) {
@@ -1375,17 +1375,29 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
}
pid = get_unaligned_be16(&data[6]);
- battery = data[5] & 0x3f;
+ battery = (data[5] & 0x3f) * 100 / 31;
+ ps_connected = data[5] & 0x80;
if (wacom->pid != pid) {
wacom->pid = pid;
wacom_schedule_work(wacom);
}
- wacom->battery_capacity = battery;
+
+ if (wacom->shared->type &&
+ ((battery != wacom->battery_capacity) ||
+ (ps_connected != wacom->ps_connected))) {
+ wacom->battery_capacity = battery;
+ wacom->ps_connected = ps_connected;
+ wacom->bat_charging = ps_connected &&
+ wacom->battery_capacity < 100;
+ wacom_notify_battery(wacom);
+ }
} else if (wacom->pid != 0) {
/* disconnected while previously connected */
wacom->pid = 0;
wacom_schedule_work(wacom);
wacom->battery_capacity = 0;
+ wacom->bat_charging = 0;
+ wacom->ps_connected = 0;
}
return 0;
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 4c59247..68cf257 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -164,6 +164,8 @@ struct wacom_wac {
int pid;
int battery_capacity;
int num_contacts_left;
+ int bat_charging;
+ int ps_connected;
};
#endif
--
2.0.0
^ permalink raw reply related
* FW: elantech modification to use with new asus touchpads
From: Arjan Opmeer @ 2014-07-10 20:17 UTC (permalink / raw)
To: linux-input
Please have a look at this:
----- Forwarded message from Marius Monton <marius.monton@gmail.com> -----
Date: Thu, 10 Jul 2014 19:43:27 +0200
Delivery-date: Thu, 10 Jul 2014 19:43:41 +0200
From: Marius Monton <marius.monton@gmail.com>
To: arjan@opmeer.net
Subject: elantech modification to use with new asus touchpads
Hello Arjan
I've sending this email because you are in the list of developer for the
elantech.c kernel module.
I have a asus s301L laptop with a unrecognized touchpad by elantech.
After debugging the output of the module, I realized that the touchpad
returns a invalid signature (to the elantech_is_signature_valid function).
Elantech version query result 0x46, 0x1f, 0x14.
I've managed to remove this signature from the list and voilà! it is
working
If you need some more information or some job for me to do, don't hesitate
to contact me.
Best regards, and thank you for your work
--
Màrius
----- End forwarded message -----
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] Input: Add Acer Aspire 5710 to nomux blacklist
From: Dmitry Torokhov @ 2014-07-10 21:11 UTC (permalink / raw)
To: Hans de Goede; +Cc: Vojtech Pavlik, Jiri Kosina, linux-input
In-Reply-To: <53BEAF57.30409@redhat.com>
On Thu, Jul 10, 2014 at 05:20:55PM +0200, Hans de Goede wrote:
> Hi,
>
> On 07/10/2014 10:45 AM, Vojtech Pavlik wrote:
> > On Thu, Jul 10, 2014 at 09:32:16AM +0200, Hans de Goede wrote:
> >
> >>>>> I also expect
> >>>>> that most of external PS/2 mice are dead by now, so number of cases when
> >>>>
> >>>> One would at least hope so. Sadly, internal mice and PS/2 keyboards
> >>>> aren't going to go away any soon, due to larger power consumption of USB
> >>>> devices.
> >>>
> >>> Right, but we are not talking about mouse vs keyboard, they use separate
> >>> ports anyway, it is touchpad plus external PS/2 mouse case where active
> >>> MUX might help.
> >>
> >> What about laptops with both a touchpad and a trackpoint ? I think in most
> >> cases the trackpoint works through some sort of pass-through mode of the
> >> touchpad (or is outright part of the touchpad ps/2 device), but are we
> >> sure there are no cases where the trackpoint and touchpad are really
> >> separate ps/2 devices hookedup through an active mux ?
> >
> > I'm not aware of any current machines using active multiplexing for
> > that. There are basically two touchpad manufacturers: Synaptics and
> > ALPS.
>
> And elantech
>
> > Synaptics has a nearly transparent passthrough mode and
> > touchpoints are connected through that. ALPS basically manufactures a
> > touchpad+touchpoint combo device and thus doesn't need a fully
> > transparent passthrough.
>
> Elantech now a days also produces a combo like alps.
They still wire it up internally and route all data through AUX port and
not use active MUX for that.
>
> > Active multiplexing was typically used for external PS/2 ports on
> > laptops, because the manufacturer couldn't anticipate the protocol of
> > the externally connected device.
>
> Right, but what about users who still have a laptop with an external
> ps/2 port which they happen to also still use ?
The assertion that it works well now, which is a stretch. As far as I
know Windows by default does not activate it, so manufacturers rarely
test it.
>
>
>
> >
> >>>>> we have users with PS/2 touchpad + external PS/2 mouse + working active
> >>>>> MUX is exceedingly small.
> >>>>>
> >>>>> Let's pull Vojtech in ;)
> >>>>
> >>>> What I'd prefer is to, based on DMI data, report but not enable by
> >>>> default Active MUX mode on any machine manufactured after a certain
> >>>> date. Plus have a DMI-based whitelist for machines that absolutely
> >>>> needed, if any are found later.
> >>>
> >>> Looking at the changes to nomux blacklist sometimes even trying MUX
> >>> messes up KBC. Instead of playing date games I'd rather simply make
> >>> i8042.nomux default. I'm fine with having whitelist for boxes that
> >>> actually need and support muxing properly.
> >>
> >> I'm a bit skeptical about making this change, see above.
> >
> > I'm not too keen about it either, as it could break existing setups.
> >
> > But I have to concede that any working hardware still using both
> > external and internal PS/2 and thus needing Active Multiplexing is most
> > likely to be found in museums today.
> >
> > So the risk of breakage isn't all that big.
>
> One of the nice things about Linux is that in general we've pretty
> decent support for older hardware, so if we decide to flip the nomux
> default, I think we should really do so based on some BIOS cut-off
> date, so as to not break older model laptops.
I think historically IBM and HPs had working MUX support while other's
did might advertise support and fail miserably when we would try
activating it.
Given that now majority of mice are USB even if we select wrong default
on some older box I think it would be acceptable as opposed to a newer
box not having touchpad at all...
Thanks.
--
Dmitry
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox