* [9front] [patch] nusb/serial: various changes
@ 2025-10-28 20:57 Arne Meyer
2025-11-15 19:12 ` cinap_lenrek
0 siblings, 1 reply; 2+ messages in thread
From: Arne Meyer @ 2025-10-28 20:57 UTC (permalink / raw)
To: 9front
[-- Attachment #1.1: Type: text/plain, Size: 803 bytes --]
These are my collected changes to nusb/serial. this is still a wip as
i'm planning on doing a few more things,
like xon/xoff flow control. I've tested all of this with real hardware,
except the jtag changes for ftdi.
Greetings,
Arne
ftdi:
fix sendlines
fix modemctl disable
ftreset clears flowcontrol, rts and dtr. update flags accordingly
fix setting of latency timer for jtag
silabs:
implement sendlines
implement modemctl
set ser->type, may be useful for future support of cp210x devs with x>2
ch340:
implement sendlines
implement modemctl
does this really work? linux driver seems to depend on rts and dtr
asserted, openbsd and freebsd don't bother at all
set ser->type to device version
serial:
make break and kn behave like devuart
when reading eiaUnctl, set dev() to driver name
[-- Attachment #1.2: Type: text/html, Size: 1780 bytes --]
[-- Attachment #2.1: Type: text/plain, Size: 351 bytes --]
from postmaster@9front:
The following attachment had content that we can't
prove to be harmless. To avoid possible automatic
execution, we changed the content headers.
The original header was:
Content-Transfer-Encoding: base64
Content-Type: text/x-diff;
name=nusbserial.diff
Content-Disposition: attachment;
filename=nusbserial.diff;
size=7187
[-- Attachment #2.2: nusbserial.diff.suspect --]
[-- Type: application/octet-stream, Size: 7187 bytes --]
diff dcbb9930ea0098005a4d8e0c6b2e299e10bf7e5f uncommitted
--- a/sys/src/cmd/nusb/serial/ch340.c
+++ b/sys/src/cmd/nusb/serial/ch340.c
@@ -24,6 +24,9 @@
LcrCS7 = 0x02,
LcrCS6 = 0x01,
LcrCS5 = 0x00,
+
+ DtrMask = 0x20,
+ RtsMask = 0x40,
};
static Cinfo chinfo[] = {
@@ -79,6 +82,9 @@
dsprint(2, "ch340: chip version: %ux.%ux\n", ver[0], ver[1]);
+ strncpy(ser->driver, "ch340", sizeof(ser->driver));
+ ser->type = ver[0];
+
if(chout(p, SerialInit, 0, 0) < 0)
return -1;
@@ -116,6 +122,31 @@
}
static int
+chsendlines(Serialport *p)
+{
+ uchar val;
+
+ val = 0;
+ if(p->rts)
+ val |= RtsMask;
+ if(p->dtr)
+ val |= DtrMask;
+
+ return chout(p, ModemCtrl, ~val, 0);
+}
+
+static int
+chmodemctl(Serialport *p, int set)
+{
+ /* XXX set dtr and rts for flow control?
+ Linux does the same. do we even need flow control then? */
+ p->rts = p->dtr = set?1:0;
+ chsendlines(p);
+ p->mctl = p->rts;
+ return chout(p, WriteReg, 0x2727, (p->mctl<<8)|p->mctl);
+}
+
+static int
chsetparam(Serialport *p)
{
uint lcr;
@@ -162,6 +193,8 @@
if(p->stop == 2)
lcr |= LcrStopBits2;
+ chmodemctl(p, p->mctl);
+
return chout(p, WriteReg, 0x2518, lcr);
}
@@ -168,5 +201,7 @@
static Serialops chops = {
.init = chinit,
.setparam = chsetparam,
+ .sendlines = chsendlines,
+ .modemctl = chmodemctl,
.findeps = findendpoints,
};
--- a/sys/src/cmd/nusb/serial/ftdi.c
+++ b/sys/src/cmd/nusb/serial/ftdi.c
@@ -887,7 +887,7 @@
{
if(set == 0){
p->mctl = 0;
- ftdiwrite(p, 0, 0, FTSETMODEMCTRL);
+ ftdiwrite(p, 0, FTDISABLEFLOWCTRL, FTSETFLOWCTRL);
return 0;
}
p->mctl = 1;
@@ -1435,12 +1435,15 @@
if(p != nil){
ftdiwrite(p, FTRESETCTLVAL, 0, FTRESET);
+ p->mctl = p->rts = p->dtr = 0;
return 0;
}
p = ser->p;
for(i = 0; i < Maxifc; i++)
- if(p[i].s != nil)
+ if(p[i].s != nil){
ftdiwrite(&p[i], FTRESETCTLVAL, 0, FTRESET);
+ p->mctl = p->rts = p->dtr = 0;
+ }
return 0;
}
@@ -1448,15 +1451,14 @@
ftinit(Serialport *p)
{
Serial *ser;
- uint timerval;
+ uchar timerval;
int res;
ser = p->s;
+ strncpy(ser->driver, "ftdi", sizeof(ser->driver));
+ ftreset(ser, p);
if(p->isjtag){
- res = ftdiwrite(p, FTSETFLOWCTRL, 0, FTDISABLEFLOWCTRL);
- if(res < 0)
- return -1;
- res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval,
+ res = ftdiread(p, FTGETLATENCYTIMER, 0, &timerval,
FTLATENCYTIMERSZ);
if(res < 0)
return -1;
@@ -1463,7 +1465,7 @@
dsprint(2, "serial: jtag latency timer is %d\n", timerval);
timerval = 2;
ftdiwrite(p, FTLATENCYDEFAULT, 0, FTSETLATENCYTIMER);
- res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval,
+ res = ftdiread(p, FTGETLATENCYTIMER, 0, &timerval,
FTLATENCYTIMERSZ);
if(res < 0)
return -1;
@@ -1492,23 +1494,21 @@
return 0;
}
-static int
-setctlline(Serialport *p, uchar val)
-{
- return ftdiwrite(p, val | (val << 8), 0, FTSETMODEMCTRL);
-}
-
static void
-updatectlst(Serialport *p, int val)
+composectl(Serialport *p)
{
if(p->rts)
- p->ctlstate |= val;
+ p->ctlstate |= CtlRTS;
else
- p->ctlstate &= ~val;
+ p->ctlstate &= ~CtlRTS;
+ if(p->dtr)
+ p->ctlstate |= CtlDTR;
+ else
+ p->ctlstate &= ~CtlDTR;
}
static int
-setctl(Serialport *p)
+ftsendlines(Serialport *p)
{
int res;
Serial *ser;
@@ -1515,35 +1515,21 @@
ser = p->s;
+ composectl(p);
if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTHETIRA1Did){
fprint(2, "serial: cannot set lines for this device\n");
- updatectlst(p, CtlRTS|CtlDTR);
- p->rts = p->dtr = 1;
return -1;
}
/* NB: you can not set DTR and RTS with one control message */
- updatectlst(p, CtlRTS);
- res = setctlline(p, (CtlRTS<<8)|p->ctlstate);
+ res = ftdiwrite(p, (CtlRTS<<8)|p->ctlstate, 0, FTSETMODEMCTRL);
if(res < 0)
return res;
- updatectlst(p, CtlDTR);
- res = setctlline(p, (CtlDTR<<8)|p->ctlstate);
+ res = ftdiwrite(p, (CtlDTR<<8)|p->ctlstate, 0, FTSETMODEMCTRL);
if(res < 0)
return res;
- return 0;
-}
-
-static int
-ftsendlines(Serialport *p)
-{
- int res;
-
- dsprint(2, "serial: sendlines: %#2.2x\n", p->ctlstate);
- res = setctl(p);
- dsprint(2, "serial: sendlines res: %d\n", res);
return 0;
}
--- a/sys/src/cmd/nusb/serial/serial.c
+++ b/sys/src/cmd/nusb/serial/serial.c
@@ -129,8 +129,11 @@
nf = tokenize(cmd, f, nelem(f));
for(i = 0; i < nf; i++){
if(strncmp(f[i], "break", 5) == 0){
- if(ser->setbreak != nil)
+ if(ser->setbreak != nil){
ser->setbreak(p, 1);
+ sleep(200);
+ ser->setbreak(p, 0);
+ }
continue;
}
@@ -173,7 +176,7 @@
case 'k':
drain++;
ser->setbreak(p, 1);
- sleep(n);
+ sleep(n<=0?200:n);
ser->setbreak(p, 0);
break;
case 'l':
@@ -291,7 +294,7 @@
s = seprint(s, e, "r%d ", p->rts);
s = seprint(s, e, "s%d ", p->stop);
s = seprint(s, e, "i%d ", p->fifo);
- s = seprint(s, e, "\ndev(%d) ", 0);
+ s = seprint(s, e, "\ndev(%s) ", ser->driver);
s = seprint(s, e, "type(%d) ", ser->type);
s = seprint(s, e, "framing(%d) ", p->nframeerr);
s = seprint(s, e, "overruns(%d) ", p->novererr);
--- a/sys/src/cmd/nusb/serial/serial.h
+++ b/sys/src/cmd/nusb/serial/serial.h
@@ -74,6 +74,7 @@
QLock;
Dev *dev; /* usb device*/
+ char driver[8]; /* driver name, e.g. ch340 */
int type; /* serial model subtype */
int recover; /* # of non-fatal recovery tries */
Serialops;
--- a/sys/src/cmd/nusb/serial/silabs.c
+++ b/sys/src/cmd/nusb/serial/silabs.c
@@ -11,6 +11,11 @@
Getbaud = 0x1D,
Setbaud = 0x1E,
+ Setflow = 0x13,
+ Flowdtron = 0x01,
+ Flowctshs = 0x08,
+ Flowrtson = 0x40,
+ Flowrtshs = 0x80,
Setlcr = 0x03,
Getlcr = 0x04,
Bitsmask = 0x0F00,
@@ -21,6 +26,9 @@
Stop1 = 0x0000,
Stop1_5 = 0x0001,
Stop2 = 0x0002,
+ Setctrl = 0x07,
+ Dtron = 0x0001,
+ Rtson = 0x0002,
};
static Cinfo slinfo[] = {
@@ -72,6 +80,23 @@
}
static int
+slgettype(Serialport *p)
+{
+ Serial *ser;
+ uchar buf;
+ int res;
+
+ ser = p->s;
+ res = usbcmd(ser->dev, Rd2h | Rvendor | Riface, 0xff, 0x370B, p->interfc,
+ &buf, 1);
+
+ if(res < 0)
+ return 0xff;
+
+ return buf;
+}
+
+static int
slinit(Serialport *p)
{
Serial *ser;
@@ -79,6 +104,9 @@
ser = p->s;
dsprint(2, "slinit\n");
+ strncpy(ser->driver, "silabs", sizeof(ser->driver));
+ ser->type = slgettype(p);
+
slput(p, Enable, 1);
slops.getparam(p);
@@ -114,6 +142,38 @@
}
static int
+slsendlines(Serialport *p)
+{
+ u16int ctrl;
+
+ ctrl = (p->dtr? Dtron : 0) | Dtron << 8;
+ ctrl |= (p->rts? Rtson : 0) | Rtson << 8;
+
+ slput(p, Setctrl, ctrl);
+ return 0;
+}
+
+static
+slmodemctl(Serialport *p, int set)
+{
+ uchar flow[4*4];
+
+ memset(flow, 0, sizeof flow);
+
+ if(set){
+ p->mctl = 1;
+ PUT4(flow, (p->dtr?Flowdtron:0) | Flowctshs);
+ PUT4(flow+4, Flowrtshs);
+ }else{
+ p->mctl = 0;
+ PUT4(flow, (p->dtr)?Flowdtron:0);
+ PUT4(flow+4, (p->rts)?Flowrtson:0);
+ }
+ slwrite(p, Setflow, flow, sizeof flow);
+ return 0;
+}
+
+static int
wait4data(Serialport *p, uchar *data, int count)
{
int n;
@@ -129,6 +189,8 @@
.init = slinit,
.getparam = slgetparam,
.setparam = slsetparam,
+ .sendlines = slsendlines,
+ .modemctl = slmodemctl,
.wait4data = wait4data,
.findeps = findendpoints,
};
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [9front] [patch] nusb/serial: various changes
2025-10-28 20:57 [9front] [patch] nusb/serial: various changes Arne Meyer
@ 2025-11-15 19:12 ` cinap_lenrek
0 siblings, 0 replies; 2+ messages in thread
From: cinap_lenrek @ 2025-11-15 19:12 UTC (permalink / raw)
To: 9front
Looks good!
Thank you!
--
cinap
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-11-15 19:15 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-28 20:57 [9front] [patch] nusb/serial: various changes Arne Meyer
2025-11-15 19:12 ` cinap_lenrek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).