• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 1999 Digi International (www.digi.com)
4  *     James Puzzo <jamesp at digi dot com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
13  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  * PURPOSE.  See the GNU General Public License for more details.
15  *
16  */
17 
18 /*
19  *
20  *  Filename:
21  *
22  *     dgrp_common.c
23  *
24  *  Description:
25  *
26  *     Definitions of global variables and functions which are either
27  *     shared by the tty, mon, and net drivers; or which cross them
28  *     functionally (like the poller).
29  *
30  *  Author:
31  *
32  *     James A. Puzzo
33  *
34  */
35 
36 #include <linux/errno.h>
37 #include <linux/tty.h>
38 #include <linux/sched.h>
39 #include <linux/cred.h>
40 
41 #include "dgrp_common.h"
42 
43 /**
44  * dgrp_carrier -- check for carrier change state and act
45  * @ch: struct ch_struct *
46  */
dgrp_carrier(struct ch_struct * ch)47 void dgrp_carrier(struct ch_struct *ch)
48 {
49 	struct nd_struct *nd;
50 
51 	int virt_carrier = 0;
52 	int phys_carrier = 0;
53 
54 	/* fix case when the tty has already closed. */
55 
56 	if (!ch)
57 		return;
58 	nd  = ch->ch_nd;
59 	if (!nd)
60 		return;
61 
62 	/*
63 	 *  If we are currently waiting to determine the status of the port,
64 	 *  we don't yet know the state of the modem lines.  As a result,
65 	 *  we ignore state changes when we are waiting for the modem lines
66 	 *  to be established.  We know, as a result of code in dgrp_net_ops,
67 	 *  that we will be called again immediately following the reception
68 	 *  of the status message with the true modem status flags in it.
69 	 */
70 	if (ch->ch_expect & RR_STATUS)
71 		return;
72 
73 	/*
74 	 * If CH_HANGUP is set, we gotta keep trying to get all the processes
75 	 * that have the port open to close the port.
76 	 * So lets just keep sending a hangup every time we get here.
77 	 */
78 	if ((ch->ch_flag & CH_HANGUP) &&
79 	    (ch->ch_tun.un_open_count > 0))
80 		tty_hangup(ch->ch_tun.un_tty);
81 
82 	/*
83 	 *  Compute the effective state of both the physical and virtual
84 	 *  senses of carrier.
85 	 */
86 
87 	if (ch->ch_s_mlast & DM_CD)
88 		phys_carrier = 1;
89 
90 	if ((ch->ch_s_mlast & DM_CD) ||
91 	    (ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
92 	    (ch->ch_flag & CH_CLOCAL))
93 		virt_carrier = 1;
94 
95 	/*
96 	 *  Test for a VIRTUAL carrier transition to HIGH.
97 	 *
98 	 *  The CH_HANGUP condition is intended to prevent any action
99 	 *  except for close.  As a result, we ignore positive carrier
100 	 *  transitions during CH_HANGUP.
101 	 */
102 	if (((ch->ch_flag & CH_HANGUP)  == 0) &&
103 	    ((ch->ch_flag & CH_VIRT_CD) == 0) &&
104 	    (virt_carrier == 1)) {
105 		/*
106 		 * When carrier rises, wake any threads waiting
107 		 * for carrier in the open routine.
108 		 */
109 		nd->nd_tx_work = 1;
110 
111 		if (waitqueue_active(&ch->ch_flag_wait))
112 			wake_up_interruptible(&ch->ch_flag_wait);
113 	}
114 
115 	/*
116 	 *  Test for a PHYSICAL transition to low, so long as we aren't
117 	 *  currently ignoring physical transitions (which is what "virtual
118 	 *  carrier" indicates).
119 	 *
120 	 *  The transition of the virtual carrier to low really doesn't
121 	 *  matter... it really only means "ignore carrier state", not
122 	 *  "make pretend that carrier is there".
123 	 */
124 	if ((virt_carrier == 0) &&
125 	    ((ch->ch_flag & CH_PHYS_CD) != 0) &&
126 	    (phys_carrier == 0)) {
127 		/*
128 		 * When carrier drops:
129 		 *
130 		 *   Do a Hard Hangup if that is called for.
131 		 *
132 		 *   Drop carrier on all open units.
133 		 *
134 		 *   Flush queues, waking up any task waiting in the
135 		 *   line discipline.
136 		 *
137 		 *   Send a hangup to the control terminal.
138 		 *
139 		 *   Enable all select calls.
140 		 */
141 
142 		nd->nd_tx_work = 1;
143 
144 		ch->ch_flag &= ~(CH_LOW | CH_EMPTY | CH_DRAIN | CH_INPUT);
145 
146 		if (waitqueue_active(&ch->ch_flag_wait))
147 			wake_up_interruptible(&ch->ch_flag_wait);
148 
149 		if (ch->ch_tun.un_open_count > 0)
150 			tty_hangup(ch->ch_tun.un_tty);
151 
152 		if (ch->ch_pun.un_open_count > 0)
153 			tty_hangup(ch->ch_pun.un_tty);
154 	}
155 
156 	/*
157 	 *  Make sure that our cached values reflect the current reality.
158 	 */
159 	if (virt_carrier == 1)
160 		ch->ch_flag |= CH_VIRT_CD;
161 	else
162 		ch->ch_flag &= ~CH_VIRT_CD;
163 
164 	if (phys_carrier == 1)
165 		ch->ch_flag |= CH_PHYS_CD;
166 	else
167 		ch->ch_flag &= ~CH_PHYS_CD;
168 
169 }
170