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