;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,WaitTimer20ms,WaitTimer40ms EXTERN IPutC EXTERN deviceBitmap,deviceChangedBitmap,lastPortResetClear,lastPortConnClear,hubIntResponse,portCur EXTERN lastPortStatus,maxPacketSize,jigBytesReceived EXTERN jailbreakState,HUB_READY,SetDeviceAddress,P1_READY,P2_READY,P3_READY,P4_READY EXTERN Device4ConfigDescriptor2Short,Device4ConfigDescriptor2,Device4ConfigDescriptor3 EXTERN SendDevice1ConfigDescriptor,ReceiveInterruptData ;USB Activity Hook ;-------------------------------------------------------------------------------------------------- USBactivityHook: add a,e 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 di 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,interruptDataReady bit 1,a jr nz,interruptDataReady 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 10100000b jr z,deviceToHostClassRequestReceived 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 00100011b jr z,otherClassRequestReceived cp 10100011b jr z,otherClassRequestReceived 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: ;Acknowledge any USB interrupts (doesn't work, despite the OS doing it) ; in a,(57h) ; ld b,a ; xor a ; out (57h),a ; ld a,0FFh ;b ;enable everything ; out (57h),a ld b,0 ret exitUSBHook: ld b,2Ch ret ;-------------------------------------------------------------------------------------------------- ;Control Requests ;-------------------------------------------------------------------------------------------------- hostToDeviceInterfaceReceived: ld a,(inputBuffer+1) cp 0Bh jr z,setInterfaceReceived LOG UnknownInterfaceRequest,a jr stallControlPipeEndHook otherClassRequestReceived: ld a,(inputBuffer+1) cp 03h jr z,hubSetFeatureReceived cp 01h jr z,hubClearFeatureReceived or a jr z,getHubStatusReceived LOG UnknownClassRequest,a jr stallControlPipeEndHook deviceToHostClassRequestReceived: ld a,(inputBuffer+1) or a jr z,getHubStatusReceived cp 06h ;GET_DESCRIPTOR jr z,getHubDescriptorReceived LOG UnknownDescriptor,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 setInterfaceReceived: ld a,(inputBuffer+4) LOG SetInterface,a jr finishControlRequest hubClearFeatureReceived: ld a,(inputBuffer+2) cp 16 jr z,$F cp 17 jr z,$F cp 18 jr z,$F cp 19 jr z,$F cp 20 jr z,$F ;Not acknowledging a status change jr finishControlRequest $$: ld a,(inputBuffer+4) dec a ld b,0 ld c,a ld hl,deviceChangedBitmap add hl,bc add hl,bc ld a,(inputBuffer+2) cp 16 jr nz,$F ld bc,1111111111111110b ld a,(inputBuffer+4) ld (lastPortConnClear),a jr hubClearFeatureContinue $$: ld bc,1111111111111110b cp 17 jr z,hubClearFeatureContinue ld bc,1111111111111011b cp 18 jr z,hubClearFeatureContinue ld bc,1111111111110111b cp 19 jr z,hubClearFeatureContinue ld bc,1111111111101111b ld a,(inputBuffer+4) ld (lastPortResetClear),a jr hubClearFeatureContinue hubClearFeatureContinue: ;BC is mask to clear against ld a,(hl) and c ld (hl),a inc hl ld a,(hl) and b ld (hl),a ld a,(inputBuffer+2) cp 10h jr nz,finishControlRequest ld a,(inputBuffer+4) cp 4 jr nz,finishControlRequest jr finishControlRequest hubSetFeatureReceived: ld a,(inputBuffer+4) dec a ld b,0 ld c,a ld hl,deviceChangedBitmap add hl,bc add hl,bc ld a,(inputBuffer+2) ld bc,00010000b cp 04h jr z,hubSetFeatureContinue ld bc,00000000b cp 08h jr nz,$F ld a,(inputBuffer+4) cp 6 jr nz,finishControlRequest ld a,HUB_READY ld (jailbreakState),a jr finishControlRequest $$: ld c,00000000b ;C is mask to set against hubSetFeatureContinue: ld a,(hl) or c ld (hl),a inc hl ld a,(hl) or b ld (hl),a ld d,1 ld a,(inputBuffer+4) $$: sla d dec a jr nz,$B ld a,d ld (hubIntResponse),a jr finishControlRequest 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 getHubStatusReceived: ld a,(inputBuffer+4) ld (lastPortStatus),a xor a out (8Eh),a ld a,40h out (91h),a ld hl,0 ld a,(inputBuffer+4) or a jr z,$F ;Set port status information in HL ld hl,deviceBitmap ld a,(inputBuffer+4) dec a ld c,a ld b,0 add hl,bc add hl,bc ld e,(hl) inc hl ld d,(hl) ex de,hl $$: ld a,l out (0A0h),a ld a,h out (0A0h),a ld hl,0 ld a,(inputBuffer+4) or a jr z,$F ;Set port change information in HL ld hl,deviceChangedBitmap ld a,(inputBuffer+4) dec a ld c,a ld b,0 add hl,bc add hl,bc ld e,(hl) inc hl ld d,(hl) ex de,hl $$: ld a,l out (0A0h),a ld a,h out (0A0h),a jr finishControlOutput 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 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 getHubDescriptorReceived: LOG ReadDescriptor,29h xor a ld (iy+asm_Flag3),a ld a,(inputBuffer+6) set 7,(iy+asm_Flag3) ld a,(inputBuffer+6) ld h,0 ld l,a ld (descSize),hl ld de,hubDescriptor ld a,(de) ld h,0 ld l,a ld bc,(descSize) or a push hl sbc hl,bc pop hl jr nc,startReceivingDescriptor ld (descSize),hl jr startReceivingDescriptor hubDescriptor: DB 09h DB 29h DB 06h DW 00A9h DB 00h ;32h DB 64h DB 00h DB 0FFh getDescriptorReceived: xor a ld (iy+asm_Flag3),a 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 ;Um...just freak out jr stallControlPipeEndHook ; 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: ;This is really horrible. ld a,(portCur) cp 1 jr nz,$F jr SendDevice1ConfigDescriptor ld a,(inputBuffer+2) LOG Custom,a cp 3 jr nz,$F ld hl,(inputBuffer+6) ld de,8 or a sbc hl,de jr z,$F ld a,P1_READY ld (jailbreakState),a set noDataLog,(iy+PS3JBFlags) jr startConfigDescriptor $$: ld a,(portCur) cp 2 jr nz,$F ld a,P2_READY ld (jailbreakState),a jr startConfigDescriptor $$: ld a,(portCur) cp 3 jr nz,$F ld a,(inputBuffer+2) cp 1 jr nz,$F ld hl,(inputBuffer+6) ld de,8 or a sbc hl,de jr z,$F ld a,P3_READY ld (jailbreakState),a jr startConfigDescriptor $$: ld a,(portCur) cp 4 jr nz,$F ld a,(inputBuffer+2) or a jr z,$F cp 1 jr nz,notConfig1 ;Port 4 config descriptor 1 ld hl,(inputBuffer+6) ld de,8 or a sbc hl,de ld de,Device4ConfigDescriptor2Short ld (configDescAddress),de jr z,$F ld de,Device4ConfigDescriptor2 ld (configDescAddress),de ld hl,18 ld (descSizeOverride),hl set overrideSize,(iy+PS3JBFlags) ld a,P4_READY ld (jailbreakState),a jr $F notConfig1: ld a,(inputBuffer+2) cp 2 jr nz,$F ;Port 4 config descriptor 2 ld de,Device4ConfigDescriptor3 ld (configDescAddress),de $$: startConfigDescriptor: set 1,(iy+asm_Flag3) ld hl,(inputBuffer+6) ld (descSize),hl ;Are we using a separate packet for the config descriptor? If not, skip this step bit useShortConfigDesc,(iy+PS3JBFlags) jr z,$F push hl ld de,8 or a sbc hl,de pop hl jr z,$F ;This is a special config descriptor packet larger than 8 bytes, so set a different size ld hl,0F00h ld (descSizeOverride),hl set overrideSize,(iy+PS3JBFlags) $$: ld de,(configDescAddress) bit useShortConfigDesc,(iy+PS3JBFlags) jr z,$F ld hl,(descSize) push hl push de ld de,8 or a sbc hl,de pop de pop hl jr nz,$F ;Size is 8, do we use the short descriptor or the big one? ld hl,8 ld (descSizeOverride),hl set overrideSize,(iy+PS3JBFlags) ld de,(shortConfigDescAddress) $$: 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: set 0,(iy+asm_Flag3) 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: $$: bit overrideSize,(iy+PS3JBFlags) res overrideSize,(iy+PS3JBFlags) jr z,$F ld hl,(descSizeOverride) ld (descSize),hl $$: LOG Custom,0FAh 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+PS3JBFlags) jr z,$F LOG DataStart,b $$: ld a,(de) LOG Data,a bit noDataLog,(iy+PS3JBFlags) jr z,gdNoLog LOG Data,a gdNoLog: out (0A0h),a inc de djnz $B LOG DataEnd,b bit noDataLog,(iy+PS3JBFlags) jr z,$F LOG DataEnd,b $$: ld hl,(descSize) ld a,h or l jr nz,$F res noDataLog,(iy+PS3JBFlags) ld a,(iy+asm_Flag3) ld (iy+asm_Flag2),a ld a,(portCur) cp 5 jr nz,finishControlOutput ld a,1 out (8Eh),a ld a,1 call SetupOutPipe ld a,2 out (8Eh),a ld a,1 call SetupInPipe 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 ;-------------------------------------------------------------------------------------------------- ;Interrupt Requests ;-------------------------------------------------------------------------------------------------- interruptDataReady: ld a,2 out (8Eh),a in a,(94h) bit 2,a jr nz,interruptDataNAKStall bit 4,a jr nz,interruptDataNAKStall set 5,(iy+41h) xor a ld (bytesRemaining),a ;Interrupt data, receive it and go di ld hl,inputBuffer ld b,8 call ReceiveInterruptData jr c,cancelUSBHook ld a,(jigBytesReceived) add a,8 ld (jigBytesReceived),a jr cancelUSBHook interruptDataNAKStall: ;Do something about this? jr cancelUSBHook ;--------------------------------------------------------------------------------------------------