static int sur40_probe()

in touchscreen/sur40.c [651:819]


static int sur40_probe(struct usb_interface *interface,
		       const struct usb_device_id *id)
{
	struct usb_device *usbdev = interface_to_usbdev(interface);
	struct sur40_state *sur40;
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	struct input_dev *input;
	int error;

	/* Check if we really have the right interface. */
	iface_desc = interface->cur_altsetting;
	if (iface_desc->desc.bInterfaceClass != 0xFF)
		return -ENODEV;

	if (iface_desc->desc.bNumEndpoints < 5)
		return -ENODEV;

	/* Use endpoint #4 (0x86). */
	endpoint = &iface_desc->endpoint[4].desc;
	if (endpoint->bEndpointAddress != TOUCH_ENDPOINT)
		return -ENODEV;

	/* Allocate memory for our device state and initialize it. */
	sur40 = kzalloc(sizeof(struct sur40_state), GFP_KERNEL);
	if (!sur40)
		return -ENOMEM;

	input = input_allocate_device();
	if (!input) {
		error = -ENOMEM;
		goto err_free_dev;
	}

	/* initialize locks/lists */
	INIT_LIST_HEAD(&sur40->buf_list);
	spin_lock_init(&sur40->qlock);
	mutex_init(&sur40->lock);

	/* Set up regular input device structure */
	input->name = DRIVER_LONG;
	usb_to_input_id(usbdev, &input->id);
	usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
	strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
	input->phys = sur40->phys;
	input->dev.parent = &interface->dev;

	input->open = sur40_open;
	input->close = sur40_close;

	error = sur40_input_setup_events(input);
	if (error)
		goto err_free_input;

	input_set_drvdata(input, sur40);
	error = input_setup_polling(input, sur40_poll);
	if (error) {
		dev_err(&interface->dev, "failed to set up polling");
		goto err_free_input;
	}

	input_set_poll_interval(input, POLL_INTERVAL);

	sur40->usbdev = usbdev;
	sur40->dev = &interface->dev;
	sur40->input = input;

	/* use the bulk-in endpoint tested above */
	sur40->bulk_in_size = usb_endpoint_maxp(endpoint);
	sur40->bulk_in_epaddr = endpoint->bEndpointAddress;
	sur40->bulk_in_buffer = kmalloc(sur40->bulk_in_size, GFP_KERNEL);
	if (!sur40->bulk_in_buffer) {
		dev_err(&interface->dev, "Unable to allocate input buffer.");
		error = -ENOMEM;
		goto err_free_input;
	}

	/* register the polled input device */
	error = input_register_device(input);
	if (error) {
		dev_err(&interface->dev,
			"Unable to register polled input device.");
		goto err_free_buffer;
	}

	/* register the video master device */
	snprintf(sur40->v4l2.name, sizeof(sur40->v4l2.name), "%s", DRIVER_LONG);
	error = v4l2_device_register(sur40->dev, &sur40->v4l2);
	if (error) {
		dev_err(&interface->dev,
			"Unable to register video master device.");
		goto err_unreg_v4l2;
	}

	/* initialize the lock and subdevice */
	sur40->queue = sur40_queue;
	sur40->queue.drv_priv = sur40;
	sur40->queue.lock = &sur40->lock;
	sur40->queue.dev = sur40->dev;

	/* initialize the queue */
	error = vb2_queue_init(&sur40->queue);
	if (error)
		goto err_unreg_v4l2;

	sur40->pix_fmt = sur40_pix_format[0];
	sur40->vdev = sur40_video_device;
	sur40->vdev.v4l2_dev = &sur40->v4l2;
	sur40->vdev.lock = &sur40->lock;
	sur40->vdev.queue = &sur40->queue;
	video_set_drvdata(&sur40->vdev, sur40);

	/* initialize the control handler for 4 controls */
	v4l2_ctrl_handler_init(&sur40->hdl, 4);
	sur40->v4l2.ctrl_handler = &sur40->hdl;
	sur40->vsvideo = (SUR40_CONTRAST_DEF << 4) | SUR40_GAIN_DEF;

	v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_BRIGHTNESS,
	  SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX, 1, clamp(brightness,
	  (uint)SUR40_BRIGHTNESS_MIN, (uint)SUR40_BRIGHTNESS_MAX));

	v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_CONTRAST,
	  SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX, 1, clamp(contrast,
	  (uint)SUR40_CONTRAST_MIN, (uint)SUR40_CONTRAST_MAX));

	v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_GAIN,
	  SUR40_GAIN_MIN, SUR40_GAIN_MAX, 1, clamp(gain,
	  (uint)SUR40_GAIN_MIN, (uint)SUR40_GAIN_MAX));

	v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops,
	  V4L2_CID_BACKLIGHT_COMPENSATION, SUR40_BACKLIGHT_MIN,
	  SUR40_BACKLIGHT_MAX, 1, SUR40_BACKLIGHT_DEF);

	v4l2_ctrl_handler_setup(&sur40->hdl);

	if (sur40->hdl.error) {
		dev_err(&interface->dev,
			"Unable to register video controls.");
		v4l2_ctrl_handler_free(&sur40->hdl);
		error = sur40->hdl.error;
		goto err_unreg_v4l2;
	}

	error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1);
	if (error) {
		dev_err(&interface->dev,
			"Unable to register video subdevice.");
		goto err_unreg_video;
	}

	/* we can register the device now, as it is ready */
	usb_set_intfdata(interface, sur40);
	dev_dbg(&interface->dev, "%s is now attached\n", DRIVER_DESC);

	return 0;

err_unreg_video:
	video_unregister_device(&sur40->vdev);
err_unreg_v4l2:
	v4l2_device_unregister(&sur40->v4l2);
err_free_buffer:
	kfree(sur40->bulk_in_buffer);
err_free_input:
	input_free_device(input);
err_free_dev:
	kfree(sur40);

	return error;
}