* Re: [PATCH 14/14] alps: Add support for v7 devices
From: Dmitry Torokhov @ 2014-07-26 5:58 UTC (permalink / raw)
To: Hans de Goede; +Cc: Yunkang Tang, linux-input
In-Reply-To: <1404919459-23561-15-git-send-email-hdegoede@redhat.com>
Hi Hans,
On Wed, Jul 09, 2014 at 05:24:19PM +0200, Hans de Goede wrote:
> 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;
Maybe:
switch (psmouse->pktcnt) {
case 3:
return (psmouse->packet[2] & 0x40) == 0x40;
case 4:
return (psmouse->packet[3] & 0x48) == 0x48;
case 6:
return (psmouse->packet[5] & 0x40) == 0x00;
}
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++)
> + ;
/* empty */;
just to make sure...
> +
> + 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[])
bool
> +{
> + int valid = 1;
bool; true
> +
> + if (id[0] == 0x73)
> + valid = 1;
true
> + else if (id[0] == 0x88) {
> + if ((id[1] == 0x07) ||
> + (id[1] == 0x08) ||
> + ((id[1] & 0xf0) == 0xB0))
> + valid = 1;
true
> + }
> +
> + return valid;
Hmmm, does not make sense - it is never false...
> +}
> +
> 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
>
Thanks.
--
Dmitry
--
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 00/14] alps: bugfixes, cleanups and new hardware support
From: Dmitry Torokhov @ 2014-07-26 5:59 UTC (permalink / raw)
To: Hans de Goede; +Cc: Yunkang Tang, linux-input
In-Reply-To: <1404919459-23561-1-git-send-email-hdegoede@redhat.com>
Hi Hans,
On Wed, Jul 09, 2014 at 05:24:05PM +0200, Hans de Goede wrote:
> Hi All,
>
> This series started out as a single patch to add support for a new model
> of alps touchpad, called PROTO_V7 in this patchset.
>
> While working on this I ended up doing some refactoring as preparation, which
> I tested on a Rushmore alps touchpad, which lead to some bugfixes and more
> cleanups, etc.
>
> The result is a 14 patch patch-set, which:
>
> 1) Significantly improves multi-touch support on V3 and V4 models (including
> the Rushmore V3 variant)
> 2) Improves the code quality / readability quite a bit
> 3) Adds support for PROTO_V7
Excellent series, very easy to read. I have applied everything but v7
support as I have questions about that patch.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2] Input: add i2c/smbus driver for elan touchpad
From: cheng wei Lin @ 2014-07-26 8:12 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, linux-input, bleung, agnescheng,
"SRD1 �蝬踐��?都����",
jeff.chuang
In-Reply-To: <20140725200656.GA2827@core.coreip.homeip.net>
Hi Dmitry,
Yes, we intend to do this. Could you help to keep the original code, thank you.
Duson
Dmitry Torokhov <dmitry.torokhov@gmail.com> 於 2014/7/26 上午4:06 寫道:
> On Fri, Jul 25, 2014 at 11:20:53AM -0700, Dmitry Torokhov wrote:
>> Hi Duson,
>>
>> On Sat, Jul 26, 2014 at 02:05:02AM +0800, cheng wei Lin wrote:
>>> Hi Dmitry,
>>>
>>> Sorry for late to reply you and thanks for your command
>>>
>>> Yes, I also agree, it looks great than my original code.
>>
>> Thank you for confirming.
>>
>>> So, should I modify this and upstream v3 patch for you?
>>
>> No, that is fine, I'll fix it up on my end.
>
> Hmm, I am also looking at elan_get_x_resolution() and in case of SMB
> we'll never get negative result since we are doing
> "elan_convert_res(val[1] & 0x0F)". Was it intended as such, or do we
> need to extend sign here via
>
> (((char)(val[1] & 0x0F)) << 4) >> 4;
>
> Thanks.
>
> --
> Dmitry
>
--
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 14/14] alps: Add support for v7 devices
From: Hans de Goede @ 2014-07-26 8:22 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Yunkang Tang, linux-input
In-Reply-To: <20140726055811.GA31435@core.coreip.homeip.net>
Hi,
On 07/26/2014 07:59 AM, Dmitry Torokhov wrote:> Hi Hans,
>
> On Wed, Jul 09, 2014 at 05:24:05PM +0200, Hans de Goede wrote:
>> Hi All,
>>
>> This series started out as a single patch to add support for a new model
>> of alps touchpad, called PROTO_V7 in this patchset.
>>
>> While working on this I ended up doing some refactoring as preparation, which
>> I tested on a Rushmore alps touchpad, which lead to some bugfixes and more
>> cleanups, etc.
>>
>> The result is a 14 patch patch-set, which:
>>
>> 1) Significantly improves multi-touch support on V3 and V4 models (including
>> the Rushmore V3 variant)
>> 2) Improves the code quality / readability quite a bit
>> 3) Adds support for PROTO_V7
>
> Excellent series, very easy to read. I have applied everything but v7
> support as I have questions about that patch.
I'm glad you like the series, that shows that my work to split it into
manageable bits was worth the extra effort, so that is good to hear.
On 07/26/2014 07:58 AM, Dmitry Torokhov wrote:
> Hi Hans,
>
> On Wed, Jul 09, 2014 at 05:24:19PM +0200, Hans de Goede wrote:
>> 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;
>
> Maybe:
>
> switch (psmouse->pktcnt) {
> case 3:
> return (psmouse->packet[2] & 0x40) == 0x40;
>
> case 4:
> return (psmouse->packet[3] & 0x48) == 0x48;
>
> case 6:
> return (psmouse->packet[5] & 0x40) == 0x00;
> }
>
> return true;
>
> ?
Will fix.
>
>
>> +}
>> +
>> +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++)
>> + ;
>
> /* empty */;
>
> just to make sure...
Will fix.
>
>> +
>> + 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[])
>
> bool
>
>> +{
>> + int valid = 1;
>
> bool; true
>
>> +
>> + if (id[0] == 0x73)
>> + valid = 1;
>
> true
>
>> + else if (id[0] == 0x88) {
>> + if ((id[1] == 0x07) ||
>> + (id[1] == 0x08) ||
>> + ((id[1] & 0xf0) == 0xB0))
>> + valid = 1;
>
> true
>
>> + }
>> +
>> + return valid;
>
> Hmmm, does not make sense - it is never false...
Right, if you look at the code it factors out (below)
valid should clearly be initialized to false, good catch.
Or even better, don't have valid at all simply use
"return true" in the if blocks and "return false"
at the end, that's what I'll do for v2.
>
>> +}
>> +
>> 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;
>> }
Regards,
Hans
--
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 v5 0/4] HID: lenovo: Add support for Lenovo Compact Keyboard
From: Jamie Lentin @ 2014-07-26 10:09 UTC (permalink / raw)
To: Antonio Ospite; +Cc: Jiri Kosina, Hans de Goede, linux-input, linux-kernel
In-Reply-To: <20140725160527.13cbeae1108fce5e09b6daae@ao2.it>
On Fri, 25 Jul 2014, Antonio Ospite wrote:
> On Wed, 23 Jul 2014 23:30:44 +0100
> Jamie Lentin <jm@lentin.co.uk> wrote:
>
>> This patchset follows on from my previous attempts to add support for
>> these keyboards from Lenovo.
>>
>> Antonio, I've used cptkbd_data and left data_pointer for now. It'd be
>> an easy patch to change data_pointer to tpkbd_data, but is drifting
>> away from what this patchset is supposed to do. Could send that
>> afterwards though.
>>
>
> Sure, no problem. I think we are good to go.
>
> BTW I was considering picking up one of such compact keyboards myself,
> but I read that the BT one uses the USB cable only for charging
> and it does not show as a USB HID device when plugged in, can you
> confirm that?
Yes, nothing happens over USB other than charging. It's slightly
irritating since I have to keep something else to hand for booting, or try
and get a dongle that goes into a HID proxy mode.
That said, I quite like it as a keyboard and happily use it for working
all day. Interestingly the bluetooth version is nicer to type on than the
USB version, even though they look physically identical. This could be
they came from different batches rather than using better keys for the
Bluetooth version.
> Thanks,
> Antonio
^ permalink raw reply
* Re: [PATCH v2 00/10] Input - wacom: conversion to HID driver, series 2
From: Przemo Firszt @ 2014-07-26 11:55 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke,
linux-kernel, linux-input
In-Reply-To: <20140725231509.GA2279@mail.corp.redhat.com>
Dnia 2014-07-25, pią o godzinie 19:15 -0400, Benjamin Tissoires pisze:
> [..]
Hi Bejnamin,
> > I don't remember for sure, but I think the range of brightness might be different
> > over usb and over bluetooth.
>
> Maybe you can try setting the sysfs file "buttons_luminance" with the
> value 8 to check if this will solve the bug.
No, that doesn't make any difference.
> The bug might also be linked to the slight difference while setting up
> the transfer of the image (WAC_CMD_ICON_START) with the value of buf[1]
> set to 1 in USB, while it was 0 on bluetooth.
>
> The weird thing is that I remembered having set the OLED (though
> scrambled) with these patches applied. I guess the scrambling was due to
> the 4-bit vs 1-bit. But I definitively had some results.
I spotted something:
hid-wacom:c (before modifications)
#define WAC_CMD_ICON_TRANSFER 0x26
wacom_sys.c: (after modifications)
#define WAC_CMD_ICON_XFER 0x23
Changing it fixes the problem. Patches to follow soon.
--
Kind regards,
Przemo Firszt
^ permalink raw reply
* [PATCH 1/2] Input - Wacom: Fix transfer header problem
From: Przemo Firszt @ 2014-07-26 11:59 UTC (permalink / raw)
To: benjamin.tissoires
Cc: dmitry.torokhov, jkosina, pinglinux, killertofu, linux-kernel,
linux-input, Przemo Firszt
Header of transfer of image is different depending on connection type.
That patch should be probably merged with 462c52a8cbcc62c
Input - wacom: Check for bluetooth protocol while setting OLEDs
Signed-off-by: Przemo Firszt <przemo@firszt.eu>
---
drivers/hid/wacom_sys.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 42f139f..51437e2 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -19,6 +19,7 @@
#define WAC_CMD_LED_CONTROL 0x20
#define WAC_CMD_ICON_START 0x21
+#define WAC_CMD_ICON_BT_XFER 0x26
#define WAC_CMD_ICON_XFER 0x23
#define WAC_CMD_RETRIES 10
@@ -550,7 +551,7 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id,
if (retval < 0)
goto out;
- buf[0] = WAC_CMD_ICON_XFER;
+ buf[0] = len == 256 ? WAC_CMD_ICON_BT_XFER : WAC_CMD_ICON_XFER;
buf[1] = button_id & 0x07;
for (i = 0; i < 4; i++) {
buf[2] = i;
--
1.9.3
^ permalink raw reply related
* Re: [PATCH 11/10] Input - wacom: Check for bluetooth protocol while setting OLEDs
From: Przemo Firszt @ 2014-07-26 12:05 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke,
linux-kernel, linux-input
In-Reply-To: <1406330411-7851-1-git-send-email-benjamin.tissoires@redhat.com>
Whole series (after including bt image fix):
Tested-By: Przemo Firszt <przemo@firszt.eu>
Dnia 2014-07-25, pią o godzinie 19:20 -0400, Benjamin Tissoires pisze:
> Bluetooth Intuos 4 use 1-bit definition while the USB ones use a 4-bits
> definition. This changes the size of the raw image we receive, and thus
> the kernel will only accept 1-bit images for Bluetooth and 4-bits for
> USB.
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
> drivers/hid/wacom_sys.c | 15 +++++++++------
> 1 file changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
> index 3adc6ef..42f139f 100644
> --- a/drivers/hid/wacom_sys.c
> +++ b/drivers/hid/wacom_sys.c
> @@ -531,12 +531,14 @@ static int wacom_led_control(struct wacom *wacom)
> return retval;
> }
>
> -static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img)
> +static int wacom_led_putimage(struct wacom *wacom, int button_id,
> + const unsigned len, const void *img)
> {
> unsigned char *buf;
> int i, retval;
> + const unsigned chunk_len = len / 4; /* 4 chunks are needed to be sent */
>
> - buf = kzalloc(259, GFP_KERNEL);
> + buf = kzalloc(chunk_len + 3 , GFP_KERNEL);
> if (!buf)
> return -ENOMEM;
>
> @@ -552,11 +554,11 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im
> buf[1] = button_id & 0x07;
> for (i = 0; i < 4; i++) {
> buf[2] = i;
> - memcpy(buf + 3, img + i * 256, 256);
> + memcpy(buf + 3, img + i * chunk_len, chunk_len);
>
> retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
> WAC_CMD_ICON_XFER,
> - buf, 259, WAC_CMD_RETRIES);
> + buf, chunk_len + 3, WAC_CMD_RETRIES);
> if (retval < 0)
> break;
> }
> @@ -657,13 +659,14 @@ static ssize_t wacom_button_image_store(struct device *dev, int button_id,
> struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> struct wacom *wacom = hid_get_drvdata(hdev);
> int err;
> + const unsigned len = hdev->bus == BUS_BLUETOOTH ? 256 : 1024;
>
> - if (count != 1024)
> + if (count != len)
> return -EINVAL;
>
> mutex_lock(&wacom->lock);
>
> - err = wacom_led_putimage(wacom, button_id, buf);
> + err = wacom_led_putimage(wacom, button_id, len, buf);
>
> mutex_unlock(&wacom->lock);
>
--
Kind regards,
Przemo Firszt
^ permalink raw reply
* [PATCH v2] alps: Add support for v7 devices
From: Hans de Goede @ 2014-07-26 12:13 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Yunkang Tang, Hans de Goede
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>
--
Changes in v2:
-alps_is_valid_package_v7: switch to using a switch-case
-alps_check_valid_firmware_id: fix to not always return true
---
drivers/input/mouse/alps.c | 256 ++++++++++++++++++++++++++++++++++++++++++++-
drivers/input/mouse/alps.h | 18 ++++
2 files changed, 271 insertions(+), 3 deletions(-)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index ad3a708..ac9fdbd 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,179 @@ 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)
+{
+ switch (psmouse->pktcnt) {
+ case 3:
+ return (psmouse->packet[2] & 0x40) == 0x40;
+ case 4:
+ return (psmouse->packet[3] & 0x48) == 0x48;
+ case 6:
+ return (psmouse->packet[5] & 0x40) == 0x00;
+ }
+ 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++)
+ /* empty */;
+
+ 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 +1183,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 +1303,19 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
return 0;
}
+static bool alps_check_valid_firmware_id(unsigned char id[])
+{
+ if (id[0] == 0x73)
+ return true;
+
+ if (id[0] == 0x88 &&
+ (id[1] == 0x07 || id[1] == 0x08 ||
+ (id[1] & 0xf0) == 0xb0 || (id[1] & 0xf0) == 0xc0))
+ return true;
+
+ return false;
+}
+
static int alps_enter_command_mode(struct psmouse *psmouse)
{
unsigned char param[4];
@@ -1130,8 +1325,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 +1979,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 +2063,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 +2149,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 +2226,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 +2275,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 +2294,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 2/2] Input - wacom: Remove passing id for wacom_set_report
From: Przemo Firszt @ 2014-07-26 11:59 UTC (permalink / raw)
To: benjamin.tissoires
Cc: dmitry.torokhov, jkosina, pinglinux, killertofu, linux-kernel,
linux-input, Przemo Firszt
In-Reply-To: <1406375969-4453-1-git-send-email-przemo@firszt.eu>
Every call of wacom_set_report was passing "id" as a separate parameter
and buffer also passed the same information. We can use first u8 of the
buffer instead of "id"
Signed-off-by: Przemo Firszt <przemo@firszt.eu>
---
drivers/hid/wacom_sys.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 51437e2..db17198 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -36,13 +36,13 @@ static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id,
return retval;
}
-static int wacom_set_report(struct hid_device *hdev, u8 type, u8 id,
- void *buf, size_t size, unsigned int retries)
+static int wacom_set_report(struct hid_device *hdev, u8 type, u8 *buf,
+ size_t size, unsigned int retries)
{
int retval;
do {
- retval = hid_hw_raw_request(hdev, id, buf, size, type,
+ retval = hid_hw_raw_request(hdev, buf[0], buf, size, type,
HID_REQ_SET_REPORT);
} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
@@ -251,8 +251,8 @@ static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
rep_data[0] = report_id;
rep_data[1] = mode;
- error = wacom_set_report(hdev, HID_FEATURE_REPORT,
- report_id, rep_data, length, 1);
+ error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data,
+ length, 1);
if (error >= 0)
error = wacom_get_report(hdev, HID_FEATURE_REPORT,
report_id, rep_data, length, 1);
@@ -525,8 +525,8 @@ static int wacom_led_control(struct wacom *wacom)
buf[4] = wacom->led.img_lum;
}
- retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
- WAC_CMD_LED_CONTROL, buf, 9, WAC_CMD_RETRIES);
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 9,
+ WAC_CMD_RETRIES);
kfree(buf);
return retval;
@@ -546,8 +546,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id,
/* Send 'start' command */
buf[0] = WAC_CMD_ICON_START;
buf[1] = 1;
- retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
- WAC_CMD_ICON_START, buf, 2, WAC_CMD_RETRIES);
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2,
+ WAC_CMD_RETRIES);
if (retval < 0)
goto out;
@@ -557,9 +557,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id,
buf[2] = i;
memcpy(buf + 3, img + i * chunk_len, chunk_len);
- retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
- WAC_CMD_ICON_XFER,
- buf, chunk_len + 3, WAC_CMD_RETRIES);
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf,
+ chunk_len + 3, WAC_CMD_RETRIES);
if (retval < 0)
break;
}
@@ -567,8 +566,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id,
/* Send 'stop' */
buf[0] = WAC_CMD_ICON_START;
buf[1] = 0;
- wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, WAC_CMD_ICON_START,
- buf, 2, WAC_CMD_RETRIES);
+ wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2,
+ WAC_CMD_RETRIES);
out:
kfree(buf);
--
1.9.3
^ permalink raw reply related
* Re: [PATCH] Input: synaptics - properly initialize slots for semi-MT
From: Benjamin Tissoires @ 2014-07-26 14:15 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, Hans de Goede, Benson Leung, Henrik Rydberg,
linux-kernel
In-Reply-To: <20140726002751.GA16660@core.coreip.homeip.net>
On Jul 25 2014 or thereabouts, Dmitry Torokhov wrote:
> Semi-MT devices are pointers too, so let's tell that to
> input_mt_init_slots(), as well as let it set up the devices as semi-MT,
> instead of us doing it manually.
>
> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> Reviewed-by: Benson Leung <bleung@chromium.org>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> drivers/input/mouse/synaptics.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> index ef9e0b8..fe607e9 100644
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -1371,11 +1371,11 @@ static void set_input_params(struct psmouse *psmouse,
> __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
> __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
> } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
> - /* Non-image sensors with AGM use semi-mt */
> - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
> - input_mt_init_slots(dev, 2, 0);
> set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
> ABS_MT_POSITION_Y);
> + /* Non-image sensors with AGM use semi-mt */
> + input_mt_init_slots(dev, 2,
> + INPUT_MT_POINTER | INPUT_MT_SEMI_MT);
> }
>
> if (SYN_CAP_PALMDETECT(priv->capabilities))
> --
> 2.0.0.526.g5318336
>
>
> --
> Dmitry
^ permalink raw reply
* [PATCH] hid: hid-prodikeys.c: Cleaning up missing null-terminate in conjunction with strncpy
From: Rickard Strandqvist @ 2014-07-26 14:21 UTC (permalink / raw)
To: Jiri Kosina, linux-input; +Cc: Rickard Strandqvist, linux-kernel
Replacing strncpy with strlcpy to avoid strings that lacks null terminate.
Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
---
drivers/hid/hid-prodikeys.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index 91fab97..007c7f5 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -641,9 +641,9 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
goto fail;
}
- strncpy(card->driver, shortname, sizeof(card->driver));
- strncpy(card->shortname, shortname, sizeof(card->shortname));
- strncpy(card->longname, longname, sizeof(card->longname));
+ strlcpy(card->driver, shortname, sizeof(card->driver));
+ strlcpy(card->shortname, shortname, sizeof(card->shortname));
+ strlcpy(card->longname, longname, sizeof(card->longname));
/* Set up rawmidi */
err = snd_rawmidi_new(card, card->shortname, 0,
@@ -654,7 +654,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
goto fail;
}
pm->rwmidi = rwmidi;
- strncpy(rwmidi->name, card->shortname, sizeof(rwmidi->name));
+ strlcpy(rwmidi->name, card->shortname, sizeof(rwmidi->name));
rwmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT;
rwmidi->private_data = pm;
--
1.7.10.4
^ permalink raw reply related
* [PATCH v6 3/4] HID: lenovo: Don't call function in condition, show error codes
From: Jamie Lentin @ 2014-07-26 14:42 UTC (permalink / raw)
To: Jiri Kosina, Antonio Ospite, Dmitry Torokhov
Cc: linux-input, linux-kernel, Jamie Lentin
In-Reply-To: <1406154648-14000-4-git-send-email-jm@lentin.co.uk>
Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
---
drivers/hid/hid-lenovo.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index a56b9e7..f96bf09 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -350,6 +350,7 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
size_t name_sz = strlen(dev_name(dev)) + 16;
char *name_mute, *name_micmute;
int i;
+ int ret;
/*
* Only register extra settings against subdevice where input_mapping
@@ -368,10 +369,9 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
return -ENODEV;
- if (sysfs_create_group(&hdev->dev.kobj,
- &lenovo_attr_group_tpkbd)) {
- hid_warn(hdev, "Could not create sysfs group\n");
- }
+ ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd);
+ if (ret)
+ hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
data_pointer = devm_kzalloc(&hdev->dev,
sizeof(struct lenovo_drvdata_tpkbd),
--
2.0.0
^ permalink raw reply related
* Re: [PATCH] Input: synaptics - properly initialize slots for semi-MT
From: Henrik Rydberg @ 2014-07-26 15:50 UTC (permalink / raw)
To: Dmitry Torokhov, linux-input
Cc: Hans de Goede, Benjamin Tissoires, Benson Leung, linux-kernel
In-Reply-To: <20140726002751.GA16660@core.coreip.homeip.net>
Hi Dmitry,
On 07/26/2014 02:27 AM, Dmitry Torokhov wrote:
> Semi-MT devices are pointers too, so let's tell that to
> input_mt_init_slots(), as well as let it set up the devices as semi-MT,
> instead of us doing it manually.
>
> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> Reviewed-by: Benson Leung <bleung@chromium.org>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/input/mouse/synaptics.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> index ef9e0b8..fe607e9 100644
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -1371,11 +1371,11 @@ static void set_input_params(struct psmouse *psmouse,
> __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
> __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
> } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
> - /* Non-image sensors with AGM use semi-mt */
> - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
> - input_mt_init_slots(dev, 2, 0);
> set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
> ABS_MT_POSITION_Y);
> + /* Non-image sensors with AGM use semi-mt */
> + input_mt_init_slots(dev, 2,
> + INPUT_MT_POINTER | INPUT_MT_SEMI_MT);
> }
As long as DOUBLE_TAP is set unconditionally in this path anyways, it should be
ok. I have a vague memory of refraining from this exact change at some point,
because of the many branches of settings.
>
> if (SYN_CAP_PALMDETECT(priv->capabilities))
>
Henrik
^ permalink raw reply
* [PATCH] hid: uhid.c: Cleaning up missing null-terminate in conjunction with strncpy
From: Rickard Strandqvist @ 2014-07-26 16:46 UTC (permalink / raw)
To: David Herrmann, Jiri Kosina
Cc: Rickard Strandqvist, linux-input, linux-kernel
Replacing strncpy with strlcpy to avoid strings that lacks null terminate.
And removed unnecessary magic numbers.
Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
---
drivers/hid/uhid.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 0cb92e3..b72ab0c 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -392,12 +392,9 @@ static int uhid_dev_create(struct uhid_device *uhid,
goto err_free;
}
- strncpy(hid->name, ev->u.create.name, 127);
- hid->name[127] = 0;
- strncpy(hid->phys, ev->u.create.phys, 63);
- hid->phys[63] = 0;
- strncpy(hid->uniq, ev->u.create.uniq, 63);
- hid->uniq[63] = 0;
+ strlcpy(hid->name, ev->u.create.name, sizeof(hid->name));
+ strlcpy(hid->phys, ev->u.create.phys, sizeof(hid->phys));
+ strlcpy(hid->uniq, ev->u.create.uniq, sizeof(hid->uniq));
hid->ll_driver = &uhid_hid_driver;
hid->bus = ev->u.create.bus;
@@ -452,12 +449,9 @@ static int uhid_dev_create2(struct uhid_device *uhid,
goto err_free;
}
- strncpy(hid->name, ev->u.create2.name, 127);
- hid->name[127] = 0;
- strncpy(hid->phys, ev->u.create2.phys, 63);
- hid->phys[63] = 0;
- strncpy(hid->uniq, ev->u.create2.uniq, 63);
- hid->uniq[63] = 0;
+ strlcpy(hid->name, ev->u.create2.name, sizeof(hid->name));
+ strlcpy(hid->phys, ev->u.create2.phys, sizeof(hid->phys));
+ strlcpy(hid->uniq, ev->u.create2.uniq, sizeof(hid->uniq));
hid->ll_driver = &uhid_hid_driver;
hid->bus = ev->u.create2.bus;
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH v2] alps: Add support for v7 devices
From: Dmitry Torokhov @ 2014-07-26 21:09 UTC (permalink / raw)
To: Hans de Goede; +Cc: linux-input, Yunkang Tang
In-Reply-To: <1406376832-7135-1-git-send-email-hdegoede@redhat.com>
Hi Hans,
On Sat, Jul 26, 2014 at 02:13:52PM +0200, Hans de Goede wrote:
> 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>
>
> --
> Changes in v2:
> -alps_is_valid_package_v7: switch to using a switch-case
> -alps_check_valid_firmware_id: fix to not always return true
Thank you for whipping the update so quickly.
> +
> +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;
> + }
I took the liberty of changing the above to another switch/case...
>
> +static bool alps_check_valid_firmware_id(unsigned char id[])
> +{
> + if (id[0] == 0x73)
> + return true;
> +
> + if (id[0] == 0x88 &&
> + (id[1] == 0x07 || id[1] == 0x08 ||
> + (id[1] & 0xf0) == 0xb0 || (id[1] & 0xf0) == 0xc0))
And split this condition into 1 line per id[1] check...
> + return true;
> +
> + return false;
> +}
> +
And applied and pushed out everything.
Thanks.
--
Dmitry
--
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: synaptics - properly initialize slots for semi-MT
From: Dmitry Torokhov @ 2014-07-26 21:12 UTC (permalink / raw)
To: Henrik Rydberg
Cc: linux-input, Hans de Goede, Benjamin Tissoires, Benson Leung,
linux-kernel
In-Reply-To: <53D3CE2E.3040103@bitmath.org>
On Sat, Jul 26, 2014 at 05:50:06PM +0200, Henrik Rydberg wrote:
> Hi Dmitry,
>
> On 07/26/2014 02:27 AM, Dmitry Torokhov wrote:
> > Semi-MT devices are pointers too, so let's tell that to
> > input_mt_init_slots(), as well as let it set up the devices as semi-MT,
> > instead of us doing it manually.
> >
> > Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> > Reviewed-by: Benson Leung <bleung@chromium.org>
> > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > ---
> > drivers/input/mouse/synaptics.c | 6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> > index ef9e0b8..fe607e9 100644
> > --- a/drivers/input/mouse/synaptics.c
> > +++ b/drivers/input/mouse/synaptics.c
> > @@ -1371,11 +1371,11 @@ static void set_input_params(struct psmouse *psmouse,
> > __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
> > __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
> > } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
> > - /* Non-image sensors with AGM use semi-mt */
> > - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
> > - input_mt_init_slots(dev, 2, 0);
> > set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
> > ABS_MT_POSITION_Y);
> > + /* Non-image sensors with AGM use semi-mt */
> > + input_mt_init_slots(dev, 2,
> > + INPUT_MT_POINTER | INPUT_MT_SEMI_MT);
> > }
>
> As long as DOUBLE_TAP is set unconditionally in this path anyways, it should be
> ok. I have a vague memory of refraining from this exact change at some point,
> because of the many branches of settings.
Yes, it is, as we should be hitting the multi-finger capability check
below.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v4] Input: synaptics - use firmware data for Cr-48
From: Dmitry Torokhov @ 2014-07-26 21:18 UTC (permalink / raw)
To: Henrik Rydberg
Cc: Chung-yih Wang, linux-input, Daniel Kurtz, Seth Forshee,
Benjamin Herrenschmidt, linux-kernel
In-Reply-To: <20130220215513.GA552@polaris.bitmath.org>
Hi Henrik,
On Wed, Feb 20, 2013 at 10:55:13PM +0100, Henrik Rydberg wrote:
> Hi Chung-yih,
>
> > The profile sensor clickpad in a Cr-48 Chromebook does a reasonable job of
> > tracking individual fingers. This tracking isn't perfect, but, experiments
> > show that it works better than just passing "semi-mt" data to userspace,
> > and making userspace try to deduce where the fingers are given a bounding box.
> >
> > This patch tries to report two-finger positions directly from firmware's sgm
> > and agm packets instead of the {(min_x, min_y), (max_x, max_y)} for profile
> > sensor clickpads on Cr-48 chromebooks. Note that this device's firmware always
> > reports the higher (smaller y) finger in the "sgm" packet, and the lower
> > (larger y) finger in the "agm" packet for the state transition from one finger
> > to two finger. Then the firmware keeps tracking of fingers with the same agm
> > or sgm packets individually. Thus, when a new finger arrives on the pad, the
> > kernel driver uses a simple Euclidean distance measure to deduce which of the
> > two new fingers should keep the tracking ID of the previous single finger.
> > Similarly, when one finger is removed, the same measure is used to determine
> > which finger remained on the pad.
> >
> > Signed-off-by: Chung-yih Wang <cywang@chromium.org>
> > ---
> > drivers/input/mouse/synaptics.c | 95 +++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 95 insertions(+)
>
> I looks right per se, but the procedure is a bit more manual than it
> needs to be. The input core can handle slot allocation these days, so
> I wonder if the the two patches below work for you, as an
> alternative?
You forgot to tell input_mt_init_slots() to track the contacts, but
otherwise it works. The version of the patch below seems to work well on
Cr-48 for me.
Thanks.
--
Dmitry
Input: synaptics - use firmware data for Cr-48
From: Henrik Rydberg <rydberg@euromail.se>
The profile sensor clickpad in a Cr-48 Chromebook does a reasonable job
of tracking individual fingers. This tracking isn't perfect, but,
experiments show that it works better than just passing "semi-mt" data
to userspace, and making userspace try to deduce where the fingers are
given a bounding box.
This patch tries to report correct two-finger positions instead of the
{(min_x, min_y), (max_x, max_y)} for profile sensor clickpads on Cr-48
chromebooks. Note that this device's firmware always reports the higher
(smaller y) finger in the "sgm" packet, and the lower (larger y) finger
in the "agm" packet. Thus, when a new finger arrives on the pad, the
kernel driver uses input core's contact tracking facilities to match
contacts with slots.
Inspired by patch by Daniel Kurtz <djkurtz@chromium.org> and Chung-yih
Wang <cywang@chromium.org>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Reviewed-by: Benson Leung <bleung@chromium.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/mouse/synaptics.c | 69 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 67 insertions(+), 2 deletions(-)
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index fe607e9..f261db9 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -67,6 +67,8 @@
#define X_MAX_POSITIVE 8176
#define Y_MAX_POSITIVE 8176
+static bool cr48_profile_sensor;
+
/*****************************************************************************
* Stuff we need even when we do not want native Synaptics support
****************************************************************************/
@@ -1152,6 +1154,42 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
priv->agm_pending = false;
}
+static void synaptics_profile_sensor_process(struct psmouse *psmouse,
+ struct synaptics_hw_state *sgm,
+ int num_fingers)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct synaptics_data *priv = psmouse->private;
+ struct synaptics_hw_state *hw[2] = { sgm, &priv->agm };
+ struct input_mt_pos pos[2];
+ int slot[2], nsemi, i;
+
+ nsemi = clamp_val(num_fingers, 0, 2);
+
+ for (i = 0; i < nsemi; i++) {
+ pos[i].x = hw[i]->x;
+ pos[i].y = synaptics_invert_y(hw[i]->y);
+ }
+
+ input_mt_assign_slots(dev, slot, pos, nsemi);
+
+ for (i = 0; i < nsemi; i++) {
+ input_mt_slot(dev, slot[i]);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+ input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y);
+ input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z);
+ }
+
+ input_mt_drop_unused(dev);
+ input_mt_report_pointer_emulation(dev, false);
+ input_mt_report_finger_count(dev, num_fingers);
+
+ synaptics_report_buttons(psmouse, sgm);
+
+ input_sync(dev);
+}
+
/*
* called for each full received packet from the touchpad
*/
@@ -1215,6 +1253,11 @@ static void synaptics_process_packet(struct psmouse *psmouse)
finger_width = 0;
}
+ if (cr48_profile_sensor) {
+ synaptics_profile_sensor_process(psmouse, &hw, num_fingers);
+ return;
+ }
+
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
num_fingers);
@@ -1360,6 +1403,9 @@ static void set_input_params(struct psmouse *psmouse,
set_abs_position_params(dev, priv, ABS_X, ABS_Y);
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
+ if (cr48_profile_sensor)
+ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
ABS_MT_POSITION_Y);
@@ -1373,9 +1419,14 @@ static void set_input_params(struct psmouse *psmouse,
} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
ABS_MT_POSITION_Y);
- /* Non-image sensors with AGM use semi-mt */
+ /*
+ * Profile sensor in CR-48 tracks contacts reasonably well,
+ * other non-image sensors with AGM use semi-mt.
+ */
input_mt_init_slots(dev, 2,
- INPUT_MT_POINTER | INPUT_MT_SEMI_MT);
+ INPUT_MT_POINTER |
+ (cr48_profile_sensor ?
+ INPUT_MT_TRACK : INPUT_MT_SEMI_MT));
}
if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -1577,10 +1628,24 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
{ }
};
+static const struct dmi_system_id __initconst cr48_dmi_table[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+ {
+ /* Cr-48 Chromebook (Codename Mario) */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "IEC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
+ },
+ },
+#endif
+ { }
+};
+
void __init synaptics_module_init(void)
{
impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
broken_olpc_ec = dmi_check_system(olpc_dmi_table);
+ cr48_profile_sensor = dmi_check_system(cr48_dmi_table);
}
static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
^ permalink raw reply related
* Re: [PATCH v2] alps: Add support for v7 devices
From: Hans de Goede @ 2014-07-26 21:59 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Yunkang Tang
In-Reply-To: <20140726210912.GA11800@core.coreip.homeip.net>
Hi,
On 07/26/2014 11:09 PM, Dmitry Torokhov wrote:
> Hi Hans,
>
> On Sat, Jul 26, 2014 at 02:13:52PM +0200, Hans de Goede wrote:
>> 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>
>>
>> --
>> Changes in v2:
>> -alps_is_valid_package_v7: switch to using a switch-case
>> -alps_check_valid_firmware_id: fix to not always return true
>
> Thank you for whipping the update so quickly.
>
>> +
>> +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;
>> + }
>
> I took the liberty of changing the above to another switch/case...
>
>>
>> +static bool alps_check_valid_firmware_id(unsigned char id[])
>> +{
>> + if (id[0] == 0x73)
>> + return true;
>> +
>> + if (id[0] == 0x88 &&
>> + (id[1] == 0x07 || id[1] == 0x08 ||
>> + (id[1] & 0xf0) == 0xb0 || (id[1] & 0xf0) == 0xc0))
>
> And split this condition into 1 line per id[1] check...
>
>> + return true;
>> +
>> + return false;
>> +}
>> +
>
> And applied and pushed out everything.
Ok, thanks.
Regards,
Hans
--
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 v4] Input: synaptics-rmi4: Add F30 support
From: Dmitry Torokhov @ 2014-07-27 7:26 UTC (permalink / raw)
To: Andrew Duggan
Cc: linux-input, Christopher Heiny, Vincent Huang, Vivian Ly,
Allie Xiong, Linus Walleij, Benjamin Tissoires, David Herrmann,
Jiri Kosina
In-Reply-To: <1406245641-6263-1-git-send-email-aduggan@synaptics.com>
Hi Andrew,
On Thu, Jul 24, 2014 at 04:47:21PM -0700, Andrew Duggan wrote:
> RMI4 Function 0x30 provides support for GPIOs, LEDs and mechanical
> buttons. In particular, the mechanical button support is used in
> an increasing number of touchpads.
>
I was reading the spec for F30 and it looks to me that instead instead of basic
keymap it should actually implement a gpio chip plus LED devices (probably
later). Then, if GPIOs are indeed attached to buttons one can use standard
gpio_keys driver to create input device.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] Input: synaptics-rmi4 - fix compiler warnings in F11
From: Dmitry Torokhov @ 2014-07-27 7:27 UTC (permalink / raw)
To: Andrew Duggan
Cc: Christopher Heiny, linux-input, Benjamin Tissoires, linux-kernel
In-Reply-To: <53D167A9.3020402@synaptics.com>
On Thu, Jul 24, 2014 at 01:08:09PM -0700, Andrew Duggan wrote:
> On 07/23/2014 06:41 PM, Christopher Heiny wrote:
> >On 07/22/2014 11:11 PM, Dmitry Torokhov wrote:
> >>Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> >
> >I've reviewed this, and can say:
> >
> >Acked-by: Christopher Heiny <cheiny@synaptics.com>
> >
> >but I haven't had a chance to apply it to my build tree.
> >
> >Andrew - I'll be OOO for a couple of days. Can you do that, and
> >add a Tested-by: or rev the patch, as appropriate?
> >
> > Thanks,
> > Chris
> >
> It compiles cleanly and works on my test system.
>
> Tested-by: Andrew Duggan <aduggan@synaptics.com>
Thank you Andrew and Chris, I'll apply it to the branch then.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2] iio: exynos-adc: add experimental touchscreen support
From: Hartmut Knaack @ 2014-07-27 21:10 UTC (permalink / raw)
To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-iio-u79uwXL29TY76Z2rM5mHXA
Cc: kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, pawel.moll-5wv7dgnIgG8,
t.figa-Sze3O3UU22JBDgjK7y7TUQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Chanwoo Choi,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, Jonathan Cameron,
Ben Dooks, galak-sgV2jX0FEOL9JmXXK+q4OQ,
ch.naveen-Sze3O3UU22JBDgjK7y7TUQ, linux-input,
heiko.stuebner-K3U4GQvHnyU, Dmitry Torokhov
In-Reply-To: <5068889.1KfVx3ksNo@wuerfel>
Arnd Bergmann schrieb:
> This adds support for the touchscreen on Samsung s3c64xx.
> The driver is completely untested but shows roughly how
> it could be done, following the example of the at91 driver.
>
> Open questions include:
>
> - compared to the old plat-samsung/adc driver, there is
> no support for prioritizing ts over other clients, nor
> for oversampling. From my reading of the code, the
> priorities didn't actually have any effect at all, but
> the oversampling might be needed. Maybe the original
> authors have some insight.
>
> - We probably need to add support for platform_data as well,
> I've skipped this so far.
>
> Signed-off-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> ---
> This should address all previous comments, and I've also added
> a write to ADC_V1_DLY() as the old driver does.
Just two minor issues inline.
>
> diff --git a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> index cad81b666a67..ba30836c73cb 100644
> --- a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> +++ b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> @@ -43,6 +43,10 @@ Required properties:
> and compatible ADC block)
> - vdd-supply VDD input supply.
>
> +Optional properties:
> +- has-touchscreen: If present, indicates that a touchscreen is
> + connected an usable.
Typo: and
> +
> Note: child nodes can be added for auto probing from device tree.
>
> Example: adding device info in dtsi file
> diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
> index 420c5cda09c3..3b684a117b9c 100644
> --- a/drivers/iio/adc/exynos_adc.c
> +++ b/drivers/iio/adc/exynos_adc.c
> @@ -34,6 +34,7 @@
> #include <linux/regulator/consumer.h>
> #include <linux/of_platform.h>
> #include <linux/err.h>
> +#include <linux/input.h>
>
> #include <linux/iio/iio.h>
> #include <linux/iio/machine.h>
> @@ -66,6 +67,9 @@
>
> #define ADC_S3C2410_CON_SELMUX(x) (((x)&0x7)<<3)
>
> +/* touch screen always uses channel 0 */
> +#define ADC_S3C2410_MUX_TS 0
> +
> /* ADCTSC Register Bits */
> #define ADC_S3C2443_TSC_UD_SEN (1u << 8)
> #define ADC_S3C2410_TSC_YM_SEN (1u << 7)
> @@ -103,24 +107,32 @@
>
> /* Bit definitions common for ADC_V1 and ADC_V2 */
> #define ADC_CON_EN_START (1u << 0)
> +#define ADC_DATX_PRESSED (1u << 15)
> #define ADC_DATX_MASK 0xFFF
> +#define ADC_DATY_MASK 0xFFF
>
> #define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100))
>
> struct exynos_adc {
> struct exynos_adc_data *data;
> struct device *dev;
> + struct input_dev *input;
> void __iomem *regs;
> void __iomem *enable_reg;
> struct clk *clk;
> struct clk *sclk;
> unsigned int irq;
> + unsigned int tsirq;
> struct regulator *vdd;
>
> struct completion completion;
>
> u32 value;
> unsigned int version;
> +
> + bool read_ts;
> + u32 ts_x;
> + u32 ts_y;
> };
>
> struct exynos_adc_data {
> @@ -205,6 +217,9 @@ static void exynos_adc_v1_init_hw(struct exynos_adc *info)
> /* Enable 12-bit ADC resolution */
> con1 |= ADC_V1_CON_RES;
> writel(con1, ADC_V1_CON(info->regs));
> +
> + /* set default touchscreen delay */
Any information about how many µs/ms it is actually set with this value?
> + writel(10000, ADC_V1_DLY(info->regs));
> }
>
> static void exynos_adc_v1_exit_hw(struct exynos_adc *info)
> @@ -390,12 +405,54 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
> return ret;
> }
>
> +static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y)
> +{
> + struct exynos_adc *info = iio_priv(indio_dev);
> + unsigned long timeout;
> + int ret;
> +
> + mutex_lock(&indio_dev->mlock);
> + info->read_ts = true;
> +
> + reinit_completion(&info->completion);
> +
> + writel(ADC_S3C2410_TSC_PULL_UP_DISABLE | ADC_TSC_AUTOPST,
> + ADC_V1_TSC(info->regs));
> +
> + /* Select the ts channel to be used and Trigger conversion */
> + info->data->start_conv(info, ADC_S3C2410_MUX_TS);
> +
> + timeout = wait_for_completion_timeout
> + (&info->completion, EXYNOS_ADC_TIMEOUT);
> + if (timeout == 0) {
> + dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
> + if (info->data->init_hw)
> + info->data->init_hw(info);
> + ret = -ETIMEDOUT;
> + } else {
> + *x = info->ts_x;
> + *y = info->ts_y;
> + ret = 0;
> + }
> +
> + info->read_ts = false;
> + mutex_unlock(&indio_dev->mlock);
> +
> + return ret;
> +}
> +
> static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
> {
> struct exynos_adc *info = (struct exynos_adc *)dev_id;
>
> /* Read value */
> - info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
> + if (info->read_ts) {
> + info->ts_x = readl(ADC_V1_DATX(info->regs));
> + info->ts_y = readl(ADC_V1_DATY(info->regs));
> + writel(ADC_TSC_WAIT4INT | ADC_S3C2443_TSC_UD_SEN, ADC_V1_TSC(info->regs));
> + } else {
> + info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
> + }
>
> /* clear irq */
> if (info->data->clear_irq)
> @@ -406,6 +463,46 @@ static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> +/*
> + * Here we (ab)use a threaded interrupt handler to stay running
> + * for as long as the touchscreen remains pressed, we report
> + * a new event with the latest data and then sleep until the
> + * next timer tick. This mirrors the behavior of the old
> + * driver, with much less code.
> + */
> +static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
> +{
> + struct exynos_adc *info = dev_id;
> + struct iio_dev *dev = dev_get_drvdata(info->dev);
> + u32 x, y;
> + bool pressed;
> + int ret;
> +
> + while (info->input->users) {
> + ret = exynos_read_s3c64xx_ts(dev, &x, &y);
> + if (ret == -ETIMEDOUT)
> + break;
> +
> + pressed = x & y & ADC_DATX_PRESSED;
> + if (!pressed) {
> + input_report_key(info->input, BTN_TOUCH, 0);
> + input_sync(info->input);
> + break;
> + }
> +
> + input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
> + input_report_abs(info->input, ABS_Y, y & ADC_DATY_MASK);
> + input_report_key(info->input, BTN_TOUCH, 1);
> + input_sync(info->input);
> +
> + msleep(1);
> + };
> +
> + writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
> +
> + return IRQ_HANDLED;
> +}
> +
> static int exynos_adc_reg_access(struct iio_dev *indio_dev,
> unsigned reg, unsigned writeval,
> unsigned *readval)
> @@ -457,12 +554,66 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
> return 0;
> }
>
> +static int exynos_adc_ts_open(struct input_dev *dev)
> +{
> + struct exynos_adc *info = input_get_drvdata(dev);
> +
> + enable_irq(info->tsirq);
> +
> + return 0;
> +}
> +
> +static void exynos_adc_ts_close(struct input_dev *dev)
> +{
> + struct exynos_adc *info = input_get_drvdata(dev);
> +
> + disable_irq(info->tsirq);
> +}
> +
> +static int exynos_adc_ts_init(struct exynos_adc *info)
> +{
> + int ret;
> +
> + if (info->tsirq <= 0)
> + return -ENODEV;
> +
> + info->input = input_allocate_device();
> + if (!info->input)
> + return -ENOMEM;
> +
> + info->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> + info->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> +
> + input_set_abs_params(info->input, ABS_X, 0, 0x3FF, 0, 0);
> + input_set_abs_params(info->input, ABS_Y, 0, 0x3FF, 0, 0);
> +
> + info->input->name = "S3C24xx TouchScreen";
> + info->input->id.bustype = BUS_HOST;
> + info->input->open = exynos_adc_ts_open;
> + info->input->close = exynos_adc_ts_close;
> +
> + input_set_drvdata(info->input, info);
> +
> + ret = input_register_device(info->input);
> + if (ret)
> + input_free_device(info->input);
> +
> + disable_irq(info->tsirq);
> + ret = request_threaded_irq(info->tsirq, NULL, exynos_ts_isr,
> + 0, "touchscreen", info);
> + if (ret)
> + input_unregister_device(info->input);
> +
> + return ret;
> +}
> +
> static int exynos_adc_probe(struct platform_device *pdev)
> {
> struct exynos_adc *info = NULL;
> struct device_node *np = pdev->dev.of_node;
> struct iio_dev *indio_dev = NULL;
> struct resource *mem;
> + bool has_ts = false;
> int ret = -ENODEV;
> int irq;
>
> @@ -498,8 +649,14 @@ static int exynos_adc_probe(struct platform_device *pdev)
> dev_err(&pdev->dev, "no irq resource?\n");
> return irq;
> }
> -
> info->irq = irq;
> +
> + irq = platform_get_irq(pdev, 1);
> + if (irq == -EPROBE_DEFER)
> + return irq;
> +
> + info->tsirq = irq;
> +
> info->dev = &pdev->dev;
>
> init_completion(&info->completion);
> @@ -565,6 +722,15 @@ static int exynos_adc_probe(struct platform_device *pdev)
> if (info->data->init_hw)
> info->data->init_hw(info);
>
> + /* leave out any TS related code if unreachable */
> + if (IS_BUILTIN(CONFIG_INPUT) ||
> + (IS_MODULE(CONFIG_INPUT) && config_enabled(MODULE)))
> + has_ts = of_property_read_bool(pdev->dev.of_node, "has-touchscreen");
> + if (has_ts)
> + ret = exynos_adc_ts_init(info);
> + if (ret)
> + goto err_iio;
> +
> ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
> if (ret < 0) {
> dev_err(&pdev->dev, "failed adding child nodes\n");
> @@ -576,6 +742,11 @@ static int exynos_adc_probe(struct platform_device *pdev)
> err_of_populate:
> device_for_each_child(&indio_dev->dev, NULL,
> exynos_adc_remove_devices);
> + if (has_ts) {
> + input_unregister_device(info->input);
> + free_irq(info->tsirq, info);
> + }
> +err_iio:
> iio_device_unregister(indio_dev);
> err_irq:
> free_irq(info->irq, info);
> @@ -595,6 +766,11 @@ static int exynos_adc_remove(struct platform_device *pdev)
> struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> struct exynos_adc *info = iio_priv(indio_dev);
>
> + if (IS_BUILTIN(CONFIG_INPUT) ||
> + (IS_MODULE(CONFIG_INPUT) && config_enabled(MODULE))) {
> + free_irq(info->tsirq, info);
> + input_unregister_device(info->input);
> + }
> device_for_each_child(&indio_dev->dev, NULL,
> exynos_adc_remove_devices);
> iio_device_unregister(indio_dev);
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH v2] iio: exynos-adc: add experimental touchscreen support
From: Heiko Stübner @ 2014-07-27 21:50 UTC (permalink / raw)
To: Hartmut Knaack
Cc: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, pawel.moll-5wv7dgnIgG8,
t.figa-Sze3O3UU22JBDgjK7y7TUQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Chanwoo Choi,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, Jonathan Cameron,
Ben Dooks, galak-sgV2jX0FEOL9JmXXK+q4OQ,
ch.naveen-Sze3O3UU22JBDgjK7y7TUQ, linux-input, Dmitry Torokhov
In-Reply-To: <53D56ABD.8080808-Mmb7MZpHnFY@public.gmane.org>
Am Sonntag, 27. Juli 2014, 23:10:21 schrieb Hartmut Knaack:
> Arnd Bergmann schrieb:
> > @@ -205,6 +217,9 @@ static void exynos_adc_v1_init_hw(struct exynos_adc
> > *info)>
> > /* Enable 12-bit ADC resolution */
> > con1 |= ADC_V1_CON_RES;
> > writel(con1, ADC_V1_CON(info->regs));
> >
> > +
> > + /* set default touchscreen delay */
>
> Any information about how many µs/ms it is actually set with this value?
"ADC conversion is delayed by counting this value. Counting clock is pclk."
So, I guess here 10000 pclk ticks.
Heiko
>
> > + writel(10000, ADC_V1_DLY(info->regs));
> >
> > }
> >
^ permalink raw reply
* Re: [PATCH v2] Input: soc_button_array: Remove kfree on data allocated with devm_zalloc
From: pramod gurav @ 2014-07-28 6:50 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, linux-kernel@vger.kernel.org, Pramod Gurav,
Lejun Zhu, Sachin Kamat
In-Reply-To: <20140725162258.GA12254@core.coreip.homeip.net>
Hi Dmitry,
Thanks for the review.
On Fri, Jul 25, 2014 at 9:52 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> Hi Pramod,
>
> On Fri, Jul 25, 2014 at 05:04:34PM +0530, pramod.gurav.etc@gmail.com wrote:
>> From: Pramod Gurav <pramod.gurav@smartplayin.com>
>>
>> This patch does below:
>> - Removes kfree done on data allocated with devm_zalloc in probe
>> path of the driver.
>> - Adds a check on return value from devm_kzalloc which was missing
>>
>> CC: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>> CC: Lejun Zhu <lejun.zhu@linux.intel.com>
>> CC: Sachin Kamat <sachin.kamat@linaro.org>
>>
>> Signed-off-by: Pramod Gurav <pramod.gurav@smartplayin.com>
>> ---
>> drivers/input/misc/soc_button_array.c | 17 +++++++----------
>> 1 file changed, 7 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
>> index 5a6334b..fc64ec6 100644
>> --- a/drivers/input/misc/soc_button_array.c
>> +++ b/drivers/input/misc/soc_button_array.c
>> @@ -83,6 +83,9 @@ soc_button_device_create(struct pnp_dev *pdev,
>> sizeof(*gpio_keys_pdata) +
>> sizeof(*gpio_keys) * MAX_NBUTTONS,
>> GFP_KERNEL);
>> + if (!gpio_keys_pdata)
>> + return ERR_PTR(-ENOMEM);
>
> OK, that makes sense.
>
>> +
>> gpio_keys = (void *)(gpio_keys_pdata + 1);
>>
>> for (info = button_info; info->name; info++) {
>> @@ -102,20 +105,16 @@ soc_button_device_create(struct pnp_dev *pdev,
>> n_buttons++;
>> }
>>
>> - if (n_buttons == 0) {
>> - error = -ENODEV;
>> - goto err_free_mem;
>> - }
>> + if (n_buttons == 0)
>> + return ERR_PTR(-ENODEV);
>
> But that one and the rest don't, because failure in
> soc_button_device_create() does not necessarily mean that binding for
> the whole device will fail. In this case we do not want unused memory
> hang around.
Agree. Should resend the patch with only the error check after mem
allocation and will be little more careful while sending any such
change. :)
>
> Thanks.
>
> --
> Dmitry
--
Thanks and Regards
Pramod
^ permalink raw reply
* Re: [PATCH v2] Input: soc_button_array: Remove kfree on data allocated with devm_zalloc
From: Dmitry Torokhov @ 2014-07-28 7:10 UTC (permalink / raw)
To: pramod gurav
Cc: linux-input, linux-kernel@vger.kernel.org, Pramod Gurav,
Lejun Zhu, Sachin Kamat
In-Reply-To: <CAMf-jSm1d0wAJ3C_yFhqnoDPSLqeDcc-ow0D=bwmLUcC9sXjLA@mail.gmail.com>
On July 27, 2014 11:50:41 PM PDT, pramod gurav <pramod.gurav.etc@gmail.com> wrote:
>Hi Dmitry,
>
>Thanks for the review.
>
>On Fri, Jul 25, 2014 at 9:52 PM, Dmitry Torokhov
><dmitry.torokhov@gmail.com> wrote:
>> Hi Pramod,
>>
>> On Fri, Jul 25, 2014 at 05:04:34PM +0530, pramod.gurav.etc@gmail.com
>wrote:
>>> From: Pramod Gurav <pramod.gurav@smartplayin.com>
>>>
>>> This patch does below:
>>> - Removes kfree done on data allocated with devm_zalloc in probe
>>> path of the driver.
>>> - Adds a check on return value from devm_kzalloc which was missing
>>>
>>> CC: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>>> CC: Lejun Zhu <lejun.zhu@linux.intel.com>
>>> CC: Sachin Kamat <sachin.kamat@linaro.org>
>>>
>>> Signed-off-by: Pramod Gurav <pramod.gurav@smartplayin.com>
>>> ---
>>> drivers/input/misc/soc_button_array.c | 17 +++++++----------
>>> 1 file changed, 7 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/input/misc/soc_button_array.c
>b/drivers/input/misc/soc_button_array.c
>>> index 5a6334b..fc64ec6 100644
>>> --- a/drivers/input/misc/soc_button_array.c
>>> +++ b/drivers/input/misc/soc_button_array.c
>>> @@ -83,6 +83,9 @@ soc_button_device_create(struct pnp_dev *pdev,
>>> sizeof(*gpio_keys_pdata) +
>>> sizeof(*gpio_keys) *
>MAX_NBUTTONS,
>>> GFP_KERNEL);
>>> + if (!gpio_keys_pdata)
>>> + return ERR_PTR(-ENOMEM);
>>
>> OK, that makes sense.
>>
>>> +
>>> gpio_keys = (void *)(gpio_keys_pdata + 1);
>>>
>>> for (info = button_info; info->name; info++) {
>>> @@ -102,20 +105,16 @@ soc_button_device_create(struct pnp_dev *pdev,
>>> n_buttons++;
>>> }
>>>
>>> - if (n_buttons == 0) {
>>> - error = -ENODEV;
>>> - goto err_free_mem;
>>> - }
>>> + if (n_buttons == 0)
>>> + return ERR_PTR(-ENODEV);
>>
>> But that one and the rest don't, because failure in
>> soc_button_device_create() does not necessarily mean that binding for
>> the whole device will fail. In this case we do not want unused memory
>> hang around.
>Agree. Should resend the patch with only the error check after mem
>allocation and will be little more careful while sending any such
>change. :)
No need to resend, I picked out the good bits and applied.
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