103831d35Sstevel /*
203831d35Sstevel  * CDDL HEADER START
303831d35Sstevel  *
403831d35Sstevel  * The contents of this file are subject to the terms of the
503831d35Sstevel  * Common Development and Distribution License, Version 1.0 only
603831d35Sstevel  * (the "License").  You may not use this file except in compliance
703831d35Sstevel  * with the License.
803831d35Sstevel  *
903831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1003831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
1103831d35Sstevel  * See the License for the specific language governing permissions
1203831d35Sstevel  * and limitations under the License.
1303831d35Sstevel  *
1403831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
1503831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1603831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
1703831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
1803831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
1903831d35Sstevel  *
2003831d35Sstevel  * CDDL HEADER END
2103831d35Sstevel  */
2203831d35Sstevel /*
2303831d35Sstevel  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
2403831d35Sstevel  * Use is subject to license terms.
2503831d35Sstevel  */
2603831d35Sstevel 
2703831d35Sstevel /*
2803831d35Sstevel  * modem_setup.c: support for the scadm modem_setup option (access to the
2903831d35Sstevel  * service processor modem - if present)
3003831d35Sstevel  */
3103831d35Sstevel 
3203831d35Sstevel #include <curses.h>
3303831d35Sstevel #include <libintl.h>
3403831d35Sstevel #include <pthread.h>
3503831d35Sstevel #include <signal.h>
3603831d35Sstevel #include <stdio.h>
3703831d35Sstevel #include <string.h>
3803831d35Sstevel #include <time.h>  /* required by librsc.h */
3903831d35Sstevel #include <unistd.h>
4003831d35Sstevel 
4103831d35Sstevel #include "librsc.h"
4203831d35Sstevel #include "adm.h"
4303831d35Sstevel 
4403831d35Sstevel 
4503831d35Sstevel extern char *ADM_Get_Var(char *Variable);
4603831d35Sstevel 
4703831d35Sstevel static void ADM_Send_Char(char  C);
48*d14c7576SToomas Soome static void *ADM_Modem_Listen(void *);
4903831d35Sstevel static void cleanup();
5003831d35Sstevel 
5103831d35Sstevel 
5203831d35Sstevel typedef enum {ST_RESET, ST_IDLE, ST_TILDA} ADM_state_t;
5303831d35Sstevel 
5403831d35Sstevel static int ADM_Continue;
5503831d35Sstevel static int winOn = 0;
5603831d35Sstevel static pthread_t modemListen;
5703831d35Sstevel 
5803831d35Sstevel 
5903831d35Sstevel void
ADM_Process_modem_setup(void)60*d14c7576SToomas Soome ADM_Process_modem_setup(void)
6103831d35Sstevel {
6203831d35Sstevel 	rscp_msg_t	msg;
6303831d35Sstevel 	struct timespec	timeout;
6403831d35Sstevel 
6503831d35Sstevel 	int		Input;
6603831d35Sstevel 	ADM_state_t	State;
6703831d35Sstevel 	int		exitLoop = 1;
6803831d35Sstevel 	char		rsc_escape[2];
6903831d35Sstevel 	char		string[40];
7003831d35Sstevel 
7103831d35Sstevel 
7203831d35Sstevel 	ADM_Start();
7303831d35Sstevel 
7403831d35Sstevel 	msg.type = DP_MODEM_CONNECT;
7503831d35Sstevel 	msg.len  = 0;
7603831d35Sstevel 	msg.data = NULL;
7703831d35Sstevel 	ADM_Send(&msg);
7803831d35Sstevel 
7903831d35Sstevel 	timeout.tv_nsec = 0;
8003831d35Sstevel 	timeout.tv_sec  = ADM_TIMEOUT;
8103831d35Sstevel 	ADM_Recv(&msg, &timeout, DP_MODEM_CONNECT_R,
8203831d35Sstevel 	    sizeof (dp_modem_connect_r_t));
8303831d35Sstevel 	if (*(int *)msg.data != DP_MODEM_PASS) {
8403831d35Sstevel 		(void) fprintf(stderr, "\n%s\n\n",
8503831d35Sstevel 		    gettext("scadm: could not connect to modem"));
8603831d35Sstevel 		exit(-1);
8703831d35Sstevel 	}
8803831d35Sstevel 	ADM_Free(&msg);
8903831d35Sstevel 
9003831d35Sstevel 	/* Get the escape char BEFORE starting up the "listen" thread */
9103831d35Sstevel 	(void) strcpy(rsc_escape, ADM_Get_Var("escape_char"));
9203831d35Sstevel 
9303831d35Sstevel 
9403831d35Sstevel 	/* Create Listening Thread */
9503831d35Sstevel 	ADM_Continue = 1;
96*d14c7576SToomas Soome 	if (pthread_create(&modemListen, NULL, ADM_Modem_Listen, NULL) != 0) {
9703831d35Sstevel 		(void) fprintf(stderr, "\n%s\n\n",
9803831d35Sstevel 		    gettext("scadm: couldn't create thread"));
9903831d35Sstevel 		exit(-1);
10003831d35Sstevel 	}
10103831d35Sstevel 
10203831d35Sstevel 	if (signal(SIGINT, cleanup) == SIG_ERR) {
10303831d35Sstevel 		(void) fprintf(stderr, "\n%s\n\n",
10403831d35Sstevel 		    gettext("scadm: cleanup() registration failed"));
10503831d35Sstevel 		ADM_Continue = 0;
10603831d35Sstevel 		exit(-1);
10703831d35Sstevel 	}
10803831d35Sstevel 
10903831d35Sstevel 
11003831d35Sstevel 	(void) sprintf(string, gettext("... Type %s. to return to prompt ..."),
11103831d35Sstevel 	    rsc_escape);
11203831d35Sstevel 	Input = 0;
11303831d35Sstevel 	State = ST_RESET;
11403831d35Sstevel 	winOn = 1;
11503831d35Sstevel 	initscr();
11603831d35Sstevel 	noecho();
11703831d35Sstevel 	printw("\n%s\n\n", string);
11803831d35Sstevel 
11903831d35Sstevel 	while (exitLoop) {
120*d14c7576SToomas Soome 		while ((Input = getch()) == ERR)
121*d14c7576SToomas Soome 			;
12203831d35Sstevel 
12303831d35Sstevel 		if (Input == 10) {
12403831d35Sstevel 			State = ST_RESET;
12503831d35Sstevel 			ADM_Send_Char('\n');
12603831d35Sstevel 			ADM_Send_Char('\r');
12703831d35Sstevel 			continue;
12803831d35Sstevel 		}
12903831d35Sstevel 
13003831d35Sstevel 		switch (State) {
13103831d35Sstevel 			case ST_RESET:
13203831d35Sstevel 				if ((char)Input == rsc_escape[0]) {
13303831d35Sstevel 					State = ST_TILDA;
13403831d35Sstevel 				} else {
13503831d35Sstevel 					State = ST_IDLE;
13603831d35Sstevel 					ADM_Send_Char((char)Input);
13703831d35Sstevel 				}
13803831d35Sstevel 				break;
13903831d35Sstevel 
14003831d35Sstevel 			case ST_IDLE:
14103831d35Sstevel 				ADM_Send_Char((char)Input);
14203831d35Sstevel 				break;
14303831d35Sstevel 
14403831d35Sstevel 			case ST_TILDA:
14503831d35Sstevel 				if ((char)Input == '.') {
14603831d35Sstevel 					ADM_Send_Char('~');
14703831d35Sstevel 					ADM_Send_Char('.');
14803831d35Sstevel 					exitLoop = 0;
14903831d35Sstevel 				} else {
15003831d35Sstevel 					State = ST_IDLE;
15103831d35Sstevel 					ADM_Send_Char((char)Input);
15203831d35Sstevel 				}
15303831d35Sstevel 				break;
15403831d35Sstevel 
15503831d35Sstevel 			default:
15603831d35Sstevel 				State = ST_IDLE;
15703831d35Sstevel 				ADM_Send_Char((char)Input);
15803831d35Sstevel 		}
15903831d35Sstevel 	}
16003831d35Sstevel 	endwin();
16103831d35Sstevel 	winOn = 0;
16203831d35Sstevel 
16303831d35Sstevel 	/* Terminate Thread */
16403831d35Sstevel 	ADM_Continue = 0;
165*d14c7576SToomas Soome 	(void) sleep(3);	/* Make sure thread has time to 'see' */
16603831d35Sstevel 				/* termination */
16703831d35Sstevel 
16803831d35Sstevel 	msg.type = DP_MODEM_DISCONNECT;
16903831d35Sstevel 	msg.len  = 0;
17003831d35Sstevel 	msg.data = NULL;
17103831d35Sstevel 	ADM_Send(&msg);
17203831d35Sstevel 
17303831d35Sstevel 	timeout.tv_nsec = 0;
17403831d35Sstevel 	timeout.tv_sec  = ADM_TIMEOUT;
17503831d35Sstevel 	ADM_Recv(&msg, &timeout, DP_MODEM_DISCONNECT_R,
17603831d35Sstevel 	    sizeof (dp_modem_disconnect_r_t));
17703831d35Sstevel 	if (*(int *)msg.data != DP_MODEM_PASS) {
17803831d35Sstevel 		(void) fprintf(stderr, "\n%s\n\n",
17903831d35Sstevel 		    gettext("scadm: could not disconnect from modem"));
18003831d35Sstevel 		ADM_Continue = 0;
18103831d35Sstevel 		exit(-1);
18203831d35Sstevel 	}
18303831d35Sstevel 	ADM_Free(&msg);
18403831d35Sstevel 
18503831d35Sstevel 	pthread_join(modemListen, NULL);
18603831d35Sstevel 
18703831d35Sstevel }
18803831d35Sstevel 
18903831d35Sstevel 
19003831d35Sstevel static void
ADM_Send_Char(char C)19103831d35Sstevel ADM_Send_Char(char C)
19203831d35Sstevel {
19303831d35Sstevel 	rscp_msg_t	Message;
19403831d35Sstevel 	char		Data[2];
19503831d35Sstevel 
19603831d35Sstevel 	Data[0] = C;
19703831d35Sstevel 	Data[1] = 0x0;
19803831d35Sstevel 	Message.type = DP_MODEM_DATA;
19903831d35Sstevel 	Message.len  = 2;
20003831d35Sstevel 	Message.data = Data;
20103831d35Sstevel 
20203831d35Sstevel 	if (rscp_send(&Message) != 0) {
20303831d35Sstevel 		(void) fprintf(stderr, "\n%s\n\n",
20403831d35Sstevel 		    gettext("scadm: Unable to send modem data to SC"));
20503831d35Sstevel 		if (winOn)
20603831d35Sstevel 			endwin();
20703831d35Sstevel 		ADM_Continue = 0;
20803831d35Sstevel 		exit(-1);
20903831d35Sstevel 	}
21003831d35Sstevel }
21103831d35Sstevel 
21203831d35Sstevel 
213*d14c7576SToomas Soome static void *
ADM_Modem_Listen(void * arg __unused)214*d14c7576SToomas Soome ADM_Modem_Listen(void *arg __unused)
21503831d35Sstevel {
21603831d35Sstevel 	rscp_msg_t	Message;
21703831d35Sstevel 	struct timespec	Timeout;
21803831d35Sstevel 
21903831d35Sstevel 
22003831d35Sstevel 	while (ADM_Continue) {
22103831d35Sstevel 		Timeout.tv_nsec = 500000000;
22203831d35Sstevel 		Timeout.tv_sec  = 0;
22303831d35Sstevel 		if (rscp_recv(&Message, &Timeout) != 0) {
22403831d35Sstevel 			continue;
22503831d35Sstevel 		}
22603831d35Sstevel 
22703831d35Sstevel 		if (Message.type != DP_MODEM_DATA) {
22803831d35Sstevel 			(void) fprintf(stderr, "\n%s: 0x%08x:0x%08lx\n\n",
22903831d35Sstevel 			    gettext("scadm: SC returned garbage"),
23003831d35Sstevel 			    Message.type, Message.len);
23103831d35Sstevel 			exit(-1);
23203831d35Sstevel 		}
23303831d35Sstevel 
23403831d35Sstevel 		(void) printf("%s", (char *)Message.data);
23503831d35Sstevel 		(void) fflush(stdout);
23603831d35Sstevel 		ADM_Free(&Message);
23703831d35Sstevel 	}
238*d14c7576SToomas Soome 	return (NULL);
23903831d35Sstevel }
24003831d35Sstevel 
24103831d35Sstevel 
24203831d35Sstevel static void
cleanup()24303831d35Sstevel cleanup()
24403831d35Sstevel {
24503831d35Sstevel 	rscp_msg_t	msg;
24603831d35Sstevel 	struct timespec	timeout;
24703831d35Sstevel 
24803831d35Sstevel 
24903831d35Sstevel 	if (winOn)
25003831d35Sstevel 		endwin();
25103831d35Sstevel 
25203831d35Sstevel 	/* Terminate Thread */
25303831d35Sstevel 	ADM_Continue = 0;
25403831d35Sstevel 
25503831d35Sstevel 	msg.type = DP_MODEM_DISCONNECT;
25603831d35Sstevel 	msg.len  = 0;
25703831d35Sstevel 	msg.data = NULL;
25803831d35Sstevel 	ADM_Send(&msg);
25903831d35Sstevel 
26003831d35Sstevel 	timeout.tv_nsec = 0;
26103831d35Sstevel 	timeout.tv_sec  = ADM_TIMEOUT;
26203831d35Sstevel 	ADM_Recv(&msg, &timeout, DP_MODEM_DISCONNECT_R,
26303831d35Sstevel 	    sizeof (dp_modem_disconnect_r_t));
26403831d35Sstevel 	if (*(int *)msg.data != DP_MODEM_PASS) {
26503831d35Sstevel 		(void) fprintf(stderr, "\n%s\n\n",
26603831d35Sstevel 		    gettext("scadm: could not disconnect from modem"));
26703831d35Sstevel 		exit(-1);
26803831d35Sstevel 	}
26903831d35Sstevel 	ADM_Free(&msg);
27003831d35Sstevel 
27103831d35Sstevel 	pthread_join(modemListen, NULL);
27203831d35Sstevel 
27303831d35Sstevel 	exit(-1);
27403831d35Sstevel }
275