1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * modem_setup.c: support for the scadm modem_setup option (access to the
29 * service processor modem - if present)
30 */
31
32 #include <curses.h>
33 #include <libintl.h>
34 #include <pthread.h>
35 #include <signal.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <time.h> /* required by librsc.h */
39 #include <unistd.h>
40
41 #include "librsc.h"
42 #include "adm.h"
43
44
45 extern char *ADM_Get_Var(char *Variable);
46
47 static void ADM_Send_Char(char C);
48 static void *ADM_Modem_Listen(void *);
49 static void cleanup();
50
51
52 typedef enum {ST_RESET, ST_IDLE, ST_TILDA} ADM_state_t;
53
54 static int ADM_Continue;
55 static int winOn = 0;
56 static pthread_t modemListen;
57
58
59 void
ADM_Process_modem_setup(void)60 ADM_Process_modem_setup(void)
61 {
62 rscp_msg_t msg;
63 struct timespec timeout;
64
65 int Input;
66 ADM_state_t State;
67 int exitLoop = 1;
68 char rsc_escape[2];
69 char string[40];
70
71
72 ADM_Start();
73
74 msg.type = DP_MODEM_CONNECT;
75 msg.len = 0;
76 msg.data = NULL;
77 ADM_Send(&msg);
78
79 timeout.tv_nsec = 0;
80 timeout.tv_sec = ADM_TIMEOUT;
81 ADM_Recv(&msg, &timeout, DP_MODEM_CONNECT_R,
82 sizeof (dp_modem_connect_r_t));
83 if (*(int *)msg.data != DP_MODEM_PASS) {
84 (void) fprintf(stderr, "\n%s\n\n",
85 gettext("scadm: could not connect to modem"));
86 exit(-1);
87 }
88 ADM_Free(&msg);
89
90 /* Get the escape char BEFORE starting up the "listen" thread */
91 (void) strcpy(rsc_escape, ADM_Get_Var("escape_char"));
92
93
94 /* Create Listening Thread */
95 ADM_Continue = 1;
96 if (pthread_create(&modemListen, NULL, ADM_Modem_Listen, NULL) != 0) {
97 (void) fprintf(stderr, "\n%s\n\n",
98 gettext("scadm: couldn't create thread"));
99 exit(-1);
100 }
101
102 if (signal(SIGINT, cleanup) == SIG_ERR) {
103 (void) fprintf(stderr, "\n%s\n\n",
104 gettext("scadm: cleanup() registration failed"));
105 ADM_Continue = 0;
106 exit(-1);
107 }
108
109
110 (void) sprintf(string, gettext("... Type %s. to return to prompt ..."),
111 rsc_escape);
112 Input = 0;
113 State = ST_RESET;
114 winOn = 1;
115 initscr();
116 noecho();
117 printw("\n%s\n\n", string);
118
119 while (exitLoop) {
120 while ((Input = getch()) == ERR)
121 ;
122
123 if (Input == 10) {
124 State = ST_RESET;
125 ADM_Send_Char('\n');
126 ADM_Send_Char('\r');
127 continue;
128 }
129
130 switch (State) {
131 case ST_RESET:
132 if ((char)Input == rsc_escape[0]) {
133 State = ST_TILDA;
134 } else {
135 State = ST_IDLE;
136 ADM_Send_Char((char)Input);
137 }
138 break;
139
140 case ST_IDLE:
141 ADM_Send_Char((char)Input);
142 break;
143
144 case ST_TILDA:
145 if ((char)Input == '.') {
146 ADM_Send_Char('~');
147 ADM_Send_Char('.');
148 exitLoop = 0;
149 } else {
150 State = ST_IDLE;
151 ADM_Send_Char((char)Input);
152 }
153 break;
154
155 default:
156 State = ST_IDLE;
157 ADM_Send_Char((char)Input);
158 }
159 }
160 endwin();
161 winOn = 0;
162
163 /* Terminate Thread */
164 ADM_Continue = 0;
165 (void) sleep(3); /* Make sure thread has time to 'see' */
166 /* termination */
167
168 msg.type = DP_MODEM_DISCONNECT;
169 msg.len = 0;
170 msg.data = NULL;
171 ADM_Send(&msg);
172
173 timeout.tv_nsec = 0;
174 timeout.tv_sec = ADM_TIMEOUT;
175 ADM_Recv(&msg, &timeout, DP_MODEM_DISCONNECT_R,
176 sizeof (dp_modem_disconnect_r_t));
177 if (*(int *)msg.data != DP_MODEM_PASS) {
178 (void) fprintf(stderr, "\n%s\n\n",
179 gettext("scadm: could not disconnect from modem"));
180 ADM_Continue = 0;
181 exit(-1);
182 }
183 ADM_Free(&msg);
184
185 pthread_join(modemListen, NULL);
186
187 }
188
189
190 static void
ADM_Send_Char(char C)191 ADM_Send_Char(char C)
192 {
193 rscp_msg_t Message;
194 char Data[2];
195
196 Data[0] = C;
197 Data[1] = 0x0;
198 Message.type = DP_MODEM_DATA;
199 Message.len = 2;
200 Message.data = Data;
201
202 if (rscp_send(&Message) != 0) {
203 (void) fprintf(stderr, "\n%s\n\n",
204 gettext("scadm: Unable to send modem data to SC"));
205 if (winOn)
206 endwin();
207 ADM_Continue = 0;
208 exit(-1);
209 }
210 }
211
212
213 static void *
ADM_Modem_Listen(void * arg __unused)214 ADM_Modem_Listen(void *arg __unused)
215 {
216 rscp_msg_t Message;
217 struct timespec Timeout;
218
219
220 while (ADM_Continue) {
221 Timeout.tv_nsec = 500000000;
222 Timeout.tv_sec = 0;
223 if (rscp_recv(&Message, &Timeout) != 0) {
224 continue;
225 }
226
227 if (Message.type != DP_MODEM_DATA) {
228 (void) fprintf(stderr, "\n%s: 0x%08x:0x%08lx\n\n",
229 gettext("scadm: SC returned garbage"),
230 Message.type, Message.len);
231 exit(-1);
232 }
233
234 (void) printf("%s", (char *)Message.data);
235 (void) fflush(stdout);
236 ADM_Free(&Message);
237 }
238 return (NULL);
239 }
240
241
242 static void
cleanup()243 cleanup()
244 {
245 rscp_msg_t msg;
246 struct timespec timeout;
247
248
249 if (winOn)
250 endwin();
251
252 /* Terminate Thread */
253 ADM_Continue = 0;
254
255 msg.type = DP_MODEM_DISCONNECT;
256 msg.len = 0;
257 msg.data = NULL;
258 ADM_Send(&msg);
259
260 timeout.tv_nsec = 0;
261 timeout.tv_sec = ADM_TIMEOUT;
262 ADM_Recv(&msg, &timeout, DP_MODEM_DISCONNECT_R,
263 sizeof (dp_modem_disconnect_r_t));
264 if (*(int *)msg.data != DP_MODEM_PASS) {
265 (void) fprintf(stderr, "\n%s\n\n",
266 gettext("scadm: could not disconnect from modem"));
267 exit(-1);
268 }
269 ADM_Free(&msg);
270
271 pthread_join(modemListen, NULL);
272
273 exit(-1);
274 }
275