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

📄 tty.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* ---- DLC callbacks ---- */static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb){	struct rfcomm_dev *dev = dlc->owner;	struct tty_struct *tty;       	if (!dev || !(tty = dev->tty)) {		kfree_skb(skb);		return;	}	BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {		register int i;		for (i = 0; i < skb->len; i++) {			if (tty->flip.count >= TTY_FLIPBUF_SIZE)				tty_flip_buffer_push(tty);			tty_insert_flip_char(tty, skb->data[i], 0);		}		tty_flip_buffer_push(tty);	} else		tty->ldisc.receive_buf(tty, skb->data, NULL, skb->len);	kfree_skb(skb);}static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err){	struct rfcomm_dev *dev = dlc->owner;	if (!dev)		return;		BT_DBG("dlc %p dev %p err %d", dlc, dev, err);	dev->err = err;	wake_up_interruptible(&dev->wait);	if (dlc->state == BT_CLOSED) {		if (!dev->tty) {			if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {				rfcomm_dev_hold(dev);				rfcomm_dev_del(dev);				/* We have to drop DLC lock here, otherwise				   rfcomm_dev_put() will dead lock if it's				   the last reference. */				rfcomm_dlc_unlock(dlc);				rfcomm_dev_put(dev);				rfcomm_dlc_lock(dlc);			}		} else 			tty_hangup(dev->tty);	}}static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig){	struct rfcomm_dev *dev = dlc->owner;	if (!dev)		return;		BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig);	dev->modem_status = 		((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) |		((v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0) |		((v24_sig & RFCOMM_V24_IC)  ? TIOCM_RI : 0) |		((v24_sig & RFCOMM_V24_DV)  ? TIOCM_CD : 0);}/* ---- TTY functions ---- */static void rfcomm_tty_wakeup(unsigned long arg){	struct rfcomm_dev *dev = (void *) arg;	struct tty_struct *tty = dev->tty;	if (!tty)		return;	BT_DBG("dev %p tty %p", dev, tty);	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)                (tty->ldisc.write_wakeup)(tty);	wake_up_interruptible(&tty->write_wait);#ifdef SERIAL_HAVE_POLL_WAIT	wake_up_interruptible(&tty->poll_wait);#endif}static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp){	DECLARE_WAITQUEUE(wait, current);	struct rfcomm_dev *dev;	struct rfcomm_dlc *dlc;	int err, id;        id = tty->index;	BT_DBG("tty %p id %d", tty, id);	/* We don't leak this refcount. For reasons which are not entirely	   clear, the TTY layer will call our ->close() method even if the	   open fails. We decrease the refcount there, and decreasing it	   here too would cause breakage. */	dev = rfcomm_dev_get(id);	if (!dev)		return -ENODEV;	BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), dev->channel, dev->opened);	if (dev->opened++ != 0)		return 0;	dlc = dev->dlc;	/* Attach TTY and open DLC */	rfcomm_dlc_lock(dlc);	tty->driver_data = dev;	dev->tty = tty;	rfcomm_dlc_unlock(dlc);	set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);	err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);	if (err < 0)		return err;	/* Wait for DLC to connect */	add_wait_queue(&dev->wait, &wait);	while (1) {		set_current_state(TASK_INTERRUPTIBLE);		if (dlc->state == BT_CLOSED) {			err = -dev->err;			break;		}		if (dlc->state == BT_CONNECTED)			break;		if (signal_pending(current)) {			err = -EINTR;			break;		}		schedule();	}	set_current_state(TASK_RUNNING);	remove_wait_queue(&dev->wait, &wait);	return err;}static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	if (!dev)		return;	BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);	if (--dev->opened == 0) {		/* Close DLC and dettach TTY */		rfcomm_dlc_close(dev->dlc, 0);		clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);		tasklet_kill(&dev->wakeup_task);		rfcomm_dlc_lock(dev->dlc);		tty->driver_data = NULL;		dev->tty = NULL;		rfcomm_dlc_unlock(dev->dlc);	}	rfcomm_dev_put(dev);}static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	struct rfcomm_dlc *dlc = dev->dlc;	struct sk_buff *skb;	int err = 0, sent = 0, size;	BT_DBG("tty %p count %d", tty, count);	while (count) {		size = min_t(uint, count, dlc->mtu);		skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC);				if (!skb)			break;		skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);		memcpy(skb_put(skb, size), buf + sent, size);		if ((err = rfcomm_dlc_send(dlc, skb)) < 0) {			kfree_skb(skb);			break;		}		sent  += size;		count -= size;	}	return sent ? sent : err;}static int rfcomm_tty_write_room(struct tty_struct *tty){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	int room;	BT_DBG("tty %p", tty);	room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc);	if (room < 0)		room = 0;	return room;}static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg){	BT_DBG("tty %p cmd 0x%02x", tty, cmd);	switch (cmd) {	case TCGETS:		BT_DBG("TCGETS is not supported");		return -ENOIOCTLCMD;	case TCSETS:		BT_DBG("TCSETS is not supported");		return -ENOIOCTLCMD;	case TIOCMIWAIT:		BT_DBG("TIOCMIWAIT");		break;	case TIOCGICOUNT:		BT_DBG("TIOCGICOUNT");		break;	case TIOCGSERIAL:		BT_ERR("TIOCGSERIAL is not supported");		return -ENOIOCTLCMD;	case TIOCSSERIAL:		BT_ERR("TIOCSSERIAL is not supported");		return -ENOIOCTLCMD;	case TIOCSERGSTRUCT:		BT_ERR("TIOCSERGSTRUCT is not supported");		return -ENOIOCTLCMD;	case TIOCSERGETLSR:		BT_ERR("TIOCSERGETLSR is not supported");		return -ENOIOCTLCMD;	case TIOCSERCONFIG:		BT_ERR("TIOCSERCONFIG is not supported");		return -ENOIOCTLCMD;	default:		return -ENOIOCTLCMD;	/* ioctls which we must ignore */	}	return -ENOIOCTLCMD;}#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old){	BT_DBG("tty %p", tty);	if ((tty->termios->c_cflag == old->c_cflag) &&		(RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old->c_iflag)))		return;	/* handle turning off CRTSCTS */	if ((old->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {		BT_DBG("turning off CRTSCTS");	}}static void rfcomm_tty_throttle(struct tty_struct *tty){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	BT_DBG("tty %p dev %p", tty, dev);		rfcomm_dlc_throttle(dev->dlc);}static void rfcomm_tty_unthrottle(struct tty_struct *tty){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	BT_DBG("tty %p dev %p", tty, dev);		rfcomm_dlc_unthrottle(dev->dlc);}static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	struct rfcomm_dlc *dlc = dev->dlc;	BT_DBG("tty %p dev %p", tty, dev);	if (skb_queue_len(&dlc->tx_queue))		return dlc->mtu;	return 0;}static void rfcomm_tty_flush_buffer(struct tty_struct *tty){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	if (!dev)		return;	BT_DBG("tty %p dev %p", tty, dev);	skb_queue_purge(&dev->dlc->tx_queue);	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)		tty->ldisc.write_wakeup(tty);}static void rfcomm_tty_send_xchar(struct tty_struct *tty, char ch){	BT_DBG("tty %p ch %c", tty, ch);}static void rfcomm_tty_wait_until_sent(struct tty_struct *tty, int timeout){	BT_DBG("tty %p timeout %d", tty, timeout);}static void rfcomm_tty_hangup(struct tty_struct *tty){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	if (!dev)		return;	BT_DBG("tty %p dev %p", tty, dev);	rfcomm_tty_flush_buffer(tty);	if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))		rfcomm_dev_del(dev);}static int rfcomm_tty_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *unused){	return 0;}static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp){ 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	BT_DBG("tty %p dev %p", tty, dev); 	return dev->modem_status;}static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear){ 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; 	struct rfcomm_dlc *dlc = dev->dlc; 	u8 v24_sig;	BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear); 	rfcomm_dlc_get_modem_status(dlc, &v24_sig); 	if (set & TIOCM_DSR || set & TIOCM_DTR) 		v24_sig |= RFCOMM_V24_RTC; 	if (set & TIOCM_RTS || set & TIOCM_CTS) 		v24_sig |= RFCOMM_V24_RTR; 	if (set & TIOCM_RI) 		v24_sig |= RFCOMM_V24_IC; 	if (set & TIOCM_CD) 		v24_sig |= RFCOMM_V24_DV; 	if (clear & TIOCM_DSR || clear & TIOCM_DTR) 		v24_sig &= ~RFCOMM_V24_RTC; 	if (clear & TIOCM_RTS || clear & TIOCM_CTS) 		v24_sig &= ~RFCOMM_V24_RTR; 	if (clear & TIOCM_RI) 		v24_sig &= ~RFCOMM_V24_IC; 	if (clear & TIOCM_CD) 		v24_sig &= ~RFCOMM_V24_DV; 	rfcomm_dlc_set_modem_status(dlc, v24_sig); 	return 0;}/* ---- TTY structure ---- */static struct tty_operations rfcomm_ops = {	.open			= rfcomm_tty_open,	.close			= rfcomm_tty_close,	.write			= rfcomm_tty_write,	.write_room		= rfcomm_tty_write_room,	.chars_in_buffer	= rfcomm_tty_chars_in_buffer,	.flush_buffer		= rfcomm_tty_flush_buffer,	.ioctl			= rfcomm_tty_ioctl,	.throttle		= rfcomm_tty_throttle,	.unthrottle		= rfcomm_tty_unthrottle,	.set_termios		= rfcomm_tty_set_termios,	.send_xchar		= rfcomm_tty_send_xchar,	.hangup			= rfcomm_tty_hangup,	.wait_until_sent	= rfcomm_tty_wait_until_sent,	.read_proc		= rfcomm_tty_read_proc,	.tiocmget		= rfcomm_tty_tiocmget,	.tiocmset		= rfcomm_tty_tiocmset,};int rfcomm_init_ttys(void){	rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);	if (!rfcomm_tty_driver)		return -1;	rfcomm_tty_driver->owner	= THIS_MODULE;	rfcomm_tty_driver->driver_name	= "rfcomm";	rfcomm_tty_driver->devfs_name	= "bluetooth/rfcomm/";	rfcomm_tty_driver->name		= "rfcomm";	rfcomm_tty_driver->major	= RFCOMM_TTY_MAJOR;	rfcomm_tty_driver->minor_start	= RFCOMM_TTY_MINOR;	rfcomm_tty_driver->type		= TTY_DRIVER_TYPE_SERIAL;	rfcomm_tty_driver->subtype	= SERIAL_TYPE_NORMAL;	rfcomm_tty_driver->flags	= TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;	rfcomm_tty_driver->init_termios	= tty_std_termios;	rfcomm_tty_driver->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL | CLOCAL;	tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);	if (tty_register_driver(rfcomm_tty_driver)) {		BT_ERR("Can't register RFCOMM TTY driver");		put_tty_driver(rfcomm_tty_driver);		return -1;	}	BT_INFO("RFCOMM TTY layer initialized");	return 0;}void rfcomm_cleanup_ttys(void){	tty_unregister_driver(rfcomm_tty_driver);	put_tty_driver(rfcomm_tty_driver);}

⌨️ 快捷键说明

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