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; 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; >> + } >> +} > > 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 >> >