aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Hartkopp <socketcan@hartkopp.net>2010-12-02 05:57:59 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-08 12:03:32 -0500
commita1044e36e457fb6dbdf90ce756d578b251d99b5e (patch)
tree8a121841aa13d7e873fa761623a79a96016aa142
parent58e481f66e31e9976558f3e4f709baf9201052fe (diff)
can: add slcan driver for serial/USB-serial CAN adapters
This patch adds support for serial/USB-serial CAN adapters implementing the LAWICEL ASCII protocol for CAN frame transport over serial lines. The driver implements the SLCAN line discipline and is heavily based on the slip.c driver. Therefore the code style remains similar to slip.c to be able to apply changes of the SLIP driver to the SLCAN driver easily. For more details see the slcan Kconfig entry. Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/can/Kconfig21
-rw-r--r--drivers/net/can/Makefile1
-rw-r--r--drivers/net/can/slcan.c755
3 files changed, 777 insertions, 0 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 080574b0fff..d5a9db60ade 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -12,6 +12,27 @@ config CAN_VCAN
12 This driver can also be built as a module. If so, the module 12 This driver can also be built as a module. If so, the module
13 will be called vcan. 13 will be called vcan.
14 14
15config CAN_SLCAN
16 tristate "Serial / USB serial CAN Adaptors (slcan)"
17 depends on CAN
18 default N
19 ---help---
20 CAN driver for several 'low cost' CAN interfaces that are attached
21 via serial lines or via USB-to-serial adapters using the LAWICEL
22 ASCII protocol. The driver implements the tty linediscipline N_SLCAN.
23
24 As only the sending and receiving of CAN frames is implemented, this
25 driver should work with the (serial/USB) CAN hardware from:
26 www.canusb.com / www.can232.com / www.mictronic.com / www.canhack.de
27
28 Userspace tools to attach the SLCAN line discipline (slcan_attach,
29 slcand) can be found in the can-utils at the SocketCAN SVN, see
30 http://developer.berlios.de/projects/socketcan for details.
31
32 The slcan driver supports up to 10 CAN netdevices by default which
33 can be changed by the 'maxdev=xx' module option. This driver can
34 also be built as a module. If so, the module will be called slcan.
35
15config CAN_DEV 36config CAN_DEV
16 tristate "Platform CAN drivers with Netlink support" 37 tristate "Platform CAN drivers with Netlink support"
17 depends on CAN 38 depends on CAN
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 90af15a4f10..07ca159ba3f 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -3,6 +3,7 @@
3# 3#
4 4
5obj-$(CONFIG_CAN_VCAN) += vcan.o 5obj-$(CONFIG_CAN_VCAN) += vcan.o
6obj-$(CONFIG_CAN_SLCAN) += slcan.o
6 7
7obj-$(CONFIG_CAN_DEV) += can-dev.o 8obj-$(CONFIG_CAN_DEV) += can-dev.o
8can-dev-y := dev.o 9can-dev-y := dev.o
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
new file mode 100644
index 00000000000..420e95ecc19
--- /dev/null
+++ b/drivers/net/can/slcan.c
@@ -0,0 +1,755 @@
1/*
2 * slcan.c - serial line CAN interface driver (using tty line discipline)
3 *
4 * This file is derived from linux/drivers/net/slip.c
5 *
6 * slip.c Authors : Laurence Culhane <loz@holmes.demon.co.uk>
7 * Fred N. van Kempen <waltje@uwalt.nl.mugnet.org>
8 * slcan.c Author : Oliver Hartkopp <socketcan@hartkopp.net>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307. You can also get it
23 * at http://www.gnu.org/licenses/gpl.html
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
36 * DAMAGE.
37 *
38 * Send feedback to <socketcan-users@lists.berlios.de>
39 *
40 */
41
42#include <linux/module.h>
43#include <linux/moduleparam.h>
44
45#include <asm/system.h>
46#include <linux/uaccess.h>
47#include <linux/bitops.h>
48#include <linux/string.h>
49#include <linux/tty.h>
50#include <linux/errno.h>
51#include <linux/netdevice.h>
52#include <linux/skbuff.h>
53#include <linux/rtnetlink.h>
54#include <linux/if_arp.h>
55#include <linux/if_ether.h>
56#include <linux/delay.h>
57#include <linux/init.h>
58#include <linux/can.h>
59
60static __initdata const char banner[] =
61 KERN_INFO "slcan: serial line CAN interface driver\n";
62
63MODULE_ALIAS_LDISC(N_SLCAN);
64MODULE_DESCRIPTION("serial line CAN interface");
65MODULE_LICENSE("GPL");
66MODULE_AUTHOR("Oliver Hartkopp <socketcan@hartkopp.net>");
67
68#define SLCAN_MAGIC 0x53CA
69
70static int maxdev = 10; /* MAX number of SLCAN channels;
71 This can be overridden with
72 insmod slcan.ko maxdev=nnn */
73module_param(maxdev, int, 0);
74MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
75
76/* maximum rx buffer len: extended CAN frame with timestamp */
77#define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1)
78
79struct slcan {
80 int magic;
81
82 /* Various fields. */
83 struct tty_struct *tty; /* ptr to TTY structure */
84 struct net_device *dev; /* easy for intr handling */
85 spinlock_t lock;
86
87 /* These are pointers to the malloc()ed frame buffers. */
88 unsigned char rbuff[SLC_MTU]; /* receiver buffer */
89 int rcount; /* received chars counter */
90 unsigned char xbuff[SLC_MTU]; /* transmitter buffer */
91 unsigned char *xhead; /* pointer to next XMIT byte */
92 int xleft; /* bytes left in XMIT queue */
93
94 unsigned long flags; /* Flag values/ mode etc */
95#define SLF_INUSE 0 /* Channel in use */
96#define SLF_ERROR 1 /* Parity, etc. error */
97
98 unsigned char leased;
99 dev_t line;
100 pid_t pid;
101};
102
103static struct net_device **slcan_devs;
104
105 /************************************************************************
106 * SLCAN ENCAPSULATION FORMAT *
107 ************************************************************************/
108
109/*
110 * A CAN frame has a can_id (11 bit standard frame format OR 29 bit extended
111 * frame format) a data length code (can_dlc) which can be from 0 to 8
112 * and up to <can_dlc> data bytes as payload.
113 * Additionally a CAN frame may become a remote transmission frame if the
114 * RTR-bit is set. This causes another ECU to send a CAN frame with the
115 * given can_id.
116 *
117 * The SLCAN ASCII representation of these different frame types is:
118 * <type> <id> <dlc> <data>*
119 *
120 * Extended frames (29 bit) are defined by capital characters in the type.
121 * RTR frames are defined as 'r' types - normal frames have 't' type:
122 * t => 11 bit data frame
123 * r => 11 bit RTR frame
124 * T => 29 bit data frame
125 * R => 29 bit RTR frame
126 *
127 * The <id> is 3 (standard) or 8 (extended) bytes in ASCII Hex (base64).
128 * The <dlc> is a one byte ASCII number ('0' - '8')
129 * The <data> section has at much ASCII Hex bytes as defined by the <dlc>
130 *
131 * Examples:
132 *
133 * t1230 : can_id 0x123, can_dlc 0, no data
134 * t4563112233 : can_id 0x456, can_dlc 3, data 0x11 0x22 0x33
135 * T12ABCDEF2AA55 : extended can_id 0x12ABCDEF, can_dlc 2, data 0xAA 0x55
136 * r1230 : can_id 0x123, can_dlc 0, no data, remote transmission request
137 *
138 */
139
140 /************************************************************************
141 * STANDARD SLCAN DECAPSULATION *
142 ************************************************************************/
143
144static int asc2nibble(char c)
145{
146
147 if ((c >= '0') && (c <= '9'))
148 return c - '0';
149
150 if ((c >= 'A') && (c <= 'F'))
151 return c - 'A' + 10;
152
153 if ((c >= 'a') && (c <= 'f'))
154 return c - 'a' + 10;
155
156 return 16; /* error */
157}
158
159/* Send one completely decapsulated can_frame to the network layer */
160static void slc_bump(struct slcan *sl)
161{
162 struct sk_buff *skb;
163 struct can_frame cf;
164 int i, dlc_pos, tmp;
165 unsigned long ultmp;
166 char cmd = sl->rbuff[0];
167
168 if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R'))
169 return;
170
171 if (cmd & 0x20) /* tiny chars 'r' 't' => standard frame format */
172 dlc_pos = 4; /* dlc position tiiid */
173 else
174 dlc_pos = 9; /* dlc position Tiiiiiiiid */
175
176 if (!((sl->rbuff[dlc_pos] >= '0') && (sl->rbuff[dlc_pos] < '9')))
177 return;
178
179 cf.can_dlc = sl->rbuff[dlc_pos] - '0'; /* get can_dlc from ASCII val */
180
181 sl->rbuff[dlc_pos] = 0; /* terminate can_id string */
182
183 if (strict_strtoul(sl->rbuff+1, 16, &ultmp))
184 return;
185
186 cf.can_id = ultmp;
187
188 if (!(cmd & 0x20)) /* NO tiny chars => extended frame format */
189 cf.can_id |= CAN_EFF_FLAG;
190
191 if ((cmd | 0x20) == 'r') /* RTR frame */
192 cf.can_id |= CAN_RTR_FLAG;
193
194 *(u64 *) (&cf.data) = 0; /* clear payload */
195
196 for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
197
198 tmp = asc2nibble(sl->rbuff[dlc_pos++]);
199 if (tmp > 0x0F)
200 return;
201 cf.data[i] = (tmp << 4);
202 tmp = asc2nibble(sl->rbuff[dlc_pos++]);
203 if (tmp > 0x0F)
204 return;
205 cf.data[i] |= tmp;
206 }
207
208
209 skb = dev_alloc_skb(sizeof(struct can_frame));
210 if (!skb)
211 return;
212
213 skb->dev = sl->dev;
214 skb->protocol = htons(ETH_P_CAN);
215 skb->pkt_type = PACKET_BROADCAST;
216 skb->ip_summed = CHECKSUM_UNNECESSARY;
217 memcpy(skb_put(skb, sizeof(struct can_frame)),
218 &cf, sizeof(struct can_frame));
219 netif_rx(skb);
220
221 sl->dev->stats.rx_packets++;
222 sl->dev->stats.rx_bytes += cf.can_dlc;
223}
224
225/* parse tty input stream */
226static void slcan_unesc(struct slcan *sl, unsigned char s)
227{
228
229 if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */
230 if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
231 (sl->rcount > 4)) {
232 slc_bump(sl);
233 }
234 sl->rcount = 0;
235 } else {
236 if (!test_bit(SLF_ERROR, &sl->flags)) {
237 if (sl->rcount < SLC_MTU) {
238 sl->rbuff[sl->rcount++] = s;
239 return;
240 } else {
241 sl->dev->stats.rx_over_errors++;
242 set_bit(SLF_ERROR, &sl->flags);
243 }
244 }
245 }
246}
247
248 /************************************************************************
249 * STANDARD SLCAN ENCAPSULATION *
250 ************************************************************************/
251
252/* Encapsulate one can_frame and stuff into a TTY queue. */
253static void slc_encaps(struct slcan *sl, struct can_frame *cf)
254{
255 int actual, idx, i;
256 char cmd;
257
258 if (cf->can_id & CAN_RTR_FLAG)
259 cmd = 'R'; /* becomes 'r' in standard frame format */
260 else
261 cmd = 'T'; /* becomes 't' in standard frame format */
262
263 if (cf->can_id & CAN_EFF_FLAG)
264 sprintf(sl->xbuff, "%c%08X%d", cmd,
265 cf->can_id & CAN_EFF_MASK, cf->can_dlc);
266 else
267 sprintf(sl->xbuff, "%c%03X%d", cmd | 0x20,
268 cf->can_id & CAN_SFF_MASK, cf->can_dlc);
269
270 idx = strlen(sl->xbuff);
271
272 for (i = 0; i < cf->can_dlc; i++)
273 sprintf(&sl->xbuff[idx + 2*i], "%02X", cf->data[i]);
274
275 strcat(sl->xbuff, "\r"); /* add terminating character */
276
277 /* Order of next two lines is *very* important.
278 * When we are sending a little amount of data,
279 * the transfer may be completed inside the ops->write()
280 * routine, because it's running with interrupts enabled.
281 * In this case we *never* got WRITE_WAKEUP event,
282 * if we did not request it before write operation.
283 * 14 Oct 1994 Dmitry Gorodchanin.
284 */
285 set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
286 actual = sl->tty->ops->write(sl->tty, sl->xbuff, strlen(sl->xbuff));
287 sl->xleft = strlen(sl->xbuff) - actual;
288 sl->xhead = sl->xbuff + actual;
289 sl->dev->stats.tx_bytes += cf->can_dlc;
290}
291
292/*
293 * Called by the driver when there's room for more data. If we have
294 * more packets to send, we send them here.
295 */
296static void slcan_write_wakeup(struct tty_struct *tty)
297{
298 int actual;
299 struct slcan *sl = (struct slcan *) tty->disc_data;
300
301 /* First make sure we're connected. */
302 if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
303 return;
304
305 if (sl->xleft <= 0) {
306 /* Now serial buffer is almost free & we can start
307 * transmission of another packet */
308 sl->dev->stats.tx_packets++;
309 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
310 netif_wake_queue(sl->dev);
311 return;
312 }
313
314 actual = tty->ops->write(tty, sl->xhead, sl->xleft);
315 sl->xleft -= actual;
316 sl->xhead += actual;
317}
318
319/* Send a can_frame to a TTY queue. */
320static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev)
321{
322 struct slcan *sl = netdev_priv(dev);
323
324 if (skb->len != sizeof(struct can_frame))
325 goto out;
326
327 spin_lock(&sl->lock);
328 if (!netif_running(dev)) {
329 spin_unlock(&sl->lock);
330 printk(KERN_WARNING "%s: xmit: iface is down\n", dev->name);
331 goto out;
332 }
333 if (sl->tty == NULL) {
334 spin_unlock(&sl->lock);
335 goto out;
336 }
337
338 netif_stop_queue(sl->dev);
339 slc_encaps(sl, (struct can_frame *) skb->data); /* encaps & send */
340 spin_unlock(&sl->lock);
341
342out:
343 kfree_skb(skb);
344 return NETDEV_TX_OK;
345}
346
347
348/******************************************
349 * Routines looking at netdevice side.
350 ******************************************/
351
352/* Netdevice UP -> DOWN routine */
353static int slc_close(struct net_device *dev)
354{
355 struct slcan *sl = netdev_priv(dev);
356
357 spin_lock_bh(&sl->lock);
358 if (sl->tty) {
359 /* TTY discipline is running. */
360 clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
361 }
362 netif_stop_queue(dev);
363 sl->rcount = 0;
364 sl->xleft = 0;
365 spin_unlock_bh(&sl->lock);
366
367 return 0;
368}
369
370/* Netdevice DOWN -> UP routine */
371static int slc_open(struct net_device *dev)
372{
373 struct slcan *sl = netdev_priv(dev);
374
375 if (sl->tty == NULL)
376 return -ENODEV;
377
378 sl->flags &= (1 << SLF_INUSE);
379 netif_start_queue(dev);
380 return 0;
381}
382
383/* Hook the destructor so we can free slcan devs at the right point in time */
384static void slc_free_netdev(struct net_device *dev)
385{
386 int i = dev->base_addr;
387 free_netdev(dev);
388 slcan_devs[i] = NULL;
389}
390
391static const struct net_device_ops slc_netdev_ops = {
392 .ndo_open = slc_open,
393 .ndo_stop = slc_close,
394 .ndo_start_xmit = slc_xmit,
395};
396
397static void slc_setup(struct net_device *dev)
398{
399 dev->netdev_ops = &slc_netdev_ops;
400 dev->destructor = slc_free_netdev;
401
402 dev->hard_header_len = 0;
403 dev->addr_len = 0;
404 dev->tx_queue_len = 10;
405
406 dev->mtu = sizeof(struct can_frame);
407 dev->type = ARPHRD_CAN;
408
409 /* New-style flags. */
410 dev->flags = IFF_NOARP;
411 dev->features = NETIF_F_NO_CSUM;
412}
413
414/******************************************
415 Routines looking at TTY side.
416 ******************************************/
417
418/*
419 * Handle the 'receiver data ready' interrupt.
420 * This function is called by the 'tty_io' module in the kernel when
421 * a block of SLCAN data has been received, which can now be decapsulated
422 * and sent on to some IP layer for further processing. This will not
423 * be re-entered while running but other ldisc functions may be called
424 * in parallel
425 */
426
427static void slcan_receive_buf(struct tty_struct *tty,
428 const unsigned char *cp, char *fp, int count)
429{
430 struct slcan *sl = (struct slcan *) tty->disc_data;
431
432 if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
433 return;
434
435 /* Read the characters out of the buffer */
436 while (count--) {
437 if (fp && *fp++) {
438 if (!test_and_set_bit(SLF_ERROR, &sl->flags))
439 sl->dev->stats.rx_errors++;
440 cp++;
441 continue;
442 }
443 slcan_unesc(sl, *cp++);
444 }
445}
446
447/************************************
448 * slcan_open helper routines.
449 ************************************/
450
451/* Collect hanged up channels */
452static void slc_sync(void)
453{
454 int i;
455 struct net_device *dev;
456 struct slcan *sl;
457
458 for (i = 0; i < maxdev; i++) {
459 dev = slcan_devs[i];
460 if (dev == NULL)
461 break;
462
463 sl = netdev_priv(dev);
464 if (sl->tty || sl->leased)
465 continue;
466 if (dev->flags & IFF_UP)
467 dev_close(dev);
468 }
469}
470
471/* Find a free SLCAN channel, and link in this `tty' line. */
472static struct slcan *slc_alloc(dev_t line)
473{
474 int i;
475 struct net_device *dev = NULL;
476 struct slcan *sl;
477
478 if (slcan_devs == NULL)
479 return NULL; /* Master array missing ! */
480
481 for (i = 0; i < maxdev; i++) {
482 dev = slcan_devs[i];
483 if (dev == NULL)
484 break;
485
486 }
487
488 /* Sorry, too many, all slots in use */
489 if (i >= maxdev)
490 return NULL;
491
492 if (dev) {
493 sl = netdev_priv(dev);
494 if (test_bit(SLF_INUSE, &sl->flags)) {
495 unregister_netdevice(dev);
496 dev = NULL;
497 slcan_devs[i] = NULL;
498 }
499 }
500
501 if (!dev) {
502 char name[IFNAMSIZ];
503 sprintf(name, "slcan%d", i);
504
505 dev = alloc_netdev(sizeof(*sl), name, slc_setup);
506 if (!dev)
507 return NULL;
508 dev->base_addr = i;
509 }
510
511 sl = netdev_priv(dev);
512
513 /* Initialize channel control data */
514 sl->magic = SLCAN_MAGIC;
515 sl->dev = dev;
516 spin_lock_init(&sl->lock);
517 slcan_devs[i] = dev;
518
519 return sl;
520}
521
522/*
523 * Open the high-level part of the SLCAN channel.
524 * This function is called by the TTY module when the
525 * SLCAN line discipline is called for. Because we are
526 * sure the tty line exists, we only have to link it to
527 * a free SLCAN channel...
528 *
529 * Called in process context serialized from other ldisc calls.
530 */
531
532static int slcan_open(struct tty_struct *tty)
533{
534 struct slcan *sl;
535 int err;
536
537 if (!capable(CAP_NET_ADMIN))
538 return -EPERM;
539
540 if (tty->ops->write == NULL)
541 return -EOPNOTSUPP;
542
543 /* RTnetlink lock is misused here to serialize concurrent
544 opens of slcan channels. There are better ways, but it is
545 the simplest one.
546 */
547 rtnl_lock();
548
549 /* Collect hanged up channels. */
550 slc_sync();
551
552 sl = tty->disc_data;
553
554 err = -EEXIST;
555 /* First make sure we're not already connected. */
556 if (sl && sl->magic == SLCAN_MAGIC)
557 goto err_exit;
558
559 /* OK. Find a free SLCAN channel to use. */
560 err = -ENFILE;
561 sl = slc_alloc(tty_devnum(tty));
562 if (sl == NULL)
563 goto err_exit;
564
565 sl->tty = tty;
566 tty->disc_data = sl;
567 sl->line = tty_devnum(tty);
568 sl->pid = current->pid;
569
570 if (!test_bit(SLF_INUSE, &sl->flags)) {
571 /* Perform the low-level SLCAN initialization. */
572 sl->rcount = 0;
573 sl->xleft = 0;
574
575 set_bit(SLF_INUSE, &sl->flags);
576
577 err = register_netdevice(sl->dev);
578 if (err)
579 goto err_free_chan;
580 }
581
582 /* Done. We have linked the TTY line to a channel. */
583 rtnl_unlock();
584 tty->receive_room = 65536; /* We don't flow control */
585 return sl->dev->base_addr;
586
587err_free_chan:
588 sl->tty = NULL;
589 tty->disc_data = NULL;
590 clear_bit(SLF_INUSE, &sl->flags);
591
592err_exit:
593 rtnl_unlock();
594
595 /* Count references from TTY module */
596 return err;
597}
598
599/*
600 * Close down a SLCAN channel.
601 * This means flushing out any pending queues, and then returning. This
602 * call is serialized against other ldisc functions.
603 *
604 * We also use this method for a hangup event.
605 */
606
607static void slcan_close(struct tty_struct *tty)
608{
609 struct slcan *sl = (struct slcan *) tty->disc_data;
610
611 /* First make sure we're connected. */
612 if (!sl || sl->magic != SLCAN_MAGIC || sl->tty != tty)
613 return;
614
615 tty->disc_data = NULL;
616 sl->tty = NULL;
617 if (!sl->leased)
618 sl->line = 0;
619
620 /* Flush network side */
621 unregister_netdev(sl->dev);
622 /* This will complete via sl_free_netdev */
623}
624
625static int slcan_hangup(struct tty_struct *tty)
626{
627 slcan_close(tty);
628 return 0;
629}
630
631/* Perform I/O control on an active SLCAN channel. */
632static int slcan_ioctl(struct tty_struct *tty, struct file *file,
633 unsigned int cmd, unsigned long arg)
634{
635 struct slcan *sl = (struct slcan *) tty->disc_data;
636 unsigned int tmp;
637
638 /* First make sure we're connected. */
639 if (!sl || sl->magic != SLCAN_MAGIC)
640 return -EINVAL;
641
642 switch (cmd) {
643 case SIOCGIFNAME:
644 tmp = strlen(sl->dev->name) + 1;
645 if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
646 return -EFAULT;
647 return 0;
648
649 case SIOCSIFHWADDR:
650 return -EINVAL;
651
652 default:
653 return tty_mode_ioctl(tty, file, cmd, arg);
654 }
655}
656
657static struct tty_ldisc_ops slc_ldisc = {
658 .owner = THIS_MODULE,
659 .magic = TTY_LDISC_MAGIC,
660 .name = "slcan",
661 .open = slcan_open,
662 .close = slcan_close,
663 .hangup = slcan_hangup,
664 .ioctl = slcan_ioctl,
665 .receive_buf = slcan_receive_buf,
666 .write_wakeup = slcan_write_wakeup,
667};
668
669static int __init slcan_init(void)
670{
671 int status;
672
673 if (maxdev < 4)
674 maxdev = 4; /* Sanity */
675
676 printk(banner);
677 printk(KERN_INFO "slcan: %d dynamic interface channels.\n", maxdev);
678
679 slcan_devs = kzalloc(sizeof(struct net_device *)*maxdev, GFP_KERNEL);
680 if (!slcan_devs) {
681 printk(KERN_ERR "slcan: can't allocate slcan device array!\n");
682 return -ENOMEM;
683 }
684
685 /* Fill in our line protocol discipline, and register it */
686 status = tty_register_ldisc(N_SLCAN, &slc_ldisc);
687 if (status) {
688 printk(KERN_ERR "slcan: can't register line discipline\n");
689 kfree(slcan_devs);
690 }
691 return status;
692}
693
694static void __exit slcan_exit(void)
695{
696 int i;
697 struct net_device *dev;
698 struct slcan *sl;
699 unsigned long timeout = jiffies + HZ;
700 int busy = 0;
701
702 if (slcan_devs == NULL)
703 return;
704
705 /* First of all: check for active disciplines and hangup them.
706 */
707 do {
708 if (busy)
709 msleep_interruptible(100);
710
711 busy = 0;
712 for (i = 0; i < maxdev; i++) {
713 dev = slcan_devs[i];
714 if (!dev)
715 continue;
716 sl = netdev_priv(dev);
717 spin_lock_bh(&sl->lock);
718 if (sl->tty) {
719 busy++;
720 tty_hangup(sl->tty);
721 }
722 spin_unlock_bh(&sl->lock);
723 }
724 } while (busy && time_before(jiffies, timeout));
725
726 /* FIXME: hangup is async so we should wait when doing this second
727 phase */
728
729 for (i = 0; i < maxdev; i++) {
730 dev = slcan_devs[i];
731 if (!dev)
732 continue;
733 slcan_devs[i] = NULL;
734
735 sl = netdev_priv(dev);
736 if (sl->tty) {
737 printk(KERN_ERR "%s: tty discipline still running\n",
738 dev->name);
739 /* Intentionally leak the control block. */
740 dev->destructor = NULL;
741 }
742
743 unregister_netdev(dev);
744 }
745
746 kfree(slcan_devs);
747 slcan_devs = NULL;
748
749 i = tty_unregister_ldisc(N_SLCAN);
750 if (i)
751 printk(KERN_ERR "slcan: can't unregister ldisc (err %d)\n", i);
752}
753
754module_init(slcan_init);
755module_exit(slcan_exit);