static int slcan_open(struct tty_struct *tty) { struct slcan *sl; int err; if (!capable(CAP_NET_ADMIN)) return -EPERM; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) if (tty->ops->write == NULL) return -EOPNOTSUPP; #endif /* RTnetlink lock is misused here to serialize concurrent opens of slcan channels. There are better ways, but it is the simplest one. */ rtnl_lock(); /* Collect hanged up channels. */ slc_sync(); sl = (struct slcan *) tty->disc_data; err = -EEXIST; /* First make sure we're not already connected. */ if (sl && sl->magic == SLCAN_MAGIC) goto err_exit; /* OK. Find a free SLCAN channel to use. */ err = -ENFILE; /* Look to see if the user has requested a specific channel * to be used (encoded as '0' plus the interface number requested in * the otherwise unused swtch termios variable ) * stty swtch 'channel' device * where 'channel' is '0' to maxdevs (0) * where device is the name of the serial device (/dev/ttyUSB0) */ if ((SWTC_CHAR(tty)>='0') && (SWTC_CHAR(tty)<'0'+maxdev)){ sl = slc_alloc(tty_devnum(tty),SWTC_CHAR(tty)); } else { /* OK. Find a free SLCAN channel to use. */ sl = slc_alloc(tty_devnum(tty),0); } if (sl == NULL) goto err_exit; sl->tty = tty; tty->disc_data = sl; sl->line = tty_devnum(tty); sl->pid = current->pid; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) /* FIXME: already done before we were called - seems this can go */ if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); #endif if (!test_bit(SLF_INUSE, &sl->flags)) { /* Perform the low-level SLCAN initialization. */ sl->rcount = 0; sl->xleft = 0; set_bit(SLF_INUSE, &sl->flags); err = register_netdevice(sl->dev); if (err) goto err_free_chan; } /* Done. We have linked the TTY line to a channel. */ rtnl_unlock(); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) tty->receive_room = 65536; /* We don't flow control */ #endif return sl->dev->base_addr; err_free_chan: sl->tty = NULL; tty->disc_data = NULL; clear_bit(SLF_INUSE, &sl->flags); err_exit: rtnl_unlock(); /* Count references from TTY module */ return err; }
static int slcan_open(struct tty_struct *tty) { struct slcan *sl; int err; if (!capable(CAP_NET_ADMIN)) return -EPERM; if (tty->ops->write == NULL) return -EOPNOTSUPP; /* RTnetlink lock is misused here to serialize concurrent opens of slcan channels. There are better ways, but it is the simplest one. */ rtnl_lock(); /* Collect hanged up channels. */ slc_sync(); sl = tty->disc_data; err = -EEXIST; /* First make sure we're not already connected. */ if (sl && sl->magic == SLCAN_MAGIC) goto err_exit; /* OK. Find a free SLCAN channel to use. */ err = -ENFILE; sl = slc_alloc(tty_devnum(tty)); if (sl == NULL) goto err_exit; sl->tty = tty; tty->disc_data = sl; sl->line = tty_devnum(tty); sl->pid = current->pid; if (!test_bit(SLF_INUSE, &sl->flags)) { /* Perform the low-level SLCAN initialization. */ sl->rcount = 0; sl->xleft = 0; set_bit(SLF_INUSE, &sl->flags); err = register_netdevice(sl->dev); if (err) goto err_free_chan; } /* Done. We have linked the TTY line to a channel. */ rtnl_unlock(); tty->receive_room = 65536; /* We don't flow control */ /* TTY layer expects 0 on success */ return 0; err_free_chan: sl->tty = NULL; tty->disc_data = NULL; clear_bit(SLF_INUSE, &sl->flags); err_exit: rtnl_unlock(); /* Count references from TTY module */ return err; }