xref: /inferno-os/appl/lib/usb/usb.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth#
2*37da2899SCharles.Forsyth# Copyright © 2002 Vita Nuova Holdings Limited
3*37da2899SCharles.Forsyth#
4*37da2899SCharles.Forsythimplement Usb;
5*37da2899SCharles.Forsyth
6*37da2899SCharles.Forsythinclude "sys.m";
7*37da2899SCharles.Forsyth	sys: Sys;
8*37da2899SCharles.Forsyth
9*37da2899SCharles.Forsythinclude "usb.m";
10*37da2899SCharles.Forsyth
11*37da2899SCharles.Forsythinclude "string.m";
12*37da2899SCharles.Forsyth	str: String;
13*37da2899SCharles.Forsyth
14*37da2899SCharles.ForsythProto: adt {
15*37da2899SCharles.Forsyth	proto: int;
16*37da2899SCharles.Forsyth	name: string;
17*37da2899SCharles.Forsyth};
18*37da2899SCharles.Forsyth
19*37da2899SCharles.ForsythSubClass: adt {
20*37da2899SCharles.Forsyth	subclass: int;
21*37da2899SCharles.Forsyth	name: string;
22*37da2899SCharles.Forsyth	proto: array of Proto;
23*37da2899SCharles.Forsyth};
24*37da2899SCharles.Forsyth
25*37da2899SCharles.ForsythClass: adt {
26*37da2899SCharles.Forsyth	class: int;
27*37da2899SCharles.Forsyth	name: string;
28*37da2899SCharles.Forsyth	subclass: array of SubClass;
29*37da2899SCharles.Forsyth};
30*37da2899SCharles.Forsyth
31*37da2899SCharles.Forsythclasses := array [] of {
32*37da2899SCharles.Forsyth	Class(Usb->CL_AUDIO, "audio",
33*37da2899SCharles.Forsyth		array [] of {
34*37da2899SCharles.Forsyth			SubClass(1, "control", nil),
35*37da2899SCharles.Forsyth			SubClass(2, "stream", nil),
36*37da2899SCharles.Forsyth			SubClass(3, "midi", nil),
37*37da2899SCharles.Forsyth		}
38*37da2899SCharles.Forsyth	),
39*37da2899SCharles.Forsyth	Class(Usb->CL_COMMS, "comms",
40*37da2899SCharles.Forsyth		array [] of {
41*37da2899SCharles.Forsyth			SubClass(1, "abstract",
42*37da2899SCharles.Forsyth				array [] of {
43*37da2899SCharles.Forsyth					Proto(1, "AT"),
44*37da2899SCharles.Forsyth				}
45*37da2899SCharles.Forsyth			)
46*37da2899SCharles.Forsyth		}
47*37da2899SCharles.Forsyth	),
48*37da2899SCharles.Forsyth	Class(Usb->CL_HID, "hid",
49*37da2899SCharles.Forsyth		array [] of {
50*37da2899SCharles.Forsyth			SubClass(1, "boot",
51*37da2899SCharles.Forsyth				array [] of {
52*37da2899SCharles.Forsyth					Proto(1, "kbd"),
53*37da2899SCharles.Forsyth					Proto(2, "mouse"),
54*37da2899SCharles.Forsyth				}
55*37da2899SCharles.Forsyth			)
56*37da2899SCharles.Forsyth		}
57*37da2899SCharles.Forsyth	),
58*37da2899SCharles.Forsyth	Class(Usb->CL_PRINTER, "printer",
59*37da2899SCharles.Forsyth		array [] of {
60*37da2899SCharles.Forsyth			SubClass(1, "printer",
61*37da2899SCharles.Forsyth				array [] of {
62*37da2899SCharles.Forsyth					Proto(1, "uni"),
63*37da2899SCharles.Forsyth					Proto(2, "bi"),
64*37da2899SCharles.Forsyth				}
65*37da2899SCharles.Forsyth			)
66*37da2899SCharles.Forsyth		}
67*37da2899SCharles.Forsyth	),
68*37da2899SCharles.Forsyth	Class(Usb->CL_HUB, "hub",
69*37da2899SCharles.Forsyth		array [] of {
70*37da2899SCharles.Forsyth			SubClass(1, "hub", nil),
71*37da2899SCharles.Forsyth		}
72*37da2899SCharles.Forsyth	),
73*37da2899SCharles.Forsyth	Class(Usb->CL_DATA, "data", nil),
74*37da2899SCharles.Forsyth	Class(Usb->CL_MASS, "mass",
75*37da2899SCharles.Forsyth		array [] of {
76*37da2899SCharles.Forsyth			SubClass(1, "rbc",
77*37da2899SCharles.Forsyth				array [] of {
78*37da2899SCharles.Forsyth					Proto(0, "cbi-cc"),
79*37da2899SCharles.Forsyth					Proto(1, "cbi-nocc"),
80*37da2899SCharles.Forsyth					Proto(16r50, "bulkonly"),
81*37da2899SCharles.Forsyth				}
82*37da2899SCharles.Forsyth			),
83*37da2899SCharles.Forsyth			SubClass(2, "sff-8020i/mmc-2",
84*37da2899SCharles.Forsyth				array [] of {
85*37da2899SCharles.Forsyth					Proto(0, "cbi-cc"),
86*37da2899SCharles.Forsyth					Proto(1, "cbi-nocc"),
87*37da2899SCharles.Forsyth					Proto(16r50, "bulkonly"),
88*37da2899SCharles.Forsyth				}
89*37da2899SCharles.Forsyth			),
90*37da2899SCharles.Forsyth			SubClass(3, "qic-157",
91*37da2899SCharles.Forsyth				array [] of {
92*37da2899SCharles.Forsyth					Proto(0, "cbi-cc"),
93*37da2899SCharles.Forsyth					Proto(1, "cbi-nocc"),
94*37da2899SCharles.Forsyth					Proto(16r50, "bulkonly"),
95*37da2899SCharles.Forsyth				}
96*37da2899SCharles.Forsyth			),
97*37da2899SCharles.Forsyth			SubClass(4, "ufi",
98*37da2899SCharles.Forsyth				array [] of {
99*37da2899SCharles.Forsyth					Proto(0, "cbi-cc"),
100*37da2899SCharles.Forsyth					Proto(1, "cbi-nocc"),
101*37da2899SCharles.Forsyth					Proto(16r50, "bulkonly"),
102*37da2899SCharles.Forsyth				}
103*37da2899SCharles.Forsyth			),
104*37da2899SCharles.Forsyth			SubClass(5, "sff-8070i",
105*37da2899SCharles.Forsyth				array [] of {
106*37da2899SCharles.Forsyth					Proto(0, "cbi-cc"),
107*37da2899SCharles.Forsyth					Proto(1, "cbi-nocc"),
108*37da2899SCharles.Forsyth					Proto(16r50, "bulkonly"),
109*37da2899SCharles.Forsyth				}
110*37da2899SCharles.Forsyth			),
111*37da2899SCharles.Forsyth			SubClass(6, "scsi",
112*37da2899SCharles.Forsyth				array [] of {
113*37da2899SCharles.Forsyth					Proto(0, "cbi-cc"),
114*37da2899SCharles.Forsyth					Proto(1, "cbi-nocc"),
115*37da2899SCharles.Forsyth					Proto(16r50, "bulkonly"),
116*37da2899SCharles.Forsyth				}
117*37da2899SCharles.Forsyth			),
118*37da2899SCharles.Forsyth		}
119*37da2899SCharles.Forsyth	),
120*37da2899SCharles.Forsyth};
121*37da2899SCharles.Forsyth
122*37da2899SCharles.Forsythget2(b: array of byte): int
123*37da2899SCharles.Forsyth{
124*37da2899SCharles.Forsyth	return int b[0] | (int b[1] << 8);
125*37da2899SCharles.Forsyth}
126*37da2899SCharles.Forsyth
127*37da2899SCharles.Forsythput2(buf: array of byte, v: int)
128*37da2899SCharles.Forsyth{
129*37da2899SCharles.Forsyth	buf[0] = byte v;
130*37da2899SCharles.Forsyth	buf[1] = byte (v >> 8);
131*37da2899SCharles.Forsyth}
132*37da2899SCharles.Forsyth
133*37da2899SCharles.Forsythget4(b: array of byte): int
134*37da2899SCharles.Forsyth{
135*37da2899SCharles.Forsyth	return int b[0] | (int b[1] << 8) | (int b[2] << 16) | (int b[3] << 24);
136*37da2899SCharles.Forsyth}
137*37da2899SCharles.Forsyth
138*37da2899SCharles.Forsythput4(buf: array of byte, v: int)
139*37da2899SCharles.Forsyth{
140*37da2899SCharles.Forsyth	buf[0] = byte v;
141*37da2899SCharles.Forsyth	buf[1] = byte (v >> 8);
142*37da2899SCharles.Forsyth	buf[2] = byte (v >> 16);
143*37da2899SCharles.Forsyth	buf[3] = byte (v >> 24);
144*37da2899SCharles.Forsyth}
145*37da2899SCharles.Forsyth
146*37da2899SCharles.Forsythbigget2(b: array of byte): int
147*37da2899SCharles.Forsyth{
148*37da2899SCharles.Forsyth	return int b[1] | (int b[0] << 8);
149*37da2899SCharles.Forsyth}
150*37da2899SCharles.Forsyth
151*37da2899SCharles.Forsythbigput2(buf: array of byte, v: int)
152*37da2899SCharles.Forsyth{
153*37da2899SCharles.Forsyth	buf[1] = byte v;
154*37da2899SCharles.Forsyth	buf[0] = byte (v >> 8);
155*37da2899SCharles.Forsyth}
156*37da2899SCharles.Forsyth
157*37da2899SCharles.Forsythbigget4(b: array of byte): int
158*37da2899SCharles.Forsyth{
159*37da2899SCharles.Forsyth	return int b[3] | (int b[2] << 8) | (int b[1] << 16) | (int b[0] << 24);
160*37da2899SCharles.Forsyth}
161*37da2899SCharles.Forsyth
162*37da2899SCharles.Forsythbigput4(buf: array of byte, v: int)
163*37da2899SCharles.Forsyth{
164*37da2899SCharles.Forsyth	buf[3] = byte v;
165*37da2899SCharles.Forsyth	buf[2] = byte (v >> 8);
166*37da2899SCharles.Forsyth	buf[1] = byte (v >> 16);
167*37da2899SCharles.Forsyth	buf[0] = byte (v >> 24);
168*37da2899SCharles.Forsyth}
169*37da2899SCharles.Forsyth
170*37da2899SCharles.Forsythstrtol(s: string, base: int): (int, string)
171*37da2899SCharles.Forsyth{
172*37da2899SCharles.Forsyth	if (str == nil)
173*37da2899SCharles.Forsyth		str = load String String->PATH;
174*37da2899SCharles.Forsyth	if (base != 0)
175*37da2899SCharles.Forsyth		return str->toint(s, base);
176*37da2899SCharles.Forsyth	if (len s >= 2 && (s[0:2] == "0X" || s[0:2] == "0x"))
177*37da2899SCharles.Forsyth		return str->toint(s[2:], 16);
178*37da2899SCharles.Forsyth	if (len s > 0 && s[0:1] == "0")
179*37da2899SCharles.Forsyth		return str->toint(s[1:], 8);
180*37da2899SCharles.Forsyth	return str->toint(s, 10);
181*37da2899SCharles.Forsyth}
182*37da2899SCharles.Forsyth
183*37da2899SCharles.Forsythmemset(buf: array of byte, v: int)
184*37da2899SCharles.Forsyth{
185*37da2899SCharles.Forsyth	for (x := 0; x < len buf; x++)
186*37da2899SCharles.Forsyth		buf[x] = byte v;
187*37da2899SCharles.Forsyth}
188*37da2899SCharles.Forsyth
189*37da2899SCharles.Forsythsetupreq(setupfd: ref Sys->FD, typ, req, value, index: int, outbuf: array of byte, count: int): int
190*37da2899SCharles.Forsyth{
191*37da2899SCharles.Forsyth	additional: int;
192*37da2899SCharles.Forsyth	if (outbuf != nil) {
193*37da2899SCharles.Forsyth		additional = len outbuf;
194*37da2899SCharles.Forsyth		# if there is an outbuf, then the count sent must be length of the payload
195*37da2899SCharles.Forsyth		# this assumes that RH2D is set
196*37da2899SCharles.Forsyth		count = additional;
197*37da2899SCharles.Forsyth	}
198*37da2899SCharles.Forsyth	else
199*37da2899SCharles.Forsyth		additional = 0;
200*37da2899SCharles.Forsyth	buf := array[8 + additional] of byte;
201*37da2899SCharles.Forsyth	buf[0] = byte typ;
202*37da2899SCharles.Forsyth	buf[1] = byte req;
203*37da2899SCharles.Forsyth	put2(buf[2:], value);
204*37da2899SCharles.Forsyth	put2(buf[4:], index);
205*37da2899SCharles.Forsyth	put2(buf[6:], count);
206*37da2899SCharles.Forsyth	if (additional)
207*37da2899SCharles.Forsyth		buf[8:] = outbuf;
208*37da2899SCharles.Forsyth	rv := sys->write(setupfd, buf, len buf);
209*37da2899SCharles.Forsyth	if (rv < 0)
210*37da2899SCharles.Forsyth		return -1;
211*37da2899SCharles.Forsyth	if (rv != len buf)
212*37da2899SCharles.Forsyth		return -1;
213*37da2899SCharles.Forsyth	return rv;
214*37da2899SCharles.Forsyth}
215*37da2899SCharles.Forsyth
216*37da2899SCharles.Forsythsetupreply(setupfd: ref Sys->FD, buf: array of byte): int
217*37da2899SCharles.Forsyth{
218*37da2899SCharles.Forsyth	nb := sys->read(setupfd, buf, len buf);
219*37da2899SCharles.Forsyth	return nb;
220*37da2899SCharles.Forsyth}
221*37da2899SCharles.Forsyth
222*37da2899SCharles.Forsythsetup(setupfd: ref Sys->FD, typ, req, value, index: int, outbuf: array of byte, inbuf: array of byte): int
223*37da2899SCharles.Forsyth{
224*37da2899SCharles.Forsyth	count: int;
225*37da2899SCharles.Forsyth	if (inbuf != nil)
226*37da2899SCharles.Forsyth		count = len inbuf;
227*37da2899SCharles.Forsyth	else
228*37da2899SCharles.Forsyth		count = 0;
229*37da2899SCharles.Forsyth	if (setupreq(setupfd, typ, req, value, index, outbuf, count) < 0)
230*37da2899SCharles.Forsyth		return -1;
231*37da2899SCharles.Forsyth	if (count == 0)
232*37da2899SCharles.Forsyth		return 0;
233*37da2899SCharles.Forsyth	return setupreply(setupfd, inbuf);
234*37da2899SCharles.Forsyth}
235*37da2899SCharles.Forsyth
236*37da2899SCharles.Forsythget_descriptor(fd: ref Sys->FD, rtyp: int, dtyp: int, dindex: int, langid: int, buf: array of byte): int
237*37da2899SCharles.Forsyth{
238*37da2899SCharles.Forsyth	nr := -1;
239*37da2899SCharles.Forsyth	if (setupreq(fd, RD2H | rtyp | Rdevice, GET_DESCRIPTOR, (dtyp << 8) | dindex, langid, nil, len buf) < 0
240*37da2899SCharles.Forsyth		|| (nr = setupreply(fd, buf)) < 1)
241*37da2899SCharles.Forsyth		return -1;
242*37da2899SCharles.Forsyth	return nr;
243*37da2899SCharles.Forsyth}
244*37da2899SCharles.Forsyth
245*37da2899SCharles.Forsythget_standard_descriptor(fd: ref Sys->FD, dtyp: int, index: int, buf: array of byte): int
246*37da2899SCharles.Forsyth{
247*37da2899SCharles.Forsyth	return get_descriptor(fd, Rstandard, dtyp, index, 0, buf);
248*37da2899SCharles.Forsyth}
249*37da2899SCharles.Forsyth
250*37da2899SCharles.Forsythget_class_descriptor(fd: ref Sys->FD, dtyp: int, index: int, buf: array of byte): int
251*37da2899SCharles.Forsyth{
252*37da2899SCharles.Forsyth	return get_descriptor(fd, Rclass, dtyp, index, 0, buf);
253*37da2899SCharles.Forsyth}
254*37da2899SCharles.Forsyth
255*37da2899SCharles.Forsythget_vendor_descriptor(fd: ref Sys->FD, dtyp: int, index: int, buf: array of byte): int
256*37da2899SCharles.Forsyth{
257*37da2899SCharles.Forsyth	return get_descriptor(fd, Rvendor, dtyp, index, 0, buf);
258*37da2899SCharles.Forsyth}
259*37da2899SCharles.Forsyth
260*37da2899SCharles.Forsythget_status(fd: ref Sys->FD, port: int): int
261*37da2899SCharles.Forsyth{
262*37da2899SCharles.Forsyth	buf := array [4] of byte;
263*37da2899SCharles.Forsyth	if (setupreq(fd, RD2H | Rclass | Rother, GET_STATUS, 0, port, nil, len buf) < 0
264*37da2899SCharles.Forsyth	 	|| setupreply(fd, buf) < len buf)
265*37da2899SCharles.Forsyth		return -1;
266*37da2899SCharles.Forsyth	return get2(buf);
267*37da2899SCharles.Forsyth}
268*37da2899SCharles.Forsyth
269*37da2899SCharles.Forsythset_address(fd: ref Sys->FD, address: int): int
270*37da2899SCharles.Forsyth{
271*37da2899SCharles.Forsyth	return setupreq(fd, RH2D | Rstandard | Rdevice, SET_ADDRESS, address, 0, nil, 0);
272*37da2899SCharles.Forsyth}
273*37da2899SCharles.Forsyth
274*37da2899SCharles.Forsythset_configuration(fd: ref Sys->FD, n: int): int
275*37da2899SCharles.Forsyth{
276*37da2899SCharles.Forsyth	return setupreq(fd, RH2D | Rstandard | Rdevice, SET_CONFIGURATION, n, 0, nil, 0);
277*37da2899SCharles.Forsyth}
278*37da2899SCharles.Forsyth
279*37da2899SCharles.Forsythsetclear_feature(fd: ref Sys->FD, rtyp: int, value: int, index: int, on: int): int
280*37da2899SCharles.Forsyth{
281*37da2899SCharles.Forsyth	req: int;
282*37da2899SCharles.Forsyth	if (on)
283*37da2899SCharles.Forsyth		req = SET_FEATURE;
284*37da2899SCharles.Forsyth	else
285*37da2899SCharles.Forsyth		req = CLEAR_FEATURE;
286*37da2899SCharles.Forsyth	return setupreq(fd, RH2D | rtyp, req, value, index, nil, 0);
287*37da2899SCharles.Forsyth}
288*37da2899SCharles.Forsyth
289*37da2899SCharles.Forsythparse_conf(b: array of byte): ref Configuration
290*37da2899SCharles.Forsyth{
291*37da2899SCharles.Forsyth	if (len b < DCONFLEN)
292*37da2899SCharles.Forsyth		return nil;
293*37da2899SCharles.Forsyth	conf := ref Configuration;
294*37da2899SCharles.Forsyth	conf.id = int b[5];
295*37da2899SCharles.Forsyth	conf.iface = array[int b[4]] of Interface;
296*37da2899SCharles.Forsyth	conf.attr = int b[7];
297*37da2899SCharles.Forsyth	conf.powerma = int b[8] * 2;
298*37da2899SCharles.Forsyth	return conf;
299*37da2899SCharles.Forsyth}
300*37da2899SCharles.Forsyth
301*37da2899SCharles.Forsythparse_iface(conf: ref Configuration, b: array of byte): ref AltInterface
302*37da2899SCharles.Forsyth{
303*37da2899SCharles.Forsyth	if (len b < DINTERLEN || conf == nil)
304*37da2899SCharles.Forsyth		return nil;
305*37da2899SCharles.Forsyth	id := int b[2];
306*37da2899SCharles.Forsyth	if (id >= len conf.iface)
307*37da2899SCharles.Forsyth		return nil;
308*37da2899SCharles.Forsyth	ai := ref AltInterface;
309*37da2899SCharles.Forsyth	ai.id = int b[3];
310*37da2899SCharles.Forsyth	if (int b[4] != 0)
311*37da2899SCharles.Forsyth		ai.ep = array [int b[4]] of ref Endpt;
312*37da2899SCharles.Forsyth	ai.class = int b[5];
313*37da2899SCharles.Forsyth	ai.subclass = int b[6];
314*37da2899SCharles.Forsyth	ai.proto = int b[7];
315*37da2899SCharles.Forsyth	conf.iface[id].altiface = ai :: conf.iface[id].altiface;
316*37da2899SCharles.Forsyth	return ai;
317*37da2899SCharles.Forsyth}
318*37da2899SCharles.Forsyth
319*37da2899SCharles.Forsythparse_endpt(conf: ref Configuration, ai: ref AltInterface, b: array of byte): ref Endpt
320*37da2899SCharles.Forsyth{
321*37da2899SCharles.Forsyth	if (len b < DENDPLEN || conf == nil || ai == nil || ai.ep == nil)
322*37da2899SCharles.Forsyth		return nil;
323*37da2899SCharles.Forsyth	for (i := 0; i < len ai.ep; i++)
324*37da2899SCharles.Forsyth		if (ai.ep[i] == nil)
325*37da2899SCharles.Forsyth			break;
326*37da2899SCharles.Forsyth	if (i >= len ai.ep)
327*37da2899SCharles.Forsyth		return nil;
328*37da2899SCharles.Forsyth	ep := ref Endpt;
329*37da2899SCharles.Forsyth	ai.ep[i] = ep;
330*37da2899SCharles.Forsyth	ep.addr = int b[2];
331*37da2899SCharles.Forsyth	ep.attr = int b[3];
332*37da2899SCharles.Forsyth	ep.d2h = ep.addr & 16r80;
333*37da2899SCharles.Forsyth	ep.etype = int b[3] & 3;
334*37da2899SCharles.Forsyth	ep.isotype = (int b[3] >> 2) & 3;
335*37da2899SCharles.Forsyth	ep.maxpkt = get2(b[4:]);
336*37da2899SCharles.Forsyth	ep.interval = int b[6];
337*37da2899SCharles.Forsyth	return ep;
338*37da2899SCharles.Forsyth}
339*37da2899SCharles.Forsyth
340*37da2899SCharles.Forsythget_parsed_configuration_descriptor(fd: ref Sys->FD, n: int): ref Configuration
341*37da2899SCharles.Forsyth{
342*37da2899SCharles.Forsyth	conf: ref Configuration;
343*37da2899SCharles.Forsyth	altiface: ref AltInterface;
344*37da2899SCharles.Forsyth
345*37da2899SCharles.Forsyth	b := array [256] of byte;
346*37da2899SCharles.Forsyth	nr := get_standard_descriptor(fd, CONFIGURATION, n, b);
347*37da2899SCharles.Forsyth	if (nr < 0)
348*37da2899SCharles.Forsyth		return nil;
349*37da2899SCharles.Forsyth	conf = nil;
350*37da2899SCharles.Forsyth	altiface = nil;
351*37da2899SCharles.Forsyth	for (i := 0; nr - i > 2 && b[i] > byte 0 && int b[i] <= nr - i; i += int b[i]) {
352*37da2899SCharles.Forsyth		ni := i + int b[i];
353*37da2899SCharles.Forsyth		case int b[i + 1] {
354*37da2899SCharles.Forsyth		Usb->CONFIGURATION =>
355*37da2899SCharles.Forsyth			conf = parse_conf(b[i: ni]);
356*37da2899SCharles.Forsyth			if (conf == nil)
357*37da2899SCharles.Forsyth				return nil;
358*37da2899SCharles.Forsyth		Usb->INTERFACE =>
359*37da2899SCharles.Forsyth			altiface = parse_iface(conf, b[i: ni]);
360*37da2899SCharles.Forsyth			if (altiface == nil)
361*37da2899SCharles.Forsyth				return nil;
362*37da2899SCharles.Forsyth		Usb->ENDPOINT =>
363*37da2899SCharles.Forsyth			if (parse_endpt(conf, altiface, b[i: ni]) == nil)
364*37da2899SCharles.Forsyth				return nil;
365*37da2899SCharles.Forsyth		}
366*37da2899SCharles.Forsyth	}
367*37da2899SCharles.Forsyth	if (i < nr)
368*37da2899SCharles.Forsyth		sys->print("usb: residue at end of descriptors\n");
369*37da2899SCharles.Forsyth	return conf;
370*37da2899SCharles.Forsyth}
371*37da2899SCharles.Forsyth
372*37da2899SCharles.Forsythget_parsed_device_descriptor(fd: ref Sys->FD): ref Device
373*37da2899SCharles.Forsyth{
374*37da2899SCharles.Forsyth	b := array [256] of byte;
375*37da2899SCharles.Forsyth	nr := get_standard_descriptor(fd, DEVICE, 0, b);
376*37da2899SCharles.Forsyth	if (nr < DDEVLEN) {
377*37da2899SCharles.Forsyth		if (nr == 8 || nr == 16) {
378*37da2899SCharles.Forsyth			memset(b[nr: DDEVLEN - 1], 0);
379*37da2899SCharles.Forsyth			b[DDEVLEN - 1] = byte 1;
380*37da2899SCharles.Forsyth			nr = DDEVLEN;
381*37da2899SCharles.Forsyth		}
382*37da2899SCharles.Forsyth		else
383*37da2899SCharles.Forsyth			return nil;
384*37da2899SCharles.Forsyth	}
385*37da2899SCharles.Forsyth	dev := ref Device;
386*37da2899SCharles.Forsyth	dev.usbmajor = int b[3];
387*37da2899SCharles.Forsyth	dev.usbminor = int b[2];
388*37da2899SCharles.Forsyth	dev.class = int b[4];
389*37da2899SCharles.Forsyth	dev.subclass = int b[5];
390*37da2899SCharles.Forsyth	dev.proto = int b[6];
391*37da2899SCharles.Forsyth	dev.maxpkt0 = int b[7];
392*37da2899SCharles.Forsyth	dev.vid = get2(b[8:]);
393*37da2899SCharles.Forsyth	dev.did = get2(b[10:]);
394*37da2899SCharles.Forsyth	dev.relmajor = int b[13];
395*37da2899SCharles.Forsyth	dev.relminor = int b[12];
396*37da2899SCharles.Forsyth	dev.nconf = int b[17];
397*37da2899SCharles.Forsyth	return dev;
398*37da2899SCharles.Forsyth}
399*37da2899SCharles.Forsyth
400*37da2899SCharles.Forsythdump_configuration(fd: ref Sys->FD, conf: ref Configuration)
401*37da2899SCharles.Forsyth{
402*37da2899SCharles.Forsyth	sys->fprint(fd, "configuration %d attr 0x%.x powerma %d\n", conf.id, conf.attr, conf.powerma);
403*37da2899SCharles.Forsyth	for (i := 0; i < len conf.iface; i++) {
404*37da2899SCharles.Forsyth		sys->fprint(fd, "\tinterface %d\n", i);
405*37da2899SCharles.Forsyth		ail := conf.iface[i].altiface;
406*37da2899SCharles.Forsyth		while (ail != nil) {
407*37da2899SCharles.Forsyth			ai := hd ail;
408*37da2899SCharles.Forsyth			sys->fprint(fd, "\t\t%d class %d subclass %d proto %d [%s]\n",
409*37da2899SCharles.Forsyth				ai.id, ai.class, ai.subclass, ai.proto,
410*37da2899SCharles.Forsyth				sclass(ai.class, ai.subclass, ai.proto));
411*37da2899SCharles.Forsyth			for (e := 0; e < len ai.ep; e++) {
412*37da2899SCharles.Forsyth				if (ai.ep[e] == nil) {
413*37da2899SCharles.Forsyth					sys->fprint(fd, "\t\t\t missing descriptor\n");
414*37da2899SCharles.Forsyth					continue;
415*37da2899SCharles.Forsyth				}
416*37da2899SCharles.Forsyth				sys->fprint(fd, "\t\t\t0x%.2ux attr 0x%.x maxpkt %d interval %d\n",
417*37da2899SCharles.Forsyth					ai.ep[e].addr, ai.ep[e].attr, ai.ep[e].maxpkt, ai.ep[e].interval);
418*37da2899SCharles.Forsyth			}
419*37da2899SCharles.Forsyth			ail = tl ail;
420*37da2899SCharles.Forsyth		}
421*37da2899SCharles.Forsyth	}
422*37da2899SCharles.Forsythsys->fprint(fd, "done dumping\n");
423*37da2899SCharles.Forsyth}
424*37da2899SCharles.Forsyth
425*37da2899SCharles.Forsythsclass(class, subclass, proto: int): string
426*37da2899SCharles.Forsyth{
427*37da2899SCharles.Forsyth	for (c := 0; c < len classes; c++)
428*37da2899SCharles.Forsyth		if (classes[c].class == class)
429*37da2899SCharles.Forsyth			break;
430*37da2899SCharles.Forsyth	if (c >= len classes)
431*37da2899SCharles.Forsyth		return sys->sprint("%d.%d.%d", class, subclass, proto);
432*37da2899SCharles.Forsyth	if (classes[c].subclass == nil)
433*37da2899SCharles.Forsyth		return sys->sprint("%s.%d.%d", classes[c].name, subclass, proto);
434*37da2899SCharles.Forsyth	for (sc := 0; sc < len classes[c].subclass; sc++)
435*37da2899SCharles.Forsyth		if (classes[c].subclass[sc].subclass == subclass)
436*37da2899SCharles.Forsyth			break;
437*37da2899SCharles.Forsyth	if (sc >= len classes[c].subclass)
438*37da2899SCharles.Forsyth		return sys->sprint("%s.%d.%d", classes[c].name, subclass, proto);
439*37da2899SCharles.Forsyth	if (classes[c].subclass[sc].proto == nil)
440*37da2899SCharles.Forsyth		return sys->sprint("%s.%s.%d", classes[c].name, classes[c].subclass[sc].name, proto);
441*37da2899SCharles.Forsyth	for (p := 0; p < len classes[c].subclass[sc].proto; p++)
442*37da2899SCharles.Forsyth		if (classes[c].subclass[sc].proto[p].proto == proto)
443*37da2899SCharles.Forsyth			break;
444*37da2899SCharles.Forsyth	if (p >= len classes[c].subclass[sc].proto)
445*37da2899SCharles.Forsyth		return sys->sprint("%s.%s.%d", classes[c].name, classes[c].subclass[sc].name, proto);
446*37da2899SCharles.Forsyth	return sys->sprint("%s.%s.%s", classes[c].name, classes[c].subclass[sc].name,
447*37da2899SCharles.Forsyth		classes[c].subclass[sc].proto[p].name);
448*37da2899SCharles.Forsyth}
449*37da2899SCharles.Forsyth
450*37da2899SCharles.Forsythinit()
451*37da2899SCharles.Forsyth{
452*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
453*37da2899SCharles.Forsyth}
454