Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hello! Perhaps a bit offtopic, but could Ioninja perform some configurations similars to what "setserial" does? The reason it that I have working with a Moxa RS232/485/422 device (UPORT 1250), and the mode (232/485/422) is configured using setserial (eg. setserial /dev/ttyUSB0 port 1). It would be useful to me to be able to configure it from inside ioninja (and to be franc, it would solve a problem I currently have, as I am not able to make setserial work well in my ARM device... any idea would be welcome :-)). Regards! Thank you
Hello Jose!
IO Ninja supports Python scripting now, so the easiest road to victory would be to find (or ask GPT/Claude to write) a snippet of Python equivalent of setserial.
setserial
A quick search reveals that setserial calls TIOCSSERIAL with struct serial_struct -- we just need to convert it to Python.
TIOCSSERIAL
struct serial_struct
Claude wrote this:
import fcntl, struct, os DEVICE = "/dev/ttyUSB0" # ioctl request numbers (from <asm-generic/ioctls.h>) TIOCGSERIAL = 0x541E # get struct serial_struct TIOCSSERIAL = 0x541F # set struct serial_struct # struct serial_struct — from <linux/serial.h>. Each format char below maps # 1:1 to a field, in order. Native alignment (default '@', no </>/! prefix) # reproduces the compiler's padding, so this is correct on both 64- and 32-bit. # # idx fmt C type field off64 note # --- --- ---------------- --------------- ----- ------------------------- # 0 i int type 0 # 1 i int line 4 ttyS index # 2 I unsigned int port 8 <-- set by `setserial port N` # 3 i int irq 12 # 4 i int flags 16 # 5 i int xmit_fifo_size 20 # 6 i int custom_divisor 24 # 7 i int baud_base 28 # 8 H unsigned short close_delay 32 # 9 c char io_type 34 # 10 c char reserved_char[1] 35 # (1 byte pad) 36 align int hub6 to 4 # 11 i int hub6 36 # 12 H unsigned short closing_wait 40 # 13 H unsigned short closing_wait2 42 # (4 bytes pad, 64-bit) 44 align pointer to 8 # 14 P void * iomem_base 48 # 15 H unsigned short iomem_reg_shift 56 # 16 I unsigned int port_high 60 # 17 L unsigned long iomap_base 64 # total size: 72 bytes (64-bit); 60 bytes (32-bit) FMT = "iiIiiiiiHcciHHPHIL" PORT = 2 # field index of `port` in the tuple above fd = os.open(DEVICE, os.O_RDWR | os.O_NOCTTY) try: # Read-modify-write: pull the real struct, change only `port`, write it back. # This preserves every other field (and any padding) exactly as the kernel # returned it, so we never depend on constructing the struct from scratch. size = struct.calcsize(FMT) buf = fcntl.ioctl(fd, TIOCGSERIAL, bytes(size)) fields = list(struct.unpack(FMT, buf)) fields[PORT] = 1 # == `setserial /dev/ttyUSB0 port 1` fcntl.ioctl(fd, TIOCSSERIAL, struct.pack(FMT, *fields)) finally: os.close(fd)
Please note -- I didn't actually run it. But the code looks about right. Let me know if it works with your Moxa!
Thank you Vladimir! I think you point me in the right direction. Also, I see that the code runs in the Python script pane (next week I will try to do it with the real device and I let you know)
...anyway, I think you should teach jancy to claude, because I feel that Python is not the best way to deal with structs...
In fact, I tried to do the same using jancy, but I cannot identify an "ioclt" equivalent in the standard library (I used the search option for "ioctl" and also check the serial coms and generic IO classes), is there some way? (easy way... I'm always asking about some thing that could be done in "in-app" scripts)
ops... I just see that problably could be done with the io.DeviceMonitor class...
Hello. I tried the python snippet with the real moxa device, and it works well. Thank you, regards!
Haha, I'm very pleased to hear that you actually prefer Jancy to Python for in-app scripting! Thank you!
Indeed, Jancy maps much nicer to the underlying C APIs, and porting C structs (such as serial_struct) to Jancy is pretty much copy-pasting. BTW, claude/codex already do very well with Jancy -- LLMs don't care much about syntax itself, so given enough samples (such as in ioninja scripts/ folder or the Jancy github repo), they will deduce everything they need to know about a programming language.
serial_struct
scripts/
As for ioctl, Jancy doesn't offer it because it's essentially impossible to come up with a sane cross-platform API for ioctls -- it's highly platform specific. The C++ STL, QT, boost, and other well established libs don't attempt to abstract ioctls either -- instead, their file classes expose the underlying OS-level handle (Jancy does the same via m_osHandle) so that you can call ioctl/DeviceIoControl yourself.
ioctl
m_osHandle
DeviceIoControl
Jancy provides dylib for very natural-looking bindings to any dynamic libraries. You can use it to link against glibc and call any system function, including ioctl:
dylib
enum { // from: bits/fcntl-linux.h O_RDONLY = 00, O_WRONLY = 01, O_RDWR = 02, O_CREAT = 0100, O_NOCTTY = 0400, // from: asm-generic/ioctls.h TIOCGSERIAL = 0x541E, TIOCSSERIAL = 0x541F, } pragma(ThinPointers, true) // all C pointers are `thin` // from: linux/serial.h struct serial_struct { int type; int line; unsigned int port; int irq; int flags; int xmit_fifo_size; int custom_divisor; int baud_base; unsigned short close_delay; char io_type; char reserved_char[1]; int hub6; unsigned short closing_wait; /* time to wait before closing */ unsigned short closing_wait2; /* no longer used... */ unsigned char *iomem_base; unsigned short iomem_reg_shift; unsigned int port_high; unsigned long iomap_base; /* cookie passed into ioremap */ }; // dylib is jancy's FFI gate to anything not covered in stdlib dylib Libc { int cdecl open( char const* name, int flags, ... // int mode (only for O_CREAT) ); int close(int fd); int cdecl ioctl( int fd, long code, ... ); int write( int fd, void const* p, size_t size ); // add as needed } pragma(ThinPointers, default) void main() { Libc libc; libc.open("libc.so.6"); // link to glibc int fd = libc.lib.open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); if (fd == -1) { std.setError("can't open port"); throw; } serial_struct ss; libc.lib.ioctl(fd, TIOCGSERIAL, &ss); // read struct_serial ss.port = ...; // modify port as needed libc.lib.ioctl(fd, TIOCSSERIAL, &ss); // write it back libc.lib.close(fd); }
Hello Vladimir! Thank you. I have tried the code with the Moxa and it works perfectly. And also, it is very interesting to know about the dylib facility, it could be very useful!! Python is a great language, and it is great to be able to use it in ioninja as it is very popular and many people will appreciate it but I think that it is not designed for for working with structs -neither packet headers !!-. Jancy is very nice and very capable -and great for communications stuff!- and being able to use it as "in-app scripts" is great. The only problem is that sometimes it is not easy know how to use it (and know what it can do). But I think this is understandable given the context... and we can always ask you Thank you and regards! Josep