xref: /illumos-gate/usr/src/cmd/scadm/sparc/mpxu/common/modem_setup.c (revision bb9b6b3f59b8820022416cea99b49c50fef6e391)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * modem_setup.c: support for the scadm modem_setup option (access to the
31  * service processor modem - if present)
32  */
33 
34 #include <curses.h>
35 #include <libintl.h>
36 #include <pthread.h>
37 #include <signal.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <time.h>  /* required by librsc.h */
41 #include <unistd.h>
42 
43 #include "librsc.h"
44 #include "adm.h"
45 
46 
47 extern char *ADM_Get_Var(char *Variable);
48 
49 static void ADM_Send_Char(char  C);
50 static void ADM_Modem_Listen();
51 static void cleanup();
52 
53 
54 typedef enum {ST_RESET, ST_IDLE, ST_TILDA} ADM_state_t;
55 
56 static int ADM_Continue;
57 static int winOn = 0;
58 static pthread_t modemListen;
59 
60 
61 void
62 ADM_Process_modem_setup()
63 {
64 	rscp_msg_t	msg;
65 	struct timespec	timeout;
66 
67 	int		Input;
68 	ADM_state_t	State;
69 	int		exitLoop = 1;
70 	char		rsc_escape[2];
71 	char		string[40];
72 
73 
74 	ADM_Start();
75 
76 	msg.type = DP_MODEM_CONNECT;
77 	msg.len  = 0;
78 	msg.data = NULL;
79 	ADM_Send(&msg);
80 
81 	timeout.tv_nsec = 0;
82 	timeout.tv_sec  = ADM_TIMEOUT;
83 	ADM_Recv(&msg, &timeout, DP_MODEM_CONNECT_R,
84 	    sizeof (dp_modem_connect_r_t));
85 	if (*(int *)msg.data != DP_MODEM_PASS) {
86 		(void) fprintf(stderr, "\n%s\n\n",
87 		    gettext("scadm: could not connect to modem"));
88 		exit(-1);
89 	}
90 	ADM_Free(&msg);
91 
92 	/* Get the escape char BEFORE starting up the "listen" thread */
93 	(void) strcpy(rsc_escape, ADM_Get_Var("escape_char"));
94 
95 
96 	/* Create Listening Thread */
97 	ADM_Continue = 1;
98 	if (pthread_create(&modemListen, NULL,
99 	    (void * (*)(void *))ADM_Modem_Listen, (void *)NULL) != 0) {
100 		(void) fprintf(stderr, "\n%s\n\n",
101 		    gettext("scadm: couldn't create thread"));
102 		exit(-1);
103 	}
104 
105 	if (signal(SIGINT, cleanup) == SIG_ERR) {
106 		(void) fprintf(stderr, "\n%s\n\n",
107 		    gettext("scadm: cleanup() registration failed"));
108 		ADM_Continue = 0;
109 		exit(-1);
110 	}
111 
112 
113 	(void) sprintf(string, gettext("... Type %s. to return to prompt ..."),
114 	    rsc_escape);
115 	Input = 0;
116 	State = ST_RESET;
117 	winOn = 1;
118 	initscr();
119 	noecho();
120 	printw("\n%s\n\n", string);
121 
122 	while (exitLoop) {
123 		while ((Input = getch()) == ERR);
124 
125 		if (Input == 10) {
126 			State = ST_RESET;
127 			ADM_Send_Char('\n');
128 			ADM_Send_Char('\r');
129 			continue;
130 		}
131 
132 		switch (State) {
133 			case ST_RESET:
134 				if ((char)Input == rsc_escape[0]) {
135 					State = ST_TILDA;
136 				} else {
137 					State = ST_IDLE;
138 					ADM_Send_Char((char)Input);
139 				}
140 				break;
141 
142 			case ST_IDLE:
143 				ADM_Send_Char((char)Input);
144 				break;
145 
146 			case ST_TILDA:
147 				if ((char)Input == '.') {
148 					ADM_Send_Char('~');
149 					ADM_Send_Char('.');
150 					exitLoop = 0;
151 				} else {
152 					State = ST_IDLE;
153 					ADM_Send_Char((char)Input);
154 				}
155 				break;
156 
157 			default:
158 				State = ST_IDLE;
159 				ADM_Send_Char((char)Input);
160 		}
161 	}
162 	endwin();
163 	winOn = 0;
164 
165 	/* Terminate Thread */
166 	ADM_Continue = 0;
167 	(void) sleep(3); 	/* Make sure thread has time to 'see' */
168 				/* termination */
169 
170 	msg.type = DP_MODEM_DISCONNECT;
171 	msg.len  = 0;
172 	msg.data = NULL;
173 	ADM_Send(&msg);
174 
175 	timeout.tv_nsec = 0;
176 	timeout.tv_sec  = ADM_TIMEOUT;
177 	ADM_Recv(&msg, &timeout, DP_MODEM_DISCONNECT_R,
178 	    sizeof (dp_modem_disconnect_r_t));
179 	if (*(int *)msg.data != DP_MODEM_PASS) {
180 		(void) fprintf(stderr, "\n%s\n\n",
181 		    gettext("scadm: could not disconnect from modem"));
182 		ADM_Continue = 0;
183 		exit(-1);
184 	}
185 	ADM_Free(&msg);
186 
187 	pthread_join(modemListen, NULL);
188 
189 }
190 
191 
192 static void
193 ADM_Send_Char(char C)
194 {
195 	rscp_msg_t	Message;
196 	char		Data[2];
197 
198 	Data[0] = C;
199 	Data[1] = 0x0;
200 	Message.type = DP_MODEM_DATA;
201 	Message.len  = 2;
202 	Message.data = Data;
203 
204 	if (rscp_send(&Message) != 0) {
205 		(void) fprintf(stderr, "\n%s\n\n",
206 		    gettext("scadm: Unable to send modem data to SC"));
207 		if (winOn)
208 			endwin();
209 		ADM_Continue = 0;
210 		exit(-1);
211 	}
212 }
213 
214 
215 static void
216 ADM_Modem_Listen()
217 {
218 	rscp_msg_t	Message;
219 	struct timespec	Timeout;
220 
221 
222 	while (ADM_Continue) {
223 		Timeout.tv_nsec = 500000000;
224 		Timeout.tv_sec  = 0;
225 		if (rscp_recv(&Message, &Timeout) != 0) {
226 			continue;
227 		}
228 
229 		if (Message.type != DP_MODEM_DATA) {
230 			(void) fprintf(stderr, "\n%s: 0x%08x:0x%08lx\n\n",
231 			    gettext("scadm: SC returned garbage"),
232 			    Message.type, Message.len);
233 			exit(-1);
234 		}
235 
236 		(void) printf("%s", (char *)Message.data);
237 		(void) fflush(stdout);
238 		ADM_Free(&Message);
239 	}
240 }
241 
242 
243 static void
244 cleanup()
245 {
246 	rscp_msg_t	msg;
247 	struct timespec	timeout;
248 
249 
250 	if (winOn)
251 		endwin();
252 
253 	/* Terminate Thread */
254 	ADM_Continue = 0;
255 
256 	msg.type = DP_MODEM_DISCONNECT;
257 	msg.len  = 0;
258 	msg.data = NULL;
259 	ADM_Send(&msg);
260 
261 	timeout.tv_nsec = 0;
262 	timeout.tv_sec  = ADM_TIMEOUT;
263 	ADM_Recv(&msg, &timeout, DP_MODEM_DISCONNECT_R,
264 	    sizeof (dp_modem_disconnect_r_t));
265 	if (*(int *)msg.data != DP_MODEM_PASS) {
266 		(void) fprintf(stderr, "\n%s\n\n",
267 		    gettext("scadm: could not disconnect from modem"));
268 		exit(-1);
269 	}
270 	ADM_Free(&msg);
271 
272 	pthread_join(modemListen, NULL);
273 
274 	exit(-1);
275 }
276