Files
pi-pm3/FIELD_STRENGTH_REPORTING_RESEARCH.md
michael 4f35df1781 Initial commit - Phase 3/4
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 13:46:22 -08:00

454 lines
12 KiB
Markdown

# 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*