include "ti83plus.inc" include "equates.inc" PUBLIC DirectUSB_Setup,DirectUSB_ConnectDevice PUBLIC DirectUSB_Connect PUBLIC DirectUSB_Start,DirectUSB_SetEventHandler,DirectUSB_Stop,DirectUSB_Teardown PUBLIC DirectUSB_GetCurrentDevice PUBLIC DirectUSB_HandleAttachedDevice,DirectUSB_SetPipeEndpoint,DirectUSB_GetFreePipe EXTERN IPutC,DispHexA,DispHexHL,IPutS,IGetKey,SetupLog,StopLog EXTERN DirectUSB_HandleHubConnected,DirectUSB_ClearHubPortFeature,DirectUSB_SetHubPortFeature EXTERN DirectUSB_GetHubPortStatus,DirectUSB_SetUSBInterruptState,DirectUSB_SetDefaultDescriptors EXTERN DirectUSB_MessagePump,DirectUSB_PeripheralInit,DirectUSB_WaitForStableLines EXTERN DirectUSB_HostInit,DirectUSB_GetDescriptor,DirectUSB_AssignNextAddress DirectUSB_Setup: ;B: flags: ; Bit 0: set to utilize interrupts (and use USB activity hook); if reset, you must handle them yourself by looping with DirectUSB_MessagePump ; Bit 1: set to use OS calls (you would reset this if you're trying to use this without an installed OS) ;Set up initial memory res 5,(iy+1Bh) res 5,(iy+41h) ld (iy+USBFlags),b xor a ld (deviceTable),a inc a ld (nextAddress),a ld hl,pipeConfiguration ld (hl),0 ld de,pipeConfiguration+1 ld bc,15 ldir ld hl,deviceTable ld (hl),0 ld de,eventHandlers+1 ld bc,bTotalNumEvents*2-1 ldir ld hl,9BD4h ld de,prevHookBlock ld bc,4 ldir ld hl,flags+3Ah ldi ;Set up logging ld b,LOG_PAGE ld hl,LOG_ADDRESS call SetupLog ;Disable all interrupt support and reset flags xor a bit interruptsEnabled,(iy+USBFlags) jr z,$F inc a $$: call DirectUSB_SetUSBInterruptState ;Set up initial descriptors if we're going to be in peripheral mode call DirectUSB_SetDefaultDescriptors xor a ret DirectUSB_SetEventHandler: ;A: event type ;DE => address of handler, or zero for none DISAVE dec a ld h,0 ld l,a add hl,hl ld bc,eventHandlers add hl,bc ld (hl),e inc hl ld (hl),d EIRESTORE ret DirectUSB_Start: call DirectUSB_Stop ;Fall through to DirectUSB_Connect DirectUSB_Connect: ;Starts a USB connection if possible, in either host or peripheral mode. in a,(4Dh) bit 6,a jr z,DirectUSB_ConnectDevice ;Vbus is high, are we disconnected? in a,(4Dh) bit 1,a scf ccf ret nz ;yes, just forget it ;Mini-B cable is connected, try to initialize in peripheral mode jr DirectUSB_PeripheralInit DirectUSB_ConnectDevice: ;Wait a bit and set the initial "interrupt" mask call DirectUSB_WaitForStableLines in a,(4Dh) bit 5,a ret nz ;mini-B or no cable connected, nevermind I guess! ;Supply power to the port call DirectUSB_HostInit ret c DirectUSB_HandleAttachedDevice: ld a,'A' call IPutC ;Set a reasonable bMaxPacketSize0 for the initial device descriptor request ld a,DEFAULT_MAX_PACKET_SIZE0 ld (bMaxPacketSize0),a ;Read the first part of the device descriptor (to get bMaxPacketSize0) ld a,01h ld de,inputBuffer ld bc,8 call DirectUSB_GetDescriptor ret c ld a,'A' call IPutC ld a,(inputBuffer+4) call DispHexA ld a,(inputBuffer+5) call DispHexA ld a,(inputBuffer+6) call DispHexA ;Save bMaxPacketSize0 ld a,(inputBuffer+7) ld (bMaxPacketSize0),a call DispHexA ;Set the device address call DirectUSB_AssignNextAddress ret c ;Now add this to our list of devices ld bc,(bMaxPacketSize0) ld b,a call AddNewDevice ld a,(inputBuffer+4) cp 09h jr z,DirectUSB_HandleHubConnected ld b,evDeviceConnected call DirectUSB_RaiseEvent DirectUSB_ConnectDeviceDone: xor a ret DirectUSB_GetFreePipe: push ix push bc call DirectUSB_GetFreePipe_Do pop bc pop ix ret DirectUSB_GetFreePipe_Do: ld ix,pipeConfiguration ld b,16 ld l,1 $$: ld a,(ix+0) or a ret z inc ix inc l djnz $B scf ret DirectUSB_SetPipeEndpoint: ;Set pipe L to endpoint A push ix push bc ld ix,pipeConfiguration-1 ld b,0 ld c,l add ix,bc ld (ix+0),a pop bc pop ix ret DirectUSB_GetCurrentDevice: ;Returns device information structure for current address in IX ;Returns carry flag set if issues push bc push de push bc push af call DirectUSB_GetCurrentDevice_Do pop bc ld a,b pop bc pop de pop bc ret DirectUSB_GetCurrentDevice_Do: in a,(80h) ld b,a ld ix,deviceTable ld de,bDeviceInformationSize $$: ld a,(ix+0) or a scf ret z cp b ret z add ix,de jr $B DirectUSB_Stop: ;Kill the USB connection ld a,2 out (54h),a xor a ret DirectUSB_Teardown: ;Restore any previous USB activity hook ld hl,prevHookBlock ld de,9BD4h ld bc,4 ldir ld de,flags+3Ah ldi ;Stop logging call StopLog xor a ret AddNewDevice: ;B: bFunctionAddress ;C: bMaxPacketSize0 push bc ld ix,deviceTable ld de,bDeviceInformationSize $$: ld a,(ix+0) or a jr z,$F add ix,de jr $B $$: ld b,16 push ix $$: ld (ix+0),0 inc ix djnz $B pop ix pop bc ld (ix+0),b ld (ix+1),c ;Terminate the table with a zero ld (ix+bDeviceInformationSize),0 ret DirectUSB_RaiseEvent: ;B: event ;IX => device information structure, if applicable dec b ld h,0 ld l,b add hl,hl ld de,eventHandlers add hl,de ld e,(hl) inc hl ld d,(hl) ex de,hl ld a,h or l ret z jp (hl)