File Index
Files and directories
Sign in
FILE

usbtv-core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/usb/usbtv/usbtv-core.c C
  1/*
  2 * Copyright (c) 2013 Lubomir Rintel
  3 * All rights reserved.
  4 *
  5 * Redistribution and use in source and binary forms, with or without
  6 * modification, are permitted provided that the following conditions
  7 * are met:
  8 * 1. Redistributions of source code must retain the above copyright
  9 *    notice, this list of conditions, and the following disclaimer,
 10 *    without modification.
 11 * 2. The name of the author may not be used to endorse or promote products
 12 *    derived from this software without specific prior written permission.
 13 *
 14 * Alternatively, this software may be distributed under the terms of the
 15 * GNU General Public License ("GPL").
 16 *
 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28 */
 29/*
 30 * Fushicai USBTV007 Audio-Video Grabber Driver
 31 *
 32 * Product web site:
 33 * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html
 34 *
 35 * Following LWN articles were very useful in construction of this driver:
 36 * Video4Linux2 API series: http://lwn.net/Articles/203924/
 37 * videobuf2 API explanation: http://lwn.net/Articles/447435/
 38 * Thanks go to Jonathan Corbet for providing this quality documentation.
 39 * He is awesome.
 40 *
 41 * No physical hardware was harmed running Windows during the
 42 * reverse-engineering activity
 43 */
 44
 45#include "usbtv.h"
 46
 47int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
 48{
 49	int ret;
 50	int pipe = usb_sndctrlpipe(usbtv->udev, 0);
 51	int i;
 52
 53	for (i = 0; i < size; i++) {
 54		u16 index = regs[i][0];
 55		u16 value = regs[i][1];
 56
 57		ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG,
 58			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 59			value, index, NULL, 0, USB_CTRL_GET_TIMEOUT);
 60		if (ret < 0)
 61			return ret;
 62	}
 63
 64	return 0;
 65}
 66
 67static int usbtv_probe(struct usb_interface *intf,
 68	const struct usb_device_id *id)
 69{
 70	int ret;
 71	int size;
 72	struct device *dev = &intf->dev;
 73	struct usbtv *usbtv;
 74	struct usb_host_endpoint *ep;
 75
 76	/* Checks that the device is what we think it is. */
 77	if (intf->num_altsetting != 2)
 78		return -ENODEV;
 79	if (intf->altsetting[1].desc.bNumEndpoints != 4)
 80		return -ENODEV;
 81
 82	ep = &intf->altsetting[1].endpoint[0];
 83
 84	/* Packet size is split into 11 bits of base size and count of
 85	 * extra multiplies of it.*/
 86	size = usb_endpoint_maxp(&ep->desc);
 87	size = size * usb_endpoint_maxp_mult(&ep->desc);
 88
 89	/* Device structure */
 90	usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL);
 91	if (usbtv == NULL)
 92		return -ENOMEM;
 93	usbtv->dev = dev;
 94	usbtv->udev = usb_get_dev(interface_to_usbdev(intf));
 95
 96	usbtv->iso_size = size;
 97
 98	usb_set_intfdata(intf, usbtv);
 99
100	ret = usbtv_video_init(usbtv);
101	if (ret < 0)
102		goto usbtv_video_fail;
103
104	ret = usbtv_audio_init(usbtv);
105	if (ret < 0)
106		goto usbtv_audio_fail;
107
108	/* for simplicity we exploit the v4l2_device reference counting */
109	v4l2_device_get(&usbtv->v4l2_dev);
110
111	dev_info(dev, "Fushicai USBTV007 Audio-Video Grabber\n");
112	return 0;
113
114usbtv_audio_fail:
115	/* we must not free at this point */
116	v4l2_device_get(&usbtv->v4l2_dev);
117	/* this will undo the v4l2_device_get() */
118	usbtv_video_free(usbtv);
119
120usbtv_video_fail:
121	usb_set_intfdata(intf, NULL);
122	usb_put_dev(usbtv->udev);
123	kfree(usbtv);
124
125	return ret;
126}
127
128static void usbtv_disconnect(struct usb_interface *intf)
129{
130	struct usbtv *usbtv = usb_get_intfdata(intf);
131
132	usb_set_intfdata(intf, NULL);
133
134	if (!usbtv)
135		return;
136
137	usbtv_audio_free(usbtv);
138	usbtv_video_free(usbtv);
139
140	usb_put_dev(usbtv->udev);
141	usbtv->udev = NULL;
142
143	/* the usbtv structure will be deallocated when v4l2 will be
144	   done using it */
145	v4l2_device_put(&usbtv->v4l2_dev);
146}
147
148static const struct usb_device_id usbtv_id_table[] = {
149	{ USB_DEVICE(0x1b71, 0x3002) },
150	{ USB_DEVICE(0x1f71, 0x3301) },
151	{ USB_DEVICE(0x1f71, 0x3306) },
152	{}
153};
154MODULE_DEVICE_TABLE(usb, usbtv_id_table);
155
156MODULE_AUTHOR("Lubomir Rintel, Federico Simoncelli");
157MODULE_DESCRIPTION("Fushicai USBTV007 Audio-Video Grabber Driver");
158MODULE_LICENSE("Dual BSD/GPL");
159
160static struct usb_driver usbtv_usb_driver = {
161	.name = "usbtv",
162	.id_table = usbtv_id_table,
163	.probe = usbtv_probe,
164	.disconnect = usbtv_disconnect,
165};
166
167module_usb_driver(usbtv_usb_driver);
~/ Read-only file preview.