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 */
auerchar_disconnect(struct auerscon * scp)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 */
auerchar_ctrlread_dispatch(struct auerscon * scp,struct auerbuf * bp)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 */
auerchar_delete(struct auerchar * ccp)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 */
auerchar_open(struct inode * inode,struct file * file)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 */
auerchar_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)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 */
auerchar_llseek(struct file * file,loff_t offset,int origin)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 */
auerchar_read(struct file * file,char * buf,size_t count,loff_t * ppos)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 */
auerchar_write(struct file * file,const char * buf,size_t len,loff_t * ppos)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 */
auerchar_release(struct inode * inode,struct file * file)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 }
616