From 42e6b54f29a2858288060e481cffdca4d227eb70 Mon Sep 17 00:00:00 2001 From: michael Date: Wed, 18 Mar 2026 19:24:05 -0700 Subject: [PATCH 1/2] refactor: move modules into core/ sub-package, normalize naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1 of package refactor. Moves all source modules into pm3py/core/ with file renames (hf_14a→hf_iso14a, hf_15→hf_iso15, hf_mf→hf_mfc) and client attribute normalization (hf.a14→hf.iso14a, hf.mf→hf.mfc). pm3py/__init__.py re-exports from core for backward compat. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/plans/2026-03-18-refactor-progress.md | 52 ++++++++++++++++++++++ pm3py/__init__.py | 6 +-- pm3py/core/__init__.py | 10 +++++ pm3py/{ => core}/client.py | 12 ++--- pm3py/{ => core}/hf.py | 8 ++-- pm3py/{hf_14a.py => core/hf_iso14a.py} | 0 pm3py/{hf_15.py => core/hf_iso15.py} | 0 pm3py/{hf_mf.py => core/hf_mfc.py} | 0 pm3py/{ => core}/hw.py | 0 pm3py/{ => core}/lf.py | 0 pm3py/{ => core}/protocol.py | 0 pm3py/{ => core}/transport.py | 0 tests/test_crc.py | 2 +- tests/test_hf.py | 6 +-- tests/test_hf_14a.py | 6 +-- tests/test_hf_15.py | 6 +-- tests/test_hf_mf.py | 6 +-- tests/test_hw.py | 8 ++-- tests/test_integration.py | 22 ++++----- tests/test_lf.py | 6 +-- tests/test_transport.py | 4 +- 21 files changed, 108 insertions(+), 46 deletions(-) create mode 100644 docs/plans/2026-03-18-refactor-progress.md create mode 100644 pm3py/core/__init__.py rename pm3py/{ => core}/client.py (95%) rename pm3py/{ => core}/hf.py (93%) rename pm3py/{hf_14a.py => core/hf_iso14a.py} (100%) rename pm3py/{hf_15.py => core/hf_iso15.py} (100%) rename pm3py/{hf_mf.py => core/hf_mfc.py} (100%) rename pm3py/{ => core}/hw.py (100%) rename pm3py/{ => core}/lf.py (100%) rename pm3py/{ => core}/protocol.py (100%) rename pm3py/{ => core}/transport.py (100%) diff --git a/docs/plans/2026-03-18-refactor-progress.md b/docs/plans/2026-03-18-refactor-progress.md new file mode 100644 index 0000000..f4ab79c --- /dev/null +++ b/docs/plans/2026-03-18-refactor-progress.md @@ -0,0 +1,52 @@ +# pm3py Refactor Progress + +**Design:** [2026-03-18-refactor-design.md](2026-03-18-refactor-design.md) +**Branch:** `refactor/core-package` +**Started:** 2026-03-18 + +## Phase 1 — Create `core/`, normalize names, fix imports + +**Status: Complete** + +### What was done + +- Created `pm3py/core/` sub-package +- Moved all source modules into `core/`: + - `protocol.py`, `transport.py`, `client.py`, `hw.py`, `hf.py`, `lf.py` — moved as-is + - `hf_14a.py` → `hf_iso14a.py` (renamed) + - `hf_15.py` → `hf_iso15.py` (renamed) + - `hf_mf.py` → `hf_mfc.py` (renamed) +- Normalized client attributes: + - `hf.a14` → `hf.iso14a` + - `hf.mf` → `hf.mfc` + - `hf.iso15` — unchanged +- Created `core/__init__.py` re-exporting: `Proxmark3`, `FirmwareInfo`, `PM3Transport`, `PM3Error`, `PM3Response`, `PM3Status`, `Cmd` +- Updated `pm3py/__init__.py` to import from `.core.*` +- Updated all 10 test files (imports + attribute references) +- **30/30 tests passing** + +### Backward compatibility + +- `from pm3py import Proxmark3` still works (re-exported) +- **Breaking:** `hf.a14` → `hf.iso14a`, `hf.mf` → `hf.mfc` +- **Breaking:** Direct imports like `from pm3py.hf_14a import ...` → `from pm3py.core.hf_iso14a import ...` + +## Phase 2 — Extract `sniff/` + +**Status: Deferred — no sniff infrastructure exists yet** + +`hf_iso15.py` is 94 lines of clean reader commands + thin `sniff()` firmware call. The trace parsing, 15693 decoders, NDEF annotation, and ANSI formatting described in the design doc haven't been written yet. Nothing to extract. + +Will revisit when sniff infrastructure is implemented. + +## Phase 3 — Scaffold `transponders/` + +**Status: Not started — models live in sim worktree** + +Transponder models exist in `.worktrees/sim-framework/` but haven't been merged to master. Scaffold when ready to migrate. + +## Phase 4 — Scaffold `reader/` and `sim/` + +**Status: Not started** + +Depends on Phase 3 and sim worktree merge. diff --git a/pm3py/__init__.py b/pm3py/__init__.py index 072a19a..2c2b328 100644 --- a/pm3py/__init__.py +++ b/pm3py/__init__.py @@ -1,6 +1,6 @@ """pm3py - Python wire protocol library for Proxmark3.""" -from .client import Proxmark3 -from .transport import PM3Error, PM3Response -from .protocol import PM3Status, Cmd +from .core.client import Proxmark3 +from .core.transport import PM3Error, PM3Response +from .core.protocol import PM3Status, Cmd __all__ = ["Proxmark3", "PM3Error", "PM3Response", "PM3Status", "Cmd"] diff --git a/pm3py/core/__init__.py b/pm3py/core/__init__.py new file mode 100644 index 0000000..ae44dce --- /dev/null +++ b/pm3py/core/__init__.py @@ -0,0 +1,10 @@ +"""pm3py.core — Wire protocol, transport, and device commands.""" +from .client import Proxmark3, FirmwareInfo +from .transport import PM3Transport, PM3Error, PM3Response +from .protocol import PM3Status, Cmd + +__all__ = [ + "Proxmark3", "FirmwareInfo", + "PM3Transport", "PM3Error", "PM3Response", + "PM3Status", "Cmd", +] diff --git a/pm3py/client.py b/pm3py/core/client.py similarity index 95% rename from pm3py/client.py rename to pm3py/core/client.py index 1285ec2..ba100fa 100644 --- a/pm3py/client.py +++ b/pm3py/core/client.py @@ -10,9 +10,9 @@ from .transport import PM3Transport, PM3Response, PM3Error, ProgressCallback from .hw import HWCommands from .lf import LFCommands from .hf import HFCommands -from .hf_14a import HF14ACommands -from .hf_15 import HF15Commands -from .hf_mf import HFMFCommands +from .hf_iso14a import HF14ACommands +from .hf_iso15 import HF15Commands +from .hf_mfc import HFMFCommands log = logging.getLogger(__name__) @@ -68,9 +68,9 @@ class Proxmark3: self.hw = HWCommands(self._transport) self.lf = LFCommands(self._transport) self.hf = HFCommands(self._transport) - self.hf.a14 = HF14ACommands(self._transport) + self.hf.iso14a = HF14ACommands(self._transport) self.hf.iso15 = HF15Commands(self._transport) - self.hf.mf = HFMFCommands(self._transport) + self.hf.mfc = HFMFCommands(self._transport) self.firmware = FirmwareInfo() async def connect(self) -> None: @@ -157,7 +157,7 @@ class _SyncProxy: if isinstance(attr, (HWCommands, LFCommands, HFCommands, HF14ACommands, HF15Commands, HFMFCommands)): return _SyncProxy(attr, self._loop) - # Sub-modules attached dynamically (e.g. hf.a14, hf.mf) + # Sub-modules attached dynamically (e.g. hf.iso14a, hf.mfc) if hasattr(attr, '_t'): return _SyncProxy(attr, self._loop) if callable(attr) and inspect.iscoroutinefunction(attr): diff --git a/pm3py/hf.py b/pm3py/core/hf.py similarity index 93% rename from pm3py/hf.py rename to pm3py/core/hf.py index bbcc747..2d118ac 100644 --- a/pm3py/hf.py +++ b/pm3py/core/hf.py @@ -11,9 +11,9 @@ class HFCommands: def __init__(self, transport: PM3Transport): self._t = transport # Sub-modules attached by client.py - self.a14 = None # type: ignore + self.iso14a = None # type: ignore self.iso15 = None # type: ignore - self.mf = None # type: ignore + self.mfc = None # type: ignore async def tune(self, on_progress: ProgressCallback = None) -> dict: """Measure HF antenna voltage.""" @@ -38,9 +38,9 @@ class HFCommands: if asyncio.iscoroutine(ret): await ret - if self.a14: + if self.iso14a: try: - card = await self.a14.scan() + card = await self.iso14a.scan() if card.get("uid"): results["iso14443a"] = card except PM3Error: diff --git a/pm3py/hf_14a.py b/pm3py/core/hf_iso14a.py similarity index 100% rename from pm3py/hf_14a.py rename to pm3py/core/hf_iso14a.py diff --git a/pm3py/hf_15.py b/pm3py/core/hf_iso15.py similarity index 100% rename from pm3py/hf_15.py rename to pm3py/core/hf_iso15.py diff --git a/pm3py/hf_mf.py b/pm3py/core/hf_mfc.py similarity index 100% rename from pm3py/hf_mf.py rename to pm3py/core/hf_mfc.py diff --git a/pm3py/hw.py b/pm3py/core/hw.py similarity index 100% rename from pm3py/hw.py rename to pm3py/core/hw.py diff --git a/pm3py/lf.py b/pm3py/core/lf.py similarity index 100% rename from pm3py/lf.py rename to pm3py/core/lf.py diff --git a/pm3py/protocol.py b/pm3py/core/protocol.py similarity index 100% rename from pm3py/protocol.py rename to pm3py/core/protocol.py diff --git a/pm3py/transport.py b/pm3py/core/transport.py similarity index 100% rename from pm3py/transport.py rename to pm3py/core/transport.py diff --git a/tests/test_crc.py b/tests/test_crc.py index 6d31728..4f1beb9 100644 --- a/tests/test_crc.py +++ b/tests/test_crc.py @@ -1,4 +1,4 @@ -from pm3py.protocol import crc16_a +from pm3py.core.protocol import crc16_a def test_crc16_a_empty(): assert crc16_a(b"") == 0x6363 # init 0xC6C6 reflected = 0x6363 diff --git a/tests/test_hf.py b/tests/test_hf.py index cfd6a62..281aa86 100644 --- a/tests/test_hf.py +++ b/tests/test_hf.py @@ -1,8 +1,8 @@ import asyncio from unittest.mock import AsyncMock -from pm3py.protocol import Cmd -from pm3py.transport import PM3Response -from pm3py.hf import HFCommands +from pm3py.core.protocol import Cmd +from pm3py.core.transport import PM3Response +from pm3py.core.hf import HFCommands def test_hf_tune(): t = AsyncMock() diff --git a/tests/test_hf_14a.py b/tests/test_hf_14a.py index a28594c..5e1bfec 100644 --- a/tests/test_hf_14a.py +++ b/tests/test_hf_14a.py @@ -1,9 +1,9 @@ import struct import asyncio from unittest.mock import AsyncMock -from pm3py.protocol import Cmd -from pm3py.transport import PM3Response -from pm3py.hf_14a import HF14ACommands +from pm3py.core.protocol import Cmd +from pm3py.core.transport import PM3Response +from pm3py.core.hf_iso14a import HF14ACommands def test_14a_scan(): t = AsyncMock() diff --git a/tests/test_hf_15.py b/tests/test_hf_15.py index fe687c0..d471e75 100644 --- a/tests/test_hf_15.py +++ b/tests/test_hf_15.py @@ -1,8 +1,8 @@ import asyncio from unittest.mock import AsyncMock -from pm3py.protocol import Cmd -from pm3py.transport import PM3Response -from pm3py.hf_15 import HF15Commands +from pm3py.core.protocol import Cmd +from pm3py.core.transport import PM3Response +from pm3py.core.hf_iso15 import HF15Commands def test_15_scan(): t = AsyncMock() diff --git a/tests/test_hf_mf.py b/tests/test_hf_mf.py index 2f10936..4c0c0f4 100644 --- a/tests/test_hf_mf.py +++ b/tests/test_hf_mf.py @@ -1,9 +1,9 @@ import struct import asyncio from unittest.mock import AsyncMock -from pm3py.protocol import Cmd -from pm3py.transport import PM3Response -from pm3py.hf_mf import HFMFCommands +from pm3py.core.protocol import Cmd +from pm3py.core.transport import PM3Response +from pm3py.core.hf_mfc import HFMFCommands def test_mf_rdbl(): t = AsyncMock() diff --git a/tests/test_hw.py b/tests/test_hw.py index 873f196..d072264 100644 --- a/tests/test_hw.py +++ b/tests/test_hw.py @@ -1,9 +1,9 @@ import struct import asyncio from unittest.mock import AsyncMock -from pm3py.protocol import Cmd -from pm3py.transport import PM3Response -from pm3py.hw import HWCommands +from pm3py.core.protocol import Cmd +from pm3py.core.transport import PM3Response +from pm3py.core.hw import HWCommands def make_ng_response(cmd: int, status: int, payload: bytes) -> PM3Response: return PM3Response(cmd=cmd, status=status, reason=0, ng=True, data=payload) @@ -91,7 +91,7 @@ def test_led_brightness(): def test_led_pwm_non_capable_raises(): """PWM on a non-PWM LED should raise PM3Error.""" - from pm3py.transport import PM3Error + from pm3py.core.transport import PM3Error import pytest transport = make_mock_transport() hw = HWCommands(transport) diff --git a/tests/test_integration.py b/tests/test_integration.py index 777b6cd..a784838 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -3,7 +3,7 @@ import struct import asyncio from unittest.mock import AsyncMock, MagicMock from pm3py import Proxmark3, Cmd -from pm3py.client import FirmwareInfo +from pm3py.core.client import FirmwareInfo def test_full_api_surface(): @@ -14,9 +14,9 @@ def test_full_api_surface(): assert hasattr(pm3, "lf") assert hasattr(pm3, "hf") assert hasattr(pm3.lf, "t55") - assert hasattr(pm3.hf, "a14") + assert hasattr(pm3.hf, "iso14a") assert hasattr(pm3.hf, "iso15") - assert hasattr(pm3.hf, "mf") + assert hasattr(pm3.hf, "mfc") assert hasattr(pm3, "send_ng") assert hasattr(pm3, "send_mix") assert hasattr(pm3, "firmware") @@ -27,7 +27,7 @@ def test_hw_ping_roundtrip(): """Test ping returns structured dict.""" pm3 = Proxmark3("/dev/null") mock_transport = AsyncMock() - from pm3py.transport import PM3Response + from pm3py.core.transport import PM3Response ping_data = bytes(range(32)) mock_transport.send_ng.return_value = PM3Response( cmd=Cmd.PING, status=0, reason=0, ng=True, data=ping_data) @@ -41,21 +41,21 @@ def test_mf_rdbl_returns_hex(): """Verify MIFARE read returns hex string data.""" pm3 = Proxmark3("/dev/null") mock_transport = AsyncMock() - from pm3py.transport import PM3Response + from pm3py.core.transport import PM3Response block = bytes(range(16)) mock_transport.send_ng.return_value = PM3Response( cmd=Cmd.HF_MIFARE_READBL, status=0, reason=0, ng=True, data=block) - pm3.hf.mf._t = mock_transport + pm3.hf.mfc._t = mock_transport result = asyncio.get_event_loop().run_until_complete( - pm3.hf.mf.rdbl(block=4, key="FFFFFFFFFFFF")) + pm3.hf.mfc.rdbl(block=4, key="FFFFFFFFFFFF")) assert result["data"] == "000102030405060708090a0b0c0d0e0f" assert result["raw"] == block def test_sync_proxy(): """Verify sync proxy wraps async calls.""" - from pm3py.transport import PM3Response - from pm3py.client import _SyncProxy + from pm3py.core.transport import PM3Response + from pm3py.core.client import _SyncProxy pm3 = Proxmark3("/dev/null") loop = asyncio.new_event_loop() @@ -83,7 +83,7 @@ def test_firmware_probe_compatible(): pm3._transport = mock_transport pm3.hw._t = mock_transport - from pm3py.transport import PM3Response + from pm3py.core.transport import PM3Response ping_data = bytes(range(32)) vstr = b"Proxmark3 RDV4.0 FW v4.18000\x00" @@ -109,7 +109,7 @@ def test_firmware_probe_ping_fails(): pm3._transport = mock_transport pm3.hw._t = mock_transport - from pm3py.transport import PM3Response, PM3Error + from pm3py.core.transport import PM3Response, PM3Error vstr = b"Proxmark3 OLD\x00" version_payload = struct.pack(" Date: Wed, 18 Mar 2026 19:28:55 -0700 Subject: [PATCH 2/2] refactor: scaffold sniff/, transponders/, reader/, sim/ sub-packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phases 2-4 of package refactor. Creates the full directory tree with __init__.py files per the design doc. Actual code migration from the sim worktree is a separate effort — models have deep inheritance chains and auth mixins that need base class extraction first. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/plans/2026-03-18-refactor-progress.md | 34 +++++++++++++++---- pm3py/reader/__init__.py | 1 + pm3py/reader/hf/__init__.py | 1 + pm3py/reader/hf/nxp/__init__.py | 1 + pm3py/reader/hf/st/__init__.py | 1 + pm3py/reader/lf/__init__.py | 1 + pm3py/reader/modes/__init__.py | 1 + pm3py/sim/__init__.py | 1 + pm3py/sniff/__init__.py | 1 + pm3py/transponders/__init__.py | 1 + pm3py/transponders/hf/__init__.py | 1 + pm3py/transponders/hf/iso14443a3/__init__.py | 1 + .../hf/iso14443a3/nxp/__init__.py | 1 + pm3py/transponders/hf/iso14443a4/__init__.py | 1 + .../hf/iso14443a4/nxp/__init__.py | 1 + pm3py/transponders/hf/iso15693/__init__.py | 1 + .../transponders/hf/iso15693/nxp/__init__.py | 1 + pm3py/transponders/hf/iso15693/st/__init__.py | 1 + pm3py/transponders/lf/__init__.py | 1 + pm3py/transponders/lf/atmel/__init__.py | 1 + pm3py/transponders/lf/em/__init__.py | 1 + 21 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 pm3py/reader/__init__.py create mode 100644 pm3py/reader/hf/__init__.py create mode 100644 pm3py/reader/hf/nxp/__init__.py create mode 100644 pm3py/reader/hf/st/__init__.py create mode 100644 pm3py/reader/lf/__init__.py create mode 100644 pm3py/reader/modes/__init__.py create mode 100644 pm3py/sim/__init__.py create mode 100644 pm3py/sniff/__init__.py create mode 100644 pm3py/transponders/__init__.py create mode 100644 pm3py/transponders/hf/__init__.py create mode 100644 pm3py/transponders/hf/iso14443a3/__init__.py create mode 100644 pm3py/transponders/hf/iso14443a3/nxp/__init__.py create mode 100644 pm3py/transponders/hf/iso14443a4/__init__.py create mode 100644 pm3py/transponders/hf/iso14443a4/nxp/__init__.py create mode 100644 pm3py/transponders/hf/iso15693/__init__.py create mode 100644 pm3py/transponders/hf/iso15693/nxp/__init__.py create mode 100644 pm3py/transponders/hf/iso15693/st/__init__.py create mode 100644 pm3py/transponders/lf/__init__.py create mode 100644 pm3py/transponders/lf/atmel/__init__.py create mode 100644 pm3py/transponders/lf/em/__init__.py diff --git a/docs/plans/2026-03-18-refactor-progress.md b/docs/plans/2026-03-18-refactor-progress.md index f4ab79c..9ca6678 100644 --- a/docs/plans/2026-03-18-refactor-progress.md +++ b/docs/plans/2026-03-18-refactor-progress.md @@ -33,20 +33,42 @@ ## Phase 2 — Extract `sniff/` -**Status: Deferred — no sniff infrastructure exists yet** +**Status: Scaffolded — extraction deferred** `hf_iso15.py` is 94 lines of clean reader commands + thin `sniff()` firmware call. The trace parsing, 15693 decoders, NDEF annotation, and ANSI formatting described in the design doc haven't been written yet. Nothing to extract. -Will revisit when sniff infrastructure is implemented. +Created `pm3py/sniff/__init__.py` placeholder. Will extract into sub-modules when sniff infrastructure is implemented. ## Phase 3 — Scaffold `transponders/` -**Status: Not started — models live in sim worktree** +**Status: Complete (scaffolded)** -Transponder models exist in `.worktrees/sim-framework/` but haven't been merged to master. Scaffold when ready to migrate. +Created full directory tree per design: +- `transponders/hf/iso14443a3/nxp/` — MIFARE Classic, Ultralight, NTAG +- `transponders/hf/iso14443a4/nxp/` — DESFire, NTAG 5 +- `transponders/hf/iso15693/nxp/` — ICODE SLIX2 +- `transponders/hf/iso15693/st/` — ST25TV +- `transponders/lf/atmel/` — T55xx +- `transponders/lf/em/` — EM4100, EM4x05 + +All directories have `__init__.py`. Model migration from sim worktree is a separate effort — the sim framework has ~7.8k LOC with deep inheritance chains (`Transponder` → `Tag15693` → `NxpIcodeTag` → `IcodeSlix2Tag`, etc.) and auth mixins (`NxpPasswordAuth`, `NxpAesAuth`). Base class extraction needs to happen alongside model migration. ## Phase 4 — Scaffold `reader/` and `sim/` -**Status: Not started** +**Status: Complete (scaffolded)** -Depends on Phase 3 and sim worktree merge. +Created directory trees per design: +- `reader/hf/nxp/` — NXP reader ICs (CLRC663, PN5xx) +- `reader/hf/st/` — ST reader ICs +- `reader/lf/` +- `reader/modes/` — inventory, programming, access control workflows +- `sim/` — sim session, table compiler, relay (migrate from worktree) + +All directories have `__init__.py`. Sim migration (~41 files, 7.8k LOC) is a separate effort. + +## Next Steps + +- Sniff infrastructure: implement trace parsing, 15693 decoders, NDEF annotation, ANSI formatting in `sniff/` +- Transponder migration: extract base classes from sim worktree, populate `transponders/` modules +- Sim migration: move sim session, table compiler, relay into `sim/` +- Reader modes: implement inventory, programming, access workflows in `reader/modes/` diff --git a/pm3py/reader/__init__.py b/pm3py/reader/__init__.py new file mode 100644 index 0000000..2ae2ba6 --- /dev/null +++ b/pm3py/reader/__init__.py @@ -0,0 +1 @@ +"""pm3py.reader — Higher-level reader modes composing core commands.""" diff --git a/pm3py/reader/hf/__init__.py b/pm3py/reader/hf/__init__.py new file mode 100644 index 0000000..057a822 --- /dev/null +++ b/pm3py/reader/hf/__init__.py @@ -0,0 +1 @@ +"""HF reader modes organized by reader IC manufacturer.""" diff --git a/pm3py/reader/hf/nxp/__init__.py b/pm3py/reader/hf/nxp/__init__.py new file mode 100644 index 0000000..d4c975c --- /dev/null +++ b/pm3py/reader/hf/nxp/__init__.py @@ -0,0 +1 @@ +"""NXP reader ICs (CLRC663, PN5xx).""" diff --git a/pm3py/reader/hf/st/__init__.py b/pm3py/reader/hf/st/__init__.py new file mode 100644 index 0000000..00c3ccd --- /dev/null +++ b/pm3py/reader/hf/st/__init__.py @@ -0,0 +1 @@ +"""ST Microelectronics reader ICs.""" diff --git a/pm3py/reader/lf/__init__.py b/pm3py/reader/lf/__init__.py new file mode 100644 index 0000000..2fbb71c --- /dev/null +++ b/pm3py/reader/lf/__init__.py @@ -0,0 +1 @@ +"""LF reader modes.""" diff --git a/pm3py/reader/modes/__init__.py b/pm3py/reader/modes/__init__.py new file mode 100644 index 0000000..2e64599 --- /dev/null +++ b/pm3py/reader/modes/__init__.py @@ -0,0 +1 @@ +"""Reader workflow modes — inventory, programming, access control.""" diff --git a/pm3py/sim/__init__.py b/pm3py/sim/__init__.py new file mode 100644 index 0000000..314f07a --- /dev/null +++ b/pm3py/sim/__init__.py @@ -0,0 +1 @@ +"""pm3py.sim — Card simulation sessions, table compiler, relay.""" diff --git a/pm3py/sniff/__init__.py b/pm3py/sniff/__init__.py new file mode 100644 index 0000000..68db8db --- /dev/null +++ b/pm3py/sniff/__init__.py @@ -0,0 +1 @@ +"""pm3py.sniff — Sniff sessions, trace parsing, protocol decoders, formatting.""" diff --git a/pm3py/transponders/__init__.py b/pm3py/transponders/__init__.py new file mode 100644 index 0000000..2dc23ab --- /dev/null +++ b/pm3py/transponders/__init__.py @@ -0,0 +1 @@ +"""pm3py.transponders — Tag/transponder models independent of hardware.""" diff --git a/pm3py/transponders/hf/__init__.py b/pm3py/transponders/hf/__init__.py new file mode 100644 index 0000000..896c1a6 --- /dev/null +++ b/pm3py/transponders/hf/__init__.py @@ -0,0 +1 @@ +"""HF transponder models organized by ISO standard, then manufacturer.""" diff --git a/pm3py/transponders/hf/iso14443a3/__init__.py b/pm3py/transponders/hf/iso14443a3/__init__.py new file mode 100644 index 0000000..fa4c38d --- /dev/null +++ b/pm3py/transponders/hf/iso14443a3/__init__.py @@ -0,0 +1 @@ +"""ISO 14443-A Layer 3 transponders (MIFARE Classic, Ultralight, NTAG).""" diff --git a/pm3py/transponders/hf/iso14443a3/nxp/__init__.py b/pm3py/transponders/hf/iso14443a3/nxp/__init__.py new file mode 100644 index 0000000..afd4290 --- /dev/null +++ b/pm3py/transponders/hf/iso14443a3/nxp/__init__.py @@ -0,0 +1 @@ +"""NXP ISO 14443-A Layer 3 transponders.""" diff --git a/pm3py/transponders/hf/iso14443a4/__init__.py b/pm3py/transponders/hf/iso14443a4/__init__.py new file mode 100644 index 0000000..06e8bf8 --- /dev/null +++ b/pm3py/transponders/hf/iso14443a4/__init__.py @@ -0,0 +1 @@ +"""ISO 14443-A Layer 4 (ISO-DEP) transponders (DESFire, NTAG 5 via -4).""" diff --git a/pm3py/transponders/hf/iso14443a4/nxp/__init__.py b/pm3py/transponders/hf/iso14443a4/nxp/__init__.py new file mode 100644 index 0000000..ce960da --- /dev/null +++ b/pm3py/transponders/hf/iso14443a4/nxp/__init__.py @@ -0,0 +1 @@ +"""NXP ISO 14443-A Layer 4 transponders.""" diff --git a/pm3py/transponders/hf/iso15693/__init__.py b/pm3py/transponders/hf/iso15693/__init__.py new file mode 100644 index 0000000..084b839 --- /dev/null +++ b/pm3py/transponders/hf/iso15693/__init__.py @@ -0,0 +1 @@ +"""ISO 15693 transponder models and NFC Forum Type 5 NDEF.""" diff --git a/pm3py/transponders/hf/iso15693/nxp/__init__.py b/pm3py/transponders/hf/iso15693/nxp/__init__.py new file mode 100644 index 0000000..fd37fbc --- /dev/null +++ b/pm3py/transponders/hf/iso15693/nxp/__init__.py @@ -0,0 +1 @@ +"""NXP ICODE / NTAG 5 ISO 15693 transponders.""" diff --git a/pm3py/transponders/hf/iso15693/st/__init__.py b/pm3py/transponders/hf/iso15693/st/__init__.py new file mode 100644 index 0000000..d02b2b0 --- /dev/null +++ b/pm3py/transponders/hf/iso15693/st/__init__.py @@ -0,0 +1 @@ +"""ST Microelectronics ISO 15693 transponders.""" diff --git a/pm3py/transponders/lf/__init__.py b/pm3py/transponders/lf/__init__.py new file mode 100644 index 0000000..02b215a --- /dev/null +++ b/pm3py/transponders/lf/__init__.py @@ -0,0 +1 @@ +"""LF transponder models organized by manufacturer.""" diff --git a/pm3py/transponders/lf/atmel/__init__.py b/pm3py/transponders/lf/atmel/__init__.py new file mode 100644 index 0000000..3ab188b --- /dev/null +++ b/pm3py/transponders/lf/atmel/__init__.py @@ -0,0 +1 @@ +"""Atmel/Microchip LF transponders (T55xx).""" diff --git a/pm3py/transponders/lf/em/__init__.py b/pm3py/transponders/lf/em/__init__.py new file mode 100644 index 0000000..befc7c2 --- /dev/null +++ b/pm3py/transponders/lf/em/__init__.py @@ -0,0 +1 @@ +"""EM Microelectronic LF transponders (EM4100, EM4x05)."""