aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Schink <jaylink-dev@marcschink.de>2016-06-23 22:24:20 +0200
committerMarc Schink <jaylink-dev@marcschink.de>2016-06-23 23:24:36 +0200
commit8c4b24ec5b9f5a3906775434d61fd5323d756d74 (patch)
treef174fdd4e667ae3b2c23f38cfd5b5f534b29e9ab
parentff42c31f41cc4cb2de75edb493c7da552065cab5 (diff)
Rework device discovery API
Signed-off-by: Marc Schink <jaylink-dev@marcschink.de>
-rw-r--r--Doxyfile1
-rw-r--r--libjaylink/core.c14
-rw-r--r--libjaylink/device.c78
-rw-r--r--libjaylink/discovery.c114
-rw-r--r--libjaylink/libjaylink-internal.h5
-rw-r--r--libjaylink/libjaylink.h15
-rw-r--r--libjaylink/list.c12
7 files changed, 171 insertions, 68 deletions
diff --git a/Doxyfile b/Doxyfile
index 5630dcf..c94a866 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -780,7 +780,6 @@ RECURSIVE = NO
EXCLUDE = libjaylink/libjaylink-internal.h \
libjaylink/list.c \
- libjaylink/discovery.c \
libjaylink/transport.c \
libjaylink/buffer.c
diff --git a/libjaylink/core.c b/libjaylink/core.c
index 9189905..1ab4607 100644
--- a/libjaylink/core.c
+++ b/libjaylink/core.c
@@ -1,7 +1,7 @@
/*
* This file is part of the libjaylink project.
*
- * Copyright (C) 2014-2015 Marc Schink <jaylink-dev@marcschink.de>
+ * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -61,6 +61,7 @@ JAYLINK_API int jaylink_init(struct jaylink_context **ctx)
}
context->devs = NULL;
+ context->discovered_devs = NULL;
/* Show error and warning messages by default. */
context->log_level = JAYLINK_LOG_LEVEL_WARNING;
@@ -87,10 +88,21 @@ JAYLINK_API int jaylink_init(struct jaylink_context **ctx)
*/
JAYLINK_API void jaylink_exit(struct jaylink_context *ctx)
{
+ struct list *item;
+
if (!ctx)
return;
+ item = ctx->discovered_devs;
+
+ while (item) {
+ jaylink_unref_device((struct jaylink_device *)item->data);
+ item = item->next;
+ }
+
+ list_free(ctx->discovered_devs);
list_free(ctx->devs);
+
libusb_exit(ctx->usb_ctx);
free(ctx);
}
diff --git a/libjaylink/device.c b/libjaylink/device.c
index 9513b21..9ec00a7 100644
--- a/libjaylink/device.c
+++ b/libjaylink/device.c
@@ -1,7 +1,7 @@
/*
* This file is part of the libjaylink project.
*
- * Copyright (C) 2014-2015 Marc Schink <jaylink-dev@marcschink.de>
+ * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -107,43 +107,93 @@ static void free_device_handle(struct jaylink_device_handle *devh)
free(devh);
}
+/** @private */
+static struct jaylink_device **allocate_device_list(size_t length)
+{
+ struct jaylink_device **list;
+
+ list = malloc(sizeof(struct jaylink_device *) * (length + 1));
+
+ if (!list)
+ return NULL;
+
+ list[length] = NULL;
+
+ return list;
+}
+
/**
- * Get a list of available devices.
+ * Get available devices.
*
* @param[in,out] ctx libjaylink context.
* @param[out] devices Newly allocated array which contains instances of
* available devices on success, and undefined on failure.
* The array is NULL-terminated and must be free'd by the
- * caller with jaylink_free_device_list().
+ * caller with jaylink_free_devices().
+ * @param[out] count Number of available devices on success, and undefined on
+ * failure. Can be NULL.
*
- * @return The length of the array excluding the trailing NULL-terminator, or a
- * negative error code on failure.
+ * @retval JAYLINK_OK Success.
+ * @retval JAYLINK_ERR_ARG Invalid arguments.
+ * @retval JAYLINK_ERR_MALLOC Memory allocation error.
+ * @retval JAYLINK_ERR Other error conditions.
+ *
+ * @see jaylink_discovery_scan()
*/
-JAYLINK_API ssize_t jaylink_get_device_list(struct jaylink_context *ctx,
- struct jaylink_device ***devices)
+JAYLINK_API int jaylink_get_devices(struct jaylink_context *ctx,
+ struct jaylink_device ***devices, size_t *count)
{
+ size_t num;
+ struct list *item;
+ struct jaylink_device **devs;
+ struct jaylink_device *dev;
+ size_t i;
+
if (!ctx || !devices)
return JAYLINK_ERR_ARG;
- return discovery_get_device_list(ctx, devices);
+ num = list_length(ctx->discovered_devs);
+ devs = allocate_device_list(num);
+
+ if (!devs) {
+ log_err(ctx, "Failed to allocate device list.");
+ return JAYLINK_ERR_MALLOC;
+ }
+
+ item = ctx->discovered_devs;
+
+ for (i = 0; i < num; i++) {
+ dev = (struct jaylink_device *)item->data;
+ devs[i] = jaylink_ref_device(dev);
+ item = item->next;
+ }
+
+ if (count)
+ *count = num;
+
+ *devices = devs;
+
+ return JAYLINK_OK;
}
/**
- * Free a device list.
+ * Free devices.
*
* @param[in,out] devices Array of device instances. Must be NULL-terminated.
- * @param[in] unref_devices Determines whether the device instances should be
- * unreferenced.
+ * @param[in] unref Determines whether the device instances should be
+ * unreferenced.
+ *
+ * @see jaylink_get_devices()
*/
-JAYLINK_API void jaylink_free_device_list(struct jaylink_device **devices,
- bool unref_devices)
+JAYLINK_API void jaylink_free_devices(struct jaylink_device **devices,
+ bool unref)
{
size_t i;
if (!devices)
return;
- if (unref_devices) {
+ if (unref) {
i = 0;
while (devices[i]) {
diff --git a/libjaylink/discovery.c b/libjaylink/discovery.c
index 4a20cdf..23e6d5c 100644
--- a/libjaylink/discovery.c
+++ b/libjaylink/discovery.c
@@ -1,7 +1,7 @@
/*
* This file is part of the libjaylink project.
*
- * Copyright (C) 2014-2015 Marc Schink <jaylink-dev@marcschink.de>
+ * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,6 +34,7 @@
* Device discovery.
*/
+/** @cond PRIVATE */
/** USB Vendor ID (VID) of SEGGER products. */
#define USB_VENDOR_ID 0x1366
@@ -67,20 +68,7 @@ static const uint16_t pids[][2] = {
* serial numbers are allowed with up to 10 digits.
*/
#define MAX_SERIAL_NUMBER_DIGITS 10
-
-static struct jaylink_device **allocate_device_list(size_t length)
-{
- struct jaylink_device **list;
-
- list = malloc(sizeof(struct jaylink_device *) * (length + 1));
-
- if (!list)
- return NULL;
-
- list[length] = NULL;
-
- return list;
-}
+/** @endcond */
static bool parse_serial_number(const char *str, uint32_t *serial_number)
{
@@ -246,19 +234,15 @@ static struct jaylink_device *probe_device(struct jaylink_context *ctx,
return dev;
}
-/** @private */
-JAYLINK_PRIV ssize_t discovery_get_device_list(struct jaylink_context *ctx,
- struct jaylink_device ***list)
+static int discovery_usb_scan(struct jaylink_context *ctx)
{
ssize_t ret;
- struct libusb_device **usb_devs;
- struct jaylink_device **devs;
+ struct libusb_device **devs;
struct jaylink_device *dev;
- size_t num_usb_devs;
- size_t num_devs;
+ size_t num;
size_t i;
- ret = libusb_get_device_list(ctx->usb_ctx, &usb_devs);
+ ret = libusb_get_device_list(ctx->usb_ctx, &devs);
if (ret < 0) {
log_err(ctx, "Failed to retrieve device list: %s.",
@@ -266,37 +250,77 @@ JAYLINK_PRIV ssize_t discovery_get_device_list(struct jaylink_context *ctx,
return JAYLINK_ERR;
}
- num_usb_devs = ret;
+ num = 0;
- /*
- * Allocate a device list with the length of the number of all found
- * USB devices because they all are possible J-Link devices.
- */
- devs = allocate_device_list(num_usb_devs);
+ for (i = 0; devs[i]; i++) {
+ dev = probe_device(ctx, devs[i]);
- if (!devs) {
- libusb_free_device_list(usb_devs, true);
- log_err(ctx, "Device list malloc failed.");
- return JAYLINK_ERR_MALLOC;
+ if (!dev)
+ continue;
+
+ ctx->discovered_devs = list_prepend(ctx->discovered_devs, dev);
+ num++;
}
- num_devs = 0;
+ libusb_free_device_list(devs, true);
+ log_dbg(ctx, "Found %zu USB device(s).", num);
- for (i = 0; i < num_usb_devs; i++) {
- dev = probe_device(ctx, usb_devs[i]);
+ return JAYLINK_OK;
+}
- if (dev) {
- devs[num_devs] = dev;
- num_devs++;
- }
+static void clear_discovery_list(struct jaylink_context *ctx)
+{
+ struct list *item;
+ struct list *tmp;
+ struct jaylink_device *dev;
+
+ item = ctx->discovered_devs;
+
+ while (item) {
+ dev = (struct jaylink_device *)item->data;
+ jaylink_unref_device(dev);
+
+ tmp = item;
+ item = item->next;
+ free(tmp);
}
- devs[num_devs] = NULL;
+ ctx->discovered_devs = NULL;
+}
+
+/**
+ * Scan for devices.
+ *
+ * @param[in,out] ctx libjaylink context.
+ * @param[in] hostifs Host interfaces to scan for devices. Use bitwise OR to
+ * specify multiple interfaces, or 0 to use all available
+ * interfaces. See #jaylink_host_interface for a description
+ * of the interfaces.
+ *
+ * @retval JAYLINK_OK Success.
+ * @retval JAYLINK_ERR_ARG Invalid arguments.
+ * @retval JAYLINK_ERR Other error conditions.
+ *
+ * @see jaylink_get_devices()
+ */
+JAYLINK_API int jaylink_discovery_scan(struct jaylink_context *ctx,
+ uint32_t hostifs)
+{
+ int ret;
+
+ if (!ctx)
+ return JAYLINK_ERR_ARG;
+
+ (void)hostifs;
- libusb_free_device_list(usb_devs, true);
- *list = devs;
+ clear_discovery_list(ctx);
- log_dbg(ctx, "Found %zu device(s).", num_devs);
+ ret = discovery_usb_scan(ctx);
+
+ if (ret != JAYLINK_OK) {
+ log_err(ctx, "USB device discovery failed.");
+ return ret;
+ }
- return num_devs;
+ return JAYLINK_OK;
}
diff --git a/libjaylink/libjaylink-internal.h b/libjaylink/libjaylink-internal.h
index 65e88f3..9d568df 100644
--- a/libjaylink/libjaylink-internal.h
+++ b/libjaylink/libjaylink-internal.h
@@ -1,7 +1,7 @@
/*
* This file is part of the libjaylink project.
*
- * Copyright (C) 2014-2015 Marc Schink <jaylink-dev@marcschink.de>
+ * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -53,6 +53,8 @@ struct jaylink_context {
* Used to prevent multiple device instances for the same device.
*/
struct list *devs;
+ /** List of recently discovered devices. */
+ struct list *discovered_devs;
/** Current log level. */
enum jaylink_log_level log_level;
/** Log callback function. */
@@ -157,6 +159,7 @@ JAYLINK_PRIV struct list *list_prepend(struct list *list, void *data);
JAYLINK_PRIV struct list *list_remove(struct list *list, const void *data);
JAYLINK_PRIV struct list *list_find_custom(struct list *list,
list_compare_callback cb, const void *cb_data);
+JAYLINK_PRIV size_t list_length(struct list *list);
JAYLINK_PRIV void list_free(struct list *list);
/*--- log.c -----------------------------------------------------------------*/
diff --git a/libjaylink/libjaylink.h b/libjaylink/libjaylink.h
index 461df29..71a92f3 100644
--- a/libjaylink/libjaylink.h
+++ b/libjaylink/libjaylink.h
@@ -1,7 +1,7 @@
/*
* This file is part of the libjaylink project.
*
- * Copyright (C) 2014-2015 Marc Schink <jaylink-dev@marcschink.de>
+ * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -359,10 +359,10 @@ JAYLINK_API void jaylink_exit(struct jaylink_context *ctx);
/*--- device.c --------------------------------------------------------------*/
-JAYLINK_API ssize_t jaylink_get_device_list(struct jaylink_context *ctx,
- struct jaylink_device ***devices);
-JAYLINK_API void jaylink_free_device_list(struct jaylink_device **devices,
- bool unref_devices);
+JAYLINK_API int jaylink_get_devices(struct jaylink_context *ctx,
+ struct jaylink_device ***devices, size_t *count);
+JAYLINK_API void jaylink_free_devices(struct jaylink_device **devices,
+ bool unref);
JAYLINK_API int jaylink_device_get_host_interface(
const struct jaylink_device *dev,
enum jaylink_host_interface *interface);
@@ -405,6 +405,11 @@ JAYLINK_API int jaylink_unregister(struct jaylink_device_handle *devh,
struct jaylink_connection *connections, size_t *count,
uint8_t *info, uint16_t *info_size);
+/*--- discovery.c -----------------------------------------------------------*/
+
+JAYLINK_API int jaylink_discovery_scan(struct jaylink_context *ctx,
+ uint32_t hostifs);
+
/*--- emucom.c --------------------------------------------------------------*/
JAYLINK_API int jaylink_emucom_read(struct jaylink_device_handle *devh,
diff --git a/libjaylink/list.c b/libjaylink/list.c
index a16ece5..6a1e328 100644
--- a/libjaylink/list.c
+++ b/libjaylink/list.c
@@ -1,7 +1,7 @@
/*
* This file is part of the libjaylink project.
*
- * Copyright (C) 2014-2015 Marc Schink <jaylink-dev@marcschink.de>
+ * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -88,6 +88,16 @@ JAYLINK_PRIV struct list *list_find_custom(struct list *list,
return NULL;
}
+JAYLINK_PRIV size_t list_length(struct list *list)
+{
+ size_t n;
+
+ for (n = 0; list; n++)
+ list = list->next;
+
+ return n;
+}
+
JAYLINK_PRIV void list_free(struct list *list)
{
struct list *tmp;