Skip to content

Commit 05edb5a

Browse files
committed
Implemented getting driver name for Linux
1 parent 5966a40 commit 05edb5a

4 files changed

Lines changed: 53 additions & 17 deletions

File tree

src/main/c/Posix/PosixHelperFunctions.c

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* PosixHelperFunctions.c
33
*
44
* Created on: Mar 10, 2015
5-
* Last Updated on: Nov 02, 2025
5+
* Last Updated on: Nov 04, 2025
66
* Author: Will Hedgecock
77
*
88
* Copyright (C) 2012-2025 Fazecast, Inc.
@@ -414,6 +414,35 @@ static void getPortLocation(const char* portDirectory, char* portLocation, int p
414414
free(busnumFile);
415415
}
416416

417+
static void getDriverName(const char* directoryToSearch, char* driverName)
418+
{
419+
// Open the directory
420+
DIR *directoryIterator = opendir(directoryToSearch);
421+
if (!directoryIterator)
422+
return;
423+
424+
// Read all sub-directories in the current directory
425+
struct dirent *directoryEntry = readdir(directoryIterator);
426+
while (directoryEntry)
427+
{
428+
// Check if entry is a valid sub-directory
429+
if (directoryEntry->d_name[0] != '.')
430+
{
431+
// Get the readable part of the driver name
432+
char *startingPoint = strchr(directoryEntry->d_name, ':');
433+
if (startingPoint != NULL)
434+
strcpy(driverName, startingPoint+1);
435+
else
436+
strcpy(driverName, directoryEntry->d_name);
437+
break;
438+
}
439+
directoryEntry = readdir(directoryIterator);
440+
}
441+
442+
// Close the directory
443+
closedir(directoryIterator);
444+
}
445+
417446
static void assignFriendlyName(const char* portDevPath, char* friendlyName)
418447
{
419448
// Manually assign a friendly name if the port type is known from its name
@@ -467,7 +496,7 @@ static void assignFriendlyName(const char* portDevPath, char* friendlyName)
467496
}
468497
}
469498

470-
static void getUsbDetails(const char* fileName, char* basePathEnd, int* vendorID, int* productID, char* serialNumber, char* manufacturer)
499+
static void getUsbDetails(const char* fileName, char* basePathEnd, int* vendorID, int* productID, char* serialNumber, char* manufacturer, char* driverName)
471500
{
472501
// Attempt to read the Vendor ID
473502
char *temp = (char*)malloc(8);
@@ -512,6 +541,11 @@ static void getUsbDetails(const char* fileName, char* basePathEnd, int* vendorID
512541
manufacturer[strcspn(manufacturer, "\r\n")] = 0;
513542
fclose(input);
514543
}
544+
545+
// Attempt to read the Device Driver
546+
strcpy(driverName, "Unknown");
547+
sprintf(basePathEnd, "driver/module/drivers");
548+
getDriverName(fileName, driverName);
515549
}
516550

517551
void searchForComPorts(serialPortVector* comPorts)
@@ -524,6 +558,7 @@ void searchForComPorts(serialPortVector* comPorts)
524558
char *line = (char*)malloc(maxLineSize), *friendlyName = (char*)malloc(256);
525559
char *portLocation = (char*)malloc(128), *interfaceDescription = (char*)malloc(256);
526560
char *serialNumber = (char*)malloc(128), *manufacturer = (char*)malloc(128);
561+
char *driverName = (char*)malloc(64);
527562

528563
// Retrieve the list of /dev/ prefixes for all physical serial ports
529564
retrievePhysicalPortPrefixes(&physicalPortPrefixes);
@@ -536,9 +571,9 @@ void searchForComPorts(serialPortVector* comPorts)
536571
while (directoryEntry)
537572
{
538573
// Ensure that the file name buffer is large enough
539-
if ((64 + strlen(directoryEntry->d_name)) > fileNameMaxLength)
574+
if ((128 + strlen(directoryEntry->d_name)) > fileNameMaxLength)
540575
{
541-
fileNameMaxLength = 64 + strlen(directoryEntry->d_name);
576+
fileNameMaxLength = 128 + strlen(directoryEntry->d_name);
542577
fileName = (char*)realloc(fileName, fileNameMaxLength);
543578
}
544579

@@ -602,7 +637,7 @@ void searchForComPorts(serialPortVector* comPorts)
602637
sprintf(basePathEnd, "/device/");
603638
basePathEnd += 8;
604639
}
605-
getUsbDetails(fileName, basePathEnd, &vendorID, &productID, serialNumber, manufacturer);
640+
getUsbDetails(fileName, basePathEnd, &vendorID, &productID, serialNumber, manufacturer, driverName);
606641
sprintf(basePathEnd, "../");
607642
getPortLocation(fileName, portLocation, isPhysical ? physicalPortNumber : -1);
608643

@@ -639,7 +674,7 @@ void searchForComPorts(serialPortVector* comPorts)
639674
}
640675
if (interfaceDescription[0] == '\0')
641676
strcpy(interfaceDescription, friendlyName);
642-
replaceDetails(port, friendlyName, interfaceDescription, portLocation, serialNumber, manufacturer, "TODO", vendorID, productID, 0);
677+
replaceDetails(port, friendlyName, interfaceDescription, portLocation, serialNumber, manufacturer, driverName, vendorID, productID, 0);
643678
}
644679

645680
// Continue port enumeration
@@ -661,7 +696,7 @@ void searchForComPorts(serialPortVector* comPorts)
661696
// Add the port to the list of available ports
662697
strcpy(friendlyName, "Physical Port ");
663698
strcat(friendlyName, directoryEntry->d_name+3);
664-
pushBack(comPorts, portDevPath, friendlyName, friendlyName, portLocation, "Unknown", "Unknown", "TODO", -1, -1, 0);
699+
pushBack(comPorts, portDevPath, friendlyName, friendlyName, portLocation, "Unknown", "Unknown", driverName, -1, -1, 0);
665700
}
666701
close(fd);
667702
}
@@ -695,7 +730,7 @@ void searchForComPorts(serialPortVector* comPorts)
695730
strcpy(interfaceDescription, friendlyName);
696731

697732
// Add the port to the list of available ports
698-
pushBack(comPorts, portDevPath, friendlyName, interfaceDescription, portLocation, serialNumber, manufacturer, "TODO", vendorID, productID, 0);
733+
pushBack(comPorts, portDevPath, friendlyName, interfaceDescription, portLocation, serialNumber, manufacturer, driverName, vendorID, productID, 0);
699734
}
700735

701736
// Read next TTY directory entry
@@ -722,9 +757,9 @@ void searchForComPorts(serialPortVector* comPorts)
722757
strcpy(fileName, "/dev/");
723758
strcat(fileName, directoryEntry->d_name);
724759
if (isPtyDevice(fileName))
725-
pushBack(comPorts, fileName, "PTY Device", "Pseudo-Terminal Device", "0-0", "Unknown", "Unknown", "TODO", -1, -1, 0);
760+
pushBack(comPorts, fileName, "PTY Device", "Pseudo-Terminal Device", "0-0", "Unknown", "Unknown", "Unknown", -1, -1, 0);
726761
else if (isBluetoothDevice(fileName))
727-
pushBack(comPorts, fileName, "Bluetooth Device", "Bluetooth Device", "0-0", "Unknown", "Unknown", "TODO", -1, -1, 0);
762+
pushBack(comPorts, fileName, "Bluetooth Device", "Bluetooth Device", "0-0", "Unknown", "Unknown", "Unknown", -1, -1, 0);
728763
else
729764
{
730765
// Copy symlinked port details from its existing TTY enumeration
@@ -748,6 +783,7 @@ void searchForComPorts(serialPortVector* comPorts)
748783
freeStringVector(&physicalPortPrefixes);
749784
if (fileName)
750785
free(fileName);
786+
free(driverName);
751787
free(interfaceDescription);
752788
free(serialNumber);
753789
free(manufacturer);

src/main/java/com/fazecast/jSerialComm/SerialPort.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -729,9 +729,9 @@ public final boolean closePort()
729729
* }
730730
* {@literal @}Override
731731
* public void serialEvent(SerialPortEvent serialPortEvent) {
732-
* if ((serialPortEvent.getEventType() & SerialPort.LISTENING_EVENT_PORT_DISCONNECTED) > 0)
732+
* if ((serialPortEvent.getEventType() {@literal &} SerialPort.LISTENING_EVENT_PORT_DISCONNECTED) {@literal >} 0)
733733
* port.closePort();
734-
* else if ((serialPortEvent.getEventType() & SerialPort.LISTENING_EVENT_DATA_RECEIVED) > 0)
734+
* else if ((serialPortEvent.getEventType() {@literal &} SerialPort.LISTENING_EVENT_DATA_RECEIVED) {@literal >} 0)
735735
* // ... you get the idea
736736
* }
737737
* });

src/main/java/com/fazecast/jSerialComm/SerialPortDataListener.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,15 @@ public interface SerialPortDataListener extends EventListener
8989
* application-level buffering should be implemented and data processing should occur on a separate thread.
9090
* <p>
9191
* Also note that if you are listening for multiple types of events (for instance, {@link SerialPort#LISTENING_EVENT_DATA_AVAILABLE} and
92-
* {@link SerialPort#LISTENING_EVENT_PORT_DISCONNECTED}) at the same time, this callback <i>may<i> be invoked only once for multiple event
92+
* {@link SerialPort#LISTENING_EVENT_PORT_DISCONNECTED}) at the same time, this callback <i>may</i> be invoked only once for multiple event
9393
* types. As such, you should test for your event of interest by bit-masking and not by testing for equivalence. The following code shows
9494
* the correct way to do this:
9595
* <pre>
9696
* {@literal @}Override
9797
* public void serialEvent(SerialPortEvent serialPortEvent) {
98-
* if ((serialPortEvent.getEventType() & SerialPort.LISTENING_EVENT_PORT_DISCONNECTED) > 0)
98+
* if ((serialPortEvent.getEventType() {@literal &} SerialPort.LISTENING_EVENT_PORT_DISCONNECTED) {@literal >} 0)
9999
* port.closePort();
100-
* else if ((serialPortEvent.getEventType() & SerialPort.LISTENING_EVENT_DATA_AVAILABLE) > 0)
100+
* else if ((serialPortEvent.getEventType() {@literal &} SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {@literal >} 0)
101101
* // ... you get the idea
102102
* }
103103
* </pre>

src/test/java/com/fazecast/jSerialComm/SerialPortTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ static public void main(String[] args)
8888
SerialPort[] ports = SerialPort.getCommPorts();
8989
System.out.println("\nAvailable Ports:\n");
9090
for (int i = 0; i < ports.length; ++i)
91-
System.out.println(" [" + i + "] " + ports[i].getSystemPortName() + " (" + ports[i].getSystemPortPath() + "): " + ports[i].getDescriptivePortName() + " - " + ports[i].getPortDescription() + " @ " + ports[i].getPortLocation() + " (VID = " + ports[i].getVendorID() + ", PID = " + ports[i].getProductID() + ", Serial = " + ports[i].getSerialNumber() + ", Manufacturer = " + ports[i].getManufacturer() + ")");
91+
System.out.println(" [" + i + "] " + ports[i].getSystemPortName() + " (" + ports[i].getSystemPortPath() + "): " + ports[i].getDescriptivePortName() + " - " + ports[i].getPortDescription() + " @ " + ports[i].getPortLocation() + " (VID = " + ports[i].getVendorID() + ", PID = " + ports[i].getProductID() + ", Serial = " + ports[i].getSerialNumber() + ", Manufacturer = " + ports[i].getManufacturer() + ", Driver = " + ports[i].getDeviceDriver() + ", Symlink = " + ports[i].isSymlink() + ")");
9292
System.out.println("\nRe-enumerating ports again in 2 seconds...\n");
9393
try { Thread.sleep(2000); } catch (Exception e) {}
9494
ports = SerialPort.getCommPorts();
9595
System.out.println("Available Ports:\n");
9696
for (int i = 0; i < ports.length; ++i)
97-
System.out.println(" [" + i + "] " + ports[i].getSystemPortName() + " (" + ports[i].getSystemPortPath() + "): " + ports[i].getDescriptivePortName() + " - " + ports[i].getPortDescription() + " @ " + ports[i].getPortLocation() + " (VID = " + ports[i].getVendorID() + ", PID = " + ports[i].getProductID() + ", Serial = " + ports[i].getSerialNumber() + ", Manufacturer = " + ports[i].getManufacturer() + ")");
97+
System.out.println(" [" + i + "] " + ports[i].getSystemPortName() + " (" + ports[i].getSystemPortPath() + "): " + ports[i].getDescriptivePortName() + " - " + ports[i].getPortDescription() + " @ " + ports[i].getPortLocation() + " (VID = " + ports[i].getVendorID() + ", PID = " + ports[i].getProductID() + ", Serial = " + ports[i].getSerialNumber() + ", Manufacturer = " + ports[i].getManufacturer() + ", Driver = " + ports[i].getDeviceDriver() + ", Symlink = " + ports[i].isSymlink() + ")");
9898
SerialPort ubxPort;
9999
System.out.print("\nChoose your desired serial port or enter -1 to specify a port directly: ");
100100
int serialPortChoice = -2;

0 commit comments

Comments
 (0)