feat(pm3py): auto-detect proxmark3 port when none specified
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
"""Main Proxmark3 client with nested API."""
|
||||
import asyncio
|
||||
import glob
|
||||
import inspect
|
||||
import logging
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from .transport import PM3Transport, PM3Response, PM3Error, ProgressCallback
|
||||
@@ -26,21 +28,42 @@ class FirmwareInfo:
|
||||
warnings: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
def find_proxmark_port() -> str | None:
|
||||
"""Auto-detect the first available Proxmark3 serial port."""
|
||||
if sys.platform == "darwin":
|
||||
patterns = ["/dev/tty.usbmodem*"]
|
||||
elif sys.platform == "win32":
|
||||
# On Windows, we can't glob — caller should specify port
|
||||
return None
|
||||
else:
|
||||
patterns = ["/dev/ttyACM*", "/dev/ttyUSB*"]
|
||||
|
||||
for pattern in patterns:
|
||||
ports = sorted(glob.glob(pattern))
|
||||
if ports:
|
||||
return ports[0]
|
||||
return None
|
||||
|
||||
|
||||
class Proxmark3:
|
||||
"""Proxmark3 device client with structured Python API.
|
||||
|
||||
Usage:
|
||||
async with Proxmark3("/dev/ttyACM0") as pm3:
|
||||
if not pm3.firmware.compatible:
|
||||
print("Warnings:", pm3.firmware.warnings)
|
||||
status = await pm3.hw.version()
|
||||
print(status)
|
||||
async with Proxmark3() as pm3: # auto-detect port
|
||||
print(await pm3.hw.ping())
|
||||
|
||||
# Raw access:
|
||||
async with Proxmark3("/dev/ttyACM0") as pm3: # explicit port
|
||||
resp = await pm3.send_ng(0x0108)
|
||||
|
||||
pm3 = Proxmark3.sync() # sync REPL, auto-detect
|
||||
"""
|
||||
|
||||
def __init__(self, port: str, baudrate: int = 115200):
|
||||
def __init__(self, port: str | None = None, baudrate: int = 115200):
|
||||
if port is None:
|
||||
port = find_proxmark_port()
|
||||
if port is None:
|
||||
raise PM3Error("No Proxmark3 device found")
|
||||
log.info("pm3py: auto-detected %s", port)
|
||||
self._transport = PM3Transport(port, baudrate)
|
||||
self.hw = HWCommands(self._transport)
|
||||
self.lf = LFCommands(self._transport)
|
||||
@@ -106,14 +129,14 @@ class Proxmark3:
|
||||
return await self._transport.send_mix(cmd, arg0, arg1, arg2, payload, timeout)
|
||||
|
||||
@classmethod
|
||||
def sync(cls, port: str, baudrate: int = 115200) -> "Proxmark3":
|
||||
def sync(cls, port: str | None = None, baudrate: int = 115200) -> "Proxmark3":
|
||||
"""Create a synchronous client for REPL / script usage.
|
||||
|
||||
Usage:
|
||||
pm3 = Proxmark3.sync("/dev/ttyACM0")
|
||||
pm3 = Proxmark3.sync() # auto-detect
|
||||
pm3 = Proxmark3.sync("/dev/ttyACM0") # explicit
|
||||
print(pm3.firmware)
|
||||
print(pm3.hw.ping())
|
||||
print(pm3.hf.mf.rdbl(block=0))
|
||||
pm3.close()
|
||||
"""
|
||||
instance = cls(port, baudrate)
|
||||
|
||||
Reference in New Issue
Block a user