1 #include <u.h> 2 #include <libc.h> 3 4 void setspeed(int, int); 5 int getspeed(char*, int); 6 void godial(int, int, char*); 7 int readmsg(int, int); 8 void punt(char*, ...); 9 10 int pulsed; 11 int verbose; 12 char msgbuf[128]; /* last message read */ 13 14 enum 15 { 16 Ok, 17 Success, 18 Failure, 19 Noise, 20 }; 21 22 typedef struct Msg Msg; 23 struct Msg 24 { 25 char *text; 26 int type; 27 }; 28 29 30 Msg msgs[] = 31 { 32 { "OK", Ok, }, 33 { "NO CARRIER", Failure, }, 34 { "ERROR", Failure, }, 35 { "NO DIALTONE", Failure, }, 36 { "BUSY", Failure, }, 37 { "NO ANSWER", Failure, }, 38 { "CONNECT", Success, }, 39 { 0, 0 }, 40 }; 41 42 void 43 usage(void) 44 { 45 punt("usage: hayes [-p] telno [device]"); 46 } 47 48 void 49 main(int argc, char **argv) 50 { 51 int data = -1; 52 int ctl = -1; 53 char *cname; 54 55 ARGBEGIN{ 56 case 'p': 57 pulsed = 1; 58 break; 59 case 'v': 60 verbose = 1; 61 break; 62 default: 63 usage(); 64 }ARGEND 65 66 switch(argc){ 67 case 1: 68 data = 1; 69 break; 70 case 2: 71 data = open(argv[1], ORDWR); 72 if(data < 0){ 73 fprint(2, "hayes: %r opening %s\n", argv[1]); 74 exits("hayes"); 75 } 76 cname = malloc(strlen(argv[1])+4); 77 sprint(cname, "%sctl", argv[1]); 78 ctl = open(cname, ORDWR); 79 free(cname); 80 break; 81 default: 82 usage(); 83 } 84 godial(data, ctl, argv[0]); 85 exits(0); 86 } 87 88 int 89 send(int fd, char *x) 90 { 91 return write(fd, x, strlen(x)); 92 } 93 94 void 95 godial(int data, int ctl, char *number) 96 { 97 char *dialstr; 98 int m; 99 int baud; 100 101 /* get the modem's attention */ 102 if(send(data, "\r+++\r") < 0) 103 punt("failed write"); 104 readmsg(data, 2); 105 sleep(1000); 106 107 /* initialize */ 108 if(send(data, "ATZ\r") < 0) 109 punt("failed write"); 110 m = readmsg(data, 2); 111 if(m < 0) 112 punt("can't get modem's attention"); 113 114 /* 115 * Q0 = report result codes 116 * V1 = full word result codes 117 * W1 = negotiation progress codes enabled 118 * E1 = echo commands 119 * M1 = speaker on until on-line 120 */ 121 if(send(data, "ATQ0V1E1M1\r") < 0) 122 punt("failed write"); 123 m = readmsg(data, 2); 124 if(m != Ok) 125 punt("can't get modem's attention"); 126 if(send(data, "ATW1\r") < 0) 127 punt("failed write"); 128 readmsg(data, 2); 129 sleep(1000); 130 131 /* godial */ 132 dialstr = malloc(6+strlen(number)); 133 sprint(dialstr, "ATD%c%s\r", pulsed ? 'P' : 'T', number); 134 if(send(data, dialstr) < 0) { 135 free(dialstr); 136 punt("failed write"); 137 } 138 free(dialstr); 139 m = readmsg(data, 60); 140 if(m != Success) 141 punt("dial failed: %s", msgbuf); 142 baud = getspeed(msgbuf, 9600); 143 setspeed(ctl, baud); 144 fprint(2, "hayes: connected at %d baud\n", baud); 145 } 146 147 /* 148 * read until we see a message or we time out 149 */ 150 int 151 readmsg(int f, int secs) 152 { 153 ulong start; 154 char *p; 155 int len; 156 Dir *d; 157 Msg *pp; 158 159 p = msgbuf; 160 len = sizeof(msgbuf) - 1; 161 for(start = time(0); time(0) <= start+secs;){ 162 if((d = dirfstat(f)) == nil) 163 punt("failed read"); 164 if(d->length == 0){ 165 free(d); 166 sleep(100); 167 continue; 168 } 169 free(d); 170 if(read(f, p, 1) <= 0) 171 punt("failed read"); 172 if(*p == '\n' || *p == '\r' || len == 0){ 173 *p = 0; 174 if(verbose && p != msgbuf) 175 fprint(2, "%s\n", msgbuf); 176 for(pp = msgs; pp->text; pp++) 177 if(strncmp(pp->text, msgbuf, strlen(pp->text))==0) 178 return pp->type; 179 start = time(0); 180 p = msgbuf; 181 len = sizeof(msgbuf) - 1; 182 continue; 183 } 184 len--; 185 p++; 186 } 187 strcpy(msgbuf, "No response from modem"); 188 return Noise; 189 } 190 191 /* 192 * get baud rate from a connect message 193 */ 194 int 195 getspeed(char *msg, int speed) 196 { 197 char *p; 198 int s; 199 200 p = msg + sizeof("CONNECT") - 1; 201 while(*p == ' ' || *p == '\t') 202 p++; 203 s = atoi(p); 204 if(s <= 0) 205 return speed; 206 else 207 return s; 208 } 209 210 /* 211 * set speed and RTS/CTS modem flow control 212 */ 213 void 214 setspeed(int ctl, int baud) 215 { 216 char buf[32]; 217 218 if(ctl < 0) 219 return; 220 sprint(buf, "b%d", baud); 221 write(ctl, buf, strlen(buf)); 222 write(ctl, "m1", 2); 223 } 224 225 226 void 227 punt(char *fmt, ...) 228 { 229 char buf[256]; 230 va_list arg; 231 int n; 232 233 strcpy(buf, "hayes: "); 234 va_start(arg, fmt); 235 n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; 236 va_end(arg); 237 buf[n] = '\n'; 238 write(2, buf, n+1); 239 exits("hayes"); 240 } 241