Add jaylink_device_get_usb_bus_ports()
[libjaylink.git] / libjaylink / device.c
blob3a5f7d2b7f2b13370bd9692dd0f6f3695ac775db
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;
144 size_t i;
146 if (!ctx || !devs)
147 return JAYLINK_ERR_ARG;
149 num = list_length(ctx->discovered_devs);
150 tmp = allocate_device_list(num);
152 if (!tmp) {
153 log_err(ctx, "Failed to allocate device list.");
154 return JAYLINK_ERR_MALLOC;
157 item = ctx->discovered_devs;
159 for (i = 0; i < num; i++) {
160 dev = (struct jaylink_device *)item->data;
161 tmp[i] = jaylink_ref_device(dev);
162 item = item->next;
165 if (count)
166 *count = num;
168 *devs = tmp;
170 return JAYLINK_OK;
174 * Free devices.
176 * @param[in,out] devs Array of device instances. Must be NULL-terminated.
177 * @param[in] unref Determines whether the device instances should be
178 * unreferenced.
180 * @see jaylink_get_devices()
182 * @since 0.1.0
184 JAYLINK_API void jaylink_free_devices(struct jaylink_device **devs, bool unref)
186 size_t i;
188 if (!devs)
189 return;
191 if (unref) {
192 for (i = 0; devs[i]; i++)
193 jaylink_unref_device(devs[i]);
196 free(devs);
200 * Get the host interface of a device.
202 * @param[in] dev Device instance.
203 * @param[out] iface Host interface of the device on success, and undefined on
204 * failure.
206 * @retval JAYLINK_OK Success.
207 * @retval JAYLINK_ERR_ARG Invalid arguments.
209 * @since 0.1.0
211 JAYLINK_API int jaylink_device_get_host_interface(
212 const struct jaylink_device *dev,
213 enum jaylink_host_interface *iface)
215 if (!dev || !iface)
216 return JAYLINK_ERR_ARG;
218 *iface = dev->iface;
220 return JAYLINK_OK;
224 * Get the serial number of a device.
226 * @note This serial number is for enumeration purpose only and might differ
227 * from the real serial number of the device.
229 * @param[in] dev Device instance.
230 * @param[out] serial_number Serial number of the device on success, and
231 * undefined on failure.
233 * @retval JAYLINK_OK Success.
234 * @retval JAYLINK_ERR_ARG Invalid arguments.
235 * @retval JAYLINK_ERR_NOT_AVAILABLE Serial number is not available.
237 * @since 0.1.0
239 JAYLINK_API int jaylink_device_get_serial_number(
240 const struct jaylink_device *dev, uint32_t *serial_number)
242 if (!dev || !serial_number)
243 return JAYLINK_ERR_ARG;
245 if (!dev->valid_serial_number)
246 return JAYLINK_ERR_NOT_AVAILABLE;
248 *serial_number = dev->serial_number;
250 return JAYLINK_OK;
254 * Get the USB address of a device.
256 * @note Identification of a device with the USB address is deprecated and the
257 * serial number should be used instead.
259 * @param[in] dev Device instance.
260 * @param[out] address USB address of the device on success, and undefined on
261 * failure.
263 * @retval JAYLINK_OK Success.
264 * @retval JAYLINK_ERR_ARG Invalid arguments.
265 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
266 * #JAYLINK_HIF_USB only.
268 * @see jaylink_device_get_serial_number()
270 * @since 0.1.0
272 JAYLINK_API int jaylink_device_get_usb_address(
273 const struct jaylink_device *dev,
274 enum jaylink_usb_address *address)
276 if (!dev || !address)
277 return JAYLINK_ERR_ARG;
279 if (dev->iface != JAYLINK_HIF_USB)
280 return JAYLINK_ERR_NOT_SUPPORTED;
282 #ifdef HAVE_LIBUSB
283 *address = dev->usb_address;
285 return JAYLINK_OK;
286 #else
287 return JAYLINK_ERR_NOT_SUPPORTED;
288 #endif
292 * Get the USB bus and port numbers of a device.
294 * @param[in] dev Device instance.
295 * @param[out] bus The bus number of the device on success and undefined on
296 * failure.
297 * @param[out] ports Newly allocated array which contains the port numbers on
298 * success and is undefined on failure. The array must be
299 * free'd by the caller.
300 * @param[out] length Length of the port array on success and undefined on
301 * failure.
303 * @retval JAYLINK_OK Success.
304 * @retval JAYLINK_ERR_ARG Invalid arguments.
305 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
306 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
307 * #JAYLINK_HIF_USB only.
309 * @since 0.2.0
311 JAYLINK_API int jaylink_device_get_usb_bus_ports(
312 const struct jaylink_device *dev, uint8_t *bus,
313 uint8_t **ports, size_t *length)
315 if (!dev || !bus || !ports || !length)
316 return JAYLINK_ERR_ARG;
318 if (dev->iface != JAYLINK_HIF_USB)
319 return JAYLINK_ERR_NOT_SUPPORTED;
321 #ifdef HAVE_LIBUSB
322 struct jaylink_context *ctx = dev->ctx;
323 int ret;
325 *ports = malloc(MAX_USB_PATH_DEPTH * sizeof(uint8_t));
327 if (!*ports) {
328 return JAYLINK_ERR_MALLOC;
331 ret = libusb_get_port_numbers(dev->usb_dev, *ports,
332 MAX_USB_PATH_DEPTH);
334 if (ret == LIBUSB_ERROR_OVERFLOW) {
335 log_err(ctx, "Failed to get port numbers: %s.",
336 libusb_error_name(ret));
337 return JAYLINK_ERR_ARG;
340 *length = ret;
341 *bus = libusb_get_bus_number(dev->usb_dev);
343 return JAYLINK_OK;
344 #else
345 return JAYLINK_ERR_NOT_SUPPORTED;
346 #endif
350 * Get the IPv4 address string of a device.
352 * @param[in] dev Device instance.
353 * @param[out] address IPv4 address string in quad-dotted decimal format of the
354 * device on success and undefined on failure.
356 * @retval JAYLINK_OK Success.
357 * @retval JAYLINK_ERR_ARG Invalid arguments.
358 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
359 * #JAYLINK_HIF_TCP only.
361 * @since 0.2.0
363 JAYLINK_API int jaylink_device_get_ipv4_address(
364 const struct jaylink_device *dev, char *address)
366 if (!dev || !address)
367 return JAYLINK_ERR_ARG;
369 if (dev->iface != JAYLINK_HIF_TCP)
370 return JAYLINK_ERR_NOT_SUPPORTED;
372 memcpy(address, dev->ipv4_address, sizeof(dev->ipv4_address));
374 return JAYLINK_OK;
378 * Get the MAC address of a device.
380 * @param[in] dev Device instance.
381 * @param[out] address MAC address of the device on success and undefined on
382 * failure. The length of the MAC address is
383 * #JAYLINK_MAC_ADDRESS_LENGTH bytes.
385 * @retval JAYLINK_OK Success.
386 * @retval JAYLINK_ERR_ARG Invalid arguments.
387 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
388 * #JAYLINK_HIF_TCP only.
389 * @retval JAYLINK_ERR_NOT_AVAILABLE MAC address is not available.
391 * @since 0.2.0
393 JAYLINK_API int jaylink_device_get_mac_address(
394 const struct jaylink_device *dev, uint8_t *address)
396 if (!dev || !address)
397 return JAYLINK_ERR_ARG;
399 if (dev->iface != JAYLINK_HIF_TCP)
400 return JAYLINK_ERR_NOT_SUPPORTED;
402 if (!dev->has_mac_address)
403 return JAYLINK_ERR_NOT_AVAILABLE;
405 memcpy(address, dev->mac_address, sizeof(dev->mac_address));
407 return JAYLINK_OK;
411 * Get the hardware version of a device.
413 * @note The hardware type can not be obtained by this function, use
414 * jaylink_get_hardware_version() instead.
416 * @param[in] dev Device instance.
417 * @param[out] version Hardware version of the device on success and undefined
418 * on failure.
420 * @retval JAYLINK_OK Success.
421 * @retval JAYLINK_ERR_ARG Invalid arguments.
422 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
423 * #JAYLINK_HIF_TCP only.
424 * @retval JAYLINK_ERR_NOT_AVAILABLE Hardware version is not available.
426 * @since 0.2.0
428 JAYLINK_API int jaylink_device_get_hardware_version(
429 const struct jaylink_device *dev,
430 struct jaylink_hardware_version *version)
432 if (!dev || !version)
433 return JAYLINK_ERR_ARG;
435 if (dev->iface != JAYLINK_HIF_TCP)
436 return JAYLINK_ERR_NOT_SUPPORTED;
438 if (!dev->has_hw_version)
439 return JAYLINK_ERR_NOT_AVAILABLE;
441 *version = dev->hw_version;
443 return JAYLINK_OK;
447 * Get the product name of a device.
449 * @param[in] dev Device instance.
450 * @param[out] name Product name of the device on success and undefined on
451 * failure. The maximum length of the product name is
452 * #JAYLINK_PRODUCT_NAME_MAX_LENGTH bytes.
454 * @retval JAYLINK_OK Success.
455 * @retval JAYLINK_ERR_ARG Invalid arguments.
456 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
457 * #JAYLINK_HIF_TCP only.
458 * @retval JAYLINK_ERR_NOT_AVAILABLE Product name is not available.
460 * @since 0.2.0
462 JAYLINK_API int jaylink_device_get_product_name(
463 const struct jaylink_device *dev, char *name)
465 if (!dev || !name)
466 return JAYLINK_ERR_ARG;
468 if (dev->iface != JAYLINK_HIF_TCP)
469 return JAYLINK_ERR_NOT_SUPPORTED;
471 if (!dev->has_product_name)
472 return JAYLINK_ERR_NOT_AVAILABLE;
474 memcpy(name, dev->product_name, sizeof(dev->product_name));
476 return JAYLINK_OK;
480 * Get the nickname of a device.
482 * @param[in] dev Device instance.
483 * @param[out] nickname Nickname of the device on success and undefined on
484 * failure. The maximum length of the nickname is
485 * #JAYLINK_NICKNAME_MAX_LENGTH bytes.
487 * @retval JAYLINK_OK Success.
488 * @retval JAYLINK_ERR_ARG Invalid arguments.
489 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
490 * #JAYLINK_HIF_TCP only.
491 * @retval JAYLINK_ERR_NOT_AVAILABLE Nickname is not available.
493 * @since 0.2.0
495 JAYLINK_API int jaylink_device_get_nickname(const struct jaylink_device *dev,
496 char *nickname)
498 if (!dev || !nickname)
499 return JAYLINK_ERR_ARG;
501 if (dev->iface != JAYLINK_HIF_TCP)
502 return JAYLINK_ERR_NOT_SUPPORTED;
504 if (!dev->has_nickname)
505 return JAYLINK_ERR_NOT_AVAILABLE;
507 memcpy(nickname, dev->nickname, sizeof(dev->nickname));
509 return JAYLINK_OK;
513 * Increment the reference count of a device.
515 * @param[in,out] dev Device instance.
517 * @return The given device instance on success, or NULL on invalid argument.
519 * @since 0.1.0
521 JAYLINK_API struct jaylink_device *jaylink_ref_device(
522 struct jaylink_device *dev)
524 if (!dev)
525 return NULL;
527 dev->ref_count++;
529 return dev;
533 * Decrement the reference count of a device.
535 * @param[in,out] dev Device instance.
537 * @since 0.1.0
539 JAYLINK_API void jaylink_unref_device(struct jaylink_device *dev)
541 struct jaylink_context *ctx;
543 if (!dev)
544 return;
546 dev->ref_count--;
548 if (!dev->ref_count) {
549 ctx = dev->ctx;
550 ctx->devs = list_remove(dev->ctx->devs, dev);
552 if (dev->iface == JAYLINK_HIF_USB) {
553 #ifdef HAVE_LIBUSB
554 log_dbg(ctx, "Device destroyed (bus:address = "
555 "%03u:%03u).",
556 libusb_get_bus_number(dev->usb_dev),
557 libusb_get_device_address(dev->usb_dev));
559 libusb_unref_device(dev->usb_dev);
560 #endif
561 } else if (dev->iface == JAYLINK_HIF_TCP) {
562 log_dbg(ctx, "Device destroyed (IPv4 address = %s).",
563 dev->ipv4_address);
564 } else {
565 log_err(ctx, "BUG: Invalid host interface: %u.",
566 dev->iface);
569 free(dev);
573 static struct jaylink_device_handle *allocate_device_handle(
574 struct jaylink_device *dev)
576 struct jaylink_device_handle *devh;
578 devh = malloc(sizeof(struct jaylink_device_handle));
580 if (!devh)
581 return NULL;
583 devh->dev = jaylink_ref_device(dev);
585 return devh;
588 static void free_device_handle(struct jaylink_device_handle *devh)
590 jaylink_unref_device(devh->dev);
591 free(devh);
595 * Open a device.
597 * @param[in,out] dev Device instance.
598 * @param[out] devh Newly allocated handle for the opened device on success,
599 * and undefined on failure.
601 * @retval JAYLINK_OK Success.
602 * @retval JAYLINK_ERR_ARG Invalid arguments.
603 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
604 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
605 * @retval JAYLINK_ERR_IO Input/output error.
606 * @retval JAYLINK_ERR Other error conditions.
608 * @since 0.1.0
610 JAYLINK_API int jaylink_open(struct jaylink_device *dev,
611 struct jaylink_device_handle **devh)
613 int ret;
614 struct jaylink_device_handle *handle;
616 if (!dev || !devh)
617 return JAYLINK_ERR_ARG;
619 handle = allocate_device_handle(dev);
621 if (!handle) {
622 log_err(dev->ctx, "Device handle malloc failed.");
623 return JAYLINK_ERR_MALLOC;
626 ret = transport_open(handle);
628 if (ret != JAYLINK_OK) {
629 free_device_handle(handle);
630 return ret;
633 *devh = handle;
635 return JAYLINK_OK;
639 * Close a device.
641 * @param[in,out] devh Device instance.
643 * @retval JAYLINK_OK Success.
644 * @retval JAYLINK_ERR_ARG Invalid arguments.
645 * @retval JAYLINK_ERR Other error conditions.
647 * @since 0.1.0
649 JAYLINK_API int jaylink_close(struct jaylink_device_handle *devh)
651 int ret;
653 if (!devh)
654 return JAYLINK_ERR_ARG;
656 ret = transport_close(devh);
657 free_device_handle(devh);
659 return ret;
663 * Get the device instance from a device handle.
665 * @note The reference count of the device instance is not increased.
667 * @param[in] devh Device handle.
669 * @return The device instance on success, or NULL on invalid argument.
671 * @since 0.1.0
673 JAYLINK_API struct jaylink_device *jaylink_get_device(
674 struct jaylink_device_handle *devh)
676 if (!devh)
677 return NULL;
679 return devh->dev;
683 * Retrieve the firmware version of a device.
685 * @param[in,out] devh Device handle.
686 * @param[out] version Newly allocated string which contains the firmware
687 * version on success, and undefined if @p length is zero
688 * or on failure. The string is null-terminated and must be
689 * free'd by the caller.
690 * @param[out] length Length of the firmware version string including trailing
691 * null-terminator on success, and undefined on failure.
692 * Zero if no firmware version string is available.
694 * @retval JAYLINK_OK Success.
695 * @retval JAYLINK_ERR_ARG Invalid arguments.
696 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
697 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
698 * @retval JAYLINK_ERR_IO Input/output error.
699 * @retval JAYLINK_ERR Other error conditions.
701 * @since 0.1.0
703 JAYLINK_API int jaylink_get_firmware_version(
704 struct jaylink_device_handle *devh, char **version,
705 size_t *length)
707 int ret;
708 struct jaylink_context *ctx;
709 uint8_t buf[2];
710 uint16_t dummy;
711 char *tmp;
713 if (!devh || !version || !length)
714 return JAYLINK_ERR_ARG;
716 ctx = devh->dev->ctx;
717 ret = transport_start_write_read(devh, 1, 2, true);
719 if (ret != JAYLINK_OK) {
720 log_err(ctx, "transport_start_write_read() failed: %s.",
721 jaylink_strerror(ret));
722 return ret;
725 buf[0] = CMD_GET_VERSION;
727 ret = transport_write(devh, buf, 1);
729 if (ret != JAYLINK_OK) {
730 log_err(ctx, "transport_write() failed: %s.",
731 jaylink_strerror(ret));
732 return ret;
735 ret = transport_read(devh, buf, 2);
737 if (ret != JAYLINK_OK) {
738 log_err(ctx, "transport_read() failed: %s.",
739 jaylink_strerror(ret));
740 return ret;
743 dummy = buffer_get_u16(buf, 0);
744 *length = dummy;
746 if (!dummy)
747 return JAYLINK_OK;
749 ret = transport_start_read(devh, dummy);
751 if (ret != JAYLINK_OK) {
752 log_err(ctx, "transport_start_read() failed: %s.",
753 jaylink_strerror(ret));
754 return ret;
757 tmp = malloc(dummy);
759 if (!tmp) {
760 log_err(ctx, "Firmware version string malloc failed.");
761 return JAYLINK_ERR_MALLOC;
764 ret = transport_read(devh, (uint8_t *)tmp, dummy);
766 if (ret != JAYLINK_OK) {
767 log_err(ctx, "transport_read() failed: %s.",
768 jaylink_strerror(ret));
769 free(tmp);
770 return ret;
773 /* Last byte is reserved for null-terminator. */
774 tmp[dummy - 1] = 0;
775 *version = tmp;
777 return JAYLINK_OK;
781 * Retrieve the hardware information of a device.
783 * @note This function must only be used if the device has the
784 * #JAYLINK_DEV_CAP_GET_HW_INFO capability.
786 * @param[in,out] devh Device handle.
787 * @param[in] mask A bit field where each set bit represents hardware
788 * information to request. See #jaylink_hardware_info for a
789 * description of the hardware information and their bit
790 * positions.
791 * @param[out] info Array to store the hardware information on success. Its
792 * content is undefined on failure. The array must be large
793 * enough to contain at least as many elements as bits set in
794 * @a mask.
796 * @retval JAYLINK_OK Success.
797 * @retval JAYLINK_ERR_ARG Invalid arguments.
798 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
799 * @retval JAYLINK_ERR_IO Input/output error.
800 * @retval JAYLINK_ERR Other error conditions.
802 * @since 0.1.0
804 JAYLINK_API int jaylink_get_hardware_info(struct jaylink_device_handle *devh,
805 uint32_t mask, uint32_t *info)
807 int ret;
808 struct jaylink_context *ctx;
809 uint8_t buf[5];
810 unsigned int i;
811 unsigned int num;
812 unsigned int length;
814 if (!devh || !mask || !info)
815 return JAYLINK_ERR_ARG;
817 ctx = devh->dev->ctx;
818 num = 0;
820 for (i = 0; i < 32; i++) {
821 if (mask & (1 << i))
822 num++;
825 length = num * sizeof(uint32_t);
827 ret = transport_start_write_read(devh, 5, length, true);
829 if (ret != JAYLINK_OK) {
830 log_err(ctx, "transport_start_write_read() failed: %s.",
831 jaylink_strerror(ret));
832 return ret;
835 buf[0] = CMD_GET_HW_INFO;
836 buffer_set_u32(buf, mask, 1);
838 ret = transport_write(devh, buf, 5);
840 if (ret != JAYLINK_OK) {
841 log_err(ctx, "transport_write() failed: %s.",
842 jaylink_strerror(ret));
843 return ret;
846 ret = transport_read(devh, (uint8_t *)info, length);
848 if (ret != JAYLINK_OK) {
849 log_err(ctx, "transport_read() failed: %s.",
850 jaylink_strerror(ret));
851 return ret;
854 for (i = 0; i < num; i++)
855 info[i] = buffer_get_u32((uint8_t *)info,
856 i * sizeof(uint32_t));
858 return JAYLINK_OK;
862 * Retrieve the counter values of a device.
864 * @note This function must only be used if the device has the
865 * #JAYLINK_DEV_CAP_GET_COUNTERS capability.
867 * @param[in,out] devh Device handle.
868 * @param[in] mask A bit field where each set bit represents a counter value to
869 * request. See #jaylink_counter for a description of the
870 * counters and their bit positions.
871 * @param[out] values Array to store the counter values on success. Its content
872 * is undefined on failure. The array must be large enough
873 * to contain at least as many elements as bits set in @p
874 * mask.
876 * @retval JAYLINK_OK Success.
877 * @retval JAYLINK_ERR_ARG Invalid arguments.
878 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
879 * @retval JAYLINK_ERR_IO Input/output error.
880 * @retval JAYLINK_ERR Other error conditions.
882 * @since 0.2.0
884 JAYLINK_API int jaylink_get_counters(struct jaylink_device_handle *devh,
885 uint32_t mask, uint32_t *values)
887 int ret;
888 struct jaylink_context *ctx;
889 uint8_t buf[5];
890 unsigned int i;
891 unsigned int num;
892 unsigned int length;
894 if (!devh || !mask || !values)
895 return JAYLINK_ERR_ARG;
897 ctx = devh->dev->ctx;
898 num = 0;
900 for (i = 0; i < 32; i++) {
901 if (mask & (1 << i))
902 num++;
905 length = num * sizeof(uint32_t);
906 ret = transport_start_write_read(devh, 5, length, true);
908 if (ret != JAYLINK_OK) {
909 log_err(ctx, "transport_start_write_read() failed: %s.",
910 jaylink_strerror(ret));
911 return ret;
914 buf[0] = CMD_GET_COUNTERS;
915 buffer_set_u32(buf, mask, 1);
917 ret = transport_write(devh, buf, 5);
919 if (ret != JAYLINK_OK) {
920 log_err(ctx, "transport_write() failed: %s.",
921 jaylink_strerror(ret));
922 return ret;
925 ret = transport_read(devh, (uint8_t *)values, length);
927 if (ret != JAYLINK_OK) {
928 log_err(ctx, "transport_read() failed: %s.",
929 jaylink_strerror(ret));
930 return ret;
933 for (i = 0; i < num; i++)
934 values[i] = buffer_get_u32((uint8_t *)values,
935 i * sizeof(uint32_t));
937 return JAYLINK_OK;
941 * Retrieve the hardware version of a device.
943 * @note This function must only be used if the device has the
944 * #JAYLINK_DEV_CAP_GET_HW_VERSION capability.
946 * @warning This function may return a value for @p version where
947 * #jaylink_hardware_version::type is not covered by
948 * #jaylink_hardware_type.
950 * @param[in,out] devh Device handle.
951 * @param[out] version Hardware version on success, and undefined on failure.
953 * @retval JAYLINK_OK Success.
954 * @retval JAYLINK_ERR_ARG Invalid arguments.
955 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
956 * @retval JAYLINK_ERR_IO Input/output error.
957 * @retval JAYLINK_ERR Other error conditions.
959 * @since 0.1.0
961 JAYLINK_API int jaylink_get_hardware_version(
962 struct jaylink_device_handle *devh,
963 struct jaylink_hardware_version *version)
965 int ret;
966 struct jaylink_context *ctx;
967 uint8_t buf[4];
968 uint32_t tmp;
970 if (!devh || !version)
971 return JAYLINK_ERR_ARG;
973 ctx = devh->dev->ctx;
974 ret = transport_start_write_read(devh, 1, 4, true);
976 if (ret != JAYLINK_OK) {
977 log_err(ctx, "transport_start_write_read() failed: %s.",
978 jaylink_strerror(ret));
979 return ret;
982 buf[0] = CMD_GET_HW_VERSION;
984 ret = transport_write(devh, buf, 1);
986 if (ret != JAYLINK_OK) {
987 log_err(ctx, "transport_write() failed: %s.",
988 jaylink_strerror(ret));
989 return ret;
992 ret = transport_read(devh, buf, 4);
994 if (ret != JAYLINK_OK) {
995 log_err(ctx, "transport_read() failed: %s.",
996 jaylink_strerror(ret));
997 return ret;
1000 tmp = buffer_get_u32(buf, 0);
1002 version->type = (tmp / 1000000) % 100;
1003 version->major = (tmp / 10000) % 100;
1004 version->minor = (tmp / 100) % 100;
1005 version->revision = tmp % 100;
1007 return JAYLINK_OK;
1011 * Retrieve the hardware status of a device.
1013 * @param[in,out] devh Device handle.
1014 * @param[out] status Hardware status on success, and undefined on failure.
1016 * @retval JAYLINK_OK Success.
1017 * @retval JAYLINK_ERR_ARG Invalid arguments.
1018 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1019 * @retval JAYLINK_ERR_IO Input/output error.
1020 * @retval JAYLINK_ERR Other error conditions.
1022 * @since 0.1.0
1024 JAYLINK_API int jaylink_get_hardware_status(struct jaylink_device_handle *devh,
1025 struct jaylink_hardware_status *status)
1027 int ret;
1028 struct jaylink_context *ctx;
1029 uint8_t buf[8];
1031 if (!devh || !status)
1032 return JAYLINK_ERR_ARG;
1034 ctx = devh->dev->ctx;
1035 ret = transport_start_write_read(devh, 1, 8, true);
1037 if (ret != JAYLINK_OK) {
1038 log_err(ctx, "transport_start_write_read() failed: %s.",
1039 jaylink_strerror(ret));
1040 return ret;
1043 buf[0] = CMD_GET_HW_STATUS;
1045 ret = transport_write(devh, buf, 1);
1047 if (ret != JAYLINK_OK) {
1048 log_err(ctx, "transport_write() failed: %s.",
1049 jaylink_strerror(ret));
1050 return ret;
1053 ret = transport_read(devh, buf, 8);
1055 if (ret != JAYLINK_OK) {
1056 log_err(ctx, "transport_read() failed: %s.",
1057 jaylink_strerror(ret));
1058 return ret;
1061 status->target_voltage = buffer_get_u16(buf, 0);
1062 status->tck = buf[2];
1063 status->tdi = buf[3];
1064 status->tdo = buf[4];
1065 status->tms = buf[5];
1066 status->tres = buf[6];
1067 status->trst = buf[7];
1069 return JAYLINK_OK;
1073 * Retrieve the capabilities of a device.
1075 * The capabilities are stored in a 32-bit bit array consisting of
1076 * #JAYLINK_DEV_CAPS_SIZE bytes where each individual bit represents a
1077 * capability. The first bit of this array is the least significant bit of the
1078 * first byte and the following bits are sequentially numbered in order of
1079 * increasing bit significance and byte index. A set bit indicates a supported
1080 * capability. See #jaylink_device_capability for a description of the
1081 * capabilities and their bit positions.
1083 * @param[in,out] devh Device handle.
1084 * @param[out] caps Buffer to store capabilities on success. Its content is
1085 * undefined on failure. The buffer must be large enough to
1086 * contain at least #JAYLINK_DEV_CAPS_SIZE bytes.
1088 * @retval JAYLINK_OK Success.
1089 * @retval JAYLINK_ERR_ARG Invalid arguments.
1090 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1091 * @retval JAYLINK_ERR_IO Input/output error.
1092 * @retval JAYLINK_ERR Other error conditions.
1094 * @see jaylink_get_extended_caps()
1095 * @see jaylink_has_cap()
1097 * @since 0.1.0
1099 JAYLINK_API int jaylink_get_caps(struct jaylink_device_handle *devh,
1100 uint8_t *caps)
1102 int ret;
1103 struct jaylink_context *ctx;
1104 uint8_t buf[1];
1106 if (!devh || !caps)
1107 return JAYLINK_ERR_ARG;
1109 ctx = devh->dev->ctx;
1110 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CAPS_SIZE, true);
1112 if (ret != JAYLINK_OK) {
1113 log_err(ctx, "transport_start_write_read() failed: %s.",
1114 jaylink_strerror(ret));
1115 return ret;
1118 buf[0] = CMD_GET_CAPS;
1120 ret = transport_write(devh, buf, 1);
1122 if (ret != JAYLINK_OK) {
1123 log_err(ctx, "transport_write() failed: %s.",
1124 jaylink_strerror(ret));
1125 return ret;
1128 ret = transport_read(devh, caps, JAYLINK_DEV_CAPS_SIZE);
1130 if (ret != JAYLINK_OK) {
1131 log_err(ctx, "transport_read() failed: %s.",
1132 jaylink_strerror(ret));
1133 return ret;
1136 return JAYLINK_OK;
1140 * Retrieve the extended capabilities of a device.
1142 * The extended capabilities are stored in a 256-bit bit array consisting of
1143 * #JAYLINK_DEV_EXT_CAPS_SIZE bytes. See jaylink_get_caps() for a further
1144 * description of how the capabilities are represented in this bit array. For a
1145 * description of the capabilities and their bit positions, see
1146 * #jaylink_device_capability.
1148 * @note This function must only be used if the device has the
1149 * #JAYLINK_DEV_CAP_GET_EXT_CAPS capability.
1151 * @param[in,out] devh Device handle.
1152 * @param[out] caps Buffer to store capabilities on success. Its content is
1153 * undefined on failure. The buffer must be large enough to
1154 * contain at least #JAYLINK_DEV_EXT_CAPS_SIZE bytes.
1156 * @retval JAYLINK_OK Success.
1157 * @retval JAYLINK_ERR_ARG Invalid arguments.
1158 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1159 * @retval JAYLINK_ERR_IO Input/output error.
1160 * @retval JAYLINK_ERR Other error conditions.
1162 * @see jaylink_get_caps()
1164 * @since 0.1.0
1166 JAYLINK_API int jaylink_get_extended_caps(struct jaylink_device_handle *devh,
1167 uint8_t *caps)
1169 int ret;
1170 struct jaylink_context *ctx;
1171 uint8_t buf[1];
1173 if (!devh || !caps)
1174 return JAYLINK_ERR_ARG;
1176 ctx = devh->dev->ctx;
1177 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_EXT_CAPS_SIZE,
1178 true);
1180 if (ret != JAYLINK_OK) {
1181 log_err(ctx, "transport_start_write_read() failed: %s.",
1182 jaylink_strerror(ret));
1183 return ret;
1186 buf[0] = CMD_GET_EXT_CAPS;
1188 ret = transport_write(devh, buf, 1);
1190 if (ret != JAYLINK_OK) {
1191 log_err(ctx, "transport_write() failed: %s.",
1192 jaylink_strerror(ret));
1193 return ret;
1196 ret = transport_read(devh, caps, JAYLINK_DEV_EXT_CAPS_SIZE);
1198 if (ret != JAYLINK_OK) {
1199 log_err(ctx, "transport_read() failed: %s.",
1200 jaylink_strerror(ret));
1201 return ret;
1204 return JAYLINK_OK;
1208 * Retrieve the size of free memory of a device.
1210 * @note This function must only be used if the device has the
1211 * #JAYLINK_DEV_CAP_GET_FREE_MEMORY capability.
1213 * @param[in,out] devh Device handle.
1214 * @param[out] size Size of free memory in bytes on success, and undefined on
1215 * failure.
1217 * @retval JAYLINK_OK Success.
1218 * @retval JAYLINK_ERR_ARG Invalid arguments.
1219 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1220 * @retval JAYLINK_ERR_IO Input/output error.
1221 * @retval JAYLINK_ERR Other error conditions.
1223 * @since 0.1.0
1225 JAYLINK_API int jaylink_get_free_memory(struct jaylink_device_handle *devh,
1226 uint32_t *size)
1228 int ret;
1229 struct jaylink_context *ctx;
1230 uint8_t buf[4];
1232 if (!devh || !size)
1233 return JAYLINK_ERR_ARG;
1235 ctx = devh->dev->ctx;
1236 ret = transport_start_write_read(devh, 1, 4, true);
1238 if (ret != JAYLINK_OK) {
1239 log_err(ctx, "transport_start_write_read() failed: %s.",
1240 jaylink_strerror(ret));
1241 return ret;
1244 buf[0] = CMD_GET_FREE_MEMORY;
1246 ret = transport_write(devh, buf, 1);
1248 if (ret != JAYLINK_OK) {
1249 log_err(ctx, "transport_write() failed: %s.",
1250 jaylink_strerror(ret));
1251 return ret;
1254 ret = transport_read(devh, buf, 4);
1256 if (ret != JAYLINK_OK) {
1257 log_err(ctx, "transport_read() failed: %s.",
1258 jaylink_strerror(ret));
1259 return ret;
1262 *size = buffer_get_u32(buf, 0);
1264 return JAYLINK_OK;
1268 * Read the raw configuration data of a device.
1270 * @note This function must only be used if the device has the
1271 * #JAYLINK_DEV_CAP_READ_CONFIG capability.
1273 * @param[in,out] devh Device handle.
1274 * @param[out] config Buffer to store configuration data on success. Its
1275 * content is undefined on failure. The buffer must be large
1276 * enough to contain at least
1277 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1279 * @retval JAYLINK_OK Success.
1280 * @retval JAYLINK_ERR_ARG Invalid arguments.
1281 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1282 * @retval JAYLINK_ERR_IO Input/output error.
1283 * @retval JAYLINK_ERR Other error conditions.
1285 * @since 0.1.0
1287 JAYLINK_API int jaylink_read_raw_config(struct jaylink_device_handle *devh,
1288 uint8_t *config)
1290 int ret;
1291 struct jaylink_context *ctx;
1292 uint8_t buf[1];
1294 if (!devh || !config)
1295 return JAYLINK_ERR_ARG;
1297 ctx = devh->dev->ctx;
1298 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CONFIG_SIZE,
1299 true);
1301 if (ret != JAYLINK_OK) {
1302 log_err(ctx, "transport_start_write_read() failed: %s.",
1303 jaylink_strerror(ret));
1304 return ret;
1307 buf[0] = CMD_READ_CONFIG;
1309 ret = transport_write(devh, buf, 1);
1311 if (ret != JAYLINK_OK) {
1312 log_err(ctx, "transport_write() failed: %s.",
1313 jaylink_strerror(ret));
1314 return ret;
1317 ret = transport_read(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1319 if (ret != JAYLINK_OK) {
1320 log_err(ctx, "transport_read() failed: %s.",
1321 jaylink_strerror(ret));
1322 return ret;
1325 return JAYLINK_OK;
1329 * Write the raw configuration data of a device.
1331 * @note This function must only be used if the device has the
1332 * #JAYLINK_DEV_CAP_WRITE_CONFIG capability.
1334 * @param[in,out] devh Device handle.
1335 * @param[in] config Buffer to write configuration data from. The size of the
1336 * configuration data is expected to be
1337 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1339 * @retval JAYLINK_OK Success.
1340 * @retval JAYLINK_ERR_ARG Invalid arguments.
1341 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1342 * @retval JAYLINK_ERR_IO Input/output error.
1343 * @retval JAYLINK_ERR Other error conditions.
1345 * @since 0.1.0
1347 JAYLINK_API int jaylink_write_raw_config(struct jaylink_device_handle *devh,
1348 const uint8_t *config)
1350 int ret;
1351 struct jaylink_context *ctx;
1352 uint8_t buf[1];
1354 if (!devh || !config)
1355 return JAYLINK_ERR_ARG;
1357 ctx = devh->dev->ctx;
1358 ret = transport_start_write(devh, 1 + JAYLINK_DEV_CONFIG_SIZE, true);
1360 if (ret != JAYLINK_OK) {
1361 log_err(ctx, "transport_start_write() failed: %s.",
1362 jaylink_strerror(ret));
1363 return ret;
1366 buf[0] = CMD_WRITE_CONFIG;
1368 ret = transport_write(devh, buf, 1);
1370 if (ret != JAYLINK_OK) {
1371 log_err(ctx, "transport_write() failed: %s.",
1372 jaylink_strerror(ret));
1373 return ret;
1376 ret = transport_write(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1378 if (ret != JAYLINK_OK) {
1379 log_err(ctx, "transport_write() failed: %s.",
1380 jaylink_strerror(ret));
1381 return ret;
1384 return JAYLINK_OK;
1387 static void parse_conn_table(struct jaylink_connection *conns,
1388 const uint8_t *buffer, uint16_t num, uint16_t entry_size)
1390 unsigned int i;
1391 size_t offset;
1392 struct in_addr in;
1394 offset = 0;
1396 for (i = 0; i < num; i++) {
1397 conns[i].pid = buffer_get_u32(buffer, offset);
1399 in.s_addr = buffer_get_u32(buffer, offset + 4);
1401 * Use inet_ntoa() instead of inet_ntop() because the latter
1402 * requires at least Windows Vista.
1404 strcpy(conns[i].hid, inet_ntoa(in));
1406 conns[i].iid = buffer[offset + 8];
1407 conns[i].cid = buffer[offset + 9];
1408 conns[i].handle = buffer_get_u16(buffer, offset + 10);
1409 conns[i].timestamp = buffer_get_u32(buffer, offset + 12);
1410 offset = offset + entry_size;
1414 static bool _inet_pton(const char *str, struct in_addr *in)
1416 #ifdef _WIN32
1417 int ret;
1418 struct sockaddr_in sock_in;
1419 int length;
1421 length = sizeof(sock_in);
1424 * Use WSAStringToAddress() instead of inet_pton() because the latter
1425 * requires at least Windows Vista.
1427 ret = WSAStringToAddress((LPTSTR)str, AF_INET, NULL,
1428 (LPSOCKADDR)&sock_in, &length);
1430 if (ret != 0)
1431 return false;
1433 *in = sock_in.sin_addr;
1434 #else
1435 if (inet_pton(AF_INET, str, in) != 1)
1436 return false;
1437 #endif
1439 return true;
1443 * Register a connection on a device.
1445 * A connection can be registered by using 0 as handle. Additional information
1446 * about the connection can be attached whereby the timestamp is a read-only
1447 * value and therefore ignored for registration. On success, a new handle
1448 * greater than 0 is obtained from the device.
1450 * However, if an obtained handle does not appear in the list of device
1451 * connections, the connection was not registered because the maximum number of
1452 * connections on the device is reached.
1454 * @note This function must only be used if the device has the
1455 * #JAYLINK_DEV_CAP_REGISTER capability.
1457 * Example code:
1458 * @code{.c}
1459 * static bool register_connection(struct jaylink_device_handle *devh,
1460 * struct jaylink_connection *conn)
1462 * int ret;
1463 * struct jaylink_connection conns[JAYLINK_MAX_CONNECTIONS];
1464 * bool found_handle;
1465 * size_t count;
1466 * size_t i;
1468 * conn->handle = 0;
1469 * conn->pid = 0;
1470 * strcpy(conn->hid, "0.0.0.0");
1471 * conn->iid = 0;
1472 * conn->cid = 0;
1474 * ret = jaylink_register(devh, conn, conns, &count);
1476 * if (ret != JAYLINK_OK) {
1477 * printf("jaylink_register() failed: %s.\n",
1478 * jaylink_strerror(ret));
1479 * return false;
1482 * found_handle = false;
1484 * for (i = 0; i < count; i++) {
1485 * if (conns[i].handle == conn->handle) {
1486 * found_handle = true;
1487 * break;
1491 * if (!found_handle) {
1492 * printf("Maximum number of connections reached.\n");
1493 * return false;
1496 * printf("Connection successfully registered.\n");
1498 * return true;
1500 * @endcode
1502 * @param[in,out] devh Device handle.
1503 * @param[in,out] connection Connection to register on the device.
1504 * @param[out] connections Array to store device connections on success.
1505 * Its content is undefined on failure. The array must
1506 * be large enough to contain at least
1507 * #JAYLINK_MAX_CONNECTIONS elements.
1508 * @param[out] count Number of device connections on success, and undefined on
1509 * failure.
1511 * @retval JAYLINK_OK Success.
1512 * @retval JAYLINK_ERR_ARG Invalid arguments.
1513 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1514 * @retval JAYLINK_ERR_PROTO Protocol violation.
1515 * @retval JAYLINK_ERR_IO Input/output error.
1516 * @retval JAYLINK_ERR Other error conditions.
1518 * @see jaylink_unregister()
1520 * @since 0.1.0
1522 JAYLINK_API int jaylink_register(struct jaylink_device_handle *devh,
1523 struct jaylink_connection *connection,
1524 struct jaylink_connection *connections, size_t *count)
1526 int ret;
1527 struct jaylink_context *ctx;
1528 uint8_t buf[REG_MAX_SIZE];
1529 uint16_t handle;
1530 uint16_t num;
1531 uint16_t entry_size;
1532 uint32_t size;
1533 uint32_t table_size;
1534 uint16_t info_size;
1535 struct in_addr in;
1537 if (!devh || !connection || !connections || !count)
1538 return JAYLINK_ERR_ARG;
1540 ctx = devh->dev->ctx;
1542 buf[0] = CMD_REGISTER;
1543 buf[1] = REG_CMD_REGISTER;
1544 buffer_set_u32(buf, connection->pid, 2);
1546 if (!_inet_pton(connection->hid, &in))
1547 return JAYLINK_ERR_ARG;
1549 buffer_set_u32(buf, in.s_addr, 6);
1551 buf[10] = connection->iid;
1552 buf[11] = connection->cid;
1553 buffer_set_u16(buf, connection->handle, 12);
1555 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1557 if (ret != JAYLINK_OK) {
1558 log_err(ctx, "transport_start_write_read() failed: %s.",
1559 jaylink_strerror(ret));
1560 return ret;
1563 ret = transport_write(devh, buf, 14);
1565 if (ret != JAYLINK_OK) {
1566 log_err(ctx, "transport_write() failed: %s.",
1567 jaylink_strerror(ret));
1568 return ret;
1571 ret = transport_read(devh, buf, REG_MIN_SIZE);
1573 if (ret != JAYLINK_OK) {
1574 log_err(ctx, "transport_read() failed: %s.",
1575 jaylink_strerror(ret));
1576 return ret;
1579 handle = buffer_get_u16(buf, 0);
1580 num = buffer_get_u16(buf, 2);
1581 entry_size = buffer_get_u16(buf, 4);
1582 info_size = buffer_get_u16(buf, 6);
1584 if (num > JAYLINK_MAX_CONNECTIONS) {
1585 log_err(ctx, "Maximum number of device connections exceeded: "
1586 "%u.", num);
1587 return JAYLINK_ERR_PROTO;
1590 if (entry_size != REG_CONN_INFO_SIZE) {
1591 log_err(ctx, "Invalid connection entry size: %u bytes.",
1592 entry_size);
1593 return JAYLINK_ERR_PROTO;
1596 table_size = num * entry_size;
1597 size = REG_HEADER_SIZE + table_size + info_size;
1599 if (size > REG_MAX_SIZE) {
1600 log_err(ctx, "Maximum registration information size exceeded: "
1601 "%u bytes.", size);
1602 return JAYLINK_ERR_PROTO;
1605 if (size > REG_MIN_SIZE) {
1606 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1608 if (ret != JAYLINK_OK) {
1609 log_err(ctx, "transport_start_read() failed: %s.",
1610 jaylink_strerror(ret));
1611 return JAYLINK_ERR;
1614 ret = transport_read(devh, buf + REG_MIN_SIZE,
1615 size - REG_MIN_SIZE);
1617 if (ret != JAYLINK_OK) {
1618 log_err(ctx, "transport_read() failed: %s.",
1619 jaylink_strerror(ret));
1620 return JAYLINK_ERR;
1624 if (!handle) {
1625 log_err(ctx, "Obtained invalid connection handle.");
1626 return JAYLINK_ERR_PROTO;
1629 connection->handle = handle;
1630 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1632 *count = num;
1634 return JAYLINK_OK;
1638 * Unregister a connection from a device.
1640 * @note This function must only be used if the device has the
1641 * #JAYLINK_DEV_CAP_REGISTER capability.
1643 * @param[in,out] devh Device handle.
1644 * @param[in,out] connection Connection to unregister from the device.
1645 * @param[out] connections Array to store device connections on success.
1646 * Its content is undefined on failure. The array must
1647 * be large enough to contain at least
1648 * #JAYLINK_MAX_CONNECTIONS elements.
1649 * @param[out] count Number of device connections on success, and undefined on
1650 * failure.
1652 * @retval JAYLINK_OK Success.
1653 * @retval JAYLINK_ERR_ARG Invalid arguments.
1654 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1655 * @retval JAYLINK_ERR_PROTO Protocol violation.
1656 * @retval JAYLINK_ERR_IO Input/output error.
1657 * @retval JAYLINK_ERR Other error conditions.
1659 * @see jaylink_register()
1661 * @since 0.1.0
1663 JAYLINK_API int jaylink_unregister(struct jaylink_device_handle *devh,
1664 const struct jaylink_connection *connection,
1665 struct jaylink_connection *connections, size_t *count)
1667 int ret;
1668 struct jaylink_context *ctx;
1669 uint8_t buf[REG_MAX_SIZE];
1670 uint16_t num;
1671 uint16_t entry_size;
1672 uint32_t size;
1673 uint32_t table_size;
1674 uint16_t info_size;
1675 struct in_addr in;
1677 if (!devh || !connection || !connections || !count)
1678 return JAYLINK_ERR_ARG;
1680 ctx = devh->dev->ctx;
1682 buf[0] = CMD_REGISTER;
1683 buf[1] = REG_CMD_UNREGISTER;
1684 buffer_set_u32(buf, connection->pid, 2);
1686 if (!_inet_pton(connection->hid, &in))
1687 return JAYLINK_ERR_ARG;
1689 buffer_set_u32(buf, in.s_addr, 6);
1691 buf[10] = connection->iid;
1692 buf[11] = connection->cid;
1693 buffer_set_u16(buf, connection->handle, 12);
1695 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1697 if (ret != JAYLINK_OK) {
1698 log_err(ctx, "transport_start_write_read() failed: %s.",
1699 jaylink_strerror(ret));
1700 return ret;
1703 ret = transport_write(devh, buf, 14);
1705 if (ret != JAYLINK_OK) {
1706 log_err(ctx, "transport_write() failed: %s.",
1707 jaylink_strerror(ret));
1708 return ret;
1711 ret = transport_read(devh, buf, REG_MIN_SIZE);
1713 if (ret != JAYLINK_OK) {
1714 log_err(ctx, "transport_read() failed: %s.",
1715 jaylink_strerror(ret));
1716 return ret;
1719 num = buffer_get_u16(buf, 2);
1720 entry_size = buffer_get_u16(buf, 4);
1721 info_size = buffer_get_u16(buf, 6);
1723 if (num > JAYLINK_MAX_CONNECTIONS) {
1724 log_err(ctx, "Maximum number of device connections exceeded: "
1725 "%u.", num);
1726 return JAYLINK_ERR_PROTO;
1729 if (entry_size != REG_CONN_INFO_SIZE) {
1730 log_err(ctx, "Invalid connection entry size: %u bytes.",
1731 entry_size);
1732 return JAYLINK_ERR_PROTO;
1735 table_size = num * entry_size;
1736 size = REG_HEADER_SIZE + table_size + info_size;
1738 if (size > REG_MAX_SIZE) {
1739 log_err(ctx, "Maximum registration information size exceeded: "
1740 "%u bytes.", size);
1741 return JAYLINK_ERR_PROTO;
1744 if (size > REG_MIN_SIZE) {
1745 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1747 if (ret != JAYLINK_OK) {
1748 log_err(ctx, "transport_start_read() failed: %s.",
1749 jaylink_strerror(ret));
1750 return JAYLINK_ERR;
1753 ret = transport_read(devh, buf + REG_MIN_SIZE,
1754 size - REG_MIN_SIZE);
1756 if (ret != JAYLINK_OK) {
1757 log_err(ctx, "transport_read() failed: %s.",
1758 jaylink_strerror(ret));
1759 return JAYLINK_ERR;
1763 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1765 *count = num;
1767 return JAYLINK_OK;