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