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
47extern char *ADM_Get_Var(char *Variable);
48
49static void ADM_Send_Char(char  C);
50static void ADM_Modem_Listen();
51static void cleanup();
52
53
54typedef enum {ST_RESET, ST_IDLE, ST_TILDA} ADM_state_t;
55
56static int ADM_Continue;
57static int winOn = 0;
58static pthread_t modemListen;
59
60
61void
62ADM_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
192static void
193ADM_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
215static void
216ADM_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
243static void
244cleanup()
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