10 REM > USBSTATUS
   20 REM Enumerate USB device statuses
   30 REM Needs to run in I/O processor
   40 :
   50 MODE &80:PRINT "USB STATUS v0.01"
   60 DIM data% 255
   70 :
   80 PROCusb_Init:PROCusb_Sync:PROCusb_Flush
   90 PROCusb_Cmd(CHR$&11)       :REM Extended Command Set
  100 PROCusb_Cmd("IPH")         :REM I/O in binary
  110 PROCusb_WrStr("FWV"+CHR$13):REM Firmware Version
  120 REPEAT:PROCusb_RdStr:PRINT $usb_result%
  130 UNTIL RIGHT$($usb_result%,1)=">"
  140 PRINTCHR$11;SPC10
  150 :
  160 FOR port%=1 TO 2
  170   PROCusb_Cmd("QP"+STR$port%)
  180   PRINT "Port ";port%;": ";FNh0(usb_result%?0,2);" ";FNh0(usb_result%?1,2);
  190   IF usb_result%?1<>0:usb_result%?0=0
  200   A%=usb_result%?0
  210   FOR bit%=7 TO 0 STEP -1
  220     IF A% AND (2^bit%):PRINT " ";MID$("SERRESPRNHIDCRCBMDOTHHUB",bit%*3+1,3); ELSE PRINT " ---";
  230   NEXT bit%:PRINT
  240 NEXT port%:PRINT
  250 :
  260 REM QDn only gives binary result when Short Command used
  270 PROCusb_Cmd("SCS"):REM Short Command Set
  280 PRINT "   CtrlSz InNm OutNm Toggle res  Index  Sub   <VID>       <BCD>"
  290 PRINT "Dev Addr|  |InSz |OutSz|Type |Port |Class|Proto| |  <PID>  | | Speed"
  300 PRINT " |   |  |  |  |  |  |  |  |  |  |  |  |  |  |  | |   | |   | |   |"
  310 FOR device%=0 TO 15
  320   PROCusb_WrStr(CHR$&85+" "+CHR$device%+CHR$13)
  330   FOR byte%=0 TO 31:data%?byte%=FNusb_Rd:NEXT byte%
  340   PRINT FNd(device%,2);": ";
  350   FOR byte%=0 TO 21:PRINTFNh0(data%?byte%,2);" ";:NEXT byte%
  360   IF data%?11=11:PRINT"Card";
  370   IF data%?11=9:PRINT"Hub";
  380   IF data%?11=8:PRINT"Disk";
  390   IF data%?11=7:PRINT"Printer";
  400   IF data%?11=3:IF data%?13=1:PRINT"Keyboard";
  410   IF data%?11=3:IF data%?13=2:PRINT"Mouse";
  420   PRINT
  430   PROCusb_Sync
  440 NEXT device%
  450 PROCusb_Sync
  460 END
  470 :
  480 :
  490 DEFFNh0(A%,N%)=RIGHT$("0000000"+STR$~A%,N%)
  500 DEFFNd(A%,N%)=RIGHT$("         "+STR$A%,N%)
  510 :
  520 REM > USBLib 1.00
  530 :
  540 REM USB access routines
  550 REM ===================
  560 DEFPROCusb_Sync:REPEATA%=?usb_D:UNTIL(?usb_S AND 128):ENDPROC
  570 DEFPROCusb_Flush:IF(?usb_S AND 128):ENDPROC
  580 PRINT'"Flushing USB";:REPEAT:REPEATA%=?usb_D:UNTIL(?usb_S AND 128)
  590 A%=TIME+20:REPEATUNTILTIME>A%:UNTIL(?usb_S AND 128):ENDPROC
  600 DEFFNusb_Err:IF?usb_result%=13 OR usb_result%?1=ASC":":=0 ELSE PRINT"USB Error: "$usb_result%:=TRUE
  610 DEFPROCusb_Cmd(A$):PROCusb_Sync:PROCusb_WrStr(A$+CHR$13):PROCusb_RdStr:ENDPROC
  620 DEFFNusb_Cmd(A$):PROCusb_Cmd(A$):=FNusb_Err
  630 DEFPROCusb_WrStr(A$):FOR A%=1 TO LEN A$:REPEATUNTIL(?usb_S AND 64)=0
  640 ?usb_D=ASCMID$(A$,A%,1):NEXT:ENDPROC
  650 DEFPROCusb_RdStr:A%=usb_result%-1:REPEATA%=A%+1:?A%=FNusb_Rd:UNTIL?A%=13:ENDPROC
  660 DEFPROCusb_Wr(A%):REPEATUNTIL(?usb_S AND 64)=0:?usb_D=A%:ENDPROC
  670 DEFFNusb_Rd:REPEATUNTIL(?usb_S AND 128)=0:=?usb_D
  680 DEFPROCusb_Init
  690 usb_D=&FCF8:usb_S=&FCF9
  700 usb_result%=usb_result%:IF usb_result%:ENDPROC
  710 DIM usb_result% 63,mc% 99
  720 FOR P=0 TO 1:P%=mc%:[OPT P*2
  730   .usb_RdData
  740   TAY:LDA #data% AND 255:STA usb_RdLp+4
  750   LDA #data% DIV 256:STA usb_RdLp+5:LDX #0
  760   .usb_RdLp:JSR usb_Rd:STA data%,X:INX:BNE usb_RdLp
  770   INC usb_RdLp+5:DEY:BNE usb_RdLp:RTS
  780   .usb_Rd:BIT usb_S:BPL usb_Rd2:BIT &FF:BPL usb_Rd
  790   .usb_Rd2:LDA usb_D:RTS
  800   .usb_WrData
  810   TAY:LDA #data% AND 255:STA usb_WrLp+1
  820   LDA #data% DIV 256:STA usb_WrLp+2:LDX #0
  830   .usb_WrLp:LDA data%,X:JSR usb_Wr
  840   .usb_WrLp2:LDA usb_D:BIT usb_S:BPL usb_WrLp2
  850   INX:BNE usb_WrLp
  860   INC usb_WrLp+2:DEY:BNE usb_WrLp:RTS
  870   .usb_Wr:BIT usb_S:BVC usb_Wr2:BIT &FF:BPL usb_Wr
  880   .usb_Wr2:STA usb_D:RTS
  890 ]NEXT:ENDPROC
  900 :