;USB activity hook include "settings.inc" include "ti83plus.inc" include "equates.inc" SEGMENT Main GLOBALS ON EXTERN DispHexA,DispHexHL,GetControlPacket,WaitPort82,SetupOutPipe,SetupInPipe,SendInterruptData,SetDeviceAddress EXTERN SmallWaitTimer,WaitTimerBms,SendBulkData,RecycleUSB,ReceiveInterruptData EXTERN DoDebug,ReceiveData,InitializePeriphUSB,receiveAndWriteUSBData,WaitTimer20ms,WaitTimer40ms EXTERN IPutC,SetupLog,BHL_plus_DE,myLoadCIndPaged,myLoadDEIndPaged,inc_BHL,GetCompatibilityData EXTERN HubDeviceDescriptor,HubConfigDescriptor EXTERN InitMemory EXTERN StringDescriptor4,StringDescriptor4End ;USB Activity Hook ;-------------------------------------------------------------------------------------------------- USBactivityHook: add a,e push ix call USBactivityHook_sub pop ix ret USBactivityHook_sub: in a,(80h) LOG Custom,a in a,(55h) ld b,a in a,(56h) 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 ;A cable plugged in bit 5,a jr nz,cancelUSBHook ;A cable unplugged bit 7,a jr z,$F ;B cable unplugged, kill USB device as peripheral call RecycleUSB jr cancelUSBHook $$: 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 ;I may or may not actually care about this flag. 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 InitMemory call InitializePeriphUSB bit onRunning,(iy+onFlags) jr nz,cancelUSBHook ld a,03h out (10h),a B_JUMP Mon 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,endpointDataReady ; bit 1,a ; jr nz,endpointDataReady bit 0,b jr nz,bit0Port86hSet LOG Custom,2 ;*** TESTING ;Try to acknowledge USB interrupts, maybe this helps (it doesn't...) in a,(57h) ld b,a xor a out (57h),a ld a,b out (57h),a 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...(or is it?) ; 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 call SetDeviceAddress jr cancelUSBHook receiveControlPacket: ld hl,inputBuffer ld b,8 call GetControlPacket 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 cp 01h jr z,hostToDeviceInterfaceReceived cp 02h jr z,requestType02Received cp 0C0h jr z,requestTypeC0Received cp 0C1h jr z,requestTypeC1Received cp 41h jr z,requestType41Received jr stallControlPipeEndHook 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 ;-------------------------------------------------------------------------------------------------- requestType02Received: ld a,(inputBuffer+1) cp 01h jr z,clearEndpointFeatureReceived jr stallControlPipeEndHook clearEndpointFeatureReceived: jr finishControlRequest requestType41Received: ld a,(inputBuffer+1) or a jr z,request0_Type41_Received cp 82h jr z,challenge1Received cp 84h jr z,challenge1SuccessReceived cp 87h jr z,challenge2Received jr stallControlPipeEndHook requestTypeC0Received: ld a,(inputBuffer+1) cp 01h jr z,request360StatusReceived jr stallControlPipeEndHook requestTypeC1Received: ld a,(inputBuffer+1) cp 01h jr z,sendPeripheralStatusReceived cp 81h jr z,request360StaticDataReceived cp 83h jr z,request360Response1Received cp 86h jr z,request360StatusDataReceived jr stallControlPipeEndHook hostToDeviceInterfaceReceived: ld a,(inputBuffer+1) cp 0Bh jr z,setInterfaceReceived LOG UnknownInterfaceRequest,a jr stallControlPipeEndHook endpointPacketReceived: ld a,(inputBuffer+1) cp 1 jr z,clearFeatureEndpoint cp 3 jr z,setFeatureEndpoint LOG UnknownDescriptor,a jr stallControlPipeEndHook deviceToHostReceived: ld a,(inputBuffer+1) or a jr z,getStatusReceived cp 06h jr z,getDescriptorReceived LOG UnknownDescriptor,a 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 z,$F LOG UnknownDescriptor,a jr stallControlPipeEndHook $$: ;Clear feature received jr finishControlRequest setFeatureReceived: jr finishControlRequest classSpecificRequestReceived: ld a,(inputBuffer+1) cp 0Ah jr z,setIdleRequest cp 09h jr z,setReportRequest LOG UnknownDescriptor,a jr stallControlPipeEndHook request0_Type41_Received: jr finishControlRequest sendPeripheralStatusReceived: call StartControlOutput ld ix,peripheralStatus ld a,(inputBuffer+6) ld (peripheralStatus+1),a ld hl,peripheralStatus ld de,saveSScreen ld bc,(inputBuffer+6) ldir jr SendControlDataBack challenge1SuccessReceived: jr finishControlRequest challenge2Received: ld a,(step) inc a ld (step),a cp 2 jr c,stallControlPipeEndHook challenge1Received: res packetReceived,(iy+myFlags) call StartControlOutput in a,(96h) ld b,a ld hl,sendByteBuffer+3 push bc $$: in a,(0A0h) ld (hl),a inc hl djnz $B pop bc ld c,b ld b,0 ld (sendByteBuffer+1),bc ld a,(inputBuffer+1) ld (sendByteBuffer),a inc bc inc bc inc bc ld (sendBufferCount),bc jr finishControlRequest request360StatusReceived: ld ix,saveSScreen ld (ix+0),01h ld (ix+1),03h ld (ix+2),0Eh push ix pop hl ld b,3 ld c,01h call SendInterruptData ld bc,3 ld (sendBufferCount),bc ld hl,sendByteBuffer ld (hl),90h ld de,0 ld (sendByteBuffer+1),de ld ix,saveSScreen ld (ix+0),0FFh ld (ix+1),01h ld (ix+2),8Fh ld (ix+3),75h jr SendControlDataBack request360StatusDataReceived: call StartControlOutput ;Send two status bytes back bit packetReceived,(iy+myFlags) ld a,1 jr z,$F inc a $$: out (0A0h),a xor a out (0A0h),a jr finishControlOutput request360Response1Received: call StartControlOutput jr SendControlDataBack request360StaticDataReceived: call StartControlOutput SendControlDataBack: ;Send DE bytes at IX back ld de,(inputBuffer+6) ld ix,saveSScreen controlOutputLoop: ld hl,maxPacketSize ld b,(hl) ld a,d or a jr nz,$F ld a,e cp b jr c,continueOutput1 $$: push de pop hl ld bc,(maxPacketSize) ld b,0 or a sbc hl,bc push hl pop de ld b,c jr continueOutput2 continueOutput1: ld b,a ld de,0 continueOutput2: $$: ld a,(ix+0) out (0A0h),a inc ix djnz $B push de pop hl ld a,h or l jr z,finishControlOutput xor a out (8Eh),a ld a,2 out (91h),a call DelayPort82 jr controlOutputLoop setInterfaceReceived: ld a,(inputBuffer+4) LOG SetInterface,a jr finishControlRequest StartControlOutput: xor a out (8Eh),a ld a,40h out (91h),a jr DelayPort82 finishControlOutput: xor a out (8Eh),a ld a,0Ah out (91h),a call WaitPort82 call WaitPort82 call WaitTimer20ms call WaitTimer20ms call WaitTimer20ms jr cancelUSBHook getStatusReceived: xor a out (8Eh),a ld a,40h out (91h),a ld a,1 out (0A0h),a xor a out (0A0h),a jr finishControlOutput clearFeatureEndpoint: ;Something is telling the calculator to clear the halt condition on an endpoint (I think this might also reset data toggle) 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 ;HACK: Set up endpoints here, I guess ld a,1 out (8Eh),a xor a call SetupInPipe ld a,2 out (8Eh),a ld a,1 call SetupOutPipe 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: ld a,(inputBuffer+3) LOG ReadDescriptor,a dec a ;cp 01h jr z,deviceDescriptorReceived dec a ;cp 02h jr z,configDescriptorReceived dec a ;cp 03h jr z,stringDescriptorReceived jr stallControlPipeEndHook stringDescriptorReceived: ld a,(inputBuffer+2) LOG StringDesc,a cp 04h jr z,sendXboxSecurityDescriptor ;Um...just freak out jr stallControlPipeEndHook sendXboxSecurityDescriptor: ld de,StringDescriptor4 ld hl,(inputBuffer+6) ld (descSize),hl ld hl,StringDescriptor4End-StringDescriptor4 ld bc,(descSize) or a push hl sbc hl,bc pop hl jr nc,$F ld (descSize),hl jr $F configDescriptorReceived: ld hl,(inputBuffer+6) ld (descSize),hl ld de,(configDescAddress) inc de inc de ld a,(de) ld l,a inc de ld a,(de) ld h,a dec de dec de dec de ld bc,(descSize) or a push hl sbc hl,bc pop hl jr nc,$F ld (descSize),hl jr $F deviceDescriptorReceived: ld de,(deviceDescAddress) descriptorReceived: ld hl,(inputBuffer+6) ld (descSize),hl push de ld de,8 or a sbc hl,de pop de jr z,startReceivingDescriptor ld a,(de) ld h,0 ld l,a ld (descSize),hl startReceivingDescriptor: $$: ld hl,(descSize) LOG Custom,h LOG Custom,l xor a out (8Eh),a ld a,40h out (91h),a call DelayPort82 ld a,1 out (20h),a di descriptorOutLoop: ld hl,maxPacketSize ld b,(hl) ld a,(descSize+1) or a jr nz,descriptorOutBig ld a,(descSize) cp b jr c,$F descriptorOutBig: ld hl,(descSize) ld bc,(maxPacketSize) ld b,0 or a sbc hl,bc ld (descSize),hl ld b,c jr continueOutput $$: ld b,a ld hl,0 ld (descSize),hl continueOutput: $$: LOG DataStart,b bit noDataLog,(iy+myFlags) jr z,$F LOG DataStart,b $$: ld a,(de) LOG Data,a bit noDataLog,(iy+myFlags) jr z,gdNoLog LOG Data,a gdNoLog: out (0A0h),a inc de djnz $B LOG DataEnd,b bit noDataLog,(iy+myFlags) jr z,$F LOG DataEnd,b $$: ld hl,(descSize) ld a,h or l jr nz,$F res noDataLog,(iy+myFlags) jr finishControlOutput $$: ;in a,(91h) LOG IntPort91,a xor a out (8Eh),a ld a,2 out (91h),a call DelayPort82 jr descriptorOutLoop setIdleRequest: finishControlRequest: xor a out (8Eh),a in a,(91h) ld a,48h out (91h),a in a,(91h) jr cancelUSBHook DelayPort82: push bc ld bc,08FFh $$: in a,(82h) bit 0,a jr nz,$F ex hl,(sp) ex hl,(sp) dec bc ld a,b or c jr nz,$B $$: pop bc ret ;-------------------------------------------------------------------------------------------------- ;Endpoint Data Ready to Receive ;-------------------------------------------------------------------------------------------------- endpointDataReady: ; ld a,7 ; call IPutC ld a,2 out (8Eh),a in a,(94h) bit 2,a jr nz,endpointDataNAKStall bit 4,a jr nz,endpointDataNAKStall set 5,(iy+41h) xor a ld (bytesRemaining),a ;Receive the data and go di ld hl,saveSScreen ld b,2 call ReceiveInterruptData jr c,cancelUSBHook ld hl,64 ld bc,(saveSScreen) or a sbc hl,bc jr nc,$F ld b,h ld c,l $$: ld hl,saveSScreen+2 call ReceiveInterruptData jr c,cancelUSBHook ld hl,saveSScreen+2 ld a,(hl) ; call DispHexA call HandleReceivedPacket ; ld a,8 ; call IPutC jr cancelUSBHook endpointDataNAKStall: ;Do something about this? jr cancelUSBHook ;-------------------------------------------------------------------------------------------------- HandleReceivedPacket: ld a,(saveSScreen) cp 01h jr z,receivedLEDUpdate ret receivedLEDUpdate: ld hl,saveSScreen ld b,3 ld c,01h call SendInterruptData ret