1# 2# Copyright © 2002 Vita Nuova Holdings Limited 3# 4implement UsbDriver; 5 6# MCT RS232 USB driver 7# 'Documentation' mined from NetBSD 8 9include "sys.m"; 10 sys: Sys; 11include "usb.m"; 12 usb: Usb; 13 14UMCT_SET_REQUEST: con 1640; 15 16REQ_SET_BAUD_RATE: con 5; 17REQ_SET_LCR: con 7; 18 19LCR_SET_BREAK: con 16r40; 20LCR_PARITY_EVEN: con 16r18; 21LCR_PARITY_ODD: con 16r08; 22LCR_PARITY_NONE: con 16r00; 23LCR_DATA_BITS_5, LCR_DATA_BITS_6, LCR_DATA_BITS_7, LCR_DATA_BITS_8: con iota; 24LCR_STOP_BITS_2: con 16r04; 25LCR_STOP_BITS_1: con 16r00; 26 27setupfd: ref Sys->FD; 28debug: con 1; 29 30ioreaderpid, statusreaderpid: int; 31 32kill(pid: int): int 33{ 34 fd := sys->open("/prog/"+string pid+"/ctl", Sys->OWRITE); 35 if (fd == nil) 36 return -1; 37 if (sys->write(fd, array of byte "kill", 4) != 4) 38 return -1; 39 return 0; 40} 41 42ioreader(pidc: chan of int, fd: ref Sys->FD) 43{ 44 pid := sys->pctl(0, nil); 45 pidc <-= pid; 46 buf := array [256] of byte; 47 while ((n := sys->read(fd, buf, len buf)) >= 0) 48 { 49 sys->print("[%d]\n", n); 50 sys->write(sys->fildes(1), buf, n); 51 } 52 ioreaderpid = -1; 53} 54 55statusreader(pidc: chan of int, fd: ref Sys->FD) 56{ 57 pid := sys->pctl(0, nil); 58 pidc <-= pid; 59 buf := array [2] of byte; 60 while ((n := sys->read(fd, buf, len buf)) >= 0) 61 { 62 sys->print("S(%d)%.2ux%.2ux\n", n, int buf[0], int buf[1]); 63 } 64 statusreaderpid = -1; 65} 66 67set_baud_rate(baud: int) 68{ 69 buf := array [1] of byte; 70 val := 12; 71 case baud { 72 300 => val = 1; 73 1200 => val = 3; 74 2400 => val = 4; 75 4800 => val = 6; 76 9600 => val = 8; 77 19200 => val = 9; 78 38400 => val = 10; 79 57600 => val = 11; 80 115200 => val = 12; 81 } 82 buf[0] = byte val; 83 if (usb->setup(setupfd, UMCT_SET_REQUEST, REQ_SET_BAUD_RATE, 0, 0, buf, nil) < 0) { 84 if (debug) 85 sys->print("usbmct: set_baud_rate failed\n"); 86 } 87} 88 89set_lcr(val: int) 90{ 91 buf := array [1] of byte; 92 buf[0] = byte val; 93 if (usb->setup(setupfd, UMCT_SET_REQUEST, REQ_SET_LCR, 0, 0, buf, nil) < 0) { 94 if (debug) 95 sys->print("usbmct: set_lcr failed\n"); 96 } 97} 98 99init(usbmod: Usb, psetupfd, pctlfd: ref Sys->FD, 100 dev: ref Usb->Device, 101 conf: array of ref Usb->Configuration, path: string): int 102{ 103 statusep, inep, outep: ref Usb->Endpt; 104 usb = usbmod; 105 sys = load Sys Sys->PATH; 106 setupfd = psetupfd; 107 # check the device descriptor to see if it really is an MCT doofer 108 if (dev.vid != 16r0711 || dev.did != 16r0230) { 109 if (debug) 110 sys->print("usbmct: wrong device!\n"); 111 return -1; 112 } 113 usb->set_configuration(setupfd, conf[0].id); 114 ai := hd conf[0].iface[0].altiface; 115 statusep = nil; 116 inep = nil; 117 outep = nil; 118 for (e := 0; e < len ai.ep; e++) { 119 ep := ai.ep[e]; 120 if ((ep.addr & 16r80) != 0 && (ep.attr & 3) == 3 && ep.maxpkt == 2) 121 statusep = ep; 122 else if ((ep.addr & 16r80) != 0 && (ep.attr & 3) == 3) 123 inep = ep; 124 else if ((ep.addr & 16r80) == 0 && (ep.attr & 3) == 2) 125 outep = ep; 126 } 127 if (statusep == nil || outep == nil || inep == nil) { 128 if (debug) 129 sys->print("usbmct: can't find sensible endpoints\n"); 130 return -1; 131 } 132 if ((inep.addr & 15) != (outep.addr & 15)) { 133 if (debug) 134 sys->print("usbmct: in and out endpoints not same number\n"); 135 return -1; 136 } 137 ioid := inep.addr & 15; 138 statusid := statusep.addr & 15; 139 if (debug) 140 sys->print("ep %d %d r %d 32\n", ioid, inep.maxpkt, inep.interval); 141 if (sys->fprint(pctlfd, "ep %d %d r %d 32", ioid, inep.maxpkt, inep.interval) < 0) { 142 if (debug) 143 sys->print("usbmct: can't create i/o endpoint (i)\n"); 144 return -1; 145 } 146# if (debug) 147# sys->print("ep %d %d r bulk 32\n", ioid, inep.maxpkt); 148# if (sys->fprint(pctlfd, "ep %d %d r bulk 32", ioid, inep.maxpkt) < 0) { 149# if (debug) 150# sys->print("usbmct: can't create i/o endpoint (i)\n"); 151# return -1; 152# } 153 if (debug) 154 sys->print("ep %d %d w bulk 8\n", ioid, outep.maxpkt); 155 if (sys->fprint(pctlfd, "ep %d %d w bulk 8", ioid, outep.maxpkt) < 0) { 156 if (debug) 157 sys->print("usbmct: can't create i/o endpoint (o)\n"); 158 return -1; 159 } 160 iofd := sys->open(path + "ep" + string ioid + "data", Sys->ORDWR); 161 if (iofd == nil) { 162 if (debug) 163 sys->print("usbmct: can't open i/o endpoint\n"); 164 return -1; 165 } 166 if (debug) 167 sys->print("ep %d %d r %d 8\n", statusid, statusep.maxpkt, statusep.interval); 168 if (sys->fprint(pctlfd, "ep %d %d r %d 8", statusid, statusep.maxpkt, statusep.interval) < 0) { 169 if (debug) 170 sys->print("usbmct: can't create status endpoint\n"); 171 return -1; 172 } 173 statusfd := sys->open(path + "ep" + string statusid + "data", Sys->ORDWR); 174 if (statusfd == nil) { 175 if (debug) 176 sys->print("usbmct: can't open status endpoint\n"); 177 return -1; 178 } 179sys->print("setting baud rate\n"); 180 set_baud_rate(9600); 181sys->print("setting lcr\n"); 182 set_lcr(LCR_PARITY_NONE | LCR_DATA_BITS_8 | LCR_STOP_BITS_1); 183sys->print("launching reader\n"); 184 pidc := chan of int; 185 spawn ioreader(pidc, iofd); 186 ioreaderpid = <- pidc; 187 spawn statusreader(pidc, statusfd); 188 statusreaderpid = <- pidc; 189 buf := array[512] of byte; 190 for (x := 0; x < 512; x += 16) { 191 buf[x:] = array of byte sys->sprint("%.2ux", x / 16); 192 buf[x + 2:] = array of byte "-0123456789-\r\n"; 193 } 194 sys->write(iofd, buf, 512); 195 return 0; 196} 197 198shutdown() 199{ 200 if (ioreaderpid >= 0) 201 kill(ioreaderpid); 202 if (statusreaderpid >= 0) 203 kill(statusreaderpid); 204} 205