Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] v4l2-core: Add support for touch devices

Some touch controllers send out touch data in a similar way to a
greyscale frame grabber.

Add new device type VFL_TYPE_TOUCH:
- This uses a new device prefix v4l-touch for these devices, to stop
generic capture software from treating them as webcams. Otherwise,
touch is treated similarly to video capture.
- Add V4L2_INPUT_TYPE_TOUCH
- Add MEDIA_INTF_T_V4L_TOUCH
- Add V4L2_CAP_TOUCH to indicate device is a touch device

Add formats:
- V4L2_TCH_FMT_DELTA_TD16 for signed 16-bit touch deltas
- V4L2_TCH_FMT_DELTA_TD08 for signed 16-bit touch deltas
- V4L2_TCH_FMT_TU16 for unsigned 16-bit touch data
- V4L2_TCH_FMT_TU08 for unsigned 8-bit touch data

This support will be used by:
- Atmel maXTouch (atmel_mxt_ts)
- Synaptics RMI4.
- sur40

Signed-off-by: Nick Dyer <nick@shmanahar.org>
Tested-by: Chris Healy <cphealy@gmail.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Nick Dyer and committed by
Mauro Carvalho Chehab
b2fe22d0 aaf578e1

+58 -9
+1
Documentation/media/kapi/v4l2-dev.rst
··· 200 200 - ``VFL_TYPE_VBI``: ``/dev/vbiX`` for vertical blank data (i.e. closed captions, teletext) 201 201 - ``VFL_TYPE_RADIO``: ``/dev/radioX`` for radio tuners 202 202 - ``VFL_TYPE_SDR``: ``/dev/swradioX`` for Software Defined Radio tuners 203 + - ``VFL_TYPE_TOUCH``: ``/dev/v4l-touchX`` for touch sensors 203 204 204 205 The last argument gives you a certain amount of control over the device 205 206 device node number used (i.e. the X in ``videoX``). Normally you will pass -1
+2
drivers/media/media-entity.c
··· 65 65 return "v4l-subdev"; 66 66 case MEDIA_INTF_T_V4L_SWRADIO: 67 67 return "v4l-swradio"; 68 + case MEDIA_INTF_T_V4L_TOUCH: 69 + return "v4l-touch"; 68 70 case MEDIA_INTF_T_ALSA_PCM_CAPTURE: 69 71 return "alsa-pcm-capture"; 70 72 case MEDIA_INTF_T_ALSA_PCM_PLAYBACK:
+11 -3
drivers/media/v4l2-core/v4l2-dev.c
··· 527 527 bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI; 528 528 bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO; 529 529 bool is_sdr = vdev->vfl_type == VFL_TYPE_SDR; 530 + bool is_tch = vdev->vfl_type == VFL_TYPE_TOUCH; 530 531 bool is_rx = vdev->vfl_dir != VFL_DIR_TX; 531 532 bool is_tx = vdev->vfl_dir != VFL_DIR_RX; 532 533 ··· 574 573 if (ops->vidioc_enum_freq_bands || ops->vidioc_g_tuner || ops->vidioc_g_modulator) 575 574 set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls); 576 575 577 - if (is_vid) { 576 + if (is_vid || is_tch) { 578 577 /* video specific ioctls */ 579 578 if ((is_rx && (ops->vidioc_enum_fmt_vid_cap || 580 579 ops->vidioc_enum_fmt_vid_cap_mplane || ··· 663 662 set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); 664 663 } 665 664 666 - if (is_vid || is_vbi || is_sdr) { 665 + if (is_vid || is_vbi || is_sdr || is_tch) { 667 666 /* ioctls valid for video, vbi or sdr */ 668 667 SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs); 669 668 SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf); ··· 676 675 SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff); 677 676 } 678 677 679 - if (is_vid || is_vbi) { 678 + if (is_vid || is_vbi || is_tch) { 680 679 /* ioctls valid for video or vbi */ 681 680 if (ops->vidioc_s_std) 682 681 set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls); ··· 751 750 case VFL_TYPE_SDR: 752 751 intf_type = MEDIA_INTF_T_V4L_SWRADIO; 753 752 vdev->entity.function = MEDIA_ENT_F_IO_SWRADIO; 753 + break; 754 + case VFL_TYPE_TOUCH: 755 + intf_type = MEDIA_INTF_T_V4L_TOUCH; 756 + vdev->entity.function = MEDIA_ENT_F_IO_V4L; 754 757 break; 755 758 case VFL_TYPE_RADIO: 756 759 intf_type = MEDIA_INTF_T_V4L_RADIO; ··· 858 853 case VFL_TYPE_SDR: 859 854 /* Use device name 'swradio' because 'sdr' was already taken. */ 860 855 name_base = "swradio"; 856 + break; 857 + case VFL_TYPE_TOUCH: 858 + name_base = "v4l-touch"; 861 859 break; 862 860 default: 863 861 printk(KERN_ERR "%s called with unknown type: %d\n",
+31 -5
drivers/media/v4l2-core/v4l2-ioctl.c
··· 924 924 bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 925 925 bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI; 926 926 bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 927 + bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; 927 928 bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 928 929 bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 929 930 ··· 933 932 934 933 switch (type) { 935 934 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 936 - if (is_vid && is_rx && 935 + if ((is_vid || is_tch) && is_rx && 937 936 (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane)) 938 937 return 0; 939 938 break; ··· 1244 1243 case V4L2_SDR_FMT_CS8: descr = "Complex S8"; break; 1245 1244 case V4L2_SDR_FMT_CS14LE: descr = "Complex S14LE"; break; 1246 1245 case V4L2_SDR_FMT_RU12LE: descr = "Real U12LE"; break; 1246 + case V4L2_TCH_FMT_DELTA_TD16: descr = "16-bit signed deltas"; break; 1247 + case V4L2_TCH_FMT_DELTA_TD08: descr = "8-bit signed deltas"; break; 1248 + case V4L2_TCH_FMT_TU16: descr = "16-bit unsigned touch data"; break; 1249 + case V4L2_TCH_FMT_TU08: descr = "8-bit unsigned touch data"; break; 1247 1250 1248 1251 default: 1249 1252 /* Compressed formats */ ··· 1314 1309 struct video_device *vfd = video_devdata(file); 1315 1310 bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1316 1311 bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 1312 + bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; 1317 1313 bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 1318 1314 bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1319 1315 int ret = -EINVAL; 1320 1316 1321 1317 switch (p->type) { 1322 1318 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1323 - if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap)) 1319 + if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_enum_fmt_vid_cap)) 1324 1320 break; 1325 1321 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg); 1326 1322 break; ··· 1368 1362 struct video_device *vfd = video_devdata(file); 1369 1363 bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1370 1364 bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 1365 + bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; 1371 1366 bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 1372 1367 bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1373 1368 int ret; ··· 1399 1392 1400 1393 switch (p->type) { 1401 1394 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1402 - if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap)) 1395 + if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_g_fmt_vid_cap)) 1403 1396 break; 1404 1397 p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1405 1398 ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); ··· 1458 1451 return -EINVAL; 1459 1452 } 1460 1453 1454 + static void v4l_pix_format_touch(struct v4l2_pix_format *p) 1455 + { 1456 + /* 1457 + * The v4l2_pix_format structure contains fields that make no sense for 1458 + * touch. Set them to default values in this case. 1459 + */ 1460 + 1461 + p->field = V4L2_FIELD_NONE; 1462 + p->colorspace = V4L2_COLORSPACE_RAW; 1463 + p->flags = 0; 1464 + p->ycbcr_enc = 0; 1465 + p->quantization = 0; 1466 + p->xfer_func = 0; 1467 + } 1468 + 1461 1469 static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, 1462 1470 struct file *file, void *fh, void *arg) 1463 1471 { ··· 1480 1458 struct video_device *vfd = video_devdata(file); 1481 1459 bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1482 1460 bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 1461 + bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; 1483 1462 bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 1484 1463 bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1485 1464 int ret; ··· 1492 1469 1493 1470 switch (p->type) { 1494 1471 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1495 - if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap)) 1472 + if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_s_fmt_vid_cap)) 1496 1473 break; 1497 1474 CLEAR_AFTER_FIELD(p, fmt.pix); 1498 1475 ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg); 1499 1476 /* just in case the driver zeroed it again */ 1500 1477 p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1478 + if (is_tch) 1479 + v4l_pix_format_touch(&p->fmt.pix); 1501 1480 return ret; 1502 1481 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 1503 1482 if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane)) ··· 1570 1545 struct video_device *vfd = video_devdata(file); 1571 1546 bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1572 1547 bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 1548 + bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; 1573 1549 bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 1574 1550 bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1575 1551 int ret; ··· 1579 1553 1580 1554 switch (p->type) { 1581 1555 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1582 - if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap)) 1556 + if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_try_fmt_vid_cap)) 1583 1557 break; 1584 1558 CLEAR_AFTER_FIELD(p, fmt.pix); 1585 1559 ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg);
+3 -1
include/media/v4l2-dev.h
··· 25 25 #define VFL_TYPE_RADIO 2 26 26 #define VFL_TYPE_SUBDEV 3 27 27 #define VFL_TYPE_SDR 4 28 - #define VFL_TYPE_MAX 5 28 + #define VFL_TYPE_TOUCH 5 29 + #define VFL_TYPE_MAX 6 29 30 30 31 /* Is this a receiver, transmitter or mem-to-mem? */ 31 32 /* Ignored for VFL_TYPE_SUBDEV. */ ··· 295 294 * - %VFL_TYPE_RADIO - A radio card 296 295 * - %VFL_TYPE_SUBDEV - A subdevice 297 296 * - %VFL_TYPE_SDR - Software Defined Radio 297 + * - %VFL_TYPE_TOUCH - A touch sensor 298 298 * 299 299 * .. note:: 300 300 *
+1
include/uapi/linux/media.h
··· 307 307 #define MEDIA_INTF_T_V4L_RADIO (MEDIA_INTF_T_V4L_BASE + 2) 308 308 #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3) 309 309 #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4) 310 + #define MEDIA_INTF_T_V4L_TOUCH (MEDIA_INTF_T_V4L_BASE + 5) 310 311 311 312 #define MEDIA_INTF_T_ALSA_PCM_CAPTURE (MEDIA_INTF_T_ALSA_BASE) 312 313 #define MEDIA_INTF_T_ALSA_PCM_PLAYBACK (MEDIA_INTF_T_ALSA_BASE + 1)
+9
include/uapi/linux/videodev2.h
··· 440 440 #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ 441 441 #define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ 442 442 443 + #define V4L2_CAP_TOUCH 0x10000000 /* Is a touch device */ 444 + 443 445 #define V4L2_CAP_DEVICE_CAPS 0x80000000 /* sets device capabilities field */ 444 446 445 447 /* ··· 636 634 #define V4L2_SDR_FMT_CS8 v4l2_fourcc('C', 'S', '0', '8') /* complex s8 */ 637 635 #define V4L2_SDR_FMT_CS14LE v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */ 638 636 #define V4L2_SDR_FMT_RU12LE v4l2_fourcc('R', 'U', '1', '2') /* real u12le */ 637 + 638 + /* Touch formats - used for Touch devices */ 639 + #define V4L2_TCH_FMT_DELTA_TD16 v4l2_fourcc('T', 'D', '1', '6') /* 16-bit signed deltas */ 640 + #define V4L2_TCH_FMT_DELTA_TD08 v4l2_fourcc('T', 'D', '0', '8') /* 8-bit signed deltas */ 641 + #define V4L2_TCH_FMT_TU16 v4l2_fourcc('T', 'U', '1', '6') /* 16-bit unsigned touch data */ 642 + #define V4L2_TCH_FMT_TU08 v4l2_fourcc('T', 'U', '0', '8') /* 8-bit unsigned touch data */ 639 643 640 644 /* priv field value to indicates that subsequent fields are valid. */ 641 645 #define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe ··· 1409 1401 /* Values for the 'type' field */ 1410 1402 #define V4L2_INPUT_TYPE_TUNER 1 1411 1403 #define V4L2_INPUT_TYPE_CAMERA 2 1404 + #define V4L2_INPUT_TYPE_TOUCH 3 1412 1405 1413 1406 /* field 'status' - general */ 1414 1407 #define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */