lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:	Sat, 29 May 2010 22:34:37 +0200
From:	Henrik Rydberg <rydberg@...omail.se>
To:	Christopher Heiny <cheiny@...aptics.com>
CC:	Dmitry Torokhov <dmitry.torokhov@...il.com>,
	Jean Delvare <khali@...ux-fr.org>,
	Linux Kernel <linux-kernel@...r.kernel.org>,
	Linux Input <linux-input@...r.kernel.org>,
	Allie Xiong <axiong@...aptics.com>,
	William Manson <wmanson@...aptics.com>
Subject: Re: [RFC PATCH 1/1] input/touchscreen: Synaptics Touchscreen Driver

Christopher Heiny wrote:
> Initial driver for Synaptics touchscreens using RMI4 protocol.
> 
> Signed-off-by: William Manson <WManson@...aptics.com>
> Signed-off-by: Allie Xiong <axiong@...aptics.com>
> Signed-off-by: Christopher Heiny <cheiny@...aptics.com>
> ---

Thank you for this driver. Some scattered comments on the MT parts below.

Henrik

[...]
> +int FN_11_report(struct rmi_application *app,
> +		struct rmi_function_info *rfi, struct input_dev *input)
> +{
> +	unsigned char values[2] = {0, 0};
> +	unsigned char data[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
> +	/* number of touch points - fingers down in this case */
> +	int fingerDownCount;
> +	int X, Y, Z, W, Wy, Wx;
> +	int finger;
> +	int fn11FingersSupported;
> +	int fn11FingerRegisters;
> +	unsigned short fn11DataBaseAddr;
> +	unsigned char fn11DataRegBlockSize;
> +	static bool wasdown;
> +
> +	fingerDownCount = 0;
> +
> +	/* get 2D sensor finger data */
> +
> +	/* First get the finger status field - the size of the finger status
> +	field is determined by the number of finger supporte - 2 bits per
> +	finger, so the number of registers to read is:
> +		registerCount = ceil(numberOfFingers/4).
> +	Read the required number of registers and check each 2 bit field to
> +	determine if a finger is down:
> +		00 = finger not present,
> +		01 = finger present and data accurate,
> +		10 = finger present but data may not be accurate,
> +		11 = reserved for product use.
> +	*/
> +	fn11FingersSupported = rfi->numDataPoints;
> +	fn11FingerRegisters = (fn11FingersSupported + 3)/4;
> +
> +	fn11DataBaseAddr = rfi->funcDescriptor.dataBaseAddr;
> +
> +	if (rmi_read_multiple(app, fn11DataBaseAddr, values,
> +			fn11FingerRegisters)) {
> +		printk(KERN_ERR "%s: RMI4 function $11 report: "
> +			"Could not read finger status registers 0x%x\n",
> +			__func__, fn11DataBaseAddr);
> +		return 0;

The in-kernel rmi interface seems to expect the number of touches to be returned
here, but it does not seem to be used anywhere. Would it not be more useful to
return zero on success, and error codes on failure?

> +	}
> +
> +	/* For each finger present, read the proper number of registers
> +	to get absolute data. */
> +	fn11DataRegBlockSize = rfi->dataRegBlockSize;
> +
> +	for (finger = 0; finger < fn11FingersSupported; finger++) {
> +		int reg;
> +		int fingerShift;
> +		int fingerStatus;
> +
> +		/* determine which data byte the finger status is in */
> +		reg = finger/4;
> +		/* bit shift to get finger's status */
> +		fingerShift = (finger % 4) * 2;
> +		fingerStatus = (values[reg] >> fingerShift) & 3;
> +
> +		/* if finger status indicates a finger is present then
> +		read the finger data and report it */
> +		if (fingerStatus == 1 || fingerStatus == 2) {
> +			/* number of active touch points not same as
> +			number of supported fingers */
> +			fingerDownCount++;
> +
> +			/* Read the finger data */
> +			if (rmi_read_multiple(app, fn11DataBaseAddr +
> +					((finger  * fn11DataRegBlockSize) +
> +					fn11FingerRegisters),
> +					data, fn11DataRegBlockSize)) {
> +				printk(KERN_ERR "%s: RMI4 function $11 report: "
> +					"Could not read finger data registers "
> +					"0x%x\n", __func__,
> +					fn11DataBaseAddr +
> +					((finger  * fn11DataRegBlockSize) +
> +					fn11FingerRegisters));
> +				return 0;

Bailing out without finishing off the input packet...

> +			} else {
> +				X = (data[0] & 0x1f) << 4;
> +				X |= data[2] & 0xf;
> +				Y = (data[1] & 0x1f) << 4;
> +				Y |= (data[2] >> 4) & 0xf;
> +				W = data[3];
> +
> +				/* upper 4 bits of W are Wy,
> +				lower 4 of W are Wx */
> +				Wy =  (W >> 4) & 0x0f;
> +				Wx = W & 0x0f;
> +
> +				Z = data[4];
> +
> +				/* if this is the first finger report normal
> +				ABS_X, ABS_Y, PRESSURE, TOOL_WIDTH events for
> +				non-MT apps. Apps that support Multi-touch
> +				will ignore these events and use the MT events.
> +				Apps that don't support Multi-touch will still
> +				function.
> +				*/
> +				if (fingerDownCount == 1) {
> +					input_report_abs(input, ABS_X, X);
> +					input_report_abs(input, ABS_Y, Y);
> +					input_report_abs(input, ABS_PRESSURE,
> +							Z);
> +					input_report_abs(input, ABS_TOOL_WIDTH,
> +							max(Wx, Wy));
> +					input_report_key(input, BTN_TOUCH, 1);
> +					wasdown = true;
> +				}
> +
> +				/* Report Multi-Touch events for each finger */
> +				/* major axis of touch area ellipse */
> +				input_report_abs(input, ABS_MT_TOUCH_MAJOR,
> +						max(Wx, Wy));
> +				/* minor axis of touch area ellipse */
> +				input_report_abs(input, ABS_MT_TOUCH_MINOR,
> +						min(Wx, Wy));
> +				/* Currently only 2 supported - 1 or 0 */
> +				input_report_abs(input, ABS_MT_ORIENTATION,
> +						(Wx > Wy ? 1 : 0));
> +				input_report_abs(input, ABS_MT_POSITION_X, X);
> +				input_report_abs(input, ABS_MT_POSITION_Y, Y);
> +				/* Tracking ID reported but not used yet */
> +				input_report_abs(input, ABS_MT_TRACKING_ID,
> +						finger+1);

The tracking id used here is not entirely proper, since the id seems to be
reused too often.

Does the position in the finger array (0..fn11FingersSupported) really track an
identified contact, as suggested by the code? If so, a proper tracking id could
be formed by keeping an id per position, and assigning a new id when the
fingerStatus changes for that position.

> +				/* MT sync between fingers */
> +				input_mt_sync(input);
> +			}
> +		}
> +	}
> +
> +	if (fingerDownCount) {
> +		/* touch will be non-zero if we had any reported events */
> +		input_sync(input); /* sync after groups of events */
> +	} else {
> +		/* if we had a finger down before and now we don't have
> +		any we need to send a button up and a sync. */
> +		if (wasdown) {
> +			wasdown = false;
> +			input_report_key(input, BTN_TOUCH, 0);
> +			input_sync(input); /* sync after groups of events */
> +		}
> +	}

input_sync() should always be called at the end, regardless. If nothing changed,
the input core will filter it out.

> +
> +	/* return the number of touch points: fingers down or buttons pressed */
> +	return fingerDownCount;
> +}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ