Re: ALPS v4 Semi-mt Support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi George,

Thanks for the patch. I've got some specific comments inline below, but
here are some general comments.

The reason I've never followed through with the v4 semi-MT support is
that I lost access to the hardware before I could complete it. When I
had the hardware the thing I struggled with was how to handle receiving
only one full set of MT data for every 3 sets of ST data. It looks like
you've opted to only report every third ST data point (if the previous
MT packet showed more than 1 touch, more on that below), when you also
have a complete set of MT data. That's one possible approach, but I'm
not sure that it's the best. Hopefully some of the input gurus on the
list can comment. As I recall the main difficulty with reporting all ST
points was not knowing the finger count until the third packet of the
sequence, so I was leaning towards accumulating the data and processing
it all in one go after the third packet in the sequence arrived.

I definitely think your state processing could be improved. My
suggestion would be to treat multi_packet as a counter. Reset it to 0
when you see the sync bit is set, and increment it for each packet until
you have a full set of MT data. That way you know for sure which section
of the MT data you're working with for any given packet. But be prepared
to handle an incomplete packet sequence as well (I'm pretty sure I saw
some of these when I was working with a v4 touchpad).

On Tue, Apr 10, 2012 at 05:02:41PM +0300, George Pantalos wrote:
> --- drivers/input/mouse/alps.c	2012-03-19 01:15:34.000000000 +0200
> +++ drivers/input/mouse/alps.c.new	2012-04-09 17:14:25.193621808 +0300
> @@ -604,11 +604,59 @@
>  
>  static void alps_process_packet_v4(struct psmouse *psmouse)
>  {
> +        struct alps_data *priv = psmouse->private;

Should be a tab instead of spaces. You've got spaces for indentation at
some other places as well. Try running checkpatch.pl (in the scripts
directory of the kernel source tree) to catch these types of problems.

>  	unsigned char *packet = psmouse->packet;
>  	struct input_dev *dev = psmouse->dev;
>  	int x, y, z;
>  	int left, right;
> +	int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
> +	int fingers = 0, bmap_fingers;
> +	unsigned int x_bitmap, y_bitmap;
> +
> +	if (priv->multi_packet) {
> +          if (packet[6] != 0x00) { 

This condition may not work all the time. Based on the documentaiton I
wrote at least it looks like byte 6 in the second packet of the sequence
could be zero, but I can't remember for sure.

> +		priv->multi_data_v4[2] = packet[6];
> +		priv->multi_data_v4[3] = packet[7];
> +		priv->multi_packet = 1;
> +		if (priv->last_fingers > 1)
> +		return;

The body of if statements needs to be indented.

> +          } else {
> +		priv->multi_data_v4[4] = packet[6];
> +		priv->multi_data_v4[5] = packet[7];
> +
> +		fingers = 0;
> +		priv->multi_packet = 0;
> +		x_bitmap = ((priv->multi_data_v4[2] & 0x1f) << 10) | /*0x1f*/
> +			   ((priv->multi_data_v4[3] & 0x60) << 3) |
> +			   ((priv->multi_data_v4[0] & 0x3f) << 2) |
> +			   ((priv->multi_data_v4[1] & 0x60) >> 5);
> +		y_bitmap = ((priv->multi_data_v4[5] & 0x01) << 10) |
> +			   ((priv->multi_data_v4[3] & 0x1f) << 5) |
> +			    (priv->multi_data_v4[1] & 0x1f);
> +	  
> +		bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap,
> +						  &x1, &y1, &x2, &y2);
> +		if (bmap_fingers > 1) {
> +			fingers = bmap_fingers;
> +		}

Braces aren't needed when there's only a single line in the body of an
if statement.

> +	  
> +		priv->last_fingers = fingers;
>  
> +          /*packet = priv->multi_data;*/
> +          /*packet = packet;*/

Delete the commented out lines if they aren't needed.

> +	  }
> +	}
> +
> +	if (!priv->multi_packet && (packet[6] & 0x40)) {
> +		priv->multi_packet = 1;
> +		priv->multi_data_v4[0] = packet[6];
> +		priv->multi_data_v4[1] = packet[7];
> +		if (priv->last_fingers > 1)
> +		return;

So you're deciding how to handle the current packet sequence based on
the number of touch points in the previous sequence. You lose a couple
of ST points then each time you transition from multiple touches to a
single touch. That might be okay, depending on what kind of feedback is
received on how to handle the packet sequences.

> +	}
> +	
> +        /*priv->multi_packet = 0;*/

Again, if this isn't needed just delete it.

> +        
>  	left = packet[4] & 0x01;
>  	right = packet[4] & 0x02;
>  
> @@ -617,21 +665,33 @@
>  	y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
>  	z = packet[5] & 0x7f;
>  
> +	if (!fingers) {
> +		x1 = x;
> +		y1 = y;
> +		fingers = z > 0 ? 1 : 0;
> +	}
> +
>  	if (z >= 64)
>  		input_report_key(dev, BTN_TOUCH, 1);
>  	else
>  		input_report_key(dev, BTN_TOUCH, 0);
>  
> +	alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
> +
> +	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
> +	input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
> +	input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
> +	input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
> +
> +	input_report_key(dev, BTN_LEFT, left);
> +	input_report_key(dev, BTN_RIGHT, right);
> +
>  	if (z > 0) {
>  		input_report_abs(dev, ABS_X, x);
>  		input_report_abs(dev, ABS_Y, y);
>  	}
>  	input_report_abs(dev, ABS_PRESSURE, z);
>  
> -	input_report_key(dev, BTN_TOOL_FINGER, z > 0);
> -	input_report_key(dev, BTN_LEFT, left);
> -	input_report_key(dev, BTN_RIGHT, right);
> -
>  	input_sync(dev);
>  }
>  
> @@ -1567,8 +1627,18 @@
>  		set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
>  		/* fall through */
>  	case ALPS_PROTO_V4:
> -		input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0);
> -		input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0);
> +		set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
> +		input_mt_init_slots(dev1, 2);
> +                input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0);
> +                input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0);
> +
> +		input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, 
> ALPS_V3_X_MAX, 0, 0);
> +		input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, 
> ALPS_V3_Y_MAX, 0, 0);
> +
> +		set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
> +		set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
> +		set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
> +		/* fall through */
>  		break;
>  	}
>  
> --- drivers/input/mouse/alps.h	2012-03-19 01:15:34.000000000 +0200
> +++ drivers/input/mouse/alps.h.new	2012-04-09 17:17:32.733618703 +0300
> @@ -39,6 +39,8 @@
>  	int prev_fin;			/* Finger bit from previous packet */
>  	int multi_packet;		/* Multi-packet data in progress */
>  	unsigned char multi_data[6];	/* Saved multi-packet data */
> +	unsigned char multi_data_v4[6];

Why do you need multi_data_v4? You should be able to use multi_data.

> +	int last_fingers;
>  	u8 quirks;
>  	struct timer_list timer;
>  };
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux