Add functions to query information about TCP/IP devices
[libjaylink.git] / libjaylink / device.c
bloba02585c341d2a0c640ae1566143364ef8617b97d
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 #include <stdlib.h>
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #ifdef _WIN32
25 #include <winsock2.h>
26 #else
27 #include <sys/socket.h>
28 #include <arpa/inet.h>
29 #endif
30 #include <libusb.h>
32 #include "libjaylink.h"
33 #include "libjaylink-internal.h"
35 /**
36 * @file
38 * Device enumeration and handling.
41 /** @cond PRIVATE */
42 #define CMD_GET_VERSION 0x01
43 #define CMD_GET_HW_STATUS 0x07
44 #define CMD_REGISTER 0x09
45 #define CMD_GET_HW_INFO 0xc1
46 #define CMD_GET_COUNTERS 0xc2
47 #define CMD_GET_FREE_MEMORY 0xd4
48 #define CMD_GET_CAPS 0xe8
49 #define CMD_GET_EXT_CAPS 0xed
50 #define CMD_GET_HW_VERSION 0xf0
51 #define CMD_READ_CONFIG 0xf2
52 #define CMD_WRITE_CONFIG 0xf3
54 #define REG_CMD_REGISTER 0x64
55 #define REG_CMD_UNREGISTER 0x65
57 /** Size of the registration header in bytes. */
58 #define REG_HEADER_SIZE 8
59 /** Minimum registration information size in bytes. */
60 #define REG_MIN_SIZE 0x4c
61 /** Maximum registration information size in bytes. */
62 #define REG_MAX_SIZE 0x200
63 /** Size of a connection entry in bytes. */
64 #define REG_CONN_INFO_SIZE 16
65 /** @endcond */
67 /** @private */
68 JAYLINK_PRIV struct jaylink_device *device_allocate(
69 struct jaylink_context *ctx)
71 struct jaylink_device *dev;
72 struct list *list;
74 dev = malloc(sizeof(struct jaylink_device));
76 if (!dev)
77 return NULL;
79 list = list_prepend(ctx->devs, dev);
81 if (!list) {
82 free(dev);
83 return NULL;
86 ctx->devs = list;
88 dev->ctx = ctx;
89 dev->ref_count = 1;
91 return dev;
94 static struct jaylink_device **allocate_device_list(size_t length)
96 struct jaylink_device **list;
98 list = malloc(sizeof(struct jaylink_device *) * (length + 1));
100 if (!list)
101 return NULL;
103 list[length] = NULL;
105 return list;
109 * Get available devices.
111 * @param[in,out] ctx libjaylink context.
112 * @param[out] devs Newly allocated array which contains instances of available
113 * devices on success, and undefined on failure. The array is
114 * NULL-terminated and must be free'd by the caller with
115 * jaylink_free_devices().
116 * @param[out] count Number of available devices on success, and undefined on
117 * failure. Can be NULL.
119 * @retval JAYLINK_OK Success.
120 * @retval JAYLINK_ERR_ARG Invalid arguments.
121 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
122 * @retval JAYLINK_ERR Other error conditions.
124 * @see jaylink_discovery_scan()
126 * @since 0.1.0
128 JAYLINK_API int jaylink_get_devices(struct jaylink_context *ctx,
129 struct jaylink_device ***devs, size_t *count)
131 size_t num;
132 struct list *item;
133 struct jaylink_device **tmp;
134 struct jaylink_device *dev;
135 size_t i;
137 if (!ctx || !devs)
138 return JAYLINK_ERR_ARG;
140 num = list_length(ctx->discovered_devs);
141 tmp = allocate_device_list(num);
143 if (!tmp) {
144 log_err(ctx, "Failed to allocate device list.");
145 return JAYLINK_ERR_MALLOC;
148 item = ctx->discovered_devs;
150 for (i = 0; i < num; i++) {
151 dev = (struct jaylink_device *)item->data;
152 tmp[i] = jaylink_ref_device(dev);
153 item = item->next;
156 if (count)
157 *count = num;
159 *devs = tmp;
161 return JAYLINK_OK;
165 * Free devices.
167 * @param[in,out] devs Array of device instances. Must be NULL-terminated.
168 * @param[in] unref Determines whether the device instances should be
169 * unreferenced.
171 * @see jaylink_get_devices()
173 * @since 0.1.0
175 JAYLINK_API void jaylink_free_devices(struct jaylink_device **devs, bool unref)
177 size_t i;
179 if (!devs)
180 return;
182 if (unref) {
183 for (i = 0; devs[i]; i++)
184 jaylink_unref_device(devs[i]);
187 free(devs);
191 * Get the host interface of a device.
193 * @param[in] dev Device instance.
194 * @param[out] iface Host interface of the device on success, and undefined on
195 * failure.
197 * @retval JAYLINK_OK Success.
198 * @retval JAYLINK_ERR_ARG Invalid arguments.
200 * @since 0.1.0
202 JAYLINK_API int jaylink_device_get_host_interface(
203 const struct jaylink_device *dev,
204 enum jaylink_host_interface *iface)
206 if (!dev || !iface)
207 return JAYLINK_ERR_ARG;
209 *iface = dev->interface;
211 return JAYLINK_OK;
215 * Get the serial number of a device.
217 * @note This serial number is for enumeration purpose only and might differ
218 * from the real serial number of the device.
220 * @param[in] dev Device instance.
221 * @param[out] serial_number Serial number of the device on success, and
222 * undefined on failure.
224 * @retval JAYLINK_OK Success.
225 * @retval JAYLINK_ERR_ARG Invalid arguments.
226 * @retval JAYLINK_ERR_NOT_AVAILABLE Serial number is not available.
228 * @since 0.1.0
230 JAYLINK_API int jaylink_device_get_serial_number(
231 const struct jaylink_device *dev, uint32_t *serial_number)
233 if (!dev || !serial_number)
234 return JAYLINK_ERR_ARG;
236 if (!dev->valid_serial_number)
237 return JAYLINK_ERR_NOT_AVAILABLE;
239 *serial_number = dev->serial_number;
241 return JAYLINK_OK;
245 * Get the USB address of a device.
247 * @note Identification of a device with the USB address is deprecated and the
248 * serial number should be used instead.
250 * @param[in] dev Device instance.
251 * @param[out] address USB address of the device on success, and undefined on
252 * failure.
254 * @retval JAYLINK_OK Success.
255 * @retval JAYLINK_ERR_ARG Invalid arguments.
256 * @retval JAYLINK_ERR_NOT_SUPPORTED Operation not supported.
258 * @see jaylink_device_get_serial_number()
260 * @since 0.1.0
262 JAYLINK_API int jaylink_device_get_usb_address(
263 const struct jaylink_device *dev,
264 enum jaylink_usb_address *address)
266 if (!dev || !address)
267 return JAYLINK_ERR_ARG;
269 if (dev->interface != JAYLINK_HIF_USB)
270 return JAYLINK_ERR_NOT_SUPPORTED;
272 *address = dev->usb_address;
274 return JAYLINK_OK;
278 * Get the IPv4 address string of a device.
280 * @param[in] dev Device instance.
281 * @param[out] address IPv4 address string in quad-dotted decimal format of the
282 * device on success and undefined on failure.
284 * @retval JAYLINK_OK Success.
285 * @retval JAYLINK_ERR_ARG Invalid arguments.
286 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
287 * #JAYLINK_HIF_TCP only.
289 * @since 0.2.0
291 JAYLINK_API int jaylink_device_get_ipv4_address(
292 const struct jaylink_device *dev, char *address)
294 if (!dev || !address)
295 return JAYLINK_ERR_ARG;
297 if (dev->interface != JAYLINK_HIF_TCP)
298 return JAYLINK_ERR_NOT_SUPPORTED;
300 memcpy(address, dev->ipv4_address, sizeof(dev->ipv4_address));
302 return JAYLINK_OK;
306 * Get the MAC address of a device.
308 * @param[in] dev Device instance.
309 * @param[out] address MAC address of the device on success and undefined on
310 * failure. The length of the MAC address is
311 * #JAYLINK_MAC_ADDRESS_LENGTH bytes.
313 * @retval JAYLINK_OK Success.
314 * @retval JAYLINK_ERR_ARG Invalid arguments.
315 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
316 * #JAYLINK_HIF_TCP only.
317 * @retval JAYLINK_ERR_NOT_AVAILABLE MAC address is not available.
319 * @since 0.2.0
321 JAYLINK_API int jaylink_device_get_mac_address(
322 const struct jaylink_device *dev, uint8_t *address)
324 if (!dev || !address)
325 return JAYLINK_ERR_ARG;
327 if (dev->interface != JAYLINK_HIF_TCP)
328 return JAYLINK_ERR_NOT_SUPPORTED;
330 if (!dev->has_mac_address)
331 return JAYLINK_ERR_NOT_AVAILABLE;
333 memcpy(address, dev->mac_address, sizeof(dev->mac_address));
335 return JAYLINK_OK;
339 * Get the hardware version of a device.
341 * @note The hardware type can not be obtained by this function, use
342 * jaylink_get_hardware_version() instead.
344 * @param[in] dev Device instance.
345 * @param[out] version Hardware version of the device on success and undefined
346 * on failure.
348 * @retval JAYLINK_OK Success.
349 * @retval JAYLINK_ERR_ARG Invalid arguments.
350 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
351 * #JAYLINK_HIF_TCP only.
352 * @retval JAYLINK_ERR_NOT_AVAILABLE Hardware version is not available.
354 * @since 0.2.0
356 JAYLINK_API int jaylink_device_get_hardware_version(
357 const struct jaylink_device *dev,
358 struct jaylink_hardware_version *version)
360 if (!dev || !version)
361 return JAYLINK_ERR_ARG;
363 if (dev->interface != JAYLINK_HIF_TCP)
364 return JAYLINK_ERR_NOT_SUPPORTED;
366 if (!dev->has_hw_version)
367 return JAYLINK_ERR_NOT_AVAILABLE;
369 *version = dev->hw_version;
371 return JAYLINK_OK;
375 * Get the product name of a device.
377 * @param[in] dev Device instance.
378 * @param[out] name Product name of the device on success and undefined on
379 * failure. The maximum length of the product name is
380 * #JAYLINK_PRODUCT_NAME_MAX_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 Product name is not available.
388 * @since 0.2.0
390 JAYLINK_API int jaylink_device_get_product_name(
391 const struct jaylink_device *dev, char *name)
393 if (!dev || !name)
394 return JAYLINK_ERR_ARG;
396 if (dev->interface != JAYLINK_HIF_TCP)
397 return JAYLINK_ERR_NOT_SUPPORTED;
399 if (!dev->has_product_name)
400 return JAYLINK_ERR_NOT_AVAILABLE;
402 memcpy(name, dev->product_name, sizeof(dev->product_name));
404 return JAYLINK_OK;
408 * Get the nickname of a device.
410 * @param[in] dev Device instance.
411 * @param[out] nickname Nickname of the device on success and undefined on
412 * failure. The maximum length of the nickname is
413 * #JAYLINK_NICKNAME_MAX_LENGTH bytes.
415 * @retval JAYLINK_OK Success.
416 * @retval JAYLINK_ERR_ARG Invalid arguments.
417 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
418 * #JAYLINK_HIF_TCP only.
419 * @retval JAYLINK_ERR_NOT_AVAILABLE Nickname is not available.
421 * @since 0.2.0
423 JAYLINK_API int jaylink_device_get_nickname(const struct jaylink_device *dev,
424 char *nickname)
426 if (!dev || !nickname)
427 return JAYLINK_ERR_ARG;
429 if (dev->interface != JAYLINK_HIF_TCP)
430 return JAYLINK_ERR_NOT_SUPPORTED;
432 if (!dev->has_nickname)
433 return JAYLINK_ERR_NOT_AVAILABLE;
435 memcpy(nickname, dev->nickname, sizeof(dev->nickname));
437 return JAYLINK_OK;
441 * Increment the reference count of a device.
443 * @param[in,out] dev Device instance.
445 * @return The given device instance on success, or NULL on invalid argument.
447 * @since 0.1.0
449 JAYLINK_API struct jaylink_device *jaylink_ref_device(
450 struct jaylink_device *dev)
452 if (!dev)
453 return NULL;
455 dev->ref_count++;
457 return dev;
461 * Decrement the reference count of a device.
463 * @param[in,out] dev Device instance.
465 * @since 0.1.0
467 JAYLINK_API void jaylink_unref_device(struct jaylink_device *dev)
469 struct jaylink_context *ctx;
471 if (!dev)
472 return;
474 dev->ref_count--;
476 if (!dev->ref_count) {
477 ctx = dev->ctx;
478 ctx->devs = list_remove(dev->ctx->devs, dev);
480 if (dev->interface == JAYLINK_HIF_USB) {
481 log_dbg(ctx, "Device destroyed (bus:address = "
482 "%03u:%03u).",
483 libusb_get_bus_number(dev->usb_dev),
484 libusb_get_device_address(dev->usb_dev));
486 libusb_unref_device(dev->usb_dev);
487 } else if (dev->interface == JAYLINK_HIF_TCP) {
488 log_dbg(ctx, "Device destroyed (IPv4 address = %s).",
489 dev->ipv4_address);
490 } else {
491 log_err(ctx, "BUG: Invalid host interface: %u.",
492 dev->interface);
495 free(dev);
499 static struct jaylink_device_handle *allocate_device_handle(
500 struct jaylink_device *dev)
502 struct jaylink_device_handle *devh;
504 devh = malloc(sizeof(struct jaylink_device_handle));
506 if (!devh)
507 return NULL;
509 devh->dev = jaylink_ref_device(dev);
511 return devh;
514 static void free_device_handle(struct jaylink_device_handle *devh)
516 jaylink_unref_device(devh->dev);
517 free(devh);
521 * Open a device.
523 * @param[in,out] dev Device instance.
524 * @param[out] devh Newly allocated handle for the opened device on success,
525 * and undefined on failure.
527 * @retval JAYLINK_OK Success.
528 * @retval JAYLINK_ERR_ARG Invalid arguments.
529 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
530 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
531 * @retval JAYLINK_ERR_NOT_SUPPORTED Operation not supported.
532 * @retval JAYLINK_ERR_IO Input/output error.
533 * @retval JAYLINK_ERR Other error conditions.
535 * @since 0.1.0
537 JAYLINK_API int jaylink_open(struct jaylink_device *dev,
538 struct jaylink_device_handle **devh)
540 int ret;
541 struct jaylink_device_handle *handle;
543 if (!dev || !devh)
544 return JAYLINK_ERR_ARG;
546 if (dev->interface != JAYLINK_HIF_USB)
547 return JAYLINK_ERR_NOT_SUPPORTED;
549 handle = allocate_device_handle(dev);
551 if (!handle) {
552 log_err(dev->ctx, "Device handle malloc failed.");
553 return JAYLINK_ERR_MALLOC;
556 ret = transport_open(handle);
558 if (ret != JAYLINK_OK) {
559 free_device_handle(handle);
560 return ret;
563 *devh = handle;
565 return JAYLINK_OK;
569 * Close a device.
571 * @param[in,out] devh Device instance.
573 * @retval JAYLINK_OK Success.
574 * @retval JAYLINK_ERR_ARG Invalid arguments.
575 * @retval JAYLINK_ERR Other error conditions.
577 * @since 0.1.0
579 JAYLINK_API int jaylink_close(struct jaylink_device_handle *devh)
581 int ret;
583 if (!devh)
584 return JAYLINK_ERR_ARG;
586 ret = transport_close(devh);
587 free_device_handle(devh);
589 return ret;
593 * Get the device instance from a device handle.
595 * @note The reference count of the device instance is not increased.
597 * @param[in] devh Device handle.
599 * @return The device instance on success, or NULL on invalid argument.
601 * @since 0.1.0
603 JAYLINK_API struct jaylink_device *jaylink_get_device(
604 struct jaylink_device_handle *devh)
606 if (!devh)
607 return NULL;
609 return devh->dev;
613 * Retrieve the firmware version of a device.
615 * @param[in,out] devh Device handle.
616 * @param[out] version Newly allocated string which contains the firmware
617 * version on success, and undefined if @p length is zero
618 * or on failure. The string is null-terminated and must be
619 * free'd by the caller.
620 * @param[out] length Length of the firmware version string including trailing
621 * null-terminator on success, and undefined on failure.
622 * Zero if no firmware version string is available.
624 * @retval JAYLINK_OK Success.
625 * @retval JAYLINK_ERR_ARG Invalid arguments.
626 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
627 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
628 * @retval JAYLINK_ERR_IO Input/output error.
629 * @retval JAYLINK_ERR Other error conditions.
631 * @since 0.1.0
633 JAYLINK_API int jaylink_get_firmware_version(
634 struct jaylink_device_handle *devh, char **version,
635 size_t *length)
637 int ret;
638 struct jaylink_context *ctx;
639 uint8_t buf[2];
640 uint16_t dummy;
641 char *tmp;
643 if (!devh || !version || !length)
644 return JAYLINK_ERR_ARG;
646 ctx = devh->dev->ctx;
647 ret = transport_start_write_read(devh, 1, 2, true);
649 if (ret != JAYLINK_OK) {
650 log_err(ctx, "transport_start_write_read() failed: %s.",
651 jaylink_strerror(ret));
652 return ret;
655 buf[0] = CMD_GET_VERSION;
657 ret = transport_write(devh, buf, 1);
659 if (ret != JAYLINK_OK) {
660 log_err(ctx, "transport_write() failed: %s.",
661 jaylink_strerror(ret));
662 return ret;
665 ret = transport_read(devh, buf, 2);
667 if (ret != JAYLINK_OK) {
668 log_err(ctx, "transport_read() failed: %s.",
669 jaylink_strerror(ret));
670 return ret;
673 dummy = buffer_get_u16(buf, 0);
674 *length = dummy;
676 if (!dummy)
677 return JAYLINK_OK;
679 ret = transport_start_read(devh, dummy);
681 if (ret != JAYLINK_OK) {
682 log_err(ctx, "transport_start_read() failed: %s.",
683 jaylink_strerror(ret));
684 return ret;
687 tmp = malloc(dummy);
689 if (!tmp) {
690 log_err(ctx, "Firmware version string malloc failed.");
691 return JAYLINK_ERR_MALLOC;
694 ret = transport_read(devh, (uint8_t *)tmp, dummy);
696 if (ret != JAYLINK_OK) {
697 log_err(ctx, "transport_read() failed: %s.",
698 jaylink_strerror(ret));
699 free(tmp);
700 return ret;
703 /* Last byte is reserved for null-terminator. */
704 tmp[dummy - 1] = 0;
705 *version = tmp;
707 return JAYLINK_OK;
711 * Retrieve the hardware information of a device.
713 * @note This function must only be used if the device has the
714 * #JAYLINK_DEV_CAP_GET_HW_INFO capability.
716 * @param[in,out] devh Device handle.
717 * @param[in] mask A bit field where each set bit represents hardware
718 * information to request. See #jaylink_hardware_info for a
719 * description of the hardware information and their bit
720 * positions.
721 * @param[out] info Array to store the hardware information on success. Its
722 * content is undefined on failure. The array must be large
723 * enough to contain at least as many elements as bits set in
724 * @a mask.
726 * @retval JAYLINK_OK Success.
727 * @retval JAYLINK_ERR_ARG Invalid arguments.
728 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
729 * @retval JAYLINK_ERR_IO Input/output error.
730 * @retval JAYLINK_ERR Other error conditions.
732 * @since 0.1.0
734 JAYLINK_API int jaylink_get_hardware_info(struct jaylink_device_handle *devh,
735 uint32_t mask, uint32_t *info)
737 int ret;
738 struct jaylink_context *ctx;
739 uint8_t buf[5];
740 unsigned int i;
741 unsigned int num;
742 unsigned int length;
744 if (!devh || !mask || !info)
745 return JAYLINK_ERR_ARG;
747 ctx = devh->dev->ctx;
748 num = 0;
750 for (i = 0; i < 32; i++) {
751 if (mask & (1 << i))
752 num++;
755 length = num * sizeof(uint32_t);
757 ret = transport_start_write_read(devh, 5, length, true);
759 if (ret != JAYLINK_OK) {
760 log_err(ctx, "transport_start_write_read() failed: %s.",
761 jaylink_strerror(ret));
762 return ret;
765 buf[0] = CMD_GET_HW_INFO;
766 buffer_set_u32(buf, mask, 1);
768 ret = transport_write(devh, buf, 5);
770 if (ret != JAYLINK_OK) {
771 log_err(ctx, "transport_write() failed: %s.",
772 jaylink_strerror(ret));
773 return ret;
776 ret = transport_read(devh, (uint8_t *)info, length);
778 if (ret != JAYLINK_OK) {
779 log_err(ctx, "transport_read() failed: %s.",
780 jaylink_strerror(ret));
781 return ret;
784 for (i = 0; i < num; i++)
785 info[i] = buffer_get_u32((uint8_t *)info,
786 i * sizeof(uint32_t));
788 return JAYLINK_OK;
792 * Retrieve the counter values of a device.
794 * @note This function must only be used if the device has the
795 * #JAYLINK_DEV_CAP_GET_COUNTERS capability.
797 * @param[in,out] devh Device handle.
798 * @param[in] mask A bit field where each set bit represents a counter value to
799 * request. See #jaylink_counter for a description of the
800 * counters and their bit positions.
801 * @param[out] values Array to store the counter values on success. Its content
802 * is undefined on failure. The array must be large enough
803 * to contain at least as many elements as bits set in @p
804 * mask.
806 * @retval JAYLINK_OK Success.
807 * @retval JAYLINK_ERR_ARG Invalid arguments.
808 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
809 * @retval JAYLINK_ERR_IO Input/output error.
810 * @retval JAYLINK_ERR Other error conditions.
812 * @since 0.2.0
814 JAYLINK_API int jaylink_get_counters(struct jaylink_device_handle *devh,
815 uint32_t mask, uint32_t *values)
817 int ret;
818 struct jaylink_context *ctx;
819 uint8_t buf[5];
820 unsigned int i;
821 unsigned int num;
822 unsigned int length;
824 if (!devh || !mask || !values)
825 return JAYLINK_ERR_ARG;
827 ctx = devh->dev->ctx;
828 num = 0;
830 for (i = 0; i < 32; i++) {
831 if (mask & (1 << i))
832 num++;
835 length = num * sizeof(uint32_t);
836 ret = transport_start_write_read(devh, 5, length, true);
838 if (ret != JAYLINK_OK) {
839 log_err(ctx, "transport_start_write_read() failed: %s.",
840 jaylink_strerror(ret));
841 return ret;
844 buf[0] = CMD_GET_COUNTERS;
845 buffer_set_u32(buf, mask, 1);
847 ret = transport_write(devh, buf, 5);
849 if (ret != JAYLINK_OK) {
850 log_err(ctx, "transport_write() failed: %s.",
851 jaylink_strerror(ret));
852 return ret;
855 ret = transport_read(devh, (uint8_t *)values, length);
857 if (ret != JAYLINK_OK) {
858 log_err(ctx, "transport_read() failed: %s.",
859 jaylink_strerror(ret));
860 return ret;
863 for (i = 0; i < num; i++)
864 values[i] = buffer_get_u32((uint8_t *)values,
865 i * sizeof(uint32_t));
867 return JAYLINK_OK;
871 * Retrieve the hardware version of a device.
873 * @note This function must only be used if the device has the
874 * #JAYLINK_DEV_CAP_GET_HW_VERSION capability.
876 * @warning This function may return a value for @p version where
877 * #jaylink_hardware_version::type is not covered by
878 * #jaylink_hardware_type.
880 * @param[in,out] devh Device handle.
881 * @param[out] version Hardware version on success, and undefined on failure.
883 * @retval JAYLINK_OK Success.
884 * @retval JAYLINK_ERR_ARG Invalid arguments.
885 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
886 * @retval JAYLINK_ERR_IO Input/output error.
887 * @retval JAYLINK_ERR Other error conditions.
889 * @since 0.1.0
891 JAYLINK_API int jaylink_get_hardware_version(
892 struct jaylink_device_handle *devh,
893 struct jaylink_hardware_version *version)
895 int ret;
896 struct jaylink_context *ctx;
897 uint8_t buf[4];
898 uint32_t tmp;
900 if (!devh || !version)
901 return JAYLINK_ERR_ARG;
903 ctx = devh->dev->ctx;
904 ret = transport_start_write_read(devh, 1, 4, true);
906 if (ret != JAYLINK_OK) {
907 log_err(ctx, "transport_start_write_read() failed: %s.",
908 jaylink_strerror(ret));
909 return ret;
912 buf[0] = CMD_GET_HW_VERSION;
914 ret = transport_write(devh, buf, 1);
916 if (ret != JAYLINK_OK) {
917 log_err(ctx, "transport_write() failed: %s.",
918 jaylink_strerror(ret));
919 return ret;
922 ret = transport_read(devh, buf, 4);
924 if (ret != JAYLINK_OK) {
925 log_err(ctx, "transport_read() failed: %s.",
926 jaylink_strerror(ret));
927 return ret;
930 tmp = buffer_get_u32(buf, 0);
932 version->type = (tmp / 1000000) % 100;
933 version->major = (tmp / 10000) % 100;
934 version->minor = (tmp / 100) % 100;
935 version->revision = tmp % 100;
937 return JAYLINK_OK;
941 * Retrieve the hardware status of a device.
943 * @param[in,out] devh Device handle.
944 * @param[out] status Hardware status on success, and undefined on failure.
946 * @retval JAYLINK_OK Success.
947 * @retval JAYLINK_ERR_ARG Invalid arguments.
948 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
949 * @retval JAYLINK_ERR_IO Input/output error.
950 * @retval JAYLINK_ERR Other error conditions.
952 * @since 0.1.0
954 JAYLINK_API int jaylink_get_hardware_status(struct jaylink_device_handle *devh,
955 struct jaylink_hardware_status *status)
957 int ret;
958 struct jaylink_context *ctx;
959 uint8_t buf[8];
961 if (!devh || !status)
962 return JAYLINK_ERR_ARG;
964 ctx = devh->dev->ctx;
965 ret = transport_start_write_read(devh, 1, 8, true);
967 if (ret != JAYLINK_OK) {
968 log_err(ctx, "transport_start_write_read() failed: %s.",
969 jaylink_strerror(ret));
970 return ret;
973 buf[0] = CMD_GET_HW_STATUS;
975 ret = transport_write(devh, buf, 1);
977 if (ret != JAYLINK_OK) {
978 log_err(ctx, "transport_write() failed: %s.",
979 jaylink_strerror(ret));
980 return ret;
983 ret = transport_read(devh, buf, 8);
985 if (ret != JAYLINK_OK) {
986 log_err(ctx, "transport_read() failed: %s.",
987 jaylink_strerror(ret));
988 return ret;
991 status->target_voltage = buffer_get_u16(buf, 0);
992 status->tck = buf[2];
993 status->tdi = buf[3];
994 status->tdo = buf[4];
995 status->tms = buf[5];
996 status->tres = buf[6];
997 status->trst = buf[7];
999 return JAYLINK_OK;
1003 * Retrieve the capabilities of a device.
1005 * The capabilities are stored in a 32-bit bit array consisting of
1006 * #JAYLINK_DEV_CAPS_SIZE bytes where each individual bit represents a
1007 * capability. The first bit of this array is the least significant bit of the
1008 * first byte and the following bits are sequentially numbered in order of
1009 * increasing bit significance and byte index. A set bit indicates a supported
1010 * capability. See #jaylink_device_capability for a description of the
1011 * capabilities and their bit positions.
1013 * @param[in,out] devh Device handle.
1014 * @param[out] caps Buffer to store capabilities on success. Its content is
1015 * undefined on failure. The buffer must be large enough to
1016 * contain at least #JAYLINK_DEV_CAPS_SIZE bytes.
1018 * @retval JAYLINK_OK Success.
1019 * @retval JAYLINK_ERR_ARG Invalid arguments.
1020 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1021 * @retval JAYLINK_ERR_IO Input/output error.
1022 * @retval JAYLINK_ERR Other error conditions.
1024 * @see jaylink_get_extended_caps()
1025 * @see jaylink_has_cap()
1027 * @since 0.1.0
1029 JAYLINK_API int jaylink_get_caps(struct jaylink_device_handle *devh,
1030 uint8_t *caps)
1032 int ret;
1033 struct jaylink_context *ctx;
1034 uint8_t buf[1];
1036 if (!devh || !caps)
1037 return JAYLINK_ERR_ARG;
1039 ctx = devh->dev->ctx;
1040 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CAPS_SIZE, true);
1042 if (ret != JAYLINK_OK) {
1043 log_err(ctx, "transport_start_write_read() failed: %s.",
1044 jaylink_strerror(ret));
1045 return ret;
1048 buf[0] = CMD_GET_CAPS;
1050 ret = transport_write(devh, buf, 1);
1052 if (ret != JAYLINK_OK) {
1053 log_err(ctx, "transport_write() failed: %s.",
1054 jaylink_strerror(ret));
1055 return ret;
1058 ret = transport_read(devh, caps, JAYLINK_DEV_CAPS_SIZE);
1060 if (ret != JAYLINK_OK) {
1061 log_err(ctx, "transport_read() failed: %s.",
1062 jaylink_strerror(ret));
1063 return ret;
1066 return JAYLINK_OK;
1070 * Retrieve the extended capabilities of a device.
1072 * The extended capabilities are stored in a 256-bit bit array consisting of
1073 * #JAYLINK_DEV_EXT_CAPS_SIZE bytes. See jaylink_get_caps() for a further
1074 * description of how the capabilities are represented in this bit array. For a
1075 * description of the capabilities and their bit positions, see
1076 * #jaylink_device_capability.
1078 * @note This function must only be used if the device has the
1079 * #JAYLINK_DEV_CAP_GET_EXT_CAPS capability.
1081 * @param[in,out] devh Device handle.
1082 * @param[out] caps Buffer to store capabilities on success. Its content is
1083 * undefined on failure. The buffer must be large enough to
1084 * contain at least #JAYLINK_DEV_EXT_CAPS_SIZE bytes.
1086 * @retval JAYLINK_OK Success.
1087 * @retval JAYLINK_ERR_ARG Invalid arguments.
1088 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1089 * @retval JAYLINK_ERR_IO Input/output error.
1090 * @retval JAYLINK_ERR Other error conditions.
1092 * @see jaylink_get_caps()
1094 * @since 0.1.0
1096 JAYLINK_API int jaylink_get_extended_caps(struct jaylink_device_handle *devh,
1097 uint8_t *caps)
1099 int ret;
1100 struct jaylink_context *ctx;
1101 uint8_t buf[1];
1103 if (!devh || !caps)
1104 return JAYLINK_ERR_ARG;
1106 ctx = devh->dev->ctx;
1107 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_EXT_CAPS_SIZE,
1108 true);
1110 if (ret != JAYLINK_OK) {
1111 log_err(ctx, "transport_start_write_read() failed: %s.",
1112 jaylink_strerror(ret));
1113 return ret;
1116 buf[0] = CMD_GET_EXT_CAPS;
1118 ret = transport_write(devh, buf, 1);
1120 if (ret != JAYLINK_OK) {
1121 log_err(ctx, "transport_write() failed: %s.",
1122 jaylink_strerror(ret));
1123 return ret;
1126 ret = transport_read(devh, caps, JAYLINK_DEV_EXT_CAPS_SIZE);
1128 if (ret != JAYLINK_OK) {
1129 log_err(ctx, "transport_read() failed: %s.",
1130 jaylink_strerror(ret));
1131 return ret;
1134 return JAYLINK_OK;
1138 * Retrieve the size of free memory of a device.
1140 * @note This function must only be used if the device has the
1141 * #JAYLINK_DEV_CAP_GET_FREE_MEMORY capability.
1143 * @param[in,out] devh Device handle.
1144 * @param[out] size Size of free memory in bytes on success, and undefined on
1145 * failure.
1147 * @retval JAYLINK_OK Success.
1148 * @retval JAYLINK_ERR_ARG Invalid arguments.
1149 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1150 * @retval JAYLINK_ERR_IO Input/output error.
1151 * @retval JAYLINK_ERR Other error conditions.
1153 * @since 0.1.0
1155 JAYLINK_API int jaylink_get_free_memory(struct jaylink_device_handle *devh,
1156 uint32_t *size)
1158 int ret;
1159 struct jaylink_context *ctx;
1160 uint8_t buf[4];
1162 if (!devh || !size)
1163 return JAYLINK_ERR_ARG;
1165 ctx = devh->dev->ctx;
1166 ret = transport_start_write_read(devh, 1, 4, true);
1168 if (ret != JAYLINK_OK) {
1169 log_err(ctx, "transport_start_write_read() failed: %s.",
1170 jaylink_strerror(ret));
1171 return ret;
1174 buf[0] = CMD_GET_FREE_MEMORY;
1176 ret = transport_write(devh, buf, 1);
1178 if (ret != JAYLINK_OK) {
1179 log_err(ctx, "transport_write() failed: %s.",
1180 jaylink_strerror(ret));
1181 return ret;
1184 ret = transport_read(devh, buf, 4);
1186 if (ret != JAYLINK_OK) {
1187 log_err(ctx, "transport_read() failed: %s.",
1188 jaylink_strerror(ret));
1189 return ret;
1192 *size = buffer_get_u32(buf, 0);
1194 return JAYLINK_OK;
1198 * Read the raw configuration data of a device.
1200 * @note This function must only be used if the device has the
1201 * #JAYLINK_DEV_CAP_READ_CONFIG capability.
1203 * @param[in,out] devh Device handle.
1204 * @param[out] config Buffer to store configuration data on success. Its
1205 * content is undefined on failure. The buffer must be large
1206 * enough to contain at least
1207 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1209 * @retval JAYLINK_OK Success.
1210 * @retval JAYLINK_ERR_ARG Invalid arguments.
1211 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1212 * @retval JAYLINK_ERR_IO Input/output error.
1213 * @retval JAYLINK_ERR Other error conditions.
1215 * @since 0.1.0
1217 JAYLINK_API int jaylink_read_raw_config(struct jaylink_device_handle *devh,
1218 uint8_t *config)
1220 int ret;
1221 struct jaylink_context *ctx;
1222 uint8_t buf[1];
1224 if (!devh || !config)
1225 return JAYLINK_ERR_ARG;
1227 ctx = devh->dev->ctx;
1228 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CONFIG_SIZE,
1229 true);
1231 if (ret != JAYLINK_OK) {
1232 log_err(ctx, "transport_start_write_read() failed: %s.",
1233 jaylink_strerror(ret));
1234 return ret;
1237 buf[0] = CMD_READ_CONFIG;
1239 ret = transport_write(devh, buf, 1);
1241 if (ret != JAYLINK_OK) {
1242 log_err(ctx, "transport_write() failed: %s.",
1243 jaylink_strerror(ret));
1244 return ret;
1247 ret = transport_read(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1249 if (ret != JAYLINK_OK) {
1250 log_err(ctx, "transport_read() failed: %s.",
1251 jaylink_strerror(ret));
1252 return ret;
1255 return JAYLINK_OK;
1259 * Write the raw configuration data of a device.
1261 * @note This function must only be used if the device has the
1262 * #JAYLINK_DEV_CAP_WRITE_CONFIG capability.
1264 * @param[in,out] devh Device handle.
1265 * @param[in] config Buffer to write configuration data from. The size of the
1266 * configuration data is expected to be
1267 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1269 * @retval JAYLINK_OK Success.
1270 * @retval JAYLINK_ERR_ARG Invalid arguments.
1271 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1272 * @retval JAYLINK_ERR_IO Input/output error.
1273 * @retval JAYLINK_ERR Other error conditions.
1275 * @since 0.1.0
1277 JAYLINK_API int jaylink_write_raw_config(struct jaylink_device_handle *devh,
1278 const uint8_t *config)
1280 int ret;
1281 struct jaylink_context *ctx;
1282 uint8_t buf[1];
1284 if (!devh || !config)
1285 return JAYLINK_ERR_ARG;
1287 ctx = devh->dev->ctx;
1288 ret = transport_start_write(devh, 1 + JAYLINK_DEV_CONFIG_SIZE, true);
1290 if (ret != JAYLINK_OK) {
1291 log_err(ctx, "transport_start_write() failed: %s.",
1292 jaylink_strerror(ret));
1293 return ret;
1296 buf[0] = CMD_WRITE_CONFIG;
1298 ret = transport_write(devh, buf, 1);
1300 if (ret != JAYLINK_OK) {
1301 log_err(ctx, "transport_write() failed: %s.",
1302 jaylink_strerror(ret));
1303 return ret;
1306 ret = transport_write(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1308 if (ret != JAYLINK_OK) {
1309 log_err(ctx, "transport_write() failed: %s.",
1310 jaylink_strerror(ret));
1311 return ret;
1314 return JAYLINK_OK;
1317 static void parse_conn_table(struct jaylink_connection *conns,
1318 const uint8_t *buffer, uint16_t num, uint16_t entry_size)
1320 unsigned int i;
1321 size_t offset;
1322 struct in_addr in;
1324 offset = 0;
1326 for (i = 0; i < num; i++) {
1327 conns[i].pid = buffer_get_u32(buffer, offset);
1329 in.s_addr = buffer_get_u32(buffer, offset + 4);
1331 * Use inet_ntoa() instead of inet_ntop() because the latter
1332 * requires at least Windows Vista.
1334 strcpy(conns[i].hid, inet_ntoa(in));
1336 conns[i].iid = buffer[offset + 8];
1337 conns[i].cid = buffer[offset + 9];
1338 conns[i].handle = buffer_get_u16(buffer, offset + 10);
1339 conns[i].timestamp = buffer_get_u32(buffer, offset + 12);
1340 offset = offset + entry_size;
1344 static bool _inet_pton(const char *str, struct in_addr *in)
1346 #ifdef _WIN32
1347 int ret;
1348 struct sockaddr_in sock_in;
1349 int length;
1351 length = sizeof(sock_in);
1354 * Use WSAStringToAddress() instead of inet_pton() because the latter
1355 * requires at least Windows Vista.
1357 ret = WSAStringToAddress((LPTSTR)str, AF_INET, NULL,
1358 (LPSOCKADDR)&sock_in, &length);
1360 if (ret != 0)
1361 return false;
1363 *in = sock_in.sin_addr;
1364 #else
1365 if (inet_pton(AF_INET, str, in) != 1)
1366 return false;
1367 #endif
1369 return true;
1373 * Register a connection on a device.
1375 * A connection can be registered by using 0 as handle. Additional information
1376 * about the connection can be attached whereby the timestamp is a read-only
1377 * value and therefore ignored for registration. On success, a new handle
1378 * greater than 0 is obtained from the device.
1380 * However, if an obtained handle does not appear in the list of device
1381 * connections, the connection was not registered because the maximum number of
1382 * connections on the device is reached.
1384 * @note This function must only be used if the device has the
1385 * #JAYLINK_DEV_CAP_REGISTER capability.
1387 * Example code:
1388 * @code{.c}
1389 * static bool register_connection(struct jaylink_device_handle *devh,
1390 * struct jaylink_connection *conn)
1392 * int ret;
1393 * struct jaylink_connection conns[JAYLINK_MAX_CONNECTIONS];
1394 * bool found_handle;
1395 * size_t count;
1396 * size_t i;
1398 * conn->handle = 0;
1399 * conn->pid = 0;
1400 * strcpy(conn->hid, "0.0.0.0");
1401 * conn->iid = 0;
1402 * conn->cid = 0;
1404 * ret = jaylink_register(devh, conn, conns, &count);
1406 * if (ret != JAYLINK_OK) {
1407 * printf("jaylink_register() failed: %s.\n",
1408 * jaylink_strerror(ret));
1409 * return false;
1412 * found_handle = false;
1414 * for (i = 0; i < count; i++) {
1415 * if (conns[i].handle == conn->handle) {
1416 * found_handle = true;
1417 * break;
1421 * if (!found_handle) {
1422 * printf("Maximum number of connections reached.\n");
1423 * return false;
1426 * printf("Connection successfully registered.\n");
1428 * return true;
1430 * @endcode
1432 * @param[in,out] devh Device handle.
1433 * @param[in,out] connection Connection to register on the device.
1434 * @param[out] connections Array to store device connections on success.
1435 * Its content is undefined on failure. The array must
1436 * be large enough to contain at least
1437 * #JAYLINK_MAX_CONNECTIONS elements.
1438 * @param[out] count Number of device connections on success, and undefined on
1439 * failure.
1441 * @retval JAYLINK_OK Success.
1442 * @retval JAYLINK_ERR_ARG Invalid arguments.
1443 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1444 * @retval JAYLINK_ERR_PROTO Protocol violation.
1445 * @retval JAYLINK_ERR_IO Input/output error.
1446 * @retval JAYLINK_ERR Other error conditions.
1448 * @see jaylink_unregister()
1450 * @since 0.1.0
1452 JAYLINK_API int jaylink_register(struct jaylink_device_handle *devh,
1453 struct jaylink_connection *connection,
1454 struct jaylink_connection *connections, size_t *count)
1456 int ret;
1457 struct jaylink_context *ctx;
1458 uint8_t buf[REG_MAX_SIZE];
1459 uint16_t handle;
1460 uint16_t num;
1461 uint16_t entry_size;
1462 uint32_t size;
1463 uint32_t table_size;
1464 uint16_t info_size;
1465 struct in_addr in;
1467 if (!devh || !connection || !connections || !count)
1468 return JAYLINK_ERR_ARG;
1470 ctx = devh->dev->ctx;
1472 buf[0] = CMD_REGISTER;
1473 buf[1] = REG_CMD_REGISTER;
1474 buffer_set_u32(buf, connection->pid, 2);
1476 if (!_inet_pton(connection->hid, &in))
1477 return JAYLINK_ERR_ARG;
1479 buffer_set_u32(buf, in.s_addr, 6);
1481 buf[10] = connection->iid;
1482 buf[11] = connection->cid;
1483 buffer_set_u16(buf, connection->handle, 12);
1485 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1487 if (ret != JAYLINK_OK) {
1488 log_err(ctx, "transport_start_write_read() failed: %s.",
1489 jaylink_strerror(ret));
1490 return ret;
1493 ret = transport_write(devh, buf, 14);
1495 if (ret != JAYLINK_OK) {
1496 log_err(ctx, "transport_write() failed: %s.",
1497 jaylink_strerror(ret));
1498 return ret;
1501 ret = transport_read(devh, buf, REG_MIN_SIZE);
1503 if (ret != JAYLINK_OK) {
1504 log_err(ctx, "transport_read() failed: %s.",
1505 jaylink_strerror(ret));
1506 return ret;
1509 handle = buffer_get_u16(buf, 0);
1510 num = buffer_get_u16(buf, 2);
1511 entry_size = buffer_get_u16(buf, 4);
1512 info_size = buffer_get_u16(buf, 6);
1514 if (num > JAYLINK_MAX_CONNECTIONS) {
1515 log_err(ctx, "Maximum number of device connections exceeded: "
1516 "%u.", num);
1517 return JAYLINK_ERR_PROTO;
1520 if (entry_size != REG_CONN_INFO_SIZE) {
1521 log_err(ctx, "Invalid connection entry size: %u bytes.",
1522 entry_size);
1523 return JAYLINK_ERR_PROTO;
1526 table_size = num * entry_size;
1527 size = REG_HEADER_SIZE + table_size + info_size;
1529 if (size > REG_MAX_SIZE) {
1530 log_err(ctx, "Maximum registration information size exceeded: "
1531 "%u bytes.", size);
1532 return JAYLINK_ERR_PROTO;
1535 if (size > REG_MIN_SIZE) {
1536 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1538 if (ret != JAYLINK_OK) {
1539 log_err(ctx, "transport_start_read() failed: %s.",
1540 jaylink_strerror(ret));
1541 return JAYLINK_ERR;
1544 ret = transport_read(devh, buf + REG_MIN_SIZE,
1545 size - REG_MIN_SIZE);
1547 if (ret != JAYLINK_OK) {
1548 log_err(ctx, "transport_read() failed: %s.",
1549 jaylink_strerror(ret));
1550 return JAYLINK_ERR;
1554 if (!handle) {
1555 log_err(ctx, "Obtained invalid connection handle.");
1556 return JAYLINK_ERR_PROTO;
1559 connection->handle = handle;
1560 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1562 *count = num;
1564 return JAYLINK_OK;
1568 * Unregister a connection from a device.
1570 * @note This function must only be used if the device has the
1571 * #JAYLINK_DEV_CAP_REGISTER capability.
1573 * @param[in,out] devh Device handle.
1574 * @param[in,out] connection Connection to unregister from the device.
1575 * @param[out] connections Array to store device connections on success.
1576 * Its content is undefined on failure. The array must
1577 * be large enough to contain at least
1578 * #JAYLINK_MAX_CONNECTIONS elements.
1579 * @param[out] count Number of device connections on success, and undefined on
1580 * failure.
1582 * @retval JAYLINK_OK Success.
1583 * @retval JAYLINK_ERR_ARG Invalid arguments.
1584 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1585 * @retval JAYLINK_ERR_PROTO Protocol violation.
1586 * @retval JAYLINK_ERR_IO Input/output error.
1587 * @retval JAYLINK_ERR Other error conditions.
1589 * @see jaylink_register()
1591 * @since 0.1.0
1593 JAYLINK_API int jaylink_unregister(struct jaylink_device_handle *devh,
1594 const struct jaylink_connection *connection,
1595 struct jaylink_connection *connections, size_t *count)
1597 int ret;
1598 struct jaylink_context *ctx;
1599 uint8_t buf[REG_MAX_SIZE];
1600 uint16_t num;
1601 uint16_t entry_size;
1602 uint32_t size;
1603 uint32_t table_size;
1604 uint16_t info_size;
1605 struct in_addr in;
1607 if (!devh || !connection || !connections || !count)
1608 return JAYLINK_ERR_ARG;
1610 ctx = devh->dev->ctx;
1612 buf[0] = CMD_REGISTER;
1613 buf[1] = REG_CMD_UNREGISTER;
1614 buffer_set_u32(buf, connection->pid, 2);
1616 if (!_inet_pton(connection->hid, &in))
1617 return JAYLINK_ERR_ARG;
1619 buffer_set_u32(buf, in.s_addr, 6);
1621 buf[10] = connection->iid;
1622 buf[11] = connection->cid;
1623 buffer_set_u16(buf, connection->handle, 12);
1625 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1627 if (ret != JAYLINK_OK) {
1628 log_err(ctx, "transport_start_write_read() failed: %s.",
1629 jaylink_strerror(ret));
1630 return ret;
1633 ret = transport_write(devh, buf, 14);
1635 if (ret != JAYLINK_OK) {
1636 log_err(ctx, "transport_write() failed: %s.",
1637 jaylink_strerror(ret));
1638 return ret;
1641 ret = transport_read(devh, buf, REG_MIN_SIZE);
1643 if (ret != JAYLINK_OK) {
1644 log_err(ctx, "transport_read() failed: %s.",
1645 jaylink_strerror(ret));
1646 return ret;
1649 num = buffer_get_u16(buf, 2);
1650 entry_size = buffer_get_u16(buf, 4);
1651 info_size = buffer_get_u16(buf, 6);
1653 if (num > JAYLINK_MAX_CONNECTIONS) {
1654 log_err(ctx, "Maximum number of device connections exceeded: "
1655 "%u.", num);
1656 return JAYLINK_ERR_PROTO;
1659 if (entry_size != REG_CONN_INFO_SIZE) {
1660 log_err(ctx, "Invalid connection entry size: %u bytes.",
1661 entry_size);
1662 return JAYLINK_ERR_PROTO;
1665 table_size = num * entry_size;
1666 size = REG_HEADER_SIZE + table_size + info_size;
1668 if (size > REG_MAX_SIZE) {
1669 log_err(ctx, "Maximum registration information size exceeded: "
1670 "%u bytes.", size);
1671 return JAYLINK_ERR_PROTO;
1674 if (size > REG_MIN_SIZE) {
1675 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1677 if (ret != JAYLINK_OK) {
1678 log_err(ctx, "transport_start_read() failed: %s.",
1679 jaylink_strerror(ret));
1680 return JAYLINK_ERR;
1683 ret = transport_read(devh, buf + REG_MIN_SIZE,
1684 size - REG_MIN_SIZE);
1686 if (ret != JAYLINK_OK) {
1687 log_err(ctx, "transport_read() failed: %s.",
1688 jaylink_strerror(ret));
1689 return JAYLINK_ERR;
1693 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1695 *count = num;
1697 return JAYLINK_OK;