diff --git a/ap_fw/main.c b/ap_fw/main.c index ee24df17..2a950f94 100644 --- a/ap_fw/main.c +++ b/ap_fw/main.c @@ -49,6 +49,7 @@ struct MacFrameBcast { #define PKT_BLOCK_PART 0xE8 #define PKT_XFER_COMPLETE 0xEA #define PKT_XFER_COMPLETE_ACK 0xEB +#define PKT_CANCEL_XFER 0xEC struct AvailDataReq { uint8_t checksum; @@ -113,7 +114,6 @@ struct blockRequest { struct blockRequestAck { uint8_t checksum; uint16_t pleaseWaitMs; - uint8_t cancelXfer; } __packed; struct espPendingData { @@ -169,7 +169,9 @@ uint32_t __xdata nextBlockAttempt = 0; // reference time for when uint8_t seq = 0; // holds current sequence number for transmission uint8_t __xdata blockbuffer[BLOCK_XFER_BUFFER_SIZE]; // block transfer buffer uint8_t lastAckMac[8] = {0}; + void sendXferCompleteAck(uint8_t *dst); +void sendCancelXfer(uint8_t *dst); // tools void addCRC(void *p, uint8_t len) { @@ -231,7 +233,9 @@ uint8_t __xdata getPacketType(void *__xdata buffer) { int8_t findSlotForMac(const uint8_t *mac) { for (uint8_t __xdata c = 0; c < MAX_PENDING_MACS; c++) { if (u64_isEq((uint64_t __xdata *)mac, (uint64_t __xdata *)&(pendingDataArr[c].targetMac))) { // this costs 1 sloc :( - return c; + if (pendingDataArr[c].attemptsLeft != 0) { + return c; + } } } return -1; @@ -244,10 +248,27 @@ int8_t findFreeSlot() { } return -1; } +int8_t findSlotForVer(const uint8_t *ver) { + for (uint8_t __xdata c = 0; c < MAX_PENDING_MACS; c++) { + // if (u64_isEq((uint64_t __xdata *)ver, (uint64_t __xdata *)&(pendingDataArr[c].availdatainfo.dataVer))) { + if (memcmp(ver, ((uint8_t __xdata *)&(pendingDataArr[c].availdatainfo.dataVer)), 8) == 0) { + if (pendingDataArr[c].attemptsLeft != 0) return c; + } + } + return -1; +} +void deleteAllPendingDataForVer(const uint8_t *ver) { + int8_t slot = -1; + do { + slot = findSlotForVer(ver); + if (slot != -1) pendingDataArr[slot].attemptsLeft = 0; + } while (slot != -1); +} // processing serial data #define ZBS_RX_WAIT_HEADER 0 #define ZBS_RX_WAIT_SDA 1 +#define ZBS_RX_WAIT_CANCEL 2 void processSerial(uint8_t lastchar) { // uartTx(lastchar); echo switch (RXState) { @@ -263,6 +284,12 @@ void processSerial(uint8_t lastchar) { serialbufferp = serialbuffer; break; } + if (strncmp(cmdbuffer, "CXD>", 4) == 0) { + RXState = ZBS_RX_WAIT_CANCEL; + bytesRemain = sizeof(struct pendingData); + serialbufferp = serialbuffer; + break; + } if (strncmp(cmdbuffer, "VER?", 4) == 0) { pr("VER>%04X\n", version); } @@ -294,6 +321,22 @@ void processSerial(uint8_t lastchar) { RXState = ZBS_RX_WAIT_HEADER; } break; + case ZBS_RX_WAIT_CANCEL: + *serialbufferp = lastchar; + serialbufferp++; + bytesRemain--; + if (bytesRemain == 0) { + if (checkCRC(serialbuffer, sizeof(struct pendingData))) { + struct pendingData *pd = (struct pendingData *)serialbuffer; + deleteAllPendingDataForVer((uint8_t *)&pd->availdatainfo.dataVer); + pr("ACK>\n"); + } else { + pr("NOK>\n"); + } + + RXState = ZBS_RX_WAIT_HEADER; + } + break; } } @@ -348,7 +391,16 @@ void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) { struct MacFrameNormal *__xdata rxHeader = (struct MacFrameNormal *)buffer; struct blockRequest *__xdata blockReq = (struct blockRequest *)(buffer + sizeof(struct MacFrameNormal) + 1); if (!checkCRC(blockReq, sizeof(struct blockRequest))) return; - // todo: actually do something with the block request + + + // check if we have data for this mac + if(findSlotForMac(rxHeader->src)==-1){ + // no data for this mac, politely tell it to fuck off + sendCancelXfer(rxHeader->src); + return; + } + + bool __xdata requestDataDownload = false; if ((blockReq->blockId != requestedData.blockId) || (!u64_isEq((const uint64_t __xdata *)&blockReq->ver, (const uint64_t __xdata *)&requestedData.ver))) { // requested block isn't already in the buffer @@ -390,8 +442,6 @@ void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) { } blockStartTimer = timerGet() + blockRequestAck->pleaseWaitMs * TIMER_TICKS_PER_MS; - blockRequestAck->cancelXfer = 0; - memcpy(txHeader->src, mSelfMac, 8); memcpy(txHeader->dst, rxHeader->src, 8); @@ -468,10 +518,9 @@ void processAvailDataReq(uint8_t *buffer) { txHeader->seq = seq++; addCRC(availDataInfo, sizeof(struct AvailDataInfo)); radioTx(radiotxbuffer); - memset(lastAckMac, 0, 8); // reset lastAckMac, so we can record if we've received exactly one ack packet + memset(lastAckMac, 0, 8); // reset lastAckMac, so we can record if we've received exactly one ack packet espNotifyAvailDataReq(availDataReq, rxHeader->src); } - void processXferComplete(uint8_t *buffer) { struct MacFrameNormal *rxHeader = (struct MacFrameNormal *)buffer; sendXferCompleteAck(rxHeader->src); @@ -530,6 +579,21 @@ void sendXferCompleteAck(uint8_t *dst) { frameHeader->pan = dstPan; radioTx(radiotxbuffer); } +void sendCancelXfer(uint8_t *dst) { + struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1); + memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal)); + radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_CANCEL_XFER; + radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING; + memcpy(frameHeader->src, mSelfMac, 8); + memcpy(frameHeader->dst, dst, 8); + frameHeader->fcs.frameType = 1; + frameHeader->fcs.panIdCompressed = 1; + frameHeader->fcs.destAddrType = 3; + frameHeader->fcs.srcAddrType = 3; + frameHeader->seq = seq++; + frameHeader->pan = dstPan; + radioTx(radiotxbuffer); +} // main loop void main(void) { diff --git a/tag_fw/syncedproto.c b/tag_fw/syncedproto.c index cb390b2d..42e28648 100644 --- a/tag_fw/syncedproto.c +++ b/tag_fw/syncedproto.c @@ -49,8 +49,7 @@ struct MacFrameBcast { uint8_t src[8]; } __packed; -#define PKT_TIMING_REQ 0xE0 -#define PKT_TIMING_RESPONSE 0xE1 + #define PKT_AVAIL_DATA_REQ 0xE5 #define PKT_AVAIL_DATA_INFO 0xE6 #define PKT_BLOCK_PARTIAL_REQUEST 0xE7 @@ -59,17 +58,7 @@ struct MacFrameBcast { #define PKT_BLOCK_PART 0xE8 #define PKT_XFER_COMPLETE 0xEA #define PKT_XFER_COMPLETE_ACK 0xEB -#define PKT_SYNC_BURST 0xEF - -struct timingResponse { - uint8_t checksum; - uint32_t burstInterval; // time between burst-start - uint8_t burstLength; // in packets; due to use of sequence field, limited to a 256-packet burst - uint16_t burstLengthMs; // burst length in ms - uint32_t timerValue; // current timer value (used to sync up other RC timers/oscillators) - uint32_t burstIntervalRemaining; // time until the next sync burst - uint8_t dataAvailable; -} __packed; +#define PKT_CANCEL_XFER 0xEC struct AvailDataReq { uint8_t checksum; @@ -129,7 +118,6 @@ struct blockRequest { struct blockRequestAck { uint8_t checksum; uint16_t pleaseWaitMs; - uint8_t cancelXfer; } __packed; #define TIMER_TICKS_PER_MS 1333UL @@ -254,7 +242,7 @@ void initAfterWake() { initRadio(); } void doSleep(uint32_t __xdata t) { - pr("s=%lu\n ", t/1000); + pr("s=%lu\n ", t / 1000); powerPortsDownForSleep(); // sleepy sleepForMsec(t); @@ -327,16 +315,16 @@ struct AvailDataInfo *__xdata getAvailDataInfo() { dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS; return NULL; } -void processBlockPart(struct blockPart *bp) { +bool processBlockPart(struct blockPart *bp) { uint16_t __xdata start = bp->blockPart * BLOCK_PART_DATA_SIZE; uint16_t __xdata size = BLOCK_PART_DATA_SIZE; // validate if it's okay to copy data if (bp->blockId != curBlock.blockId) { // pr("got a packet for block %02X\n", bp->blockId); - return; + return false; } - if (start >= (sizeof(blockXferBuffer) - 1)) return; - if (bp->blockPart > BLOCK_MAX_PARTS) return; + if (start >= (sizeof(blockXferBuffer) - 1)) return false; + if (bp->blockPart > BLOCK_MAX_PARTS) return false; if ((start + size) > sizeof(blockXferBuffer)) { size = sizeof(blockXferBuffer) - start; } @@ -345,6 +333,9 @@ void processBlockPart(struct blockPart *bp) { xMemCopy((void *)(blockXferBuffer + start), (const void *)bp->data, size); // we don't need this block anymore, set bit to 0 so we don't request it again curBlock.requestedParts[bp->blockPart / 8] &= ~(1 << (bp->blockPart % 8)); + return true; + } else { + return false; } } bool blockRxLoop(uint32_t timeout) { @@ -356,9 +347,8 @@ bool blockRxLoop(uint32_t timeout) { int8_t __xdata ret = commsRxUnencrypted(inBuffer); if (ret > 1) { if (getPacketType(inBuffer) == PKT_BLOCK_PART) { - success = true; struct blockPart *bp = (struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1); - processBlockPart(bp); + success = processBlockPart(bp); } } } @@ -369,7 +359,6 @@ bool blockRxLoop(uint32_t timeout) { struct blockRequestAck *__xdata continueToRX() { struct blockRequestAck *ack = (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1); ack->pleaseWaitMs = 0; - ack->cancelXfer = 0; return ack; } void sendBlockRequest() { @@ -421,6 +410,8 @@ struct blockRequestAck *__xdata performBlockRequest() { // processBlockPart((struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1)); return continueToRX(); break; + case PKT_CANCEL_XFER: + return NULL; default: pr("pkt w/type %02X\n", getPacketType(inBuffer)); break; @@ -681,9 +672,9 @@ void doDataDownload(struct AvailDataInfo *__xdata avail) { // do transfer! uint8_t __xdata blockRequestAttempt = 0; + uint8_t __xdata blockValidateAttempt = 0; while (!curXferComplete) { // this while loop loops until the transfer has been completed, or we get tired for other reasons - blockRequestAttempt = 0; startdownload:; #ifdef DEBUGBLOCKS pr("REQ %d[", curBlock.blockId); @@ -703,15 +694,10 @@ void doDataDownload(struct AvailDataInfo *__xdata avail) { // DO BLOCK REQUEST - request a block, get an ack with timing info (hopefully) struct blockRequestAck *__xdata ack = performBlockRequest(); if (ack == NULL) { - pr("no reply on gblockrequest\n"); - // didn't get an ack :( we'll probably try again later - return; - } else if (ack->cancelXfer == 1) { - // we were asked to cancel the transfer by the AP - pr("transfer cancelled by AP\n"); + pr("Cancelled request\n"); return; } else { - // got an ack + // got an ack! } // SLEEP - until the AP is ready with the data @@ -764,7 +750,8 @@ void doDataDownload(struct AvailDataInfo *__xdata avail) { if (blockComplete) { if (validateBlockData()) { // checked and found okay - requestPartialBlock = false; + requestPartialBlock = false; // next block is going to be requested from the ESP32 by the AP + blockValidateAttempt = 0; switch (curBlock.type) { case DATATYPE_IMG: case DATATYPE_IMGRAW: @@ -776,6 +763,11 @@ void doDataDownload(struct AvailDataInfo *__xdata avail) { } } else { // block checked, but failed validation. Mark all parts for this block as 'request' + blockValidateAttempt++; + if (blockValidateAttempt > 5) { + pr("bailing on download, 0 blockparts rx'd\n"); + return; + } for (uint8_t c = 0; c < partsThisBlock; c++) { curBlock.requestedParts[c / 8] |= (1 << (c % 8)); } @@ -905,6 +897,6 @@ void mainProtocolLoop(void) { } else { } } - doSleep(getNextSleep()*1000UL); + doSleep(getNextSleep() * 1000UL); } } \ No newline at end of file