]>
Commit | Line | Data |
---|---|---|
b11869db PE |
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> | |
5a0e3ad6 | 20 | #include <linux/slab.h> |
1d03d2bd | 21 | #include <linux/smp_lock.h> |
b11869db PE |
22 | #include <linux/usb.h> |
23 | #include <dvb-usb.h> | |
24 | ||
25 | #define S2250_LOADER_FIRMWARE "s2250_loader.fw" | |
26 | #define S2250_FIRMWARE "s2250.fw" | |
27 | ||
28 | typedef struct device_extension_s { | |
29 | struct kref kref; | |
30 | int minor; | |
31 | struct usb_device *usbdev; | |
32 | } device_extension_t, *pdevice_extension_t; | |
33 | ||
34 | #define USB_s2250loader_MAJOR 240 | |
35 | #define USB_s2250loader_MINOR_BASE 0 | |
36 | #define MAX_DEVICES 256 | |
37 | ||
38 | static pdevice_extension_t s2250_dev_table[MAX_DEVICES]; | |
fd9a40da | 39 | static DEFINE_MUTEX(s2250_dev_table_mutex); |
b11869db PE |
40 | |
41 | #define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref) | |
42 | static void s2250loader_delete(struct kref *kref) | |
43 | { | |
44 | pdevice_extension_t s = to_s2250loader_dev_common(kref); | |
45 | s2250_dev_table[s->minor] = NULL; | |
46 | kfree(s); | |
47 | } | |
48 | ||
49 | static int s2250loader_probe(struct usb_interface *interface, | |
50 | const struct usb_device_id *id) | |
51 | { | |
52 | struct usb_device *usbdev; | |
53 | int minor, ret; | |
54 | pdevice_extension_t s = NULL; | |
55 | const struct firmware *fw; | |
56 | ||
57 | usbdev = usb_get_dev(interface_to_usbdev(interface)); | |
58 | if (!usbdev) { | |
59 | printk(KERN_ERR "Enter s2250loader_probe failed\n"); | |
60 | return -1; | |
61 | } | |
62 | printk(KERN_INFO "Enter s2250loader_probe 2.6 kernel\n"); | |
63 | printk(KERN_INFO "vendor id 0x%x, device id 0x%x devnum:%d\n", | |
64 | usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, | |
65 | usbdev->devnum); | |
66 | ||
67 | if (usbdev->descriptor.bNumConfigurations != 1) { | |
68 | printk(KERN_ERR "can't handle multiple config\n"); | |
69 | return -1; | |
70 | } | |
fd9a40da | 71 | mutex_lock(&s2250_dev_table_mutex); |
b11869db PE |
72 | |
73 | for (minor = 0; minor < MAX_DEVICES; minor++) { | |
74 | if (s2250_dev_table[minor] == NULL) | |
75 | break; | |
76 | } | |
77 | ||
78 | if (minor < 0 || minor >= MAX_DEVICES) { | |
79 | printk(KERN_ERR "Invalid minor: %d\n", minor); | |
80 | goto failed; | |
81 | } | |
82 | ||
83 | /* Allocate dev data structure */ | |
84 | s = kmalloc(sizeof(device_extension_t), GFP_KERNEL); | |
85 | if (s == NULL) { | |
86 | printk(KERN_ERR "Out of memory\n"); | |
87 | goto failed; | |
88 | } | |
89 | s2250_dev_table[minor] = s; | |
90 | ||
91 | printk(KERN_INFO "s2250loader_probe: Device %d on Bus %d Minor %d\n", | |
92 | usbdev->devnum, usbdev->bus->busnum, minor); | |
93 | ||
94 | memset(s, 0, sizeof(device_extension_t)); | |
95 | s->usbdev = usbdev; | |
96 | printk(KERN_INFO "loading 2250 loader\n"); | |
97 | ||
98 | kref_init(&(s->kref)); | |
99 | ||
fd9a40da | 100 | mutex_unlock(&s2250_dev_table_mutex); |
b11869db PE |
101 | |
102 | if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) { | |
103 | printk(KERN_ERR | |
104 | "s2250: unable to load firmware from file \"%s\"\n", | |
105 | S2250_LOADER_FIRMWARE); | |
106 | goto failed2; | |
107 | } | |
108 | ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2); | |
109 | release_firmware(fw); | |
110 | if (0 != ret) { | |
111 | printk(KERN_ERR "loader download failed\n"); | |
112 | goto failed2; | |
113 | } | |
114 | ||
115 | if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) { | |
116 | printk(KERN_ERR | |
117 | "s2250: unable to load firmware from file \"%s\"\n", | |
118 | S2250_FIRMWARE); | |
119 | goto failed2; | |
120 | } | |
121 | ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2); | |
122 | release_firmware(fw); | |
123 | if (0 != ret) { | |
124 | printk(KERN_ERR "firmware_s2250 download failed\n"); | |
125 | goto failed2; | |
126 | } | |
127 | ||
128 | usb_set_intfdata(interface, s); | |
129 | return 0; | |
130 | ||
131 | failed: | |
fd9a40da | 132 | mutex_unlock(&s2250_dev_table_mutex); |
b11869db PE |
133 | failed2: |
134 | if (s) | |
135 | kref_put(&(s->kref), s2250loader_delete); | |
136 | ||
137 | printk(KERN_ERR "probe failed\n"); | |
138 | return -1; | |
139 | } | |
140 | ||
141 | static void s2250loader_disconnect(struct usb_interface *interface) | |
142 | { | |
f51f9030 | 143 | pdevice_extension_t s; |
b11869db PE |
144 | printk(KERN_INFO "s2250: disconnect\n"); |
145 | lock_kernel(); | |
146 | s = usb_get_intfdata(interface); | |
147 | usb_set_intfdata(interface, NULL); | |
148 | kref_put(&(s->kref), s2250loader_delete); | |
149 | unlock_kernel(); | |
150 | } | |
151 | ||
a457732b | 152 | static const struct usb_device_id s2250loader_ids[] = { |
b11869db PE |
153 | {USB_DEVICE(0x1943, 0xa250)}, |
154 | {} /* Terminating entry */ | |
155 | }; | |
156 | ||
157 | MODULE_DEVICE_TABLE(usb, s2250loader_ids); | |
158 | ||
159 | static struct usb_driver s2250loader_driver = { | |
160 | .name = "s2250-loader", | |
161 | .probe = s2250loader_probe, | |
162 | .disconnect = s2250loader_disconnect, | |
163 | .id_table = s2250loader_ids, | |
164 | }; | |
165 | ||
832b6a89 | 166 | static int __init s2250loader_init(void) |
b11869db PE |
167 | { |
168 | int r; | |
169 | unsigned i = 0; | |
170 | ||
171 | for (i = 0; i < MAX_DEVICES; i++) | |
172 | s2250_dev_table[i] = NULL; | |
173 | ||
174 | r = usb_register(&s2250loader_driver); | |
175 | if (r) { | |
176 | printk(KERN_ERR "usb_register failed. Error number %d\n", r); | |
177 | return -1; | |
178 | } | |
179 | ||
180 | printk(KERN_INFO "s2250loader_init: driver registered\n"); | |
181 | return 0; | |
182 | } | |
832b6a89 | 183 | module_init(s2250loader_init); |
b11869db | 184 | |
832b6a89 | 185 | static void __exit s2250loader_cleanup(void) |
b11869db PE |
186 | { |
187 | printk(KERN_INFO "s2250loader_cleanup\n"); | |
188 | usb_deregister(&s2250loader_driver); | |
189 | } | |
832b6a89 PE |
190 | module_exit(s2250loader_cleanup); |
191 | ||
192 | MODULE_AUTHOR(""); | |
193 | MODULE_DESCRIPTION("firmware loader for Sensoray 2250/2251"); | |
194 | MODULE_LICENSE("GPL v2"); |