...
 
Commits (5)
......@@ -74,7 +74,7 @@ JAYLINK_PRIV uint16_t buffer_get_u16(const uint8_t *buffer, size_t offset)
* host byte order.
*/
#ifdef WORDS_BIGENDIAN
value = (((uint16_t)buffer[offset + 1])) | \
value = (((uint16_t)buffer[offset + 1])) |
(((uint16_t)buffer[offset + 0]) << 8);
#else
memcpy(&value, buffer + offset, sizeof(value));
......@@ -128,9 +128,9 @@ JAYLINK_PRIV uint32_t buffer_get_u32(const uint8_t *buffer, size_t offset)
* host byte order.
*/
#ifdef WORDS_BIGENDIAN
value = (((uint32_t)buffer[offset + 3])) | \
(((uint32_t)buffer[offset + 2]) << 8) | \
(((uint32_t)buffer[offset + 1]) << 16) | \
value = (((uint32_t)buffer[offset + 3])) |
(((uint32_t)buffer[offset + 2]) << 8) |
(((uint32_t)buffer[offset + 1]) << 16) |
(((uint32_t)buffer[offset + 0]) << 24);
#else
memcpy(&value, buffer + offset, sizeof(value));
......
......@@ -239,7 +239,7 @@ JAYLINK_API int jaylink_device_get_serial_number(
if (!dev || !serial_number)
return JAYLINK_ERR_ARG;
if (!dev->valid_serial_number)
if (!dev->has_serial_number)
return JAYLINK_ERR_NOT_AVAILABLE;
*serial_number = dev->serial_number;
......
......@@ -129,7 +129,7 @@ static bool parse_adv_message(struct jaylink_device *dev,
dev->has_mac_address = true;
dev->serial_number = buffer_get_u32(buffer, 48);
dev->valid_serial_number = true;
dev->has_serial_number = true;
tmp = buffer_get_u32(buffer, 52);
dev->hw_version.type = (tmp / 1000000) % 100;
......@@ -205,7 +205,7 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
dev->iface = JAYLINK_HIF_TCP;
dev->serial_number = tmp.serial_number;
dev->valid_serial_number = tmp.valid_serial_number;
dev->has_serial_number = tmp.has_serial_number;
memcpy(dev->ipv4_address, tmp.ipv4_address, sizeof(dev->ipv4_address));
......
......@@ -43,25 +43,28 @@
#define USB_VENDOR_ID 0x1366
/* USB Product IDs (PID) and their corresponding USB addresses. */
static const uint16_t pids[][2] = {
{0x0101, 0},
{0x0102, 1},
{0x0103, 2},
{0x0104, 3},
{0x0105, 0},
{0x0107, 0},
{0x0108, 0},
{0x1010, 0},
{0x1011, 0},
{0x1012, 0},
{0x1013, 0},
{0x1014, 0},
{0x1015, 0},
{0x1016, 0},
{0x1017, 0},
{0x1018, 0},
{0x1020, 0},
{0x1055, 0}
static const struct {
uint16_t pid;
enum jaylink_usb_address usb_address;
} pids[] = {
{0x0101, JAYLINK_USB_ADDRESS_0},
{0x0102, JAYLINK_USB_ADDRESS_1},
{0x0103, JAYLINK_USB_ADDRESS_2},
{0x0104, JAYLINK_USB_ADDRESS_3},
{0x0105, JAYLINK_USB_ADDRESS_0},
{0x0107, JAYLINK_USB_ADDRESS_0},
{0x0108, JAYLINK_USB_ADDRESS_0},
{0x1010, JAYLINK_USB_ADDRESS_0},
{0x1011, JAYLINK_USB_ADDRESS_0},
{0x1012, JAYLINK_USB_ADDRESS_0},
{0x1013, JAYLINK_USB_ADDRESS_0},
{0x1014, JAYLINK_USB_ADDRESS_0},
{0x1015, JAYLINK_USB_ADDRESS_0},
{0x1016, JAYLINK_USB_ADDRESS_0},
{0x1017, JAYLINK_USB_ADDRESS_0},
{0x1018, JAYLINK_USB_ADDRESS_0},
{0x1020, JAYLINK_USB_ADDRESS_0},
{0x1055, JAYLINK_USB_ADDRESS_0}
};
/** Maximum length of the USB string descriptor for the serial number. */
......@@ -134,9 +137,9 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
struct libusb_device_handle *usb_devh;
struct jaylink_device *dev;
char buf[USB_SERIAL_NUMBER_LENGTH + 1];
uint8_t usb_address;
enum jaylink_usb_address usb_address;
uint32_t serial_number;
bool valid_serial_number;
bool has_serial_number;
bool found_device;
ret = libusb_get_device_descriptor(usb_dev, &desc);
......@@ -153,9 +156,9 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
found_device = false;
for (size_t i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) {
if (pids[i][0] == desc.idProduct) {
if (pids[i].pid == desc.idProduct) {
usb_address = pids[i].usb_address;
found_device = true;
usb_address = pids[i][1];
break;
}
}
......@@ -177,7 +180,7 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
if (dev) {
log_dbg(ctx, "Device: USB address = %u.", dev->usb_address);
if (dev->valid_serial_number)
if (dev->has_serial_number)
log_dbg(ctx, "Device: Serial number = %u.",
dev->serial_number);
else
......@@ -197,7 +200,7 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
}
serial_number = 0;
valid_serial_number = true;
has_serial_number = true;
ret = libusb_get_string_descriptor_ascii(usb_devh, desc.iSerialNumber,
(unsigned char *)buf, USB_SERIAL_NUMBER_LENGTH + 1);
......@@ -207,10 +210,10 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
if (ret < 0) {
log_warn(ctx, "Failed to retrieve serial number: %s.",
libusb_error_name(ret));
valid_serial_number = false;
has_serial_number = false;
}
if (valid_serial_number) {
if (has_serial_number) {
if (!parse_serial_number(buf, &serial_number)) {
log_warn(ctx, "Failed to parse serial number.");
return NULL;
......@@ -219,7 +222,7 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
log_dbg(ctx, "Device: USB address = %u.", usb_address);
if (valid_serial_number)
if (has_serial_number)
log_dbg(ctx, "Device: Serial number = %u.", serial_number);
else
log_dbg(ctx, "Device: Serial number = N/A.");
......@@ -237,7 +240,7 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
dev->usb_dev = libusb_ref_device(usb_dev);
dev->usb_address = usb_address;
dev->serial_number = serial_number;
dev->valid_serial_number = valid_serial_number;
dev->has_serial_number = has_serial_number;
return dev;
}
......
......@@ -95,13 +95,13 @@ struct jaylink_device {
* real serial number of the device.
*/
uint32_t serial_number;
/** Indicates whether the serial number is valid. */
bool valid_serial_number;
/** Indicates whether the serial number is available. */
bool has_serial_number;
#ifdef HAVE_LIBUSB
/** libusb device instance. */
struct libusb_device *usb_dev;
/** USB address of the device. */
uint8_t usb_address;
enum jaylink_usb_address usb_address;
#endif
/**
* IPv4 address.
......@@ -255,6 +255,8 @@ JAYLINK_PRIV void log_dbgio(const struct jaylink_context *ctx,
/*--- socket.c --------------------------------------------------------------*/
JAYLINK_PRIV int socket_connect(int sock, const struct sockaddr *address,
size_t address_length, size_t timeout);
JAYLINK_PRIV bool socket_close(int sock);
JAYLINK_PRIV bool socket_bind(int sock, const struct sockaddr *address,
size_t length);
......@@ -267,8 +269,11 @@ JAYLINK_PRIV bool socket_sendto(int sock, const void *buffer, size_t *length,
size_t address_length);
JAYLINK_PRIV bool socket_recvfrom(int sock, void *buffer, size_t *length,
int flags, struct sockaddr *address, size_t *address_length);
JAYLINK_PRIV bool socket_get_option(int sock, int level, int option,
void *value, size_t *length);
JAYLINK_PRIV bool socket_set_option(int sock, int level, int option,
const void *value, size_t length);
JAYLINK_PRIV bool socket_set_blocking(int sock, bool blocking);
/*--- transport.c -----------------------------------------------------------*/
......
......@@ -17,12 +17,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#include "libjaylink.h"
......@@ -34,6 +36,76 @@
* Socket abstraction layer.
*/
/**
* Initiate a connection on a socket.
*
* @param[in] sock Socket descriptor.
* @param[in] address Address to establish the connection.
* @param[in] address_length Length of the structure pointed to by @p address
* in bytes.
* @param[in] timeout Connection timeout in milliseconds. Use 0 to wait
* indefinitely.
*
* @retval JAYLINK_OK Success.
* @retval JAYLINK_ERR_ARG Invalid arguments.
* @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
* @retval JAYLINK_ERR Other error conditions.
*/
JAYLINK_PRIV int socket_connect(int sock, const struct sockaddr *address,
size_t address_length, size_t timeout)
{
int ret;
fd_set fds;
struct timeval tv;
int socket_error;
size_t option_length;
if (!address)
return JAYLINK_ERR_ARG;
if (!socket_set_blocking(sock, false))
return JAYLINK_ERR;
#ifdef _WIN32
ret = connect(sock, address, address_length);
if (ret != 0 && WSAGetLastError() != WSAEWOULDBLOCK)
return JAYLINK_ERR;
#else
errno = 0;
ret = connect(sock, address, address_length);
if (ret != 0 && errno != EINPROGRESS)
return JAYLINK_ERR;
#endif
if (!ret)
return JAYLINK_OK;
FD_ZERO(&fds);
FD_SET(sock, &fds);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
ret = select(sock + 1, NULL, &fds, NULL, &tv);
if (!socket_set_blocking(sock, true))
return JAYLINK_ERR;
if (!ret)
return JAYLINK_ERR_TIMEOUT;
option_length = sizeof(socket_error);
if (!socket_get_option(sock, SOL_SOCKET, SO_ERROR, &socket_error,
&option_length))
return JAYLINK_ERR;
if (!socket_error)
return JAYLINK_OK;
return JAYLINK_ERR;
}
/**
* Close a socket.
*
......@@ -236,6 +308,26 @@ JAYLINK_PRIV bool socket_recvfrom(int sock, void *buffer, size_t *length,
return true;
}
/**
* Get an option of a socket.
*
* @param[in] sock Socket descriptor.
* @param[in] level Level at which the option is defined.
* @param[in] option Option to get the value for.
* @param[in] value Buffer to store the value.
* @param[in] length Length of the value buffer in bytes.
*
* @return Whether the option was set successfully.
*/
JAYLINK_PRIV bool socket_get_option(int sock, int level, int option,
void *value, size_t *length)
{
if (!getsockopt(sock, level, option, value, (socklen_t *)length))
return true;
return false;
}
/**
* Set an option on a socket.
*
......@@ -255,3 +347,44 @@ JAYLINK_PRIV bool socket_set_option(int sock, int level, int option,
return false;
}
/**
* Set the blocking mode of a socket.
*
* @param[in] sock Socket descriptor.
* @param[in] blocking Whether the socket should be in blocking mode or not.
*
* @return Whether the blocking mode was set successfully.
*/
JAYLINK_PRIV bool socket_set_blocking(int sock, bool blocking)
{
int ret;
#ifdef _WIN32
u_long mode;
mode = !blocking;
ret = ioctlsocket(sock, FIONBIO, &mode);
if (ret != NO_ERROR)
return false;
#else
int flags;
flags = fcntl(sock, F_GETFL, 0);
if (flags < 0)
return false;
if (blocking)
flags &= ~O_NONBLOCK;
else
flags |= O_NONBLOCK;
ret = fcntl(sock, F_SETFL, flags);
if (ret != 0)
return false;
#endif
return true;
}
......@@ -55,6 +55,8 @@
/** Buffer size in bytes. */
#define BUFFER_SIZE 2048
/** Timeout to establish a connection in milliseconds. */
#define CONNECT_TIMEOUT 5000
/** Timeout of a receive operation in milliseconds. */
#define RECV_TIMEOUT 5000
/** Timeout of a send operation in milliseconds. */
......@@ -267,8 +269,16 @@ JAYLINK_PRIV int transport_tcp_open(struct jaylink_device_handle *devh)
if (sock < 0)
continue;
if (!connect(sock, info->ai_addr, info->ai_addrlen))
ret = socket_connect(sock, info->ai_addr, info->ai_addrlen,
CONNECT_TIMEOUT);
if (ret == JAYLINK_ERR_TIMEOUT) {
freeaddrinfo(info);
cleanup_handle(devh);
return JAYLINK_ERR_TIMEOUT;
} else if (ret == JAYLINK_OK) {
break;
}
socket_close(sock);
sock = -1;
......