Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
 
5
#include "modem.h"
6
 
7
typedef struct {
8
	char	*terse;
9
	char	*verbose;
10
	int	result;
11
	int	(*f)(Modem*);
12
} ResultCode;
13
 
14
static ResultCode results[] = {
15
	{ "0",	"OK",		Rok,		0, },
16
	{ "1",	"CONNECT",	Rconnect,	0, },
17
	{ "2",	"RING",		Rring,		0, },
18
	{ "3",	"NO CARRIER", 	Rfailure,	0, },
19
	{ "4",	"ERROR",	Rrerror,	0, },
20
	{ "5",	"CONNECT 1200",	Rconnect,	0, },
21
	{ "6",	"NO DIALTONE",	Rfailure,	0, },
22
	{ "7",	"BUSY",		Rfailure,	0, },
23
	{ "8",	"NO ANSWER",	Rfailure,	0, },
24
	{ "9",	"CONNECT 2400",	Rconnect,	0, },		/* MT1432BA */
25
	{ "10",	"CONNECT 2400",	Rconnect,	0, },		/* Hayes */
26
	{ "11",	"CONNECT 4800",	Rconnect,	0, },
27
	{ "12",	"CONNECT 9600",	Rconnect,	0, },
28
	{ "13",	"CONNECT 14400",Rconnect,	0, },
29
	{ "23",	"CONNECT 1275",	Rconnect,	0, },		/* MT1432BA */
30
 
31
	{ "-1",	"+FCON",	Rcontinue,	fcon, },
32
	{ "-1",	"+FTSI",	Rcontinue,	ftsi, },
33
	{ "-1",	"+FDCS",	Rcontinue,	fdcs, },
34
	{ "-1",	"+FCFR",	Rcontinue,	fcfr, },
35
	{ "-1",	"+FPTS",	Rcontinue,	fpts, },
36
	{ "-1",	"+FET",		Rcontinue,	fet, },
37
	{ "-1",	"+FHNG",	Rcontinue,	fhng, },
38
 
39
	{ 0 },
40
};
41
 
42
void
43
initmodem(Modem *m, int fd, int cfd, char *type, char *id)
44
{
45
	m->fd = fd;
46
	m->cfd = cfd;
47
	if(id == 0)
48
		id = "Plan 9";
49
	m->id = id;
50
	m->t = type;
51
}
52
 
53
int
54
rawmchar(Modem *m, char *p)
55
{
56
	Dir *d;
57
	int n;
58
 
59
	if(m->icount == 0)
60
		m->iptr = m->ibuf;
61
 
62
	if(m->icount){
63
		*p = *m->iptr++;
64
		m->icount--;
65
		return Eok;
66
	}
67
 
68
	m->iptr = m->ibuf;
69
 
70
	if((d = dirfstat(m->fd)) == nil){
71
		verbose("rawmchar: dirfstat: %r");
72
		return seterror(m, Esys);
73
	}
74
	n = d->length;
75
	free(d);
76
	if(n == 0)
77
		return Enoresponse;
78
 
79
	if(n > sizeof(m->ibuf)-1)
80
		n = sizeof(m->ibuf)-1;
81
	if((m->icount = read(m->fd, m->ibuf, n)) <= 0){
82
		verbose("rawmchar: read: %r");
83
		m->icount = 0;
84
		return seterror(m, Esys);
85
	}
86
	*p = *m->iptr++;
87
	m->icount--;
88
 
89
	return Eok;
90
}
91
 
92
int
93
getmchar(Modem *m, char *buf, long timeout)
94
{
95
	int r, t;
96
 
97
	timeout += time(0);
98
	while((t = time(0)) <= timeout){
99
		switch(r = rawmchar(m, buf)){
100
 
101
		case Eok:
102
			return Eok;
103
 
104
		case Enoresponse:
105
			sleep(100);
106
			continue;
107
 
108
		default:
109
			return r;
110
		}
111
	}
112
	verbose("getmchar: time %ud, timeout %ud", t, timeout);
113
 
114
	return seterror(m, Enoresponse);
115
}
116
 
117
int
118
putmchar(Modem *m, char *p)
119
{
120
	if(write(m->fd, p, 1) < 0)
121
		return seterror(m, Esys);
122
	return Eok;
123
}
124
 
125
/*
126
 *  lines terminate with cr-lf
127
 */
128
static int
129
getmline(Modem *m, char *buf, int len, long timeout)
130
{
131
	int r, t;
132
	char *e = buf+len-1;
133
	char last = 0;
134
 
135
	timeout += time(0);
136
	while((t = time(0)) <= timeout){
137
		switch(r = rawmchar(m, buf)){
138
 
139
		case Eok:
140
			/* ignore ^s ^q which are used for flow */
141
			if(*buf == '\021' || *buf == '\023')
142
				continue;
143
			if(*buf == '\n'){
144
				/* ignore nl if its not with a cr */
145
				if(last == '\r'){
146
					*buf = 0;
147
					return Eok;
148
				}
149
				continue;
150
			}
151
			last = *buf;
152
			if(*buf == '\r')
153
				continue;
154
			buf++;
155
			if(buf == e){
156
				*buf = 0;
157
				return Eok;
158
			}
159
			continue;
160
 
161
		case Enoresponse:
162
			sleep(100);
163
			continue;
164
 
165
		default:
166
			return r;
167
		}
168
	}
169
	verbose("getmline: time %ud, timeout %ud", t, timeout);
170
 
171
	return seterror(m, Enoresponse);
172
}
173
 
174
int
175
command(Modem *m, char *s)
176
{
177
	verbose("m->: %s", s);
178
	if(fprint(m->fd, "%s\r", s) < 0)
179
		return seterror(m, Esys);
180
	return Eok;
181
}
182
 
183
/*
184
 * Read till we see a message or we time out.
185
 * BUG: line lengths not checked;
186
 *	newlines
187
 */
188
int
189
response(Modem *m, int timeout)
190
{
191
	int r;
192
	ResultCode *rp;
193
 
194
	while(getmline(m, m->response, sizeof(m->response), timeout) == Eok){
195
		if(m->response[0] == 0)
196
			continue;
197
		verbose("<-m: %s", m->response);
198
		for(rp = results; rp->terse; rp++){
199
			if(strncmp(rp->verbose, m->response, strlen(rp->verbose)))
200
				continue;
201
			r = rp->result;
202
			if(rp->f && (r = (*rp->f)(m)) == Rcontinue)
203
				break;
204
			return r;
205
		}
206
	}
207
 
208
	m->response[0] = 0;
209
	return Rnoise;
210
}
211
 
212
void
213
xonoff(Modem *m, int i)
214
{
215
	char buf[8];
216
 
217
	sprint(buf, "x%d", i);
218
	i = strlen(buf);
219
	write(m->cfd, buf, i);
220
}