; *************************************************************************** ; copyright : (C) 2025 by Martin Preuss ; email : martin@libchipcard.de ; ; *************************************************************************** ; * This file is part of the project "AqHome". * ; * Please see toplevel file COPYING of that project for license details. * ; *************************************************************************** ; *************************************************************************** ; defines ; --------------------------------------------------------------------------- ; network interfaces .equ NETDEV0_IFACENUM = 1 .equ NETDEV1_IFACENUM = 2 ; *************************************************************************** ; data .dseg appRouterDataBegin: appRouterRangeBegin: .byte 1 appRouterRangeEnd: .byte 1 appRouterDataEnd: ; *************************************************************************** ; code .cseg ; --------------------------------------------------------------------------- ; @routine AppRouter_Init @global AppRouter_Init: ldi xh, HIGH(appRouterDataBegin) ldi xl, LOW(appRouterDataBegin) clr r16 ldi r17, (appRouterDataEnd-appRouterDataBegin) rcall Utils_FillSram #ifndef APP_ROUTER_NO_ADDR_MGR ldi r16, 0xe0 ; default range from 0xe0-0xef (will be changed later) sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r16 ; use first address for router itself sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r16 ; use same address for both interfaces to save on addresses inc r16 sts appRouterRangeBegin, r16 ; range from router+1 ldi r16, 0xef sts appRouterRangeEnd, r16 rcall appRouterReadConfFromEeprom ; try to read config from EEPROM #endif ; set interface number for NETDEV0 ldi r16, NETDEV0_IFACENUM sts netInterfaceData+NET_IFACE_OFFS_IFACENUM, r16 ; set interface number for NETDEV1 ldi r16, NETDEV1_IFACENUM sts netInterfaceData2+NET_IFACE_OFFS_IFACENUM, r16 #ifndef APP_ROUTER_NO_ADDR_MGR ldi r18, NETMSG_CMD_ADDRESS_RANGE rcall appRouterSendRangeMsgToDev1 #endif ret ; @end ; --------------------------------------------------------------------------- ; @routine AppRouter_EveryDay @global ; ; @clobbers R16, R17, X AppRouter_EveryDay: ldi yl, LOW(netInterfaceData) ldi yh, HIGH(netInterfaceData) bigcall NET_Interface_ResetStats ; (R16, R17, X) ldi yl, LOW(netInterfaceData2) ldi yh, HIGH(netInterfaceData2) bigcall NET_Interface_ResetStats ; (R16, R17, X) ret ; @end ; --------------------------------------------------------------------------- ; @routine AppRouter_Run @global ; ; Read messages from either interface and forward to the other one. AppRouter_Run: rjmp appRouterCheckRecvdMsg ; @end ; --------------------------------------------------------------------------- ; @routine appRouterHandleMsgAnyDev @global ; ; @param X pointer to received message ; @return CFLAG set if msg handled, cleared otherwise ; @clobbers any, !X appRouterHandleMsgAnyDev: push xl push xh rcall appRouterHandleMsgAnyDev_savedX pop xh pop xl rjmp appRouterHandleMsgAnyDev_end appRouterHandleMsgAnyDev_savedX: adiw xh:xl, NETMSG_OFFS_CMD ; maybe move ping/reboot handling to all/main.asm? ld r16, X sbiw xh:xl, NETMSG_OFFS_CMD cpi r16, NETMSG_CMD_REBOOT_REQUEST breq appRouterHandleMsgAnyDev_handleRebootMsg cpi r16, NETMSG_CMD_PING breq appRouterHandleMsgAnyDev_handlePingMsg cpi r16, NETMSG_CMD_VALUE_SET breq appRouterHandleMsgAnyDev_handleSetValue rjmp appRouterHandleMsgAnyDev_clcRet appRouterHandleMsgAnyDev_handleRebootMsg: rcall appRouterHandleRebootRequest ret appRouterHandleMsgAnyDev_handlePingMsg: rcall appRouterHandlePingRequest clc ret appRouterHandleMsgAnyDev_handleSetValue: rcall NETMSG_ValueRead ; (none) cpi r17, VALUE_ID_ROUTER_SETRANGE breq appRouterHandleMsgAnyDev_handleSetRange rjmp appRouterHandleMsgAnyDev_clcRet appRouterHandleMsgAnyDev_handleSetRange: #ifndef APP_ROUTER_NO_ADDR_MGR sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r18 ; use first address for router itself sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r18 ; use same address for both interfaces to save on addresses inc r18 ; start range after router sts appRouterRangeBegin, r18 sts appRouterRangeEnd, r19 ; send ACK ldi r23, NETMSG_CMD_VALUE_SET_ACK rcall Main_SendValueResponse ; (clobbers all, including Y) ; let subnodes re-eunumerate ldi r18, NETMSG_CMD_REENUM rcall appRouterSendRangeMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y) rcall appRouterWriteConfToEeprom ; (r16, r17, X) #endif sec ret appRouterHandleMsgAnyDev_clcRet: clc appRouterHandleMsgAnyDev_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appRouterHandleDev1Msg @global ; ; Handle messages from controlled subnet. ; ; @param X pointer to received message ; @return CFLAG set if msg handled, cleared otherwise ; @clobbers any, !X appRouterHandleDev1Msg: #ifndef APP_ROUTER_NO_ADDR_MGR push xl push xh rcall appRouterHandleDev1Msg_savedX pop xh pop xl rjmp appRouterHandleDev1Msg_end appRouterHandleDev1Msg_savedX: adiw xh:xl, NETMSG_OFFS_CMD ld r16, X sbiw xh:xl, NETMSG_OFFS_CMD cpi r16, NETMSG_CMD_NEED_ADDRESS breq appRouterHandleDev1Msg_handleNeedAddr cpi r16, NETMSG_CMD_CLAIM_ADDRESS breq appRouterHandleDev1Msg_handleClaimAddr ; add more here ldi r16, 0 rjmp appRouterHandleDev1Msg_clcRet appRouterHandleDev1Msg_handleNeedAddr: ldi r18, NETMSG_CMD_ADDRESS_RANGE rcall appRouterSendRangeMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y) sec rjmp appRouterHandleDev1Msg_end appRouterHandleDev1Msg_handleClaimAddr: rcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19) rcall appRouterIsR19InRange brcs appRouterHandleDev1Msg_end ; is not in subnet range, deny rcall appRouterSendDenyAddrR19ToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y) sec rjmp appRouterHandleDev1Msg_end #endif appRouterHandleDev1Msg_clcRet: clc appRouterHandleDev1Msg_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appRouterIsR19InRange ; ; @param R19 address to check against range ; @clobbers R16 appRouterIsR19InRange: lds r16, appRouterRangeBegin cp r19, r16 brcs appRouterIsR19InRangeClcRet lds r16, appRouterRangeEnd cp r16, r19 brcs appRouterIsR19InRangeClcRet sec rjmp appRouterIsR19InRange_end appRouterIsR19InRangeClcRet: clc appRouterIsR19InRange_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appRouterSendDenyAddrR19ToDev1 ; ; @param R19 address to send ; @clobbers R16, R17, R18, R19, R20, R21, X, Y appRouterSendDenyAddrR19ToDev1: ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny addr rjmp appRouterSendAddrMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y) ; @end ; --------------------------------------------------------------------------- ; @routine appRouterSendAddrMsgToDev1 ; ; @param R18 command ; @param R19 address to send ; @clobbers R16 (R17, R18, R19, R20, R21, X, Y) appRouterSendAddrMsgToDev1: bigcall NET_Buffer_Alloc ; (R16, R17, X) brcc appRouterSendAddrMsgToDev1_end push r16 adiw xh:xl, 1 bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21) sbiw xh:xl, 1 pop r16 rcall appRouterSendMsgToDev1 ; (R16, R17, R18, R24, R25, X, Y) appRouterSendAddrMsgToDev1_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appRouterSendRangeMsgToDev1 ; ; @param R18 msg code ; @return CFLAG set if message enqueued, cleared on error ; @clobbers (R16, R17, R18, R19, R20, R21, R24, R25, X, Y) appRouterSendRangeMsgToDev1: bigcall NET_Buffer_Alloc ; (R16, R17, X) brcc appRouterSendRangeMsgToDev1_end push r16 lds r20, appRouterRangeBegin lds r21, appRouterRangeEnd adiw xh:xl, 1 bigcall NETMSG_Range_Write ; (R16, R17, R18, R19, R20, R21) sbiw xh:xl, 1 pop r16 rcall appRouterSendMsgToDev1 ; (R16, R17, R18, R24, R25, X, Y) appRouterSendRangeMsgToDev1_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appRouterSendMsgToDev1 ; ; @param R16 num of allocated buffer ; @param X msg to send (points to start of allocated buffer, e.g. buffer header) ; @return CFLAG set if message enqueued, cleared on error ; @clobbers Y (R16, R17, R18, R24, R25, X) appRouterSendMsgToDev1: ldi yl, LOW(netInterfaceData2) ldi yh, HIGH(netInterfaceData2) bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X) brcs appRouterSendMsgToDev1_end bigcall NET_Buffer_ReleaseByNum ; (R16, X) ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW rcall NET_Interface_IncCounter16 ; (R24, R25) clc appRouterSendMsgToDev1_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appRouterHandleRebootRequest ; ; Doesn't return if reboot msg is valid. ; ; @param X pointer to received message appRouterHandleRebootRequest: rcall NETMSG_RebootRequestRead brcc appRouterHandleRebootRequest_end ; reboot cli bigjmp BOOTLOADER_ADDR appRouterHandleRebootRequest_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appRouterHandlePingRequest ; ; @param X pointer to received message appRouterHandlePingRequest: ld r17, X lds r16, (netInterfaceData+NET_IFACE_OFFS_ADDRESS) cp r16, r17 breq appRouterHandlePingRequest_forMe cpi r17, 0xff breq appRouterHandlePingRequest_forMe clc rjmp appRouterHandlePingRequest_end appRouterHandlePingRequest_forMe: adiw xh:xl, NETMSG_OFFS_SRCADDR ld r17, X sbiw xh:xl, NETMSG_OFFS_SRCADDR push r17 bigcall NET_Buffer_Alloc ; (R16, R17, X) pop r17 brcc appRouterHandlePingRequest_end ; jmp on error push r16 ; buffer num mov r16, r17 ; DEST addr adiw xh:xl, 1 ldi yl, LOW(netInterfaceData) ldi yh, HIGH(netInterfaceData) bigcall NETMSG_Pong_Write ; (R16, R17, R18, R19, R20, X) sbiw xh:xl, 1 pop r16 ; buffer num bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X) appRouterHandlePingRequest_end: ret ; --------------------------------------------------------------------------- ; @routine appRouterCheckRecvdMsg ; ; Read messages from either interface and forward to the other one. ; ; @return CFLAG set if something done, cleared otherwise appRouterCheckRecvdMsg: rcall NET_PeekNextIncomingMsgNum ; check read queue (bufNum->r16) brcc appRouterCheckRecvdMsg_end ; no msg, jmp rcall NET_Buffer_Locate ; (R17) rcall appRouterHandleRouterMsgWithHdr ; filter out router msgs brcs appRouterCheckRecvdMsg_removeMsg ; handled by router code, don't forward ; let system handle incoming messages adiw xh:xl, 1 rcall appRouterLetSysHandleMsg sbiw xh:xl, 1 ; forward to other interface ld r17, X andi r17, (1<