Open rusefillc opened 2 years ago
For the most part, I don't know that this is necessary. The openPort()
call will fail in these circumstances (if you are making it to a 'write' call, then your application is not examining the result of the 'open' call), and for the most part, it's really the only reason that the openPort()
call will fail on an enumerated port. If a user really wants to examine the exact error code returned by the OS, they can call getLastErrorCode()
after a failed openPort()
call to see the underlying reason for the failure. (If you are using Linux, then a return code of EACCES (13) signifies a permissions error.)
Additionally, the README, Installation Wiki, and Troubleshooting Wiki all clearly identify permissions as an annoying and common issue for serial ports on Posix-based systems, with suggestions on how to overcome the issue. Finally, in the 2.9.X series of releases, there was a new method added called allowElevatedPermissionsRequest()
which you can call on your serial port object before trying to open it, and it will automatically try to do all the necessary steps to ensure that a user is able to open a serial port, if they can't already. I would recommend adding this method call to your port opening routine, especially if you are guaranteed to be running your application from a command line (since it may prompt for a sudo-password the very first time you open a port if the library is unable to open it).
@hedgecrw you mention a return code of 13 signifies permissions error. Is this part of the contract of the API or this is platform-specific? Any suggestions how to show a meaningful error message to users that is platform-independent when openPort()
fails? if no, at least do you have a table explaining what each code means?
@theHilikus, the 13 return code error is unfortunately platform-specific (Linux-specific actually). It could be something else entirely on Windows, Android, Mac, FreeBSD, etc. That's actually the main reason I added the functionality to return the actual OS-specified error codes in recent releases, so that users could make use of them more intelligently. I can't give you a full listing of codes because they are different (and extensive) for every supported OS (and potentially different distros of Linux). In a future release, I'll try to add some sort of functionality to give a least a rudimentary idea of why openPort()
may have failed, but it will probably not be until the next major release v3.0.0 (which will allow people to use this library on Android without rooting their phones).
excellent. thank you for the info and for the library!
I'll try to add some sort of functionality to give a least a rudimentary idea of why
openPort()
may have failed, but it will probably not be until the next major release v3.0.0 (which will allow people to use this library on Android without rooting their phones).
On my Serial4j API (working currently only with POSIX), i used an ErrnoToException.java
utility to convert native errors to java exceptions, users can handle these exceptions and fire listeners when they are caught, but the downside you will need to build multiple Error codes lists
for different Operating systems.
Here is a snippet of the code:
#include<TerminalDevice.h>
int TerminalDevice::openPort(const char* port, int flag) {
return open(port, flag);
}
int TerminalDevice::fetchSerialPorts(struct DynamicBuffer* serialPorts) {
DIR* dirp = opendir(DEVICES_DIR);
/* sanity check the input */
if (dirp == NULL) {
return ERR_INVALID_DIR;
}
struct dirent* dp = (struct dirent*) calloc(1, sizeof(struct dirent));
/* start at the beginning of the buffer to override last data */
serialPorts->resetDataPointer();
/* start reading available ports */
while ((dp = readdir(dirp)) != NULL) {
char* device = (char*) calloc(1, sizeof(char));
device = SerialUtils::concatIntoDevice(device, dp->d_name, DEVICES_DIR);
/* delete the device buffer if it's not a serial port */
if (!SerialUtils::isSerialPort(device, DEFAULT_FLAGS)) {
BufferUtils::deleteBuffer(device);
continue;
}
/* add the device to the serial ports major buffer and count up */
serialPorts->add(device);
}
/* release resources */
closedir(dirp);
BufferUtils::deleteBuffer(dp);
/* throws error indicating the availability issues */
if (serialPorts->getItem(0) == NULL) {
return ERR_NO_AVAILABLE_TTY_DEVICES;
}
return OPERATION_SUCCEEDED;
}
...
On java:
public final void openPort(final SerialPort serialPort) throws NoSuchDeviceException,
PermissionDeniedException,
BrokenPipeException,
InvalidPortException,
OperationFailedException,
NoAvailableTtyDevicesException {
if (isSerial4jLoggingEnabled()) {
LOGGER.log(Level.INFO, "Opening serial device " + serialPort.getPath());
}
this.nativeTerminalDevice.setSerialPort(serialPort);
final int errno = nativeTerminalDevice.openPort0(serialPort.getPath(), permissions.getValue());
ErrnoToException.throwFromErrno(errno, serialPort.getPath());
/* update port data natively */
/* ... */
}
public void initTermios() throws NoSuchDeviceException,
PermissionDeniedException,
BrokenPipeException,
InvalidPortException,
OperationFailedException,
FileNotFoundException,
NoAvailableTtyDevicesException {
if (isSerial4jLoggingEnabled()) {
LOGGER.log(Level.INFO, "Initializing serial device " + getSerialPort().getPath());
}
final int errno = nativeTerminalDevice.initTermios0();
ErrnoToException.throwFromErrno(errno, getSerialPort().getPath());
/* get the java streams from the port after initializing it with the native terminal */
inputStream = new FileInputStream(getSerialPort().getPath());
outputStream = new FileOutputStream(getSerialPort().getPath());
}
...
A more verbose process specific to the OP request is to initially try to write a tmp file to the /dev
and throws PermissionDeniedException
if the errno is -1 for example....
Hello @hedgecrw,
I got errorCode - 5, errorlocation - 602 in log while opening serial port on Ubuntu 20.04 with jSerialComm v2.9.2 and jdk v11.0.17
Can you please help to know what is the cause of error while opening port?
User privileges are updated as per your documentation.
In putty terminal, the port opens correctly.
is it possible/should it be possible for application to know that it has no permission for serial port in *nix?
under root my stuff works
without root I have access control issue. I still get port in the list of ports available but all I get is a 'write' method failing to write.
Is there an API to detect that specific error? Should there be an API to detect that specific error?