Complete overhaul of JNI boundary - store FD and details in C
This commit is contained in:
parent
6ab8a2380a
commit
bc39570ff1
|
@ -2,7 +2,7 @@
|
|||
* PosixHelperFunctions.c
|
||||
*
|
||||
* Created on: Mar 10, 2015
|
||||
* Last Updated on: Oct 29, 2021
|
||||
* Last Updated on: Nov 14, 2021
|
||||
* Author: Will Hedgecock
|
||||
*
|
||||
* Copyright (C) 2012-2021 Fazecast, Inc.
|
||||
|
@ -34,41 +34,78 @@
|
|||
#include <unistd.h>
|
||||
#include "PosixHelperFunctions.h"
|
||||
|
||||
// Common functionality
|
||||
void push_back(struct charTupleVector* vector, const char* firstString, const char* secondString, const char* thirdString)
|
||||
// Common storage functionality
|
||||
serialPort* pushBack(serialPortVector* vector, const char* key, const char* friendlyName, const char* description)
|
||||
{
|
||||
// Allocate memory for new string storage
|
||||
vector->length++;
|
||||
char** newMemory = (char**)realloc(vector->first, vector->length*sizeof(char*));
|
||||
if (newMemory)
|
||||
vector->first = newMemory;
|
||||
newMemory = (char**)realloc(vector->second, vector->length*sizeof(char*));
|
||||
if (newMemory)
|
||||
vector->second = newMemory;
|
||||
newMemory = (char**)realloc(vector->third, vector->length*sizeof(char*));
|
||||
if (newMemory)
|
||||
vector->third = newMemory;
|
||||
// Allocate memory for the new SerialPort storage structure
|
||||
if (vector->capacity == vector->length)
|
||||
{
|
||||
serialPort** newArray = (serialPort**)realloc(vector->ports, ++vector->capacity * sizeof(serialPort*));
|
||||
if (newArray)
|
||||
vector->ports = newArray;
|
||||
else
|
||||
{
|
||||
vector->capacity--;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
serialPort* port = (serialPort*)malloc(sizeof(serialPort));
|
||||
if (port)
|
||||
vector->ports[vector->length++] = port;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
// Store new strings
|
||||
vector->first[vector->length-1] = (char*)malloc(strlen(firstString)+1);
|
||||
vector->second[vector->length-1] = (char*)malloc(strlen(secondString)+1);
|
||||
vector->third[vector->length-1] = (char*)malloc(strlen(thirdString)+1);
|
||||
strcpy(vector->first[vector->length-1], firstString);
|
||||
strcpy(vector->second[vector->length-1], secondString);
|
||||
strcpy(vector->third[vector->length-1], thirdString);
|
||||
// Initialize the storage structure
|
||||
memset(port, 0, sizeof(serialPort));
|
||||
port->handle = -1;
|
||||
port->enumerated = 1;
|
||||
port->portPath = (char*)malloc(strlen(key) + 1);
|
||||
port->friendlyName = (char*)malloc(strlen(friendlyName) + 1);
|
||||
port->portDescription = (char*)malloc(strlen(description) + 1);
|
||||
|
||||
// Store port strings
|
||||
strcpy(port->portPath, key);
|
||||
strcpy(port->friendlyName, friendlyName);
|
||||
strcpy(port->portDescription, description);
|
||||
|
||||
// Return the newly created serial port structure
|
||||
return port;
|
||||
}
|
||||
|
||||
char keyExists(struct charTupleVector* vector, const char* key)
|
||||
serialPort* fetchPort(serialPortVector* vector, const char* key)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < vector->length; ++i)
|
||||
if (strcmp(key, vector->first[i]) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
for (int i = 0; i < vector->length; ++i)
|
||||
if (strcmp(key, vector->ports[i]->portPath) == 0)
|
||||
return vector->ports[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void removePort(serialPortVector* vector, serialPort* port)
|
||||
{
|
||||
// Clean up memory associated with the port
|
||||
free(port->portPath);
|
||||
free(port->friendlyName);
|
||||
free(port->portDescription);
|
||||
if (port->readBuffer)
|
||||
free(port->readBuffer);
|
||||
|
||||
// Move up all remaining ports in the serial port listing
|
||||
for (int i = 0; i < vector->length; ++i)
|
||||
if (vector->ports[i] == port)
|
||||
{
|
||||
for (int j = i; j < (vector->length - 1); ++j)
|
||||
vector->ports[j] = vector->ports[j+1];
|
||||
vector->length--;
|
||||
break;
|
||||
}
|
||||
|
||||
// Free the serial port structure memory
|
||||
free(port);
|
||||
}
|
||||
|
||||
// Linux-specific functionality
|
||||
#if defined(__linux__)
|
||||
|
||||
#include <linux/serial.h>
|
||||
#include <asm/termios.h>
|
||||
#include <asm/ioctls.h>
|
||||
|
@ -144,7 +181,7 @@ void getInterfaceDescription(const char* interfaceFile, char* interfaceDescripti
|
|||
}
|
||||
}
|
||||
|
||||
void recursiveSearchForComPorts(charTupleVector* comPorts, const char* fullPathToSearch)
|
||||
void recursiveSearchForComPorts(serialPortVector* comPorts, const char* fullPathToSearch)
|
||||
{
|
||||
// Open the directory
|
||||
DIR *directoryIterator = opendir(fullPathToSearch);
|
||||
|
@ -171,6 +208,12 @@ void recursiveSearchForComPorts(charTupleVector* comPorts, const char* fullPathT
|
|||
strcpy(systemName, "/dev/");
|
||||
strcat(systemName, directoryEntry->d_name);
|
||||
|
||||
// Check if port is already enumerated
|
||||
serialPort *port = fetchPort(comPorts, systemName);
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
{
|
||||
// See if device has a registered friendly name
|
||||
char* friendlyName = (char*)malloc(256);
|
||||
char* productFile = (char*)malloc(strlen(fullPathToSearch) + strlen(directoryEntry->d_name) + 30);
|
||||
|
@ -197,14 +240,14 @@ void recursiveSearchForComPorts(charTupleVector* comPorts, const char* fullPathT
|
|||
{
|
||||
strcpy(friendlyName, "Bluetooth Port ");
|
||||
strcat(friendlyName, directoryEntry->d_name);
|
||||
push_back(comPorts, systemName, friendlyName, friendlyName);
|
||||
pushBack(comPorts, systemName, friendlyName, friendlyName);
|
||||
}
|
||||
else if (((strlen(directoryEntry->d_name) >= 6) && (directoryEntry->d_name[3] == 'A') && (directoryEntry->d_name[4] == 'M') && (directoryEntry->d_name[5] == 'A')) ||
|
||||
((ioctl(fd, TIOCGSERIAL, &serialInfo) == 0) && (serialInfo.type != PORT_UNKNOWN)))
|
||||
{
|
||||
strcpy(friendlyName, "Physical Port ");
|
||||
strcat(friendlyName, directoryEntry->d_name+3);
|
||||
push_back(comPorts, systemName, friendlyName, friendlyName);
|
||||
pushBack(comPorts, systemName, friendlyName, friendlyName);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
@ -227,7 +270,7 @@ void recursiveSearchForComPorts(charTupleVector* comPorts, const char* fullPathT
|
|||
}
|
||||
if (interfaceDescription[0] == '\0')
|
||||
strcpy(interfaceDescription, friendlyName);
|
||||
push_back(comPorts, systemName, friendlyName, interfaceDescription);
|
||||
pushBack(comPorts, systemName, friendlyName, interfaceDescription);
|
||||
|
||||
// Clean up memory
|
||||
free(interfaceFile);
|
||||
|
@ -252,7 +295,7 @@ void recursiveSearchForComPorts(charTupleVector* comPorts, const char* fullPathT
|
|||
}
|
||||
if (interfaceDescription[0] == '\0')
|
||||
strcpy(interfaceDescription, friendlyName);
|
||||
push_back(comPorts, systemName, friendlyName, interfaceDescription);
|
||||
pushBack(comPorts, systemName, friendlyName, interfaceDescription);
|
||||
|
||||
// Clean up memory
|
||||
free(interfaceFile);
|
||||
|
@ -261,30 +304,21 @@ void recursiveSearchForComPorts(charTupleVector* comPorts, const char* fullPathT
|
|||
|
||||
// Clean up memory
|
||||
free(productFile);
|
||||
free(systemName);
|
||||
free(friendlyName);
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
free(systemName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search for more serial ports within the directory
|
||||
charTupleVector newComPorts = { (char**)malloc(1), (char**)malloc(1), (char**)malloc(1), 0 };
|
||||
char* nextDirectory = (char*)malloc(strlen(fullPathToSearch) + strlen(directoryEntry->d_name) + 5);
|
||||
strcpy(nextDirectory, fullPathToSearch);
|
||||
strcat(nextDirectory, directoryEntry->d_name);
|
||||
strcat(nextDirectory, "/");
|
||||
recursiveSearchForComPorts(&newComPorts, nextDirectory);
|
||||
recursiveSearchForComPorts(comPorts, nextDirectory);
|
||||
free(nextDirectory);
|
||||
int i;
|
||||
for (i = 0; i < newComPorts.length; ++i)
|
||||
{
|
||||
push_back(comPorts, newComPorts.first[i], newComPorts.second[i], newComPorts.third[i]);
|
||||
free(newComPorts.first[i]);
|
||||
free(newComPorts.second[i]);
|
||||
free(newComPorts.third[i]);
|
||||
}
|
||||
free(newComPorts.first);
|
||||
free(newComPorts.second);
|
||||
free(newComPorts.third);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +329,54 @@ void recursiveSearchForComPorts(charTupleVector* comPorts, const char* fullPathT
|
|||
closedir(directoryIterator);
|
||||
}
|
||||
|
||||
void lastDitchSearchForComPorts(charTupleVector* comPorts)
|
||||
void driverBasedSearchForComPorts(serialPortVector* comPorts, const char* fullPathToDriver, const char* fullBasePathToPort)
|
||||
{
|
||||
// Search for unidentified physical serial ports
|
||||
FILE *serialDriverFile = fopen(fullPathToDriver, "rb");
|
||||
if (serialDriverFile)
|
||||
{
|
||||
char* serialLine = (char*)malloc(128);
|
||||
while (fgets(serialLine, 128, serialDriverFile))
|
||||
if (strstr(serialLine, "uart:") && (strstr(serialLine, "uart:unknown") == NULL))
|
||||
{
|
||||
// Determine system name of port
|
||||
*strchr(serialLine, ':') = '\0';
|
||||
char* systemName = (char*)malloc(256);
|
||||
strcpy(systemName, fullBasePathToPort);
|
||||
strcat(systemName, serialLine);
|
||||
|
||||
// Check if port is already enumerated
|
||||
serialPort *port = fetchPort(comPorts, systemName);
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
{
|
||||
// Ensure that the port is valid and not a symlink
|
||||
struct stat fileStats;
|
||||
if ((access(systemName, F_OK) == 0) && (lstat(systemName, &fileStats) == 0) && !S_ISLNK(fileStats.st_mode))
|
||||
{
|
||||
// Set static friendly name
|
||||
char* friendlyName = (char*)malloc(256);
|
||||
strcpy(friendlyName, "Physical Port ");
|
||||
strcat(friendlyName, serialLine);
|
||||
|
||||
// Add the port to the list
|
||||
pushBack(comPorts, systemName, friendlyName, friendlyName);
|
||||
|
||||
// Clean up memory
|
||||
free(friendlyName);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
free(systemName);
|
||||
}
|
||||
free(serialLine);
|
||||
fclose(serialDriverFile);
|
||||
}
|
||||
}
|
||||
|
||||
void lastDitchSearchForComPorts(serialPortVector* comPorts)
|
||||
{
|
||||
// Open the linux dev directory
|
||||
DIR *directoryIterator = opendir("/dev/");
|
||||
|
@ -317,17 +398,25 @@ void lastDitchSearchForComPorts(charTupleVector* comPorts)
|
|||
strcpy(systemName, "/dev/");
|
||||
strcat(systemName, directoryEntry->d_name);
|
||||
|
||||
// Check if port is already enumerated
|
||||
serialPort *port = fetchPort(comPorts, systemName);
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
{
|
||||
// Set static friendly name
|
||||
char* friendlyName = (char*)malloc(256);
|
||||
strcpy(friendlyName, "USB-Based Serial Port");
|
||||
|
||||
// Determine if port is already in the list, and add it if not
|
||||
if (!keyExists(comPorts, systemName))
|
||||
push_back(comPorts, systemName, friendlyName, friendlyName);
|
||||
// Add the port to the list
|
||||
pushBack(comPorts, systemName, friendlyName, friendlyName);
|
||||
|
||||
// Clean up memory
|
||||
free(friendlyName);
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
free(systemName);
|
||||
free(friendlyName);
|
||||
}
|
||||
else if ((strlen(directoryEntry->d_name) >= 6) && (directoryEntry->d_name[0] == 't') && (directoryEntry->d_name[1] == 't') && (directoryEntry->d_name[2] == 'y') &&
|
||||
(directoryEntry->d_name[3] == 'A') && (directoryEntry->d_name[4] == 'P'))
|
||||
|
@ -337,17 +426,25 @@ void lastDitchSearchForComPorts(charTupleVector* comPorts)
|
|||
strcpy(systemName, "/dev/");
|
||||
strcat(systemName, directoryEntry->d_name);
|
||||
|
||||
// Check if port is already enumerated
|
||||
serialPort *port = fetchPort(comPorts, systemName);
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
{
|
||||
// Set static friendly name
|
||||
char* friendlyName = (char*)malloc(256);
|
||||
strcpy(friendlyName, "Advantech Extended Serial Port");
|
||||
|
||||
// Determine if port is already in the list, and add it if not
|
||||
if (!keyExists(comPorts, systemName))
|
||||
push_back(comPorts, systemName, friendlyName, friendlyName);
|
||||
// Add the port to the list
|
||||
pushBack(comPorts, systemName, friendlyName, friendlyName);
|
||||
|
||||
// Clean up memory
|
||||
free(friendlyName);
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
free(systemName);
|
||||
free(friendlyName);
|
||||
}
|
||||
else if ((strlen(directoryEntry->d_name) >= 6) && (directoryEntry->d_name[0] == 'r') && (directoryEntry->d_name[1] == 'f') && (directoryEntry->d_name[2] == 'c') &&
|
||||
(directoryEntry->d_name[3] == 'o') && (directoryEntry->d_name[4] == 'm') && (directoryEntry->d_name[5] == 'm'))
|
||||
|
@ -357,17 +454,25 @@ void lastDitchSearchForComPorts(charTupleVector* comPorts)
|
|||
strcpy(systemName, "/dev/");
|
||||
strcat(systemName, directoryEntry->d_name);
|
||||
|
||||
// Check if port is already enumerated
|
||||
serialPort *port = fetchPort(comPorts, systemName);
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
{
|
||||
// Set static friendly name
|
||||
char* friendlyName = (char*)malloc(256);
|
||||
strcpy(friendlyName, "Bluetooth-Based Serial Port");
|
||||
|
||||
// Determine if port is already in the list, and add it if not
|
||||
if (!keyExists(comPorts, systemName))
|
||||
push_back(comPorts, systemName, friendlyName, friendlyName);
|
||||
// Add the port to the list
|
||||
pushBack(comPorts, systemName, friendlyName, friendlyName);
|
||||
|
||||
// Clean up memory
|
||||
free(friendlyName);
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
free(systemName);
|
||||
free(friendlyName);
|
||||
}
|
||||
directoryEntry = readdir(directoryIterator);
|
||||
}
|
||||
|
@ -376,45 +481,6 @@ void lastDitchSearchForComPorts(charTupleVector* comPorts)
|
|||
closedir(directoryIterator);
|
||||
}
|
||||
|
||||
void driverBasedSearchForComPorts(charTupleVector* comPorts)
|
||||
{
|
||||
// Search for unidentified physical serial ports
|
||||
FILE *serialDriverFile = fopen("/proc/tty/driver/serial", "rb");
|
||||
if (serialDriverFile)
|
||||
{
|
||||
char* serialLine = (char*)malloc(128);
|
||||
while (fgets(serialLine, 128, serialDriverFile))
|
||||
if (strstr(serialLine, "uart:") && (strstr(serialLine, "uart:unknown") == NULL))
|
||||
{
|
||||
// Determine system name of port
|
||||
*strchr(serialLine, ':') = '\0';
|
||||
char* systemName = (char*)malloc(256);
|
||||
char* friendlyName = (char*)malloc(256);
|
||||
strcpy(systemName, "/dev/ttyS");
|
||||
strcat(systemName, serialLine);
|
||||
|
||||
// Ensure that the port is valid and not a symlink
|
||||
struct stat fileStats;
|
||||
if ((access(systemName, F_OK) == 0) && (lstat(systemName, &fileStats) == 0) && !S_ISLNK(fileStats.st_mode))
|
||||
{
|
||||
// Set static friendly name
|
||||
strcpy(friendlyName, "Physical Port ");
|
||||
strcat(friendlyName, serialLine);
|
||||
|
||||
// Determine if port is already in the list, and add it if not
|
||||
if (!keyExists(comPorts, systemName))
|
||||
push_back(comPorts, systemName, friendlyName, friendlyName);
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
free(systemName);
|
||||
free(friendlyName);
|
||||
}
|
||||
free(serialLine);
|
||||
fclose(serialDriverFile);
|
||||
}
|
||||
}
|
||||
|
||||
baud_rate getBaudRateCode(baud_rate baudRate)
|
||||
{
|
||||
// Translate a raw baud rate into a system-specified one
|
||||
|
@ -455,18 +521,36 @@ baud_rate getBaudRateCode(baud_rate baudRate)
|
|||
return B57600;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case 76800:
|
||||
#ifdef B76800
|
||||
return B76800;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case 115200:
|
||||
#ifdef B115200
|
||||
return B115200;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case 153600:
|
||||
#ifdef B153600
|
||||
return B153600;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case 230400:
|
||||
#ifdef B230400
|
||||
return B230400;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case 307200:
|
||||
#ifdef B307200
|
||||
return B307200;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case 460800:
|
||||
#ifdef B460800
|
||||
|
@ -485,6 +569,12 @@ baud_rate getBaudRateCode(baud_rate baudRate)
|
|||
return B576000;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case 614400:
|
||||
#ifdef B614400
|
||||
return B614400;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
case 921600:
|
||||
#ifdef B921600
|
||||
|
@ -570,14 +660,15 @@ int setBaudRateCustom(int portFD, baud_rate baudRate)
|
|||
retVal = ioctl(portFD, TIOCSSERIAL, &serInfo);
|
||||
}
|
||||
#endif
|
||||
return (retVal == 0);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Solaris-specific functionality
|
||||
#elif defined(__sun__)
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
void searchForComPorts(charTupleVector* comPorts)
|
||||
void searchForComPorts(serialPortVector* comPorts)
|
||||
{
|
||||
// Open the Solaris callout dev directory
|
||||
DIR *directoryIterator = opendir("/dev/cua/");
|
||||
|
@ -595,23 +686,28 @@ void searchForComPorts(charTupleVector* comPorts)
|
|||
strcpy(systemName, "/dev/cua/");
|
||||
strcat(systemName, directoryEntry->d_name);
|
||||
|
||||
// Check if port is already enumerated
|
||||
serialPort *port = fetchPort(comPorts, systemName);
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
{
|
||||
// Set static friendly name
|
||||
char* friendlyName = (char*)malloc(256);
|
||||
strcpy(friendlyName, "Serial Port");
|
||||
|
||||
// Ensure that the file is not a directory
|
||||
// Add the port to the list if it is not a directory
|
||||
struct stat fileStats;
|
||||
stat(systemName, &fileStats);
|
||||
if (!S_ISDIR(fileStats.st_mode))
|
||||
{
|
||||
// Determine if port is already in the list, and add it if not
|
||||
if (!keyExists(comPorts, systemName))
|
||||
push_back(comPorts, systemName, friendlyName, friendlyName);
|
||||
pushBack(comPorts, systemName, friendlyName, friendlyName);
|
||||
|
||||
// Clean up memory
|
||||
free(friendlyName);
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
free(systemName);
|
||||
free(friendlyName);
|
||||
}
|
||||
directoryEntry = readdir(directoryIterator);
|
||||
}
|
||||
|
@ -636,23 +732,28 @@ void searchForComPorts(charTupleVector* comPorts)
|
|||
strcpy(systemName, "/dev/term/");
|
||||
strcat(systemName, directoryEntry->d_name);
|
||||
|
||||
// Check if port is already enumerated
|
||||
serialPort *port = fetchPort(comPorts, systemName);
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
{
|
||||
// Set static friendly name
|
||||
char* friendlyName = (char*)malloc(256);
|
||||
strcpy(friendlyName, "Serial Port (Dial-In)");
|
||||
|
||||
// Ensure that the file is not a directory
|
||||
// Add the port to the list if the file is not a directory
|
||||
struct stat fileStats;
|
||||
stat(systemName, &fileStats);
|
||||
if (!S_ISDIR(fileStats.st_mode))
|
||||
{
|
||||
// Determine if port is already in the list, and add it if not
|
||||
if (!keyExists(comPorts, systemName))
|
||||
push_back(comPorts, systemName, friendlyName, friendlyName);
|
||||
pushBack(comPorts, systemName, friendlyName, friendlyName);
|
||||
|
||||
// Clean up memory
|
||||
free(friendlyName);
|
||||
}
|
||||
|
||||
// Clean up memory
|
||||
free(systemName);
|
||||
free(friendlyName);
|
||||
}
|
||||
directoryEntry = readdir(directoryIterator);
|
||||
}
|
||||
|
@ -667,8 +768,8 @@ int flock(int fd, int op)
|
|||
int rc = 0;
|
||||
|
||||
#if defined(F_SETLK) && defined(F_SETLKW)
|
||||
struct flock fl = {0};
|
||||
switch (op & (LOCK_EX|LOCK_SH|LOCK_UN))
|
||||
struct flock fl = { 0 };
|
||||
switch (op & (LOCK_EX | LOCK_SH | LOCK_UN))
|
||||
{
|
||||
case LOCK_EX:
|
||||
fl.l_type = F_WRLCK;
|
||||
|
@ -751,13 +852,90 @@ baud_rate getBaudRateCode(baud_rate baudRate)
|
|||
int setBaudRateCustom(int portFD, baud_rate baudRate)
|
||||
{
|
||||
// No way to set custom baud rates on this OS
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Apple-specific functionality
|
||||
#elif defined(__APPLE__)
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/serial/IOSerialKeys.h>
|
||||
#include <IOKit/serial/ioss.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
void searchForComPorts(serialPortVector* comPorts)
|
||||
{
|
||||
serialPort *port;
|
||||
int numValues = 0;
|
||||
io_object_t serialPort;
|
||||
io_iterator_t serialPortIterator;
|
||||
char friendlyName[1024], comPortCu[1024], comPortTty[1024], portDescription[1024];
|
||||
|
||||
// Enumerate serial ports on machine
|
||||
IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(kIOSerialBSDServiceValue), &serialPortIterator);
|
||||
while ((serialPort = IOIteratorNext(serialPortIterator)))
|
||||
{
|
||||
++numValues;
|
||||
IOObjectRelease(serialPort);
|
||||
}
|
||||
IOIteratorReset(serialPortIterator);
|
||||
for (int i = 0; i < numValues; ++i)
|
||||
{
|
||||
// Get serial port information
|
||||
friendlyName[0] = '\0';
|
||||
serialPort = IOIteratorNext(serialPortIterator);
|
||||
io_registry_entry_t parent = 0;
|
||||
io_registry_entry_t service = serialPort;
|
||||
while (service)
|
||||
{
|
||||
if (IOObjectConformsTo(service, "IOUSBDevice"))
|
||||
{
|
||||
IORegistryEntryGetName(service, friendlyName);
|
||||
break;
|
||||
}
|
||||
if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent) != KERN_SUCCESS)
|
||||
break;
|
||||
if (service != serialPort)
|
||||
IOObjectRelease(service);
|
||||
service = parent;
|
||||
}
|
||||
if (service != serialPort)
|
||||
IOObjectRelease(service);
|
||||
|
||||
// Get serial port name and COM value
|
||||
if (friendlyName[0] == '\0')
|
||||
{
|
||||
CFStringRef friendlyNameRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0);
|
||||
CFStringGetCString(friendlyNameRef, friendlyName, sizeof(friendlyName), kCFStringEncodingUTF8);
|
||||
CFRelease(friendlyNameRef);
|
||||
}
|
||||
CFStringRef comPortRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
|
||||
CFStringGetCString(comPortRef, comPortCu, sizeof(comPortCu), kCFStringEncodingUTF8);
|
||||
CFRelease(comPortRef);
|
||||
comPortRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIODialinDeviceKey), kCFAllocatorDefault, 0);
|
||||
CFStringGetCString(comPortRef, comPortTty, sizeof(comPortTty), kCFStringEncodingUTF8);
|
||||
CFRelease(comPortRef);
|
||||
|
||||
// Check if callout port is already enumerated
|
||||
port = fetchPort(comPorts, comPortCu);
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
pushBack(comPorts, comPortCu, friendlyName, friendlyName);
|
||||
|
||||
// Check if dialin port is already enumerated
|
||||
port = fetchPort(comPorts, comPortTty);
|
||||
strcat(friendlyName, " (Dial-In)");
|
||||
if (port)
|
||||
port->enumerated = 1;
|
||||
else
|
||||
pushBack(comPorts, comPortTty, friendlyName, friendlyName);
|
||||
IOObjectRelease(serialPort);
|
||||
}
|
||||
IOObjectRelease(serialPortIterator);
|
||||
}
|
||||
|
||||
baud_rate getBaudRateCode(baud_rate baudRate)
|
||||
{
|
||||
|
@ -848,8 +1026,9 @@ int setBaudRateCustom(int portFD, baud_rate baudRate)
|
|||
// Use OSX-specific ioctls to set a custom baud rate
|
||||
unsigned long microseconds = 1000;
|
||||
int retVal = ioctl(portFD, IOSSIOSPEED, &baudRate);
|
||||
ioctl(portFD, IOSSDATALAT, µseconds);
|
||||
return (retVal == 0);
|
||||
if (retVal == 0)
|
||||
retVal = ioctl(portFD, IOSSDATALAT, µseconds);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* PosixHelperFunctions.h
|
||||
*
|
||||
* Created on: Mar 10, 2015
|
||||
* Last Updated on: Apr 01, 2020
|
||||
* Last Updated on: Nov 14, 2021
|
||||
* Author: Will Hedgecock
|
||||
*
|
||||
* Copyright (C) 2012-2020 Fazecast, Inc.
|
||||
* Copyright (C) 2012-2021 Fazecast, Inc.
|
||||
*
|
||||
* This file is part of jSerialComm.
|
||||
*
|
||||
|
@ -26,22 +26,38 @@
|
|||
#ifndef __POSIX_HELPER_FUNCTIONS_HEADER_H__
|
||||
#define __POSIX_HELPER_FUNCTIONS_HEADER_H__
|
||||
|
||||
// Common functionality
|
||||
typedef struct charTupleVector
|
||||
// Serial port JNI header file
|
||||
#include "../com_fazecast_jSerialComm_SerialPort.h"
|
||||
|
||||
// Serial port data structure
|
||||
typedef struct serialPort
|
||||
{
|
||||
char **first, **second, **third;
|
||||
size_t length;
|
||||
} charTupleVector;
|
||||
void push_back(struct charTupleVector* vector, const char* firstString, const char* secondString, const char* thirdString);
|
||||
char keyExists(struct charTupleVector* vector, const char* key);
|
||||
char *portPath, *friendlyName, *portDescription, *readBuffer;
|
||||
int errorLineNumber, errorNumber, handle, readBufferLength;
|
||||
volatile char enumerated, eventListenerRunning;
|
||||
} serialPort;
|
||||
|
||||
// Common storage functionality
|
||||
typedef struct serialPortVector
|
||||
{
|
||||
serialPort **ports;
|
||||
int length, capacity;
|
||||
} serialPortVector;
|
||||
serialPort* pushBack(serialPortVector* vector, const char* key, const char* friendlyName, const char* description);
|
||||
serialPort* fetchPort(serialPortVector* vector, const char* key);
|
||||
void removePort(serialPortVector* vector, serialPort* port);
|
||||
|
||||
// Forced definitions
|
||||
#ifndef CMSPAR
|
||||
#define CMSPAR 010000000000
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
// Linux-specific functionality
|
||||
#if defined(__linux__)
|
||||
|
||||
typedef int baud_rate;
|
||||
#ifdef __ANDROID__
|
||||
extern int ioctl(int __fd, int __request, ...);
|
||||
|
@ -51,12 +67,13 @@ extern int ioctl(int __fd, unsigned long int __request, ...);
|
|||
void getDriverName(const char* directoryToSearch, char* friendlyName);
|
||||
void getFriendlyName(const char* productFile, char* friendlyName);
|
||||
void getInterfaceDescription(const char* interfaceFile, char* interfaceDescription);
|
||||
void recursiveSearchForComPorts(charTupleVector* comPorts, const char* fullPathToSearch);
|
||||
void lastDitchSearchForComPorts(charTupleVector* comPorts);
|
||||
void driverBasedSearchForComPorts(charTupleVector* comPorts);
|
||||
void recursiveSearchForComPorts(serialPortVector* comPorts, const char* fullPathToSearch);
|
||||
void driverBasedSearchForComPorts(serialPortVector* comPorts, const char* fullPathToDriver, const char* fullBasePathToPort);
|
||||
void lastDitchSearchForComPorts(serialPortVector* comPorts);
|
||||
|
||||
// Solaris-specific functionality
|
||||
#elif defined(__sun__)
|
||||
|
||||
#define LOCK_SH 1
|
||||
#define LOCK_EX 2
|
||||
#define LOCK_NB 4
|
||||
|
@ -64,13 +81,14 @@ void driverBasedSearchForComPorts(charTupleVector* comPorts);
|
|||
typedef int baud_rate;
|
||||
extern int ioctl(int __fd, int __request, ...);
|
||||
int flock(int fd, int op);
|
||||
void searchForComPorts(charTupleVector* comPorts);
|
||||
void searchForComPorts(serialPortVector* comPorts);
|
||||
|
||||
// Apple-specific functionality
|
||||
#elif defined(__APPLE__)
|
||||
#define fdatasync(a) fsync(a)
|
||||
|
||||
#include <termios.h>
|
||||
typedef speed_t baud_rate;
|
||||
void searchForComPorts(serialPortVector* comPorts);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue