📄 mkiss.c
字号:
{ switch (s) { case END: /* drop keeptest bit = VSV */ if (test_bit(AXF_KEEPTEST, &ax->flags)) clear_bit(AXF_KEEPTEST, &ax->flags); if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2)) ax_bump(ax); clear_bit(AXF_ESCAPE, &ax->flags); ax->rcount = 0; return; case ESC: set_bit(AXF_ESCAPE, &ax->flags); return; case ESC_ESC: if (test_and_clear_bit(AXF_ESCAPE, &ax->flags)) s = ESC; break; case ESC_END: if (test_and_clear_bit(AXF_ESCAPE, &ax->flags)) s = END; break; } if (!test_bit(AXF_ERROR, &ax->flags)) { if (ax->rcount < ax->buffsize) { ax->rbuff[ax->rcount++] = s; return; } ax->rx_over_errors++; set_bit(AXF_ERROR, &ax->flags); }}int ax_set_mac_address(struct device *dev, void *addr){ if (copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN)) return -EFAULT; return 0;}static int ax_set_dev_mac_address(struct device *dev, void *addr){ struct sockaddr *sa = addr; memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN); return 0;}/* Perform I/O control on an active ax25 channel. */static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg){ struct ax_disp *ax = (struct ax_disp *)tty->disc_data; unsigned int tmp; /* First make sure we're connected. */ if (ax == NULL || ax->magic != AX25_MAGIC) return -EINVAL; switch (cmd) { case SIOCGIFNAME: if (copy_to_user(arg, ax->dev->name, strlen(ax->dev->name) + 1)) return -EFAULT; return 0; case SIOCGIFENCAP: put_user(4, (int *)arg); return 0; case SIOCSIFENCAP: get_user(tmp, (int *)arg); ax->mode = tmp; ax->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */ ax->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3; ax->dev->type = ARPHRD_AX25; return 0; case SIOCSIFHWADDR: return ax_set_mac_address(ax->dev, arg); default: return -ENOIOCTLCMD; }}static int ax_open_dev(struct device *dev){ struct ax_disp *ax = (struct ax_disp*)dev->priv; if (ax->tty==NULL) return -ENODEV; return 0;}/* Initialize AX25 control device -- register AX25 line discipline */__initfunc(int mkiss_init_ctrl_dev(void)){ int status; if (ax25_maxdev < 4) ax25_maxdev = 4; /* Sanity */ if ((ax25_ctrls = kmalloc(sizeof(void*) * ax25_maxdev, GFP_KERNEL)) == NULL) { printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array ! No mkiss available\n"); return -ENOMEM; } /* Clear the pointer array, we allocate devices when we need them */ memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */ /* Fill in our line protocol discipline, and register it */ memset(&ax_ldisc, 0, sizeof(ax_ldisc)); ax_ldisc.magic = TTY_LDISC_MAGIC; ax_ldisc.name = "mkiss"; ax_ldisc.flags = 0; ax_ldisc.open = ax25_open; ax_ldisc.close = ax25_close; ax_ldisc.read = NULL; ax_ldisc.write = NULL; ax_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *, unsigned int, unsigned long))ax25_disp_ioctl; ax_ldisc.poll = NULL; ax_ldisc.receive_buf = ax25_receive_buf; ax_ldisc.receive_room = ax25_receive_room; ax_ldisc.write_wakeup = ax25_write_wakeup; if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0) printk(KERN_ERR "mkiss: can't register line discipline (err = %d)\n", status); mkiss_init();#ifdef MODULE return status;#else /* * Return "not found", so that dev_init() will unlink * the placeholder device entry for us. */ return ENODEV;#endif}/* Initialize the driver. Called by network startup. */static int ax25_init(struct device *dev){ struct ax_disp *ax = (struct ax_disp*)dev->priv; static char ax25_bcast[AX25_ADDR_LEN] = {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1}; static char ax25_test[AX25_ADDR_LEN] = {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1}; if (ax == NULL) /* Allocation failed ?? */ return -ENODEV; /* Set up the "AX25 Control Block". (And clear statistics) */ memset(ax, 0, sizeof (struct ax_disp)); ax->magic = AX25_MAGIC; ax->dev = dev; /* Finish setting up the DEVICE info. */ dev->mtu = AX_MTU; dev->hard_start_xmit = ax_xmit; dev->open = ax_open_dev; dev->stop = ax_close; dev->get_stats = ax_get_stats;#ifdef HAVE_SET_MAC_ADDR dev->set_mac_address = ax_set_dev_mac_address;#endif dev->hard_header_len = 0; dev->addr_len = 0; dev->type = ARPHRD_AX25; dev->tx_queue_len = 10; memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) dev->hard_header = ax_header; dev->rebuild_header = ax_rebuild_header;#endif dev_init_buffers(dev); /* New-style flags. */ dev->flags = 0; return 0;}static int mkiss_open(struct tty_struct *tty, struct file *filp){ struct mkiss_channel *mkiss; int chan; chan = MINOR(tty->device) - tty->driver.minor_start; if (chan < 0 || chan >= NR_MKISS) return -ENODEV; mkiss = &MKISS_Info[chan]; mkiss->magic = MKISS_DRIVER_MAGIC; mkiss->init = 1; mkiss->tty = tty; tty->driver_data = mkiss; tty->termios->c_iflag = IGNBRK | IGNPAR; tty->termios->c_cflag = B9600 | CS8 | CLOCAL; tty->termios->c_cflag &= ~CBAUD; return 0;}static void mkiss_close(struct tty_struct *tty, struct file * filp){ struct mkiss_channel *mkiss = tty->driver_data; if (mkiss == NULL || mkiss->magic != MKISS_DRIVER_MAGIC) return; mkiss->tty = NULL; mkiss->init = 0; tty->stopped = 0;}static int mkiss_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count){ return 0;}static int mkiss_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg){ /* Ignore serial ioctl's */ switch (cmd) { case TCSBRK: case TIOCMGET: case TIOCMBIS: case TIOCMBIC: case TIOCMSET: case TCSETS: case TCSETSF: /* should flush first, but... */ case TCSETSW: /* should wait until flush, but... */ return 0; default: return -ENOIOCTLCMD; }}static void mkiss_dummy(struct tty_struct *tty){ struct mkiss_channel *mkiss = tty->driver_data; if (tty == NULL) return; if (mkiss == NULL) return;}static void mkiss_dummy2(struct tty_struct *tty, unsigned char ch){ struct mkiss_channel *mkiss = tty->driver_data; if (tty == NULL) return; if (mkiss == NULL) return;}static int mkiss_write_room(struct tty_struct * tty){ struct mkiss_channel *mkiss = tty->driver_data; if (tty == NULL) return 0; if (mkiss == NULL) return 0; return 65536; /* We can handle an infinite amount of data. :-) */}static int mkiss_chars_in_buffer(struct tty_struct *tty){ struct mkiss_channel *mkiss = tty->driver_data; if (tty == NULL) return 0; if (mkiss == NULL) return 0; return 0;}static void mkiss_set_termios(struct tty_struct *tty, struct termios *old_termios){ /* we don't do termios */}/* ******************************************************************** *//* * Init MKISS driver * *//* ******************************************************************** */__initfunc(static int mkiss_init(void)){ memset(&mkiss_driver, 0, sizeof(struct tty_driver)); mkiss_driver.magic = MKISS_DRIVER_MAGIC; mkiss_driver.name = "mkiss"; mkiss_driver.major = MKISS_MAJOR; mkiss_driver.minor_start = 0; mkiss_driver.num = NR_MKISS; mkiss_driver.type = TTY_DRIVER_TYPE_SERIAL; mkiss_driver.subtype = MKISS_SERIAL_TYPE_NORMAL; /* not needed */ mkiss_driver.init_termios = tty_std_termios; mkiss_driver.init_termios.c_iflag = IGNBRK | IGNPAR; mkiss_driver.init_termios.c_cflag = B9600 | CS8 | CLOCAL; mkiss_driver.flags = TTY_DRIVER_REAL_RAW; mkiss_driver.refcount = &mkiss_refcount; mkiss_driver.table = mkiss_table; mkiss_driver.termios = (struct termios **)mkiss_termios; mkiss_driver.termios_locked = (struct termios **)mkiss_termios_locked; mkiss_driver.ioctl = mkiss_ioctl; mkiss_driver.open = mkiss_open; mkiss_driver.close = mkiss_close; mkiss_driver.write = mkiss_write; mkiss_driver.write_room = mkiss_write_room; mkiss_driver.chars_in_buffer = mkiss_chars_in_buffer; mkiss_driver.set_termios = mkiss_set_termios; /* some unused functions */ mkiss_driver.flush_buffer = mkiss_dummy; mkiss_driver.throttle = mkiss_dummy; mkiss_driver.unthrottle = mkiss_dummy; mkiss_driver.stop = mkiss_dummy; mkiss_driver.start = mkiss_dummy; mkiss_driver.hangup = mkiss_dummy; mkiss_driver.flush_chars = mkiss_dummy; mkiss_driver.put_char = mkiss_dummy2; if (tty_register_driver(&mkiss_driver)) { printk(KERN_ERR "mkiss: couldn't register Mkiss device\n"); return -EIO; } printk(KERN_INFO "AX.25 Multikiss device enabled\n"); return 0;}#ifdef MODULEEXPORT_NO_SYMBOLS;MODULE_PARM(ax25_maxdev, "i");MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");int init_module(void){ return mkiss_init_ctrl_dev();}void cleanup_module(void){ int i; if (ax25_ctrls != NULL) { for (i = 0; i < ax25_maxdev; i++) { if (ax25_ctrls[i]) { /* * VSV = if dev->start==0, then device * unregistred while close proc. */ if (ax25_ctrls[i]->dev.start) unregister_netdev(&(ax25_ctrls[i]->dev)); kfree(ax25_ctrls[i]); ax25_ctrls[i] = NULL; } } kfree(ax25_ctrls); ax25_ctrls = NULL; } if ((i = tty_register_ldisc(N_AX25, NULL))) printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i); if (tty_unregister_driver(&mkiss_driver)) /* remove devive */ printk(KERN_ERR "mkiss: can't unregister MKISS device\n");}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -