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 <thread.h>
4
#include "usb.h"
5
#include "usbfs.h"
6
#include "serial.h"
7
#include "prolific.h"
8
 
9
Cinfo plinfo[] = {
10
	{ PL2303Vid,	PL2303Did },
11
	{ PL2303Vid,	PL2303DidRSAQ2 },
12
	{ PL2303Vid,	PL2303DidDCU11 },
13
	{ PL2303Vid,	PL2303DidRSAQ3 },
14
	{ PL2303Vid,	PL2303DidPHAROS },
15
	{ PL2303Vid,	PL2303DidALDIGA },
16
	{ PL2303Vid,	PL2303DidMMX },
17
	{ PL2303Vid,	PL2303DidGPRS },
18
	{ IODATAVid,	IODATADid },
19
	{ IODATAVid,	IODATADidRSAQ5 },
20
	{ ATENVid,	ATENDid },
21
	{ ATENVid2,	ATENDid },
22
	{ ELCOMVid,	ELCOMDid },
23
	{ ELCOMVid,	ELCOMDidUCSGT },
24
	{ ITEGNOVid,	ITEGNODid },
25
	{ ITEGNOVid,	ITEGNODid2080 },
26
	{ MA620Vid,	MA620Did },
27
	{ RATOCVid,	RATOCDid },
28
	{ TRIPPVid,	TRIPPDid },
29
	{ RADIOSHACKVid,RADIOSHACKDid },
30
	{ DCU10Vid,	DCU10Did },
31
	{ SITECOMVid,	SITECOMDid },
32
	{ ALCATELVid,	ALCATELDid },
33
	{ SAMSUNGVid,	SAMSUNGDid },
34
	{ SIEMENSVid,	SIEMENSDidSX1 },
35
	{ SIEMENSVid,	SIEMENSDidX65 },
36
	{ SIEMENSVid,	SIEMENSDidX75 },
37
	{ SIEMENSVid,	SIEMENSDidEF81 },
38
	{ SYNTECHVid,	SYNTECHDid },
39
	{ NOKIACA42Vid,	NOKIACA42Did },
40
	{ CA42CA42Vid,	CA42CA42Did },
41
	{ SAGEMVid,	SAGEMDid },
42
	{ LEADTEKVid,	LEADTEK9531Did },
43
	{ SPEEDDRAGONVid,SPEEDDRAGONDid },
44
	{ DATAPILOTU2Vid,DATAPILOTU2Did },
45
	{ BELKINVid,	BELKINDid },
46
	{ ALCORVid,	ALCORDid },
47
	{ WS002INVid,	WS002INDid },
48
	{ COREGAVid,	COREGADid },
49
	{ YCCABLEVid,	YCCABLEDid },
50
	{ SUPERIALVid,	SUPERIALDid },
51
	{ HPVid,	HPLD220Did },
52
	{ 0,		0 },
53
};
54
 
55
int
56
plmatch(char *info)
57
{
58
	Cinfo *ip;
59
	char buf[50];
60
 
61
	for(ip = plinfo; ip->vid != 0; ip++){
62
		snprint(buf, sizeof buf, "vid %#06x did %#06x",
63
			ip->vid, ip->did);
64
		dsprint(2, "serial: %s %s\n", buf, info);
65
		if(strstr(info, buf) != nil)
66
			return 0;
67
	}
68
	return -1;
69
}
70
 
71
static void	statusreader(void *u);
72
 
73
static void
74
dumpbuf(uchar *buf, int bufsz)
75
{
76
	int i;
77
 
78
	for(i=0; i<bufsz; i++)
79
		print("buf[%d]=%#ux ", i, buf[i]);
80
	print("\n");
81
}
82
 
83
static int
84
vendorread(Serialport *p, int val, int index, uchar *buf)
85
{
86
	int res;
87
	Serial *ser;
88
 
89
	ser = p->s;
90
 
91
	dsprint(2, "serial: vendorread val: 0x%x idx:%d buf:%p\n",
92
		val, index, buf);
93
	res = usbcmd(ser->dev,  Rd2h | Rvendor | Rdev, VendorReadReq,
94
		val, index, buf, 1);
95
	dsprint(2, "serial: vendorread res:%d\n", res);
96
	return res;
97
}
98
 
99
static int
100
vendorwrite(Serialport *p, int val, int index)
101
{
102
	int res;
103
	Serial *ser;
104
 
105
	ser = p->s;
106
 
107
	dsprint(2, "serial: vendorwrite val: 0x%x idx:%d\n", val, index);
108
	res = usbcmd(ser->dev, Rh2d | Rvendor | Rdev, VendorWriteReq,
109
		val, index, nil, 0);
110
	dsprint(2, "serial: vendorwrite res:%d\n", res);
111
	return res;
112
}
113
 
114
/* BUG: I could probably read Dcr0 and set only the bits */
115
static int
116
plmodemctl(Serialport *p, int set)
117
{
118
	Serial *ser;
119
 
120
	ser = p->s;
121
 
122
	if(set == 0){
123
		p->mctl = 0;
124
		vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init);
125
		return 0;
126
	}
127
 
128
	p->mctl = 1;
129
	if(ser->type == TypeHX)
130
		vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init|Dcr0HwFcX);
131
	else
132
		vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init|Dcr0HwFcH);
133
	return 0;
134
}
135
 
136
static int
137
plgetparam(Serialport *p)
138
{
139
	uchar buf[ParamReqSz];
140
	int res;
141
	Serial *ser;
142
 
143
	ser = p->s;
144
 
145
 
146
	res = usbcmd(ser->dev, Rd2h | Rclass | Riface, GetLineReq,
147
		0, 0, buf, sizeof buf);
148
	p->baud = GET4(buf);
149
 
150
	/*
151
	 * with the Pl9 interface it is not possible to set `1.5' as stop bits
152
	 * for the prologic:
153
	 *	0 is 1 stop bit
154
	 *	1 is 1.5 stop bits
155
	 *	2 is 2 stop bits
156
	 */
157
	if(buf[4] == 1)
158
		fprint(2, "warning, stop bit set to 1.5 unsupported");
159
	else if(buf[4] == 0)
160
		p->stop = 1;
161
	else if(buf[4] == 2)
162
		p->stop = 2;
163
	p->parity = buf[5];
164
	p->bits = buf[6];
165
 
166
	dsprint(2, "serial: getparam: ");
167
	if(serialdebug)
168
		dumpbuf(buf, sizeof buf);
169
	dsprint(2, "serial: getparam res: %d\n", res);
170
	return res;
171
}
172
 
173
static int
174
plsetparam(Serialport *p)
175
{
176
	uchar buf[ParamReqSz];
177
	int res;
178
	Serial *ser;
179
 
180
	ser = p->s;
181
 
182
	PUT4(buf, p->baud);
183
 
184
	if(p->stop == 1)
185
		buf[4] = 0;
186
	else if(p->stop == 2)
187
		buf[4] = 2; 			/* see comment in getparam */
188
	buf[5] = p->parity;
189
	buf[6] = p->bits;
190
 
191
	dsprint(2, "serial: setparam: ");
192
	if(serialdebug)
193
		dumpbuf(buf, sizeof buf);
194
	res = usbcmd(ser->dev, Rh2d | Rclass | Riface, SetLineReq,
195
		0, 0, buf, sizeof buf);
196
	plmodemctl(p, p->mctl);
197
	plgetparam(p);		/* make sure our state corresponds */
198
 
199
	dsprint(2, "serial: setparam res: %d\n", res);
200
	return res;
201
}
202
 
203
static int
204
revid(ulong devno)
205
{
206
	switch(devno){
207
	case RevH:
208
		return TypeH;
209
	case RevX:
210
	case RevHX:
211
	case Rev1:
212
		return TypeHX;
213
	default:
214
		return TypeUnk;
215
	}
216
}
217
 
218
/* linux driver says the release id is not always right */
219
static int
220
heuristicid(ulong csp, ulong maxpkt)
221
{
222
	if(Class(csp) == 0x02)
223
		return TypeH;
224
	else if(maxpkt == 0x40)
225
		return TypeHX;
226
	else if(Class(csp) == 0x00 || Class(csp) == 0xFF)
227
		return TypeH;
228
	else{
229
		fprint(2, "serial: chip unknown, setting to HX version\n");
230
		return TypeHX;
231
	}
232
}
233
 
234
static int
235
plinit(Serialport *p)
236
{
237
	char *st;
238
	uchar *buf;
239
	ulong csp, maxpkt, dno;
240
	Serial *ser;
241
 
242
	ser = p->s;
243
	buf = emallocz(VendorReqSz, 1);
244
	dsprint(2, "plinit\n");
245
 
246
	csp = ser->dev->usb->csp;
247
	maxpkt = ser->dev->maxpkt;
248
	dno = ser->dev->usb->dno;
249
 
250
	if((ser->type = revid(dno)) == TypeUnk)
251
		ser->type = heuristicid(csp, maxpkt);
252
 
253
	dsprint(2, "serial: type %d\n", ser->type);
254
 
255
	vendorread(p, 0x8484, 0, buf);
256
	vendorwrite(p, 0x0404, 0);
257
	vendorread(p, 0x8484, 0, buf);
258
	vendorread(p, 0x8383, 0, buf);
259
	vendorread(p, 0x8484, 0, buf);
260
	vendorwrite(p, 0x0404, 1);
261
	vendorread(p, 0x8484, 0, buf);
262
	vendorread(p, 0x8383, 0, buf);
263
 
264
	vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init);
265
	vendorwrite(p, Dcr1Idx|DcrSet, Dcr1Init);
266
 
267
	if(ser->type == TypeHX)
268
		vendorwrite(p, Dcr2Idx|DcrSet, Dcr2InitX);
269
	else
270
		vendorwrite(p, Dcr2Idx|DcrSet, Dcr2InitH);
271
 
272
	plgetparam(p);
273
	qunlock(ser);
274
	free(buf);
275
	st = emallocz(255, 1);
276
	qlock(ser);
277
	if(serialdebug)
278
		serdumpst(p, st, 255);
279
	dsprint(2, st);
280
	free(st);
281
	/* p gets freed by closedev, the process has a reference */
282
	incref(ser->dev);
283
	proccreate(statusreader, p, 8*1024);
284
	return 0;
285
}
286
 
287
static int
288
plsetbreak(Serialport *p, int val)
289
{
290
	Serial *ser;
291
 
292
	ser = p->s;
293
	return usbcmd(ser->dev, Rh2d | Rclass | Riface,
294
		(val != 0? BreakOn: BreakOff), val, 0, nil, 0);
295
}
296
 
297
static int
298
plclearpipes(Serialport *p)
299
{
300
	Serial *ser;
301
 
302
	ser = p->s;
303
 
304
	if(ser->type == TypeHX){
305
		vendorwrite(p, PipeDSRst, 0);
306
		vendorwrite(p, PipeUSRst, 0);
307
	}else{
308
		if(unstall(ser->dev, p->epout, Eout) < 0)
309
			dprint(2, "disk: unstall epout: %r\n");
310
		if(unstall(ser->dev, p->epin, Ein) < 0)
311
			dprint(2, "disk: unstall epin: %r\n");
312
		if(unstall(ser->dev, p->epintr, Ein) < 0)
313
			dprint(2, "disk: unstall epintr: %r\n");
314
	}
315
	return 0;
316
}
317
 
318
static int
319
setctlline(Serialport *p, uchar val)
320
{
321
	Serial *ser;
322
 
323
	ser = p->s;
324
	return usbcmd(ser->dev, Rh2d | Rclass | Riface, SetCtlReq,
325
		val, 0, nil, 0);
326
}
327
 
328
static void
329
composectl(Serialport *p)
330
{
331
	if(p->rts)
332
		p->ctlstate |= CtlRTS;
333
	else
334
		p->ctlstate &= ~CtlRTS;
335
	if(p->dtr)
336
		p->ctlstate |= CtlDTR;
337
	else
338
		p->ctlstate &= ~CtlDTR;
339
}
340
 
341
static int
342
plsendlines(Serialport *p)
343
{
344
	int res;
345
 
346
	dsprint(2, "serial: sendlines: %#2.2x\n", p->ctlstate);
347
	composectl(p);
348
	res = setctlline(p, p->ctlstate);
349
	dsprint(2, "serial: sendlines res: %d\n", res);
350
	return 0;
351
}
352
 
353
static int
354
plreadstatus(Serialport *p)
355
{
356
	int nr, dfd;
357
	char err[40];
358
	uchar buf[VendorReqSz];
359
	Serial *ser;
360
 
361
	ser = p->s;
362
 
363
	qlock(ser);
364
	dsprint(2, "serial: reading from interrupt\n");
365
	dfd = p->epintr->dfd;
366
 
367
	qunlock(ser);
368
	nr = read(dfd, buf, sizeof buf);
369
	qlock(ser);
370
	snprint(err, sizeof err, "%r");
371
	dsprint(2, "serial: interrupt read %d %r\n", nr);
372
 
373
	if(nr < 0 && strstr(err, "timed out") == nil){
374
		dsprint(2, "serial: need to recover, status read %d %r\n", nr);
375
		if(serialrecover(ser, nil, nil, err) < 0){
376
			qunlock(ser);
377
			return -1;
378
		}
379
	}
380
	if(nr < 0)
381
		dsprint(2, "serial: reading status: %r");
382
	else if(nr >= sizeof buf - 1){
383
		p->dcd = buf[8] & DcdStatus;
384
		p->dsr = buf[8] & DsrStatus;
385
		p->cts = buf[8] & BreakerrStatus;
386
		p->ring = buf[8] & RingStatus;
387
		p->cts = buf[8] & CtsStatus;
388
		if(buf[8] & FrerrStatus)
389
			p->nframeerr++;
390
		if(buf[8] & ParerrStatus)
391
			p->nparityerr++;
392
		if(buf[8] & OvererrStatus)
393
			p->novererr++;
394
	} else
395
		dsprint(2, "serial: bad status read %d\n", nr);
396
	dsprint(2, "serial: finished read from interrupt %d\n", nr);
397
	qunlock(ser);
398
	return 0;
399
}
400
 
401
static void
402
statusreader(void *u)
403
{
404
	Serialport *p;
405
	Serial *ser;
406
 
407
	p = u;
408
	ser = p->s;
409
	threadsetname("statusreaderproc");
410
	while(plreadstatus(p) >= 0)
411
		;
412
	fprint(2, "serial: statusreader exiting\n");
413
	closedev(ser->dev);
414
}
415
 
416
/*
417
 * Maximum number of bytes transferred per frame
418
 * The output buffer size cannot be increased due to the size encoding
419
 */
420
 
421
static int
422
plseteps(Serialport *p)
423
{
424
	devctl(p->epin,  "maxpkt 256");
425
	devctl(p->epout, "maxpkt 256");
426
	return 0;
427
}
428
 
429
Serialops plops = {
430
	.init		= plinit,
431
	.getparam	= plgetparam,
432
	.setparam	= plsetparam,
433
	.clearpipes	= plclearpipes,
434
	.sendlines	= plsendlines,
435
	.modemctl	= plmodemctl,
436
	.setbreak	= plsetbreak,
437
	.seteps		= plseteps,
438
};