- C 98.2%
- Python 1.8%
| captures | ||
| ghidra | ||
| hp_8753e_doc | ||
| notes | ||
| tools | ||
| .gitignore | ||
| .mcp.json | ||
| enet100_multipad_probe.py | ||
| enet100_port5015_probe.py | ||
| enet100_probe.py | ||
| enet100_smoketest.py | ||
| enet100_srq_probe.py | ||
| GPIB-ENET-100_Protocol.md | ||
| output.txt | ||
| output_multipad.txt | ||
| output_pushprobe.txt | ||
| README.md | ||
NI GPIB-ENET/100 → pyvisa on Linux (driver-free)
Reverse-engineering project to control GPIB lab instruments (first target: HP 8753E vector network analyzer) through an NI GPIB-ENET/100 Ethernet↔GPIB adapter, natively on Linux, without NI's proprietary driver.
1. Goal & constraints
- Keep the existing NI GPIB-ENET/100 (replacement adapters are expensive).
- Linux-native operation (no permanent Windows dependency in the loop).
- Control instruments via a pyvisa-style API.
- First instrument: HP 8753E VNA.
2. Key finding — why there is no off-the-shelf path
pyvisa is only a frontend; it needs a backend that actually speaks the controller's protocol. Neither available backend can drive the ENET/100:
| Backend | ENET/100 support on Linux |
|---|---|
| NI-VISA / NI-488.2 (proprietary) | No. NI dropped the /100; the Linux driver lists only the GPIB-ENET/1000. The /100 was removed around the time NI hardened against fake USB clones. |
pyvisa-py (@py, pure Python) |
No. It speaks VXI-11 / HiSLIP / raw TCP socket over Ethernet, and GPIB via linux-gpib. The ENET/100 speaks none of these — it uses NI's proprietary protocol on TCP port 5000. |
Confirmed symptoms from others: TCPIP::<ip>::INSTR → connection refused;
ASRL<addr>::<ip>::5000::INSTR → fails. NI states plainly that you cannot talk
to the ENET over plain TCP/IP without going through the driver.
→ Conclusion: of {keep the /100, stay on Linux, use pyvisa}, the only DIY way to satisfy all three is to reverse-engineer the port-5000 protocol and wrap it ourselves. That is the path this project takes.
3. The ENET protocol (reference shape)
The closest available reference is libnienet.py (Robert Jördens), which
implements the protocol of the original GPIB-ENET. It is a thin RPC over
TCP:5000 that serializes the classic NI-488 API.
- Transport: TCP, port 5000, big-endian (
!). - Command frame: 1-byte command ID + arguments, padded to 12 bytes.
- Response header:
!HH4xL→status(u16),error(u16), 4 bytes pad,count(u32), followed by payload. - Payload fragments: each prefixed with
!HH→flags(u16),length(u16); read repeats whileflagsis set. - Command IDs (original ENET):
0x07ibdev,0x12ibonl,0x04ibclr,0x1fibtmo,0x20ibtrg,0x19ibrsp,0x23ibwrt,0x16ibrd, … - Write sends the command (with length) then the raw bytes, then reads a response. Read sends the command then consumes the fragmented stream.
⚠️ Critical caveat: this is the original ENET protocol. The /100 is the successor and almost certainly uses a similar but not identical protocol (the Py3 port of libnienet is explicitly "not for /100 or /1000"). Treat the frame layout as a hypothesis to verify, not a finished spec.
4. Reverse-engineering plan
The ENET/100 is a network device, so a VM with bridged networking reaches it directly — no USB passthrough needed.
- Reference rig: Windows VM with bridged networking + NI-488.2 installed; ENET/100 configured and reachable on the same LAN.
- Generate traffic: send
*IDN?to the HP 8753E from the VM (NI MAX /gpibintctrl, or a 3-line pyvisa script on the NI backend). - Capture: Wireshark on the host, filter
tcp.port == 5000. - Decode: compare captured frames against
enet100_probe.py. Adjust command IDs, field widths, and the "magic" address bytes inwrite()/read()until your generated frames byte-for-byte reproduce the NI driver's.
When your frames match the capture, you have a working Linux-native path.
5. Python integration strategy
- Start minimal. Do not build a full pyvisa-py backend first — overkill.
Use the
EnetResourceclass (write/read/query/timeout/close) as a pyvisa-Resource look-alike. Write instrument code against that interface so a real backend can be slotted in later without touching measurement scripts. - Reference repos:
libnienet.py— original protocol implementation (Python 2).vc12345679/NI_GPIB_ENET_Py3— Python 3 port +querywrapper; structure is ~1:1 what we need (targets original ENET, not /100).
6. HP 8753E specifics (the easy part, once transport works)
- GPIB address: set on the front panel (
Localkey → GPIB menu; commonly 16). Must matchpadin the code. - IEEE 488.2: the E generation supports common commands →
*IDN?and*OPC?work (the older 8753C does not).*IDN?is the ideal first test; expectHEWLETT PACKARD,8753E,.... - Command set: HP-8753 mnemonics, not modern SCPI. Examples:
STAR/STOP— start / stop frequencyPOIN— number of pointsFORM4— ASCII data formatOUTPFORM— read the formatted trace
- Sweeps take time: use generous timeouts and synchronize with
*OPC?(trigger sweep → wait for1→ read data) instead of fixed delays.
7. Suggested workspace layout
enet100-pyvisa/
├── README.md # this file
├── enet100_probe.py # transport + EnetResource starter (provided)
├── captures/ # Wireshark .pcapng reference captures
│ └── idn_query.pcapng
├── notes/
│ └── protocol.md # decoded command IDs / frame deltas vs. original
├── instruments/
│ └── hp8753e.py # high-level VNA wrapper (built on EnetResource)
└── tests/
└── test_idn.py
8. Next steps (checklist)
- Stand up the Windows VM reference rig (bridged net + NI-488.2).
- Confirm the ENET/100's IP and the 8753E's GPIB address.
- Capture a clean
*IDN?exchange ontcp.port == 5000. - Diff capture vs.
enet100_probe.py; record deltas innotes/protocol.md. - Get
*IDN?working end-to-end from Linux. - Add
ibtmo/*OPC?handshaking for sweeps. - Build
instruments/hp8753e.py(set freqs, points, read trace). - (Optional) wrap as a proper pyvisa-py backend for drop-in compatibility.
9. Fallback options (if RE stalls)
- Windows/VM bridge: run pyvisa on the NI backend inside the VM (the /100 is supported on Windows) — keeps the hardware, loses Linux-native.
- Replace the controller: a linux-gpib-supported adapter (e.g. Keysight 82357B USB-GPIB, or a genuine NI GPIB-USB-HS) works out-of-the-box with pyvisa-py — loses the /100, gains the least friction.
Status: scaffolding. The protocol frame layout in enet100_probe.py is a
hypothesis derived from the original GPIB-ENET and must be verified against a
real ENET/100 capture.