Re: [PATCH v4] vivid: Add touch support

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

 



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@xxxxxxxxx>
> ---
> 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



[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