forsyth20121205-174063a80cc13 years agoHistory
453 lines · 9.9 KB · Brainfuck
RawDownload
## Copyright © 2002 Vita Nuova Holdings Limited#implement Usb; include "sys.m";	sys: Sys; include "usb.m"; include "string.m";	str: String; Proto: adt {	proto: int;	name: string;}; SubClass: adt {	subclass: int;	name: string;	proto: array of Proto;}; Class: adt {	class: int;	name: string;	subclass: array of SubClass;}; classes := array [] of {	Class(Usb->CL_AUDIO, "audio",		array [] of {			SubClass(1, "control", nil),			SubClass(2, "stream", nil),			SubClass(3, "midi", nil),		}	),	Class(Usb->CL_COMMS, "comms",		array [] of {			SubClass(1, "abstract",				array [] of {					Proto(1, "AT"),				}			)		}	),	Class(Usb->CL_HID, "hid",		array [] of {			SubClass(1, "boot",				array [] of {					Proto(1, "kbd"),					Proto(2, "mouse"),				}			)		}	),	Class(Usb->CL_PRINTER, "printer",		array [] of {			SubClass(1, "printer",				array [] of {					Proto(1, "uni"),					Proto(2, "bi"),				}			)		}	),	Class(Usb->CL_HUB, "hub",		array [] of {			SubClass(1, "hub", nil),		}	),	Class(Usb->CL_DATA, "data", nil),	Class(Usb->CL_MASS, "mass",		array [] of {			SubClass(1, "rbc",				array [] of {					Proto(0, "cbi-cc"),					Proto(1, "cbi-nocc"),					Proto(16r50, "bulkonly"),				}			),			SubClass(2, "sff-8020i/mmc-2",				array [] of {					Proto(0, "cbi-cc"),					Proto(1, "cbi-nocc"),					Proto(16r50, "bulkonly"),				}			),			SubClass(3, "qic-157",				array [] of {					Proto(0, "cbi-cc"),					Proto(1, "cbi-nocc"),					Proto(16r50, "bulkonly"),				}			),			SubClass(4, "ufi",				array [] of {					Proto(0, "cbi-cc"),					Proto(1, "cbi-nocc"),					Proto(16r50, "bulkonly"),				}			),			SubClass(5, "sff-8070i",				array [] of {					Proto(0, "cbi-cc"),					Proto(1, "cbi-nocc"),					Proto(16r50, "bulkonly"),				}			),			SubClass(6, "scsi",				array [] of {					Proto(0, "cbi-cc"),					Proto(1, "cbi-nocc"),					Proto(16r50, "bulkonly"),				}			),		}	),}; get2(b: array of byte): int{	return int b[0] | (int b[1] << 8);} put2(buf: array of byte, v: int){	buf[0] = byte v;	buf[1] = byte (v >> 8);} get4(b: array of byte): int{	return int b[0] | (int b[1] << 8) | (int b[2] << 16) | (int b[3] << 24);} put4(buf: array of byte, v: int){	buf[0] = byte v;	buf[1] = byte (v >> 8);	buf[2] = byte (v >> 16);	buf[3] = byte (v >> 24);} bigget2(b: array of byte): int{	return int b[1] | (int b[0] << 8);} bigput2(buf: array of byte, v: int){	buf[1] = byte v;	buf[0] = byte (v >> 8);} bigget4(b: array of byte): int{	return int b[3] | (int b[2] << 8) | (int b[1] << 16) | (int b[0] << 24);} bigput4(buf: array of byte, v: int){	buf[3] = byte v;	buf[2] = byte (v >> 8);	buf[1] = byte (v >> 16);	buf[0] = byte (v >> 24);} strtol(s: string, base: int): (int, string){	if (str == nil)		str = load String String->PATH;	if (base != 0)		return str->toint(s, base);	if (len s >= 2 && (s[0:2] == "0X" || s[0:2] == "0x"))		return str->toint(s[2:], 16);	if (len s > 0 && s[0:1] == "0")		return str->toint(s[1:], 8);	return str->toint(s, 10);} memset(buf: array of byte, v: int){	for (x := 0; x < len buf; x++)		buf[x] = byte v;} setupreq(setupfd: ref Sys->FD, typ, req, value, index: int, outbuf: array of byte, count: int): int{	additional: int;	if (outbuf != nil) {		additional = len outbuf;		# if there is an outbuf, then the count sent must be length of the payload		# this assumes that RH2D is set		count = additional;	}	else		additional = 0;	buf := array[8 + additional] of byte;	buf[0] = byte typ;	buf[1] = byte req;	put2(buf[2:], value);	put2(buf[4:], index);	put2(buf[6:], count);	if (additional)		buf[8:] = outbuf;	rv := sys->write(setupfd, buf, len buf);	if (rv < 0)		return -1;	if (rv != len buf)		return -1;	return rv;} setupreply(setupfd: ref Sys->FD, buf: array of byte): int{	nb := sys->read(setupfd, buf, len buf);	return nb;} setup(setupfd: ref Sys->FD, typ, req, value, index: int, outbuf: array of byte, inbuf: array of byte): int{	count: int;	if (inbuf != nil)		count = len inbuf;	else		count = 0;	if (setupreq(setupfd, typ, req, value, index, outbuf, count) < 0)		return -1;	if (count == 0)		return 0;	return setupreply(setupfd, inbuf);} get_descriptor(fd: ref Sys->FD, rtyp: int, dtyp: int, dindex: int, langid: int, buf: array of byte): int{	nr := -1;	if (setupreq(fd, RD2H | rtyp | Rdevice, GET_DESCRIPTOR, (dtyp << 8) | dindex, langid, nil, len buf) < 0		|| (nr = setupreply(fd, buf)) < 1)		return -1;	return nr;} get_standard_descriptor(fd: ref Sys->FD, dtyp: int, index: int, buf: array of byte): int{	return get_descriptor(fd, Rstandard, dtyp, index, 0, buf);} get_class_descriptor(fd: ref Sys->FD, dtyp: int, index: int, buf: array of byte): int{	return get_descriptor(fd, Rclass, dtyp, index, 0, buf);} get_vendor_descriptor(fd: ref Sys->FD, dtyp: int, index: int, buf: array of byte): int{	return get_descriptor(fd, Rvendor, dtyp, index, 0, buf);} get_status(fd: ref Sys->FD, port: int): int{	buf := array [4] of byte;	if (setupreq(fd, RD2H | Rclass | Rother, GET_STATUS, 0, port, nil, len buf) < 0	 	|| setupreply(fd, buf) < len buf)		return -1;	return get2(buf);} set_address(fd: ref Sys->FD, address: int): int{	return setupreq(fd, RH2D | Rstandard | Rdevice, SET_ADDRESS, address, 0, nil, 0);} set_configuration(fd: ref Sys->FD, n: int): int{	return setupreq(fd, RH2D | Rstandard | Rdevice, SET_CONFIGURATION, n, 0, nil, 0);} setclear_feature(fd: ref Sys->FD, rtyp: int, value: int, index: int, on: int): int{	req: int;	if (on)		req = SET_FEATURE;	else		req = CLEAR_FEATURE;	return setupreq(fd, RH2D | rtyp, req, value, index, nil, 0);} parse_conf(b: array of byte): ref Configuration{	if (len b < DCONFLEN)		return nil;	conf := ref Configuration;	conf.id = int b[5];	conf.iface = array[int b[4]] of Interface;	conf.attr = int b[7];	conf.powerma = int b[8] * 2;	return conf;} parse_iface(conf: ref Configuration, b: array of byte): ref AltInterface{	if (len b < DINTERLEN || conf == nil)		return nil;	id := int b[2];	if (id >= len conf.iface)		return nil;	ai := ref AltInterface;	ai.id = int b[3];	if (int b[4] != 0)		ai.ep = array [int b[4]] of ref Endpt;	ai.class = int b[5];	ai.subclass = int b[6];	ai.proto = int b[7];	conf.iface[id].altiface = ai :: conf.iface[id].altiface;	return ai;}	parse_endpt(conf: ref Configuration, ai: ref AltInterface, b: array of byte): ref Endpt{	if (len b < DENDPLEN || conf == nil || ai == nil || ai.ep == nil)		return nil;	for (i := 0; i < len ai.ep; i++)		if (ai.ep[i] == nil)			break;	if (i >= len ai.ep)		return nil;	ep := ref Endpt;	ai.ep[i] = ep;	ep.addr = int b[2];	ep.attr = int b[3];	ep.d2h = ep.addr & 16r80;	ep.etype = int b[3] & 3;	ep.isotype = (int b[3] >> 2) & 3;	ep.maxpkt = get2(b[4:]);	ep.interval = int b[6];	return ep;} get_parsed_configuration_descriptor(fd: ref Sys->FD, n: int): ref Configuration{	conf: ref Configuration;	altiface: ref AltInterface; 	b := array [256] of byte;	nr := get_standard_descriptor(fd, CONFIGURATION, n, b);	if (nr < 0)		return nil;	conf = nil;	altiface = nil;	for (i := 0; nr - i > 2 && b[i] > byte 0 && int b[i] <= nr - i; i += int b[i]) {		ni := i + int b[i];		case int b[i + 1] {		Usb->CONFIGURATION =>			conf = parse_conf(b[i: ni]);			if (conf == nil)				return nil;		Usb->INTERFACE =>			altiface = parse_iface(conf, b[i: ni]);			if (altiface == nil)				return nil;		Usb->ENDPOINT =>			if (parse_endpt(conf, altiface, b[i: ni]) == nil)				return nil;		}	}	if (i < nr)		sys->print("usb: residue at end of descriptors\n");	return conf;} get_parsed_device_descriptor(fd: ref Sys->FD): ref Device{	b := array [256] of byte;	nr := get_standard_descriptor(fd, DEVICE, 0, b);	if (nr < DDEVLEN) {		if (nr == 8 || nr == 16) {			memset(b[nr: DDEVLEN - 1], 0);			b[DDEVLEN - 1] = byte 1;			nr = DDEVLEN;		}		else			return nil;	}	dev := ref Device;	dev.usbmajor = int b[3];	dev.usbminor = int b[2];	dev.class = int b[4];	dev.subclass = int b[5];	dev.proto = int b[6];	dev.maxpkt0 = int b[7];	dev.vid = get2(b[8:]);	dev.did = get2(b[10:]);	dev.relmajor = int b[13];	dev.relminor = int b[12];	dev.nconf = int b[17];	return dev;} dump_configuration(fd: ref Sys->FD, conf: ref Configuration){	sys->fprint(fd, "configuration %d attr 0x%.x powerma %d\n", conf.id, conf.attr, conf.powerma);	for (i := 0; i < len conf.iface; i++) {		sys->fprint(fd, "\tinterface %d\n", i);		ail := conf.iface[i].altiface;		while (ail != nil) {			ai := hd ail;			sys->fprint(fd, "\t\t%d class %d subclass %d proto %d [%s]\n",				ai.id, ai.class, ai.subclass, ai.proto,					sclass(ai.class, ai.subclass, ai.proto));			for (e := 0; e < len ai.ep; e++) {				if (ai.ep[e] == nil) {					sys->fprint(fd, "\t\t\t missing descriptor\n");					continue;				}				sys->fprint(fd, "\t\t\t0x%.2ux attr 0x%.x maxpkt %d interval %d\n",					ai.ep[e].addr, ai.ep[e].attr, ai.ep[e].maxpkt, ai.ep[e].interval);			}			ail = tl ail;		}	}sys->fprint(fd, "done dumping\n");} sclass(class, subclass, proto: int): string{	for (c := 0; c < len classes; c++)		if (classes[c].class == class)			break;	if (c >= len classes)		return sys->sprint("%d.%d.%d", class, subclass, proto);	if (classes[c].subclass == nil)		return sys->sprint("%s.%d.%d", classes[c].name, subclass, proto);	for (sc := 0; sc < len classes[c].subclass; sc++)		if (classes[c].subclass[sc].subclass == subclass)			break;	if (sc >= len classes[c].subclass)		return sys->sprint("%s.%d.%d", classes[c].name, subclass, proto);	if (classes[c].subclass[sc].proto == nil)		return sys->sprint("%s.%s.%d", classes[c].name, classes[c].subclass[sc].name, proto);	for (p := 0; p < len classes[c].subclass[sc].proto; p++)		if (classes[c].subclass[sc].proto[p].proto == proto)			break;	if (p >= len classes[c].subclass[sc].proto)		return sys->sprint("%s.%s.%d", classes[c].name, classes[c].subclass[sc].name, proto);	return sys->sprint("%s.%s.%s", classes[c].name, classes[c].subclass[sc].name,		classes[c].subclass[sc].proto[p].name);} init(){	sys = load Sys Sys->PATH;}