155 lines · 2.8 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <thread.h>#include "usb.h"#include "usbfs.h"#include "serial.h"#include "silabs.h" static Cinfo slinfo[] = {	{ 0x10c4, 0xea60, },		/* CP210x */	{ 0x10c4, 0xea61, },		/* CP210x */	{ 0,	0, },}; enum {	Enable		= 0x00, 	Getbaud		= 0x1D,	Setbaud		= 0x1E,	Setlcr		= 0x03,	Getlcr		= 0x04,		Bitsmask	= 0x0F00,		Bitsshift	= 8,		Parmask		= 0x00F0,		Parshift	= 4,		Stopmask	= 0x000F,		Stop1		= 0x0000,		Stop1_5		= 0x0001,		Stop2		= 0x0002,}; slmatch(char *info){	Cinfo *ip;	char buf[50]; 	for(ip = slinfo; ip->vid != 0; ip++){		snprint(buf, sizeof buf, "vid %#06x did %#06x",			ip->vid, ip->did);		if(strstr(info, buf) != nil)			return 0;	}	return -1;} static intslwrite(Serialport *p, int req, void *buf, int len){	Serial *ser; 	ser = p->s;	return usbcmd(ser->dev, Rh2d | Rvendor | Riface, req, 0, p->interfc,		buf, len);} static intslput(Serialport *p, uint op, uint val){	Serial *ser; 	ser = p->s;	return usbcmd(ser->dev, Rh2d | Rvendor | Riface, op, val, p->interfc,		nil, 0);} static intslread(Serialport *p, int req, void *buf, int len){	Serial *ser; 	ser = p->s;	return usbcmd(ser->dev, Rd2h | Rvendor | Riface, req, 0, p->interfc,		buf, len);} static intslinit(Serialport *p){	Serial *ser; 	ser = p->s;	dsprint(2, "slinit\n"); 	slput(p, Enable, 1); 	slops.getparam(p); 	/* p gets freed by closedev, the process has a reference */	incref(ser->dev);	return 0;} static intslgetparam(Serialport *p){	u16int lcr; 	slread(p, Getbaud, &p->baud, sizeof(p->baud));	slread(p, Getlcr, &lcr, sizeof(lcr));	p->bits = (lcr&Bitsmask)>>Bitsshift;	p->parity = (lcr&Parmask)>>Parshift;	p->stop = (lcr&Stopmask) == Stop1? 1 : 2;	return 0;} static intslsetparam(Serialport *p){	u16int lcr; 	lcr = p->stop == 1? Stop1 : Stop2;	lcr |= (p->bits<<Bitsshift) | (p->parity<<Parshift);	slput(p, Setlcr, lcr);	slwrite(p, Setbaud, &p->baud, sizeof(p->baud));	return 0;} static intseteps(Serialport *p){	if(devctl(p->epin, "timeout 0") < 0){		fprint(2, "can't set timeout on %s: %r\n", p->epin->dir);		return -1;	}	return 0;} static intwait4data(Serialport *p, uchar *data, int count){	int n; 	qunlock(p->s);	while ((n = read(p->epin->dfd, data, count)) == 0)		;	qlock(p->s);	return n;} Serialops slops = {	.init		= slinit,	.getparam	= slgetparam,	.setparam	= slsetparam,	.seteps		= seteps,	.wait4data	= wait4data,};