[我们使用连接到USB上Mac上的串行设备,需要配置DTR / RTS线路设置。从技术上讲,这涉及到open(3)
,ioctl(3)
的使用。
我们用C语言实现了这一点,并且有效。下面是显示核心部分的非常简化代码段。
然后,我们将代码迁移到Java / JNA并遇到了移植的代码确实起作用的问题,尽管它基本上是C代码的逐行转换。问题是我们在哪里出错?
Java失败的症状是从errno=25 'Inappropriate ioctl for device'
的调用返回了ioctl()
。由于它在C语言中有效,因此似乎在JNA中确实出错了。
我们做了什么:
ioctl()
的签名。根据手册页似乎正确,并包含文件。TIOCMSET
的ioctl代码未正确传递,因为它为负数。 这里是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语言中实现了这一点...
ioctl.h
头文件,发现它期望将int
作为第三个参数: