⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slip.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
}static void slip_unesc(struct slip *sl, unsigned char s){	switch(s) {	 case END:#ifdef CONFIG_SLIP_SMART		/* drop keeptest bit = VSV */		if (test_bit(SLF_KEEPTEST, &sl->flags))			clear_bit(SLF_KEEPTEST, &sl->flags);#endif		if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  {			sl_bump(sl);		}		clear_bit(SLF_ESCAPE, &sl->flags);		sl->rcount = 0;		return;	 case ESC:		set_bit(SLF_ESCAPE, &sl->flags);		return;	 case ESC_ESC:		if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))  {			s = ESC;		}		break;	 case ESC_END:		if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))  {			s = END;		}		break;	}	if (!test_bit(SLF_ERROR, &sl->flags))  {		if (sl->rcount < sl->buffsize)  {			sl->rbuff[sl->rcount++] = s;			return;		}		sl->rx_over_errors++;		set_bit(SLF_ERROR, &sl->flags);	}}#ifdef CONFIG_SLIP_MODE_SLIP6/************************************************************************ *			 6 BIT SLIP ENCAPSULATION			* ************************************************************************/intslip_esc6(unsigned char *s, unsigned char *d, int len){	unsigned char *ptr = d;	unsigned char c;	int i;	unsigned short v = 0;	short bits = 0;	/*	 * Send an initial END character to flush out any	 * data that may have accumulated in the receiver	 * due to line noise.	 */	*ptr++ = 0x70;	/*	 * Encode the packet into printable ascii characters	 */	for (i = 0; i < len; ++i) {		v = (v << 8) | s[i];		bits += 8;		while (bits >= 6) {			bits -= 6;			c = 0x30 + ((v >> bits) & 0x3F);			*ptr++ = c;		}	}	if (bits) {		c = 0x30 + ((v << (6 - bits)) & 0x3F);		*ptr++ = c;	}	*ptr++ = 0x70;	return ptr - d;}voidslip_unesc6(struct slip *sl, unsigned char s){	unsigned char c;	if (s == 0x70) {#ifdef CONFIG_SLIP_SMART		/* drop keeptest bit = VSV */		if (test_bit(SLF_KEEPTEST, &sl->flags))			clear_bit(SLF_KEEPTEST, &sl->flags);#endif		if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  {			sl_bump(sl);		}		sl->rcount = 0;		sl->xbits = 0;		sl->xdata = 0; 	} else if (s >= 0x30 && s < 0x70) {		sl->xdata = (sl->xdata << 6) | ((s - 0x30) & 0x3F);		sl->xbits += 6;		if (sl->xbits >= 8) {			sl->xbits -= 8;			c = (unsigned char)(sl->xdata >> sl->xbits);			if (!test_bit(SLF_ERROR, &sl->flags))  {				if (sl->rcount < sl->buffsize)  {					sl->rbuff[sl->rcount++] = c;					return;				}				sl->rx_over_errors++;				set_bit(SLF_ERROR, &sl->flags);			}		} 	}}#endif /* CONFIG_SLIP_MODE_SLIP6 *//* Perform I/O control on an active SLIP channel. */static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg){	struct slip *sl = (struct slip *) tty->disc_data;	unsigned int tmp;	int __user *p = (int __user *)arg;	/* First make sure we're connected. */	if (!sl || sl->magic != SLIP_MAGIC) {		return -EINVAL;	}	switch(cmd) {	 case SIOCGIFNAME:		tmp = strlen(sl->dev->name) + 1;		if (copy_to_user((void __user *)arg, sl->dev->name, tmp))			return -EFAULT;		return 0;	case SIOCGIFENCAP:		if (put_user(sl->mode, p))			return -EFAULT;		return 0;	case SIOCSIFENCAP:		if (get_user(tmp, p))			return -EFAULT;#ifndef SL_INCLUDE_CSLIP		if (tmp & (SL_MODE_CSLIP|SL_MODE_ADAPTIVE))  {			return -EINVAL;		}#else		if ((tmp & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) ==		    (SL_MODE_ADAPTIVE | SL_MODE_CSLIP))  {			/* return -EINVAL; */			tmp &= ~SL_MODE_ADAPTIVE;		}#endif#ifndef CONFIG_SLIP_MODE_SLIP6		if (tmp & SL_MODE_SLIP6)  {			return -EINVAL;		}#endif		sl->mode = tmp;		sl->dev->type = ARPHRD_SLIP+sl->mode;		return 0;	 case SIOCSIFHWADDR:		return -EINVAL;#ifdef CONFIG_SLIP_SMART	/* VSV changes start here */        case SIOCSKEEPALIVE:		if (get_user(tmp, p))			return -EFAULT;                if (tmp > 255) /* max for unchar */			return -EINVAL;		spin_lock_bh(&sl->lock);		if (!sl->tty) {			spin_unlock_bh(&sl->lock);			return -ENODEV;		}		if ((sl->keepalive = (unchar) tmp) != 0) {			mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);			set_bit(SLF_KEEPTEST, &sl->flags);                } else {                        del_timer (&sl->keepalive_timer);		}		spin_unlock_bh(&sl->lock);		return 0;        case SIOCGKEEPALIVE:		if (put_user(sl->keepalive, p))			return -EFAULT;		return 0;        case SIOCSOUTFILL:		if (get_user(tmp, p))			return -EFAULT;                if (tmp > 255) /* max for unchar */			return -EINVAL;		spin_lock_bh(&sl->lock);		if (!sl->tty) {			spin_unlock_bh(&sl->lock);			return -ENODEV;		}                if ((sl->outfill = (unchar) tmp) != 0){			mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);			set_bit(SLF_OUTWAIT, &sl->flags);		} else {                        del_timer (&sl->outfill_timer);		}		spin_unlock_bh(&sl->lock);                return 0;        case SIOCGOUTFILL:		if (put_user(sl->outfill, p))			return -EFAULT;		return 0;	/* VSV changes end */#endif	/* Allow stty to read, but not set, the serial port */	case TCGETS:	case TCGETA:		return n_tty_ioctl(tty, file, cmd, arg);	default:		return -ENOIOCTLCMD;	}}/* VSV changes start here */#ifdef CONFIG_SLIP_SMART/* function do_ioctl called from net/core/dev.c   to allow get/set outfill/keepalive parameter   by ifconfig                                 */static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd){	struct slip *sl = (struct slip*)(dev->priv);	unsigned long *p = (unsigned long *)&rq->ifr_ifru;	if (sl == NULL)		/* Allocation failed ?? */		return -ENODEV;	spin_lock_bh(&sl->lock);	if (!sl->tty) {		spin_unlock_bh(&sl->lock);		return -ENODEV;	}	switch(cmd){        case SIOCSKEEPALIVE:		/* max for unchar */                if ((unsigned)*p > 255) {			spin_unlock_bh(&sl->lock);			return -EINVAL;		}		sl->keepalive = (unchar) *p;		if (sl->keepalive != 0) {			sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;			mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);			set_bit(SLF_KEEPTEST, &sl->flags);                } else {                        del_timer(&sl->keepalive_timer);		}		break;        case SIOCGKEEPALIVE:		*p = sl->keepalive;		break;        case SIOCSOUTFILL:                if ((unsigned)*p > 255) { /* max for unchar */			spin_unlock_bh(&sl->lock);			return -EINVAL;		}                if ((sl->outfill = (unchar)*p) != 0){			mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);			set_bit(SLF_OUTWAIT, &sl->flags);		} else {                        del_timer (&sl->outfill_timer);		}                break;        case SIOCGOUTFILL:		*p = sl->outfill;		break;        case SIOCSLEASE:		/* Resolve race condition, when ioctl'ing hanged up 		   and opened by another process device.		 */		if (sl->tty != current->signal->tty && sl->pid != current->pid) {			spin_unlock_bh(&sl->lock);			return -EPERM;		}		sl->leased = 0;                if (*p)			sl->leased = 1;                break;        case SIOCGLEASE:		*p = sl->leased;	};	spin_unlock_bh(&sl->lock);	return 0;}#endif/* VSV changes end */static struct tty_ldisc	sl_ldisc = {	.owner 		= THIS_MODULE,	.magic 		= TTY_LDISC_MAGIC,	.name 		= "slip",	.open 		= slip_open,	.close	 	= slip_close,	.ioctl		= slip_ioctl,	.receive_buf	= slip_receive_buf,	.receive_room	= slip_receive_room,	.write_wakeup	= slip_write_wakeup,};static int __init slip_init(void){	int status;	if (slip_maxdev < 4)		slip_maxdev = 4; /* Sanity */	printk(KERN_INFO "SLIP: version %s (dynamic channels, max=%d)"#ifdef CONFIG_SLIP_MODE_SLIP6	       " (6 bit encapsulation enabled)"#endif	       ".\n",	       SLIP_VERSION, slip_maxdev );#if defined(SL_INCLUDE_CSLIP)	printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n");#endif#ifdef CONFIG_SLIP_SMART	printk(KERN_INFO "SLIP linefill/keepalive option.\n");#endif	slip_devs = kmalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);	if (!slip_devs) {		printk(KERN_ERR "SLIP: Can't allocate slip devices array!  Uaargh! (-> No SLIP available)\n");		return -ENOMEM;	}	/* Clear the pointer array, we allocate devices when we need them */	memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev); 	/* Fill in our line protocol discipline, and register it */	if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {		printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);		kfree(slip_devs);	}	return status;}static void __exit slip_exit(void){	int i;	struct net_device *dev;	struct slip *sl;	unsigned long timeout = jiffies + HZ;	int busy = 0;	if (slip_devs == NULL) 		return;	/* First of all: check for active disciplines and hangup them.	 */	do {		if (busy) {			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(HZ / 10);		}		busy = 0;		for (i = 0; i < slip_maxdev; i++) {			dev = slip_devs[i];			if (!dev)				continue;			sl = dev->priv;			spin_lock_bh(&sl->lock);			if (sl->tty) {				busy++;				tty_hangup(sl->tty);			}			spin_unlock_bh(&sl->lock);		}	} while (busy && time_before(jiffies, timeout));	for (i = 0; i < slip_maxdev; i++) {		dev = slip_devs[i];		if (!dev)			continue;		slip_devs[i] = NULL;		sl = dev->priv;		if (sl->tty) {			printk(KERN_ERR "%s: tty discipline still running\n",			       dev->name);			/* Intentionally leak the control block. */			dev->destructor = NULL;		} 		unregister_netdev(dev);	}	kfree(slip_devs);	slip_devs = NULL;	if ((i = tty_register_ldisc(N_SLIP, NULL)))	{		printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);	}}module_init(slip_init);module_exit(slip_exit);#ifdef CONFIG_SLIP_SMART/* * This is start of the code for multislip style line checking * added by Stanislav Voronyi. All changes before marked VSV */static void sl_outfill(unsigned long sls){	struct slip *sl=(struct slip *)sls;	spin_lock(&sl->lock);	if (sl->tty == NULL)		goto out;	if(sl->outfill)	{		if( test_bit(SLF_OUTWAIT, &sl->flags) )		{			/* no packets were transmitted, do outfill */#ifdef CONFIG_SLIP_MODE_SLIP6			unsigned char s = (sl->mode & SL_MODE_SLIP6)?0x70:END;#else			unsigned char s = END;#endif			/* put END into tty queue. Is it right ??? */			if (!netif_queue_stopped(sl->dev))			{				/* if device busy no outfill */				sl->tty->driver->write(sl->tty, 0, &s, 1);			}		}		else			set_bit(SLF_OUTWAIT, &sl->flags);		mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);	}out:	spin_unlock(&sl->lock);}static void sl_keepalive(unsigned long sls){	struct slip *sl=(struct slip *)sls;	spin_lock(&sl->lock);	if (sl->tty == NULL)		goto out;	if( sl->keepalive)	{		if(test_bit(SLF_KEEPTEST, &sl->flags))		{			/* keepalive still high :(, we must hangup */			if( sl->outfill ) /* outfill timer must be deleted too */				(void)del_timer(&sl->outfill_timer);			printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);			tty_hangup(sl->tty); /* this must hangup tty & close slip */			/* I think we need not something else */			goto out;		}		else			set_bit(SLF_KEEPTEST, &sl->flags);		mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);	}out:	spin_unlock(&sl->lock);}#endifMODULE_LICENSE("GPL");MODULE_ALIAS_LDISC(N_SLIP);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -