/* * 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,};
/*
* 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 int
slwrite(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 int
slput(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 int
slread(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 int
slinit(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 int
slgetparam(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 int
slsetparam(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 int
seteps(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 int
wait4data(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,
};