linux/drivers/media/usb/usbtv/usbtv-core.c
<<
>>
Prefs
   1/*
   2 * Fushicai USBTV007 Audio-Video Grabber Driver
   3 *
   4 * Product web site:
   5 * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html
   6 *
   7 * Following LWN articles were very useful in construction of this driver:
   8 * Video4Linux2 API series: http://lwn.net/Articles/203924/
   9 * videobuf2 API explanation: http://lwn.net/Articles/447435/
  10 * Thanks go to Jonathan Corbet for providing this quality documentation.
  11 * He is awesome.
  12 *
  13 * Copyright (c) 2013 Lubomir Rintel
  14 * All rights reserved.
  15 * No physical hardware was harmed running Windows during the
  16 * reverse-engineering activity
  17 *
  18 * Redistribution and use in source and binary forms, with or without
  19 * modification, are permitted provided that the following conditions
  20 * are met:
  21 * 1. Redistributions of source code must retain the above copyright
  22 *    notice, this list of conditions, and the following disclaimer,
  23 *    without modification.
  24 * 2. The name of the author may not be used to endorse or promote products
  25 *    derived from this software without specific prior written permission.
  26 *
  27 * Alternatively, this software may be distributed under the terms of the
  28 * GNU General Public License ("GPL").
  29 */
  30
  31#include "usbtv.h"
  32
  33int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
  34{
  35        int ret;
  36        int pipe = usb_rcvctrlpipe(usbtv->udev, 0);
  37        int i;
  38
  39        for (i = 0; i < size; i++) {
  40                u16 index = regs[i][0];
  41                u16 value = regs[i][1];
  42
  43                ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG,
  44                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  45                        value, index, NULL, 0, 0);
  46                if (ret < 0)
  47                        return ret;
  48        }
  49
  50        return 0;
  51}
  52
  53static int usbtv_probe(struct usb_interface *intf,
  54        const struct usb_device_id *id)
  55{
  56        int ret;
  57        int size;
  58        struct device *dev = &intf->dev;
  59        struct usbtv *usbtv;
  60
  61        /* Checks that the device is what we think it is. */
  62        if (intf->num_altsetting != 2)
  63                return -ENODEV;
  64        if (intf->altsetting[1].desc.bNumEndpoints != 4)
  65                return -ENODEV;
  66
  67        /* Packet size is split into 11 bits of base size and count of
  68         * extra multiplies of it.*/
  69        size = usb_endpoint_maxp(&intf->altsetting[1].endpoint[0].desc);
  70        size = (size & 0x07ff) * (((size & 0x1800) >> 11) + 1);
  71
  72        /* Device structure */
  73        usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL);
  74        if (usbtv == NULL)
  75                return -ENOMEM;
  76        usbtv->dev = dev;
  77        usbtv->udev = usb_get_dev(interface_to_usbdev(intf));
  78
  79        usbtv->iso_size = size;
  80
  81        usb_set_intfdata(intf, usbtv);
  82
  83        ret = usbtv_video_init(usbtv);
  84        if (ret < 0)
  85                goto usbtv_video_fail;
  86
  87        ret = usbtv_audio_init(usbtv);
  88        if (ret < 0)
  89                goto usbtv_audio_fail;
  90
  91        /* for simplicity we exploit the v4l2_device reference counting */
  92        v4l2_device_get(&usbtv->v4l2_dev);
  93
  94        dev_info(dev, "Fushicai USBTV007 Audio-Video Grabber\n");
  95        return 0;
  96
  97usbtv_audio_fail:
  98        usbtv_video_free(usbtv);
  99
 100usbtv_video_fail:
 101        usb_set_intfdata(intf, NULL);
 102        usb_put_dev(usbtv->udev);
 103        kfree(usbtv);
 104
 105        return ret;
 106}
 107
 108static void usbtv_disconnect(struct usb_interface *intf)
 109{
 110        struct usbtv *usbtv = usb_get_intfdata(intf);
 111
 112        usb_set_intfdata(intf, NULL);
 113
 114        if (!usbtv)
 115                return;
 116
 117        usbtv_audio_free(usbtv);
 118        usbtv_video_free(usbtv);
 119
 120        usb_put_dev(usbtv->udev);
 121        usbtv->udev = NULL;
 122
 123        /* the usbtv structure will be deallocated when v4l2 will be
 124           done using it */
 125        v4l2_device_put(&usbtv->v4l2_dev);
 126}
 127
 128static struct usb_device_id usbtv_id_table[] = {
 129        { USB_DEVICE(0x1b71, 0x3002) },
 130        {}
 131};
 132MODULE_DEVICE_TABLE(usb, usbtv_id_table);
 133
 134MODULE_AUTHOR("Lubomir Rintel, Federico Simoncelli");
 135MODULE_DESCRIPTION("Fushicai USBTV007 Audio-Video Grabber Driver");
 136MODULE_LICENSE("Dual BSD/GPL");
 137
 138static struct usb_driver usbtv_usb_driver = {
 139        .name = "usbtv",
 140        .id_table = usbtv_id_table,
 141        .probe = usbtv_probe,
 142        .disconnect = usbtv_disconnect,
 143};
 144
 145module_usb_driver(usbtv_usb_driver);
 146