Re: [PATCH v7] vivid: Add touch support

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

 



On 11/19/19 10:23 AM, Hans Verkuil wrote:
> On 11/19/19 10:02 AM, Hans Verkuil wrote:
>> Hi Vandana,
>>
>> On 11/18/19 4:53 PM, Vandana BN wrote:
>>> Support to emulate touch devices in vivid driver.
>>> It generates touch patterns simulating, single tap, double tap, triple
>>
>> No , after 'simulating'.
>>
>>> tap, move from left to right, zoom in, zoom out, palm press simulating
>>> large area being pressed on screen, and an invalid pattern of
>>
>> Drop the 'invalid': it is not invalid, just very, very unusual.
>>
>>> simulating 16 different simultaneous touch points.
>>> All of these patterns are based on behavior of rmi_f54 driver.
>>
>> The patterns aren't from that driver, but the generated values are.
>>
>>>
>>> Signed-off-by: Vandana BN <bnvandana@xxxxxxxxx>
>>> ---
>>> Changes since V6:
>>> 	simplified touch pattern generation.
>>> ---
>>>  drivers/media/platform/vivid/Makefile         |   3 +-
>>>  drivers/media/platform/vivid/vivid-core.c     | 164 +++++++++-
>>>  drivers/media/platform/vivid/vivid-core.h     |  20 ++
>>>  drivers/media/platform/vivid/vivid-ctrls.c    |  11 +
>>>  .../platform/vivid/vivid-kthread-touch.c      | 181 +++++++++++
>>>  .../platform/vivid/vivid-kthread-touch.h      |  13 +
>>>  .../media/platform/vivid/vivid-touch-cap.c    | 286 ++++++++++++++++++
>>>  .../media/platform/vivid/vivid-touch-cap.h    |  35 +++
>>>  8 files changed, 700 insertions(+), 13 deletions(-)
>>>  create mode 100644 drivers/media/platform/vivid/vivid-kthread-touch.c
>>>  create mode 100644 drivers/media/platform/vivid/vivid-kthread-touch.h
>>>  create mode 100644 drivers/media/platform/vivid/vivid-touch-cap.c
>>>  create mode 100644 drivers/media/platform/vivid/vivid-touch-cap.h
>>
>> <snip>
>>
> 
> I couldn't resist: here is a vivid_tch_buf_set that fills in the neighboring
> pixels as well for more realism:
> 
> static void vivid_tch_buf_set(__s16 *tch_buf, struct v4l2_pix_format *f, int index)
> {
>         unsigned int x = index % f->width;
>         unsigned int y = index / f->width;
>         unsigned int offset = VIVID_MIN_PRESSURE;
> 
>         tch_buf[index] = offset + get_random_int() % 40;

40 should be a define as well.

It makes sense to make a get_random_pressure static inline instead of calling
get_random_int() % 40 here.

>         offset /= 2;
>         if (x)
>                 tch_buf[index - 1] = offset + get_random_int() % 40;
>         if (x < f->width - 1)
>                 tch_buf[index + 1] = offset + get_random_int() % 40;
>         if (y)
>                 tch_buf[index - f->width] = offset + get_random_int() % 40;
>         if (y < f->height - 1)
>                 tch_buf[index + f->width] = offset + get_random_int() % 40;
>         offset /= 2;
>         if (x && y)
>                 tch_buf[index - 1 - f->width] = offset + get_random_int() % 40;
>         if (x < f->width - 1 && y)
>                 tch_buf[index + 1 - f->width] = offset + get_random_int() % 40;
>         if (x && y < f->height - 1)
>                 tch_buf[index - 1 + f->width] = offset + get_random_int() % 40;
>         if (x < f->width - 1 && y < f->height - 1)
>                 tch_buf[index + 1 + f->width] = offset + get_random_int() % 40;
> }
> 
> The result now looks very close to the real hardware.
> 
>>> +void vivid_fillbuff_tch(struct vivid_dev *dev, struct vivid_buffer *buf)
>>> +{
>>> +	struct v4l2_pix_format *f = &dev->tch_format;
>>> +	int size = f->width * f->height;
>>> +	int index = 0, x, y, xstart, ystart;
>>> +	unsigned int test_pattern, test_pat_idx, rand;
>>> +
>>> +	__s16 *tch_buf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
>>> +
>>> +	buf->vb.sequence = dev->touch_cap_seq_count;
>>> +	test_pattern = (buf->vb.sequence / 15) % TEST_CASE_MAX;
>>> +	test_pat_idx = buf->vb.sequence % 15;
>>> +
>>> +	vivid_fill_buff_noise(tch_buf, size);
>>> +
>>> +	if (test_pat_idx >= 10)
>>
>> The values 10 and 15 should be defines. That makes it easy to change later.
>>
>> I think it would be better to change 15 to 16 and 10 to 12: 16 helps because
>> in the corner case where the sequence counter will wrap around you will get
>> a smooth transition. And 12 makes each sequence just a little bit longer,
>> which makes it easier to see.
>>
>>> +		return;
>>> +
>>> +	if (test_pat_idx == 0)
>>> +		dev->tch_pat_random = get_random_int();
>>> +	rand = dev->tch_pat_random;
>>> +
>>> +	switch (test_pattern) {
>>> +	case SINGLE_TAP:
>>> +		if (test_pat_idx == 5)
>>> +			vivid_tch_buf_set(tch_buf, rand % size);
>>> +		break;
>>> +	case DOUBLE_TAP:
>>> +		if (test_pat_idx == 3 || test_pat_idx == 6)
>>> +			vivid_tch_buf_set(tch_buf, rand % size);
>>> +		break;
>>> +	case TRIPLE_TAP:
>>> +		if (test_pat_idx == 3 || test_pat_idx == 6 || test_pat_idx == 9)
>>> +			vivid_tch_buf_set(tch_buf, rand % size);
>>> +		break;
>>> +	case MOVE_LEFT_TO_RIGHT:
>>> +		vivid_tch_buf_set(tch_buf,
>>> +				  (rand % f->height) * f->width + test_pat_idx * (f->width / 10));
>>
>> Line too long (same in similar cases below). It's easiest to break it off after the + like this:
>>
>> 		vivid_tch_buf_set(tch_buf,
>> 				  (rand % f->height) * f->width +
>> 				  test_pat_idx * (f->width / 10));
>>
>>> +		break;
>>> +	case ZOOM_IN:
>>> +		x = f->width / 2;
>>> +		y = f->height / 2;
>>
>> You need extra variables for the offset from the center:
>>
>> 		offset_x = ((9 - test_pat_idx) * x) / 10;   (10 should be a define as discussed above)
>> 		offset_y = ((9 - test_pat_idx) * y) / 10;
>>
>>> +		if (x + test_pat_idx < f->width && y + test_pat_idx < f->height) {
>>
>> Then this if can be dropped here as well.
>>
>>> +			vivid_tch_buf_set(tch_buf, (x - test_pat_idx) + f->width * (y - test_pat_idx));
>>> +			vivid_tch_buf_set(tch_buf, (x + test_pat_idx) + f->width * (y + test_pat_idx));
>>> +		}
>>> +		break;
>>> +	case ZOOM_OUT:
>>> +		x = f->width / 2;
>>> +		y = f->height / 2;
>>> +		index = min(x, y) - test_pat_idx - 1;> +		if (x + index >= f->width / 2 && y + index >= f->height / 2) {
>>
>> Same here.
>>
>>> +			vivid_tch_buf_set(tch_buf, (x - index) + f->width * (y - index));
>>> +			vivid_tch_buf_set(tch_buf, (x + index) + f->width * (y + index));
>>> +		}
>>> +		break;
>>> +	case PALM_PRESS:
> 
> For this palm press test and...
> 
>>> +		xstart = f->width - f->width / 4;
>>
>> Just set this to 0, so the palm covers the bottom quarter.
>>
>>> +		ystart = f->height - f->height / 4;
>>> +		if (test_pat_idx != 5)
>>> +			break;
>>> +		for (x = xstart; x < f->width; x++)
>>> +			for (y = ystart; y < f->height; y++)
>>> +				vivid_tch_buf_set(tch_buf, x + f->width * y);
>>> +		break;
>>> +	case MULTIPLE_PRESS:
> 
> ... the multiple press test you can drop the 'if (test_pat_idx != 5)' bit:
> i.e. this pattern should be there for the full 10 frames.
> 
> The point of this pattern is to test something unusual, so it makes sense
> to show these two patterns for a longer time.
> 
> Regards,
> 
> 	Hans
> 
>>> +		/* 16 pressure points */
>>> +		if (test_pat_idx != 5)
>>> +			break;
>>> +		for (y = 0; y < 4; y++) {
>>> +			for (x = 0; x < 4; x++) {
>>> +				ystart = (y * f->height) / 4 + f->height / 8;
>>> +				xstart = (x * f->width) / 4 + f->width / 8;
>>> +				vivid_tch_buf_set(tch_buf, ystart * f->width + xstart);
>>> +			}
>>> +		}
>>> +		break;
>>> +	}

I realized that there is a final step that needs to be done here: the
buffer is supposed to be in little endian format, so if vivid is compiled
on a big endian host, then the buffer contents needs to be converted.

So:

#ifdef __BIG_ENDIAN__
		for all pixels:
			tch_buf[i] = (__force s16)__cpu_to_le16((u16)tch_buf[i]);
#endif

Regards,

	Hans

>>> +}
>>
>> Regards,
>>
>> 	Hans
>>
>>> diff --git a/drivers/media/platform/vivid/vivid-touch-cap.h b/drivers/media/platform/vivid/vivid-touch-cap.h
>>> new file mode 100644
>>> index 000000000000..6e83ca919f07
>>> --- /dev/null
>>> +++ b/drivers/media/platform/vivid/vivid-touch-cap.h
>>> @@ -0,0 +1,35 @@
>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>> +/*
>>> + * vivid-touch-cap.h - touch support functions.
>>> + */
>>> +#ifndef _VIVID_TOUCH_CAP_H_
>>> +#define _VIVID_TOUCH_CAP_H_
>>> +
>>> +#define VIVID_TCH_HEIGHT	12
>>> +#define VIVID_TCH_WIDTH		21
>>> +#define VIVID_MIN_PRESSURE	180
>>> +
>>> +enum vivid_tch_test {
>>> +	SINGLE_TAP,
>>> +	DOUBLE_TAP,
>>> +	TRIPLE_TAP,
>>> +	MOVE_LEFT_TO_RIGHT,
>>> +	ZOOM_IN,
>>> +	ZOOM_OUT,
>>> +	PALM_PRESS,
>>> +	MULTIPLE_PRESS,
>>> +	TEST_CASE_MAX
>>> +};
>>> +
>>> +extern const struct vb2_ops vivid_touch_cap_qops;
>>> +
>>> +int vivid_enum_fmt_tch(struct file *file, void  *priv, struct v4l2_fmtdesc *f);
>>> +int vivid_g_fmt_tch(struct file *file, void *priv, struct v4l2_format *f);
>>> +int vivid_enum_input_tch(struct file *file, void *priv, struct v4l2_input *inp);
>>> +int vivid_g_input_tch(struct file *file, void *priv, unsigned int *i);
>>> +int vivid_s_input_tch(struct file *file, void *priv, unsigned int i);
>>> +void vivid_fillbuff_tch(struct vivid_dev *dev, struct vivid_buffer *buf);
>>> +int vivid_set_touch(struct vivid_dev *dev, unsigned int i);
>>> +int vivid_g_parm_tch(struct file *file, void *priv,
>>> +		     struct v4l2_streamparm *parm);
>>> +#endif
>>>
>>
> 




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux