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