added mtd driver
[linux-2.4.git] / drivers / usb / auerchar.c
1 /*****************************************************************************/
2 /*
3  *      auerchar.c  --  Auerswald PBX/System Telephone character interface.
4  *
5  *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
6  *
7  *      Very much code of this driver is borrowed from dabusb.c (Deti Fliegl)
8  *      and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you.
9  *
10  *      This program is free software; you can redistribute it and/or modify
11  *      it under the terms of the GNU General Public License as published by
12  *      the Free Software Foundation; either version 2 of the License, or
13  *      (at your option) any later version.
14  *
15  *      This program is distributed in the hope that it will be useful,
16  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *      GNU General Public License for more details.
19  *
20  *      You should have received a copy of the GNU General Public License
21  *      along with this program; if not, write to the Free Software
22  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24  /*****************************************************************************/
25
26 #undef DEBUG                    /* include debug macros until it's done */
27 #include <linux/usb.h>
28 #include "auerchar.h"
29 #include "auermain.h"
30 #include <linux/slab.h>
31 #include <asm/uaccess.h>        /* user area access functions */
32
33 /*-------------------------------------------------------------------*/
34
35 /* wake up waiting readers */
36 static void auerchar_disconnect(struct auerscon *scp)
37 {
38         struct auerchar *ccp =((struct auerchar *) ((char *) (scp) - (unsigned long) (&((struct auerchar *) 0)->scontext)));
39         dbg("auerchar_disconnect called");
40         ccp->removed = 1;
41         wake_up(&ccp->readwait);
42 }
43
44
45 /* dispatch a read paket to a waiting character device */
46 static void auerchar_ctrlread_dispatch(struct auerscon *scp,
47                                        struct auerbuf *bp)
48 {
49         unsigned long flags;
50         struct auerchar *ccp;
51         struct auerbuf *newbp = NULL;
52         char *charp;
53         dbg("auerchar_ctrlread_dispatch called");
54         ccp =((struct auerchar *) ((char *) (scp) - (unsigned long)(&((struct auerchar *) 0)->scontext)));
55
56         /* get a read buffer from character device context */
57         newbp = auerbuf_getbuf(&ccp->bufctl);
58         if (!newbp) {
59                 dbg("No read buffer available, discard paket!");
60                 return;         /* no buffer, no dispatch */
61         }
62
63         /* copy information to new buffer element
64            (all buffers have the same length) */
65         charp = newbp->bufp;
66         newbp->bufp = bp->bufp;
67         bp->bufp = charp;
68         newbp->len = bp->len;
69
70         /* insert new buffer in read list */
71         spin_lock_irqsave(&ccp->bufctl.lock, flags);
72         list_add_tail(&newbp->buff_list, &ccp->bufctl.rec_buff_list);
73         spin_unlock_irqrestore(&ccp->bufctl.lock, flags);
74         dbg("read buffer appended to rec_list");
75
76         /* wake up pending synchronous reads */
77         wake_up(&ccp->readwait);
78 }
79
80
81 /* Delete an auerswald character context */
82 void auerchar_delete(struct auerchar *ccp)
83 {
84         dbg("auerchar_delete");
85         if (ccp == NULL)
86                 return;
87
88         /* wake up pending synchronous reads */
89         ccp->removed = 1;
90         wake_up(&ccp->readwait);
91
92         /* remove the read buffer */
93         if (ccp->readbuf) {
94                 auerbuf_releasebuf(ccp->readbuf);
95                 ccp->readbuf = NULL;
96         }
97
98         /* remove the character buffers */
99         auerbuf_free_buffers(&ccp->bufctl);
100
101         /* release the memory */
102         kfree(ccp);
103 }
104
105
106 /* --------------------------------------------------------------------- */
107 /* Char device functions                                                 */
108
109 /* Open a new character device */
110 int auerchar_open(struct inode *inode, struct file *file)
111 {
112         int dtindex = MINOR(inode->i_rdev) - AUER_MINOR_BASE;
113         struct auerswald *cp = NULL;
114         struct auerchar *ccp = NULL;
115         int ret;
116
117         /* minor number in range? */
118         if ((dtindex < 0) || (dtindex >= AUER_MAX_DEVICES)) {
119                 return -ENODEV;
120         }
121         /* usb device available? */
122         if (down_interruptible(&auerdev_table_mutex)) {
123                 return -ERESTARTSYS;
124         }
125         cp = auerdev_table[dtindex];
126         if (cp == NULL) {
127                 up(&auerdev_table_mutex);
128                 return -ENODEV;
129         }
130         if (down_interruptible(&cp->mutex)) {
131                 up(&auerdev_table_mutex);
132                 return -ERESTARTSYS;
133         }
134         up(&auerdev_table_mutex);
135
136         /* we have access to the device. Now lets allocate memory */
137         ccp = (struct auerchar *) kmalloc(sizeof(struct auerchar), GFP_KERNEL);
138         if (ccp == NULL) {
139                 err("out of memory");
140                 ret = -ENOMEM;
141                 goto ofail;
142         }
143
144         /* Initialize device descriptor */
145         memset(ccp, 0, sizeof(struct auerchar));
146         init_MUTEX(&ccp->mutex);
147         init_MUTEX(&ccp->readmutex);
148         auerbuf_init(&ccp->bufctl);
149         ccp->scontext.id = AUH_UNASSIGNED;
150         ccp->scontext.dispatch = auerchar_ctrlread_dispatch;
151         ccp->scontext.disconnect = auerchar_disconnect;
152         init_waitqueue_head(&ccp->readwait);
153
154         ret =
155             auerbuf_setup(&ccp->bufctl, AU_RBUFFERS,
156                           cp->maxControlLength + AUH_SIZE);
157         if (ret) {
158                 goto ofail;
159         }
160
161         cp->open_count++;
162         ccp->auerdev = cp;
163         dbg("open %s as /dev/usb/%s", cp->dev_desc, cp->name);
164         up(&cp->mutex);
165
166         /* file IO stuff */
167         file->f_pos = 0;
168         file->private_data = ccp;
169         return 0;
170
171         /* Error exit */
172       ofail:up(&cp->mutex);
173         auerchar_delete(ccp);
174         return ret;
175 }
176
177
178 /* IOCTL functions */
179 int auerchar_ioctl(struct inode *inode, struct file *file,
180                    unsigned int cmd, unsigned long arg)
181 {
182         struct auerchar *ccp = (struct auerchar *) file->private_data;
183         int ret = 0;
184         struct audevinfo devinfo;
185         struct auerswald *cp = NULL;
186         unsigned int u;
187         dbg("ioctl");
188
189         /* get the mutexes */
190         if (down_interruptible(&ccp->mutex)) {
191                 return -ERESTARTSYS;
192         }
193         cp = ccp->auerdev;
194         if (!cp) {
195                 up(&ccp->mutex);
196                 return -ENODEV;
197         }
198         if (down_interruptible(&cp->mutex)) {
199                 up(&ccp->mutex);
200                 return -ERESTARTSYS;
201         }
202
203         /* Check for removal */
204         if (!cp->usbdev) {
205                 up(&cp->mutex);
206                 up(&ccp->mutex);
207                 return -ENODEV;
208         }
209
210         switch (cmd) {
211
212                 /* return != 0 if Transmitt channel ready to send */
213         case IOCTL_AU_TXREADY:
214                 dbg("IOCTL_AU_TXREADY");
215                 u = ccp->auerdev && (ccp->scontext.id != AUH_UNASSIGNED)
216                     && !list_empty(&cp->bufctl.free_buff_list);
217                 ret = put_user(u, (unsigned int *) arg);
218                 break;
219
220                 /* return != 0 if connected to a service channel */
221         case IOCTL_AU_CONNECT:
222                 dbg("IOCTL_AU_CONNECT");
223                 u = (ccp->scontext.id != AUH_UNASSIGNED);
224                 ret = put_user(u, (unsigned int *) arg);
225                 break;
226
227                 /* return != 0 if Receive Data available */
228         case IOCTL_AU_RXAVAIL:
229                 dbg("IOCTL_AU_RXAVAIL");
230                 if (ccp->scontext.id == AUH_UNASSIGNED) {
231                         ret = -EIO;
232                         break;
233                 }
234                 u = 0;          /* no data */
235                 if (ccp->readbuf) {
236                         int restlen = ccp->readbuf->len - ccp->readoffset;
237                         if (restlen > 0)
238                                 u = 1;
239                 }
240                 if (!u) {
241                         if (!list_empty(&ccp->bufctl.rec_buff_list)) {
242                                 u = 1;
243                         }
244                 }
245                 ret = put_user(u, (unsigned int *) arg);
246                 break;
247
248                 /* return the max. buffer length for the device */
249         case IOCTL_AU_BUFLEN:
250                 dbg("IOCTL_AU_BUFLEN");
251                 u = cp->maxControlLength;
252                 ret = put_user(u, (unsigned int *) arg);
253                 break;
254
255                 /* requesting a service channel */
256         case IOCTL_AU_SERVREQ:
257                 dbg("IOCTL_AU_SERVREQ");
258                 /* requesting a service means: release the previous one first */
259                 auerswald_removeservice(cp, &ccp->scontext);
260                 /* get the channel number */
261                 ret = get_user(u, (unsigned int *) arg);
262                 if (ret) {
263                         break;
264                 }
265                 if ((u < AUH_FIRSTUSERCH) || (u >= AUH_TYPESIZE)) {
266                         ret = -EIO;
267                         break;
268                 }
269                 dbg("auerchar service request parameters are ok");
270                 ccp->scontext.id = u;
271
272                 /* request the service now */
273                 ret = auerswald_addservice(cp, &ccp->scontext);
274                 if (ret) {
275                         /* no: revert service entry */
276                         ccp->scontext.id = AUH_UNASSIGNED;
277                 }
278                 break;
279
280                 /* get a string descriptor for the device */
281         case IOCTL_AU_DEVINFO:
282                 dbg("IOCTL_AU_DEVINFO");
283                 if (copy_from_user
284                     (&devinfo, (void *) arg, sizeof(struct audevinfo))) {
285                         ret = -EFAULT;
286                         break;
287                 }
288                 u = strlen(cp->dev_desc) + 1;
289                 if (u > devinfo.bsize) {
290                         u = devinfo.bsize;
291                 }
292                 ret = copy_to_user(devinfo.buf, cp->dev_desc, u);
293                 break;
294
295                 /* get the max. string descriptor length */
296         case IOCTL_AU_SLEN:
297                 dbg("IOCTL_AU_SLEN");
298                 u = AUSI_DLEN;
299                 ret = put_user(u, (unsigned int *) arg);
300                 break;
301
302         default:
303                 dbg("IOCTL_AU_UNKNOWN");
304                 ret = -ENOIOCTLCMD;
305                 break;
306         }
307         /* release the mutexes */
308         up(&cp->mutex);
309         up(&ccp->mutex);
310         return ret;
311 }
312
313
314 /* Seek is not supported */
315 loff_t auerchar_llseek(struct file * file, loff_t offset, int origin)
316 {
317         dbg("auerchar_seek");
318         return -ESPIPE;
319 }
320
321
322 /* Read data from the device */
323 ssize_t auerchar_read(struct file * file, char *buf, size_t count,
324                       loff_t * ppos)
325 {
326         unsigned long flags;
327         struct auerchar *ccp = (struct auerchar *) file->private_data;
328         struct auerbuf *bp = NULL;
329         wait_queue_t wait;
330
331         dbg("auerchar_read");
332
333         /* Error checking */
334         if (!ccp)
335                 return -EIO;
336         if (*ppos)
337                 return -ESPIPE;
338         if (count == 0)
339                 return 0;
340
341         /* get the mutex */
342         if (down_interruptible(&ccp->mutex))
343                 return -ERESTARTSYS;
344
345         /* Can we expect to read something? */
346         if (ccp->scontext.id == AUH_UNASSIGNED) {
347                 up(&ccp->mutex);
348                 return -EIO;
349         }
350
351         /* only one reader per device allowed */
352         if (down_interruptible(&ccp->readmutex)) {
353                 up(&ccp->mutex);
354                 return -ERESTARTSYS;
355         }
356
357         /* read data from readbuf, if available */
358       doreadbuf:
359         bp = ccp->readbuf;
360         if (bp) {
361                 /* read the maximum bytes */
362                 int restlen = bp->len - ccp->readoffset;
363                 if (restlen < 0)
364                         restlen = 0;
365                 if (count > restlen)
366                         count = restlen;
367                 if (count) {
368                         if (copy_to_user
369                             (buf, bp->bufp + ccp->readoffset, count)) {
370                                 dbg("auerswald_read: copy_to_user failed");
371                                 up(&ccp->readmutex);
372                                 up(&ccp->mutex);
373                                 return -EFAULT;
374                         }
375                 }
376                 /* advance the read offset */
377                 ccp->readoffset += count;
378                 restlen -= count;
379                 // reuse the read buffer
380                 if (restlen <= 0) {
381                         auerbuf_releasebuf(bp);
382                         ccp->readbuf = NULL;
383                 }
384                 /* return with number of bytes read */
385                 if (count) {
386                         up(&ccp->readmutex);
387                         up(&ccp->mutex);
388                         return count;
389                 }
390         }
391
392         /* a read buffer is not available. Try to get the next data block. */
393       doreadlist:
394         /* Preparing for sleep */
395         init_waitqueue_entry(&wait, current);
396         set_current_state(TASK_INTERRUPTIBLE);
397         add_wait_queue(&ccp->readwait, &wait);
398
399         bp = NULL;
400         spin_lock_irqsave(&ccp->bufctl.lock, flags);
401         if (!list_empty(&ccp->bufctl.rec_buff_list)) {
402                 /* yes: get the entry */
403                 struct list_head *tmp = ccp->bufctl.rec_buff_list.next;
404                 list_del(tmp);
405                 bp = list_entry(tmp, struct auerbuf, buff_list);
406         }
407         spin_unlock_irqrestore(&ccp->bufctl.lock, flags);
408
409         /* have we got data? */
410         if (bp) {
411                 ccp->readbuf = bp;
412                 ccp->readoffset = AUH_SIZE;     /* for headerbyte */
413                 set_current_state(TASK_RUNNING);
414                 remove_wait_queue(&ccp->readwait, &wait);
415                 goto doreadbuf; /* now we can read! */
416         }
417
418         /* no data available. Should we wait? */
419         if (file->f_flags & O_NONBLOCK) {
420                 dbg("No read buffer available, returning -EAGAIN");
421                 set_current_state(TASK_RUNNING);
422                 remove_wait_queue(&ccp->readwait, &wait);
423                 up(&ccp->readmutex);
424                 up(&ccp->mutex);
425                 return -EAGAIN; /* nonblocking, no data available */
426         }
427
428         /* yes, we should wait! */
429         up(&ccp->mutex);        /* allow other operations while we wait */
430         schedule();
431         remove_wait_queue(&ccp->readwait, &wait);
432         if (signal_pending(current)) {
433                 /* waked up by a signal */
434                 up(&ccp->readmutex);
435                 return -ERESTARTSYS;
436         }
437
438         /* Anything left to read? */
439         if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
440                 up(&ccp->readmutex);
441                 return -EIO;
442         }
443
444         if (down_interruptible(&ccp->mutex)) {
445                 up(&ccp->readmutex);
446                 return -ERESTARTSYS;
447         }
448
449         /* try to read the incomming data again */
450         goto doreadlist;
451 }
452
453
454 /* Write a data block into the right service channel of the device */
455 ssize_t auerchar_write(struct file *file, const char *buf, size_t len,
456                        loff_t * ppos)
457 {
458         struct auerchar *ccp = (struct auerchar *) file->private_data;
459         struct auerswald *cp = NULL;
460         struct auerbuf *bp;
461         int ret;
462         wait_queue_t wait;
463
464         dbg("auerchar_write %d bytes", len);
465
466         /* Error checking */
467         if (!ccp)
468                 return -EIO;
469         if (*ppos)
470                 return -ESPIPE;
471         if (len == 0)
472                 return 0;
473
474       write_again:
475         /* get the mutex */
476         if (down_interruptible(&ccp->mutex))
477                 return -ERESTARTSYS;
478
479         /* Can we expect to write something? */
480         if (ccp->scontext.id == AUH_UNASSIGNED) {
481                 up(&ccp->mutex);
482                 return -EIO;
483         }
484
485         cp = ccp->auerdev;
486         if (!cp) {
487                 up(&ccp->mutex);
488                 return -ERESTARTSYS;
489         }
490         if (down_interruptible(&cp->mutex)) {
491                 up(&ccp->mutex);
492                 return -ERESTARTSYS;
493         }
494         if (!cp->usbdev) {
495                 up(&cp->mutex);
496                 up(&ccp->mutex);
497                 return -EIO;
498         }
499         /* Prepare for sleep */
500         init_waitqueue_entry(&wait, current);
501         set_current_state(TASK_INTERRUPTIBLE);
502         add_wait_queue(&cp->bufferwait, &wait);
503
504         /* Try to get a buffer from the device pool.
505            We can't use a buffer from ccp->bufctl because the write
506            command will last beond a release() */
507         bp = auerbuf_getbuf(&cp->bufctl);
508         /* are there any buffers left? */
509         if (!bp) {
510                 up(&cp->mutex);
511                 up(&ccp->mutex);
512
513                 /* NONBLOCK: don't wait */
514                 if (file->f_flags & O_NONBLOCK) {
515                         set_current_state(TASK_RUNNING);
516                         remove_wait_queue(&cp->bufferwait, &wait);
517                         return -EAGAIN;
518                 }
519
520                 /* BLOCKING: wait */
521                 schedule();
522                 remove_wait_queue(&cp->bufferwait, &wait);
523                 if (signal_pending(current)) {
524                         /* waked up by a signal */
525                         return -ERESTARTSYS;
526                 }
527                 goto write_again;
528         } else {
529                 set_current_state(TASK_RUNNING);
530                 remove_wait_queue(&cp->bufferwait, &wait);
531         }
532
533         /* protect against too big write requests */
534         if (len > cp->maxControlLength)
535                 len = cp->maxControlLength;
536
537         /* Fill the buffer */
538         if (copy_from_user(bp->bufp + AUH_SIZE, buf, len)) {
539                 dbg("copy_from_user failed");
540                 auerbuf_releasebuf(bp);
541                 /* Wake up all processes waiting for a buffer */
542                 wake_up(&cp->bufferwait);
543                 up(&cp->mutex);
544                 up(&ccp->mutex);
545                 return -EIO;
546         }
547
548         /* set the header byte */
549         *(bp->bufp) = ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT;
550
551         /* Set the transfer Parameters */
552         bp->len = len + AUH_SIZE;
553         bp->dr->bRequestType = AUT_WREQ;
554         bp->dr->bRequest = AUV_WBLOCK;
555         bp->dr->wValue = cpu_to_le16(0);
556         bp->dr->wIndex =
557             cpu_to_le16(ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT);
558         bp->dr->wLength = cpu_to_le16(len + AUH_SIZE);
559         FILL_CONTROL_URB(bp->urbp, cp->usbdev,
560                          usb_sndctrlpipe(cp->usbdev, 0),
561                          (unsigned char *) bp->dr, bp->bufp,
562                          len + AUH_SIZE, auerchar_ctrlwrite_complete, bp);
563         /* up we go */
564         ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
565         up(&cp->mutex);
566         if (ret) {
567                 dbg("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
568                 auerbuf_releasebuf(bp);
569                 /* Wake up all processes waiting for a buffer */
570                 wake_up(&cp->bufferwait);
571                 up(&ccp->mutex);
572                 return -EIO;
573         } else {
574                 dbg("auerchar_write: Write OK");
575                 up(&ccp->mutex);
576                 return len;
577         }
578 }
579
580
581 /* Close a character device */
582 int auerchar_release(struct inode *inode, struct file *file)
583 {
584         struct auerchar *ccp = (struct auerchar *) file->private_data;
585         struct auerswald *cp;
586         dbg("release");
587
588         /* get the mutexes */
589         if (down_interruptible(&ccp->mutex)) {
590                 return -ERESTARTSYS;
591         }
592         cp = ccp->auerdev;
593         if (cp) {
594                 if (down_interruptible(&cp->mutex)) {
595                         up(&ccp->mutex);
596                         return -ERESTARTSYS;
597                 }
598                 /* remove an open service */
599                 auerswald_removeservice(cp, &ccp->scontext);
600                 /* detach from device */
601                 if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) {
602                         /* usb device waits for removal */
603                         up(&cp->mutex);
604                         auerswald_delete(cp);
605                 } else {
606                         up(&cp->mutex);
607                 }
608                 cp = NULL;
609                 ccp->auerdev = NULL;
610         }
611         up(&ccp->mutex);
612         auerchar_delete(ccp);
613
614         return 0;
615 }