diff options
author | merge <null@invalid> | 2009-01-22 13:55:32 +0000 |
---|---|---|
committer | Andy Green <agreen@octopus.localdomain> | 2009-01-22 13:55:32 +0000 |
commit | aa6f5ffbdba45aa8e19e5048648fc6c7b25376d3 (patch) | |
tree | fbb786d0ac6f8a774fd834e9ce951197e60fbffa /drivers/staging/go7007/s2250-loader.c | |
parent | f2d78193eae5dccd3d588d2c8ea0866efc368332 (diff) |
MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141
pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 / fdf777a63bcb59e0dfd78bfe2c6242e01f6d4eb9 ... parent commitmessage:
From: merge <null@invalid>
MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040
stable-tracking-hist top was MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 / 90463bfd2d5a3c8b52f6e6d71024a00e052b0ced ... parent commitmessage:
From: merge <null@invalid>
MERGE-via-mokopatches-tracking-hist-fix-stray-endmenu-patch
mokopatches-tracking-hist top was fix-stray-endmenu-patch / 3630e0be570de8057e7f8d2fe501ed353cdf34e6 ... parent commitmessage:
From: Andy Green <andy@openmoko.com>
fix-stray-endmenu.patch
Signed-off-by: Andy Green <andy@openmoko.com>
Diffstat (limited to 'drivers/staging/go7007/s2250-loader.c')
-rw-r--r-- | drivers/staging/go7007/s2250-loader.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c new file mode 100644 index 00000000000..a5e4acab089 --- /dev/null +++ b/drivers/staging/go7007/s2250-loader.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2008 Sensoray Company Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/usb.h> +#include <dvb-usb.h> + +#define S2250_LOADER_FIRMWARE "s2250_loader.fw" +#define S2250_FIRMWARE "s2250.fw" + +typedef struct device_extension_s { + struct kref kref; + int minor; + struct usb_device *usbdev; +} device_extension_t, *pdevice_extension_t; + +#define USB_s2250loader_MAJOR 240 +#define USB_s2250loader_MINOR_BASE 0 +#define MAX_DEVICES 256 + +static pdevice_extension_t s2250_dev_table[MAX_DEVICES]; +static DECLARE_MUTEX(s2250_dev_table_mutex); + +#define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref) +static void s2250loader_delete(struct kref *kref) +{ + pdevice_extension_t s = to_s2250loader_dev_common(kref); + s2250_dev_table[s->minor] = NULL; + kfree(s); +} + +static int s2250loader_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *usbdev; + int minor, ret; + pdevice_extension_t s = NULL; + const struct firmware *fw; + + usbdev = usb_get_dev(interface_to_usbdev(interface)); + if (!usbdev) { + printk(KERN_ERR "Enter s2250loader_probe failed\n"); + return -1; + } + printk(KERN_INFO "Enter s2250loader_probe 2.6 kernel\n"); + printk(KERN_INFO "vendor id 0x%x, device id 0x%x devnum:%d\n", + usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, + usbdev->devnum); + + if (usbdev->descriptor.bNumConfigurations != 1) { + printk(KERN_ERR "can't handle multiple config\n"); + return -1; + } + down(&s2250_dev_table_mutex); + + for (minor = 0; minor < MAX_DEVICES; minor++) { + if (s2250_dev_table[minor] == NULL) + break; + } + + if (minor < 0 || minor >= MAX_DEVICES) { + printk(KERN_ERR "Invalid minor: %d\n", minor); + goto failed; + } + + /* Allocate dev data structure */ + s = kmalloc(sizeof(device_extension_t), GFP_KERNEL); + if (s == NULL) { + printk(KERN_ERR "Out of memory\n"); + goto failed; + } + s2250_dev_table[minor] = s; + + printk(KERN_INFO "s2250loader_probe: Device %d on Bus %d Minor %d\n", + usbdev->devnum, usbdev->bus->busnum, minor); + + memset(s, 0, sizeof(device_extension_t)); + s->usbdev = usbdev; + printk(KERN_INFO "loading 2250 loader\n"); + + kref_init(&(s->kref)); + + up(&s2250_dev_table_mutex); + + if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) { + printk(KERN_ERR + "s2250: unable to load firmware from file \"%s\"\n", + S2250_LOADER_FIRMWARE); + goto failed2; + } + ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2); + release_firmware(fw); + if (0 != ret) { + printk(KERN_ERR "loader download failed\n"); + goto failed2; + } + + if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) { + printk(KERN_ERR + "s2250: unable to load firmware from file \"%s\"\n", + S2250_FIRMWARE); + goto failed2; + } + ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2); + release_firmware(fw); + if (0 != ret) { + printk(KERN_ERR "firmware_s2250 download failed\n"); + goto failed2; + } + + usb_set_intfdata(interface, s); + return 0; + +failed: + up(&s2250_dev_table_mutex); +failed2: + if (s) + kref_put(&(s->kref), s2250loader_delete); + + printk(KERN_ERR "probe failed\n"); + return -1; +} + +static void s2250loader_disconnect(struct usb_interface *interface) +{ + pdevice_extension_t s = usb_get_intfdata(interface); + printk(KERN_INFO "s2250: disconnect\n"); + lock_kernel(); + s = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + kref_put(&(s->kref), s2250loader_delete); + unlock_kernel(); +} + +static struct usb_device_id s2250loader_ids[] = { + {USB_DEVICE(0x1943, 0xa250)}, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, s2250loader_ids); + +static struct usb_driver s2250loader_driver = { + .name = "s2250-loader", + .probe = s2250loader_probe, + .disconnect = s2250loader_disconnect, + .id_table = s2250loader_ids, +}; + +int s2250loader_init(void) +{ + int r; + unsigned i = 0; + + for (i = 0; i < MAX_DEVICES; i++) + s2250_dev_table[i] = NULL; + + r = usb_register(&s2250loader_driver); + if (r) { + printk(KERN_ERR "usb_register failed. Error number %d\n", r); + return -1; + } + + printk(KERN_INFO "s2250loader_init: driver registered\n"); + return 0; +} +EXPORT_SYMBOL(s2250loader_init); + +void s2250loader_cleanup(void) +{ + printk(KERN_INFO "s2250loader_cleanup\n"); + usb_deregister(&s2250loader_driver); +} +EXPORT_SYMBOL(s2250loader_cleanup); |