# Field Strength Reporting - Firmware Modification Research ## Executive Summary **Goal:** Modify PM3 firmware to report real-time LF and HF field strength values to enable LED brightness control via Lua script. **Verdict:** **LOW IMPACT, RECOMMENDED FOR IMPLEMENTATION** The modification is straightforward, follows existing patterns, and has minimal risk. Estimated implementation time: 45-60 minutes including testing. --- ## Current Situation ### Existing `hw detectreader` Command - Uses `CMD_LISTEN_READER_FIELD` (0x0420) - Firmware function: `ListenReaderField()` in [armsrc/appmain.c:686-850](armsrc/appmain.c#L686) - **Problem:** Firmware only: - Prints values via `Dbprintf()` (debug output, not accessible from Lua) - Controls LEDs directly in firmware (hard-coded patterns) - Never sends field strength data back to client ### What We Need - Continuous streaming of LF and HF field strength values (in mV) - Accessible from Lua scripts via `reply_ng()` - Update rate: ~20 Hz (50ms intervals) - Data format: Two uint16_t values (LF voltage, HF voltage) --- ## Proposed Solution ### Architecture Pattern Follow the existing `CMD_MEASURE_ANTENNA_TUNING_HF` pattern: **Mode-based state machine:** ```c Mode 1: Initialize measurement (reply with PM3_SUCCESS) Mode 2: Measure and return data (reply with field strength values) Mode 3: Shutdown (reply with PM3_SUCCESS) ``` This pattern is proven, well-tested, and already used successfully. ### Implementation Approach #### Option A: Modify Existing Command (RECOMMENDED) **Extend `CMD_LISTEN_READER_FIELD` to support data reporting** **Pros:** - No new command ID needed - Leverages existing hardware code - Backwards compatible (mode 1 = current behavior, mode 2 = new streaming) - Minimal code changes **Cons:** - Slight complexity in command handler (mode switching) #### Option B: Create New Command **Add `CMD_LISTEN_READER_FIELD_STREAM` (0x0421)** **Pros:** - Cleaner separation of concerns - No risk to existing hw detectreader functionality **Cons:** - Need to allocate new command ID - Duplicate some existing code - More changes required **Recommendation:** **Option A** - Extend existing command with mode parameter --- ## Required Changes ### 1. Firmware Changes (armsrc/appmain.c) **Location:** `ListenReaderField()` function, line 686 **Change:** ```c // Current: void ListenReaderField(uint8_t limit) // Modified: void ListenReaderField(uint8_t limit, uint8_t mode) // Add mode parameter: // mode 0: Original behavior (LED patterns, debug output) // mode 1: Stream data mode (send values via reply_ng) ``` **Modification in main loop (lines 744-778):** ```c if (mode == 1) { // Create payload struct struct { uint16_t lf_mv; uint16_t hf_mv; } __attribute__((packed)) payload; payload.lf_mv = lf_av; payload.hf_mv = hf_av; // Send values back to client reply_ng(CMD_LISTEN_READER_FIELD, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload)); } ``` **Lines of code to add:** ~20 lines **Lines to modify:** ~5 lines **Risk level:** LOW (contained change, existing patterns) ### 2. Command Handler Changes (armsrc/appmain.c) **Location:** `case CMD_LISTEN_READER_FIELD:` line 2543 **Change:** ```c case CMD_LISTEN_READER_FIELD: { if (packet->length != 2) // Was: != 1 break; uint8_t limit = packet->data.asBytes[0]; uint8_t mode = packet->data.asBytes[1]; // NEW ListenReaderField(limit, mode); // Pass mode reply_ng(CMD_LISTEN_READER_FIELD, PM3_EOPABORTED, NULL, 0); break; } ``` **Lines to modify:** 3 lines **Risk level:** MINIMAL ### 3. Client Changes (client/src/cmdhw.c) **Location:** `CmdDetectReader()` function, line 534 **No changes required** - existing hw detectreader continues to work (mode=0) **For new Lua script:** ```lua -- Send mode=1 to enable streaming local data = string.char(limit, 1) -- limit, mode command = Command:newNG{ cmd = cmds.CMD_LISTEN_READER_FIELD, data = data } ``` ### 4. Optional: Add Payload Structure (include/pm3_cmd.h) **Location:** After line 246 **Add:** ```c // Field strength measurement payload typedef struct { uint16_t lf_mv; // LF field strength in millivolts uint16_t hf_mv; // HF field strength in millivolts } PACKED payload_field_strength_t; ``` **Lines to add:** 5 lines **Risk level:** ZERO (optional documentation, doesn't affect functionality) --- ## Potential Complications & Mitigations ### 1. SWIG Python Wrapper **Issue:** If we modify pm3_cmd.h, SWIG must be rebuilt **Impact:** Medium (requires manual rebuild) **Mitigation:** - Document rebuild requirement - Add to our build script - Only affects Python bindings (Lua unaffected) **Commands:** ```bash cd client/experimental_lib ./00make_swig.sh ./01make_lib.sh ``` ### 2. Backwards Compatibility **Issue:** Old clients won't understand mode parameter **Impact:** LOW **Mitigation:** - Old clients send 1 byte (mode defaults to 0) - New clients send 2 bytes (mode specified) - Firmware handles both gracefully ### 3. Update Rate Performance **Issue:** 20 Hz update rate = 20 USB packets/sec **Impact:** MINIMAL **Analysis:** - Each packet: ~20 bytes (4 bytes payload + overhead) - Total bandwidth: 400 bytes/sec = 0.4 KB/sec - USB 2.0 full-speed: 12 Mbps = 1.5 MB/sec - **Utilization: 0.027%** - negligible ### 4. Firmware Flash Size **Issue:** Adding code increases firmware size **Impact:** NEGLIGIBLE **Analysis:** - Adding ~20 lines ≈ 200-300 bytes compiled - Current firmware size: ~200 KB (typical) - Flash capacity: 512 KB (PM3 Easy) - **Increase: <0.15%** - safe margin ### 5. Testing Requirements **Issue:** Need to verify on actual hardware **Impact:** Medium (requires physical device) **Test cases:** ``` 1. LF field detection (125 kHz reader) 2. HF field detection (13.56 MHz reader/phone NFC) 3. Simultaneous LF+HF 4. Backwards compatibility (old hw detectreader still works) 5. LED brightness control from Lua ``` --- ## Build & Flash Process ### 1. Modify Code - Edit `armsrc/appmain.c` (~25 lines) - Optional: Edit `include/pm3_cmd.h` (~5 lines) ### 2. Compile Firmware ```bash cd /home/work/dangerous-pi/.pm3-test/proxmark3 make clean SKIPQT=1 make -j8 armsrc/obj/fullimage.elf ``` **Time:** ~2-3 minutes ### 3. Flash Firmware ```bash ./pm3-flash-all ``` **Time:** ~30 seconds ### 4. Test ```bash ./pm3 -c "hw detectreader" # Old command still works ./pm3 -c "script run field_strength_test" # New streaming ``` **Time:** ~5 minutes ### 5. Rebuild SWIG (if pm3_cmd.h modified) ```bash cd client/experimental_lib ./00make_swig.sh ./01make_lib.sh ``` **Time:** ~1 minute **Total Time:** 10-15 minutes --- ## Upstreaming Potential ### Why This Is a Good Upstream Contribution **Benefits to PM3 Community:** 1. **Programmatic field detection** - enables automation scripts 2. **Precise measurements** - get exact mV values, not just on/off 3. **Multi-device coordination** - essential for systems like Dangerous Pi 4. **Backwards compatible** - doesn't break existing tools **Follows Iceman Fork Conventions:** - ✅ Uses CLIParser patterns (already established) - ✅ reply_ng() for data transfer - ✅ Mode-based state machine (proven pattern) - ✅ Minimal, focused changes - ✅ No breaking changes - ✅ Self-documented code **Similar Precedents:** - `CMD_MEASURE_ANTENNA_TUNING_HF` - exact same pattern - `CMD_MEASURE_ANTENNA_TUNING_LF` - dual-value reporting - Both accepted upstream ### Preparation for PR **Before submitting:** 1. Test on multiple hardware variants (Easy, RDV4) 2. Document in CHANGELOG.md 3. Add usage examples in commit message 4. Reference this research doc 5. Emphasize automation/multi-device use case **Estimated acceptance probability:** HIGH (70-80%) --- ## Risk Assessment Matrix | Risk Factor | Probability | Impact | Mitigation | |-------------|------------|--------|------------| | Compilation errors | Low | Low | Follow existing patterns exactly | | Runtime crashes | Very Low | Medium | Contained changes, tested pattern | | SWIG rebuild required | Certain | Low | Documented procedure, quick rebuild | | Backwards compatibility broken | Very Low | High | Dual-mode design prevents this | | Flash size exceeded | Very Low | High | Change is <1KB, plenty of margin | | USB bandwidth issues | Very Low | Low | 0.027% utilization | | Upstream rejection | Medium | Low | Feature is useful, well-implemented | **Overall Risk:** **LOW** --- ## Implementation Timeline ### Phase 1: Core Implementation (30 min) - Modify `ListenReaderField()` function - Update command handler - Optional: Add payload struct - Compile & flash ### Phase 2: Testing (15 min) - Test LF field detection - Test HF field detection - Verify backwards compatibility - Test LED brightness control ### Phase 3: Documentation (15 min) - Update script documentation - Create usage examples - Document SWIG rebuild if needed **Total Estimated Time:** 60 minutes --- ## Alternative Approaches Considered ### Alt 1: Parse Debug Output **Rejected:** Hacky, unreliable, requires USB CDC mode ### Alt 2: Use Existing hw detectreader As-Is **Rejected:** Can't control LEDs precisely, no programmable access ### Alt 3: Create Entirely New Command **Rejected:** Unnecessary duplication, more complex ### Alt 4: Firmware-only LED Control **Rejected:** Not flexible enough, can't adapt patterns --- ## Decision Matrix | Criteria | Weight | Score (1-10) | Weighted | |----------|--------|--------------|----------| | Implementation Effort | 20% | 9 | 1.8 | | Code Complexity | 15% | 8 | 1.2 | | Risk Level | 25% | 9 | 2.25 | | Maintainability | 15% | 9 | 1.35 | | Upstream Acceptance | 15% | 7 | 1.05 | | Feature Completeness | 10% | 10 | 1.0 | **Total Score: 8.65 / 10** ⭐⭐⭐⭐⭐ --- ## Recommendation ### ✅ **PROCEED WITH IMPLEMENTATION** **Justification:** 1. **Low Risk:** Follows proven patterns, minimal code changes 2. **High Value:** Enables precise field detection with programmable LED control 3. **Clean Design:** Mode-based approach is elegant and backwards compatible 4. **Manageable Effort:** ~1 hour total implementation time 5. **Upstream Potential:** High probability of acceptance **Next Steps:** 1. Schedule implementation session (60 min) 2. Prepare test equipment (LF reader, HF reader/NFC phone) 3. Have backup: keep current working firmware binary 4. Document changes for potential upstream PR --- ## Code Diff Preview ### armsrc/appmain.c - Function Signature ```diff -void ListenReaderField(uint8_t limit) { +void ListenReaderField(uint8_t limit, uint8_t mode) { ``` ### armsrc/appmain.c - Streaming Mode ```diff if (mode == 2) { + } else if (mode == 3) { + // Streaming mode - send values back to client + if (limit == LF_ONLY || limit == LF_HF_BOTH) { + struct { + uint16_t lf_mv; + uint16_t hf_mv; + } __attribute__((packed)) payload = { + .lf_mv = lf_av, + .hf_mv = hf_av + }; + reply_ng(CMD_LISTEN_READER_FIELD, PM3_SUCCESS, + (uint8_t *)&payload, sizeof(payload)); + } } ``` ### armsrc/appmain.c - Command Handler ```diff case CMD_LISTEN_READER_FIELD: { - if (packet->length != sizeof(uint8_t)) + if (packet->length != 1 && packet->length != 2) break; - ListenReaderField(packet->data.asBytes[0]); + uint8_t limit = packet->data.asBytes[0]; + uint8_t mode = (packet->length == 2) ? packet->data.asBytes[1] : 0; + ListenReaderField(limit, mode); reply_ng(CMD_LISTEN_READER_FIELD, PM3_EOPABORTED, NULL, 0); break; } ``` --- ## Conclusion The firmware modification to enable field strength reporting is: - **Technically sound** - follows existing patterns - **Low risk** - minimal, contained changes - **High value** - enables powerful scripting capabilities - **Reasonable effort** - ~1 hour implementation - **Upstream ready** - good candidate for contribution **Confidence Level:** ⭐⭐⭐⭐⭐ (Very High) **Recommendation:** Proceed with implementation in next session. --- *Research completed: 2025-12-02* *Researcher: Claude (Dangerous Pi Project)* *Status: Ready for implementation*