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                printk(KERN_ERR "Enter s2250loader_probe failed\n");
  59                return -1;
  60        }
  61        printk(KERN_INFO "Enter s2250loader_probe 2.6 kernel\n");
  62        printk(KERN_INFO "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                printk(KERN_ERR "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                printk(KERN_ERR "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                printk(KERN_ERR "Out of memory\n");
  86                goto failed;
  87        }
  88        s2250_dev_table[minor] = s;
  89
  90        printk(KERN_INFO "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        printk(KERN_INFO "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                printk(KERN_ERR
 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                printk(KERN_ERR "loader download failed\n");
 111                goto failed2;
 112        }
 113
 114        if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) {
 115                printk(KERN_ERR
 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                printk(KERN_ERR "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        printk(KERN_ERR "probe failed\n");
 137        return -1;
 138}
 139
 140static void s2250loader_disconnect(struct usb_interface *interface)
 141{
 142        pdevice_extension_t s;
 143        printk(KERN_INFO "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
 163static int __init s2250loader_init(void)
 164{
 165        int r;
 166        unsigned i = 0;
 167
 168        for (i = 0; i < MAX_DEVICES; i++)
 169                s2250_dev_table[i] = NULL;
 170
 171        r = usb_register(&s2250loader_driver);
 172        if (r) {
 173                printk(KERN_ERR "usb_register failed. Error number %d\n", r);
 174                return -1;
 175        }
 176
 177        printk(KERN_INFO "s2250loader_init: driver registered\n");
 178        return 0;
 179}
 180module_init(s2250loader_init);
 181
 182static void __exit s2250loader_cleanup(void)
 183{
 184        printk(KERN_INFO "s2250loader_cleanup\n");
 185        usb_deregister(&s2250loader_driver);
 186}
 187module_exit(s2250loader_cleanup);
 188
 189MODULE_AUTHOR("");
 190MODULE_DESCRIPTION("firmware loader for Sensoray 2250/2251");
 191MODULE_LICENSE("GPL v2");
 192
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.