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

📄 ircomm_tty.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (self->tx_skb)		len = self->tx_skb->len;	restore_flags(flags);	return len;}static void ircomm_tty_shutdown(struct ircomm_tty_cb *self){	unsigned long flags;	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	IRDA_DEBUG(0, __FUNCTION__ "()\n");		if (!(self->flags & ASYNC_INITIALIZED))		return;	save_flags(flags);	cli();	del_timer(&self->watchdog_timer);		/* Free parameter buffer */	if (self->ctrl_skb) {		dev_kfree_skb(self->ctrl_skb);		self->ctrl_skb = NULL;	}	/* Free transmit buffer */	if (self->tx_skb) {		dev_kfree_skb(self->tx_skb);		self->tx_skb = NULL;	}	ircomm_tty_detach_cable(self);	if (self->ircomm) {		ircomm_close(self->ircomm);		self->ircomm = NULL;	}	self->flags &= ~ASYNC_INITIALIZED;	restore_flags(flags);}/* * Function ircomm_tty_hangup (tty) * *    This routine notifies the tty driver that it should hangup the tty *    device. *  */static void ircomm_tty_hangup(struct tty_struct *tty){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	IRDA_DEBUG(0, __FUNCTION__"()\n");	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	if (!tty)		return;	/* ircomm_tty_flush_buffer(tty); */	ircomm_tty_shutdown(self);	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);	self->tty = 0;	self->open_count = 0;	wake_up_interruptible(&self->open_wait);}/* * Function ircomm_tty_send_xchar (tty, ch) * *    This routine is used to send a high-priority XON/XOFF character to *    the device. */static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch){	IRDA_DEBUG(0, __FUNCTION__"(), not impl\n");}/* * Function ircomm_tty_start (tty) * *    This routine notifies the tty driver that it resume sending *    characters to the tty device.   */void ircomm_tty_start(struct tty_struct *tty){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	ircomm_flow_request(self->ircomm, FLOW_START);}/* * Function ircomm_tty_stop (tty) * *     This routine notifies the tty driver that it should stop outputting *     characters to the tty device.  */void ircomm_tty_stop(struct tty_struct *tty) {	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	ircomm_flow_request(self->ircomm, FLOW_STOP);}/* * Function ircomm_check_modem_status (self) * *    Check for any changes in the DCE's line settings. This function should *    be called whenever the dce parameter settings changes, to update the *    flow control settings and other things */void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self){	struct tty_struct *tty;	int status;	IRDA_DEBUG(0, __FUNCTION__ "()\n");	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	tty = self->tty;	status = self->settings.dce;	if (status & IRCOMM_DCE_DELTA_ANY) {		/*wake_up_interruptible(&self->delta_msr_wait);*/	}	if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {		IRDA_DEBUG(2, __FUNCTION__ 			   "(), ircomm%d CD now %s...\n", self->line,			   (status & IRCOMM_CD) ? "on" : "off");		if (status & IRCOMM_CD) {			wake_up_interruptible(&self->open_wait);		} else if (!((self->flags & ASYNC_CALLOUT_ACTIVE) &&			   (self->flags & ASYNC_CALLOUT_NOHUP))) 		{			IRDA_DEBUG(2, __FUNCTION__ 				   "(), Doing serial hangup..\n");			if (tty)				tty_hangup(tty);			/* Hangup will remote the tty, so better break out */			return;		}	}	if (self->flags & ASYNC_CTS_FLOW) {		if (tty->hw_stopped) {			if (status & IRCOMM_CTS) {				IRDA_DEBUG(2, __FUNCTION__ 					   "(), CTS tx start...\n");				tty->hw_stopped = 0;								/* Wake up processes blocked on open */				wake_up_interruptible(&self->open_wait);				queue_task(&self->tqueue, &tq_immediate);				mark_bh(IMMEDIATE_BH);				return;			}		} else {			if (!(status & IRCOMM_CTS)) {				IRDA_DEBUG(2, __FUNCTION__ 					   "(), CTS tx stop...\n");				tty->hw_stopped = 1;			}		}	}}/* * Function ircomm_tty_data_indication (instance, sap, skb) * *    Handle incomming data, and deliver it to the line discipline * */static int ircomm_tty_data_indication(void *instance, void *sap,				      struct sk_buff *skb){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;	IRDA_DEBUG(2, __FUNCTION__"()\n");		ASSERT(self != NULL, return -1;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);	ASSERT(skb != NULL, return -1;);	if (!self->tty) {		IRDA_DEBUG(0, __FUNCTION__ "(), no tty!\n");		dev_kfree_skb(skb);		return 0;	}	/* 	 * If we receive data when hardware is stopped then something is wrong.	 * We try to poll the peers line settings to check if we are up todate.	 * Devices like WinCE can do this, and since they don't send any 	 * params, we can just as well declare the hardware for running.	 */	if (self->tty->hw_stopped && (self->flow == FLOW_START)) {		IRDA_DEBUG(0, __FUNCTION__ "(), polling for line settings!\n");		ircomm_param_request(self, IRCOMM_POLL, TRUE);		/* We can just as well declare the hardware for running */		ircomm_tty_send_initial_parameters(self);		ircomm_tty_link_established(self);	}	/* 	 * Just give it over to the line discipline. There is no need to	 * involve the flip buffers, since we are not running in an interrupt 	 * handler	 */	self->tty->ldisc.receive_buf(self->tty, skb->data, NULL, skb->len);	dev_kfree_skb(skb);	return 0;}/* * Function ircomm_tty_control_indication (instance, sap, skb) * *    Parse all incomming parameters (easy!) * */static int ircomm_tty_control_indication(void *instance, void *sap,					 struct sk_buff *skb){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;	int clen;	IRDA_DEBUG(4, __FUNCTION__"()\n");		ASSERT(self != NULL, return -1;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);	ASSERT(skb != NULL, return -1;);	clen = skb->data[0];	irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen), 			       &ircomm_param_info);	dev_kfree_skb(skb);	return 0;}/* * Function ircomm_tty_flow_indication (instance, sap, cmd) * *    This function is called by IrTTP when it wants us to slow down the *    transmission of data. We just mark the hardware as stopped, and wait *    for IrTTP to notify us that things are OK again. */static void ircomm_tty_flow_indication(void *instance, void *sap, 				       LOCAL_FLOW cmd){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;	struct tty_struct *tty;	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	tty = self->tty;	switch (cmd) {	case FLOW_START:		IRDA_DEBUG(2, __FUNCTION__ "(), hw start!\n");		tty->hw_stopped = 0;		/* ircomm_tty_do_softint will take care of the rest */		queue_task(&self->tqueue, &tq_immediate);		mark_bh(IMMEDIATE_BH);		break;	default:  /* If we get here, something is very wrong, better stop */	case FLOW_STOP:		IRDA_DEBUG(2, __FUNCTION__ "(), hw stopped!\n");		tty->hw_stopped = 1;		break;	}	self->flow = cmd;}static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf){        int  ret=0;	ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]);	ret += sprintf(buf+ret, "Service type: ");	if (self->service_type & IRCOMM_9_WIRE)		ret += sprintf(buf+ret, "9_WIRE");	else if (self->service_type & IRCOMM_3_WIRE)		ret += sprintf(buf+ret, "3_WIRE");	else if (self->service_type & IRCOMM_3_WIRE_RAW)		ret += sprintf(buf+ret, "3_WIRE_RAW");	else		ret += sprintf(buf+ret, "No common service type!\n");        ret += sprintf(buf+ret, "\n");	ret += sprintf(buf+ret, "Port name: %s\n", self->settings.port_name);	ret += sprintf(buf+ret, "DTE status: ");	        if (self->settings.dte & IRCOMM_RTS)                ret += sprintf(buf+ret, "RTS|");        if (self->settings.dte & IRCOMM_DTR)                ret += sprintf(buf+ret, "DTR|");	if (self->settings.dte)		ret--; /* remove the last | */        ret += sprintf(buf+ret, "\n");	ret += sprintf(buf+ret, "DCE status: ");        if (self->settings.dce & IRCOMM_CTS)                ret += sprintf(buf+ret, "CTS|");        if (self->settings.dce & IRCOMM_DSR)                ret += sprintf(buf+ret, "DSR|");        if (self->settings.dce & IRCOMM_CD)                ret += sprintf(buf+ret, "CD|");        if (self->settings.dce & IRCOMM_RI)                 ret += sprintf(buf+ret, "RI|");	if (self->settings.dce)		ret--; /* remove the last | */        ret += sprintf(buf+ret, "\n");	ret += sprintf(buf+ret, "Configuration: ");	if (!self->settings.null_modem)		ret += sprintf(buf+ret, "DTE <-> DCE\n");	else		ret += sprintf(buf+ret, 			       "DTE <-> DTE (null modem emulation)\n");	ret += sprintf(buf+ret, "Data rate: %d\n", self->settings.data_rate);	ret += sprintf(buf+ret, "Flow control: ");	if (self->settings.flow_control & IRCOMM_XON_XOFF_IN)		ret += sprintf(buf+ret, "XON_XOFF_IN|");	if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT)		ret += sprintf(buf+ret, "XON_XOFF_OUT|");	if (self->settings.flow_control & IRCOMM_RTS_CTS_IN)		ret += sprintf(buf+ret, "RTS_CTS_IN|");	if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT)		ret += sprintf(buf+ret, "RTS_CTS_OUT|");	if (self->settings.flow_control & IRCOMM_DSR_DTR_IN)		ret += sprintf(buf+ret, "DSR_DTR_IN|");	if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT)		ret += sprintf(buf+ret, "DSR_DTR_OUT|");	if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN)		ret += sprintf(buf+ret, "ENQ_ACK_IN|");	if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT)		ret += sprintf(buf+ret, "ENQ_ACK_OUT|");	if (self->settings.flow_control)		ret--; /* remove the last | */        ret += sprintf(buf+ret, "\n");	ret += sprintf(buf+ret, "Flags: ");	if (self->flags & ASYNC_CTS_FLOW)		ret += sprintf(buf+ret, "ASYNC_CTS_FLOW|");	if (self->flags & ASYNC_CHECK_CD)		ret += sprintf(buf+ret, "ASYNC_CHECK_CD|");	if (self->flags & ASYNC_INITIALIZED)		ret += sprintf(buf+ret, "ASYNC_INITIALIZED|");	if (self->flags & ASYNC_LOW_LATENCY)		ret += sprintf(buf+ret, "ASYNC_LOW_LATENCY|");	if (self->flags & ASYNC_CLOSING)		ret += sprintf(buf+ret, "ASYNC_CLOSING|");	if (self->flags & ASYNC_NORMAL_ACTIVE)		ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|");	if (self->flags & ASYNC_CALLOUT_ACTIVE)		ret += sprintf(buf+ret, "ASYNC_CALLOUT_ACTIVE|");	if (self->flags)		ret--; /* remove the last | */	ret += sprintf(buf+ret, "\n");	ret += sprintf(buf+ret, "Role: %s\n", self->client ? 		       "client" : "server");	ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);	ret += sprintf(buf+ret, "Max data size: %d\n", self->max_data_size);	ret += sprintf(buf+ret, "Max header size: %d\n", self->max_header_size);			if (self->tty)		ret += sprintf(buf+ret, "Hardware: %s\n", 			       self->tty->hw_stopped ? "Stopped" : "Running");        ret += sprintf(buf+ret, "\n");        return ret;}/* * Function ircomm_tty_read_proc (buf, start, offset, len, eof, unused) * *     * */#ifdef CONFIG_PROC_FSstatic int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,				int *eof, void *unused){	struct ircomm_tty_cb *self;        int count = 0, l;        off_t begin = 0;	self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);	while ((self != NULL) && (count < 4000)) {		if (self->magic != IRCOMM_TTY_MAGIC)			return 0;                l = ircomm_tty_line_info(self, buf + count);                count += l;                if (count+begin > offset+len)                        goto done;                if (count+begin < offset) {                        begin += count;                        count = 0;                }						self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);        }        *eof = 1;done:        if (offset >= count+begin)                return 0;        *start = buf + (offset-begin);        return ((len < begin+count-offset) ? len : begin+count-offset);}#endif /* CONFIG_PROC_FS */#ifdef MODULEMODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");MODULE_DESCRIPTION("IrCOMM serial TTY driver");int init_module(void) {	return ircomm_tty_init();}void cleanup_module(void){	ircomm_tty_cleanup();}#endif /* MODULE */

⌨️ 快捷键说明

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