| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Surface2.0/SUR40/PixelSense input driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 14 | 15 | * |
|---|
| 15 | 16 | * and from the v4l2-pci-skeleton driver, |
|---|
| 16 | 17 | * Copyright (c) Copyright 2014 Cisco Systems, Inc. |
|---|
| 17 | | - * |
|---|
| 18 | | - * This program is free software; you can redistribute it and/or |
|---|
| 19 | | - * modify it under the terms of the GNU General Public License as |
|---|
| 20 | | - * published by the Free Software Foundation; either version 2 of |
|---|
| 21 | | - * the License, or (at your option) any later version. |
|---|
| 22 | 18 | */ |
|---|
| 23 | 19 | |
|---|
| 24 | 20 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 31 | 27 | #include <linux/uaccess.h> |
|---|
| 32 | 28 | #include <linux/usb.h> |
|---|
| 33 | 29 | #include <linux/printk.h> |
|---|
| 34 | | -#include <linux/input-polldev.h> |
|---|
| 30 | +#include <linux/input.h> |
|---|
| 35 | 31 | #include <linux/input/mt.h> |
|---|
| 36 | 32 | #include <linux/usb/input.h> |
|---|
| 37 | 33 | #include <linux/videodev2.h> |
|---|
| .. | .. |
|---|
| 190 | 186 | .width = SENSOR_RES_X / 2, |
|---|
| 191 | 187 | .height = SENSOR_RES_Y / 2, |
|---|
| 192 | 188 | .field = V4L2_FIELD_NONE, |
|---|
| 193 | | - .colorspace = V4L2_COLORSPACE_SRGB, |
|---|
| 189 | + .colorspace = V4L2_COLORSPACE_RAW, |
|---|
| 194 | 190 | .bytesperline = SENSOR_RES_X / 2, |
|---|
| 195 | 191 | .sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2), |
|---|
| 196 | 192 | }, |
|---|
| .. | .. |
|---|
| 199 | 195 | .width = SENSOR_RES_X / 2, |
|---|
| 200 | 196 | .height = SENSOR_RES_Y / 2, |
|---|
| 201 | 197 | .field = V4L2_FIELD_NONE, |
|---|
| 202 | | - .colorspace = V4L2_COLORSPACE_SRGB, |
|---|
| 198 | + .colorspace = V4L2_COLORSPACE_RAW, |
|---|
| 203 | 199 | .bytesperline = SENSOR_RES_X / 2, |
|---|
| 204 | 200 | .sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2), |
|---|
| 205 | 201 | } |
|---|
| .. | .. |
|---|
| 210 | 206 | |
|---|
| 211 | 207 | struct usb_device *usbdev; |
|---|
| 212 | 208 | struct device *dev; |
|---|
| 213 | | - struct input_polled_dev *input; |
|---|
| 209 | + struct input_dev *input; |
|---|
| 214 | 210 | |
|---|
| 215 | 211 | struct v4l2_device v4l2; |
|---|
| 216 | 212 | struct video_device vdev; |
|---|
| .. | .. |
|---|
| 374 | 370 | goto error; |
|---|
| 375 | 371 | |
|---|
| 376 | 372 | result = sur40_command(dev, SUR40_GET_VERSION, 0x03, buffer, 12); |
|---|
| 373 | + if (result < 0) |
|---|
| 374 | + goto error; |
|---|
| 375 | + |
|---|
| 376 | + result = 0; |
|---|
| 377 | 377 | |
|---|
| 378 | 378 | /* |
|---|
| 379 | 379 | * Discard the result buffer - no known data inside except |
|---|
| .. | .. |
|---|
| 385 | 385 | } |
|---|
| 386 | 386 | |
|---|
| 387 | 387 | /* |
|---|
| 388 | | - * Callback routines from input_polled_dev |
|---|
| 388 | + * Callback routines from input_dev |
|---|
| 389 | 389 | */ |
|---|
| 390 | 390 | |
|---|
| 391 | 391 | /* Enable the device, polling will now start. */ |
|---|
| 392 | | -static void sur40_open(struct input_polled_dev *polldev) |
|---|
| 392 | +static int sur40_open(struct input_dev *input) |
|---|
| 393 | 393 | { |
|---|
| 394 | | - struct sur40_state *sur40 = polldev->private; |
|---|
| 394 | + struct sur40_state *sur40 = input_get_drvdata(input); |
|---|
| 395 | 395 | |
|---|
| 396 | 396 | dev_dbg(sur40->dev, "open\n"); |
|---|
| 397 | | - sur40_init(sur40); |
|---|
| 397 | + return sur40_init(sur40); |
|---|
| 398 | 398 | } |
|---|
| 399 | 399 | |
|---|
| 400 | 400 | /* Disable device, polling has stopped. */ |
|---|
| 401 | | -static void sur40_close(struct input_polled_dev *polldev) |
|---|
| 401 | +static void sur40_close(struct input_dev *input) |
|---|
| 402 | 402 | { |
|---|
| 403 | | - struct sur40_state *sur40 = polldev->private; |
|---|
| 403 | + struct sur40_state *sur40 = input_get_drvdata(input); |
|---|
| 404 | 404 | |
|---|
| 405 | 405 | dev_dbg(sur40->dev, "close\n"); |
|---|
| 406 | 406 | /* |
|---|
| .. | .. |
|---|
| 452 | 452 | } |
|---|
| 453 | 453 | |
|---|
| 454 | 454 | /* core function: poll for new input data */ |
|---|
| 455 | | -static void sur40_poll(struct input_polled_dev *polldev) |
|---|
| 455 | +static void sur40_poll(struct input_dev *input) |
|---|
| 456 | 456 | { |
|---|
| 457 | | - struct sur40_state *sur40 = polldev->private; |
|---|
| 458 | | - struct input_dev *input = polldev->input; |
|---|
| 457 | + struct sur40_state *sur40 = input_get_drvdata(input); |
|---|
| 459 | 458 | int result, bulk_read, need_blobs, packet_blobs, i; |
|---|
| 460 | | - u32 uninitialized_var(packet_id); |
|---|
| 461 | | - |
|---|
| 462 | 459 | struct sur40_header *header = &sur40->bulk_in_buffer->header; |
|---|
| 463 | 460 | struct sur40_blob *inblob = &sur40->bulk_in_buffer->blobs[0]; |
|---|
| 464 | 461 | |
|---|
| .. | .. |
|---|
| 492 | 489 | if (need_blobs == -1) { |
|---|
| 493 | 490 | need_blobs = le16_to_cpu(header->count); |
|---|
| 494 | 491 | dev_dbg(sur40->dev, "need %d blobs\n", need_blobs); |
|---|
| 495 | | - packet_id = le32_to_cpu(header->packet_id); |
|---|
| 492 | + /* packet_id = le32_to_cpu(header->packet_id); */ |
|---|
| 496 | 493 | } |
|---|
| 497 | 494 | |
|---|
| 498 | 495 | /* |
|---|
| .. | .. |
|---|
| 617 | 614 | } |
|---|
| 618 | 615 | |
|---|
| 619 | 616 | /* Initialize input device parameters. */ |
|---|
| 620 | | -static void sur40_input_setup(struct input_dev *input_dev) |
|---|
| 617 | +static int sur40_input_setup_events(struct input_dev *input_dev) |
|---|
| 621 | 618 | { |
|---|
| 622 | | - __set_bit(EV_KEY, input_dev->evbit); |
|---|
| 623 | | - __set_bit(EV_ABS, input_dev->evbit); |
|---|
| 619 | + int error; |
|---|
| 624 | 620 | |
|---|
| 625 | 621 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
|---|
| 626 | 622 | 0, SENSOR_RES_X, 0, 0); |
|---|
| .. | .. |
|---|
| 641 | 637 | |
|---|
| 642 | 638 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); |
|---|
| 643 | 639 | |
|---|
| 644 | | - input_mt_init_slots(input_dev, MAX_CONTACTS, |
|---|
| 645 | | - INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); |
|---|
| 640 | + error = input_mt_init_slots(input_dev, MAX_CONTACTS, |
|---|
| 641 | + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); |
|---|
| 642 | + if (error) { |
|---|
| 643 | + dev_err(input_dev->dev.parent, "failed to set up slots\n"); |
|---|
| 644 | + return error; |
|---|
| 645 | + } |
|---|
| 646 | + |
|---|
| 647 | + return 0; |
|---|
| 646 | 648 | } |
|---|
| 647 | 649 | |
|---|
| 648 | 650 | /* Check candidate USB interface. */ |
|---|
| .. | .. |
|---|
| 653 | 655 | struct sur40_state *sur40; |
|---|
| 654 | 656 | struct usb_host_interface *iface_desc; |
|---|
| 655 | 657 | struct usb_endpoint_descriptor *endpoint; |
|---|
| 656 | | - struct input_polled_dev *poll_dev; |
|---|
| 658 | + struct input_dev *input; |
|---|
| 657 | 659 | int error; |
|---|
| 658 | 660 | |
|---|
| 659 | 661 | /* Check if we really have the right interface. */ |
|---|
| .. | .. |
|---|
| 674 | 676 | if (!sur40) |
|---|
| 675 | 677 | return -ENOMEM; |
|---|
| 676 | 678 | |
|---|
| 677 | | - poll_dev = input_allocate_polled_device(); |
|---|
| 678 | | - if (!poll_dev) { |
|---|
| 679 | + input = input_allocate_device(); |
|---|
| 680 | + if (!input) { |
|---|
| 679 | 681 | error = -ENOMEM; |
|---|
| 680 | 682 | goto err_free_dev; |
|---|
| 681 | 683 | } |
|---|
| .. | .. |
|---|
| 685 | 687 | spin_lock_init(&sur40->qlock); |
|---|
| 686 | 688 | mutex_init(&sur40->lock); |
|---|
| 687 | 689 | |
|---|
| 688 | | - /* Set up polled input device control structure */ |
|---|
| 689 | | - poll_dev->private = sur40; |
|---|
| 690 | | - poll_dev->poll_interval = POLL_INTERVAL; |
|---|
| 691 | | - poll_dev->open = sur40_open; |
|---|
| 692 | | - poll_dev->poll = sur40_poll; |
|---|
| 693 | | - poll_dev->close = sur40_close; |
|---|
| 694 | | - |
|---|
| 695 | 690 | /* Set up regular input device structure */ |
|---|
| 696 | | - sur40_input_setup(poll_dev->input); |
|---|
| 697 | | - |
|---|
| 698 | | - poll_dev->input->name = DRIVER_LONG; |
|---|
| 699 | | - usb_to_input_id(usbdev, &poll_dev->input->id); |
|---|
| 691 | + input->name = DRIVER_LONG; |
|---|
| 692 | + usb_to_input_id(usbdev, &input->id); |
|---|
| 700 | 693 | usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys)); |
|---|
| 701 | 694 | strlcat(sur40->phys, "/input0", sizeof(sur40->phys)); |
|---|
| 702 | | - poll_dev->input->phys = sur40->phys; |
|---|
| 703 | | - poll_dev->input->dev.parent = &interface->dev; |
|---|
| 695 | + input->phys = sur40->phys; |
|---|
| 696 | + input->dev.parent = &interface->dev; |
|---|
| 697 | + |
|---|
| 698 | + input->open = sur40_open; |
|---|
| 699 | + input->close = sur40_close; |
|---|
| 700 | + |
|---|
| 701 | + error = sur40_input_setup_events(input); |
|---|
| 702 | + if (error) |
|---|
| 703 | + goto err_free_input; |
|---|
| 704 | + |
|---|
| 705 | + input_set_drvdata(input, sur40); |
|---|
| 706 | + error = input_setup_polling(input, sur40_poll); |
|---|
| 707 | + if (error) { |
|---|
| 708 | + dev_err(&interface->dev, "failed to set up polling"); |
|---|
| 709 | + goto err_free_input; |
|---|
| 710 | + } |
|---|
| 711 | + |
|---|
| 712 | + input_set_poll_interval(input, POLL_INTERVAL); |
|---|
| 704 | 713 | |
|---|
| 705 | 714 | sur40->usbdev = usbdev; |
|---|
| 706 | 715 | sur40->dev = &interface->dev; |
|---|
| 707 | | - sur40->input = poll_dev; |
|---|
| 716 | + sur40->input = input; |
|---|
| 708 | 717 | |
|---|
| 709 | 718 | /* use the bulk-in endpoint tested above */ |
|---|
| 710 | 719 | sur40->bulk_in_size = usb_endpoint_maxp(endpoint); |
|---|
| .. | .. |
|---|
| 713 | 722 | if (!sur40->bulk_in_buffer) { |
|---|
| 714 | 723 | dev_err(&interface->dev, "Unable to allocate input buffer."); |
|---|
| 715 | 724 | error = -ENOMEM; |
|---|
| 716 | | - goto err_free_polldev; |
|---|
| 725 | + goto err_free_input; |
|---|
| 717 | 726 | } |
|---|
| 718 | 727 | |
|---|
| 719 | 728 | /* register the polled input device */ |
|---|
| 720 | | - error = input_register_polled_device(poll_dev); |
|---|
| 729 | + error = input_register_device(input); |
|---|
| 721 | 730 | if (error) { |
|---|
| 722 | 731 | dev_err(&interface->dev, |
|---|
| 723 | 732 | "Unable to register polled input device."); |
|---|
| .. | .. |
|---|
| 801 | 810 | v4l2_device_unregister(&sur40->v4l2); |
|---|
| 802 | 811 | err_free_buffer: |
|---|
| 803 | 812 | kfree(sur40->bulk_in_buffer); |
|---|
| 804 | | -err_free_polldev: |
|---|
| 805 | | - input_free_polled_device(sur40->input); |
|---|
| 813 | +err_free_input: |
|---|
| 814 | + input_free_device(input); |
|---|
| 806 | 815 | err_free_dev: |
|---|
| 807 | 816 | kfree(sur40); |
|---|
| 808 | 817 | |
|---|
| .. | .. |
|---|
| 818 | 827 | video_unregister_device(&sur40->vdev); |
|---|
| 819 | 828 | v4l2_device_unregister(&sur40->v4l2); |
|---|
| 820 | 829 | |
|---|
| 821 | | - input_unregister_polled_device(sur40->input); |
|---|
| 822 | | - input_free_polled_device(sur40->input); |
|---|
| 830 | + input_unregister_device(sur40->input); |
|---|
| 823 | 831 | kfree(sur40->bulk_in_buffer); |
|---|
| 824 | 832 | kfree(sur40); |
|---|
| 825 | 833 | |
|---|
| .. | .. |
|---|
| 934 | 942 | strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver)); |
|---|
| 935 | 943 | strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card)); |
|---|
| 936 | 944 | usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info)); |
|---|
| 937 | | - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH | |
|---|
| 938 | | - V4L2_CAP_READWRITE | |
|---|
| 939 | | - V4L2_CAP_STREAMING; |
|---|
| 940 | | - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
|---|
| 941 | 945 | return 0; |
|---|
| 942 | 946 | } |
|---|
| 943 | 947 | |
|---|
| .. | .. |
|---|
| 1167 | 1171 | .fops = &sur40_video_fops, |
|---|
| 1168 | 1172 | .ioctl_ops = &sur40_video_ioctl_ops, |
|---|
| 1169 | 1173 | .release = video_device_release_empty, |
|---|
| 1174 | + .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH | |
|---|
| 1175 | + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING, |
|---|
| 1170 | 1176 | }; |
|---|
| 1171 | 1177 | |
|---|
| 1172 | 1178 | /* USB-specific object needed to register this driver with the USB subsystem. */ |
|---|