mirror of
git://sigrok.org/libserialport
synced 2023-08-10 21:13:24 +03:00
Various cosmetic and consistency fixes.
This commit is contained in:
parent
2b40f81454
commit
dc422c04af
16
freebsd.c
16
freebsd.c
|
@ -133,7 +133,7 @@ static int libusb_query_port(struct libusb20_device *dev, int idx,
|
||||||
if (sbuf[0] == 0)
|
if (sbuf[0] == 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
DBG("device interface descriptor: idx=%003d '%s'\n", idx, sbuf);
|
DBG("Device interface descriptor: idx=%003d '%s'\n", idx, sbuf);
|
||||||
j = strchr(sbuf, ':');
|
j = strchr(sbuf, ':');
|
||||||
if (j > sbuf) {
|
if (j > sbuf) {
|
||||||
sbuf[j - sbuf] = 0;
|
sbuf[j - sbuf] = 0;
|
||||||
|
@ -244,13 +244,13 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
uint8_t idx;
|
uint8_t idx;
|
||||||
int sub_inst;
|
int sub_inst;
|
||||||
|
|
||||||
DBG("portname: '%s'\n", port->name);
|
DBG("Portname: '%s'\n", port->name);
|
||||||
|
|
||||||
if (!strncmp(port->name, DEV_CUA_PATH, strlen(DEV_CUA_PATH))) {
|
if (!strncmp(port->name, DEV_CUA_PATH, strlen(DEV_CUA_PATH))) {
|
||||||
cua_sfx = port->name + strlen(DEV_CUA_PATH);
|
cua_sfx = port->name + strlen(DEV_CUA_PATH);
|
||||||
DBG("'%s': '%s'\n", DEV_CUA_PATH, cua_sfx);
|
DBG("'%s': '%s'\n", DEV_CUA_PATH, cua_sfx);
|
||||||
} else {
|
} else {
|
||||||
RETURN_ERROR(SP_ERR_ARG, "Device name not recognized.");
|
RETURN_ERROR(SP_ERR_ARG, "Device name not recognized");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Native UART enumeration. */
|
/* Native UART enumeration. */
|
||||||
|
@ -271,7 +271,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
libusb20_dev_open(dev, 0);
|
libusb20_dev_open(dev, 0);
|
||||||
DBG("device descriptor: '%s'\n", libusb20_dev_get_desc(dev));
|
DBG("Device descriptor: '%s'\n", libusb20_dev_get_desc(dev));
|
||||||
|
|
||||||
for (idx = 0; idx <= UINT8_MAX - 1; idx++) {
|
for (idx = 0; idx <= UINT8_MAX - 1; idx++) {
|
||||||
char *drv_name_str = NULL;
|
char *drv_name_str = NULL;
|
||||||
|
@ -316,7 +316,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
libusb20_be_free(be);
|
libusb20_be_free(be);
|
||||||
|
|
||||||
if (cua_dev_found == 0)
|
if (cua_dev_found == 0)
|
||||||
DBG("WARN: found no match '%s' %s'\n", port->name, cua_sfx);
|
DBG("WARN: Found no match '%s' %s'\n", port->name, cua_sfx);
|
||||||
|
|
||||||
RETURN_OK();
|
RETURN_OK();
|
||||||
}
|
}
|
||||||
|
@ -332,7 +332,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
|
|
||||||
DEBUG("Enumerating tty devices");
|
DEBUG("Enumerating tty devices");
|
||||||
if (!(dir = opendir("/dev")))
|
if (!(dir = opendir("/dev")))
|
||||||
RETURN_FAIL("could not open dir /dev");
|
RETURN_FAIL("Could not open dir /dev");
|
||||||
|
|
||||||
DEBUG("Iterating over results");
|
DEBUG("Iterating over results");
|
||||||
while (!readdir_r(dir, &entry, &result) && result) {
|
while (!readdir_r(dir, &entry, &result) && result) {
|
||||||
|
@ -353,7 +353,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
|
|
||||||
/* Check that we can open tty/cua device in rw mode - we need that. */
|
/* Check that we can open tty/cua device in rw mode - we need that. */
|
||||||
if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY | O_TTY_INIT | O_CLOEXEC)) < 0) {
|
if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY | O_TTY_INIT | O_CLOEXEC)) < 0) {
|
||||||
DEBUG("open failed, skipping");
|
DEBUG("Open failed, skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
|
|
||||||
*list = list_append(*list, name);
|
*list = list_append(*list, name);
|
||||||
if (!list) {
|
if (!list) {
|
||||||
SET_ERROR(ret, SP_ERR_MEM, "list append failed");
|
SET_ERROR(ret, SP_ERR_MEM, "List append failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#define _BSD_SOURCE // for timeradd, timersub, timercmp
|
#define _BSD_SOURCE /* For timeradd, timersub, timercmp. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -182,7 +182,7 @@ extern void (*sp_debug_handler)(const char *format, ...);
|
||||||
#define RETURN() do { \
|
#define RETURN() do { \
|
||||||
DEBUG_FMT("%s returning", __func__); \
|
DEBUG_FMT("%s returning", __func__); \
|
||||||
return; \
|
return; \
|
||||||
} while(0)
|
} while (0)
|
||||||
#define RETURN_CODE(x) do { \
|
#define RETURN_CODE(x) do { \
|
||||||
DEBUG_FMT("%s returning " #x, __func__); \
|
DEBUG_FMT("%s returning " #x, __func__); \
|
||||||
return x; \
|
return x; \
|
||||||
|
|
30
linux.c
30
linux.c
|
@ -22,8 +22,10 @@
|
||||||
|
|
||||||
SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
{
|
{
|
||||||
/* Description limited to 127 char,
|
/*
|
||||||
anything longer would not be user friendly anyway */
|
* Description limited to 127 char, anything longer
|
||||||
|
* would not be user friendly anyway.
|
||||||
|
*/
|
||||||
char description[128];
|
char description[128];
|
||||||
int bus, address;
|
int bus, address;
|
||||||
unsigned int vid, pid;
|
unsigned int vid, pid;
|
||||||
|
@ -36,12 +38,12 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
int i, count;
|
int i, count;
|
||||||
|
|
||||||
if (strncmp(port->name, "/dev/", 5))
|
if (strncmp(port->name, "/dev/", 5))
|
||||||
RETURN_ERROR(SP_ERR_ARG, "Device name not recognized.");
|
RETURN_ERROR(SP_ERR_ARG, "Device name not recognized");
|
||||||
|
|
||||||
snprintf(file_name, sizeof(file_name), "/sys/class/tty/%s", dev);
|
snprintf(file_name, sizeof(file_name), "/sys/class/tty/%s", dev);
|
||||||
count = readlink(file_name, file_name, sizeof(file_name));
|
count = readlink(file_name, file_name, sizeof(file_name));
|
||||||
if (count <= 0 || count >= (int) sizeof(file_name)-1)
|
if (count <= 0 || count >= (int)(sizeof(file_name) - 1))
|
||||||
RETURN_ERROR(SP_ERR_ARG, "Device not found.");
|
RETURN_ERROR(SP_ERR_ARG, "Device not found");
|
||||||
file_name[count] = 0;
|
file_name[count] = 0;
|
||||||
if (strstr(file_name, "bluetooth"))
|
if (strstr(file_name, "bluetooth"))
|
||||||
port->transport = SP_TRANSPORT_BLUETOOTH;
|
port->transport = SP_TRANSPORT_BLUETOOTH;
|
||||||
|
@ -49,7 +51,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
port->transport = SP_TRANSPORT_USB;
|
port->transport = SP_TRANSPORT_USB;
|
||||||
|
|
||||||
if (port->transport == SP_TRANSPORT_USB) {
|
if (port->transport == SP_TRANSPORT_USB) {
|
||||||
for (i=0; i<5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
strcat(sub_dir, "../");
|
strcat(sub_dir, "../");
|
||||||
|
|
||||||
snprintf(file_name, sizeof(file_name), dir_name, dev, sub_dir, "busnum");
|
snprintf(file_name, sizeof(file_name), dir_name, dev, sub_dir, "busnum");
|
||||||
|
@ -181,13 +183,13 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
|
|
||||||
DEBUG("Enumerating tty devices");
|
DEBUG("Enumerating tty devices");
|
||||||
if (!(dir = opendir("/sys/class/tty")))
|
if (!(dir = opendir("/sys/class/tty")))
|
||||||
RETURN_FAIL("could not open /sys/class/tty");
|
RETURN_FAIL("Could not open /sys/class/tty");
|
||||||
|
|
||||||
DEBUG("Iterating over results");
|
DEBUG("Iterating over results");
|
||||||
while (!readdir_r(dir, &entry, &result) && result) {
|
while (!readdir_r(dir, &entry, &result) && result) {
|
||||||
snprintf(buf, sizeof(buf), "/sys/class/tty/%s", entry.d_name);
|
snprintf(buf, sizeof(buf), "/sys/class/tty/%s", entry.d_name);
|
||||||
len = readlink(buf, target, sizeof(target));
|
len = readlink(buf, target, sizeof(target));
|
||||||
if (len <= 0 || len >= (int) sizeof(target)-1)
|
if (len <= 0 || len >= (int)(sizeof(target) - 1))
|
||||||
continue;
|
continue;
|
||||||
target[len] = 0;
|
target[len] = 0;
|
||||||
if (strstr(target, "virtual"))
|
if (strstr(target, "virtual"))
|
||||||
|
@ -195,12 +197,14 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
snprintf(name, sizeof(name), "/dev/%s", entry.d_name);
|
snprintf(name, sizeof(name), "/dev/%s", entry.d_name);
|
||||||
DEBUG_FMT("Found device %s", name);
|
DEBUG_FMT("Found device %s", name);
|
||||||
if (strstr(target, "serial8250")) {
|
if (strstr(target, "serial8250")) {
|
||||||
/* The serial8250 driver has a hardcoded number of ports.
|
/*
|
||||||
|
* The serial8250 driver has a hardcoded number of ports.
|
||||||
* The only way to tell which actually exist on a given system
|
* The only way to tell which actually exist on a given system
|
||||||
* is to try to open them and make an ioctl call. */
|
* is to try to open them and make an ioctl call.
|
||||||
|
*/
|
||||||
DEBUG("serial8250 device, attempting to open");
|
DEBUG("serial8250 device, attempting to open");
|
||||||
if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
|
if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
|
||||||
DEBUG("open failed, skipping");
|
DEBUG("Open failed, skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_SERIAL_STRUCT
|
#ifdef HAVE_SERIAL_STRUCT
|
||||||
|
@ -213,7 +217,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (serial_info.type == PORT_UNKNOWN) {
|
if (serial_info.type == PORT_UNKNOWN) {
|
||||||
DEBUG("port type is unknown, skipping");
|
DEBUG("Port type is unknown, skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -221,7 +225,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
DEBUG_FMT("Found port %s", name);
|
DEBUG_FMT("Found port %s", name);
|
||||||
*list = list_append(*list, name);
|
*list = list_append(*list, name);
|
||||||
if (!list) {
|
if (!list) {
|
||||||
SET_ERROR(ret, SP_ERR_MEM, "list append failed");
|
SET_ERROR(ret, SP_ERR_MEM, "List append failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
macosx.c
22
macosx.c
|
@ -23,8 +23,10 @@
|
||||||
|
|
||||||
SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
{
|
{
|
||||||
/* Description limited to 127 char,
|
/*
|
||||||
anything longer would not be user friendly anyway */
|
* Description limited to 127 char, anything longer
|
||||||
|
* would not be user friendly anyway.
|
||||||
|
*/
|
||||||
char description[128];
|
char description[128];
|
||||||
int bus, address, vid, pid = -1;
|
int bus, address, vid, pid = -1;
|
||||||
char manufacturer[128], product[128], serial[128];
|
char manufacturer[128], product[128], serial[128];
|
||||||
|
@ -111,8 +113,10 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
port->usb_bus = bus;
|
port->usb_bus = bus;
|
||||||
port->usb_address = address;
|
port->usb_address = address;
|
||||||
}
|
}
|
||||||
if (cf_bus ) CFRelease(cf_bus);
|
if (cf_bus)
|
||||||
if (cf_address) CFRelease(cf_address);
|
CFRelease(cf_bus);
|
||||||
|
if (cf_address)
|
||||||
|
CFRelease(cf_address);
|
||||||
|
|
||||||
cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
|
cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
|
||||||
CFSTR("idVendor"),
|
CFSTR("idVendor"),
|
||||||
|
@ -127,12 +131,14 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
if (cf_vendor && cf_product &&
|
if (cf_vendor && cf_product &&
|
||||||
CFNumberGetValue(cf_vendor , kCFNumberIntType, &vid) &&
|
CFNumberGetValue(cf_vendor , kCFNumberIntType, &vid) &&
|
||||||
CFNumberGetValue(cf_product, kCFNumberIntType, &pid)) {
|
CFNumberGetValue(cf_product, kCFNumberIntType, &pid)) {
|
||||||
DEBUG_FMT("Found matching USB vid:pid %04X:%04X", vid, pid);
|
DEBUG_FMT("Found matching USB VID:PID %04X:%04X", vid, pid);
|
||||||
port->usb_vid = vid;
|
port->usb_vid = vid;
|
||||||
port->usb_pid = pid;
|
port->usb_pid = pid;
|
||||||
}
|
}
|
||||||
if (cf_vendor ) CFRelease(cf_vendor);
|
if (cf_vendor)
|
||||||
if (cf_product) CFRelease(cf_product);
|
CFRelease(cf_vendor);
|
||||||
|
if (cf_product)
|
||||||
|
CFRelease(cf_product);
|
||||||
|
|
||||||
if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
|
if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
|
||||||
CFSTR("USB Vendor Name"), kCFAllocatorDefault,
|
CFSTR("USB Vendor Name"), kCFAllocatorDefault,
|
||||||
|
@ -209,7 +215,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
if (result) {
|
if (result) {
|
||||||
DEBUG_FMT("Found port %s", path);
|
DEBUG_FMT("Found port %s", path);
|
||||||
if (!(*list = list_append(*list, path))) {
|
if (!(*list = list_append(*list, path))) {
|
||||||
SET_ERROR(ret, SP_ERR_MEM, "list append failed");
|
SET_ERROR(ret, SP_ERR_MEM, "List append failed");
|
||||||
IOObjectRelease(port);
|
IOObjectRelease(port);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
70
serialport.c
70
serialport.c
|
@ -156,8 +156,10 @@ SP_API enum sp_return sp_get_port_usb_bus_address(const struct sp_port *port,
|
||||||
if (port->usb_bus < 0 || port->usb_address < 0)
|
if (port->usb_bus < 0 || port->usb_address < 0)
|
||||||
RETURN_ERROR(SP_ERR_SUPP, "Bus and address values are not available");
|
RETURN_ERROR(SP_ERR_SUPP, "Bus and address values are not available");
|
||||||
|
|
||||||
if (usb_bus) *usb_bus = port->usb_bus;
|
if (usb_bus)
|
||||||
if (usb_address) *usb_address = port->usb_address;
|
*usb_bus = port->usb_bus;
|
||||||
|
if (usb_address)
|
||||||
|
*usb_address = port->usb_address;
|
||||||
|
|
||||||
RETURN_OK();
|
RETURN_OK();
|
||||||
}
|
}
|
||||||
|
@ -174,8 +176,10 @@ SP_API enum sp_return sp_get_port_usb_vid_pid(const struct sp_port *port,
|
||||||
if (port->usb_vid < 0 || port->usb_pid < 0)
|
if (port->usb_vid < 0 || port->usb_pid < 0)
|
||||||
RETURN_ERROR(SP_ERR_SUPP, "VID:PID values are not available");
|
RETURN_ERROR(SP_ERR_SUPP, "VID:PID values are not available");
|
||||||
|
|
||||||
if (usb_vid) *usb_vid = port->usb_vid;
|
if (usb_vid)
|
||||||
if (usb_pid) *usb_pid = port->usb_pid;
|
*usb_vid = port->usb_vid;
|
||||||
|
if (usb_pid)
|
||||||
|
*usb_pid = port->usb_pid;
|
||||||
|
|
||||||
RETURN_OK();
|
RETURN_OK();
|
||||||
}
|
}
|
||||||
|
@ -372,9 +376,9 @@ SP_API void sp_free_port_list(struct sp_port **list)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_PORT() do { \
|
#define CHECK_PORT() do { \
|
||||||
if (port == NULL) \
|
if (!port) \
|
||||||
RETURN_ERROR(SP_ERR_ARG, "Null port"); \
|
RETURN_ERROR(SP_ERR_ARG, "Null port"); \
|
||||||
if (port->name == NULL) \
|
if (!port->name) \
|
||||||
RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
|
RETURN_ERROR(SP_ERR_ARG, "Null port name"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -431,7 +435,7 @@ SP_API enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
|
||||||
free(escaped_port_name);
|
free(escaped_port_name);
|
||||||
|
|
||||||
if (port->hdl == INVALID_HANDLE_VALUE)
|
if (port->hdl == INVALID_HANDLE_VALUE)
|
||||||
RETURN_FAIL("port CreateFile() failed");
|
RETURN_FAIL("Port CreateFile() failed");
|
||||||
|
|
||||||
/* All timeouts initially disabled. */
|
/* All timeouts initially disabled. */
|
||||||
port->timeouts.ReadIntervalTimeout = 0;
|
port->timeouts.ReadIntervalTimeout = 0;
|
||||||
|
@ -570,7 +574,7 @@ SP_API enum sp_return sp_close(struct sp_port *port)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/* Returns non-zero upon success, 0 upon failure. */
|
/* Returns non-zero upon success, 0 upon failure. */
|
||||||
if (CloseHandle(port->hdl) == 0)
|
if (CloseHandle(port->hdl) == 0)
|
||||||
RETURN_FAIL("port CloseHandle() failed");
|
RETURN_FAIL("Port CloseHandle() failed");
|
||||||
port->hdl = INVALID_HANDLE_VALUE;
|
port->hdl = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
/* Close event handles for overlapped structures. */
|
/* Close event handles for overlapped structures. */
|
||||||
|
@ -740,15 +744,14 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop until we have written the requested number of bytes. */
|
/* Loop until we have written the requested number of bytes. */
|
||||||
while (bytes_written < count)
|
while (bytes_written < count) {
|
||||||
{
|
|
||||||
/* Wait until space is available. */
|
/* Wait until space is available. */
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(port->fd, &fds);
|
FD_SET(port->fd, &fds);
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
if (timercmp(&now, &end, >)) {
|
if (timercmp(&now, &end, >)) {
|
||||||
DEBUG("write timed out");
|
DEBUG("Write timed out");
|
||||||
RETURN_INT(bytes_written);
|
RETURN_INT(bytes_written);
|
||||||
}
|
}
|
||||||
timersub(&end, &now, &delta);
|
timersub(&end, &now, &delta);
|
||||||
|
@ -762,7 +765,7 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
|
||||||
RETURN_FAIL("select() failed");
|
RETURN_FAIL("select() failed");
|
||||||
}
|
}
|
||||||
} else if (result == 0) {
|
} else if (result == 0) {
|
||||||
DEBUG("write timed out");
|
DEBUG("Write timed out");
|
||||||
RETURN_INT(bytes_written);
|
RETURN_INT(bytes_written);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,10 +825,11 @@ SP_API enum sp_return sp_nonblocking_write(struct sp_port *port,
|
||||||
if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
|
if (SetCommTimeouts(port->hdl, &port->timeouts) == 0)
|
||||||
RETURN_FAIL("SetCommTimeouts() failed");
|
RETURN_FAIL("SetCommTimeouts() failed");
|
||||||
|
|
||||||
/* Keep writing data until the OS has to actually start an async IO for it.
|
/*
|
||||||
* At that point we know the buffer is full. */
|
* Keep writing data until the OS has to actually start an async IO
|
||||||
while (written < count)
|
* for it. At that point we know the buffer is full.
|
||||||
{
|
*/
|
||||||
|
while (written < count) {
|
||||||
/* Copy first byte of user buffer. */
|
/* Copy first byte of user buffer. */
|
||||||
port->pending_byte = *ptr++;
|
port->pending_byte = *ptr++;
|
||||||
|
|
||||||
|
@ -941,8 +945,7 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop until we have the requested number of bytes. */
|
/* Loop until we have the requested number of bytes. */
|
||||||
while (bytes_read < count)
|
while (bytes_read < count) {
|
||||||
{
|
|
||||||
/* Wait until data is available. */
|
/* Wait until data is available. */
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(port->fd, &fds);
|
FD_SET(port->fd, &fds);
|
||||||
|
@ -962,7 +965,7 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
|
||||||
RETURN_FAIL("select() failed");
|
RETURN_FAIL("select() failed");
|
||||||
}
|
}
|
||||||
} else if (result == 0) {
|
} else if (result == 0) {
|
||||||
DEBUG("read timed out");
|
DEBUG("Read timed out");
|
||||||
RETURN_INT(bytes_read);
|
RETURN_INT(bytes_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1121,11 +1124,11 @@ static enum sp_return add_handle(struct sp_event_set *event_set,
|
||||||
|
|
||||||
if (!(new_handles = realloc(event_set->handles,
|
if (!(new_handles = realloc(event_set->handles,
|
||||||
sizeof(event_handle) * (event_set->count + 1))))
|
sizeof(event_handle) * (event_set->count + 1))))
|
||||||
RETURN_ERROR(SP_ERR_MEM, "handle array realloc() failed");
|
RETURN_ERROR(SP_ERR_MEM, "Handle array realloc() failed");
|
||||||
|
|
||||||
if (!(new_masks = realloc(event_set->masks,
|
if (!(new_masks = realloc(event_set->masks,
|
||||||
sizeof(enum sp_event) * (event_set->count + 1))))
|
sizeof(enum sp_event) * (event_set->count + 1))))
|
||||||
RETURN_ERROR(SP_ERR_MEM, "mask array realloc() failed");
|
RETURN_ERROR(SP_ERR_MEM, "Mask array realloc() failed");
|
||||||
|
|
||||||
event_set->handles = new_handles;
|
event_set->handles = new_handles;
|
||||||
event_set->masks = new_masks;
|
event_set->masks = new_masks;
|
||||||
|
@ -1235,12 +1238,11 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop until an event occurs. */
|
/* Loop until an event occurs. */
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
if (timercmp(&now, &end, >)) {
|
if (timercmp(&now, &end, >)) {
|
||||||
DEBUG("wait timed out");
|
DEBUG("Wait timed out");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
timersub(&end, &now, &delta);
|
timersub(&end, &now, &delta);
|
||||||
|
@ -1285,7 +1287,7 @@ static enum sp_return get_baudrate(int fd, int *baudrate)
|
||||||
|
|
||||||
if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
|
if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
|
||||||
free(data);
|
free(data);
|
||||||
RETURN_FAIL("getting termios failed");
|
RETURN_FAIL("Getting termios failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
*baudrate = get_termios_speed(data);
|
*baudrate = get_termios_speed(data);
|
||||||
|
@ -1308,7 +1310,7 @@ static enum sp_return set_baudrate(int fd, int baudrate)
|
||||||
|
|
||||||
if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
|
if (ioctl(fd, get_termios_get_ioctl(), data) < 0) {
|
||||||
free(data);
|
free(data);
|
||||||
RETURN_FAIL("getting termios failed");
|
RETURN_FAIL("Getting termios failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("Setting baud rate");
|
DEBUG("Setting baud rate");
|
||||||
|
@ -1317,7 +1319,7 @@ static enum sp_return set_baudrate(int fd, int baudrate)
|
||||||
|
|
||||||
if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
|
if (ioctl(fd, get_termios_set_ioctl(), data) < 0) {
|
||||||
free(data);
|
free(data);
|
||||||
RETURN_FAIL("setting termios failed");
|
RETURN_FAIL("Setting termios failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -1340,7 +1342,7 @@ static enum sp_return get_flow(int fd, struct port_data *data)
|
||||||
|
|
||||||
if (ioctl(fd, TCGETX, termx) < 0) {
|
if (ioctl(fd, TCGETX, termx) < 0) {
|
||||||
free(termx);
|
free(termx);
|
||||||
RETURN_FAIL("getting termiox failed");
|
RETURN_FAIL("Getting termiox failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
|
get_termiox_flow(termx, &data->rts_flow, &data->cts_flow,
|
||||||
|
@ -1364,7 +1366,7 @@ static enum sp_return set_flow(int fd, struct port_data *data)
|
||||||
|
|
||||||
if (ioctl(fd, TCGETX, termx) < 0) {
|
if (ioctl(fd, TCGETX, termx) < 0) {
|
||||||
free(termx);
|
free(termx);
|
||||||
RETURN_FAIL("getting termiox failed");
|
RETURN_FAIL("Getting termiox failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("Setting advanced flow control");
|
DEBUG("Setting advanced flow control");
|
||||||
|
@ -1374,7 +1376,7 @@ static enum sp_return set_flow(int fd, struct port_data *data)
|
||||||
|
|
||||||
if (ioctl(fd, TCSETX, termx) < 0) {
|
if (ioctl(fd, TCSETX, termx) < 0) {
|
||||||
free(termx);
|
free(termx);
|
||||||
RETURN_FAIL("setting termiox failed");
|
RETURN_FAIL("Setting termiox failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(termx);
|
free(termx);
|
||||||
|
@ -1958,8 +1960,10 @@ static enum sp_return set_config(struct sp_port *port, struct port_data *data,
|
||||||
if (baud_nonstd != B0) {
|
if (baud_nonstd != B0) {
|
||||||
if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
|
if (ioctl(port->fd, IOSSIOSPEED, &baud_nonstd) == -1)
|
||||||
RETURN_FAIL("IOSSIOSPEED ioctl failed");
|
RETURN_FAIL("IOSSIOSPEED ioctl failed");
|
||||||
/* Set baud rates in data->term to correct, but incompatible
|
/*
|
||||||
* with tcsetattr() value, same as delivered by tcgetattr(). */
|
* Set baud rates in data->term to correct, but incompatible
|
||||||
|
* with tcsetattr() value, same as delivered by tcgetattr().
|
||||||
|
*/
|
||||||
if (cfsetspeed(&data->term, baud_nonstd) < 0)
|
if (cfsetspeed(&data->term, baud_nonstd) < 0)
|
||||||
RETURN_FAIL("cfsetspeed() failed");
|
RETURN_FAIL("cfsetspeed() failed");
|
||||||
}
|
}
|
||||||
|
@ -1991,7 +1995,7 @@ SP_API enum sp_return sp_new_config(struct sp_port_config **config_ptr)
|
||||||
*config_ptr = NULL;
|
*config_ptr = NULL;
|
||||||
|
|
||||||
if (!(config = malloc(sizeof(struct sp_port_config))))
|
if (!(config = malloc(sizeof(struct sp_port_config))))
|
||||||
RETURN_ERROR(SP_ERR_MEM, "config malloc failed");
|
RETURN_ERROR(SP_ERR_MEM, "Config malloc failed");
|
||||||
|
|
||||||
config->baudrate = -1;
|
config->baudrate = -1;
|
||||||
config->bits = -1;
|
config->bits = -1;
|
||||||
|
|
112
windows.c
112
windows.c
|
@ -21,31 +21,31 @@
|
||||||
#include "libserialport.h"
|
#include "libserialport.h"
|
||||||
#include "libserialport_internal.h"
|
#include "libserialport_internal.h"
|
||||||
|
|
||||||
/* USB path is a string of at most 8 decimal numbers < 128 separated by dots */
|
/* USB path is a string of at most 8 decimal numbers < 128 separated by dots. */
|
||||||
#define MAX_USB_PATH (8*3 + 7*1 + 1)
|
#define MAX_USB_PATH ((8 * 3) + (7 * 1) + 1)
|
||||||
|
|
||||||
static void enumerate_hub(struct sp_port *port, char *hub_name,
|
static void enumerate_hub(struct sp_port *port, char *hub_name,
|
||||||
char *parent_path);
|
char *parent_path);
|
||||||
|
|
||||||
static char *wc_to_utf8(PWCHAR wc_buffer, ULONG size)
|
static char *wc_to_utf8(PWCHAR wc_buffer, ULONG size)
|
||||||
{
|
{
|
||||||
WCHAR wc_str[size/sizeof(WCHAR)+1];
|
WCHAR wc_str[(size / sizeof(WCHAR)) + 1];
|
||||||
char *utf8_str;
|
char *utf8_str;
|
||||||
|
|
||||||
/* zero terminate the wide char string */
|
/* Zero-terminate the wide char string. */
|
||||||
memcpy(wc_str, wc_buffer, size);
|
memcpy(wc_str, wc_buffer, size);
|
||||||
wc_str[sizeof(wc_str)-1] = 0;
|
wc_str[sizeof(wc_str) - 1] = 0;
|
||||||
|
|
||||||
/* compute the size of the utf8 converted string */
|
/* Compute the size of the UTF-8 converted string. */
|
||||||
if (!(size = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wc_str, -1,
|
if (!(size = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wc_str, -1,
|
||||||
NULL, 0, NULL, NULL)))
|
NULL, 0, NULL, NULL)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* allocate utf8 output buffer */
|
/* Allocate UTF-8 output buffer. */
|
||||||
if (!(utf8_str = malloc(size)))
|
if (!(utf8_str = malloc(size)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* actually converted to utf8 */
|
/* Actually converted to UTF-8. */
|
||||||
if (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wc_str, -1,
|
if (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wc_str, -1,
|
||||||
utf8_str, size, NULL, NULL)) {
|
utf8_str, size, NULL, NULL)) {
|
||||||
free(utf8_str);
|
free(utf8_str);
|
||||||
|
@ -57,29 +57,29 @@ static char *wc_to_utf8(PWCHAR wc_buffer, ULONG size)
|
||||||
|
|
||||||
static char *get_root_hub_name(HANDLE host_controller)
|
static char *get_root_hub_name(HANDLE host_controller)
|
||||||
{
|
{
|
||||||
USB_ROOT_HUB_NAME root_hub_name;
|
USB_ROOT_HUB_NAME root_hub_name;
|
||||||
PUSB_ROOT_HUB_NAME root_hub_name_wc;
|
PUSB_ROOT_HUB_NAME root_hub_name_wc;
|
||||||
char *root_hub_name_utf8;
|
char *root_hub_name_utf8;
|
||||||
ULONG size = 0;
|
ULONG size = 0;
|
||||||
|
|
||||||
/* compute the size of the root hub name string */
|
/* Compute the size of the root hub name string. */
|
||||||
if (!DeviceIoControl(host_controller, IOCTL_USB_GET_ROOT_HUB_NAME, 0, 0,
|
if (!DeviceIoControl(host_controller, IOCTL_USB_GET_ROOT_HUB_NAME, 0, 0,
|
||||||
&root_hub_name, sizeof(root_hub_name), &size, NULL))
|
&root_hub_name, sizeof(root_hub_name), &size, NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* allocate wide char root hub name string */
|
/* Allocate wide char root hub name string. */
|
||||||
size = root_hub_name.ActualLength;
|
size = root_hub_name.ActualLength;
|
||||||
if (!(root_hub_name_wc = malloc(size)))
|
if (!(root_hub_name_wc = malloc(size)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* actually get the root hub name string */
|
/* Actually get the root hub name string. */
|
||||||
if (!DeviceIoControl(host_controller, IOCTL_USB_GET_ROOT_HUB_NAME,
|
if (!DeviceIoControl(host_controller, IOCTL_USB_GET_ROOT_HUB_NAME,
|
||||||
NULL, 0, root_hub_name_wc, size, &size, NULL)) {
|
NULL, 0, root_hub_name_wc, size, &size, NULL)) {
|
||||||
free(root_hub_name_wc);
|
free(root_hub_name_wc);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert the root hub name string to utf8 */
|
/* Convert the root hub name string to UTF-8. */
|
||||||
root_hub_name_utf8 = wc_to_utf8(root_hub_name_wc->RootHubName, size);
|
root_hub_name_utf8 = wc_to_utf8(root_hub_name_wc->RootHubName, size);
|
||||||
free(root_hub_name_wc);
|
free(root_hub_name_wc);
|
||||||
return root_hub_name_utf8;
|
return root_hub_name_utf8;
|
||||||
|
@ -87,25 +87,25 @@ static char *get_root_hub_name(HANDLE host_controller)
|
||||||
|
|
||||||
static char *get_external_hub_name(HANDLE hub, ULONG connection_index)
|
static char *get_external_hub_name(HANDLE hub, ULONG connection_index)
|
||||||
{
|
{
|
||||||
USB_NODE_CONNECTION_NAME ext_hub_name;
|
USB_NODE_CONNECTION_NAME ext_hub_name;
|
||||||
PUSB_NODE_CONNECTION_NAME ext_hub_name_wc;
|
PUSB_NODE_CONNECTION_NAME ext_hub_name_wc;
|
||||||
char *ext_hub_name_utf8;
|
char *ext_hub_name_utf8;
|
||||||
ULONG size;
|
ULONG size;
|
||||||
|
|
||||||
/* compute the size of the external hub name string */
|
/* Compute the size of the external hub name string. */
|
||||||
ext_hub_name.ConnectionIndex = connection_index;
|
ext_hub_name.ConnectionIndex = connection_index;
|
||||||
if (!DeviceIoControl(hub, IOCTL_USB_GET_NODE_CONNECTION_NAME,
|
if (!DeviceIoControl(hub, IOCTL_USB_GET_NODE_CONNECTION_NAME,
|
||||||
&ext_hub_name, sizeof(ext_hub_name),
|
&ext_hub_name, sizeof(ext_hub_name),
|
||||||
&ext_hub_name, sizeof(ext_hub_name), &size, NULL))
|
&ext_hub_name, sizeof(ext_hub_name), &size, NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* allocate wide char external hub name string */
|
/* Allocate wide char external hub name string. */
|
||||||
size = ext_hub_name.ActualLength;
|
size = ext_hub_name.ActualLength;
|
||||||
if (size <= sizeof(ext_hub_name)
|
if (size <= sizeof(ext_hub_name)
|
||||||
|| !(ext_hub_name_wc = malloc(size)))
|
|| !(ext_hub_name_wc = malloc(size)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* get the name of the external hub attached to the specified port */
|
/* Get the name of the external hub attached to the specified port. */
|
||||||
ext_hub_name_wc->ConnectionIndex = connection_index;
|
ext_hub_name_wc->ConnectionIndex = connection_index;
|
||||||
if (!DeviceIoControl(hub, IOCTL_USB_GET_NODE_CONNECTION_NAME,
|
if (!DeviceIoControl(hub, IOCTL_USB_GET_NODE_CONNECTION_NAME,
|
||||||
ext_hub_name_wc, size,
|
ext_hub_name_wc, size,
|
||||||
|
@ -114,7 +114,7 @@ static char *get_external_hub_name(HANDLE hub, ULONG connection_index)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert the external hub name string to utf8 */
|
/* Convert the external hub name string to UTF-8. */
|
||||||
ext_hub_name_utf8 = wc_to_utf8(ext_hub_name_wc->NodeName, size);
|
ext_hub_name_utf8 = wc_to_utf8(ext_hub_name_wc->NodeName, size);
|
||||||
free(ext_hub_name_wc);
|
free(ext_hub_name_wc);
|
||||||
return ext_hub_name_utf8;
|
return ext_hub_name_utf8;
|
||||||
|
@ -125,14 +125,14 @@ static char *get_string_descriptor(HANDLE hub_device, ULONG connection_index,
|
||||||
{
|
{
|
||||||
char desc_req_buf[sizeof(USB_DESCRIPTOR_REQUEST) +
|
char desc_req_buf[sizeof(USB_DESCRIPTOR_REQUEST) +
|
||||||
MAXIMUM_USB_STRING_LENGTH] = { 0 };
|
MAXIMUM_USB_STRING_LENGTH] = { 0 };
|
||||||
PUSB_DESCRIPTOR_REQUEST desc_req = (void *) desc_req_buf;
|
PUSB_DESCRIPTOR_REQUEST desc_req = (void *)desc_req_buf;
|
||||||
PUSB_STRING_DESCRIPTOR desc = (void *) (desc_req + 1);
|
PUSB_STRING_DESCRIPTOR desc = (void *)(desc_req + 1);
|
||||||
ULONG size = sizeof(desc_req_buf);
|
ULONG size = sizeof(desc_req_buf);
|
||||||
|
|
||||||
desc_req->ConnectionIndex = connection_index;
|
desc_req->ConnectionIndex = connection_index;
|
||||||
desc_req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8)
|
desc_req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8)
|
||||||
| descriptor_index;
|
| descriptor_index;
|
||||||
desc_req->SetupPacket.wIndex = 0;
|
desc_req->SetupPacket.wIndex = 0;
|
||||||
desc_req->SetupPacket.wLength = size - sizeof(*desc_req);
|
desc_req->SetupPacket.wLength = size - sizeof(*desc_req);
|
||||||
|
|
||||||
if (!DeviceIoControl(hub_device,
|
if (!DeviceIoControl(hub_device,
|
||||||
|
@ -155,7 +155,7 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device,
|
||||||
|
|
||||||
for (index = 1; index <= nb_ports; index++) {
|
for (index = 1; index <= nb_ports; index++) {
|
||||||
PUSB_NODE_CONNECTION_INFORMATION_EX connection_info_ex;
|
PUSB_NODE_CONNECTION_INFORMATION_EX connection_info_ex;
|
||||||
ULONG size = sizeof(*connection_info_ex) + 30*sizeof(USB_PIPE_INFO);
|
ULONG size = sizeof(*connection_info_ex) + (30 * sizeof(USB_PIPE_INFO));
|
||||||
|
|
||||||
if (!(connection_info_ex = malloc(size)))
|
if (!(connection_info_ex = malloc(size)))
|
||||||
break;
|
break;
|
||||||
|
@ -165,11 +165,13 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device,
|
||||||
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
|
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
|
||||||
connection_info_ex, size,
|
connection_info_ex, size,
|
||||||
connection_info_ex, size, &size, NULL)) {
|
connection_info_ex, size, &size, NULL)) {
|
||||||
/* try to get CONNECTION_INFORMATION if CONNECTION_INFORMATION_EX
|
/*
|
||||||
did not work */
|
* Try to get CONNECTION_INFORMATION if
|
||||||
|
* CONNECTION_INFORMATION_EX did not work.
|
||||||
|
*/
|
||||||
PUSB_NODE_CONNECTION_INFORMATION connection_info;
|
PUSB_NODE_CONNECTION_INFORMATION connection_info;
|
||||||
|
|
||||||
size = sizeof(*connection_info) + 30*sizeof(USB_PIPE_INFO);
|
size = sizeof(*connection_info) + (30 * sizeof(USB_PIPE_INFO));
|
||||||
if (!(connection_info = malloc(size))) {
|
if (!(connection_info = malloc(size))) {
|
||||||
free(connection_info_ex);
|
free(connection_info_ex);
|
||||||
continue;
|
continue;
|
||||||
|
@ -192,7 +194,7 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection_info_ex->DeviceIsHub) {
|
if (connection_info_ex->DeviceIsHub) {
|
||||||
/* recursively enumerate external hub */
|
/* Recursively enumerate external hub. */
|
||||||
PCHAR ext_hub_name;
|
PCHAR ext_hub_name;
|
||||||
if ((ext_hub_name = get_external_hub_name(hub_device, index))) {
|
if ((ext_hub_name = get_external_hub_name(hub_device, index))) {
|
||||||
snprintf(path, sizeof(path), "%s%ld.",
|
snprintf(path, sizeof(path), "%s%ld.",
|
||||||
|
@ -204,13 +206,13 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device,
|
||||||
snprintf(path, sizeof(path), "%s%ld",
|
snprintf(path, sizeof(path), "%s%ld",
|
||||||
parent_path, connection_info_ex->ConnectionIndex);
|
parent_path, connection_info_ex->ConnectionIndex);
|
||||||
|
|
||||||
/* check if this device is the one we search for */
|
/* Check if this device is the one we search for. */
|
||||||
if (strcmp(path, port->usb_path)) {
|
if (strcmp(path, port->usb_path)) {
|
||||||
free(connection_info_ex);
|
free(connection_info_ex);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finally grab detailed informations regarding the device */
|
/* Finally grab detailed information regarding the device. */
|
||||||
port->usb_address = connection_info_ex->DeviceAddress + 1;
|
port->usb_address = connection_info_ex->DeviceAddress + 1;
|
||||||
port->usb_vid = connection_info_ex->DeviceDescriptor.idVendor;
|
port->usb_vid = connection_info_ex->DeviceDescriptor.idVendor;
|
||||||
port->usb_pid = connection_info_ex->DeviceDescriptor.idProduct;
|
port->usb_pid = connection_info_ex->DeviceDescriptor.idProduct;
|
||||||
|
@ -239,7 +241,7 @@ static void enumerate_hub(struct sp_port *port, char *hub_name,
|
||||||
ULONG size = sizeof(hub_info);
|
ULONG size = sizeof(hub_info);
|
||||||
char *device_name;
|
char *device_name;
|
||||||
|
|
||||||
/* open the hub with its full name */
|
/* Open the hub with its full name. */
|
||||||
if (!(device_name = malloc(strlen("\\\\.\\") + strlen(hub_name) + 1)))
|
if (!(device_name = malloc(strlen("\\\\.\\") + strlen(hub_name) + 1)))
|
||||||
return;
|
return;
|
||||||
strcpy(device_name, "\\\\.\\");
|
strcpy(device_name, "\\\\.\\");
|
||||||
|
@ -250,10 +252,10 @@ static void enumerate_hub(struct sp_port *port, char *hub_name,
|
||||||
if (hub_device == INVALID_HANDLE_VALUE)
|
if (hub_device == INVALID_HANDLE_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* get the number of ports of the hub */
|
/* Get the number of ports of the hub. */
|
||||||
if (DeviceIoControl(hub_device, IOCTL_USB_GET_NODE_INFORMATION,
|
if (DeviceIoControl(hub_device, IOCTL_USB_GET_NODE_INFORMATION,
|
||||||
&hub_info, size, &hub_info, size, &size, NULL))
|
&hub_info, size, &hub_info, size, &size, NULL))
|
||||||
/* enumerate the ports of the hub */
|
/* Enumerate the ports of the hub. */
|
||||||
enumerate_hub_ports(port, hub_device,
|
enumerate_hub_ports(port, hub_device,
|
||||||
hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts, parent_path);
|
hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts, parent_path);
|
||||||
|
|
||||||
|
@ -277,11 +279,11 @@ static void get_usb_details(struct sp_port *port, DEVINST dev_inst_match)
|
||||||
SP_DEVINFO_DATA device_info_data;
|
SP_DEVINFO_DATA device_info_data;
|
||||||
ULONG i, size = 0;
|
ULONG i, size = 0;
|
||||||
|
|
||||||
device_info = SetupDiGetClassDevs(&GUID_CLASS_USB_HOST_CONTROLLER,NULL,NULL,
|
device_info = SetupDiGetClassDevs(&GUID_CLASS_USB_HOST_CONTROLLER, NULL, NULL,
|
||||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||||
device_info_data.cbSize = sizeof(device_info_data);
|
device_info_data.cbSize = sizeof(device_info_data);
|
||||||
|
|
||||||
for (i=0; SetupDiEnumDeviceInfo(device_info, i, &device_info_data); i++) {
|
for (i = 0; SetupDiEnumDeviceInfo(device_info, i, &device_info_data); i++) {
|
||||||
SP_DEVICE_INTERFACE_DATA device_interface_data;
|
SP_DEVICE_INTERFACE_DATA device_interface_data;
|
||||||
PSP_DEVICE_INTERFACE_DETAIL_DATA device_detail_data;
|
PSP_DEVICE_INTERFACE_DETAIL_DATA device_detail_data;
|
||||||
DEVINST dev_inst = dev_inst_match;
|
DEVINST dev_inst = dev_inst_match;
|
||||||
|
@ -333,8 +335,10 @@ static void get_usb_details(struct sp_port *port, DEVINST dev_inst_match)
|
||||||
|
|
||||||
SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
{
|
{
|
||||||
/* Description limited to 127 char,
|
/*
|
||||||
anything longer would not be user friendly anyway */
|
* Description limited to 127 char, anything longer
|
||||||
|
* would not be user friendly anyway.
|
||||||
|
*/
|
||||||
char description[128];
|
char description[128];
|
||||||
SP_DEVINFO_DATA device_info_data = { .cbSize = sizeof(device_info_data) };
|
SP_DEVINFO_DATA device_info_data = { .cbSize = sizeof(device_info_data) };
|
||||||
HDEVINFO device_info;
|
HDEVINFO device_info;
|
||||||
|
@ -345,14 +349,14 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
if (device_info == INVALID_HANDLE_VALUE)
|
if (device_info == INVALID_HANDLE_VALUE)
|
||||||
RETURN_FAIL("SetupDiGetClassDevs() failed");
|
RETURN_FAIL("SetupDiGetClassDevs() failed");
|
||||||
|
|
||||||
for (i=0; SetupDiEnumDeviceInfo(device_info, i, &device_info_data); i++) {
|
for (i = 0; SetupDiEnumDeviceInfo(device_info, i, &device_info_data); i++) {
|
||||||
HKEY device_key;
|
HKEY device_key;
|
||||||
DEVINST dev_inst;
|
DEVINST dev_inst;
|
||||||
char value[8], class[16];
|
char value[8], class[16];
|
||||||
DWORD size, type;
|
DWORD size, type;
|
||||||
CONFIGRET cr;
|
CONFIGRET cr;
|
||||||
|
|
||||||
/* check if this is the device we are looking for */
|
/* Check if this is the device we are looking for. */
|
||||||
device_key = SetupDiOpenDevRegKey(device_info, &device_info_data,
|
device_key = SetupDiOpenDevRegKey(device_info, &device_info_data,
|
||||||
DICS_FLAG_GLOBAL, 0,
|
DICS_FLAG_GLOBAL, 0,
|
||||||
DIREG_DEV, KEY_QUERY_VALUE);
|
DIREG_DEV, KEY_QUERY_VALUE);
|
||||||
|
@ -369,7 +373,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
if (strcmp(value, port->name))
|
if (strcmp(value, port->name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* check port transport type */
|
/* Check port transport type. */
|
||||||
dev_inst = device_info_data.DevInst;
|
dev_inst = device_info_data.DevInst;
|
||||||
size = sizeof(class);
|
size = sizeof(class);
|
||||||
cr = CR_FAILURE;
|
cr = CR_FAILURE;
|
||||||
|
@ -381,7 +385,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
port->transport = SP_TRANSPORT_USB;
|
port->transport = SP_TRANSPORT_USB;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get port description (friendly name) */
|
/* Get port description (friendly name). */
|
||||||
dev_inst = device_info_data.DevInst;
|
dev_inst = device_info_data.DevInst;
|
||||||
size = sizeof(description);
|
size = sizeof(description);
|
||||||
while ((cr = CM_Get_DevNode_Registry_PropertyA(dev_inst,
|
while ((cr = CM_Get_DevNode_Registry_PropertyA(dev_inst,
|
||||||
|
@ -390,21 +394,21 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
if (cr == CR_SUCCESS)
|
if (cr == CR_SUCCESS)
|
||||||
port->description = strdup(description);
|
port->description = strdup(description);
|
||||||
|
|
||||||
/* get more informations for USB connected ports */
|
/* Get more informations for USB connected ports. */
|
||||||
if (port->transport == SP_TRANSPORT_USB) {
|
if (port->transport == SP_TRANSPORT_USB) {
|
||||||
char usb_path[MAX_USB_PATH] = "", tmp[MAX_USB_PATH];
|
char usb_path[MAX_USB_PATH] = "", tmp[MAX_USB_PATH];
|
||||||
char device_id[MAX_DEVICE_ID_LEN];
|
char device_id[MAX_DEVICE_ID_LEN];
|
||||||
|
|
||||||
/* recurse over parents to build the USB device path */
|
/* Recurse over parents to build the USB device path. */
|
||||||
dev_inst = device_info_data.DevInst;
|
dev_inst = device_info_data.DevInst;
|
||||||
do {
|
do {
|
||||||
/* verify that this layer of the tree is USB related */
|
/* Verify that this layer of the tree is USB related. */
|
||||||
if (CM_Get_Device_IDA(dev_inst, device_id,
|
if (CM_Get_Device_IDA(dev_inst, device_id,
|
||||||
sizeof(device_id), 0) != CR_SUCCESS
|
sizeof(device_id), 0) != CR_SUCCESS
|
||||||
|| strncmp(device_id, "USB\\", 4))
|
|| strncmp(device_id, "USB\\", 4))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* discard one layer for composite devices */
|
/* Discard one layer for composite devices. */
|
||||||
char compat_ids[512], *p = compat_ids;
|
char compat_ids[512], *p = compat_ids;
|
||||||
size = sizeof(compat_ids);
|
size = sizeof(compat_ids);
|
||||||
if (CM_Get_DevNode_Registry_PropertyA(dev_inst,
|
if (CM_Get_DevNode_Registry_PropertyA(dev_inst,
|
||||||
|
@ -420,11 +424,11 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stop the recursion when reaching the USB root */
|
/* Stop the recursion when reaching the USB root. */
|
||||||
if (!strncmp(device_id, "USB\\ROOT", 8))
|
if (!strncmp(device_id, "USB\\ROOT", 8))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* prepend the address of current USB layer to the USB path */
|
/* Prepend the address of current USB layer to the USB path. */
|
||||||
DWORD address;
|
DWORD address;
|
||||||
size = sizeof(address);
|
size = sizeof(address);
|
||||||
if (CM_Get_DevNode_Registry_PropertyA(dev_inst, CM_DRP_ADDRESS,
|
if (CM_Get_DevNode_Registry_PropertyA(dev_inst, CM_DRP_ADDRESS,
|
||||||
|
@ -437,7 +441,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
|
|
||||||
port->usb_path = strdup(usb_path);
|
port->usb_path = strdup(usb_path);
|
||||||
|
|
||||||
/* wake up the USB device to be able to read string descriptor */
|
/* Wake up the USB device to be able to read string descriptor. */
|
||||||
char *escaped_port_name;
|
char *escaped_port_name;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
|
if (!(escaped_port_name = malloc(strlen(port->name) + 5)))
|
||||||
|
@ -449,7 +453,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
|
||||||
free(escaped_port_name);
|
free(escaped_port_name);
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
|
||||||
/* retrieve USB device details from the device descriptor */
|
/* Retrieve USB device details from the device descriptor. */
|
||||||
get_usb_details(port, device_info_data.DevInst);
|
get_usb_details(port, device_info_data.DevInst);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -485,11 +489,11 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
}
|
}
|
||||||
max_data_len = max_data_size / sizeof(TCHAR);
|
max_data_len = max_data_size / sizeof(TCHAR);
|
||||||
if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
|
if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) {
|
||||||
SET_ERROR(ret, SP_ERR_MEM, "registry value malloc failed");
|
SET_ERROR(ret, SP_ERR_MEM, "Registry value malloc failed");
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
|
if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) {
|
||||||
SET_ERROR(ret, SP_ERR_MEM, "registry data malloc failed");
|
SET_ERROR(ret, SP_ERR_MEM, "Registry data malloc failed");
|
||||||
goto out_free_value;
|
goto out_free_value;
|
||||||
}
|
}
|
||||||
DEBUG("Iterating over values");
|
DEBUG("Iterating over values");
|
||||||
|
@ -508,7 +512,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
name_len = data_len + 1;
|
name_len = data_len + 1;
|
||||||
#endif
|
#endif
|
||||||
if (!(name = malloc(name_len))) {
|
if (!(name = malloc(name_len))) {
|
||||||
SET_ERROR(ret, SP_ERR_MEM, "registry port name malloc failed");
|
SET_ERROR(ret, SP_ERR_MEM, "Registry port name malloc failed");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
|
@ -518,7 +522,7 @@ SP_PRIV enum sp_return list_ports(struct sp_port ***list)
|
||||||
#endif
|
#endif
|
||||||
DEBUG_FMT("Found port %s", name);
|
DEBUG_FMT("Found port %s", name);
|
||||||
if (!(*list = list_append(*list, name))) {
|
if (!(*list = list_append(*list, name))) {
|
||||||
SET_ERROR(ret, SP_ERR_MEM, "list append failed");
|
SET_ERROR(ret, SP_ERR_MEM, "List append failed");
|
||||||
free(name);
|
free(name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user