🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
454 lines
12 KiB
Markdown
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*
|