meson: Simplify code for libusb dependency
[libjaylink.git] / libjaylink / device.c
blob3477a0f0211de2f59c27002cedc8131abb1373d1
1 /*
2 * This file is part of the libjaylink project.
4 * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #ifdef _WIN32
29 #include <winsock2.h>
30 #else
31 #include <sys/socket.h>
32 #include <arpa/inet.h>
33 #endif
34 #ifdef HAVE_LIBUSB
35 #include <libusb.h>
36 #endif
38 #include "libjaylink.h"
39 #include "libjaylink-internal.h"
41 /**
42 * @file
44 * Device enumeration and handling.
47 /** @cond PRIVATE */
48 #define CMD_GET_VERSION 0x01
49 #define CMD_GET_HW_STATUS 0x07
50 #define CMD_REGISTER 0x09
51 #define CMD_GET_HW_INFO 0xc1
52 #define CMD_GET_COUNTERS 0xc2
53 #define CMD_GET_FREE_MEMORY 0xd4
54 #define CMD_GET_CAPS 0xe8
55 #define CMD_GET_EXT_CAPS 0xed
56 #define CMD_GET_HW_VERSION 0xf0
57 #define CMD_READ_CONFIG 0xf2
58 #define CMD_WRITE_CONFIG 0xf3
60 #define REG_CMD_REGISTER 0x64
61 #define REG_CMD_UNREGISTER 0x65
63 /** Size of the registration header in bytes. */
64 #define REG_HEADER_SIZE 8
65 /** Minimum registration information size in bytes. */
66 #define REG_MIN_SIZE 0x4c
67 /** Maximum registration information size in bytes. */
68 #define REG_MAX_SIZE 0x200
69 /** Size of a connection entry in bytes. */
70 #define REG_CONN_INFO_SIZE 16
72 /* The maximum path depth according to the USB 3.0 specification. */
73 #define MAX_USB_PATH_DEPTH 7
74 /** @endcond */
76 /** @private */
77 JAYLINK_PRIV struct jaylink_device *device_allocate(
78 struct jaylink_context *ctx)
80 struct jaylink_device *dev;
81 struct list *list;
83 dev = malloc(sizeof(struct jaylink_device));
85 if (!dev)
86 return NULL;
88 list = list_prepend(ctx->devs, dev);
90 if (!list) {
91 free(dev);
92 return NULL;
95 ctx->devs = list;
97 dev->ctx = ctx;
98 dev->ref_count = 1;
100 return dev;
103 static struct jaylink_device **allocate_device_list(size_t length)
105 struct jaylink_device **list;
107 list = malloc(sizeof(struct jaylink_device *) * (length + 1));
109 if (!list)
110 return NULL;
112 list[length] = NULL;
114 return list;
118 * Get available devices.
120 * @param[in,out] ctx libjaylink context.
121 * @param[out] devs Newly allocated array which contains instances of available
122 * devices on success, and undefined on failure. The array is
123 * NULL-terminated and must be free'd by the caller with
124 * jaylink_free_devices().
125 * @param[out] count Number of available devices on success, and undefined on
126 * failure. Can be NULL.
128 * @retval JAYLINK_OK Success.
129 * @retval JAYLINK_ERR_ARG Invalid arguments.
130 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
131 * @retval JAYLINK_ERR Other error conditions.
133 * @see jaylink_discovery_scan()
135 * @since 0.1.0
137 JAYLINK_API int jaylink_get_devices(struct jaylink_context *ctx,
138 struct jaylink_device ***devs, size_t *count)
140 size_t num;
141 struct list *item;
142 struct jaylink_device **tmp;
143 struct jaylink_device *dev;
145 if (!ctx || !devs)
146 return JAYLINK_ERR_ARG;
148 num = list_length(ctx->discovered_devs);
149 tmp = allocate_device_list(num);
151 if (!tmp) {
152 log_err(ctx, "Failed to allocate device list");
153 return JAYLINK_ERR_MALLOC;
156 item = ctx->discovered_devs;
158 for (size_t i = 0; i < num; i++) {
159 dev = (struct jaylink_device *)item->data;
160 tmp[i] = jaylink_ref_device(dev);
161 item = item->next;
164 if (count)
165 *count = num;
167 *devs = tmp;
169 return JAYLINK_OK;
173 * Free devices.
175 * @param[in,out] devs Array of device instances. Must be NULL-terminated.
176 * @param[in] unref Determines whether the device instances should be
177 * unreferenced.
179 * @see jaylink_get_devices()
181 * @since 0.1.0
183 JAYLINK_API void jaylink_free_devices(struct jaylink_device **devs, bool unref)
185 if (!devs)
186 return;
188 if (unref) {
189 for (size_t i = 0; devs[i]; i++)
190 jaylink_unref_device(devs[i]);
193 free(devs);
197 * Get the host interface of a device.
199 * @param[in] dev Device instance.
200 * @param[out] iface Host interface of the device on success, and undefined on
201 * failure.
203 * @retval JAYLINK_OK Success.
204 * @retval JAYLINK_ERR_ARG Invalid arguments.
206 * @since 0.1.0
208 JAYLINK_API int jaylink_device_get_host_interface(
209 const struct jaylink_device *dev,
210 enum jaylink_host_interface *iface)
212 if (!dev || !iface)
213 return JAYLINK_ERR_ARG;
215 *iface = dev->iface;
217 return JAYLINK_OK;
221 * Get the serial number of a device.
223 * @note This serial number is for enumeration purpose only and might differ
224 * from the real serial number of the device.
226 * @param[in] dev Device instance.
227 * @param[out] serial_number Serial number of the device on success, and
228 * undefined on failure.
230 * @retval JAYLINK_OK Success.
231 * @retval JAYLINK_ERR_ARG Invalid arguments.
232 * @retval JAYLINK_ERR_NOT_AVAILABLE Serial number is not available.
234 * @since 0.1.0
236 JAYLINK_API int jaylink_device_get_serial_number(
237 const struct jaylink_device *dev, uint32_t *serial_number)
239 if (!dev || !serial_number)
240 return JAYLINK_ERR_ARG;
242 if (!dev->has_serial_number)
243 return JAYLINK_ERR_NOT_AVAILABLE;
245 *serial_number = dev->serial_number;
247 return JAYLINK_OK;
251 * Get the USB address of a device.
253 * @note Identification of a device with the USB address is deprecated and the
254 * serial number should be used instead.
256 * @param[in] dev Device instance.
257 * @param[out] address USB address of the device on success, and undefined on
258 * failure.
260 * @retval JAYLINK_OK Success.
261 * @retval JAYLINK_ERR_ARG Invalid arguments.
262 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
263 * #JAYLINK_HIF_USB only.
265 * @see jaylink_device_get_serial_number()
267 * @since 0.1.0
269 JAYLINK_API int jaylink_device_get_usb_address(
270 const struct jaylink_device *dev,
271 enum jaylink_usb_address *address)
273 if (!dev || !address)
274 return JAYLINK_ERR_ARG;
276 if (dev->iface != JAYLINK_HIF_USB)
277 return JAYLINK_ERR_NOT_SUPPORTED;
279 #ifdef HAVE_LIBUSB
280 *address = dev->usb_address;
282 return JAYLINK_OK;
283 #else
284 return JAYLINK_ERR_NOT_SUPPORTED;
285 #endif
289 * Get the USB bus and port numbers of a device.
291 * @param[in] dev Device instance.
292 * @param[out] bus The bus number of the device on success and undefined on
293 * failure.
294 * @param[out] ports Newly allocated array which contains the port numbers on
295 * success and is undefined on failure. The array must be
296 * free'd by the caller.
297 * @param[out] length Length of the port array on success and undefined on
298 * failure.
300 * @retval JAYLINK_OK Success.
301 * @retval JAYLINK_ERR_ARG Invalid arguments.
302 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
303 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
304 * #JAYLINK_HIF_USB only.
306 * @since 0.2.0
308 JAYLINK_API int jaylink_device_get_usb_bus_ports(
309 const struct jaylink_device *dev, uint8_t *bus,
310 uint8_t **ports, size_t *length)
312 if (!dev || !bus || !ports || !length)
313 return JAYLINK_ERR_ARG;
315 if (dev->iface != JAYLINK_HIF_USB)
316 return JAYLINK_ERR_NOT_SUPPORTED;
318 #ifdef HAVE_LIBUSB
319 struct jaylink_context *ctx = dev->ctx;
320 int ret;
322 *ports = malloc(MAX_USB_PATH_DEPTH * sizeof(uint8_t));
324 if (!*ports) {
325 return JAYLINK_ERR_MALLOC;
328 ret = libusb_get_port_numbers(dev->usb_dev, *ports,
329 MAX_USB_PATH_DEPTH);
331 if (ret == LIBUSB_ERROR_OVERFLOW) {
332 log_err(ctx, "Failed to get port numbers: %s",
333 libusb_error_name(ret));
334 return JAYLINK_ERR_ARG;
337 *length = ret;
338 *bus = libusb_get_bus_number(dev->usb_dev);
340 return JAYLINK_OK;
341 #else
342 return JAYLINK_ERR_NOT_SUPPORTED;
343 #endif
347 * Get the IPv4 address string of a device.
349 * @param[in] dev Device instance.
350 * @param[out] address IPv4 address string in quad-dotted decimal format of the
351 * device on success and undefined on failure.
353 * @retval JAYLINK_OK Success.
354 * @retval JAYLINK_ERR_ARG Invalid arguments.
355 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
356 * #JAYLINK_HIF_TCP only.
358 * @since 0.2.0
360 JAYLINK_API int jaylink_device_get_ipv4_address(
361 const struct jaylink_device *dev, char *address)
363 if (!dev || !address)
364 return JAYLINK_ERR_ARG;
366 if (dev->iface != JAYLINK_HIF_TCP)
367 return JAYLINK_ERR_NOT_SUPPORTED;
369 memcpy(address, dev->ipv4_address, sizeof(dev->ipv4_address));
371 return JAYLINK_OK;
375 * Get the MAC address of a device.
377 * @param[in] dev Device instance.
378 * @param[out] address MAC address of the device on success and undefined on
379 * failure. The length of the MAC address is
380 * #JAYLINK_MAC_ADDRESS_LENGTH bytes.
382 * @retval JAYLINK_OK Success.
383 * @retval JAYLINK_ERR_ARG Invalid arguments.
384 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
385 * #JAYLINK_HIF_TCP only.
386 * @retval JAYLINK_ERR_NOT_AVAILABLE MAC address is not available.
388 * @since 0.2.0
390 JAYLINK_API int jaylink_device_get_mac_address(
391 const struct jaylink_device *dev, uint8_t *address)
393 if (!dev || !address)
394 return JAYLINK_ERR_ARG;
396 if (dev->iface != JAYLINK_HIF_TCP)
397 return JAYLINK_ERR_NOT_SUPPORTED;
399 if (!dev->has_mac_address)
400 return JAYLINK_ERR_NOT_AVAILABLE;
402 memcpy(address, dev->mac_address, sizeof(dev->mac_address));
404 return JAYLINK_OK;
408 * Get the hardware version of a device.
410 * @note The hardware type can not be obtained by this function, use
411 * jaylink_get_hardware_version() instead.
413 * @param[in] dev Device instance.
414 * @param[out] version Hardware version of the device on success and undefined
415 * on failure.
417 * @retval JAYLINK_OK Success.
418 * @retval JAYLINK_ERR_ARG Invalid arguments.
419 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
420 * #JAYLINK_HIF_TCP only.
421 * @retval JAYLINK_ERR_NOT_AVAILABLE Hardware version is not available.
423 * @since 0.2.0
425 JAYLINK_API int jaylink_device_get_hardware_version(
426 const struct jaylink_device *dev,
427 struct jaylink_hardware_version *version)
429 if (!dev || !version)
430 return JAYLINK_ERR_ARG;
432 if (dev->iface != JAYLINK_HIF_TCP)
433 return JAYLINK_ERR_NOT_SUPPORTED;
435 if (!dev->has_hw_version)
436 return JAYLINK_ERR_NOT_AVAILABLE;
438 *version = dev->hw_version;
440 return JAYLINK_OK;
444 * Get the product name of a device.
446 * @param[in] dev Device instance.
447 * @param[out] name Product name of the device on success and undefined on
448 * failure. The maximum length of the product name is
449 * #JAYLINK_PRODUCT_NAME_MAX_LENGTH bytes.
451 * @retval JAYLINK_OK Success.
452 * @retval JAYLINK_ERR_ARG Invalid arguments.
453 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
454 * #JAYLINK_HIF_TCP only.
455 * @retval JAYLINK_ERR_NOT_AVAILABLE Product name is not available.
457 * @since 0.2.0
459 JAYLINK_API int jaylink_device_get_product_name(
460 const struct jaylink_device *dev, char *name)
462 if (!dev || !name)
463 return JAYLINK_ERR_ARG;
465 if (dev->iface != JAYLINK_HIF_TCP)
466 return JAYLINK_ERR_NOT_SUPPORTED;
468 if (!dev->has_product_name)
469 return JAYLINK_ERR_NOT_AVAILABLE;
471 memcpy(name, dev->product_name, sizeof(dev->product_name));
473 return JAYLINK_OK;
477 * Get the nickname of a device.
479 * @param[in] dev Device instance.
480 * @param[out] nickname Nickname of the device on success and undefined on
481 * failure. The maximum length of the nickname is
482 * #JAYLINK_NICKNAME_MAX_LENGTH bytes.
484 * @retval JAYLINK_OK Success.
485 * @retval JAYLINK_ERR_ARG Invalid arguments.
486 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
487 * #JAYLINK_HIF_TCP only.
488 * @retval JAYLINK_ERR_NOT_AVAILABLE Nickname is not available.
490 * @since 0.2.0
492 JAYLINK_API int jaylink_device_get_nickname(const struct jaylink_device *dev,
493 char *nickname)
495 if (!dev || !nickname)
496 return JAYLINK_ERR_ARG;
498 if (dev->iface != JAYLINK_HIF_TCP)
499 return JAYLINK_ERR_NOT_SUPPORTED;
501 if (!dev->has_nickname)
502 return JAYLINK_ERR_NOT_AVAILABLE;
504 memcpy(nickname, dev->nickname, sizeof(dev->nickname));
506 return JAYLINK_OK;
510 * Increment the reference count of a device.
512 * @param[in,out] dev Device instance.
514 * @return The given device instance on success, or NULL on invalid argument.
516 * @since 0.1.0
518 JAYLINK_API struct jaylink_device *jaylink_ref_device(
519 struct jaylink_device *dev)
521 if (!dev)
522 return NULL;
524 dev->ref_count++;
526 return dev;
530 * Decrement the reference count of a device.
532 * @param[in,out] dev Device instance.
534 * @since 0.1.0
536 JAYLINK_API void jaylink_unref_device(struct jaylink_device *dev)
538 struct jaylink_context *ctx;
540 if (!dev)
541 return;
543 dev->ref_count--;
545 if (!dev->ref_count) {
546 ctx = dev->ctx;
547 ctx->devs = list_remove(dev->ctx->devs, dev);
549 if (dev->iface == JAYLINK_HIF_USB) {
550 #ifdef HAVE_LIBUSB
551 log_dbg(ctx, "Device destroyed (bus:address = "
552 "%03u:%03u)",
553 libusb_get_bus_number(dev->usb_dev),
554 libusb_get_device_address(dev->usb_dev));
556 libusb_unref_device(dev->usb_dev);
557 #endif
558 } else if (dev->iface == JAYLINK_HIF_TCP) {
559 log_dbg(ctx, "Device destroyed (IPv4 address = %s)",
560 dev->ipv4_address);
561 } else {
562 log_err(ctx, "BUG: Invalid host interface: %u",
563 dev->iface);
566 free(dev);
570 static struct jaylink_device_handle *allocate_device_handle(
571 struct jaylink_device *dev)
573 struct jaylink_device_handle *devh;
575 devh = malloc(sizeof(struct jaylink_device_handle));
577 if (!devh)
578 return NULL;
580 devh->dev = jaylink_ref_device(dev);
582 return devh;
585 static void free_device_handle(struct jaylink_device_handle *devh)
587 jaylink_unref_device(devh->dev);
588 free(devh);
592 * Open a device.
594 * @param[in,out] dev Device instance.
595 * @param[out] devh Newly allocated handle for the opened device on success,
596 * and undefined on failure.
598 * @retval JAYLINK_OK Success.
599 * @retval JAYLINK_ERR_ARG Invalid arguments.
600 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
601 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
602 * @retval JAYLINK_ERR_IO Input/output error.
603 * @retval JAYLINK_ERR Other error conditions.
605 * @since 0.1.0
607 JAYLINK_API int jaylink_open(struct jaylink_device *dev,
608 struct jaylink_device_handle **devh)
610 int ret;
611 struct jaylink_device_handle *handle;
613 if (!dev || !devh)
614 return JAYLINK_ERR_ARG;
616 handle = allocate_device_handle(dev);
618 if (!handle) {
619 log_err(dev->ctx, "Device handle malloc failed");
620 return JAYLINK_ERR_MALLOC;
623 ret = transport_open(handle);
625 if (ret != JAYLINK_OK) {
626 free_device_handle(handle);
627 return ret;
630 *devh = handle;
632 return JAYLINK_OK;
636 * Close a device.
638 * @param[in,out] devh Device instance.
640 * @retval JAYLINK_OK Success.
641 * @retval JAYLINK_ERR_ARG Invalid arguments.
642 * @retval JAYLINK_ERR Other error conditions.
644 * @since 0.1.0
646 JAYLINK_API int jaylink_close(struct jaylink_device_handle *devh)
648 int ret;
650 if (!devh)
651 return JAYLINK_ERR_ARG;
653 ret = transport_close(devh);
654 free_device_handle(devh);
656 return ret;
660 * Get the device instance from a device handle.
662 * @note The reference count of the device instance is not increased.
664 * @param[in] devh Device handle.
666 * @return The device instance on success, or NULL on invalid argument.
668 * @since 0.1.0
670 JAYLINK_API struct jaylink_device *jaylink_get_device(
671 struct jaylink_device_handle *devh)
673 if (!devh)
674 return NULL;
676 return devh->dev;
680 * Retrieve the firmware version of a device.
682 * @param[in,out] devh Device handle.
683 * @param[out] version Newly allocated string which contains the firmware
684 * version on success, and undefined if @p length is zero
685 * or on failure. The string is null-terminated and must be
686 * free'd by the caller.
687 * @param[out] length Length of the firmware version string including trailing
688 * null-terminator on success, and undefined on failure.
689 * Zero if no firmware version string is available.
691 * @retval JAYLINK_OK Success.
692 * @retval JAYLINK_ERR_ARG Invalid arguments.
693 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
694 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
695 * @retval JAYLINK_ERR_IO Input/output error.
696 * @retval JAYLINK_ERR Other error conditions.
698 * @since 0.1.0
700 JAYLINK_API int jaylink_get_firmware_version(
701 struct jaylink_device_handle *devh, char **version,
702 size_t *length)
704 int ret;
705 struct jaylink_context *ctx;
706 uint8_t buf[2];
707 uint16_t dummy;
708 char *tmp;
710 if (!devh || !version || !length)
711 return JAYLINK_ERR_ARG;
713 ctx = devh->dev->ctx;
714 ret = transport_start_write_read(devh, 1, 2, true);
716 if (ret != JAYLINK_OK) {
717 log_err(ctx, "transport_start_write_read() failed: %s",
718 jaylink_strerror(ret));
719 return ret;
722 buf[0] = CMD_GET_VERSION;
724 ret = transport_write(devh, buf, 1);
726 if (ret != JAYLINK_OK) {
727 log_err(ctx, "transport_write() failed: %s",
728 jaylink_strerror(ret));
729 return ret;
732 ret = transport_read(devh, buf, 2);
734 if (ret != JAYLINK_OK) {
735 log_err(ctx, "transport_read() failed: %s",
736 jaylink_strerror(ret));
737 return ret;
740 dummy = buffer_get_u16(buf, 0);
741 *length = dummy;
743 if (!dummy)
744 return JAYLINK_OK;
746 ret = transport_start_read(devh, dummy);
748 if (ret != JAYLINK_OK) {
749 log_err(ctx, "transport_start_read() failed: %s",
750 jaylink_strerror(ret));
751 return ret;
754 tmp = malloc(dummy);
756 if (!tmp) {
757 log_err(ctx, "Firmware version string malloc failed");
758 return JAYLINK_ERR_MALLOC;
761 ret = transport_read(devh, (uint8_t *)tmp, dummy);
763 if (ret != JAYLINK_OK) {
764 log_err(ctx, "transport_read() failed: %s",
765 jaylink_strerror(ret));
766 free(tmp);
767 return ret;
770 /* Last byte is reserved for null-terminator. */
771 tmp[dummy - 1] = 0;
772 *version = tmp;
774 return JAYLINK_OK;
778 * Retrieve the hardware information of a device.
780 * @note This function must only be used if the device has the
781 * #JAYLINK_DEV_CAP_GET_HW_INFO capability.
783 * @param[in,out] devh Device handle.
784 * @param[in] mask A bit field where each set bit represents hardware
785 * information to request. See #jaylink_hardware_info for a
786 * description of the hardware information and their bit
787 * positions.
788 * @param[out] info Array to store the hardware information on success. Its
789 * content is undefined on failure. The array must be large
790 * enough to contain at least as many elements as bits set in
791 * @a mask.
793 * @retval JAYLINK_OK Success.
794 * @retval JAYLINK_ERR_ARG Invalid arguments.
795 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
796 * @retval JAYLINK_ERR_IO Input/output error.
797 * @retval JAYLINK_ERR Other error conditions.
799 * @since 0.1.0
801 JAYLINK_API int jaylink_get_hardware_info(struct jaylink_device_handle *devh,
802 uint32_t mask, uint32_t *info)
804 int ret;
805 struct jaylink_context *ctx;
806 uint8_t buf[5];
807 unsigned int num;
808 unsigned int length;
810 if (!devh || !mask || !info)
811 return JAYLINK_ERR_ARG;
813 ctx = devh->dev->ctx;
814 num = 0;
816 for (unsigned int i = 0; i < 32; i++) {
817 if (mask & (1 << i))
818 num++;
821 length = num * sizeof(uint32_t);
823 ret = transport_start_write_read(devh, 5, length, true);
825 if (ret != JAYLINK_OK) {
826 log_err(ctx, "transport_start_write_read() failed: %s",
827 jaylink_strerror(ret));
828 return ret;
831 buf[0] = CMD_GET_HW_INFO;
832 buffer_set_u32(buf, mask, 1);
834 ret = transport_write(devh, buf, 5);
836 if (ret != JAYLINK_OK) {
837 log_err(ctx, "transport_write() failed: %s",
838 jaylink_strerror(ret));
839 return ret;
842 ret = transport_read(devh, (uint8_t *)info, length);
844 if (ret != JAYLINK_OK) {
845 log_err(ctx, "transport_read() failed: %s",
846 jaylink_strerror(ret));
847 return ret;
850 for (unsigned int i = 0; i < num; i++)
851 info[i] = buffer_get_u32((uint8_t *)info,
852 i * sizeof(uint32_t));
854 return JAYLINK_OK;
858 * Retrieve the counter values of a device.
860 * @note This function must only be used if the device has the
861 * #JAYLINK_DEV_CAP_GET_COUNTERS capability.
863 * @param[in,out] devh Device handle.
864 * @param[in] mask A bit field where each set bit represents a counter value to
865 * request. See #jaylink_counter for a description of the
866 * counters and their bit positions.
867 * @param[out] values Array to store the counter values on success. Its content
868 * is undefined on failure. The array must be large enough
869 * to contain at least as many elements as bits set in @p
870 * mask.
872 * @retval JAYLINK_OK Success.
873 * @retval JAYLINK_ERR_ARG Invalid arguments.
874 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
875 * @retval JAYLINK_ERR_IO Input/output error.
876 * @retval JAYLINK_ERR Other error conditions.
878 * @since 0.2.0
880 JAYLINK_API int jaylink_get_counters(struct jaylink_device_handle *devh,
881 uint32_t mask, uint32_t *values)
883 int ret;
884 struct jaylink_context *ctx;
885 uint8_t buf[5];
886 unsigned int num;
887 unsigned int length;
889 if (!devh || !mask || !values)
890 return JAYLINK_ERR_ARG;
892 ctx = devh->dev->ctx;
893 num = 0;
895 for (unsigned int i = 0; i < 32; i++) {
896 if (mask & (1 << i))
897 num++;
900 length = num * sizeof(uint32_t);
901 ret = transport_start_write_read(devh, 5, length, true);
903 if (ret != JAYLINK_OK) {
904 log_err(ctx, "transport_start_write_read() failed: %s",
905 jaylink_strerror(ret));
906 return ret;
909 buf[0] = CMD_GET_COUNTERS;
910 buffer_set_u32(buf, mask, 1);
912 ret = transport_write(devh, buf, 5);
914 if (ret != JAYLINK_OK) {
915 log_err(ctx, "transport_write() failed: %s",
916 jaylink_strerror(ret));
917 return ret;
920 ret = transport_read(devh, (uint8_t *)values, length);
922 if (ret != JAYLINK_OK) {
923 log_err(ctx, "transport_read() failed: %s",
924 jaylink_strerror(ret));
925 return ret;
928 for (unsigned int i = 0; i < num; i++)
929 values[i] = buffer_get_u32((uint8_t *)values,
930 i * sizeof(uint32_t));
932 return JAYLINK_OK;
936 * Retrieve the hardware version of a device.
938 * @note This function must only be used if the device has the
939 * #JAYLINK_DEV_CAP_GET_HW_VERSION capability.
941 * @warning This function may return a value for @p version where
942 * #jaylink_hardware_version::type is not covered by
943 * #jaylink_hardware_type.
945 * @param[in,out] devh Device handle.
946 * @param[out] version Hardware version on success, and undefined on failure.
948 * @retval JAYLINK_OK Success.
949 * @retval JAYLINK_ERR_ARG Invalid arguments.
950 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
951 * @retval JAYLINK_ERR_IO Input/output error.
952 * @retval JAYLINK_ERR Other error conditions.
954 * @since 0.1.0
956 JAYLINK_API int jaylink_get_hardware_version(
957 struct jaylink_device_handle *devh,
958 struct jaylink_hardware_version *version)
960 int ret;
961 struct jaylink_context *ctx;
962 uint8_t buf[4];
963 uint32_t tmp;
965 if (!devh || !version)
966 return JAYLINK_ERR_ARG;
968 ctx = devh->dev->ctx;
969 ret = transport_start_write_read(devh, 1, 4, true);
971 if (ret != JAYLINK_OK) {
972 log_err(ctx, "transport_start_write_read() failed: %s",
973 jaylink_strerror(ret));
974 return ret;
977 buf[0] = CMD_GET_HW_VERSION;
979 ret = transport_write(devh, buf, 1);
981 if (ret != JAYLINK_OK) {
982 log_err(ctx, "transport_write() failed: %s",
983 jaylink_strerror(ret));
984 return ret;
987 ret = transport_read(devh, buf, 4);
989 if (ret != JAYLINK_OK) {
990 log_err(ctx, "transport_read() failed: %s",
991 jaylink_strerror(ret));
992 return ret;
995 tmp = buffer_get_u32(buf, 0);
997 version->type = (tmp / 1000000) % 100;
998 version->major = (tmp / 10000) % 100;
999 version->minor = (tmp / 100) % 100;
1000 version->revision = tmp % 100;
1002 return JAYLINK_OK;
1006 * Retrieve the hardware status of a device.
1008 * @param[in,out] devh Device handle.
1009 * @param[out] status Hardware status on success, and undefined on failure.
1011 * @retval JAYLINK_OK Success.
1012 * @retval JAYLINK_ERR_ARG Invalid arguments.
1013 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1014 * @retval JAYLINK_ERR_IO Input/output error.
1015 * @retval JAYLINK_ERR Other error conditions.
1017 * @since 0.1.0
1019 JAYLINK_API int jaylink_get_hardware_status(struct jaylink_device_handle *devh,
1020 struct jaylink_hardware_status *status)
1022 int ret;
1023 struct jaylink_context *ctx;
1024 uint8_t buf[8];
1026 if (!devh || !status)
1027 return JAYLINK_ERR_ARG;
1029 ctx = devh->dev->ctx;
1030 ret = transport_start_write_read(devh, 1, 8, true);
1032 if (ret != JAYLINK_OK) {
1033 log_err(ctx, "transport_start_write_read() failed: %s",
1034 jaylink_strerror(ret));
1035 return ret;
1038 buf[0] = CMD_GET_HW_STATUS;
1040 ret = transport_write(devh, buf, 1);
1042 if (ret != JAYLINK_OK) {
1043 log_err(ctx, "transport_write() failed: %s",
1044 jaylink_strerror(ret));
1045 return ret;
1048 ret = transport_read(devh, buf, 8);
1050 if (ret != JAYLINK_OK) {
1051 log_err(ctx, "transport_read() failed: %s",
1052 jaylink_strerror(ret));
1053 return ret;
1056 status->target_voltage = buffer_get_u16(buf, 0);
1057 status->tck = buf[2];
1058 status->tdi = buf[3];
1059 status->tdo = buf[4];
1060 status->tms = buf[5];
1061 status->tres = buf[6];
1062 status->trst = buf[7];
1064 return JAYLINK_OK;
1068 * Retrieve the capabilities of a device.
1070 * The capabilities are stored in a 32-bit bit array consisting of
1071 * #JAYLINK_DEV_CAPS_SIZE bytes where each individual bit represents a
1072 * capability. The first bit of this array is the least significant bit of the
1073 * first byte and the following bits are sequentially numbered in order of
1074 * increasing bit significance and byte index. A set bit indicates a supported
1075 * capability. See #jaylink_device_capability for a description of the
1076 * capabilities and their bit positions.
1078 * @param[in,out] devh Device handle.
1079 * @param[out] caps Buffer to store capabilities on success. Its content is
1080 * undefined on failure. The buffer must be large enough to
1081 * contain at least #JAYLINK_DEV_CAPS_SIZE bytes.
1083 * @retval JAYLINK_OK Success.
1084 * @retval JAYLINK_ERR_ARG Invalid arguments.
1085 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1086 * @retval JAYLINK_ERR_IO Input/output error.
1087 * @retval JAYLINK_ERR Other error conditions.
1089 * @see jaylink_get_extended_caps()
1090 * @see jaylink_has_cap()
1092 * @since 0.1.0
1094 JAYLINK_API int jaylink_get_caps(struct jaylink_device_handle *devh,
1095 uint8_t *caps)
1097 int ret;
1098 struct jaylink_context *ctx;
1099 uint8_t buf[1];
1101 if (!devh || !caps)
1102 return JAYLINK_ERR_ARG;
1104 ctx = devh->dev->ctx;
1105 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CAPS_SIZE, true);
1107 if (ret != JAYLINK_OK) {
1108 log_err(ctx, "transport_start_write_read() failed: %s",
1109 jaylink_strerror(ret));
1110 return ret;
1113 buf[0] = CMD_GET_CAPS;
1115 ret = transport_write(devh, buf, 1);
1117 if (ret != JAYLINK_OK) {
1118 log_err(ctx, "transport_write() failed: %s",
1119 jaylink_strerror(ret));
1120 return ret;
1123 ret = transport_read(devh, caps, JAYLINK_DEV_CAPS_SIZE);
1125 if (ret != JAYLINK_OK) {
1126 log_err(ctx, "transport_read() failed: %s",
1127 jaylink_strerror(ret));
1128 return ret;
1131 return JAYLINK_OK;
1135 * Retrieve the extended capabilities of a device.
1137 * The extended capabilities are stored in a 256-bit bit array consisting of
1138 * #JAYLINK_DEV_EXT_CAPS_SIZE bytes. See jaylink_get_caps() for a further
1139 * description of how the capabilities are represented in this bit array. For a
1140 * description of the capabilities and their bit positions, see
1141 * #jaylink_device_capability.
1143 * @note This function must only be used if the device has the
1144 * #JAYLINK_DEV_CAP_GET_EXT_CAPS capability.
1146 * @param[in,out] devh Device handle.
1147 * @param[out] caps Buffer to store capabilities on success. Its content is
1148 * undefined on failure. The buffer must be large enough to
1149 * contain at least #JAYLINK_DEV_EXT_CAPS_SIZE bytes.
1151 * @retval JAYLINK_OK Success.
1152 * @retval JAYLINK_ERR_ARG Invalid arguments.
1153 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1154 * @retval JAYLINK_ERR_IO Input/output error.
1155 * @retval JAYLINK_ERR Other error conditions.
1157 * @see jaylink_get_caps()
1159 * @since 0.1.0
1161 JAYLINK_API int jaylink_get_extended_caps(struct jaylink_device_handle *devh,
1162 uint8_t *caps)
1164 int ret;
1165 struct jaylink_context *ctx;
1166 uint8_t buf[1];
1168 if (!devh || !caps)
1169 return JAYLINK_ERR_ARG;
1171 ctx = devh->dev->ctx;
1172 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_EXT_CAPS_SIZE,
1173 true);
1175 if (ret != JAYLINK_OK) {
1176 log_err(ctx, "transport_start_write_read() failed: %s",
1177 jaylink_strerror(ret));
1178 return ret;
1181 buf[0] = CMD_GET_EXT_CAPS;
1183 ret = transport_write(devh, buf, 1);
1185 if (ret != JAYLINK_OK) {
1186 log_err(ctx, "transport_write() failed: %s",
1187 jaylink_strerror(ret));
1188 return ret;
1191 ret = transport_read(devh, caps, JAYLINK_DEV_EXT_CAPS_SIZE);
1193 if (ret != JAYLINK_OK) {
1194 log_err(ctx, "transport_read() failed: %s",
1195 jaylink_strerror(ret));
1196 return ret;
1199 return JAYLINK_OK;
1203 * Retrieve the size of free memory of a device.
1205 * @note This function must only be used if the device has the
1206 * #JAYLINK_DEV_CAP_GET_FREE_MEMORY capability.
1208 * @param[in,out] devh Device handle.
1209 * @param[out] size Size of free memory in bytes on success, and undefined on
1210 * failure.
1212 * @retval JAYLINK_OK Success.
1213 * @retval JAYLINK_ERR_ARG Invalid arguments.
1214 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1215 * @retval JAYLINK_ERR_IO Input/output error.
1216 * @retval JAYLINK_ERR Other error conditions.
1218 * @since 0.1.0
1220 JAYLINK_API int jaylink_get_free_memory(struct jaylink_device_handle *devh,
1221 uint32_t *size)
1223 int ret;
1224 struct jaylink_context *ctx;
1225 uint8_t buf[4];
1227 if (!devh || !size)
1228 return JAYLINK_ERR_ARG;
1230 ctx = devh->dev->ctx;
1231 ret = transport_start_write_read(devh, 1, 4, true);
1233 if (ret != JAYLINK_OK) {
1234 log_err(ctx, "transport_start_write_read() failed: %s",
1235 jaylink_strerror(ret));
1236 return ret;
1239 buf[0] = CMD_GET_FREE_MEMORY;
1241 ret = transport_write(devh, buf, 1);
1243 if (ret != JAYLINK_OK) {
1244 log_err(ctx, "transport_write() failed: %s",
1245 jaylink_strerror(ret));
1246 return ret;
1249 ret = transport_read(devh, buf, 4);
1251 if (ret != JAYLINK_OK) {
1252 log_err(ctx, "transport_read() failed: %s",
1253 jaylink_strerror(ret));
1254 return ret;
1257 *size = buffer_get_u32(buf, 0);
1259 return JAYLINK_OK;
1263 * Read the raw configuration data of a device.
1265 * @note This function must only be used if the device has the
1266 * #JAYLINK_DEV_CAP_READ_CONFIG capability.
1268 * @param[in,out] devh Device handle.
1269 * @param[out] config Buffer to store configuration data on success. Its
1270 * content is undefined on failure. The buffer must be large
1271 * enough to contain at least
1272 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1274 * @retval JAYLINK_OK Success.
1275 * @retval JAYLINK_ERR_ARG Invalid arguments.
1276 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1277 * @retval JAYLINK_ERR_IO Input/output error.
1278 * @retval JAYLINK_ERR Other error conditions.
1280 * @since 0.1.0
1282 JAYLINK_API int jaylink_read_raw_config(struct jaylink_device_handle *devh,
1283 uint8_t *config)
1285 int ret;
1286 struct jaylink_context *ctx;
1287 uint8_t buf[1];
1289 if (!devh || !config)
1290 return JAYLINK_ERR_ARG;
1292 ctx = devh->dev->ctx;
1293 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CONFIG_SIZE,
1294 true);
1296 if (ret != JAYLINK_OK) {
1297 log_err(ctx, "transport_start_write_read() failed: %s",
1298 jaylink_strerror(ret));
1299 return ret;
1302 buf[0] = CMD_READ_CONFIG;
1304 ret = transport_write(devh, buf, 1);
1306 if (ret != JAYLINK_OK) {
1307 log_err(ctx, "transport_write() failed: %s",
1308 jaylink_strerror(ret));
1309 return ret;
1312 ret = transport_read(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1314 if (ret != JAYLINK_OK) {
1315 log_err(ctx, "transport_read() failed: %s",
1316 jaylink_strerror(ret));
1317 return ret;
1320 return JAYLINK_OK;
1324 * Write the raw configuration data of a device.
1326 * @note This function must only be used if the device has the
1327 * #JAYLINK_DEV_CAP_WRITE_CONFIG capability.
1329 * @param[in,out] devh Device handle.
1330 * @param[in] config Buffer to write configuration data from. The size of the
1331 * configuration data is expected to be
1332 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1334 * @retval JAYLINK_OK Success.
1335 * @retval JAYLINK_ERR_ARG Invalid arguments.
1336 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1337 * @retval JAYLINK_ERR_IO Input/output error.
1338 * @retval JAYLINK_ERR Other error conditions.
1340 * @since 0.1.0
1342 JAYLINK_API int jaylink_write_raw_config(struct jaylink_device_handle *devh,
1343 const uint8_t *config)
1345 int ret;
1346 struct jaylink_context *ctx;
1347 uint8_t buf[1];
1349 if (!devh || !config)
1350 return JAYLINK_ERR_ARG;
1352 ctx = devh->dev->ctx;
1353 ret = transport_start_write(devh, 1 + JAYLINK_DEV_CONFIG_SIZE, true);
1355 if (ret != JAYLINK_OK) {
1356 log_err(ctx, "transport_start_write() failed: %s",
1357 jaylink_strerror(ret));
1358 return ret;
1361 buf[0] = CMD_WRITE_CONFIG;
1363 ret = transport_write(devh, buf, 1);
1365 if (ret != JAYLINK_OK) {
1366 log_err(ctx, "transport_write() failed: %s",
1367 jaylink_strerror(ret));
1368 return ret;
1371 ret = transport_write(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1373 if (ret != JAYLINK_OK) {
1374 log_err(ctx, "transport_write() failed: %s",
1375 jaylink_strerror(ret));
1376 return ret;
1379 return JAYLINK_OK;
1382 static void parse_conn_table(struct jaylink_connection *conns,
1383 const uint8_t *buffer, uint16_t num, uint16_t entry_size)
1385 size_t offset;
1386 struct in_addr in;
1388 offset = 0;
1390 for (unsigned int i = 0; i < num; i++) {
1391 conns[i].pid = buffer_get_u32(buffer, offset);
1393 in.s_addr = buffer_get_u32(buffer, offset + 4);
1395 * Use inet_ntoa() instead of inet_ntop() because the latter
1396 * requires at least Windows Vista.
1398 strcpy(conns[i].hid, inet_ntoa(in));
1400 conns[i].iid = buffer[offset + 8];
1401 conns[i].cid = buffer[offset + 9];
1402 conns[i].handle = buffer_get_u16(buffer, offset + 10);
1403 conns[i].timestamp = buffer_get_u32(buffer, offset + 12);
1404 offset = offset + entry_size;
1408 static bool _inet_pton(const char *str, struct in_addr *in)
1410 #ifdef _WIN32
1411 int ret;
1412 struct sockaddr_in sock_in;
1413 int length;
1415 length = sizeof(sock_in);
1418 * Use WSAStringToAddress() instead of inet_pton() because the latter
1419 * requires at least Windows Vista.
1421 ret = WSAStringToAddress((LPTSTR)str, AF_INET, NULL,
1422 (LPSOCKADDR)&sock_in, &length);
1424 if (ret != 0)
1425 return false;
1427 *in = sock_in.sin_addr;
1428 #else
1429 if (inet_pton(AF_INET, str, in) != 1)
1430 return false;
1431 #endif
1433 return true;
1437 * Register a connection on a device.
1439 * A connection can be registered by using 0 as handle. Additional information
1440 * about the connection can be attached whereby the timestamp is a read-only
1441 * value and therefore ignored for registration. On success, a new handle
1442 * greater than 0 is obtained from the device.
1444 * However, if an obtained handle does not appear in the list of device
1445 * connections, the connection was not registered because the maximum number of
1446 * connections on the device is reached.
1448 * @note This function must only be used if the device has the
1449 * #JAYLINK_DEV_CAP_REGISTER capability.
1451 * Example code:
1452 * @code{.c}
1453 * static bool register_connection(struct jaylink_device_handle *devh,
1454 * struct jaylink_connection *conn)
1456 * int ret;
1457 * struct jaylink_connection conns[JAYLINK_MAX_CONNECTIONS];
1458 * bool found_handle;
1459 * size_t count;
1461 * conn->handle = 0;
1462 * conn->pid = 0;
1463 * strcpy(conn->hid, "0.0.0.0");
1464 * conn->iid = 0;
1465 * conn->cid = 0;
1467 * ret = jaylink_register(devh, conn, conns, &count);
1469 * if (ret != JAYLINK_OK) {
1470 * printf("jaylink_register() failed: %s.\n",
1471 * jaylink_strerror(ret));
1472 * return false;
1475 * found_handle = false;
1477 * for (size_t i = 0; i < count; i++) {
1478 * if (conns[i].handle == conn->handle) {
1479 * found_handle = true;
1480 * break;
1484 * if (!found_handle) {
1485 * printf("Maximum number of connections reached.\n");
1486 * return false;
1489 * printf("Connection successfully registered.\n");
1491 * return true;
1493 * @endcode
1495 * @param[in,out] devh Device handle.
1496 * @param[in,out] connection Connection to register on the device.
1497 * @param[out] connections Array to store device connections on success.
1498 * Its content is undefined on failure. The array must
1499 * be large enough to contain at least
1500 * #JAYLINK_MAX_CONNECTIONS elements.
1501 * @param[out] count Number of device connections on success, and undefined on
1502 * failure.
1504 * @retval JAYLINK_OK Success.
1505 * @retval JAYLINK_ERR_ARG Invalid arguments.
1506 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1507 * @retval JAYLINK_ERR_PROTO Protocol violation.
1508 * @retval JAYLINK_ERR_IO Input/output error.
1509 * @retval JAYLINK_ERR Other error conditions.
1511 * @see jaylink_unregister()
1513 * @since 0.1.0
1515 JAYLINK_API int jaylink_register(struct jaylink_device_handle *devh,
1516 struct jaylink_connection *connection,
1517 struct jaylink_connection *connections, size_t *count)
1519 int ret;
1520 struct jaylink_context *ctx;
1521 uint8_t buf[REG_MAX_SIZE];
1522 uint16_t handle;
1523 uint16_t num;
1524 uint16_t entry_size;
1525 uint32_t size;
1526 uint32_t table_size;
1527 uint16_t info_size;
1528 struct in_addr in;
1530 if (!devh || !connection || !connections || !count)
1531 return JAYLINK_ERR_ARG;
1533 ctx = devh->dev->ctx;
1535 buf[0] = CMD_REGISTER;
1536 buf[1] = REG_CMD_REGISTER;
1537 buffer_set_u32(buf, connection->pid, 2);
1539 if (!_inet_pton(connection->hid, &in))
1540 return JAYLINK_ERR_ARG;
1542 buffer_set_u32(buf, in.s_addr, 6);
1544 buf[10] = connection->iid;
1545 buf[11] = connection->cid;
1546 buffer_set_u16(buf, connection->handle, 12);
1548 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1550 if (ret != JAYLINK_OK) {
1551 log_err(ctx, "transport_start_write_read() failed: %s",
1552 jaylink_strerror(ret));
1553 return ret;
1556 ret = transport_write(devh, buf, 14);
1558 if (ret != JAYLINK_OK) {
1559 log_err(ctx, "transport_write() failed: %s",
1560 jaylink_strerror(ret));
1561 return ret;
1564 ret = transport_read(devh, buf, REG_MIN_SIZE);
1566 if (ret != JAYLINK_OK) {
1567 log_err(ctx, "transport_read() failed: %s",
1568 jaylink_strerror(ret));
1569 return ret;
1572 handle = buffer_get_u16(buf, 0);
1573 num = buffer_get_u16(buf, 2);
1574 entry_size = buffer_get_u16(buf, 4);
1575 info_size = buffer_get_u16(buf, 6);
1577 if (num > JAYLINK_MAX_CONNECTIONS) {
1578 log_err(ctx, "Maximum number of device connections exceeded: "
1579 "%u", num);
1580 return JAYLINK_ERR_PROTO;
1583 if (entry_size != REG_CONN_INFO_SIZE) {
1584 log_err(ctx, "Invalid connection entry size: %u bytes",
1585 entry_size);
1586 return JAYLINK_ERR_PROTO;
1589 table_size = num * entry_size;
1590 size = REG_HEADER_SIZE + table_size + info_size;
1592 if (size > REG_MAX_SIZE) {
1593 log_err(ctx, "Maximum registration information size exceeded: "
1594 "%u bytes", size);
1595 return JAYLINK_ERR_PROTO;
1598 if (size > REG_MIN_SIZE) {
1599 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1601 if (ret != JAYLINK_OK) {
1602 log_err(ctx, "transport_start_read() failed: %s",
1603 jaylink_strerror(ret));
1604 return JAYLINK_ERR;
1607 ret = transport_read(devh, buf + REG_MIN_SIZE,
1608 size - REG_MIN_SIZE);
1610 if (ret != JAYLINK_OK) {
1611 log_err(ctx, "transport_read() failed: %s",
1612 jaylink_strerror(ret));
1613 return JAYLINK_ERR;
1617 if (!handle) {
1618 log_err(ctx, "Obtained invalid connection handle");
1619 return JAYLINK_ERR_PROTO;
1622 connection->handle = handle;
1623 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1625 *count = num;
1627 return JAYLINK_OK;
1631 * Unregister a connection from a device.
1633 * @note This function must only be used if the device has the
1634 * #JAYLINK_DEV_CAP_REGISTER capability.
1636 * @param[in,out] devh Device handle.
1637 * @param[in,out] connection Connection to unregister from the device.
1638 * @param[out] connections Array to store device connections on success.
1639 * Its content is undefined on failure. The array must
1640 * be large enough to contain at least
1641 * #JAYLINK_MAX_CONNECTIONS elements.
1642 * @param[out] count Number of device connections on success, and undefined on
1643 * failure.
1645 * @retval JAYLINK_OK Success.
1646 * @retval JAYLINK_ERR_ARG Invalid arguments.
1647 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1648 * @retval JAYLINK_ERR_PROTO Protocol violation.
1649 * @retval JAYLINK_ERR_IO Input/output error.
1650 * @retval JAYLINK_ERR Other error conditions.
1652 * @see jaylink_register()
1654 * @since 0.1.0
1656 JAYLINK_API int jaylink_unregister(struct jaylink_device_handle *devh,
1657 const struct jaylink_connection *connection,
1658 struct jaylink_connection *connections, size_t *count)
1660 int ret;
1661 struct jaylink_context *ctx;
1662 uint8_t buf[REG_MAX_SIZE];
1663 uint16_t num;
1664 uint16_t entry_size;
1665 uint32_t size;
1666 uint32_t table_size;
1667 uint16_t info_size;
1668 struct in_addr in;
1670 if (!devh || !connection || !connections || !count)
1671 return JAYLINK_ERR_ARG;
1673 ctx = devh->dev->ctx;
1675 buf[0] = CMD_REGISTER;
1676 buf[1] = REG_CMD_UNREGISTER;
1677 buffer_set_u32(buf, connection->pid, 2);
1679 if (!_inet_pton(connection->hid, &in))
1680 return JAYLINK_ERR_ARG;
1682 buffer_set_u32(buf, in.s_addr, 6);
1684 buf[10] = connection->iid;
1685 buf[11] = connection->cid;
1686 buffer_set_u16(buf, connection->handle, 12);
1688 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1690 if (ret != JAYLINK_OK) {
1691 log_err(ctx, "transport_start_write_read() failed: %s",
1692 jaylink_strerror(ret));
1693 return ret;
1696 ret = transport_write(devh, buf, 14);
1698 if (ret != JAYLINK_OK) {
1699 log_err(ctx, "transport_write() failed: %s",
1700 jaylink_strerror(ret));
1701 return ret;
1704 ret = transport_read(devh, buf, REG_MIN_SIZE);
1706 if (ret != JAYLINK_OK) {
1707 log_err(ctx, "transport_read() failed: %s",
1708 jaylink_strerror(ret));
1709 return ret;
1712 num = buffer_get_u16(buf, 2);
1713 entry_size = buffer_get_u16(buf, 4);
1714 info_size = buffer_get_u16(buf, 6);
1716 if (num > JAYLINK_MAX_CONNECTIONS) {
1717 log_err(ctx, "Maximum number of device connections exceeded: "
1718 "%u", num);
1719 return JAYLINK_ERR_PROTO;
1722 if (entry_size != REG_CONN_INFO_SIZE) {
1723 log_err(ctx, "Invalid connection entry size: %u bytes",
1724 entry_size);
1725 return JAYLINK_ERR_PROTO;
1728 table_size = num * entry_size;
1729 size = REG_HEADER_SIZE + table_size + info_size;
1731 if (size > REG_MAX_SIZE) {
1732 log_err(ctx, "Maximum registration information size exceeded: "
1733 "%u bytes", size);
1734 return JAYLINK_ERR_PROTO;
1737 if (size > REG_MIN_SIZE) {
1738 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1740 if (ret != JAYLINK_OK) {
1741 log_err(ctx, "transport_start_read() failed: %s",
1742 jaylink_strerror(ret));
1743 return JAYLINK_ERR;
1746 ret = transport_read(devh, buf + REG_MIN_SIZE,
1747 size - REG_MIN_SIZE);
1749 if (ret != JAYLINK_OK) {
1750 log_err(ctx, "transport_read() failed: %s",
1751 jaylink_strerror(ret));
1752 return JAYLINK_ERR;
1756 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1758 *count = num;
1760 return JAYLINK_OK;