Re-write the device discovery using the iterator api
Replacing the callback based interface with an iterator based interface, results in a more extensible abstraction with a common interface for each of the built-in I/O implementations (serial, usbhid, irda and bluetooth).
This commit is contained in:
parent
296fad2d9d
commit
ca91500ed5
376
src/bluetooth.c
376
src/bluetooth.c
@ -50,6 +50,7 @@
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DC_ADDRESS_FORMAT "%012I64X"
|
||||
@ -64,7 +65,33 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_bluetooth_vtable)
|
||||
|
||||
struct dc_bluetooth_device_t {
|
||||
dc_bluetooth_address_t address;
|
||||
char name[248];
|
||||
};
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
static dc_status_t dc_bluetooth_iterator_next (dc_iterator_t *iterator, void *item);
|
||||
static dc_status_t dc_bluetooth_iterator_free (dc_iterator_t *iterator);
|
||||
|
||||
typedef struct dc_bluetooth_iterator_t {
|
||||
dc_iterator_t base;
|
||||
#ifdef _WIN32
|
||||
HANDLE hLookup;
|
||||
#else
|
||||
int fd;
|
||||
inquiry_info *devices;
|
||||
size_t count;
|
||||
size_t current;
|
||||
#endif
|
||||
} dc_bluetooth_iterator_t;
|
||||
|
||||
static const dc_iterator_vtable_t dc_bluetooth_iterator_vtable = {
|
||||
sizeof(dc_bluetooth_iterator_t),
|
||||
dc_bluetooth_iterator_next,
|
||||
dc_bluetooth_iterator_free,
|
||||
};
|
||||
|
||||
static const dc_iostream_vtable_t dc_bluetooth_vtable = {
|
||||
sizeof(dc_socket_t),
|
||||
dc_socket_set_timeout, /* set_timeout */
|
||||
@ -194,6 +221,220 @@ error:
|
||||
#endif
|
||||
#endif
|
||||
|
||||
dc_bluetooth_address_t
|
||||
dc_bluetooth_device_get_address (dc_bluetooth_device_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return 0;
|
||||
|
||||
return device->address;
|
||||
}
|
||||
|
||||
const char *
|
||||
dc_bluetooth_device_get_name (dc_bluetooth_device_t *device)
|
||||
{
|
||||
if (device == NULL || device->name[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
return device->name;
|
||||
}
|
||||
|
||||
void
|
||||
dc_bluetooth_device_free (dc_bluetooth_device_t *device)
|
||||
{
|
||||
free (device);
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_bluetooth_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_t *descriptor)
|
||||
{
|
||||
#ifdef BLUETOOTH
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_bluetooth_iterator_t *iterator = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
iterator = (dc_bluetooth_iterator_t *) dc_iterator_allocate (context, &dc_bluetooth_iterator_vtable);
|
||||
if (iterator == NULL) {
|
||||
SYSERROR (context, S_ENOMEM);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
WSAQUERYSET wsaq;
|
||||
memset(&wsaq, 0, sizeof (wsaq));
|
||||
wsaq.dwSize = sizeof (wsaq);
|
||||
wsaq.dwNameSpace = NS_BTH;
|
||||
wsaq.lpcsaBuffer = NULL;
|
||||
|
||||
HANDLE hLookup = NULL;
|
||||
if (WSALookupServiceBegin(&wsaq, LUP_CONTAINERS | LUP_FLUSHCACHE, &hLookup) != 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
if (errcode == WSASERVICE_NOT_FOUND) {
|
||||
// No remote bluetooth devices found.
|
||||
hLookup = NULL;
|
||||
} else {
|
||||
SYSERROR (context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_free;
|
||||
}
|
||||
}
|
||||
|
||||
iterator->hLookup = hLookup;
|
||||
#else
|
||||
// Get the resource number for the first available bluetooth adapter.
|
||||
int dev = hci_get_route (NULL);
|
||||
if (dev < 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
SYSERROR (context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Open a socket to the bluetooth adapter.
|
||||
int fd = hci_open_dev (dev);
|
||||
if (fd < 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
SYSERROR (context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Perform the bluetooth device discovery. The inquiry lasts for at
|
||||
// most MAX_PERIODS * 1.28 seconds, and at most MAX_DEVICES devices
|
||||
// will be returned.
|
||||
inquiry_info *devices = NULL;
|
||||
int ndevices = hci_inquiry (dev, MAX_PERIODS, MAX_DEVICES, NULL, &devices, IREQ_CACHE_FLUSH);
|
||||
if (ndevices < 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
SYSERROR (context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
iterator->fd = fd;
|
||||
iterator->devices = devices;
|
||||
iterator->count = ndevices;
|
||||
iterator->current = 0;
|
||||
#endif
|
||||
|
||||
*out = (dc_iterator_t *) iterator;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
#ifndef _WIN32
|
||||
error_close:
|
||||
hci_close_dev(fd);
|
||||
#endif
|
||||
error_free:
|
||||
dc_iterator_deallocate ((dc_iterator_t *) iterator);
|
||||
return status;
|
||||
#else
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
static dc_status_t
|
||||
dc_bluetooth_iterator_next (dc_iterator_t *abstract, void *out)
|
||||
{
|
||||
dc_bluetooth_iterator_t *iterator = (dc_bluetooth_iterator_t *) abstract;
|
||||
dc_bluetooth_device_t *device = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (iterator->hLookup == NULL) {
|
||||
return DC_STATUS_DONE;
|
||||
}
|
||||
|
||||
unsigned char buf[4096];
|
||||
LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
|
||||
memset(pwsaResults, 0, sizeof(WSAQUERYSET));
|
||||
pwsaResults->dwSize = sizeof(WSAQUERYSET);
|
||||
pwsaResults->dwNameSpace = NS_BTH;
|
||||
pwsaResults->lpBlob = NULL;
|
||||
|
||||
while (1) {
|
||||
DWORD dwSize = sizeof(buf);
|
||||
if (WSALookupServiceNext (iterator->hLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR, &dwSize, pwsaResults) != 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
if (errcode == WSA_E_NO_MORE || errcode == WSAENOMORE) {
|
||||
break; // No more results.
|
||||
}
|
||||
SYSERROR (abstract->context, errcode);
|
||||
return dc_socket_syserror(errcode);
|
||||
}
|
||||
|
||||
if (pwsaResults->dwNumberOfCsAddrs == 0 ||
|
||||
pwsaResults->lpcsaBuffer == NULL ||
|
||||
pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr == NULL) {
|
||||
ERROR (abstract->context, "Invalid results returned");
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
SOCKADDR_BTH *sa = (SOCKADDR_BTH *) pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr;
|
||||
dc_bluetooth_address_t address = sa->btAddr;
|
||||
const char *name = (char *) pwsaResults->lpszServiceInstanceName;
|
||||
#else
|
||||
while (iterator->current < iterator->count) {
|
||||
inquiry_info *dev = &iterator->devices[iterator->current++];
|
||||
|
||||
dc_bluetooth_address_t address = dc_address_get (&dev->bdaddr);
|
||||
|
||||
// Get the user friendly name.
|
||||
char buf[HCI_MAX_NAME_LENGTH], *name = buf;
|
||||
int rc = hci_read_remote_name (iterator->fd, &dev->bdaddr, sizeof(buf), buf, 0);
|
||||
if (rc < 0) {
|
||||
name = NULL;
|
||||
}
|
||||
|
||||
// Null terminate the string.
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
#endif
|
||||
|
||||
INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s",
|
||||
address, name ? name : "");
|
||||
|
||||
device = (dc_bluetooth_device_t *) malloc (sizeof(dc_bluetooth_device_t));
|
||||
if (device == NULL) {
|
||||
SYSERROR (abstract->context, S_ENOMEM);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
device->address = address;
|
||||
if (name) {
|
||||
strncpy(device->name, name, sizeof(device->name) - 1);
|
||||
device->name[sizeof(device->name) - 1] = '\0';
|
||||
} else {
|
||||
memset(device->name, 0, sizeof(device->name));
|
||||
}
|
||||
|
||||
*(dc_bluetooth_device_t **) out = device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return DC_STATUS_DONE;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_bluetooth_iterator_free (dc_iterator_t *abstract)
|
||||
{
|
||||
dc_bluetooth_iterator_t *iterator = (dc_bluetooth_iterator_t *) abstract;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (iterator->hLookup) {
|
||||
WSALookupServiceEnd (iterator->hLookup);
|
||||
}
|
||||
#else
|
||||
bt_free(iterator->devices);
|
||||
hci_close_dev(iterator->fd);
|
||||
#endif
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
dc_status_t
|
||||
dc_bluetooth_open (dc_iostream_t **out, dc_context_t *context)
|
||||
{
|
||||
@ -233,141 +474,6 @@ error_free:
|
||||
#endif
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_bluetooth_discover (dc_iostream_t *abstract, dc_bluetooth_callback_t callback, void *userdata)
|
||||
{
|
||||
#ifdef BLUETOOTH
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSAQUERYSET wsaq;
|
||||
memset(&wsaq, 0, sizeof (wsaq));
|
||||
wsaq.dwSize = sizeof (wsaq);
|
||||
wsaq.dwNameSpace = NS_BTH;
|
||||
wsaq.lpcsaBuffer = NULL;
|
||||
|
||||
HANDLE hLookup;
|
||||
if (WSALookupServiceBegin(&wsaq, LUP_CONTAINERS | LUP_FLUSHCACHE, &hLookup) != 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
if (errcode == WSASERVICE_NOT_FOUND) {
|
||||
// No remote bluetooth devices found.
|
||||
status = DC_STATUS_SUCCESS;
|
||||
} else {
|
||||
SYSERROR (abstract->context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
}
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
unsigned char buf[4096];
|
||||
LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
|
||||
memset(pwsaResults, 0, sizeof(WSAQUERYSET));
|
||||
pwsaResults->dwSize = sizeof(WSAQUERYSET);
|
||||
pwsaResults->dwNameSpace = NS_BTH;
|
||||
pwsaResults->lpBlob = NULL;
|
||||
|
||||
while (1) {
|
||||
DWORD dwSize = sizeof(buf);
|
||||
if (WSALookupServiceNext (hLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR, &dwSize, pwsaResults) != 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
if (errcode == WSA_E_NO_MORE || errcode == WSAENOMORE) {
|
||||
break; // No more results.
|
||||
}
|
||||
SYSERROR (abstract->context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
if (pwsaResults->dwNumberOfCsAddrs == 0 ||
|
||||
pwsaResults->lpcsaBuffer == NULL ||
|
||||
pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr == NULL) {
|
||||
ERROR (abstract->context, "Invalid results returned");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
SOCKADDR_BTH *sa = (SOCKADDR_BTH *) pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr;
|
||||
dc_bluetooth_address_t address = sa->btAddr;
|
||||
const char *name = (char *) pwsaResults->lpszServiceInstanceName;
|
||||
|
||||
INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s", address, name);
|
||||
|
||||
if (callback) callback (address, name, userdata);
|
||||
|
||||
}
|
||||
|
||||
error_close:
|
||||
WSALookupServiceEnd (hLookup);
|
||||
#else
|
||||
// Get the resource number for the first available bluetooth adapter.
|
||||
int dev = hci_get_route (NULL);
|
||||
if (dev < 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
SYSERROR (abstract->context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// Open a socket to the bluetooth adapter.
|
||||
int fd = hci_open_dev (dev);
|
||||
if (fd < 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
SYSERROR (abstract->context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// Allocate a buffer to store the results of the discovery.
|
||||
inquiry_info *devices = (inquiry_info *) malloc (MAX_DEVICES * sizeof(inquiry_info));
|
||||
if (devices == NULL) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
SYSERROR (abstract->context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Perform the bluetooth device discovery. The inquiry lasts for at
|
||||
// most MAX_PERIODS * 1.28 seconds, and at most MAX_DEVICES devices
|
||||
// will be returned.
|
||||
int ndevices = hci_inquiry (dev, MAX_PERIODS, MAX_DEVICES, NULL, &devices, IREQ_CACHE_FLUSH);
|
||||
if (ndevices < 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
SYSERROR (abstract->context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < ndevices; ++i) {
|
||||
dc_bluetooth_address_t address = dc_address_get (&devices[i].bdaddr);
|
||||
|
||||
// Get the user friendly name.
|
||||
char buf[HCI_MAX_NAME_LENGTH], *name = buf;
|
||||
int rc = hci_read_remote_name (fd, &devices[i].bdaddr, sizeof(buf), buf, 0);
|
||||
if (rc < 0) {
|
||||
name = NULL;
|
||||
}
|
||||
|
||||
INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s", address, name);
|
||||
|
||||
if (callback) callback (address, name, userdata);
|
||||
}
|
||||
|
||||
error_free:
|
||||
free(devices);
|
||||
error_close:
|
||||
hci_close_dev(fd);
|
||||
#endif
|
||||
|
||||
error_exit:
|
||||
return status;
|
||||
#else
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_bluetooth_connect (dc_iostream_t *abstract, dc_bluetooth_address_t address, unsigned int port)
|
||||
{
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
#include <libdivecomputer/common.h>
|
||||
#include <libdivecomputer/context.h>
|
||||
#include <libdivecomputer/iostream.h>
|
||||
#include <libdivecomputer/iterator.h>
|
||||
#include <libdivecomputer/descriptor.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -40,13 +42,45 @@ typedef unsigned long long dc_bluetooth_address_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Bluetooth enumeration callback.
|
||||
*
|
||||
* @param[in] address The bluetooth device address.
|
||||
* @param[in] name The bluetooth device name.
|
||||
* @param[in] userdata The user data pointer.
|
||||
* Opaque object representing a bluetooth device.
|
||||
*/
|
||||
typedef void (*dc_bluetooth_callback_t) (dc_bluetooth_address_t address, const char *name, void *userdata);
|
||||
typedef struct dc_bluetooth_device_t dc_bluetooth_device_t;
|
||||
|
||||
/**
|
||||
* Get the address of the bluetooth device.
|
||||
*
|
||||
* @param[in] device A valid bluetooth device.
|
||||
*/
|
||||
dc_bluetooth_address_t
|
||||
dc_bluetooth_device_get_address (dc_bluetooth_device_t *device);
|
||||
|
||||
/**
|
||||
* Get the name of the bluetooth device.
|
||||
*
|
||||
* @param[in] device A valid bluetooth device.
|
||||
*/
|
||||
const char *
|
||||
dc_bluetooth_device_get_name (dc_bluetooth_device_t *device);
|
||||
|
||||
/**
|
||||
* Destroy the bluetooth device and free all resources.
|
||||
*
|
||||
* @param[in] device A valid bluetooth device.
|
||||
*/
|
||||
void
|
||||
dc_bluetooth_device_free (dc_bluetooth_device_t *device);
|
||||
|
||||
/**
|
||||
* Create an iterator to enumerate the bluetooth devices.
|
||||
*
|
||||
* @param[out] iterator A location to store the iterator.
|
||||
* @param[in] context A valid context object.
|
||||
* @param[in] descriptor A valid device descriptor or NULL.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_bluetooth_iterator_new (dc_iterator_t **iterator, dc_context_t *context, dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Open an bluetooth connection.
|
||||
@ -59,18 +93,6 @@ typedef void (*dc_bluetooth_callback_t) (dc_bluetooth_address_t address, const c
|
||||
dc_status_t
|
||||
dc_bluetooth_open (dc_iostream_t **iostream, dc_context_t *context);
|
||||
|
||||
/**
|
||||
* Enumerate the bluetooth devices.
|
||||
*
|
||||
* @param[in] iostream A valid bluetooth connection.
|
||||
* @param[in] callback The callback function to call.
|
||||
* @param[in] userdata User data to pass to the callback function.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_bluetooth_discover (dc_iostream_t *iostream, dc_bluetooth_callback_t callback, void *userdata);
|
||||
|
||||
/**
|
||||
* Connect to an bluetooth device.
|
||||
*
|
||||
|
||||
303
src/irda.c
303
src/irda.c
@ -47,12 +47,46 @@
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
#include "array.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_irda_vtable)
|
||||
|
||||
#define DISCOVER_MAX_DEVICES 16 // Maximum number of devices.
|
||||
#define DISCOVER_MAX_RETRIES 4 // Maximum number of retries.
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DISCOVER_BUFSIZE sizeof (DEVICELIST) + \
|
||||
sizeof (IRDA_DEVICE_INFO) * (DISCOVER_MAX_DEVICES - 1)
|
||||
#else
|
||||
#define DISCOVER_BUFSIZE sizeof (struct irda_device_list) + \
|
||||
sizeof (struct irda_device_info) * (DISCOVER_MAX_DEVICES - 1)
|
||||
#endif
|
||||
|
||||
struct dc_irda_device_t {
|
||||
unsigned int address;
|
||||
unsigned int charset;
|
||||
unsigned int hints;
|
||||
char name[22];
|
||||
};
|
||||
|
||||
#ifdef IRDA
|
||||
static dc_status_t dc_irda_iterator_next (dc_iterator_t *iterator, void *item);
|
||||
|
||||
typedef struct dc_irda_iterator_t {
|
||||
dc_iterator_t base;
|
||||
dc_irda_device_t items[DISCOVER_MAX_DEVICES];
|
||||
size_t count;
|
||||
size_t current;
|
||||
} dc_irda_iterator_t;
|
||||
|
||||
static const dc_iterator_vtable_t dc_irda_iterator_vtable = {
|
||||
sizeof(dc_irda_iterator_t),
|
||||
dc_irda_iterator_next,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const dc_iostream_vtable_t dc_irda_vtable = {
|
||||
sizeof(dc_socket_t),
|
||||
dc_socket_set_timeout, /* set_timeout */
|
||||
@ -73,6 +107,180 @@ static const dc_iostream_vtable_t dc_irda_vtable = {
|
||||
};
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
dc_irda_device_get_address (dc_irda_device_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return 0;
|
||||
|
||||
return device->address;
|
||||
}
|
||||
|
||||
const char *
|
||||
dc_irda_device_get_name (dc_irda_device_t *device)
|
||||
{
|
||||
if (device == NULL || device->name[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
return device->name;
|
||||
}
|
||||
|
||||
void
|
||||
dc_irda_device_free (dc_irda_device_t *device)
|
||||
{
|
||||
free (device);
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_irda_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_t *descriptor)
|
||||
{
|
||||
#ifdef IRDA
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_irda_iterator_t *iterator = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
iterator = (dc_irda_iterator_t *) dc_iterator_allocate (context, &dc_irda_iterator_vtable);
|
||||
if (iterator == NULL) {
|
||||
SYSERROR (context, S_ENOMEM);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Initialize the socket library.
|
||||
status = dc_socket_init (context);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Open the socket.
|
||||
int fd = socket (AF_IRDA, SOCK_STREAM, 0);
|
||||
if (fd == S_INVALID) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
SYSERROR (context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_socket_exit;
|
||||
}
|
||||
|
||||
unsigned char data[DISCOVER_BUFSIZE] = {0};
|
||||
#ifdef _WIN32
|
||||
DEVICELIST *list = (DEVICELIST *) data;
|
||||
#else
|
||||
struct irda_device_list *list = (struct irda_device_list *) data;
|
||||
#endif
|
||||
s_socklen_t size = sizeof (data);
|
||||
|
||||
int rc = 0;
|
||||
unsigned int nretries = 0;
|
||||
while ((rc = getsockopt (fd, SOL_IRLMP, IRLMP_ENUMDEVICES, (char *) data, &size)) != 0 ||
|
||||
#ifdef _WIN32
|
||||
list->numDevice == 0)
|
||||
#else
|
||||
list->len == 0)
|
||||
#endif
|
||||
{
|
||||
// Automatically retry the discovery when no devices were found.
|
||||
// On Linux, getsockopt fails with EAGAIN when no devices are
|
||||
// discovered, while on Windows it succeeds and sets the number
|
||||
// of devices to zero. Both situations are handled the same here.
|
||||
if (rc != 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
if (errcode != S_EAGAIN) {
|
||||
SYSERROR (context, errcode);
|
||||
status = dc_socket_syserror(errcode);
|
||||
goto error_socket_close;
|
||||
}
|
||||
}
|
||||
|
||||
// Abort if the maximum number of retries is reached.
|
||||
if (nretries++ >= DISCOVER_MAX_RETRIES) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Restore the size parameter in case it was
|
||||
// modified by the previous getsockopt call.
|
||||
size = sizeof (data);
|
||||
|
||||
#ifdef _WIN32
|
||||
Sleep (1000);
|
||||
#else
|
||||
sleep (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
S_CLOSE (fd);
|
||||
dc_socket_exit (context);
|
||||
|
||||
unsigned int count = 0;
|
||||
#ifdef _WIN32
|
||||
for (size_t i = 0; i < list->numDevice; ++i) {
|
||||
const char *name = list->Device[i].irdaDeviceName;
|
||||
unsigned int address = array_uint32_le (list->Device[i].irdaDeviceID);
|
||||
unsigned int charset = list->Device[i].irdaCharSet;
|
||||
unsigned int hints = (list->Device[i].irdaDeviceHints1 << 8) +
|
||||
list->Device[i].irdaDeviceHints2;
|
||||
#else
|
||||
for (size_t i = 0; i < list->len; ++i) {
|
||||
const char *name = list->dev[i].info;
|
||||
unsigned int address = list->dev[i].daddr;
|
||||
unsigned int charset = list->dev[i].charset;
|
||||
unsigned int hints = array_uint16_be (list->dev[i].hints);
|
||||
#endif
|
||||
|
||||
INFO (context, "Discover: address=%08x, name=%s, charset=%02x, hints=%04x",
|
||||
address, name, charset, hints);
|
||||
|
||||
strncpy(iterator->items[count].name, name, sizeof(iterator->items[count].name) - 1);
|
||||
iterator->items[count].name[sizeof(iterator->items[count].name) - 1] = '\0';
|
||||
iterator->items[count].address = address;
|
||||
iterator->items[count].charset = charset;
|
||||
iterator->items[count].hints = hints;
|
||||
count++;
|
||||
}
|
||||
|
||||
iterator->current = 0;
|
||||
iterator->count = count;
|
||||
|
||||
*out = (dc_iterator_t *) iterator;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_socket_close:
|
||||
S_CLOSE (fd);
|
||||
error_socket_exit:
|
||||
dc_socket_exit (context);
|
||||
error_free:
|
||||
dc_iterator_deallocate ((dc_iterator_t *) iterator);
|
||||
return status;
|
||||
#else
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef IRDA
|
||||
static dc_status_t
|
||||
dc_irda_iterator_next (dc_iterator_t *abstract, void *out)
|
||||
{
|
||||
dc_irda_iterator_t *iterator = (dc_irda_iterator_t *) abstract;
|
||||
dc_irda_device_t *device = NULL;
|
||||
|
||||
if (iterator->current >= iterator->count)
|
||||
return DC_STATUS_DONE;
|
||||
|
||||
device = (dc_irda_device_t *) malloc (sizeof(dc_irda_device_t));
|
||||
if (device == NULL) {
|
||||
SYSERROR (abstract->context, S_ENOMEM);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
*device = iterator->items[iterator->current++];
|
||||
|
||||
*(dc_irda_device_t **) out = device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
dc_status_t
|
||||
dc_irda_open (dc_iostream_t **out, dc_context_t *context)
|
||||
{
|
||||
@ -108,101 +316,6 @@ error_free:
|
||||
#endif
|
||||
}
|
||||
|
||||
#define DISCOVER_MAX_DEVICES 16 // Maximum number of devices.
|
||||
#define DISCOVER_MAX_RETRIES 4 // Maximum number of retries.
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DISCOVER_BUFSIZE sizeof (DEVICELIST) + \
|
||||
sizeof (IRDA_DEVICE_INFO) * (DISCOVER_MAX_DEVICES - 1)
|
||||
#else
|
||||
#define DISCOVER_BUFSIZE sizeof (struct irda_device_list) + \
|
||||
sizeof (struct irda_device_info) * (DISCOVER_MAX_DEVICES - 1)
|
||||
#endif
|
||||
|
||||
dc_status_t
|
||||
dc_irda_discover (dc_iostream_t *abstract, dc_irda_callback_t callback, void *userdata)
|
||||
{
|
||||
#ifdef IRDA
|
||||
dc_socket_t *device = (dc_socket_t *) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
unsigned char data[DISCOVER_BUFSIZE] = {0};
|
||||
#ifdef _WIN32
|
||||
DEVICELIST *list = (DEVICELIST *) data;
|
||||
int size = sizeof (data);
|
||||
#else
|
||||
struct irda_device_list *list = (struct irda_device_list *) data;
|
||||
socklen_t size = sizeof (data);
|
||||
#endif
|
||||
|
||||
int rc = 0;
|
||||
unsigned int nretries = 0;
|
||||
while ((rc = getsockopt (device->fd, SOL_IRLMP, IRLMP_ENUMDEVICES, (char*) data, &size)) != 0 ||
|
||||
#ifdef _WIN32
|
||||
list->numDevice == 0)
|
||||
#else
|
||||
list->len == 0)
|
||||
#endif
|
||||
{
|
||||
// Automatically retry the discovery when no devices were found.
|
||||
// On Linux, getsockopt fails with EAGAIN when no devices are
|
||||
// discovered, while on Windows it succeeds and sets the number
|
||||
// of devices to zero. Both situations are handled the same here.
|
||||
if (rc != 0) {
|
||||
s_errcode_t errcode = S_ERRNO;
|
||||
if (errcode != S_EAGAIN) {
|
||||
SYSERROR (abstract->context, errcode);
|
||||
return dc_socket_syserror(errcode);
|
||||
}
|
||||
}
|
||||
|
||||
// Abort if the maximum number of retries is reached.
|
||||
if (nretries++ >= DISCOVER_MAX_RETRIES)
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
// Restore the size parameter in case it was
|
||||
// modified by the previous getsockopt call.
|
||||
size = sizeof (data);
|
||||
|
||||
#ifdef _WIN32
|
||||
Sleep (1000);
|
||||
#else
|
||||
sleep (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
#ifdef _WIN32
|
||||
for (unsigned int i = 0; i < list->numDevice; ++i) {
|
||||
const char *name = list->Device[i].irdaDeviceName;
|
||||
unsigned int address = array_uint32_le (list->Device[i].irdaDeviceID);
|
||||
unsigned int charset = list->Device[i].irdaCharSet;
|
||||
unsigned int hints = (list->Device[i].irdaDeviceHints1 << 8) +
|
||||
list->Device[i].irdaDeviceHints2;
|
||||
#else
|
||||
for (unsigned int i = 0; i < list->len; ++i) {
|
||||
const char *name = list->dev[i].info;
|
||||
unsigned int address = list->dev[i].daddr;
|
||||
unsigned int charset = list->dev[i].charset;
|
||||
unsigned int hints = array_uint16_be (list->dev[i].hints);
|
||||
#endif
|
||||
|
||||
INFO (abstract->context,
|
||||
"Discover: address=%08x, name=%s, charset=%02x, hints=%04x",
|
||||
address, name, charset, hints);
|
||||
|
||||
callback (address, name, charset, hints, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
#else
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_irda_connect_name (dc_iostream_t *abstract, unsigned int address, const char *name)
|
||||
{
|
||||
|
||||
60
src/irda.h
60
src/irda.h
@ -25,21 +25,53 @@
|
||||
#include <libdivecomputer/common.h>
|
||||
#include <libdivecomputer/context.h>
|
||||
#include <libdivecomputer/iostream.h>
|
||||
#include <libdivecomputer/iterator.h>
|
||||
#include <libdivecomputer/descriptor.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* IrDA enumeration callback.
|
||||
*
|
||||
* @param[in] address The IrDA device address.
|
||||
* @param[in] name The IrDA device name.
|
||||
* @param[in] charset The IrDA device character set.
|
||||
* @param[in] hints The IrDA device hints.
|
||||
* @param[in] userdata The user data pointer.
|
||||
* Opaque object representing an IrDA device.
|
||||
*/
|
||||
typedef void (*dc_irda_callback_t) (unsigned int address, const char *name, unsigned int charset, unsigned int hints, void *userdata);
|
||||
typedef struct dc_irda_device_t dc_irda_device_t;
|
||||
|
||||
/**
|
||||
* Get the address of the IrDA device.
|
||||
*
|
||||
* @param[in] device A valid IrDA device.
|
||||
*/
|
||||
unsigned int
|
||||
dc_irda_device_get_address (dc_irda_device_t *device);
|
||||
|
||||
/**
|
||||
* Get the name of the IrDA device.
|
||||
*
|
||||
* @param[in] device A valid IrDA device.
|
||||
*/
|
||||
const char *
|
||||
dc_irda_device_get_name (dc_irda_device_t *device);
|
||||
|
||||
/**
|
||||
* Destroy the IrDA device and free all resources.
|
||||
*
|
||||
* @param[in] device A valid IrDA device.
|
||||
*/
|
||||
void
|
||||
dc_irda_device_free (dc_irda_device_t *device);
|
||||
|
||||
/**
|
||||
* Create an iterator to enumerate the IrDA devices.
|
||||
*
|
||||
* @param[out] iterator A location to store the iterator.
|
||||
* @param[in] context A valid context object.
|
||||
* @param[in] descriptor A valid device descriptor or NULL.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_iterator_new (dc_iterator_t **iterator, dc_context_t *context, dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Open an IrDA connection.
|
||||
@ -52,18 +84,6 @@ typedef void (*dc_irda_callback_t) (unsigned int address, const char *name, unsi
|
||||
dc_status_t
|
||||
dc_irda_open (dc_iostream_t **iostream, dc_context_t *context);
|
||||
|
||||
/**
|
||||
* Enumerate the IrDA devices.
|
||||
*
|
||||
* @param[in] iostream A valid IrDA connection.
|
||||
* @param[in] callback The callback function to call.
|
||||
* @param[in] userdata User data to pass to the callback function.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_irda_discover (dc_iostream_t *iostream, dc_irda_callback_t callback, void *userdata);
|
||||
|
||||
/**
|
||||
* Connect to an IrDA device.
|
||||
*
|
||||
|
||||
34
src/serial.h
34
src/serial.h
@ -25,29 +25,45 @@
|
||||
#include <libdivecomputer/common.h>
|
||||
#include <libdivecomputer/context.h>
|
||||
#include <libdivecomputer/iostream.h>
|
||||
#include <libdivecomputer/iterator.h>
|
||||
#include <libdivecomputer/descriptor.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Serial enumeration callback.
|
||||
*
|
||||
* @param[in] name The name of the device node.
|
||||
* @param[in] userdata The user data pointer.
|
||||
* Opaque object representing a serial device.
|
||||
*/
|
||||
typedef void (*dc_serial_callback_t) (const char *name, void *userdata);
|
||||
typedef struct dc_serial_device_t dc_serial_device_t;
|
||||
|
||||
/**
|
||||
* Enumerate the serial ports.
|
||||
* Get the device node of the serial device.
|
||||
*
|
||||
* @param[in] callback The callback function to call.
|
||||
* @param[in] userdata User data to pass to the callback function.
|
||||
* @param[in] device A valid serial device.
|
||||
*/
|
||||
const char *
|
||||
dc_serial_device_get_name (dc_serial_device_t *device);
|
||||
|
||||
/**
|
||||
* Destroy the serial device and free all resources.
|
||||
*
|
||||
* @param[in] device A valid serial device.
|
||||
*/
|
||||
void
|
||||
dc_serial_device_free (dc_serial_device_t *device);
|
||||
|
||||
/**
|
||||
* Create an iterator to enumerate the serial devices.
|
||||
*
|
||||
* @param[out] iterator A location to store the iterator.
|
||||
* @param[in] context A valid context object.
|
||||
* @param[in] descriptor A valid device descriptor or NULL.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_serial_enumerate (dc_serial_callback_t callback, void *userdata);
|
||||
dc_serial_iterator_new (dc_iterator_t **iterator, dc_context_t *context, dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Open a serial connection.
|
||||
|
||||
@ -58,6 +58,12 @@
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
|
||||
#define DIRNAME "/dev"
|
||||
|
||||
static dc_status_t dc_serial_iterator_next (dc_iterator_t *iterator, void *item);
|
||||
static dc_status_t dc_serial_iterator_free (dc_iterator_t *iterator);
|
||||
|
||||
static dc_status_t dc_serial_set_timeout (dc_iostream_t *iostream, int timeout);
|
||||
static dc_status_t dc_serial_set_latency (dc_iostream_t *iostream, unsigned int value);
|
||||
@ -75,6 +81,15 @@ static dc_status_t dc_serial_purge (dc_iostream_t *iostream, dc_direction_t dire
|
||||
static dc_status_t dc_serial_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
|
||||
static dc_status_t dc_serial_close (dc_iostream_t *iostream);
|
||||
|
||||
struct dc_serial_device_t {
|
||||
char name[256];
|
||||
};
|
||||
|
||||
typedef struct dc_serial_iterator_t {
|
||||
dc_iterator_t base;
|
||||
DIR *dp;
|
||||
} dc_serial_iterator_t;
|
||||
|
||||
typedef struct dc_serial_t {
|
||||
dc_iostream_t base;
|
||||
/*
|
||||
@ -94,6 +109,12 @@ typedef struct dc_serial_t {
|
||||
unsigned int nbits;
|
||||
} dc_serial_t;
|
||||
|
||||
static const dc_iterator_vtable_t dc_serial_iterator_vtable = {
|
||||
sizeof(dc_serial_iterator_t),
|
||||
dc_serial_iterator_next,
|
||||
dc_serial_iterator_free,
|
||||
};
|
||||
|
||||
static const dc_iostream_vtable_t dc_serial_vtable = {
|
||||
sizeof(dc_serial_t),
|
||||
dc_serial_set_timeout, /* set_timeout */
|
||||
@ -131,12 +152,60 @@ syserror(int errcode)
|
||||
}
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
|
||||
const char *
|
||||
dc_serial_device_get_name (dc_serial_device_t *device)
|
||||
{
|
||||
DIR *dp = NULL;
|
||||
if (device == NULL || device->name[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
return device->name;
|
||||
}
|
||||
|
||||
void
|
||||
dc_serial_device_free (dc_serial_device_t *device)
|
||||
{
|
||||
free (device);
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_serial_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_t *descriptor)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_serial_iterator_t *iterator = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
iterator = (dc_serial_iterator_t *) dc_iterator_allocate (context, &dc_serial_iterator_vtable);
|
||||
if (iterator == NULL) {
|
||||
SYSERROR (context, ENOMEM);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
iterator->dp = opendir (DIRNAME);
|
||||
if (iterator->dp == NULL) {
|
||||
int errcode = errno;
|
||||
SYSERROR (context, errcode);
|
||||
status = syserror (errcode);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
*out = (dc_iterator_t *) iterator;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free:
|
||||
dc_iterator_deallocate ((dc_iterator_t *) iterator);
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_serial_iterator_next (dc_iterator_t *abstract, void *out)
|
||||
{
|
||||
dc_serial_iterator_t *iterator = (dc_serial_iterator_t *) abstract;
|
||||
dc_serial_device_t *device = NULL;
|
||||
|
||||
struct dirent *ep = NULL;
|
||||
const char *dirname = "/dev";
|
||||
const char *patterns[] = {
|
||||
#if defined (__APPLE__)
|
||||
"tty.*",
|
||||
@ -149,28 +218,40 @@ dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
|
||||
NULL
|
||||
};
|
||||
|
||||
dp = opendir (dirname);
|
||||
if (dp == NULL) {
|
||||
return DC_STATUS_IO;
|
||||
}
|
||||
|
||||
while ((ep = readdir (dp)) != NULL) {
|
||||
while ((ep = readdir (iterator->dp)) != NULL) {
|
||||
for (size_t i = 0; patterns[i] != NULL; ++i) {
|
||||
if (fnmatch (patterns[i], ep->d_name, 0) == 0) {
|
||||
char filename[1024];
|
||||
int n = snprintf (filename, sizeof (filename), "%s/%s", dirname, ep->d_name);
|
||||
if (n >= sizeof (filename)) {
|
||||
closedir (dp);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
if (fnmatch (patterns[i], ep->d_name, 0) != 0)
|
||||
continue;
|
||||
|
||||
callback (filename, userdata);
|
||||
break;
|
||||
char filename[sizeof(device->name)];
|
||||
int n = snprintf (filename, sizeof (filename), "%s/%s", DIRNAME, ep->d_name);
|
||||
if (n < 0 || (size_t) n >= sizeof (filename)) {
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
device = (dc_serial_device_t *) malloc (sizeof(dc_serial_device_t));
|
||||
if (device == NULL) {
|
||||
SYSERROR (abstract->context, ENOMEM);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
strncpy(device->name, filename, sizeof(device->name));
|
||||
|
||||
*(dc_serial_device_t **) out = device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
closedir (dp);
|
||||
return DC_STATUS_DONE;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_serial_iterator_free (dc_iterator_t *abstract)
|
||||
{
|
||||
dc_serial_iterator_t *iterator = (dc_serial_iterator_t *) abstract;
|
||||
|
||||
closedir (iterator->dp);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -29,6 +29,10 @@
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
|
||||
static dc_status_t dc_serial_iterator_next (dc_iterator_t *iterator, void *item);
|
||||
static dc_status_t dc_serial_iterator_free (dc_iterator_t *iterator);
|
||||
|
||||
static dc_status_t dc_serial_set_timeout (dc_iostream_t *iostream, int timeout);
|
||||
static dc_status_t dc_serial_set_latency (dc_iostream_t *iostream, unsigned int value);
|
||||
@ -46,6 +50,17 @@ static dc_status_t dc_serial_purge (dc_iostream_t *iostream, dc_direction_t dire
|
||||
static dc_status_t dc_serial_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
|
||||
static dc_status_t dc_serial_close (dc_iostream_t *iostream);
|
||||
|
||||
struct dc_serial_device_t {
|
||||
char name[256];
|
||||
};
|
||||
|
||||
typedef struct dc_serial_iterator_t {
|
||||
dc_iterator_t base;
|
||||
HKEY hKey;
|
||||
DWORD count;
|
||||
DWORD current;
|
||||
} dc_serial_iterator_t;
|
||||
|
||||
typedef struct dc_serial_t {
|
||||
dc_iostream_t base;
|
||||
/*
|
||||
@ -65,6 +80,12 @@ typedef struct dc_serial_t {
|
||||
unsigned int nbits;
|
||||
} dc_serial_t;
|
||||
|
||||
static const dc_iterator_vtable_t dc_serial_iterator_vtable = {
|
||||
sizeof(dc_serial_iterator_t),
|
||||
dc_serial_iterator_next,
|
||||
dc_serial_iterator_free,
|
||||
};
|
||||
|
||||
static const dc_iostream_vtable_t dc_serial_vtable = {
|
||||
sizeof(dc_serial_t),
|
||||
dc_serial_set_timeout, /* set_timeout */
|
||||
@ -101,37 +122,92 @@ syserror(DWORD errcode)
|
||||
}
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
|
||||
const char *
|
||||
dc_serial_device_get_name (dc_serial_device_t *device)
|
||||
{
|
||||
if (device == NULL || device->name[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
return device->name;
|
||||
}
|
||||
|
||||
void
|
||||
dc_serial_device_free (dc_serial_device_t *device)
|
||||
{
|
||||
free (device);
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_serial_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_t *descriptor)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_serial_iterator_t *iterator = NULL;
|
||||
HKEY hKey = NULL;
|
||||
DWORD count = 0;
|
||||
LONG rc = 0;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
iterator = (dc_serial_iterator_t *) dc_iterator_allocate (context, &dc_serial_iterator_vtable);
|
||||
if (iterator == NULL) {
|
||||
SYSERROR (context, ERROR_OUTOFMEMORY);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Open the registry key.
|
||||
HKEY hKey;
|
||||
LONG rc = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey);
|
||||
rc = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey);
|
||||
if (rc != ERROR_SUCCESS) {
|
||||
if (rc == ERROR_FILE_NOT_FOUND)
|
||||
return DC_STATUS_SUCCESS;
|
||||
else
|
||||
return DC_STATUS_IO;
|
||||
if (rc == ERROR_FILE_NOT_FOUND) {
|
||||
hKey = NULL;
|
||||
} else {
|
||||
SYSERROR (context, rc);
|
||||
status = syserror (rc);
|
||||
goto error_free;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the number of values.
|
||||
DWORD count = 0;
|
||||
rc = RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL);
|
||||
if (rc != ERROR_SUCCESS) {
|
||||
RegCloseKey(hKey);
|
||||
return DC_STATUS_IO;
|
||||
if (hKey) {
|
||||
rc = RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL);
|
||||
if (rc != ERROR_SUCCESS) {
|
||||
SYSERROR (context, rc);
|
||||
status = syserror (rc);
|
||||
goto error_close;
|
||||
}
|
||||
}
|
||||
|
||||
for (DWORD i = 0; i < count; ++i) {
|
||||
iterator->hKey = hKey;
|
||||
iterator->count = count;
|
||||
iterator->current = 0;
|
||||
|
||||
*out = (dc_iterator_t *) iterator;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_close:
|
||||
RegCloseKey (hKey);
|
||||
error_free:
|
||||
dc_iterator_deallocate ((dc_iterator_t *) iterator);
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_serial_iterator_next (dc_iterator_t *abstract, void *out)
|
||||
{
|
||||
dc_serial_iterator_t *iterator = (dc_serial_iterator_t *) abstract;
|
||||
dc_serial_device_t *device = NULL;
|
||||
|
||||
while (iterator->current < iterator->count) {
|
||||
// Get the value name, data and type.
|
||||
char name[512], data[512];
|
||||
char name[256], data[sizeof(device->name)];
|
||||
DWORD name_len = sizeof (name);
|
||||
DWORD data_len = sizeof (data);
|
||||
DWORD type = 0;
|
||||
rc = RegEnumValueA (hKey, i, name, &name_len, NULL, &type, (LPBYTE) data, &data_len);
|
||||
LONG rc = RegEnumValueA (iterator->hKey, iterator->current++, name, &name_len, NULL, &type, (LPBYTE) data, &data_len);
|
||||
if (rc != ERROR_SUCCESS) {
|
||||
RegCloseKey(hKey);
|
||||
return DC_STATUS_IO;
|
||||
SYSERROR (abstract->context, rc);
|
||||
return syserror (rc);
|
||||
}
|
||||
|
||||
// Ignore non-string values.
|
||||
@ -140,17 +216,36 @@ dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
|
||||
|
||||
// Prevent a possible buffer overflow.
|
||||
if (data_len >= sizeof (data)) {
|
||||
RegCloseKey(hKey);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Null terminate the string.
|
||||
data[data_len] = 0;
|
||||
|
||||
callback (data, userdata);
|
||||
device = (dc_serial_device_t *) malloc (sizeof(dc_serial_device_t));
|
||||
if (device == NULL) {
|
||||
SYSERROR (abstract->context, ERROR_OUTOFMEMORY);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
strncpy(device->name, data, sizeof(device->name));
|
||||
|
||||
*(dc_serial_device_t **) out = device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return DC_STATUS_DONE;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_serial_iterator_free (dc_iterator_t *abstract)
|
||||
{
|
||||
dc_serial_iterator_t *iterator = (dc_serial_iterator_t *) abstract;
|
||||
|
||||
if (iterator->hKey) {
|
||||
RegCloseKey (iterator->hKey);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
237
src/usbhid.c
237
src/usbhid.c
@ -54,6 +54,7 @@
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -66,12 +67,30 @@ typedef pthread_mutex_t dc_mutex_t;
|
||||
|
||||
#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_usbhid_vtable)
|
||||
|
||||
struct dc_usbhid_device_t {
|
||||
unsigned short vid, pid;
|
||||
};
|
||||
|
||||
#ifdef USBHID
|
||||
static dc_status_t dc_usbhid_iterator_next (dc_iterator_t *iterator, void *item);
|
||||
static dc_status_t dc_usbhid_iterator_free (dc_iterator_t *iterator);
|
||||
|
||||
static dc_status_t dc_usbhid_set_timeout (dc_iostream_t *iostream, int timeout);
|
||||
static dc_status_t dc_usbhid_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
||||
static dc_status_t dc_usbhid_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
||||
static dc_status_t dc_usbhid_close (dc_iostream_t *iostream);
|
||||
|
||||
typedef struct dc_usbhid_iterator_t {
|
||||
dc_iterator_t base;
|
||||
#if defined(USE_LIBUSB)
|
||||
struct libusb_device **devices;
|
||||
size_t count;
|
||||
size_t current;
|
||||
#elif defined(USE_HIDAPI)
|
||||
struct hid_device_info *devices, *current;
|
||||
#endif
|
||||
} dc_usbhid_iterator_t;
|
||||
|
||||
typedef struct dc_usbhid_t {
|
||||
/* Base class. */
|
||||
dc_iostream_t base;
|
||||
@ -88,6 +107,12 @@ typedef struct dc_usbhid_t {
|
||||
#endif
|
||||
} dc_usbhid_t;
|
||||
|
||||
static const dc_iterator_vtable_t dc_usbhid_iterator_vtable = {
|
||||
sizeof(dc_usbhid_iterator_t),
|
||||
dc_usbhid_iterator_next,
|
||||
dc_usbhid_iterator_free,
|
||||
};
|
||||
|
||||
static const dc_iostream_vtable_t dc_usbhid_vtable = {
|
||||
sizeof(dc_usbhid_t),
|
||||
dc_usbhid_set_timeout, /* set_timeout */
|
||||
@ -211,6 +236,218 @@ dc_usbhid_exit (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
dc_usbhid_device_get_vid (dc_usbhid_device_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return 0;
|
||||
|
||||
return device->vid;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
dc_usbhid_device_get_pid (dc_usbhid_device_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return 0;
|
||||
|
||||
return device->pid;
|
||||
}
|
||||
|
||||
void
|
||||
dc_usbhid_device_free(dc_usbhid_device_t *device)
|
||||
{
|
||||
free (device);
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_usbhid_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_t *descriptor)
|
||||
{
|
||||
#ifdef USBHID
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_usbhid_iterator_t *iterator = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
iterator = (dc_usbhid_iterator_t *) dc_iterator_allocate (context, &dc_usbhid_iterator_vtable);
|
||||
if (iterator == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Initialize the usb library.
|
||||
status = dc_usbhid_init (context);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
#if defined(USE_LIBUSB)
|
||||
// Enumerate the USB devices.
|
||||
struct libusb_device **devices = NULL;
|
||||
ssize_t ndevices = libusb_get_device_list (g_usbhid_ctx, &devices);
|
||||
if (ndevices < 0) {
|
||||
ERROR (context, "Failed to enumerate the usb devices (%s).",
|
||||
libusb_error_name (ndevices));
|
||||
status = syserror (ndevices);
|
||||
goto error_usb_exit;
|
||||
}
|
||||
|
||||
iterator->devices = devices;
|
||||
iterator->count = ndevices;
|
||||
iterator->current = 0;
|
||||
#elif defined(USE_HIDAPI)
|
||||
struct hid_device_info *devices = hid_enumerate(0x0, 0x0);
|
||||
if (devices == NULL) {
|
||||
status = DC_STATUS_IO;
|
||||
goto error_usb_exit;
|
||||
}
|
||||
|
||||
iterator->devices = devices;
|
||||
iterator->current = devices;
|
||||
#endif
|
||||
|
||||
*out = (dc_iterator_t *) iterator;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_usb_exit:
|
||||
dc_usbhid_exit ();
|
||||
error_free:
|
||||
dc_iterator_deallocate ((dc_iterator_t *) iterator);
|
||||
return status;
|
||||
#else
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USBHID
|
||||
static dc_status_t
|
||||
dc_usbhid_iterator_next (dc_iterator_t *abstract, void *out)
|
||||
{
|
||||
dc_usbhid_iterator_t *iterator = (dc_usbhid_iterator_t *) abstract;
|
||||
dc_usbhid_device_t *device = NULL;
|
||||
|
||||
#if defined(USE_LIBUSB)
|
||||
while (iterator->current < iterator->count) {
|
||||
struct libusb_device *current = iterator->devices[iterator->current++];
|
||||
|
||||
// Get the device descriptor.
|
||||
struct libusb_device_descriptor dev;
|
||||
int rc = libusb_get_device_descriptor (current, &dev);
|
||||
if (rc < 0) {
|
||||
ERROR (abstract->context, "Failed to get the device descriptor (%s).",
|
||||
libusb_error_name (rc));
|
||||
return syserror (rc);
|
||||
}
|
||||
|
||||
// Get the active configuration descriptor.
|
||||
struct libusb_config_descriptor *config = NULL;
|
||||
rc = libusb_get_active_config_descriptor (current, &config);
|
||||
if (rc != LIBUSB_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to get the configuration descriptor (%s).",
|
||||
libusb_error_name (rc));
|
||||
return syserror (rc);
|
||||
}
|
||||
|
||||
// Find the first HID interface.
|
||||
const struct libusb_interface_descriptor *interface = NULL;
|
||||
for (unsigned int i = 0; i < config->bNumInterfaces; i++) {
|
||||
const struct libusb_interface *iface = &config->interface[i];
|
||||
for (int j = 0; j < iface->num_altsetting; j++) {
|
||||
const struct libusb_interface_descriptor *desc = &iface->altsetting[j];
|
||||
if (desc->bInterfaceClass == LIBUSB_CLASS_HID && interface == NULL) {
|
||||
interface = desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interface == NULL) {
|
||||
libusb_free_config_descriptor (config);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the first input and output interrupt endpoints.
|
||||
const struct libusb_endpoint_descriptor *ep_in = NULL, *ep_out = NULL;
|
||||
for (unsigned int i = 0; i < interface->bNumEndpoints; i++) {
|
||||
const struct libusb_endpoint_descriptor *desc = &interface->endpoint[i];
|
||||
|
||||
unsigned int type = desc->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK;
|
||||
unsigned int direction = desc->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK;
|
||||
|
||||
if (type != LIBUSB_TRANSFER_TYPE_INTERRUPT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (direction == LIBUSB_ENDPOINT_IN && ep_in == NULL) {
|
||||
ep_in = desc;
|
||||
}
|
||||
|
||||
if (direction == LIBUSB_ENDPOINT_OUT && ep_out == NULL) {
|
||||
ep_out = desc;
|
||||
}
|
||||
}
|
||||
|
||||
if (ep_in == NULL || ep_out == NULL) {
|
||||
libusb_free_config_descriptor (config);
|
||||
continue;
|
||||
}
|
||||
|
||||
device = (dc_usbhid_device_t *) malloc (sizeof(dc_usbhid_device_t));
|
||||
if (device == NULL) {
|
||||
ERROR (abstract->context, "Failed to allocate memory.");
|
||||
libusb_free_config_descriptor (config);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
device->vid = dev.idVendor;
|
||||
device->pid = dev.idProduct;
|
||||
|
||||
*(dc_usbhid_device_t **) out = device;
|
||||
|
||||
libusb_free_config_descriptor (config);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
#elif defined(USE_HIDAPI)
|
||||
while (iterator->current) {
|
||||
struct hid_device_info *current = iterator->current;
|
||||
iterator->current = current->next;
|
||||
|
||||
device = (dc_usbhid_device_t *) malloc (sizeof(dc_usbhid_device_t));
|
||||
if (device == NULL) {
|
||||
ERROR (abstract->context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
device->vid = current->vendor_id;
|
||||
device->pid = current->product_id;
|
||||
|
||||
*(dc_usbhid_device_t **) out = device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
return DC_STATUS_DONE;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_usbhid_iterator_free (dc_iterator_t *abstract)
|
||||
{
|
||||
dc_usbhid_iterator_t *iterator = (dc_usbhid_iterator_t *) abstract;
|
||||
|
||||
#if defined(USE_LIBUSB)
|
||||
libusb_free_device_list (iterator->devices, 1);
|
||||
#elif defined(USE_HIDAPI)
|
||||
hid_free_enumeration (iterator->devices);
|
||||
#endif
|
||||
dc_usbhid_exit ();
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
dc_status_t
|
||||
dc_usbhid_open (dc_iostream_t **out, dc_context_t *context, unsigned int vid, unsigned int pid)
|
||||
{
|
||||
|
||||
43
src/usbhid.h
43
src/usbhid.h
@ -25,11 +25,54 @@
|
||||
#include <libdivecomputer/common.h>
|
||||
#include <libdivecomputer/context.h>
|
||||
#include <libdivecomputer/iostream.h>
|
||||
#include <libdivecomputer/iterator.h>
|
||||
#include <libdivecomputer/descriptor.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Opaque object representing a USB HID device.
|
||||
*/
|
||||
typedef struct dc_usbhid_device_t dc_usbhid_device_t;
|
||||
|
||||
/**
|
||||
* Get the vendor id (VID) of the USB HID device.
|
||||
*
|
||||
* @param[in] device A valid USB HID device.
|
||||
*/
|
||||
unsigned int
|
||||
dc_usbhid_device_get_vid (dc_usbhid_device_t *device);
|
||||
|
||||
/**
|
||||
* Get the product id (PID) of the USB HID device.
|
||||
*
|
||||
* @param[in] device A valid USB HID device.
|
||||
*/
|
||||
unsigned int
|
||||
dc_usbhid_device_get_pid (dc_usbhid_device_t *device);
|
||||
|
||||
/**
|
||||
* Destroy the USB HID device and free all resources.
|
||||
*
|
||||
* @param[in] device A valid USB HID device.
|
||||
*/
|
||||
void
|
||||
dc_usbhid_device_free(dc_usbhid_device_t *device);
|
||||
|
||||
/**
|
||||
* Create an iterator to enumerate the USB HID devices.
|
||||
*
|
||||
* @param[out] iterator A location to store the iterator.
|
||||
* @param[in] context A valid context object.
|
||||
* @param[in] descriptor A valid device descriptor or NULL.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_usbhid_iterator_new (dc_iterator_t **iterator, dc_context_t *context, dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Open a USB HID connection.
|
||||
*
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
typedef struct uwatec_smart_device_t {
|
||||
dc_device_t base;
|
||||
dc_iostream_t *iostream;
|
||||
unsigned int address;
|
||||
unsigned int timestamp;
|
||||
unsigned int devtime;
|
||||
dc_ticks_t systime;
|
||||
@ -62,8 +61,8 @@ static const dc_device_vtable_t uwatec_smart_device_vtable = {
|
||||
static dc_status_t
|
||||
uwatec_smart_extract_dives (dc_device_t *device, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata);
|
||||
|
||||
static void
|
||||
uwatec_smart_discovery (unsigned int address, const char *name, unsigned int charset, unsigned int hints, void *userdata)
|
||||
static int
|
||||
uwatec_smart_filter (const char *name)
|
||||
{
|
||||
static const char *names[] = {
|
||||
"Aladin Smart Com",
|
||||
@ -75,16 +74,16 @@ uwatec_smart_discovery (unsigned int address, const char *name, unsigned int cha
|
||||
"UWATEC Galileo Sol",
|
||||
};
|
||||
|
||||
uwatec_smart_device_t *device = (uwatec_smart_device_t*) userdata;
|
||||
if (device == NULL || name == NULL)
|
||||
return;
|
||||
if (name == NULL)
|
||||
return 0;
|
||||
|
||||
for (size_t i = 0; i < C_ARRAY_SIZE(names); ++i) {
|
||||
if (strcasecmp(name, names[i]) == 0) {
|
||||
device->address = address;
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -152,6 +151,8 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
uwatec_smart_device_t *device = NULL;
|
||||
dc_iterator_t *iterator = NULL;
|
||||
dc_irda_device_t *dev = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
@ -165,33 +166,48 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
|
||||
|
||||
// Set the default values.
|
||||
device->iostream = NULL;
|
||||
device->address = 0;
|
||||
device->timestamp = 0;
|
||||
device->systime = (dc_ticks_t) -1;
|
||||
device->devtime = 0;
|
||||
|
||||
// Create the irda device iterator.
|
||||
status = dc_irda_iterator_new (&iterator, context, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to create the irda iterator.");
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Enumerate the irda devices.
|
||||
while (1) {
|
||||
dc_irda_device_t *current = NULL;
|
||||
status = dc_iterator_next (iterator, ¤t);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
if (status == DC_STATUS_DONE) {
|
||||
ERROR (context, "No dive computer found.");
|
||||
status = DC_STATUS_NODEVICE;
|
||||
} else {
|
||||
ERROR (context, "Failed to enumerate the irda devices.");
|
||||
}
|
||||
goto error_iterator_free;
|
||||
}
|
||||
|
||||
if (uwatec_smart_filter (dc_irda_device_get_name (current))) {
|
||||
dev = current;
|
||||
break;
|
||||
}
|
||||
|
||||
dc_irda_device_free (current);
|
||||
}
|
||||
|
||||
// Open the irda socket.
|
||||
status = dc_irda_open (&device->iostream, context);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to open the irda socket.");
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Discover the device.
|
||||
status = dc_irda_discover (device->iostream, uwatec_smart_discovery, device);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to discover the device.");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
if (device->address == 0) {
|
||||
ERROR (context, "No dive computer found.");
|
||||
status = DC_STATUS_IO;
|
||||
goto error_close;
|
||||
goto error_device_free;
|
||||
}
|
||||
|
||||
// Connect the device.
|
||||
status = dc_irda_connect_lsap (device->iostream, device->address, 1);
|
||||
status = dc_irda_connect_lsap (device->iostream, dc_irda_device_get_address (dev), 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to connect the device.");
|
||||
goto error_close;
|
||||
@ -210,6 +226,10 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
|
||||
|
||||
error_close:
|
||||
dc_iostream_close (device->iostream);
|
||||
error_device_free:
|
||||
dc_irda_device_free (dev);
|
||||
error_iterator_free:
|
||||
dc_iterator_free (iterator);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user