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