Mac设备访问在C中有效,但Java / JNA中的等效代码无效

问题描述 投票:0回答:1

[我们使用连接到USB上Mac上的串行设备,需要配置DTR / RTS线路设置。从技术上讲,这涉及到open(3)ioctl(3)的使用。

我们用C语言实现了这一点,并且有效。下面是显示核心部分的非常简化代码段。

然后,我们将代码迁移到Java / JNA并遇到了移植的代码确实起作用的问题,尽管它基本上是C代码的逐行转换。问题是我们在哪里出错?

Java失败的症状是从errno=25 'Inappropriate ioctl for device'的调用返回了ioctl()。由于它在C语言中有效,因此似乎在JNA中确实出错了。

我们做了什么:

    检查了标头常量的值。请注意,C代码会生成在Java代码中使用的与Java兼容的常量定义。
  • 检查ioctl()的签名。根据手册页似乎正确,并包含文件。
  • 猜测问题是TIOCMSET的ioctl代码未正确传递,因为它为负数。
  • 我们使用JNA 5.5.0。

这里是C代码。该代码段只是读取行的设置,并将它们未经修改地写回以进行演示。这是代码(请注意硬编码的设备名称)。

int main(int argc, char **argv) { // Print constant values. printf( "long TIOCMGET = 0x%x;\n", TIOCMGET ); printf( "long TIOCMSET = 0x%x;\n", TIOCMSET ); printf( "int O_RDWR = 0x%x;\n", O_RDWR ); printf( "int O_NDELAY = 0x%x;\n", O_NDELAY ); printf( "int O_NOCTTY = 0x%x;\n", O_NOCTTY ); int value = O_RDWR|O_NDELAY|O_NOCTTY; printf( "value=%x\n", value ); int portfd = open("/dev/tty.usbmodem735ae091", value); printf( "portfd=%d\n", portfd ); int lineStatus; printf( "TIOCMGET %x\n", TIOCMGET ); int rc = ioctl( portfd, TIOCMGET, &lineStatus ); printf( "rc=%d, linestatus=%x\n", rc, lineStatus ); rc = ioctl( portfd, TIOCMSET, &lineStatus ); printf( "rc=%d, linestatus=%x\n", rc, lineStatus ); if ( rc == -1 ) printf( "Failure\n" ); else printf( "Success\n" ); if ( portfd != -1 ) close( portfd ); return 0; }

上面的输出是:

long TIOCMGET = 0x4004746a; long TIOCMSET = 0x8004746d; int O_RDWR = 0x2; int O_NDELAY = 0x4; int O_NOCTTY = 0x20000; value=20006 portfd=3 TIOCMGET 4004746a rc=0, linestatus=6 rc=0, linestatus=6 Success

这是Java实现:

public class Cli { /** * Java mapping for lib c */ public interface MacCl extends Library { String NAME = "c"; MacCl INSTANCE = Native.load(NAME, MacCl.class); int open(String pathname, int flags); int close(int fd); int ioctl(int fd, long param, LongByReference request); String strerror( int errno ); } private static final MacCl C = MacCl.INSTANCE; private static PrintStream out = System.err; public static void main( String[] argv ) { long TIOCMGET = 0x4004746a; long TIOCMSET = 0x8004746d; int O_RDWR = 0x2; int O_NDELAY = 0x4; int O_NOCTTY = 0x20000; int value = O_RDWR|O_NDELAY|O_NOCTTY; out.printf( "value=%x\n", value ); int portfd = C.open( "/dev/tty.usbmodem735ae091", value ); out.printf( "portfd=%d\n", portfd ); LongByReference lineStatus = new LongByReference(); int rc = C.ioctl( portfd, TIOCMGET, lineStatus ); out.printf( "rc=%d, linestatus=%d\n", rc, lineStatus.getValue() ); rc = C.ioctl( portfd, TIOCMSET, lineStatus ); out.printf( "rc=%d errno='%s'\n", rc, C.strerror( Native.getLastError() ) ); if ( rc == -1 ) out.print( "Failure." ); else out.print( "Success." ); if ( portfd != -1 ) C.close( portfd ); } }

Java输出是:

value=20006 portfd=23 rc=0, linestatus=6 rc=-1 errno='Inappropriate ioctl for device' Failure.

[我们使用连接到USB上Mac上的串行设备,需要配置DTR / RTS线路设置。从技术上讲,这涉及open(3),ioctl(3)的使用。我们在C语言中实现了这一点...
java macos jna
1个回答
0
投票
查看您正在使用的命令的ioctl.h头文件,发现它期望将int作为第三个参数:
© www.soinside.com 2019 - 2024. All rights reserved.