Import 2.3.11pre5
[davej-history.git] / drivers / usb / ezusb.c
blobbcc5c9f5cb5f69871d29500cb8484748639b00e6
1 /*****************************************************************************/
3 /*
4 * ezusb.c -- Firmware download miscdevice for Anchorchips EZUSB microcontrollers.
6 * Copyright (C) 1999
7 * Thomas Sailer (sailer@ife.ee.ethz.ch)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * History:
24 * 0.1 26.05.99 Created
28 /*****************************************************************************/
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/socket.h>
33 #include <asm/uaccess.h>
34 #include <linux/miscdevice.h>
36 #include "usb.h"
37 #include "ezusb.h"
39 /* --------------------------------------------------------------------- */
41 #define NREZUSB 1
43 static struct ezusb {
44 struct semaphore mutex;
45 struct usb_device *usbdev;
46 unsigned int irqep;
47 unsigned int intlen;
48 unsigned char intdata[64];
49 } ezusb[NREZUSB];
51 /* --------------------------------------------------------------------- */
53 static int ezusb_irq(int state, void *__buffer, int len, void *dev_id)
55 struct ezusb *ez = (struct ezusb *)dev_id;
57 if (len > sizeof(ez->intdata))
58 len = sizeof(ez->intdata);
59 ez->intlen = len;
60 memcpy(ez->intdata, __buffer, len);
61 return 1;
64 /* --------------------------------------------------------------------- */
66 static loff_t ezusb_llseek(struct file *file, loff_t offset, int origin)
68 struct ezusb *ez = (struct ezusb *)file->private_data;
70 switch(origin) {
71 case 1:
72 offset += file->f_pos;
73 break;
74 case 2:
75 offset += 0x10000;
76 break;
78 if (offset < 0 || offset >= 0x10000)
79 return -EINVAL;
80 return (file->f_pos = offset);
83 static ssize_t ezusb_read(struct file *file, char *buf, size_t sz, loff_t *ppos)
85 struct ezusb *ez = (struct ezusb *)file->private_data;
86 unsigned pos = *ppos;
87 unsigned ret = 0;
88 unsigned len;
89 unsigned char b[64];
90 devrequest dr;
91 int i;
93 if (*ppos < 0 || *ppos >= 0x10000)
94 return -EINVAL;
95 down(&ez->mutex);
96 if (!ez->usbdev) {
97 up(&ez->mutex);
98 return -EIO;
100 while (sz > 0 && pos < 0x10000) {
101 len = sz;
102 if (len > sizeof(b))
103 len = sizeof(b);
104 if (pos + len > 0x10000)
105 len = 0x10000 - pos;
106 dr.requesttype = 0xc0;
107 dr.request = 0xa0;
108 dr.value = pos;
109 dr.index = 0;
110 dr.length = len;
111 i = ez->usbdev->bus->op->control_msg(ez->usbdev, usb_rcvctrlpipe(ez->usbdev, 0), &dr, b, len);
112 if (i) {
113 up(&ez->mutex);
114 printk(KERN_WARNING "ezusb: upload failed pos %u len %u ret %d\n", dr.value, dr.length, i);
115 *ppos = pos;
116 if (ret)
117 return ret;
118 return -ENXIO;
120 if (copy_to_user(buf, b, len)) {
121 up(&ez->mutex);
122 *ppos = pos;
123 if (ret)
124 return ret;
125 return -EFAULT;
127 pos += len;
128 buf += len;
129 sz -= len;
130 ret += len;
132 up(&ez->mutex);
133 *ppos = pos;
134 return ret;
137 static ssize_t ezusb_write(struct file *file, const char *buf, size_t sz, loff_t *ppos)
139 struct ezusb *ez = (struct ezusb *)file->private_data;
140 unsigned pos = *ppos;
141 unsigned ret = 0;
142 unsigned len;
143 unsigned char b[64];
144 devrequest dr;
145 int i;
147 if (*ppos < 0 || *ppos >= 0x10000)
148 return -EINVAL;
149 down(&ez->mutex);
150 if (!ez->usbdev) {
151 up(&ez->mutex);
152 return -EIO;
154 while (sz > 0 && pos < 0x10000) {
155 len = sz;
156 if (len > sizeof(b))
157 len = sizeof(b);
158 if (pos + len > 0x10000)
159 len = 0x10000 - pos;
160 if (copy_from_user(b, buf, len)) {
161 up(&ez->mutex);
162 *ppos = pos;
163 if (ret)
164 return ret;
165 return -EFAULT;
167 dr.requesttype = 0x40;
168 dr.request = 0xa0;
169 dr.value = pos;
170 dr.index = 0;
171 dr.length = len;
172 i = ez->usbdev->bus->op->control_msg(ez->usbdev, usb_sndctrlpipe(ez->usbdev, 0), &dr, b, len);
173 if (i) {
174 up(&ez->mutex);
175 printk(KERN_WARNING "ezusb: download failed pos %u len %u ret %d\n", dr.value, dr.length, i);
176 *ppos = pos;
177 if (ret)
178 return ret;
179 return -ENXIO;
181 pos += len;
182 buf += len;
183 sz -= len;
184 ret += len;
186 up(&ez->mutex);
187 *ppos = pos;
188 return ret;
191 static int ezusb_open(struct inode *inode, struct file *file)
193 struct ezusb *ez = &ezusb[0];
195 down(&ez->mutex);
196 while (!ez->usbdev) {
197 up(&ez->mutex);
198 if (!(file->f_flags & O_NONBLOCK)) {
199 return -EIO;
201 schedule_timeout(HZ/2);
202 if (signal_pending(current))
203 return -EAGAIN;
204 down(&ez->mutex);
206 up(&ez->mutex);
207 file->f_pos = 0;
208 file->private_data = ez;
209 return 0;
212 static int ezusb_release(struct inode *inode, struct file *file)
214 struct ezusb *ez = (struct ezusb *)file->private_data;
215 return 0;
218 static int ezusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
220 struct ezusb *ez = (struct ezusb *)file->private_data;
221 struct ezusb_ctrltransfer ctrl;
222 struct ezusb_bulktransfer bulk;
223 unsigned int len1, ep;
224 unsigned long len2;
225 unsigned int irqep;
226 unsigned char tbuf[1024];
227 int i;
229 switch (cmd) {
230 case EZUSB_CONTROL:
231 copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
232 if (ctrl.dlen > sizeof(tbuf) || ctrl.dlen > 1024)
233 return -EINVAL;
234 if (ctrl.requesttype & 0x80) {
235 if (ctrl.dlen && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.dlen))
236 return -EINVAL;
237 down(&ez->mutex);
238 if (!ez->usbdev) {
239 up(&ez->mutex);
240 return -EIO;
242 i = ez->usbdev->bus->op->control_msg(ez->usbdev, usb_rcvctrlpipe(ez->usbdev, 0),
243 (devrequest *)&ctrl, tbuf, ctrl.dlen);
244 up(&ez->mutex);
245 if (!i && ctrl.dlen) {
246 copy_to_user_ret(ctrl.data, tbuf, ctrl.dlen, -EFAULT);
248 } else {
249 if (ctrl.dlen) {
250 copy_from_user_ret(tbuf, ctrl.data, ctrl.dlen, -EFAULT);
252 down(&ez->mutex);
253 if (!ez->usbdev) {
254 up(&ez->mutex);
255 return -EIO;
257 i = ez->usbdev->bus->op->control_msg(ez->usbdev, usb_sndctrlpipe(ez->usbdev, 0),
258 (devrequest *)&ctrl, tbuf, ctrl.dlen);
259 up(&ez->mutex);
261 if (i) {
262 printk(KERN_WARNING "ezusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n",
263 ctrl.requesttype, ctrl.request, ctrl.length, i);
264 return -ENXIO;
266 return 0;
268 case EZUSB_INTERRUPT:
269 get_user_ret(irqep, (unsigned int *)arg, -EFAULT);
270 if (irqep != ez->irqep) {
271 if (ez->irqep)
272 return -EIO;
273 ez->irqep = irqep;
274 usb_request_irq(ez->usbdev, usb_rcvctrlpipe(ez->usbdev, ez->irqep),
275 ezusb_irq, 2 /* interval */, ez);
276 ez->intlen = 0;
277 return -EAGAIN;
279 copy_to_user_ret((&((struct ezusb_interrupttransfer *)0)->data) + arg,
280 ez->intdata, 64, -EFAULT);
281 return ez->intlen;
283 case EZUSB_BULK:
284 copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
285 len1 = bulk.len;
286 if (len1 > sizeof(tbuf))
287 len1 = sizeof(tbuf);
288 if (bulk.ep & 0x80) {
289 if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1))
290 return -EINVAL;
291 down(&ez->mutex);
292 if (!ez->usbdev) {
293 up(&ez->mutex);
294 return -EIO;
296 i = ez->usbdev->bus->op->bulk_msg(ez->usbdev, usb_rcvbulkpipe(ez->usbdev, bulk.ep & 0x7f),
297 tbuf, len1, &len2);
298 up(&ez->mutex);
299 if (!i && len2) {
300 copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
302 } else {
303 if (len1) {
304 copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
306 down(&ez->mutex);
307 if (!ez->usbdev) {
308 up(&ez->mutex);
309 return -EIO;
311 i = ez->usbdev->bus->op->bulk_msg(ez->usbdev, usb_sndbulkpipe(ez->usbdev, bulk.ep & 0x7f),
312 tbuf, len1, &len2);
313 up(&ez->mutex);
315 if (i) {
316 printk(KERN_WARNING "ezusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n",
317 bulk.ep, bulk.len, i);
318 return -ENXIO;
320 return len2;
322 case EZUSB_RESETEP:
323 get_user_ret(ep, (unsigned int *)arg, -EFAULT);
324 if ((ep & ~0x80) >= 16)
325 return -EINVAL;
326 usb_settoggle(ez->usbdev, ep & 0xf, !(ep & 0x80), 0);
327 return 0;
329 return -ENOIOCTLCMD;
332 static struct file_operations ezusb_fops = {
333 ezusb_llseek,
334 ezusb_read,
335 ezusb_write,
336 NULL, /* readdir */
337 NULL, /* poll */
338 ezusb_ioctl,
339 NULL, /* mmap */
340 ezusb_open,
341 NULL, /* flush */
342 ezusb_release,
343 NULL, /* fsync */
344 NULL, /* fasync */
345 NULL, /* check_media_change */
346 NULL, /* revalidate */
347 NULL /* lock */
350 static struct miscdevice ezusb_misc = {
351 192, "ezusb", &ezusb_fops
354 /* --------------------------------------------------------------------- */
356 static int ezusb_probe(struct usb_device *usbdev)
358 struct ezusb *ez = &ezusb[0];
359 struct usb_interface_descriptor *interface;
360 struct usb_endpoint_descriptor *endpoint;
362 #undef KERN_DEBUG
363 #define KERN_DEBUG ""
364 printk(KERN_DEBUG "ezusb: probe: vendor id 0x%x, device id 0x%x\n",
365 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
367 /* the 1234:5678 is just a self assigned test ID */
368 if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) &&
369 (usbdev->descriptor.idVendor != 0x1234 || usbdev->descriptor.idProduct != 0x5678))
370 return -1;
372 /* We don't handle multiple configurations */
373 if (usbdev->descriptor.bNumConfigurations != 1)
374 return -1;
376 /* We don't handle multiple interfaces */
377 if (usbdev->config[0].bNumInterfaces != 1)
378 return -1;
380 down(&ez->mutex);
381 if (ez->usbdev) {
382 up(&ez->mutex);
383 printk(KERN_INFO "ezusb: device already used\n");
384 return -1;
386 ez->usbdev = usbdev;
387 usbdev->private = ez;
388 if (usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue)) {
389 printk(KERN_ERR "ezusb: set_configuration failed\n");
390 goto err;
392 interface = &usbdev->config[0].altsetting[1].interface[0];
393 if (usb_set_interface(usbdev, 0, 1)) {
394 printk(KERN_ERR "ezusb: set_interface failed\n");
395 goto err;
397 up(&ez->mutex);
398 MOD_INC_USE_COUNT;
399 return 0;
401 err:
402 up(&ez->mutex);
403 ez->usbdev = NULL;
404 usbdev->private = NULL;
405 return -1;
408 static void ezusb_disconnect(struct usb_device *usbdev)
410 struct ezusb *ez = (struct ezusb *)usbdev->private;
412 down(&ez->mutex);
413 ez->usbdev = NULL;
414 up(&ez->mutex);
415 usbdev->private = NULL;
416 MOD_DEC_USE_COUNT;
419 static struct usb_driver ezusb_driver = {
420 "ezusb",
421 ezusb_probe,
422 ezusb_disconnect,
423 { NULL, NULL }
426 /* --------------------------------------------------------------------- */
428 int ezusb_init(void)
430 unsigned u;
432 /* initialize struct */
433 for (u = 0; u < NREZUSB; u++) {
434 init_MUTEX(&ezusb[u].mutex);
435 ezusb[u].usbdev = NULL;
436 ezusb[u].irqep = 0;
438 /* register misc device */
439 if (misc_register(&ezusb_misc)) {
440 printk(KERN_WARNING "ezusb: cannot register minor %d\n", ezusb_misc.minor);
441 return -1;
443 usb_register(&ezusb_driver);
444 printk(KERN_INFO "ezusb: Anchorchip firmware download driver registered\n");
445 return 0;
448 void ezusb_cleanup(void)
450 usb_deregister(&ezusb_driver);
451 misc_deregister(&ezusb_misc);
454 /* --------------------------------------------------------------------- */
456 #ifdef MODULE
458 int minor = 192;
460 int init_module(void)
462 ezusb_misc.minor = minor;
463 return ezusb_init();
466 void cleanup_module(void)
468 ezusb_cleanup();
471 #endif
473 /* --------------------------------------------------------------------- */