linux/drivers/staging/media/go7007/s2250-loader.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2008 Sensoray Company Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License (Version 2) as
   6 * published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software Foundation,
  15 * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/init.h>
  20#include <linux/slab.h>
  21#include <linux/usb.h>
  22#include <dvb-usb.h>
  23
  24#define S2250_LOADER_FIRMWARE   "s2250_loader.fw"
  25#define S2250_FIRMWARE          "s2250.fw"
  26
  27typedef struct device_extension_s {
  28    struct kref     kref;
  29    int minor;
  30    struct usb_device *usbdev;
  31} device_extension_t, *pdevice_extension_t;
  32
  33#define USB_s2250loader_MAJOR 240
  34#define USB_s2250loader_MINOR_BASE 0
  35#define MAX_DEVICES 256
  36
  37static pdevice_extension_t s2250_dev_table[MAX_DEVICES];
  38static DEFINE_MUTEX(s2250_dev_table_mutex);
  39
  40#define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref)
  41static void s2250loader_delete(struct kref *kref)
  42{
  43        pdevice_extension_t s = to_s2250loader_dev_common(kref);
  44        s2250_dev_table[s->minor] = NULL;
  45        kfree(s);
  46}
  47
  48static int s2250loader_probe(struct usb_interface *interface,
  49                                const struct usb_device_id *id)
  50{
  51        struct usb_device *usbdev;
  52        int minor, ret;
  53        pdevice_extension_t s = NULL;
  54        const struct firmware *fw;
  55
  56        usbdev = usb_get_dev(interface_to_usbdev(interface));
  57        if (!usbdev) {
  58                dev_err(&interface->dev, "Enter s2250loader_probe failed\n");
  59                return -1;
  60        }
  61        dev_info(&interface->dev, "Enter s2250loader_probe 2.6 kernel\n");
  62        dev_info(&interface->dev, "vendor id 0x%x, device id 0x%x devnum:%d\n",
  63                 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
  64                 usbdev->devnum);
  65
  66        if (usbdev->descriptor.bNumConfigurations != 1) {
  67                dev_err(&interface->dev, "can't handle multiple config\n");
  68                return -1;
  69        }
  70        mutex_lock(&s2250_dev_table_mutex);
  71
  72        for (minor = 0; minor < MAX_DEVICES; minor++) {
  73                if (s2250_dev_table[minor] == NULL)
  74                        break;
  75        }
  76
  77        if (minor < 0 || minor >= MAX_DEVICES) {
  78                dev_err(&interface->dev, "Invalid minor: %d\n", minor);
  79                goto failed;
  80        }
  81
  82        /* Allocate dev data structure */
  83        s = kmalloc(sizeof(device_extension_t), GFP_KERNEL);
  84        if (s == NULL)
  85                goto failed;
  86
  87        s2250_dev_table[minor] = s;
  88
  89        dev_info(&interface->dev,
  90                 "s2250loader_probe: Device %d on Bus %d Minor %d\n",
  91                 usbdev->devnum, usbdev->bus->busnum, minor);
  92
  93        memset(s, 0, sizeof(device_extension_t));
  94        s->usbdev = usbdev;
  95        dev_info(&interface->dev, "loading 2250 loader\n");
  96
  97        kref_init(&(s->kref));
  98
  99        mutex_unlock(&s2250_dev_table_mutex);
 100
 101        if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) {
 102                dev_err(&interface->dev,
 103                        "s2250: unable to load firmware from file \"%s\"\n",
 104                        S2250_LOADER_FIRMWARE);
 105                goto failed2;
 106        }
 107        ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
 108        release_firmware(fw);
 109        if (0 != ret) {
 110                dev_err(&interface->dev, "loader download failed\n");
 111                goto failed2;
 112        }
 113
 114        if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) {
 115                dev_err(&interface->dev,
 116                        "s2250: unable to load firmware from file \"%s\"\n",
 117                        S2250_FIRMWARE);
 118                goto failed2;
 119        }
 120        ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
 121        release_firmware(fw);
 122        if (0 != ret) {
 123                dev_err(&interface->dev, "firmware_s2250 download failed\n");
 124                goto failed2;
 125        }
 126
 127        usb_set_intfdata(interface, s);
 128        return 0;
 129
 130failed:
 131        mutex_unlock(&s2250_dev_table_mutex);
 132failed2:
 133        if (s)
 134                kref_put(&(s->kref), s2250loader_delete);
 135
 136        dev_err(&interface->dev, "probe failed\n");
 137        return -1;
 138}
 139
 140static void s2250loader_disconnect(struct usb_interface *interface)
 141{
 142        pdevice_extension_t s;
 143        dev_info(&interface->dev, "s2250: disconnect\n");
 144        s = usb_get_intfdata(interface);
 145        usb_set_intfdata(interface, NULL);
 146        kref_put(&(s->kref), s2250loader_delete);
 147}
 148
 149static const struct usb_device_id s2250loader_ids[] = {
 150        {USB_DEVICE(0x1943, 0xa250)},
 151        {}                          /* Terminating entry */
 152};
 153
 154MODULE_DEVICE_TABLE(usb, s2250loader_ids);
 155
 156static struct usb_driver s2250loader_driver = {
 157        .name           = "s2250-loader",
 158        .probe          = s2250loader_probe,
 159        .disconnect     = s2250loader_disconnect,
 160        .id_table       = s2250loader_ids,
 161};
 162
 163module_usb_driver(s2250loader_driver);
 164
 165MODULE_AUTHOR("");
 166MODULE_DESCRIPTION("firmware loader for Sensoray 2250/2251");
 167MODULE_LICENSE("GPL v2");
 168MODULE_FIRMWARE(S2250_LOADER_FIRMWARE);
 169MODULE_FIRMWARE(S2250_FIRMWARE);
 170
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.