All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hans Verkuil <hverkuil@xs4all.nl>
To: Vandana BN <bnvandana@gmail.com>, linux-media@vger.kernel.org
Subject: Re: [PATCH v4] vivid: Add touch support
Date: Wed, 13 Nov 2019 08:51:45 +0100	[thread overview]
Message-ID: <41670600-f97f-8c52-d13b-78fb1c44a01b@xs4all.nl> (raw)
In-Reply-To: <20191113073754.15877-1-bnvandana@gmail.com>

Hi Vandana,

Is the last posted v4l-utils patch still valid with this v4?

I managed to get the rmi4 driver to work on my Lenovo laptop, but I get
weird data from the device. I am still investigating what is going on.

Anyway, I have some more, fairly minor, comments about this patch below.

Regards,

	Hans


On 11/13/19 8:37 AM, Vandana BN wrote:
> Support to emulate touch devices in vivid driver.
> 
> Signed-off-by: Vandana BN <bnvandana@gmail.com>
> ---
> Incorporate changes from https://patchwork.linuxtv.org/patch/59782/,
> to avoid the mutex unlocking/relocking around the kthread_stop.
> ---
>  drivers/media/platform/vivid/Makefile         |   3 +-
>  drivers/media/platform/vivid/vivid-core.c     | 187 +++++++++-
>  drivers/media/platform/vivid/vivid-core.h     |  22 ++
>  drivers/media/platform/vivid/vivid-ctrls.c    |  11 +
>  .../platform/vivid/vivid-kthread-touch.c      | 207 +++++++++++
>  .../platform/vivid/vivid-kthread-touch.h      |  13 +
>  .../media/platform/vivid/vivid-touch-cap.c    | 325 ++++++++++++++++++
>  .../media/platform/vivid/vivid-touch-cap.h    |  43 +++
>  8 files changed, 796 insertions(+), 15 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>

> diff --git a/drivers/media/platform/vivid/vivid-kthread-touch.c b/drivers/media/platform/vivid/vivid-kthread-touch.c
> new file mode 100644
> index 000000000000..7ef7230c9a27
> --- /dev/null
> +++ b/drivers/media/platform/vivid/vivid-kthread-touch.c
> @@ -0,0 +1,207 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * vivid-kthread-touch.c - touch capture thread support functions.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/sched.h>
> +#include <linux/slab.h>
> +#include <linux/font.h>

This header is unused.

> +#include <linux/mutex.h>
> +#include <linux/videodev2.h>
> +#include <linux/kthread.h>
> +#include <linux/freezer.h>
> +#include <linux/random.h>

as is this one (I think).

> +#include <asm/div64.h>
> +#include <media/videobuf2-vmalloc.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-fh.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-rect.h>

I suspect some of these v4l2 headers can be dropped as well.

> +
> +#include "vivid-core.h"
> +#include "vivid-osd.h"
> +#include "vivid-ctrls.h"

Are osd and ctrls.h needed?

> +#include "vivid-kthread-touch.h"
> +#include "vivid-touch-cap.h"

In other words, weed out the unnecessary headers from this list.

> +
> +static noinline_for_stack void vivid_thread_tch_cap_tick(struct vivid_dev *dev,
> +							 int dropped_bufs)
> +{
> +	struct vivid_buffer *tch_cap_buf = NULL;
> +
> +	dprintk(dev, 1, "Touch Capture Thread Tick\n");
> +
> +	spin_lock(&dev->slock);
> +	if (!list_empty(&dev->touch_cap_active)) {
> +		tch_cap_buf = list_entry(dev->touch_cap_active.next,
> +					 struct vivid_buffer, list);
> +		list_del(&tch_cap_buf->list);
> +	}
> +
> +	spin_unlock(&dev->slock);
> +
> +	if (tch_cap_buf) {
> +		v4l2_ctrl_request_setup(tch_cap_buf->vb.vb2_buf.req_obj.req,
> +					&dev->ctrl_hdl_touch_cap);
> +
> +		vivid_fillbuff_tch(dev, tch_cap_buf);
> +		v4l2_ctrl_request_complete(tch_cap_buf->vb.vb2_buf.req_obj.req,
> +					   &dev->ctrl_hdl_touch_cap);
> +		vb2_buffer_done(&tch_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
> +				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
> +		dprintk(dev, 2, "touch_cap buffer %d done\n",
> +			tch_cap_buf->vb.vb2_buf.index);
> +
> +		tch_cap_buf->vb.vb2_buf.timestamp = ktime_get_ns() + dev->time_wrap_offset;
> +	}
> +	dev->dqbuf_error = false;
> +}
> +
> +static int vivid_thread_touch_cap(void *data)
> +{
> +	struct vivid_dev *dev = data;
> +	u64 numerators_since_start;
> +	u64 buffers_since_start;
> +	u64 next_jiffies_since_start;
> +	unsigned long jiffies_since_start;
> +	unsigned long cur_jiffies;
> +	unsigned int wait_jiffies;
> +	unsigned int numerator;
> +	unsigned int denominator;
> +	int dropped_bufs;
> +
> +	dprintk(dev, 1, "Touch Capture Thread Start\n");
> +
> +	set_freezable();
> +
> +	/* Resets frame counters */
> +	dev->touch_cap_seq_offset = 0;
> +	dev->touch_cap_seq_count = 0;
> +	dev->touch_cap_seq_resync = false;
> +	dev->jiffies_touch_cap = jiffies;
> +
> +	for (;;) {
> +		try_to_freeze();
> +		if (kthread_should_stop())
> +			break;
> +
> +		if (!mutex_trylock(&dev->mutex)) {
> +			schedule_timeout_uninterruptible(1);
> +			continue;
> +		}
> +		cur_jiffies = jiffies;
> +		if (dev->touch_cap_seq_resync) {
> +			dev->jiffies_touch_cap = cur_jiffies;
> +			dev->touch_cap_seq_offset = dev->touch_cap_seq_count + 1;
> +			dev->touch_cap_seq_count = 0;
> +			dev->cap_seq_resync = false;
> +		}
> +		denominator = dev->timeperframe_tch_cap.denominator;
> +		numerator = dev->timeperframe_tch_cap.numerator;
> +
> +		/* Calculate the number of jiffies since we started streaming */
> +		jiffies_since_start = cur_jiffies - dev->jiffies_touch_cap;
> +		/* Get the number of buffers streamed since the start */
> +		buffers_since_start = (u64)jiffies_since_start * denominator +
> +				      (HZ * numerator) / 2;
> +		do_div(buffers_since_start, HZ * numerator);
> +
> +		/*
> +		 * After more than 0xf0000000 (rounded down to a multiple of
> +		 * 'jiffies-per-day' to ease jiffies_to_msecs calculation)
> +		 * jiffies have passed since we started streaming reset the
> +		 * counters and keep track of the sequence offset.
> +		 */
> +		if (jiffies_since_start > JIFFIES_RESYNC) {
> +			dev->jiffies_touch_cap = cur_jiffies;
> +			dev->cap_seq_offset = buffers_since_start;
> +			buffers_since_start = 0;
> +		}
> +		dropped_bufs = buffers_since_start + dev->touch_cap_seq_offset - dev->touch_cap_seq_count;
> +		dev->touch_cap_seq_count = buffers_since_start + dev->touch_cap_seq_offset;
> +
> +		vivid_thread_tch_cap_tick(dev, dropped_bufs);
> +
> +		/*
> +		 * Calculate the number of 'numerators' streamed
> +		 * since we started, including the current buffer.
> +		 */
> +		numerators_since_start = ++buffers_since_start * numerator;
> +
> +		/* And the number of jiffies since we started */
> +		jiffies_since_start = jiffies - dev->jiffies_touch_cap;
> +
> +		mutex_unlock(&dev->mutex);
> +
> +		/*
> +		 * Calculate when that next buffer is supposed to start
> +		 * in jiffies since we started streaming.
> +		 */
> +		next_jiffies_since_start = numerators_since_start * HZ +
> +					   denominator / 2;
> +		do_div(next_jiffies_since_start, denominator);
> +		/* If it is in the past, then just schedule asap */
> +		if (next_jiffies_since_start < jiffies_since_start)
> +			next_jiffies_since_start = jiffies_since_start;
> +
> +		wait_jiffies = next_jiffies_since_start - jiffies_since_start;
> +		schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
> +	}
> +	dprintk(dev, 1, "Touch Capture Thread End\n");
> +	return 0;
> +}
> +
> +int vivid_start_generating_touch_cap(struct vivid_dev *dev)
> +{
> +	dprintk(dev, 1, "%s\n", __func__);
> +
> +	if (dev->kthread_touch_cap) {
> +		dev->touch_cap_streaming = true;
> +		return 0;
> +	}
> +
> +	dev->kthread_touch_cap = kthread_run(vivid_thread_touch_cap, dev,
> +					     "%s-tch-cap", dev->v4l2_dev.name);
> +
> +	if (IS_ERR(dev->kthread_touch_cap)) {
> +		int err = PTR_ERR(dev->kthread_touch_cap);
> +
> +		dev->kthread_touch_cap = NULL;
> +		v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
> +		return err;
> +	}
> +	dev->touch_cap_streaming = true;
> +	dprintk(dev, 1, "returning from %s\n", __func__);
> +	return 0;
> +}
> +
> +void vivid_stop_generating_touch_cap(struct vivid_dev *dev)
> +{
> +	dprintk(dev, 1, "%s\n", __func__);
> +
> +	if (!dev->kthread_touch_cap)
> +		return;
> +
> +	dev->touch_cap_streaming = false;
> +
> +	while (!list_empty(&dev->touch_cap_active)) {
> +		struct vivid_buffer *buf;
> +
> +		buf = list_entry(dev->touch_cap_active.next,
> +				 struct vivid_buffer, list);
> +		list_del(&buf->list);
> +		v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
> +					   &dev->ctrl_hdl_touch_cap);
> +		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
> +		dprintk(dev, 2, "touch_cap buffer %d done\n",
> +			buf->vb.vb2_buf.index);
> +	}
> +
> +	kthread_stop(dev->kthread_touch_cap);
> +	dev->kthread_touch_cap = NULL;
> +}
> diff --git a/drivers/media/platform/vivid/vivid-kthread-touch.h b/drivers/media/platform/vivid/vivid-kthread-touch.h
> new file mode 100644
> index 000000000000..ecf79b46209e
> --- /dev/null
> +++ b/drivers/media/platform/vivid/vivid-kthread-touch.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * vivid-kthread-cap.h - video/vbi capture thread support functions.
> + *
> + */
> +
> +#ifndef _VIVID_KTHREAD_CAP_H_
> +#define _VIVID_KTHREAD_CAP_H_
> +
> +int vivid_start_generating_touch_cap(struct vivid_dev *dev);
> +void vivid_stop_generating_touch_cap(struct vivid_dev *dev);
> +
> +#endif
> diff --git a/drivers/media/platform/vivid/vivid-touch-cap.c b/drivers/media/platform/vivid/vivid-touch-cap.c
> new file mode 100644
> index 000000000000..b8c1a78fb1be
> --- /dev/null
> +++ b/drivers/media/platform/vivid/vivid-touch-cap.c
> @@ -0,0 +1,325 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * vivid-touch-cap.c - touch support functions.
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/videodev2.h>
> +#include <media/v4l2-common.h>
> +#include <linux/usb/video.h>

Here too are some includes that can be dropped.

> +
> +#include "vivid-core.h"
> +#include "vivid-kthread-touch.h"
> +#include "vivid-touch-cap.h"
> +
> +static int touch_cap_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
> +				 unsigned int *nplanes, unsigned int sizes[],
> +				 struct device *alloc_devs[])
> +{
> +	unsigned int size = sizeof(struct vivid_touch_buf);
> +
> +	if (*nplanes) {
> +		if (sizes[0] < size)
> +			return -EINVAL;
> +	} else {
> +		sizes[0] = size;
> +	}
> +
> +	if (vq->num_buffers + *nbuffers < 2)
> +		*nbuffers = 2 - vq->num_buffers;
> +
> +	*nplanes = 1;
> +	return 0;
> +}
> +
> +static int touch_cap_buf_prepare(struct vb2_buffer *vb)
> +{
> +	struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
> +	unsigned int size = sizeof(struct vivid_touch_buf);
> +
> +	dprintk(dev, 1, "%s\n", __func__);
> +
> +	if (dev->buf_prepare_error) {
> +		/*
> +		 * Error injection: test what happens if buf_prepare() returns
> +		 * an error.
> +		 */
> +		dev->buf_prepare_error = false;
> +		return -EINVAL;
> +	}
> +	if (vb2_plane_size(vb, 0) < size) {
> +		dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
> +			__func__, vb2_plane_size(vb, 0), size);
> +		return -EINVAL;
> +	}
> +	vb2_set_plane_payload(vb, 0, size);
> +
> +	return 0;
> +}
> +
> +static void touch_cap_buf_queue(struct vb2_buffer *vb)
> +{
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
> +	struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
> +
> +	dprintk(dev, 1, "%s\n", __func__);
> +
> +	spin_lock(&dev->slock);
> +	list_add_tail(&buf->list, &dev->touch_cap_active);
> +	spin_unlock(&dev->slock);
> +}
> +
> +static int touch_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
> +{
> +	struct vivid_dev *dev = vb2_get_drv_priv(vq);
> +	int err;
> +
> +	dprintk(dev, 1, "%s\n", __func__);
> +	dev->touch_cap_seq_count = 0;
> +	dev->tch_test_pattern = SINGLE_TAP;
> +	dev->tch_cnt = 1;
> +	if (dev->start_streaming_error) {
> +		dev->start_streaming_error = false;
> +		err = -EINVAL;
> +	} else {
> +		err = vivid_start_generating_touch_cap(dev);
> +	}
> +	if (err) {
> +		struct vivid_buffer *buf, *tmp;
> +
> +		list_for_each_entry_safe(buf, tmp,
> +					 &dev->touch_cap_active, list) {
> +			list_del(&buf->list);
> +			vb2_buffer_done(&buf->vb.vb2_buf,
> +					VB2_BUF_STATE_QUEUED);
> +		}
> +	}
> +	return err;
> +}
> +
> +/* abort streaming and wait for last buffer */
> +static void touch_cap_stop_streaming(struct vb2_queue *vq)
> +{
> +	struct vivid_dev *dev = vb2_get_drv_priv(vq);
> +
> +	dprintk(dev, 1, "%s\n", __func__);
> +	vivid_stop_generating_touch_cap(dev);
> +}
> +
> +static void touch_cap_buf_request_complete(struct vb2_buffer *vb)
> +{
> +	struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
> +
> +	v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_touch_cap);
> +}
> +
> +const struct vb2_ops vivid_touch_cap_qops = {
> +	.queue_setup		= touch_cap_queue_setup,
> +	.buf_prepare		= touch_cap_buf_prepare,
> +	.buf_queue		= touch_cap_buf_queue,
> +	.start_streaming	= touch_cap_start_streaming,
> +	.stop_streaming		= touch_cap_stop_streaming,
> +	.buf_request_complete	= touch_cap_buf_request_complete,
> +	.wait_prepare		= vb2_ops_wait_prepare,
> +	.wait_finish		= vb2_ops_wait_finish,
> +};
> +
> +int vivid_enum_fmt_tch(struct file *file, void  *priv, struct v4l2_fmtdesc *f)
> +{
> +	struct vivid_dev *dev = video_drvdata(file);
> +
> +	if (f->index)
> +		return -EINVAL;
> +
> +	dprintk(dev, 1, "%s\n", __func__);
> +
> +	f->pixelformat = V4L2_TCH_FMT_TU16;
> +	return 0;
> +}
> +
> +int vivid_g_fmt_tch(struct file *file, void *priv, struct v4l2_format *f)
> +{
> +	struct vivid_dev *dev = video_drvdata(file);
> +
> +	dprintk(dev, 1, "%s\n", __func__);
> +
> +	f->fmt.pix = dev->tch_format;
> +	return 0;
> +}
> +
> +int vivid_g_parm_tch(struct file *file, void *priv,
> +		     struct v4l2_streamparm *parm)
> +{
> +	struct vivid_dev *dev = video_drvdata(file);
> +
> +	dprintk(dev, 1, "%s\n", __func__);
> +
> +	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		return -EINVAL;
> +
> +	parm->parm.capture.capability   = V4L2_CAP_TIMEPERFRAME;
> +	parm->parm.capture.timeperframe = dev->timeperframe_tch_cap;
> +	parm->parm.capture.readbuffers  = 1;
> +	return 0;
> +}
> +
> +int vivid_enum_input_tch(struct file *file, void *priv, struct v4l2_input *inp)
> +{
> +	struct vivid_dev *dev = video_drvdata(file);
> +
> +	dprintk(dev, 1, "%s\n", __func__);
> +
> +	if (inp->index)
> +		return -EINVAL;
> +
> +	inp->type = V4L2_INPUT_TYPE_TOUCH;
> +	snprintf(inp->name, sizeof(inp->name), "Vivid Touch %u",
> +		 dev->input_name_counter[inp->index]);
> +	inp->capabilities = 0;
> +	return 0;
> +}
> +
> +int vivid_g_input_tch(struct file *file, void *priv, unsigned int *i)
> +{
> +	*i = 0;
> +	return 0;
> +}
> +
> +int vivid_set_touch(struct vivid_dev *dev, unsigned int i)
> +{
> +	struct v4l2_pix_format *f = &dev->tch_format;
> +
> +	if (i)
> +		return -EINVAL;
> +
> +	f->pixelformat = V4L2_TCH_FMT_TU16;
> +	f->width =  VIVID_TCH_WIDTH;
> +	f->height = VIVID_TCH_HEIGHT;
> +	f->field = V4L2_FIELD_NONE;
> +	f->colorspace = V4L2_COLORSPACE_RAW;
> +	f->bytesperline = f->width * sizeof(u16);
> +	f->sizeimage = f->width * f->height * sizeof(u16);
> +	return 0;
> +}
> +
> +int vivid_s_input_tch(struct file *file, void *priv, unsigned int i)
> +{
> +	return vivid_set_touch(video_drvdata(file), i);
> +}
> +
> +int vivid_enum_frameintervals_tch(struct file *file, void *priv,
> +				  struct v4l2_frmivalenum *fival)
> +{
> +	struct vivid_dev *dev = video_drvdata(file);
> +
> +	if (fival->index)
> +		return -EINVAL;
> +	if (fival->width < VIVID_TCH_WIDTH ||
> +	    fival->width > VIVID_TCH_WIDTH)
> +		return -EINVAL;
> +	if (fival->height < VIVID_TCH_HEIGHT ||
> +	    fival->height > VIVID_TCH_HEIGHT)
> +		return -EINVAL;

That's the equivalent of fival->height != VIVID_TCH_HEIGHT :-)

> +
> +	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
> +	fival->discrete = dev->timeperframe_tch_cap;
> +	return 0;
> +}
> +
> +int vivid_enum_framesizes_tch(struct file *file, void *fh,
> +			      struct v4l2_frmsizeenum *fsize)
> +{
> +	if (fsize->index)
> +		return -EINVAL;
> +	if (fsize->pixel_format != V4L2_TCH_FMT_TU16)
> +		return -EINVAL;
> +
> +	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
> +	fsize->discrete.width  = VIVID_TCH_WIDTH;
> +	fsize->discrete.height = VIVID_TCH_HEIGHT;
> +	return 0;
> +}
> +
> +void vivid_fillbuff_tch(struct vivid_dev *dev, struct vivid_buffer *buf)
> +{
> +	int size = VIVID_TCH_WIDTH * VIVID_TCH_HEIGHT;
> +	int index = 0, x, y, xstart, ystart;
> +	struct vivid_touch_buf *tch_buf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
> +
> +	buf->vb.sequence = dev->touch_cap_seq_count;
> +
> +	memset(tch_buf, 0, vb2_plane_size(&buf->vb.vb2_buf, 0));
> +
> +	switch (dev->tch_test_pattern) {
> +	case SINGLE_TAP:
> +	case DOUBLE_TAP:
> +	case TRIPLE_TAP:
> +		if (dev->tch_cnt == 1)
> +			dev->tch_index = get_random_int() % size;
> +		if (dev->tch_cnt % 2)
> +			tch_buf->buf[dev->tch_index] = get_random_int() % VIVID_MAX_PRESSURE;
> +		dev->tch_cnt++;
> +		if (dev->tch_cnt > dev->tch_test_pattern * 2) {
> +			dev->tch_test_pattern++;
> +			dev->tch_cnt = 1;
> +		}
> +		break;
> +	case SWAP_LEFT_RIGHT:
> +		x = get_random_int() % VIVID_TCH_WIDTH;
> +		for (index = x; index < VIVID_TCH_WIDTH ; index++)
> +			tch_buf->buf[index] = get_random_int() % VIVID_MAX_PRESSURE;
> +		dev->tch_test_pattern++;
> +		dev->tch_index = 0;
> +		break;
> +	case ZOOM_IN:
> +	case ZOOM_OUT:
> +		x = VIVID_TCH_WIDTH / 2;
> +		y = VIVID_TCH_HEIGHT / 2;
> +		if (!dev->tch_index) {
> +			index = x + VIVID_TCH_WIDTH * y;
> +			tch_buf->buf[index] = get_random_int() % VIVID_MAX_PRESSURE;
> +			if (dev->tch_test_pattern == ZOOM_OUT)
> +				dev->tch_test_pattern++;
> +		} else {
> +			index = (x - dev->tch_index) + VIVID_TCH_WIDTH * (y - dev->tch_index);
> +			tch_buf->buf[index] = get_random_int() % VIVID_MAX_PRESSURE;
> +			index = (x + dev->tch_index) + VIVID_TCH_WIDTH * (y + dev->tch_index);
> +			tch_buf->buf[index] = get_random_int() % VIVID_MAX_PRESSURE;
> +		}
> +		if (dev->tch_test_pattern == ZOOM_IN) {
> +			dev->tch_index++;
> +			if (x + dev->tch_index >= VIVID_TCH_WIDTH ||
> +			    y + dev->tch_index >= VIVID_TCH_HEIGHT)
> +				dev->tch_test_pattern++;
> +		}
> +		if (dev->tch_test_pattern == ZOOM_OUT)
> +			dev->tch_index--;
> +		break;
> +	case PALM_PRESS:
> +		xstart = VIVID_TCH_WIDTH - VIVID_TCH_WIDTH / 4;
> +		ystart = VIVID_TCH_HEIGHT - VIVID_TCH_HEIGHT / 4;
> +		for (x = xstart; x < VIVID_TCH_WIDTH; x++) {
> +			for (y = ystart; y < VIVID_TCH_HEIGHT; y++) {
> +				index = x + VIVID_TCH_WIDTH * y;
> +				tch_buf->buf[index] = get_random_int() % VIVID_MAX_PRESSURE;
> +			}
> +		}
> +		dev->tch_test_pattern++;
> +		break;
> +	case MULTIPLE_PRESS:
> +		/*16 pressure points*/
> +		for (x = 0; x < 16; x++) {
> +			index = get_random_int() % size;
> +			tch_buf->buf[index] = get_random_int() % VIVID_MAX_PRESSURE;
> +		}
> +		dev->tch_test_pattern++;
> +		break;
> +	}
> +
> +	if (dev->tch_test_pattern == TEST_CASE_MAX) {
> +		dev->tch_test_pattern = SINGLE_TAP;
> +		dev->tch_cnt = 1;
> +	}
> +}
> 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..41ac3409ab31
> --- /dev/null
> +++ b/drivers/media/platform/vivid/vivid-touch-cap.h
> @@ -0,0 +1,43 @@
> +/* 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	24
> +#define VIVID_TCH_WIDTH		14
> +#define VIVID_MAX_PRESSURE	255
> +
> +enum vivid_tch_test {
> +	SINGLE_TAP = 1,
> +	DOUBLE_TAP,
> +	TRIPLE_TAP,
> +	SWAP_LEFT_RIGHT,

You mean: MOVE_LEFT_TO_RIGHT

> +	ZOOM_IN,
> +	ZOOM_OUT,
> +	PALM_PRESS,
> +	MULTIPLE_PRESS,
> +	TEST_CASE_MAX
> +};
> +
> +struct vivid_touch_buf {
> +	u16	buf[VIVID_TCH_WIDTH * VIVID_TCH_HEIGHT];
> +};
> +
> +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);
> +int vivid_enum_frameintervals_tch(struct file *file, void *priv,
> +				  struct v4l2_frmivalenum *fival);
> +int vivid_enum_framesizes_tch(struct file *file, void *fh,
> +			      struct v4l2_frmsizeenum *fsize);
> +#endif
> 

Regards,

	Hans

  reply	other threads:[~2019-11-13  7:51 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20191112135421.3766-1-bnvandana@gmail.com>
2019-11-13  7:37 ` [PATCH v4] vivid: Add touch support Vandana BN
2019-11-13  7:51   ` Hans Verkuil [this message]
2019-11-13 11:20     ` [PATCH v5] " Vandana BN
2019-11-13 14:15       ` Hans Verkuil
2019-11-13 14:52         ` Hans Verkuil
2019-11-15 13:23           ` [PATCH v6] " Vandana BN
2019-11-16 10:41             ` Hans Verkuil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=41670600-f97f-8c52-d13b-78fb1c44a01b@xs4all.nl \
    --to=hverkuil@xs4all.nl \
    --cc=bnvandana@gmail.com \
    --cc=linux-media@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.