changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: nusb/serial: add support for CH340 serial converter

changeset 6840: c927ec087782
parent 6839: 30fdf5a6055d
child 6841: abba5fd1c922
author: cinap_lenrek@felloff.net
date: Sun, 21 Oct 2018 17:24:33 +0200
files: sys/src/cmd/nusb/serial/ch340.c sys/src/cmd/nusb/serial/mkfile sys/src/cmd/nusb/serial/serial.c
description: nusb/serial: add support for CH340 serial converter
     1.1new file mode 100644
     1.2--- /dev/null
     1.3+++ b/sys/src/cmd/nusb/serial/ch340.c
     1.4@@ -0,0 +1,171 @@
     1.5+#include <u.h>
     1.6+#include <libc.h>
     1.7+#include <thread.h>
     1.8+#include <fcall.h>
     1.9+#include <9p.h>
    1.10+#include "usb.h"
    1.11+#include "serial.h"
    1.12+
    1.13+enum {
    1.14+	ReadVersion	= 0x5F,
    1.15+	ReadReg		= 0x95,
    1.16+	WriteReg	= 0x9A,
    1.17+	SerialInit	= 0xA1,
    1.18+	ModemCtrl	= 0xA4,
    1.19+
    1.20+	LcrEnableRx	= 0x80,
    1.21+	LcrEnableTx	= 0x40,
    1.22+	LcrMarkSpace	= 0x20,
    1.23+	LcrParEven	= 0x10,
    1.24+	LcrEnablePar	= 0x08,
    1.25+	LcrStopBits2	= 0x04,
    1.26+
    1.27+	LcrCS8		= 0x03,
    1.28+	LcrCS7		= 0x02,
    1.29+	LcrCS6		= 0x01,
    1.30+	LcrCS5		= 0x00,
    1.31+};
    1.32+
    1.33+static Cinfo chinfo[] = {
    1.34+	{ 0x4348, 0x5523, },
    1.35+	{ 0x1a86, 0x7523, },
    1.36+	{ 0x1a86, 0x5523, },
    1.37+	{ 0,	0, },
    1.38+};
    1.39+
    1.40+static Serialops chops;
    1.41+
    1.42+int
    1.43+chprobe(Serial *ser)
    1.44+{
    1.45+	Usbdev *ud = ser->dev->usb;
    1.46+
    1.47+	if(matchid(chinfo, ud->vid, ud->did) == nil)
    1.48+		return -1;
    1.49+	ser->Serialops = chops;
    1.50+	return 0;
    1.51+}
    1.52+
    1.53+static int
    1.54+chin(Serialport *p, uint req, uint val, uint index, void *buf, int len)
    1.55+{
    1.56+	Serial *ser;
    1.57+
    1.58+	ser = p->s;
    1.59+	return usbcmd(ser->dev, Rd2h | Rvendor | Rdev, req, val, index, buf, len);
    1.60+}
    1.61+
    1.62+static int
    1.63+chout(Serialport *p, uint req, uint val, uint index)
    1.64+{
    1.65+	Serial *ser;
    1.66+
    1.67+	ser = p->s;
    1.68+	return usbcmd(ser->dev, Rh2d | Rvendor | Rdev, req, val, index, nil, 0);
    1.69+}
    1.70+
    1.71+
    1.72+static int
    1.73+chinit(Serialport *p)
    1.74+{
    1.75+	Serial *ser;
    1.76+	uchar ver[2];
    1.77+
    1.78+	ser = p->s;
    1.79+	dsprint(2, "chinit\n");
    1.80+
    1.81+	if(chin(p, ReadVersion, 0, 0, ver, sizeof(ver)) < 0)
    1.82+		return -1;
    1.83+
    1.84+	dsprint(2, "ch340: chip version: %ux.%ux\n", ver[0], ver[1]);
    1.85+
    1.86+	if(chout(p, SerialInit, 0, 0) < 0)
    1.87+		return -1;
    1.88+
    1.89+	p->baud = 115200;
    1.90+	p->stop = 1;
    1.91+	p->bits = 8;
    1.92+
    1.93+	chops.setparam(p);
    1.94+
    1.95+	/* p gets freed by closedev, the process has a reference */
    1.96+	incref(ser->dev);
    1.97+	return 0;
    1.98+}
    1.99+
   1.100+static int
   1.101+chsetbaud(Serialport *p)
   1.102+{
   1.103+	uint factor, divisor, a;
   1.104+
   1.105+	factor = 1532620800 / p->baud;
   1.106+	divisor = 3;
   1.107+
   1.108+	while((factor > 0xfff0) && divisor) {
   1.109+		factor /= 8;
   1.110+		divisor--;
   1.111+	}
   1.112+
   1.113+	if(factor > 0xfff0)
   1.114+		return -1;
   1.115+
   1.116+	factor = 0x10000 - factor;
   1.117+	a = (factor & 0xFF00) | divisor;
   1.118+	a |= 1<<7;
   1.119+	return chout(p, WriteReg, 0x1312, a);
   1.120+}
   1.121+
   1.122+static int
   1.123+chsetparam(Serialport *p)
   1.124+{
   1.125+	uint lcr;
   1.126+
   1.127+	if(p->baud > 0)
   1.128+		chsetbaud(p);
   1.129+
   1.130+	lcr = LcrEnableRx | LcrEnableTx;
   1.131+
   1.132+	switch(p->bits){
   1.133+	case 5:
   1.134+		lcr |= LcrCS5;
   1.135+		break;
   1.136+	case 6:
   1.137+		lcr |= LcrCS6;
   1.138+		break;
   1.139+	case 7:
   1.140+		lcr |= LcrCS7;
   1.141+		break;
   1.142+	case 8:
   1.143+	default:
   1.144+		lcr |= LcrCS8;
   1.145+		break;
   1.146+	}
   1.147+
   1.148+	switch(p->parity){
   1.149+	case 0:
   1.150+	default:
   1.151+		break;
   1.152+	case 1:
   1.153+		lcr |= LcrEnablePar;
   1.154+		break;
   1.155+	case 2:
   1.156+		lcr |= LcrEnablePar|LcrParEven;
   1.157+		break;
   1.158+	case 3:
   1.159+		lcr |= LcrEnablePar|LcrMarkSpace;
   1.160+		break;
   1.161+	case 4:
   1.162+		lcr |= LcrEnablePar|LcrParEven|LcrMarkSpace;
   1.163+		break;
   1.164+	};
   1.165+
   1.166+	if(p->stop == 2)
   1.167+		lcr |= LcrStopBits2;
   1.168+
   1.169+	return chout(p, WriteReg, 0x2518, lcr);
   1.170+}
   1.171+
   1.172+static Serialops chops = {
   1.173+	.init		= chinit,
   1.174+	.setparam	= chsetparam,
   1.175+};
     2.1--- a/sys/src/cmd/nusb/serial/mkfile
     2.2+++ b/sys/src/cmd/nusb/serial/mkfile
     2.3@@ -1,7 +1,7 @@
     2.4 </$objtype/mkfile
     2.5 
     2.6 TARG=serial
     2.7-OFILES=ftdi.$O serial.$O prolific.$O ucons.$O silabs.$O
     2.8+OFILES=ftdi.$O serial.$O prolific.$O ucons.$O silabs.$O ch340.$O
     2.9 HFILES=\
    2.10 	../lib/usb.h\
    2.11 	serial.h\
     3.1--- a/sys/src/cmd/nusb/serial/serial.c
     3.2+++ b/sys/src/cmd/nusb/serial/serial.c
     3.3@@ -712,6 +712,7 @@ static Srv serialfs = {
     3.4 extern int ftprobe(Serial *ser);
     3.5 extern int plprobe(Serial *ser);
     3.6 extern int slprobe(Serial *ser);
     3.7+extern int chprobe(Serial *ser);
     3.8 extern int uconsprobe(Serial *ser);
     3.9 
    3.10 void
    3.11@@ -748,7 +749,8 @@ threadmain(int argc, char* argv[])
    3.12 	if(uconsprobe(ser)
    3.13 	&& ftprobe(ser)
    3.14 	&& slprobe(ser)
    3.15-	&& plprobe(ser))
    3.16+	&& plprobe(ser)
    3.17+	&& chprobe(ser))
    3.18 		sysfatal("no serial devices found");
    3.19 
    3.20 	for(i = 0; i < ser->nifcs; i++){
    3.21@@ -769,7 +771,7 @@ threadmain(int argc, char* argv[])
    3.22 	for(i = 0; i < ser->nifcs; i++){
    3.23 		p = &ser->p[i];
    3.24 		if(serinit(p) < 0)
    3.25-			sysfatal("wserinit: %r");
    3.26+			sysfatal("serinit: %r");
    3.27 		if(ser->nifcs == 1)
    3.28 			snprint(p->name, sizeof p->name, "%s%s", p->isjtag ? "jtag" : "eiaU", dev->hname);
    3.29 		else