diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/usb/usbmct.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/lib/usb/usbmct.b')
| -rw-r--r-- | appl/lib/usb/usbmct.b | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/appl/lib/usb/usbmct.b b/appl/lib/usb/usbmct.b new file mode 100644 index 00000000..7384cb23 --- /dev/null +++ b/appl/lib/usb/usbmct.b @@ -0,0 +1,204 @@ +# +# Copyright © 2002 Vita Nuova Holdings Limited +# +implement UsbDriver; + +# MCT RS232 USB driver +# 'Documentation' mined from NetBSD + +include "sys.m"; + sys: Sys; +include "usb.m"; + usb: Usb; + +UMCT_SET_REQUEST: con 1640; + +REQ_SET_BAUD_RATE: con 5; +REQ_SET_LCR: con 7; + +LCR_SET_BREAK: con 16r40; +LCR_PARITY_EVEN: con 16r18; +LCR_PARITY_ODD: con 16r08; +LCR_PARITY_NONE: con 16r00; +LCR_DATA_BITS_5, LCR_DATA_BITS_6, LCR_DATA_BITS_7, LCR_DATA_BITS_8: con iota; +LCR_STOP_BITS_2: con 16r04; +LCR_STOP_BITS_1: con 16r00; + +setupfd: ref Sys->FD; +debug: con 1; + +ioreaderpid, statusreaderpid: int; + +kill(pid: int): int +{ + fd := sys->open("/prog/"+string pid+"/ctl", Sys->OWRITE); + if (fd == nil) + return -1; + if (sys->write(fd, array of byte "kill", 4) != 4) + return -1; + return 0; +} + +ioreader(pidc: chan of int, fd: ref Sys->FD) +{ + pid := sys->pctl(0, nil); + pidc <-= pid; + buf := array [256] of byte; + while ((n := sys->read(fd, buf, len buf)) >= 0) + { + sys->print("[%d]\n", n); + sys->write(sys->fildes(1), buf, n); + } + ioreaderpid = -1; +} + +statusreader(pidc: chan of int, fd: ref Sys->FD) +{ + pid := sys->pctl(0, nil); + pidc <-= pid; + buf := array [2] of byte; + while ((n := sys->read(fd, buf, len buf)) >= 0) + { + sys->print("S(%d)%.2ux%.2ux\n", n, int buf[0], int buf[1]); + } + statusreaderpid = -1; +} + +set_baud_rate(baud: int) +{ + buf := array [1] of byte; + val := 12; + case baud { + 300 => val = 1; + 1200 => val = 3; + 2400 => val = 4; + 4800 => val = 6; + 9600 => val = 8; + 19200 => val = 9; + 38400 => val = 10; + 57600 => val = 11; + 115200 => val = 12; + } + buf[0] = byte val; + if (usb->setup(setupfd, UMCT_SET_REQUEST, REQ_SET_BAUD_RATE, 0, 0, buf, nil) < 0) { + if (debug) + sys->print("usbmct: set_baud_rate failed\n"); + } +} + +set_lcr(val: int) +{ + buf := array [1] of byte; + buf[0] = byte val; + if (usb->setup(setupfd, UMCT_SET_REQUEST, REQ_SET_LCR, 0, 0, buf, nil) < 0) { + if (debug) + sys->print("usbmct: set_lcr failed\n"); + } +} + +init(usbmod: Usb, psetupfd, pctlfd: ref Sys->FD, + dev: ref Usb->Device, + conf: array of ref Usb->Configuration, path: string): int +{ + statusep, inep, outep: ref Usb->Endpt; + usb = usbmod; + sys = load Sys Sys->PATH; + setupfd = psetupfd; + # check the device descriptor to see if it really is an MCT doofer + if (dev.vid != 16r0711 || dev.did != 16r0230) { + if (debug) + sys->print("usbmct: wrong device!\n"); + return -1; + } + usb->set_configuration(setupfd, conf[0].id); + ai := hd conf[0].iface[0].altiface; + statusep = nil; + inep = nil; + outep = nil; + for (e := 0; e < len ai.ep; e++) { + ep := ai.ep[e]; + if ((ep.addr & 16r80) != 0 && (ep.attr & 3) == 3 && ep.maxpkt == 2) + statusep = ep; + else if ((ep.addr & 16r80) != 0 && (ep.attr & 3) == 3) + inep = ep; + else if ((ep.addr & 16r80) == 0 && (ep.attr & 3) == 2) + outep = ep; + } + if (statusep == nil || outep == nil || inep == nil) { + if (debug) + sys->print("usbmct: can't find sensible endpoints\n"); + return -1; + } + if ((inep.addr & 15) != (outep.addr & 15)) { + if (debug) + sys->print("usbmct: in and out endpoints not same number\n"); + return -1; + } + ioid := inep.addr & 15; + statusid := statusep.addr & 15; + if (debug) + sys->print("ep %d %d r %d 32\n", ioid, inep.maxpkt, inep.interval); + if (sys->fprint(pctlfd, "ep %d %d r %d 32", ioid, inep.maxpkt, inep.interval) < 0) { + if (debug) + sys->print("usbmct: can't create i/o endpoint (i)\n"); + return -1; + } +# if (debug) +# sys->print("ep %d %d r bulk 32\n", ioid, inep.maxpkt); +# if (sys->fprint(pctlfd, "ep %d %d r bulk 32", ioid, inep.maxpkt) < 0) { +# if (debug) +# sys->print("usbmct: can't create i/o endpoint (i)\n"); +# return -1; +# } + if (debug) + sys->print("ep %d %d w bulk 8\n", ioid, outep.maxpkt); + if (sys->fprint(pctlfd, "ep %d %d w bulk 8", ioid, outep.maxpkt) < 0) { + if (debug) + sys->print("usbmct: can't create i/o endpoint (o)\n"); + return -1; + } + iofd := sys->open(path + "ep" + string ioid + "data", Sys->ORDWR); + if (iofd == nil) { + if (debug) + sys->print("usbmct: can't open i/o endpoint\n"); + return -1; + } + if (debug) + sys->print("ep %d %d r %d 8\n", statusid, statusep.maxpkt, statusep.interval); + if (sys->fprint(pctlfd, "ep %d %d r %d 8", statusid, statusep.maxpkt, statusep.interval) < 0) { + if (debug) + sys->print("usbmct: can't create status endpoint\n"); + return -1; + } + statusfd := sys->open(path + "ep" + string statusid + "data", Sys->ORDWR); + if (statusfd == nil) { + if (debug) + sys->print("usbmct: can't open status endpoint\n"); + return -1; + } +sys->print("setting baud rate\n"); + set_baud_rate(9600); +sys->print("setting lcr\n"); + set_lcr(LCR_PARITY_NONE | LCR_DATA_BITS_8 | LCR_STOP_BITS_1); +sys->print("launching reader\n"); + pidc := chan of int; + spawn ioreader(pidc, iofd); + ioreaderpid = <- pidc; + spawn statusreader(pidc, statusfd); + statusreaderpid = <- pidc; + buf := array[512] of byte; + for (x := 0; x < 512; x += 16) { + buf[x:] = array of byte sys->sprint("%.2ux", x / 16); + buf[x + 2:] = array of byte "-0123456789-\r\n"; + } + sys->write(iofd, buf, 512); + return 0; +} + +shutdown() +{ + if (ioreaderpid >= 0) + kill(ioreaderpid); + if (statusreaderpid >= 0) + kill(statusreaderpid); +} |
