#include #include #include #include #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; }