;USB activity hook include "settings.inc" include "ti83plus.inc" include "equates.inc" SEGMENT Main GLOBALS ON EXTERN DispHexA,DispHexHL,GetControlPacket,WaitPort82,SetupOutPipe,SetupInPipe,SendInterruptData EXTERN debugStep,col1,col2,SmallWaitTimer,WaitTimerBms,SendBulkData,handleCalcData,RecycleUSB EXTERN DoDebug,ReceiveData,InitializePeriphUSB,receiveAndWriteUSBData,DoLog2 ;USB Activity Hook ;-------------------------------------------------------------------------------------------------- USBactivityHook: add a,e ; res debugOn,(iy+periph8xFlags) ;***TESTING ; ld a,(debugStep) ;***TESTING ; inc a ; ; ld (debugStep),a ; ; ld hl,(curRow) ; ; push hl ; ; ld hl,0707h ; ; ld (curRow),hl ; ; call DispHexA ; ; pop hl ; ; ld (curRow),hl ; in a,(55h) ; bit debugOn,(iy+periph8xFlags) ;*** TESTING ; call nz,DispHexA ; ld b,a in a,(56h) ; bit debugOn,(iy+periph8xFlags) ;*** TESTING ; call nz,DispHexA ; LOG Interrupt,b LOG Interrupt,a or a jr z,skipPort56h ;Port 56h has the event bit 6,a jr nz,BcablePluggedIn bit 4,a jr nz,cancelUSBHook ;exitUSBHook ;A cable plugged in bit 5,a jr nz,cancelUSBHook ;exitUSBHook ;A cable unplugged bit 7,a jr z,notBcableUnplugged ;cancelUSBHook ;exitUSBHook ;B cable unplugged ;kill USB device as peripheral call RecycleUSB jr cancelUSBHook xor a out (5Bh),a in a,(4Dh) bit 5,a jr nz,$F xor a out (4Ch),a res 6,(iy+41h) jr continueKill $$: ld b,8 in a,(4Dh) bit 6,a jr nz,$F ld b,0 $$: ld a,b out (4Ch),a continueKill: ld a,2 out (54h),a ld a,(39h) and 0F8h out (39h),a res 0,(iy+41h) in a,(4Dh) bit 5,a jr nz,continueKill2 ld de,0FFFFh $$: dec de ld a,d or e scf jr z,cancelUSBHook in a,(4Dh) bit 7,a jr z,$B in a,(4Dh) bit 0,a jr z,$B ld a,22h out (57h),a jr cancelUSBHook continueKill2: in a,(4Dh) bit 6,a jr nz,$F xor a out (4Ch),a ld a,50h jr finalKill $$: ld a,93h finalKill: out (57h),a jr cancelUSBHook notBcableUnplugged: bit 1,a jr z,skipPort56h ;1,(56h) was set call InitializePeriphUSB jr nc,cancelUSBHook LOG Custom,04h jr cancelUSBHook bit0Port56hSet: ;I have absolutely no idea what 0,(56h) being set means, and we will never know. ;I go ahead and re-initialize just because, though. Who knows, it might actually do the right thing. LOG Bit0Port56,a call InitializePeriphUSB jr cancelUSBHook skipPort56h: in a,(56h) bit 0,a jr nz,bit0Port56hSet in a,(55h) ld b,a and 11h xor 11h jr z,cancelUSBHook bit 4,b jr z,readData di bit 3,(iy+41h) jr nz,cancelUSBHook in a,(8Fh) bit 7,a jr nz,killUSBInterruptDisableError $$: xor a out (5Bh),a ld a,20h out (57h),a jr killUSBError bit0Port86hSet: in a,(8Fh) bit 7,a jr z,$B killUSBInterruptDisableError: xor a out (5Bh),a killUSBError: call unknownOutputs in a,(4Dh) bit 5,a jr nz,$F ld de,0FFFFh smallLoop: dec de ld a,d or e jr z,scfeiUSBError in a,(4Dh) bit 7,a jr z,smallLoop in a,(4Dh) bit 0,a jr z,smallLoop ld a,22h out (57h),a jr cancelUSBHook $$: in a,(4Dh) bit 6,a jr nz,$F xor a out (4Ch),a ld a,50h jr outPort57h $$: ld a,93h outPort57h: out (57h),a jr cancelUSBHook unknownOutputs: in a,(4Dh) bit 5,a jr nz,$F xor a res 6,(iy+41h) jr port54h39hOutput $$: ld b,8 in a,(4Dh) bit 6,a jr nz,$F ld b,0 $$: ld a,b out (4Ch),a port54h39hOutput: ld a,2 out (54h),a in a,(39h) and 0F8h out (39h),a ret scfeiUSBError: scf ei ld a,1 out (5Bh),a res 0,(iy+41h) jr cancelUSBHook ;Not sure whether this should run or not ld b,50 call WaitTimerBms LOG Custom,3 ;*** TESTING ei ld a,1 out (5Bh),a res 0,(iy+41h) jr cancelUSBHook BcablePluggedIn: LOG PeriphInit,0 call InitializePeriphUSB jr cancelUSBHook readData: di bit 0,(iy+41h) jr nz,cancelUSBHook in a,(8Fh) LOG IntPort8F,a ;*** TESTING in a,(86h) ld b,a LOG IntPort86,a ;*** TESTING bit 2,a jr nz,enableControlOutput in a,(82h) LOG IntPort82,a ;*** TESTING bit 0,a jr nz,controlDataReady in a,(84h) LOG IntPort84,a bit 2,a jr nz,bulkDataReady bit 0,b jr nz,bit0Port86hSet LOG Custom,2 ;*** TESTING jr cancelUSBHook ;*** INCOMPLETE - some sort of data enableControlOutput: LOG EnableOut,0 xor a ld (9C86h),a ld a,1 out (5Bh),a in a,(87h) or 1 out (87h),a jr cancelUSBHook controlDataReady: xor a out (8Eh),a in a,(91h) LOG ControlData,a cp 5 ;*** HACK: I have no idea why this is suddenly necessary... jr z,receiveControlPacket ; ld b,a and 4 jr z,$F ld a,b and 0FBh out (91h),a jr cancelUSBHook $$: ld a,b and 10h jr z,$F ld a,b or 80h out (91h),a $$: ld a,b and 1 jr nz,receiveControlPacket ld hl,USBflag bit setAddress,(hl) jr z,cancelUSBHook ;this should never happen (but apparently it does, OS ignores it) res setAddress,(hl) ld a,(USBaddress) LOG SetAddress,a out (80h),a jr cancelUSBHook receiveControlPacket: ld hl,inputBuffer ld b,8 call GetControlPacket ; bit debugOn,(iy+periph8xFlags) ;***TESTING ; call nz,DoDebug ;***TESTING ld a,(inputBuffer) LOG ControlData,a cp 80h jr z,deviceToHostReceived cp 81h jr z,deviceToHostReceived cp 02h jr z,endpointPacketReceived or a jr z,hostToDeviceReceived ld hl,USBflag bit msdActive,(hl) jr z,$F cp 0A1h jr z,getMaxLUNReceived $$: bit kbdActive,(hl) jr z,stallControlPipeEndHook cp 21h jr z,classSpecificRequestReceived cp 22h jr z,classSpecificRequestReceived stallControlPipeEndHook: ld hl,inputBuffer ld de,statVars+100h ld bc,8 ldir LOG IStallPipe,0 xor a out (8Eh),a ld a,60h out (91h),a cancelUSBHook: ld b,0 ret exitUSBHook: ld b,2Ch ret ;-------------------------------------------------------------------------------------------------- ;Control Requests ;-------------------------------------------------------------------------------------------------- endpointPacketReceived: ld a,(inputBuffer+1) cp 1 jr z,clearFeatureEndpoint cp 3 jr z,setFeatureEndpoint jr stallControlPipeEndHook deviceToHostReceived: ld a,(inputBuffer+1) cp 06h jr z,getDescriptorReceived jr stallControlPipeEndHook hostToDeviceReceived: ld a,(inputBuffer+1) cp 05h jr z,setAddressReceived cp 09h jr z,setConfigurationReceived cp 03h jr z,setFeatureReceived dec a jr nz,stallControlPipeEndHook ;Clear feature received jr finishControlRequest setFeatureReceived: jr finishControlRequest classSpecificRequestReceived: ld a,(inputBuffer+1) cp 0Ah jr z,setIdleRequest cp 09h jr z,setReportRequest jr stallControlPipeEndHook getMaxLUNReceived: ; LOG OutA0Start,0 xor a out (8Eh),a ld a,40h out (91h),a xor a out (0A0h),a finishControlOutput: ; bit debugOn,(iy+periph8xFlags) ;***TESTING ; call nz,DoDebug ;***TESTING xor a out (8Eh),a ld a,0Ah out (91h),a call WaitPort82 ; bit debugOn,(iy+periph8xFlags) ;***TESTING ; call nz,DoDebug ;***TESTING call WaitPort82 ; bit debugOn,(iy+periph8xFlags) ;***TESTING ; call nz,DoDebug ;***TESTING jr cancelUSBHook clearFeatureEndpoint: ;Something is telling the calculator to clear the halt condition on an endpoint. ld a,(inputBuffer+4) and 7Fh ld (USBaddress),a ld a,(inputBuffer+4) and 80h ld (USBaddress+1),a in a,(8Eh) push af ld a,(USBaddress) out (8Eh),a ld a,(USBaddress+1) or a jr z,$F in a,(91h) and 0EFh or 40h out (91h),a jr endpointReceivedDone $$: in a,(94h) and 0DFh or 80h out (94h),a endpointReceivedDone: pop af out (8Eh),a jr finishControlRequest setFeatureEndpoint: ;Something is telling the calculator to halt an endpoint. ld a,(inputBuffer+4) and 7Fh ld (USBaddress),a ld a,(inputBuffer+4) and 80h ld (USBaddress+1),a in a,(8Eh) push af ld a,(USBaddress) out (8Eh),a ld a,(USBaddress+1) or a jr nz,$F ld a,10h out (91h),a jr endpointReceivedDone $$: ld a,20h out (91h),a jr endpointReceivedDone setReportRequest: xor a out (8Eh),a ld a,40h out (91h),a ld de,0FFFFh $$: dec de ld a,d or e jr z,stallControlPipeEndHook in a,(82h) and 1 jr z,$B in a,(91h) and 1 jr z,stallControlPipeEndHook in a,(96h) dec a jr nz,stallControlPipeEndHook in a,(0A0h) ;this is probably 01, don't really care either way jr finishControlRequest setConfigurationReceived: LOG SetConfig,0 ld a,1 out (8Eh),a ld a,1 ld hl,USBflag set driverConfigured,(hl) ;HID/other communication can start now bit kbdActive,(hl) jr nz,$F ld a,8 $$: call SetupOutPipe ld a,2 out (8Eh),a bit kbdActive,(hl) jr nz,$F ld a,8 call SetupInPipe jr finishSetConfiguration $$: ld a,1 out (8Eh),a ld a,0Ah out (99h),a ld a,31h out (98h),a xor a in a,(98h) ld a,c out (90h),a xor a in a,(90h) finishSetConfiguration: xor a ld (bytesRemaining),a jr finishControlRequest setAddressReceived: ld a,(inputBuffer+2) LOG GotSetAddr,a ld (USBaddress),a ld hl,USBflag set setAddress,(hl) ld a,1 out (5Bh),a ld a,7Fh out (87h),a ld a,0Eh out (89h),a jr finishControlRequest getDescriptorReceived: ; xor a ;***TESTING ; ld (col1),a ;***TESTING ld a,(inputBuffer+3) ; call DispHexA LOG ReadDescriptor,a dec a ;cp 01h jr z,deviceDescriptorReceived dec a ;cp 02h jr z,configDescriptorReceived dec a ;cp 03h jr z,stringDescriptorReceived cp 22h-3 jr z,reportDescriptorReceived jr stallControlPipeEndHook reportDescriptorReceived: ;set debugOn,(iy+periph8xFlags) ;***TESTING ld a,(inputBuffer+4) or a ; ld de,HIDreportDescriptor jr nz,stallControlPipeEndHook ld a,(inputBuffer+6) ld (numOutBytes),a ld a,(de) inc de ld hl,numOutBytes ld b,(hl) cp b jr nc,$F ld (numOutBytes),a jr $F stringDescriptorReceived: ld a,(inputBuffer+2) ;***HACK - it should pull this from the API LOG StringDesc,a or a ld de,stringDescriptor jr z,descriptorReceived dec a ld de,manufacturerString jr z,descriptorReceived dec a jr nz,stallControlPipeEndHook ld de,productString in a,(21h) and 3 jr z,descriptorReceived ld de,productStringSE jr descriptorReceived configDescriptorReceived: ld a,(inputBuffer+6) ld (numOutBytes),a ld de,(configDescAddress) inc de inc de ld a,(de) dec de dec de ld hl,numOutBytes ld b,(hl) cp b jr nc,$F ld (numOutBytes),a jr $F deviceDescriptorReceived: ld de,(deviceDescAddress) descriptorReceived: ld a,(de) ld (numOutBytes),a $$: xor a out (8Eh),a ld a,40h out (91h),a descriptorOutLoop: ld a,(numOutBytes) cp 40h jr c,$F ld b,40h ;***HACK - bMaxPacketSize0 is hard-coded here sub b ld (numOutBytes),a jr continueOutput $$: ld b,a xor a ld (numOutBytes),a continueOutput: push bc ;***HACK - apparently the 40h command above needs a little delay sometimes ld bc,0FFh ; - the check on port 82h might be meaningless, but if it $$: ;in a,(82h) ; actually did succeed, the delay is no longer necessary ;bit 0,a ; ;jr nz,$F ; ex hl,(sp) ; ex hl,(sp) ; ex hl,(sp) ; ex hl,(sp) ; dec bc ; ld a,b ; or c ; jr nz,$B ; $$: pop bc ; $$: ld a,(de) out (0A0h),a inc de djnz $B ld a,(numOutBytes) or a jr z,finishControlOutput xor a out (8Eh),a ld a,2 out (91h),a jr descriptorOutLoop setIdleRequest: finishControlRequest: xor a out (8Eh),a in a,(91h) ld a,48h out (91h),a in a,(91h) jr cancelUSBHook ;-------------------------------------------------------------------------------------------------- ;Bulk Requests ;-------------------------------------------------------------------------------------------------- bulkDataReady: ld a,2 out (8Eh),a in a,(96h) LOG InData,a ld c,a ;might not need to do this ld b,0 ; set 5,(iy+41h) set 0,(iy+41h) xor a out (5Bh),a ld (bytesRemaining),a ;Calculator bulk data received, deal with it ld hl,cancelUSBHook push hl ld hl,(callbackAddress) jp (hl) ;-------------------------------------------------------------------------------------------------- ;String descriptors stringDescriptor: DB 04h ;size of descriptor DB 03h ;string descriptor type DB 09h,04h ;UNICODE string manufacturerString: DB manufacturerStringEnd-manufacturerString DB 03h DB 'T',0,'e',0,'x',0,'a',0,'s',0,' ',0,'I',0,'n',0,'s',0,'t',0,'r',0,'u',0,'m',0,'e',0,'n',0,'t',0,'s',0,' ',0 DB 'I',0,'n',0,'c',0,'o',0,'r',0,'p',0,'o',0,'r',0,'a',0,'t',0,'e',0,'d',0 manufacturerStringEnd: productString: DB productStringEnd-productString DB 03h DB 'T',0,'I',0,'-',0,'8',0,'4',0,' ',0,'P',0,'l',0,'u',0,'s',0 productStringEnd: productStringSE: DB productStringSEEnd-productStringSE DB 03h DB 'T',0,'I',0,'-',0,'8',0,'4',0,' ',0,'P',0,'l',0,'u',0,'s',0,' ',0 DB 'S',0,'i',0,'l',0,'v',0,'e',0,'r',0,' ',0,'E',0,'d',0,'i',0,'t',0,'i',0,'o',0,'n',0 productStringSEEnd: