nyholku / purejavacomm

Pure Java implementation of JavaComm SerialPort
http://www.sparetimelabs.com/purejavacomm/index.html
BSD 3-Clause "New" or "Revised" License
366 stars 146 forks source link

Can not open Ports with more than one digit in it #53

Closed modmoto closed 9 years ago

modmoto commented 9 years ago

Hi,

I have got a device with 16 serial ports over TCP/IP (Moxa Nport 6530) wich appear as ordinary comports on my Windows PC. I tried the whole day to get to open the ports with two digits but I can not get it to work. On the line 838 is also a FIXIT marker, maybe somebody knows this issue? I tried to figure out if it could be a overflow of a c-string or the regex for getting the comports is wrong, but none of that helped. Anybody has an idea?

This is the log:

Try open: COM10 log: call CreateFileW, class 'jtermios.JTermios$JTermiosLogging', line 389 log: CreateFileW(COM10, 0xC0000000, 0x00000000, null, 0x00000003, 0x40000000,null) => opaque@0xffffffffffffffff log: call GetLastError, class 'jtermios.JTermios$JTermiosLogging', line 389 log: GetLastError() => 2 log: call FormatMessageW, class 'jtermios.JTermios$JTermiosLogging', line 389 log: FormatMessageW(00001200, null, 2, 1024, allocated@0xd4cb500 (2048 bytes), 2048, null ) => 44 log: fail() class 'jtermios.windows.JTermiosImpl', line 388, Windows GetLastError()= 2, The system cannot find the file specified.

Port in use or not available: COM10 log: call QueryDosDeviceW, class 'jtermios.JTermios$JTermiosLogging', line 389 log: QueryDosDeviceW(null,[C@11d7d5ee,8192) => 0 log: call QueryDosDeviceW, class 'jtermios.JTermios$JTermiosLogging', line 389 log: QueryDosDeviceW(null,[C@711e0568,16384) => 11014 log: call GetLastError, class 'jtermios.JTermios$JTermiosLogging', lipurejavacomm.PortInUseException at purejavacomm.PureJavaSerialPort.(PureJavaSerialPort.java:838) at purejavacomm.CommPortIdentifier.open(CommPortIdentifier.java:98) at Communication.TelegramSender.openCommport(TelegramSender.java:91) at Multiplexer.Multiplexer.(Multiplexer.java:35) at Multiplexer.Multiplexer.getInstance(Multiplexer.java:57) at Model.Model.initializeMultiplexer(Model.java:95) at BGTest.Main.main(Main.java:19) ne 389 log: GetLastError() => 0

But so far: extremely nice library, using it a lot :)

nyholku commented 9 years ago

On 16/12/2014 17:39, Lauchi wrote:

Hi,

I have got a device with 16 serial ports over TCP/IP (Moxa Nport 6530) wich appear as ordinary comports on my Windows PC. I tried the whole day to get to open the ports with two digits but I can not get it to work. On the line 838 is also a FIXIT marker, maybe somebody knows this issue? I tried to figure out if it could be a overflow of a c-string or the regex for getting the comports is wrong, but none of that helped. Anybody has an idea?

This is the log:

Try open: COM10 log: call CreateFileW, class 'jtermios.JTermios$JTermiosLogging', line 389 log: CreateFileW(COM10, 0xC0000000, 0x00000000, null, 0x00000003, 0x40000000,null) => opaque@0xffffffffffffffff log: call GetLastError, class 'jtermios.JTermios$JTermiosLogging', line 389 log: GetLastError() => 2 log: call FormatMessageW, class 'jtermios.JTermios$JTermiosLogging', line 389 log: FormatMessageW(00001200, null, 2, 1024, allocated@0xd4cb500 (2048 bytes), 2048, null ) => 44 log: fail() class 'jtermios.windows.JTermiosImpl', line 388, Windows GetLastError()= 2, The system cannot find the file specified.

Port in use or not available: COM10 log: call QueryDosDeviceW, class 'jtermios.JTermios$JTermiosLogging', line 389 log: QueryDosDeviceW(null,[C@11d7d5ee,8192) => 0 log: call QueryDosDeviceW, class 'jtermios.JTermios$JTermiosLogging', line 389 log: QueryDosDeviceW(null,[C@711e0568,16384) => 11014 log: call GetLastError, class 'jtermios.JTermios$JTermiosLogging', lipurejavacomm.PortInUseException at purejavacomm.PureJavaSerialPort.(PureJavaSerialPort.java:838) at purejavacomm.CommPortIdentifier.open(CommPortIdentifier.java:98) at Communication.TelegramSender.openCommport(TelegramSender.java:91) at Multiplexer.Multiplexer.(Multiplexer.java:35) at Multiplexer.Multiplexer.getInstance(Multiplexer.java:57) at Model.Model.initializeMultiplexer(Model.java:95) at BGTest.Main.main(Main.java:19) ne 389 log: GetLastError() => 0

But so far: extremely nice library, using it a lot :)


Reply to this email directly or view it on GitHub: https://github.com/nyholku/purejavacomm/issues/53 hi, doubt the problem is with the two digit COM port number as I seem to recall using at least COM15.

I can try to ponder this over the weekend, now I'm too busy.

br Kusti

modmoto commented 9 years ago

I just tried to rename COM2, wich always opened to COM18 or COM10 and it threw the same exception. When I changed COM10, wich always failed to COM2 the port opened. So it clearly has to do something with the naming, as it always throws the exception when using a 2 digit COM port :/

nyholku commented 9 years ago

Still busy but I checked the regexp with

Pattern p=Pattern.compile("^COM.*");
System.out.println(p.matcher("COM1").matches());
System.out.println(p.matcher("COM10").matches());

and that output 'true' and 'true' so that appears to work.

And it is hard to see where else the one/two digit COM name would make a difference as everywhere it is passed just as a string. If (and when, I believe you) I would think it has to fail inside jtermios.windows.JTermiosImpl.getPortList() so I suggest you set a break point there and trace through it to see that all you ports get inserted to the list and see if the names are correct … hey that rings a bell, let's see:

http://support.microsoft.com/kb/115831

right, so that is your problem I bet.

Try opening "\.\COM10"

If (and when!) that works see if getPortList() in your machine returns COM10 or .\COM10 for your ports and report back here. If it returns the former then I may have to patch the code that opens the port to add the prefix, or something, will have to think about that.

modmoto commented 9 years ago

jeah, that was the solution =) I fiddled around a little bit, but the best solution is to add a "\.\" suffix to the "CreateFile" methods in WinAPI.java, as in the KB is stated, that it works for all ComPorts:

static public HANDLE CreateFileA(String name, int access, int sharing, SECURITY_ATTRIBUTES security, int create, int attribs, Pointer template) {
        log = log & log(5, "call CreateFileA, %s\n", lineno());
        HANDLE h = m_K32lib.CreateFileA("\\\\.\\" + name, access, sharing, security, create, attribs, template);
        log = log & log(4, "CreateFileA(%s, 0x%08X, 0x%08X, %s, 0x%08X, 0x%08X,%s) => %s\n", name, access, sharing, security, create, attribs, template, h);
        return h;
    }

    static public HANDLE CreateFileW(WString name, int access, int sharing, SECURITY_ATTRIBUTES security, int create, int attribs, Pointer template) {
        log = log & log(5, "call CreateFileW, %s\n", lineno());
        HANDLE h = m_K32lib.CreateFileW(new WString("\\\\.\\" + name), access, sharing, security, create, attribs, template);
        log = log & log(4, "CreateFileW(%s, 0x%08X, 0x%08X, %s, 0x%08X, 0x%08X,%s) => %s\n", name, access, sharing, security, create, attribs, template, h);
        return h;
    }

Now also the COM10+ get opened along with the 1-9 ports. Thanks a lot for the help =)

edit: I just closed all the ports again because I thought maybe the function to close the ports is also related to this problem, but everything turned out fine. Closing is still possible =)

nyholku commented 9 years ago

Finally had some minutes to look into this.

Glad that we seemed to have found the problem, however this leaves me confused.

If you look at jtermios.windows.JTermiosImpl.java around line 139 you will see:

    if (!filename.startsWith("\\\\"))
        filename = "\\\\.\\" + filename;

    m_Comm = CreateFileW(new WString(filename), GENERIC_READ | GENERIC_WRITE, 0, null, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, null);

So two digit port numbers should have worked for you !?!? Just like I remembered originally...

I would appreciate if you would dig a bit deeper and see why this did not work for you … have you got the latest version I guess is the obvious question? PureJavaComm. getVersion() should tell you definitely what version you are using.

In any case the right spot to fix this is not in WinAPI class as that class, architecturally speaking, is supposed to just be a Java interface to Windows API and thus should behave as closely as feasible to the C-API.

nyholku commented 9 years ago

Been two weeks now and no response and the original code looks like it should work so I'm closing this, feel free to re-open if you have something to report.