Commit | Line | Data |
---|---|---|
0b52b749 BP |
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 | */ | |
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 | } |