cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

usbtv-core.c (4832B)


      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_rcvctrlpipe(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);