9front - general discussion about 9front
 help / color / mirror / Atom feed
* new nusb/serial driver
@ 2020-06-11  7:03 Eli Cohen
  2020-06-11  7:17 ` [9front] " Alex Musolino
  0 siblings, 1 reply; 15+ messages in thread
From: Eli Cohen @ 2020-06-11  7:03 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 227 bytes --]

I have written an extremely limited and flaky CDC ACM driver for
nusb/serial. it works well enough to communicate with my Arduino Mega
2560. it would be nice if someone smarter than me with similar
hardware could look at this.

[-- Attachment #2: serial.patch --]
[-- Type: text/x-patch, Size: 1756 bytes --]

Only in /usr/glenda/nusb/serial: cdc.c
diff -ur /sys/src/cmd/nusb/serial/mkfile /usr/glenda/nusb/serial/mkfile
--- /sys/src/cmd/nusb/serial/mkfile	Fri Dec 13 00:31:34 2019
+++ /usr/glenda/nusb/serial/mkfile	Mon Jun  8 18:00:33 2020
@@ -1,7 +1,7 @@
 </$objtype/mkfile
 
 TARG=serial
-OFILES=ftdi.$O serial.$O prolific.$O ucons.$O silabs.$O ch340.$O
+OFILES=ftdi.$O serial.$O prolific.$O ucons.$O silabs.$O ch340.$O cdc.$O
 HFILES=\
 	../lib/usb.h\
 	serial.h\
diff -ur /sys/src/cmd/nusb/serial/serial.c /usr/glenda/nusb/serial/serial.c
--- /sys/src/cmd/nusb/serial/serial.c	Fri Dec 13 00:31:34 2019
+++ /usr/glenda/nusb/serial/serial.c	Wed Jun 10 21:36:54 2020
@@ -621,9 +621,12 @@
 {
 	int i, epin, epout, epintr;
 	Ep *ep, **eps;
+	int oifc;
 
+	oifc = ifc;
 	epintr = epin = epout = -1;
 
+TOPFINDEPS:
 	/*
 	 * interfc 0 means start from the start which is equiv to
 	 * iterate through endpoints probably, could be done better
@@ -644,8 +647,13 @@
 		}
 	}
 	dprint(2, "serial[%d]: ep ids: in %d out %d intr %d\n", ifc, epin, epout, epintr);
-	if(epin == -1 || epout == -1 || (ser->hasepintr && epintr == -1))
-		return -1;
+	if(epin == -1 || epout == -1 || (ser->hasepintr && epintr == -1)){
+		ifc++;
+		if(ifc > 1)
+			return -1;
+		goto TOPFINDEPS;
+	}
+	ifc = oifc;
 
 	if(openeps(&ser->p[ifc], epin, epout, epintr) < 0)
 		return -1;
@@ -714,6 +722,7 @@
 extern int slprobe(Serial *ser);
 extern int chprobe(Serial *ser);
 extern int uconsprobe(Serial *ser);
+extern int cdcprobe(Serial *ser);
 
 void
 threadmain(int argc, char* argv[])
@@ -750,7 +759,8 @@
 	&& ftprobe(ser)
 	&& slprobe(ser)
 	&& plprobe(ser)
-	&& chprobe(ser))
+	&& chprobe(ser)
+	&& cdcprobe(ser))
 		sysfatal("no serial devices found");
 
 	for(i = 0; i < ser->nifcs; i++){

[-- Attachment #3: cdc.c --]
[-- Type: text/x-csrc, Size: 2398 bytes --]

#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include <9p.h>
#include "usb.h"
#include "serial.h"

enum {
	ScACM = 2,
	AT	= 1,
};

static int
cdcsetparam(Serialport *p)
{
	int res;
	uchar vals[7];
	Serial *ser;

	ser = p->s;

	PUT4(vals, p->baud);

	vals[4] = 0;
	if(p->stop == 1)
		vals[4] = 0;
	if(p->stop == 15)
		vals[4] = 1;
	if(p->stop == 2)
		vals[4] = 2;

	vals[5] = p->parity;

	vals[6] = p->bits;

	res = usbcmd(ser->dev, Rh2d | Rclass | Riface, 0x20, 0, 0, vals, 7);

	return res;
}

static int
cdcinit(Serialport *p)
{
	Serial *ser;

	p->baud = 115200;
	p->bits = 8;
	p->parity = 0;
	p->stop = 1;

	ser = p->s;

	cdcsetparam(p);
	incref(ser->dev);
	return 0;
}

static int
cdcsetbreak(Serialport *p, int val)
{
	Serial *ser;

	ser = p->s;
	return usbcmd(ser->dev, Rh2d | Rclass | Riface, 0x23, (val != 0? 0xffff: 0x0000), 0, nil, 0);
}

static int
cdcseteps(Serialport *p)
{
	devctl(p->epin, "maxpkt 256");
	devctl(p->epout, "maxpkt 256");
	return 0;
}

static int
cdcsendlines(Serialport *p)
{
	if(p->rts)
		p->ctlstate |= 0x0002;
	else
		p->ctlstate &= ~0x0002;
	if(p->dtr)
		p->ctlstate |= 0x0001;
	else
		p->ctlstate &= ~0x0001;

	return usbcmd(p->s->dev, Rh2d | Rclass | Riface, 0x22, p->ctlstate, 0, nil, 0);
}

static int
cdcclearpipes(Serialport *p)
{
	Serial *ser;

	ser = p->s;

	if(unstall(ser->dev, p->epout, Eout) < 0)
		dprint(2, "disk: unstall epout: %r\n");
	if(unstall(ser->dev, p->epin, Ein) < 0)
		dprint(2, "disk: unstall epin: %r\n");
	if(unstall(ser->dev, p->epintr, Ein) < 0)
		dprint(2, "disk: unstall epintr: %r\n");

	return 0;
}

static int
cdcwait4data(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;
}

static Serialops cdcops = {
	.init		= cdcinit,
	.setparam	= cdcsetparam,
	.setbreak	= cdcsetbreak,
	.seteps		= cdcseteps,
	.sendlines	= cdcsendlines,
	.clearpipes	= cdcclearpipes,
	.wait4data	= cdcwait4data,
};

int
cdcprobe(Serial *ser)
{
	int i, c;
	ulong csp;
	Usbdev *ud = ser->dev->usb;
	Ep *ep;

	c = 0;
	for (i = 0; i < nelem(ud->ep); i++) {
		if ((ep = ud->ep[i]) == nil)
			continue;
		csp = ep->iface->csp;
		if (Class(csp) == Clcomms && Subclass(csp) == ScACM && Proto(csp) == AT)
			c++;
	}

	if (c == 0)
		return -1;

	ser->nifcs = 1;
	ser->outhdrsz = 0;
	ser->hasepintr = 1;
	ser->Serialops = cdcops;
	return 0;
}

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-06-13 15:37 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-11  7:03 new nusb/serial driver Eli Cohen
2020-06-11  7:17 ` [9front] " Alex Musolino
2020-06-11  7:19   ` Eli Cohen
2020-06-11  7:29     ` Alex Musolino
2020-06-11  7:36       ` Eli Cohen
2020-06-11  7:57         ` Eli Cohen
2020-06-11 12:15           ` cinap_lenrek
2020-06-11 14:08             ` Eli Cohen
2020-06-11 17:10               ` cinap_lenrek
2020-06-12  1:28                 ` Eli Cohen
2020-06-12 18:02                 ` cinap_lenrek
2020-06-12 22:15                   ` Eli Cohen
2020-06-13 14:03                     ` cinap_lenrek
2020-06-13 14:18                       ` Eli Cohen
2020-06-13 15:37                         ` 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).