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

📄 tty.c

📁 基于liunx的蓝牙协议栈源代码版本為2.13,可以方便的下載和移植!
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 refference */				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 = MINOR(tty->device) - tty->driver.minor_start;	BT_DBG("tty %p id %d", tty, id);	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, int from_user, 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 from_user %d count %d", tty, from_user, count);	while (count) {		size = min_t(uint, count, dlc->mtu);		if (from_user)			skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, 0, GFP_KERNEL);		else			skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, 0, GFP_ATOMIC);				if (!skb)			break;		skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);		if (from_user)			copy_from_user(skb_put(skb, size), buf + sent, size);		else			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 void rfcomm_tty_put_char(struct tty_struct *tty, unsigned char ch){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	struct rfcomm_dlc *dlc = dev->dlc;	struct sk_buff *skb;	BT_DBG("tty %p char %x", tty, ch);	skb = rfcomm_wmalloc(dev, 1 + RFCOMM_SKB_RESERVE, 1, GFP_ATOMIC);	if (!skb)		return;	skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);	*(char *)skb_put(skb, 1) = ch;	if ((rfcomm_dlc_send(dlc, skb)) < 0)		kfree_skb(skb);	}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_set_modem_status(uint cmd, struct rfcomm_dlc *dlc, uint status){	u8 v24_sig, mask;	BT_DBG("dlc %p cmd 0x%02x", dlc, cmd);	if (cmd == TIOCMSET)		v24_sig = 0;	else		rfcomm_dlc_get_modem_status(dlc, &v24_sig);	mask =  ((status & TIOCM_DSR) ? RFCOMM_V24_RTC : 0) |		((status & TIOCM_DTR) ? RFCOMM_V24_RTC : 0) |		((status & TIOCM_RTS) ? RFCOMM_V24_RTR : 0) |		((status & TIOCM_CTS) ? RFCOMM_V24_RTR : 0) |		((status & TIOCM_RI)  ? RFCOMM_V24_IC  : 0) |		((status & TIOCM_CD)  ? RFCOMM_V24_DV  : 0);	if (cmd == TIOCMBIC)		v24_sig &= ~mask;	else		v24_sig |= mask;	rfcomm_dlc_set_modem_status(dlc, v24_sig);	return 0;}static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg){	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;	struct rfcomm_dlc *dlc = dev->dlc;	uint status;	int err;	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 TIOCMGET:		BT_DBG("TIOCMGET");		return put_user(dev->modem_status, (unsigned int *)arg);	case TIOCMSET: /* Turns on and off the lines as specified by the mask */	case TIOCMBIS: /* Turns on the lines as specified by the mask */	case TIOCMBIC: /* Turns off the lines as specified by the mask */		if ((err = get_user(status, (unsigned int *)arg)))			return err;		return rfcomm_tty_set_modem_status(cmd, dlc, status);	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;}/* ---- TTY structure ---- */static int    rfcomm_tty_refcount;       /* If we manage several devices */static struct tty_struct *rfcomm_tty_table[RFCOMM_TTY_PORTS];static struct termios *rfcomm_tty_termios[RFCOMM_TTY_PORTS];static struct termios *rfcomm_tty_termios_locked[RFCOMM_TTY_PORTS];static struct tty_driver rfcomm_tty_driver = {	magic:			TTY_DRIVER_MAGIC,	driver_name:		"rfcomm",#ifdef CONFIG_DEVFS_FS	name:			"bluetooth/rfcomm/%d",#else	name:			"rfcomm",#endif	major:			RFCOMM_TTY_MAJOR,	minor_start:		RFCOMM_TTY_MINOR,	num:			RFCOMM_TTY_PORTS,	type:			TTY_DRIVER_TYPE_SERIAL,	subtype:		SERIAL_TYPE_NORMAL,	flags:			TTY_DRIVER_REAL_RAW,	refcount:		&rfcomm_tty_refcount,	table:			rfcomm_tty_table,	termios:		rfcomm_tty_termios,	termios_locked:		rfcomm_tty_termios_locked,	open:			rfcomm_tty_open,	close:			rfcomm_tty_close,	put_char:		rfcomm_tty_put_char,	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,	stop:			NULL,	start:			NULL,	hangup:			rfcomm_tty_hangup,	wait_until_sent:	rfcomm_tty_wait_until_sent,	read_proc:		rfcomm_tty_read_proc,};int rfcomm_init_ttys(void){	int i;	/* Initalize our global data */	for (i = 0; i < RFCOMM_TTY_PORTS; i++)		rfcomm_tty_table[i] = NULL;	/* Register the TTY driver */	rfcomm_tty_driver.init_termios = tty_std_termios;	rfcomm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	rfcomm_tty_driver.flags = TTY_DRIVER_REAL_RAW;	if (tty_register_driver(&rfcomm_tty_driver)) {		BT_ERR("Can't register RFCOMM TTY driver");		return -1;	}	return 0;}void rfcomm_cleanup_ttys(void){	tty_unregister_driver(&rfcomm_tty_driver);	return;}

⌨️ 快捷键说明

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