diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/irda/irtty-sir.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/net/irda/irtty-sir.c')
-rw-r--r-- | drivers/net/irda/irtty-sir.c | 642 |
1 files changed, 642 insertions, 0 deletions
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c new file mode 100644 index 000000000000..7d23aa375908 --- /dev/null +++ b/drivers/net/irda/irtty-sir.c | |||
@@ -0,0 +1,642 @@ | |||
1 | /********************************************************************* | ||
2 | * | ||
3 | * Filename: irtty-sir.c | ||
4 | * Version: 2.0 | ||
5 | * Description: IrDA line discipline implementation | ||
6 | * Status: Experimental. | ||
7 | * Author: Dag Brattli <dagb@cs.uit.no> | ||
8 | * Created at: Tue Dec 9 21:18:38 1997 | ||
9 | * Modified at: Sun Oct 27 22:13:30 2002 | ||
10 | * Modified by: Martin Diehl <mad@mdiehl.de> | ||
11 | * Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk> | ||
12 | * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> | ||
13 | * | ||
14 | * Copyright (c) 1998-2000 Dag Brattli, | ||
15 | * Copyright (c) 2002 Martin Diehl, | ||
16 | * All Rights Reserved. | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License as | ||
20 | * published by the Free Software Foundation; either version 2 of | ||
21 | * the License, or (at your option) any later version. | ||
22 | * | ||
23 | * Neither Dag Brattli nor University of Tromsų admit liability nor | ||
24 | * provide warranty for any of this software. This material is | ||
25 | * provided "AS-IS" and at no charge. | ||
26 | * | ||
27 | ********************************************************************/ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/tty.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | #include <linux/smp_lock.h> | ||
35 | #include <linux/delay.h> | ||
36 | |||
37 | #include <net/irda/irda.h> | ||
38 | #include <net/irda/irda_device.h> | ||
39 | |||
40 | #include "sir-dev.h" | ||
41 | #include "irtty-sir.h" | ||
42 | |||
43 | static int qos_mtt_bits = 0x03; /* 5 ms or more */ | ||
44 | |||
45 | module_param(qos_mtt_bits, int, 0); | ||
46 | MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); | ||
47 | |||
48 | /* ------------------------------------------------------- */ | ||
49 | |||
50 | /* device configuration callbacks always invoked with irda-thread context */ | ||
51 | |||
52 | /* find out, how many chars we have in buffers below us | ||
53 | * this is allowed to lie, i.e. return less chars than we | ||
54 | * actually have. The returned value is used to determine | ||
55 | * how long the irdathread should wait before doing the | ||
56 | * real blocking wait_until_sent() | ||
57 | */ | ||
58 | |||
59 | static int irtty_chars_in_buffer(struct sir_dev *dev) | ||
60 | { | ||
61 | struct sirtty_cb *priv = dev->priv; | ||
62 | |||
63 | IRDA_ASSERT(priv != NULL, return -1;); | ||
64 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); | ||
65 | |||
66 | return priv->tty->driver->chars_in_buffer(priv->tty); | ||
67 | } | ||
68 | |||
69 | /* Wait (sleep) until underlaying hardware finished transmission | ||
70 | * i.e. hardware buffers are drained | ||
71 | * this must block and not return before all characters are really sent | ||
72 | * | ||
73 | * If the tty sits on top of a 16550A-like uart, there are typically | ||
74 | * up to 16 bytes in the fifo - f.e. 9600 bps 8N1 needs 16.7 msec | ||
75 | * | ||
76 | * With usbserial the uart-fifo is basically replaced by the converter's | ||
77 | * outgoing endpoint buffer, which can usually hold 64 bytes (at least). | ||
78 | * With pl2303 it appears we are safe with 60msec here. | ||
79 | * | ||
80 | * I really wish all serial drivers would provide | ||
81 | * correct implementation of wait_until_sent() | ||
82 | */ | ||
83 | |||
84 | #define USBSERIAL_TX_DONE_DELAY 60 | ||
85 | |||
86 | static void irtty_wait_until_sent(struct sir_dev *dev) | ||
87 | { | ||
88 | struct sirtty_cb *priv = dev->priv; | ||
89 | struct tty_struct *tty; | ||
90 | |||
91 | IRDA_ASSERT(priv != NULL, return;); | ||
92 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); | ||
93 | |||
94 | tty = priv->tty; | ||
95 | if (tty->driver->wait_until_sent) { | ||
96 | lock_kernel(); | ||
97 | tty->driver->wait_until_sent(tty, msecs_to_jiffies(100)); | ||
98 | unlock_kernel(); | ||
99 | } | ||
100 | else { | ||
101 | msleep(USBSERIAL_TX_DONE_DELAY); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Function irtty_change_speed (dev, speed) | ||
107 | * | ||
108 | * Change the speed of the serial port. | ||
109 | * | ||
110 | * This may sleep in set_termios (usbserial driver f.e.) and must | ||
111 | * not be called from interrupt/timer/tasklet therefore. | ||
112 | * All such invocations are deferred to kIrDAd now so we can sleep there. | ||
113 | */ | ||
114 | |||
115 | static int irtty_change_speed(struct sir_dev *dev, unsigned speed) | ||
116 | { | ||
117 | struct sirtty_cb *priv = dev->priv; | ||
118 | struct tty_struct *tty; | ||
119 | struct termios old_termios; | ||
120 | int cflag; | ||
121 | |||
122 | IRDA_ASSERT(priv != NULL, return -1;); | ||
123 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); | ||
124 | |||
125 | tty = priv->tty; | ||
126 | |||
127 | lock_kernel(); | ||
128 | old_termios = *(tty->termios); | ||
129 | cflag = tty->termios->c_cflag; | ||
130 | |||
131 | cflag &= ~CBAUD; | ||
132 | |||
133 | IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed); | ||
134 | |||
135 | switch (speed) { | ||
136 | case 1200: | ||
137 | cflag |= B1200; | ||
138 | break; | ||
139 | case 2400: | ||
140 | cflag |= B2400; | ||
141 | break; | ||
142 | case 4800: | ||
143 | cflag |= B4800; | ||
144 | break; | ||
145 | case 19200: | ||
146 | cflag |= B19200; | ||
147 | break; | ||
148 | case 38400: | ||
149 | cflag |= B38400; | ||
150 | break; | ||
151 | case 57600: | ||
152 | cflag |= B57600; | ||
153 | break; | ||
154 | case 115200: | ||
155 | cflag |= B115200; | ||
156 | break; | ||
157 | case 9600: | ||
158 | default: | ||
159 | cflag |= B9600; | ||
160 | break; | ||
161 | } | ||
162 | |||
163 | tty->termios->c_cflag = cflag; | ||
164 | if (tty->driver->set_termios) | ||
165 | tty->driver->set_termios(tty, &old_termios); | ||
166 | unlock_kernel(); | ||
167 | |||
168 | priv->io.speed = speed; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Function irtty_set_dtr_rts (dev, dtr, rts) | ||
175 | * | ||
176 | * This function can be used by dongles etc. to set or reset the status | ||
177 | * of the dtr and rts lines | ||
178 | */ | ||
179 | |||
180 | static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts) | ||
181 | { | ||
182 | struct sirtty_cb *priv = dev->priv; | ||
183 | int set = 0; | ||
184 | int clear = 0; | ||
185 | |||
186 | IRDA_ASSERT(priv != NULL, return -1;); | ||
187 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); | ||
188 | |||
189 | if (rts) | ||
190 | set |= TIOCM_RTS; | ||
191 | else | ||
192 | clear |= TIOCM_RTS; | ||
193 | if (dtr) | ||
194 | set |= TIOCM_DTR; | ||
195 | else | ||
196 | clear |= TIOCM_DTR; | ||
197 | |||
198 | /* | ||
199 | * We can't use ioctl() because it expects a non-null file structure, | ||
200 | * and we don't have that here. | ||
201 | * This function is not yet defined for all tty driver, so | ||
202 | * let's be careful... Jean II | ||
203 | */ | ||
204 | IRDA_ASSERT(priv->tty->driver->tiocmset != NULL, return -1;); | ||
205 | priv->tty->driver->tiocmset(priv->tty, NULL, set, clear); | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | /* ------------------------------------------------------- */ | ||
211 | |||
212 | /* called from sir_dev when there is more data to send | ||
213 | * context is either netdev->hard_xmit or some transmit-completion bh | ||
214 | * i.e. we are under spinlock here and must not sleep. | ||
215 | */ | ||
216 | |||
217 | static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t len) | ||
218 | { | ||
219 | struct sirtty_cb *priv = dev->priv; | ||
220 | struct tty_struct *tty; | ||
221 | int writelen; | ||
222 | |||
223 | IRDA_ASSERT(priv != NULL, return -1;); | ||
224 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); | ||
225 | |||
226 | tty = priv->tty; | ||
227 | if (!tty->driver->write) | ||
228 | return 0; | ||
229 | tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); | ||
230 | if (tty->driver->write_room) { | ||
231 | writelen = tty->driver->write_room(tty); | ||
232 | if (writelen > len) | ||
233 | writelen = len; | ||
234 | } | ||
235 | else | ||
236 | writelen = len; | ||
237 | return tty->driver->write(tty, ptr, writelen); | ||
238 | } | ||
239 | |||
240 | /* ------------------------------------------------------- */ | ||
241 | |||
242 | /* irda line discipline callbacks */ | ||
243 | |||
244 | /* | ||
245 | * Function irtty_receive_buf( tty, cp, count) | ||
246 | * | ||
247 | * Handle the 'receiver data ready' interrupt. This function is called | ||
248 | * by the 'tty_io' module in the kernel when a block of IrDA data has | ||
249 | * been received, which can now be decapsulated and delivered for | ||
250 | * further processing | ||
251 | * | ||
252 | * calling context depends on underlying driver and tty->low_latency! | ||
253 | * for example (low_latency: 1 / 0): | ||
254 | * serial.c: uart-interrupt / softint | ||
255 | * usbserial: urb-complete-interrupt / softint | ||
256 | */ | ||
257 | |||
258 | static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | ||
259 | char *fp, int count) | ||
260 | { | ||
261 | struct sir_dev *dev; | ||
262 | struct sirtty_cb *priv = tty->disc_data; | ||
263 | int i; | ||
264 | |||
265 | IRDA_ASSERT(priv != NULL, return;); | ||
266 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); | ||
267 | |||
268 | if (unlikely(count==0)) /* yes, this happens */ | ||
269 | return; | ||
270 | |||
271 | dev = priv->dev; | ||
272 | if (!dev) { | ||
273 | IRDA_WARNING("%s(), not ready yet!\n", __FUNCTION__); | ||
274 | return; | ||
275 | } | ||
276 | |||
277 | for (i = 0; i < count; i++) { | ||
278 | /* | ||
279 | * Characters received with a parity error, etc? | ||
280 | */ | ||
281 | if (fp && *fp++) { | ||
282 | IRDA_DEBUG(0, "Framing or parity error!\n"); | ||
283 | sirdev_receive(dev, NULL, 0); /* notify sir_dev (updating stats) */ | ||
284 | return; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | sirdev_receive(dev, cp, count); | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Function irtty_receive_room (tty) | ||
293 | * | ||
294 | * Used by the TTY to find out how much data we can receive at a time | ||
295 | * | ||
296 | */ | ||
297 | static int irtty_receive_room(struct tty_struct *tty) | ||
298 | { | ||
299 | struct sirtty_cb *priv = tty->disc_data; | ||
300 | |||
301 | IRDA_ASSERT(priv != NULL, return 0;); | ||
302 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return 0;); | ||
303 | |||
304 | return 65536; /* We can handle an infinite amount of data. :-) */ | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Function irtty_write_wakeup (tty) | ||
309 | * | ||
310 | * Called by the driver when there's room for more data. If we have | ||
311 | * more packets to send, we send them here. | ||
312 | * | ||
313 | */ | ||
314 | static void irtty_write_wakeup(struct tty_struct *tty) | ||
315 | { | ||
316 | struct sirtty_cb *priv = tty->disc_data; | ||
317 | |||
318 | IRDA_ASSERT(priv != NULL, return;); | ||
319 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); | ||
320 | |||
321 | tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); | ||
322 | |||
323 | if (priv->dev) | ||
324 | sirdev_write_complete(priv->dev); | ||
325 | } | ||
326 | |||
327 | /* ------------------------------------------------------- */ | ||
328 | |||
329 | /* | ||
330 | * Function irtty_stop_receiver (tty, stop) | ||
331 | * | ||
332 | */ | ||
333 | |||
334 | static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) | ||
335 | { | ||
336 | struct termios old_termios; | ||
337 | int cflag; | ||
338 | |||
339 | lock_kernel(); | ||
340 | old_termios = *(tty->termios); | ||
341 | cflag = tty->termios->c_cflag; | ||
342 | |||
343 | if (stop) | ||
344 | cflag &= ~CREAD; | ||
345 | else | ||
346 | cflag |= CREAD; | ||
347 | |||
348 | tty->termios->c_cflag = cflag; | ||
349 | if (tty->driver->set_termios) | ||
350 | tty->driver->set_termios(tty, &old_termios); | ||
351 | unlock_kernel(); | ||
352 | } | ||
353 | |||
354 | /*****************************************************************/ | ||
355 | |||
356 | /* serialize ldisc open/close with sir_dev */ | ||
357 | static DECLARE_MUTEX(irtty_sem); | ||
358 | |||
359 | /* notifier from sir_dev when irda% device gets opened (ifup) */ | ||
360 | |||
361 | static int irtty_start_dev(struct sir_dev *dev) | ||
362 | { | ||
363 | struct sirtty_cb *priv; | ||
364 | struct tty_struct *tty; | ||
365 | |||
366 | /* serialize with ldisc open/close */ | ||
367 | down(&irtty_sem); | ||
368 | |||
369 | priv = dev->priv; | ||
370 | if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { | ||
371 | up(&irtty_sem); | ||
372 | return -ESTALE; | ||
373 | } | ||
374 | |||
375 | tty = priv->tty; | ||
376 | |||
377 | if (tty->driver->start) | ||
378 | tty->driver->start(tty); | ||
379 | /* Make sure we can receive more data */ | ||
380 | irtty_stop_receiver(tty, FALSE); | ||
381 | |||
382 | up(&irtty_sem); | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | /* notifier from sir_dev when irda% device gets closed (ifdown) */ | ||
387 | |||
388 | static int irtty_stop_dev(struct sir_dev *dev) | ||
389 | { | ||
390 | struct sirtty_cb *priv; | ||
391 | struct tty_struct *tty; | ||
392 | |||
393 | /* serialize with ldisc open/close */ | ||
394 | down(&irtty_sem); | ||
395 | |||
396 | priv = dev->priv; | ||
397 | if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { | ||
398 | up(&irtty_sem); | ||
399 | return -ESTALE; | ||
400 | } | ||
401 | |||
402 | tty = priv->tty; | ||
403 | |||
404 | /* Make sure we don't receive more data */ | ||
405 | irtty_stop_receiver(tty, TRUE); | ||
406 | if (tty->driver->stop) | ||
407 | tty->driver->stop(tty); | ||
408 | |||
409 | up(&irtty_sem); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | /* ------------------------------------------------------- */ | ||
415 | |||
416 | static struct sir_driver sir_tty_drv = { | ||
417 | .owner = THIS_MODULE, | ||
418 | .driver_name = "sir_tty", | ||
419 | .start_dev = irtty_start_dev, | ||
420 | .stop_dev = irtty_stop_dev, | ||
421 | .do_write = irtty_do_write, | ||
422 | .chars_in_buffer = irtty_chars_in_buffer, | ||
423 | .wait_until_sent = irtty_wait_until_sent, | ||
424 | .set_speed = irtty_change_speed, | ||
425 | .set_dtr_rts = irtty_set_dtr_rts, | ||
426 | }; | ||
427 | |||
428 | /* ------------------------------------------------------- */ | ||
429 | |||
430 | /* | ||
431 | * Function irtty_ioctl (tty, file, cmd, arg) | ||
432 | * | ||
433 | * The Swiss army knife of system calls :-) | ||
434 | * | ||
435 | */ | ||
436 | static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) | ||
437 | { | ||
438 | struct irtty_info { char name[6]; } info; | ||
439 | struct sir_dev *dev; | ||
440 | struct sirtty_cb *priv = tty->disc_data; | ||
441 | int err = 0; | ||
442 | |||
443 | IRDA_ASSERT(priv != NULL, return -ENODEV;); | ||
444 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -EBADR;); | ||
445 | |||
446 | IRDA_DEBUG(3, "%s(cmd=0x%X)\n", __FUNCTION__, cmd); | ||
447 | |||
448 | dev = priv->dev; | ||
449 | IRDA_ASSERT(dev != NULL, return -1;); | ||
450 | |||
451 | switch (cmd) { | ||
452 | case TCGETS: | ||
453 | case TCGETA: | ||
454 | err = n_tty_ioctl(tty, file, cmd, arg); | ||
455 | break; | ||
456 | |||
457 | case IRTTY_IOCTDONGLE: | ||
458 | /* this call blocks for completion */ | ||
459 | err = sirdev_set_dongle(dev, (IRDA_DONGLE) arg); | ||
460 | break; | ||
461 | |||
462 | case IRTTY_IOCGET: | ||
463 | IRDA_ASSERT(dev->netdev != NULL, return -1;); | ||
464 | |||
465 | memset(&info, 0, sizeof(info)); | ||
466 | strncpy(info.name, dev->netdev->name, sizeof(info.name)-1); | ||
467 | |||
468 | if (copy_to_user((void __user *)arg, &info, sizeof(info))) | ||
469 | err = -EFAULT; | ||
470 | break; | ||
471 | default: | ||
472 | err = -ENOIOCTLCMD; | ||
473 | break; | ||
474 | } | ||
475 | return err; | ||
476 | } | ||
477 | |||
478 | |||
479 | /* | ||
480 | * Function irtty_open(tty) | ||
481 | * | ||
482 | * This function is called by the TTY module when the IrDA line | ||
483 | * discipline is called for. Because we are sure the tty line exists, | ||
484 | * we only have to link it to a free IrDA channel. | ||
485 | */ | ||
486 | static int irtty_open(struct tty_struct *tty) | ||
487 | { | ||
488 | struct sir_dev *dev; | ||
489 | struct sirtty_cb *priv; | ||
490 | int ret = 0; | ||
491 | |||
492 | /* Module stuff handled via irda_ldisc.owner - Jean II */ | ||
493 | |||
494 | /* First make sure we're not already connected. */ | ||
495 | if (tty->disc_data != NULL) { | ||
496 | priv = tty->disc_data; | ||
497 | if (priv && priv->magic == IRTTY_MAGIC) { | ||
498 | ret = -EEXIST; | ||
499 | goto out; | ||
500 | } | ||
501 | tty->disc_data = NULL; /* ### */ | ||
502 | } | ||
503 | |||
504 | /* stop the underlying driver */ | ||
505 | irtty_stop_receiver(tty, TRUE); | ||
506 | if (tty->driver->stop) | ||
507 | tty->driver->stop(tty); | ||
508 | |||
509 | if (tty->driver->flush_buffer) | ||
510 | tty->driver->flush_buffer(tty); | ||
511 | |||
512 | /* apply mtt override */ | ||
513 | sir_tty_drv.qos_mtt_bits = qos_mtt_bits; | ||
514 | |||
515 | /* get a sir device instance for this driver */ | ||
516 | dev = sirdev_get_instance(&sir_tty_drv, tty->name); | ||
517 | if (!dev) { | ||
518 | ret = -ENODEV; | ||
519 | goto out; | ||
520 | } | ||
521 | |||
522 | /* allocate private device info block */ | ||
523 | priv = kmalloc(sizeof(*priv), GFP_KERNEL); | ||
524 | if (!priv) | ||
525 | goto out_put; | ||
526 | memset(priv, 0, sizeof(*priv)); | ||
527 | |||
528 | priv->magic = IRTTY_MAGIC; | ||
529 | priv->tty = tty; | ||
530 | priv->dev = dev; | ||
531 | |||
532 | /* serialize with start_dev - in case we were racing with ifup */ | ||
533 | down(&irtty_sem); | ||
534 | |||
535 | dev->priv = priv; | ||
536 | tty->disc_data = priv; | ||
537 | |||
538 | up(&irtty_sem); | ||
539 | |||
540 | IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name); | ||
541 | |||
542 | return 0; | ||
543 | |||
544 | out_put: | ||
545 | sirdev_put_instance(dev); | ||
546 | out: | ||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | /* | ||
551 | * Function irtty_close (tty) | ||
552 | * | ||
553 | * Close down a IrDA channel. This means flushing out any pending queues, | ||
554 | * and then restoring the TTY line discipline to what it was before it got | ||
555 | * hooked to IrDA (which usually is TTY again). | ||
556 | */ | ||
557 | static void irtty_close(struct tty_struct *tty) | ||
558 | { | ||
559 | struct sirtty_cb *priv = tty->disc_data; | ||
560 | |||
561 | IRDA_ASSERT(priv != NULL, return;); | ||
562 | IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); | ||
563 | |||
564 | /* Hm, with a dongle attached the dongle driver wants | ||
565 | * to close the dongle - which requires the use of | ||
566 | * some tty write and/or termios or ioctl operations. | ||
567 | * Are we allowed to call those when already requested | ||
568 | * to shutdown the ldisc? | ||
569 | * If not, we should somehow mark the dev being staled. | ||
570 | * Question remains, how to close the dongle in this case... | ||
571 | * For now let's assume we are granted to issue tty driver calls | ||
572 | * until we return here from the ldisc close. I'm just wondering | ||
573 | * how this behaves with hotpluggable serial hardware like | ||
574 | * rs232-pcmcia card or usb-serial... | ||
575 | * | ||
576 | * priv->tty = NULL?; | ||
577 | */ | ||
578 | |||
579 | /* we are dead now */ | ||
580 | tty->disc_data = NULL; | ||
581 | |||
582 | sirdev_put_instance(priv->dev); | ||
583 | |||
584 | /* Stop tty */ | ||
585 | irtty_stop_receiver(tty, TRUE); | ||
586 | tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); | ||
587 | if (tty->driver->stop) | ||
588 | tty->driver->stop(tty); | ||
589 | |||
590 | kfree(priv); | ||
591 | |||
592 | IRDA_DEBUG(0, "%s - %s: irda line discipline closed\n", __FUNCTION__, tty->name); | ||
593 | } | ||
594 | |||
595 | /* ------------------------------------------------------- */ | ||
596 | |||
597 | static struct tty_ldisc irda_ldisc = { | ||
598 | .magic = TTY_LDISC_MAGIC, | ||
599 | .name = "irda", | ||
600 | .flags = 0, | ||
601 | .open = irtty_open, | ||
602 | .close = irtty_close, | ||
603 | .read = NULL, | ||
604 | .write = NULL, | ||
605 | .ioctl = irtty_ioctl, | ||
606 | .poll = NULL, | ||
607 | .receive_buf = irtty_receive_buf, | ||
608 | .receive_room = irtty_receive_room, | ||
609 | .write_wakeup = irtty_write_wakeup, | ||
610 | .owner = THIS_MODULE, | ||
611 | }; | ||
612 | |||
613 | /* ------------------------------------------------------- */ | ||
614 | |||
615 | static int __init irtty_sir_init(void) | ||
616 | { | ||
617 | int err; | ||
618 | |||
619 | if ((err = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0) | ||
620 | IRDA_ERROR("IrDA: can't register line discipline (err = %d)\n", | ||
621 | err); | ||
622 | return err; | ||
623 | } | ||
624 | |||
625 | static void __exit irtty_sir_cleanup(void) | ||
626 | { | ||
627 | int err; | ||
628 | |||
629 | if ((err = tty_register_ldisc(N_IRDA, NULL))) { | ||
630 | IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n", | ||
631 | __FUNCTION__, err); | ||
632 | } | ||
633 | } | ||
634 | |||
635 | module_init(irtty_sir_init); | ||
636 | module_exit(irtty_sir_cleanup); | ||
637 | |||
638 | MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); | ||
639 | MODULE_DESCRIPTION("IrDA TTY device driver"); | ||
640 | MODULE_ALIAS_LDISC(N_IRDA); | ||
641 | MODULE_LICENSE("GPL"); | ||
642 | |||