transport: Add initial TCP/IP support
[libjaylink.git] / libjaylink / device.c
blobd9545635f6080916e1fd442e2933c78c8a7e0ea8
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_IO Input/output error.
532 * @retval JAYLINK_ERR Other error conditions.
534 * @since 0.1.0
536 JAYLINK_API int jaylink_open(struct jaylink_device *dev,
537 struct jaylink_device_handle **devh)
539 int ret;
540 struct jaylink_device_handle *handle;
542 if (!dev || !devh)
543 return JAYLINK_ERR_ARG;
545 handle = allocate_device_handle(dev);
547 if (!handle) {
548 log_err(dev->ctx, "Device handle malloc failed.");
549 return JAYLINK_ERR_MALLOC;
552 ret = transport_open(handle);
554 if (ret != JAYLINK_OK) {
555 free_device_handle(handle);
556 return ret;
559 *devh = handle;
561 return JAYLINK_OK;
565 * Close a device.
567 * @param[in,out] devh Device instance.
569 * @retval JAYLINK_OK Success.
570 * @retval JAYLINK_ERR_ARG Invalid arguments.
571 * @retval JAYLINK_ERR Other error conditions.
573 * @since 0.1.0
575 JAYLINK_API int jaylink_close(struct jaylink_device_handle *devh)
577 int ret;
579 if (!devh)
580 return JAYLINK_ERR_ARG;
582 ret = transport_close(devh);
583 free_device_handle(devh);
585 return ret;
589 * Get the device instance from a device handle.
591 * @note The reference count of the device instance is not increased.
593 * @param[in] devh Device handle.
595 * @return The device instance on success, or NULL on invalid argument.
597 * @since 0.1.0
599 JAYLINK_API struct jaylink_device *jaylink_get_device(
600 struct jaylink_device_handle *devh)
602 if (!devh)
603 return NULL;
605 return devh->dev;
609 * Retrieve the firmware version of a device.
611 * @param[in,out] devh Device handle.
612 * @param[out] version Newly allocated string which contains the firmware
613 * version on success, and undefined if @p length is zero
614 * or on failure. The string is null-terminated and must be
615 * free'd by the caller.
616 * @param[out] length Length of the firmware version string including trailing
617 * null-terminator on success, and undefined on failure.
618 * Zero if no firmware version string is available.
620 * @retval JAYLINK_OK Success.
621 * @retval JAYLINK_ERR_ARG Invalid arguments.
622 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
623 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
624 * @retval JAYLINK_ERR_IO Input/output error.
625 * @retval JAYLINK_ERR Other error conditions.
627 * @since 0.1.0
629 JAYLINK_API int jaylink_get_firmware_version(
630 struct jaylink_device_handle *devh, char **version,
631 size_t *length)
633 int ret;
634 struct jaylink_context *ctx;
635 uint8_t buf[2];
636 uint16_t dummy;
637 char *tmp;
639 if (!devh || !version || !length)
640 return JAYLINK_ERR_ARG;
642 ctx = devh->dev->ctx;
643 ret = transport_start_write_read(devh, 1, 2, true);
645 if (ret != JAYLINK_OK) {
646 log_err(ctx, "transport_start_write_read() failed: %s.",
647 jaylink_strerror(ret));
648 return ret;
651 buf[0] = CMD_GET_VERSION;
653 ret = transport_write(devh, buf, 1);
655 if (ret != JAYLINK_OK) {
656 log_err(ctx, "transport_write() failed: %s.",
657 jaylink_strerror(ret));
658 return ret;
661 ret = transport_read(devh, buf, 2);
663 if (ret != JAYLINK_OK) {
664 log_err(ctx, "transport_read() failed: %s.",
665 jaylink_strerror(ret));
666 return ret;
669 dummy = buffer_get_u16(buf, 0);
670 *length = dummy;
672 if (!dummy)
673 return JAYLINK_OK;
675 ret = transport_start_read(devh, dummy);
677 if (ret != JAYLINK_OK) {
678 log_err(ctx, "transport_start_read() failed: %s.",
679 jaylink_strerror(ret));
680 return ret;
683 tmp = malloc(dummy);
685 if (!tmp) {
686 log_err(ctx, "Firmware version string malloc failed.");
687 return JAYLINK_ERR_MALLOC;
690 ret = transport_read(devh, (uint8_t *)tmp, dummy);
692 if (ret != JAYLINK_OK) {
693 log_err(ctx, "transport_read() failed: %s.",
694 jaylink_strerror(ret));
695 free(tmp);
696 return ret;
699 /* Last byte is reserved for null-terminator. */
700 tmp[dummy - 1] = 0;
701 *version = tmp;
703 return JAYLINK_OK;
707 * Retrieve the hardware information of a device.
709 * @note This function must only be used if the device has the
710 * #JAYLINK_DEV_CAP_GET_HW_INFO capability.
712 * @param[in,out] devh Device handle.
713 * @param[in] mask A bit field where each set bit represents hardware
714 * information to request. See #jaylink_hardware_info for a
715 * description of the hardware information and their bit
716 * positions.
717 * @param[out] info Array to store the hardware information on success. Its
718 * content is undefined on failure. The array must be large
719 * enough to contain at least as many elements as bits set in
720 * @a mask.
722 * @retval JAYLINK_OK Success.
723 * @retval JAYLINK_ERR_ARG Invalid arguments.
724 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
725 * @retval JAYLINK_ERR_IO Input/output error.
726 * @retval JAYLINK_ERR Other error conditions.
728 * @since 0.1.0
730 JAYLINK_API int jaylink_get_hardware_info(struct jaylink_device_handle *devh,
731 uint32_t mask, uint32_t *info)
733 int ret;
734 struct jaylink_context *ctx;
735 uint8_t buf[5];
736 unsigned int i;
737 unsigned int num;
738 unsigned int length;
740 if (!devh || !mask || !info)
741 return JAYLINK_ERR_ARG;
743 ctx = devh->dev->ctx;
744 num = 0;
746 for (i = 0; i < 32; i++) {
747 if (mask & (1 << i))
748 num++;
751 length = num * sizeof(uint32_t);
753 ret = transport_start_write_read(devh, 5, length, true);
755 if (ret != JAYLINK_OK) {
756 log_err(ctx, "transport_start_write_read() failed: %s.",
757 jaylink_strerror(ret));
758 return ret;
761 buf[0] = CMD_GET_HW_INFO;
762 buffer_set_u32(buf, mask, 1);
764 ret = transport_write(devh, buf, 5);
766 if (ret != JAYLINK_OK) {
767 log_err(ctx, "transport_write() failed: %s.",
768 jaylink_strerror(ret));
769 return ret;
772 ret = transport_read(devh, (uint8_t *)info, length);
774 if (ret != JAYLINK_OK) {
775 log_err(ctx, "transport_read() failed: %s.",
776 jaylink_strerror(ret));
777 return ret;
780 for (i = 0; i < num; i++)
781 info[i] = buffer_get_u32((uint8_t *)info,
782 i * sizeof(uint32_t));
784 return JAYLINK_OK;
788 * Retrieve the counter values of a device.
790 * @note This function must only be used if the device has the
791 * #JAYLINK_DEV_CAP_GET_COUNTERS capability.
793 * @param[in,out] devh Device handle.
794 * @param[in] mask A bit field where each set bit represents a counter value to
795 * request. See #jaylink_counter for a description of the
796 * counters and their bit positions.
797 * @param[out] values Array to store the counter values on success. Its content
798 * is undefined on failure. The array must be large enough
799 * to contain at least as many elements as bits set in @p
800 * mask.
802 * @retval JAYLINK_OK Success.
803 * @retval JAYLINK_ERR_ARG Invalid arguments.
804 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
805 * @retval JAYLINK_ERR_IO Input/output error.
806 * @retval JAYLINK_ERR Other error conditions.
808 * @since 0.2.0
810 JAYLINK_API int jaylink_get_counters(struct jaylink_device_handle *devh,
811 uint32_t mask, uint32_t *values)
813 int ret;
814 struct jaylink_context *ctx;
815 uint8_t buf[5];
816 unsigned int i;
817 unsigned int num;
818 unsigned int length;
820 if (!devh || !mask || !values)
821 return JAYLINK_ERR_ARG;
823 ctx = devh->dev->ctx;
824 num = 0;
826 for (i = 0; i < 32; i++) {
827 if (mask & (1 << i))
828 num++;
831 length = num * sizeof(uint32_t);
832 ret = transport_start_write_read(devh, 5, length, true);
834 if (ret != JAYLINK_OK) {
835 log_err(ctx, "transport_start_write_read() failed: %s.",
836 jaylink_strerror(ret));
837 return ret;
840 buf[0] = CMD_GET_COUNTERS;
841 buffer_set_u32(buf, mask, 1);
843 ret = transport_write(devh, buf, 5);
845 if (ret != JAYLINK_OK) {
846 log_err(ctx, "transport_write() failed: %s.",
847 jaylink_strerror(ret));
848 return ret;
851 ret = transport_read(devh, (uint8_t *)values, length);
853 if (ret != JAYLINK_OK) {
854 log_err(ctx, "transport_read() failed: %s.",
855 jaylink_strerror(ret));
856 return ret;
859 for (i = 0; i < num; i++)
860 values[i] = buffer_get_u32((uint8_t *)values,
861 i * sizeof(uint32_t));
863 return JAYLINK_OK;
867 * Retrieve the hardware version of a device.
869 * @note This function must only be used if the device has the
870 * #JAYLINK_DEV_CAP_GET_HW_VERSION capability.
872 * @warning This function may return a value for @p version where
873 * #jaylink_hardware_version::type is not covered by
874 * #jaylink_hardware_type.
876 * @param[in,out] devh Device handle.
877 * @param[out] version Hardware version on success, and undefined on failure.
879 * @retval JAYLINK_OK Success.
880 * @retval JAYLINK_ERR_ARG Invalid arguments.
881 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
882 * @retval JAYLINK_ERR_IO Input/output error.
883 * @retval JAYLINK_ERR Other error conditions.
885 * @since 0.1.0
887 JAYLINK_API int jaylink_get_hardware_version(
888 struct jaylink_device_handle *devh,
889 struct jaylink_hardware_version *version)
891 int ret;
892 struct jaylink_context *ctx;
893 uint8_t buf[4];
894 uint32_t tmp;
896 if (!devh || !version)
897 return JAYLINK_ERR_ARG;
899 ctx = devh->dev->ctx;
900 ret = transport_start_write_read(devh, 1, 4, true);
902 if (ret != JAYLINK_OK) {
903 log_err(ctx, "transport_start_write_read() failed: %s.",
904 jaylink_strerror(ret));
905 return ret;
908 buf[0] = CMD_GET_HW_VERSION;
910 ret = transport_write(devh, buf, 1);
912 if (ret != JAYLINK_OK) {
913 log_err(ctx, "transport_write() failed: %s.",
914 jaylink_strerror(ret));
915 return ret;
918 ret = transport_read(devh, buf, 4);
920 if (ret != JAYLINK_OK) {
921 log_err(ctx, "transport_read() failed: %s.",
922 jaylink_strerror(ret));
923 return ret;
926 tmp = buffer_get_u32(buf, 0);
928 version->type = (tmp / 1000000) % 100;
929 version->major = (tmp / 10000) % 100;
930 version->minor = (tmp / 100) % 100;
931 version->revision = tmp % 100;
933 return JAYLINK_OK;
937 * Retrieve the hardware status of a device.
939 * @param[in,out] devh Device handle.
940 * @param[out] status Hardware status on success, and undefined on failure.
942 * @retval JAYLINK_OK Success.
943 * @retval JAYLINK_ERR_ARG Invalid arguments.
944 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
945 * @retval JAYLINK_ERR_IO Input/output error.
946 * @retval JAYLINK_ERR Other error conditions.
948 * @since 0.1.0
950 JAYLINK_API int jaylink_get_hardware_status(struct jaylink_device_handle *devh,
951 struct jaylink_hardware_status *status)
953 int ret;
954 struct jaylink_context *ctx;
955 uint8_t buf[8];
957 if (!devh || !status)
958 return JAYLINK_ERR_ARG;
960 ctx = devh->dev->ctx;
961 ret = transport_start_write_read(devh, 1, 8, true);
963 if (ret != JAYLINK_OK) {
964 log_err(ctx, "transport_start_write_read() failed: %s.",
965 jaylink_strerror(ret));
966 return ret;
969 buf[0] = CMD_GET_HW_STATUS;
971 ret = transport_write(devh, buf, 1);
973 if (ret != JAYLINK_OK) {
974 log_err(ctx, "transport_write() failed: %s.",
975 jaylink_strerror(ret));
976 return ret;
979 ret = transport_read(devh, buf, 8);
981 if (ret != JAYLINK_OK) {
982 log_err(ctx, "transport_read() failed: %s.",
983 jaylink_strerror(ret));
984 return ret;
987 status->target_voltage = buffer_get_u16(buf, 0);
988 status->tck = buf[2];
989 status->tdi = buf[3];
990 status->tdo = buf[4];
991 status->tms = buf[5];
992 status->tres = buf[6];
993 status->trst = buf[7];
995 return JAYLINK_OK;
999 * Retrieve the capabilities of a device.
1001 * The capabilities are stored in a 32-bit bit array consisting of
1002 * #JAYLINK_DEV_CAPS_SIZE bytes where each individual bit represents a
1003 * capability. The first bit of this array is the least significant bit of the
1004 * first byte and the following bits are sequentially numbered in order of
1005 * increasing bit significance and byte index. A set bit indicates a supported
1006 * capability. See #jaylink_device_capability for a description of the
1007 * capabilities and their bit positions.
1009 * @param[in,out] devh Device handle.
1010 * @param[out] caps Buffer to store capabilities on success. Its content is
1011 * undefined on failure. The buffer must be large enough to
1012 * contain at least #JAYLINK_DEV_CAPS_SIZE bytes.
1014 * @retval JAYLINK_OK Success.
1015 * @retval JAYLINK_ERR_ARG Invalid arguments.
1016 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1017 * @retval JAYLINK_ERR_IO Input/output error.
1018 * @retval JAYLINK_ERR Other error conditions.
1020 * @see jaylink_get_extended_caps()
1021 * @see jaylink_has_cap()
1023 * @since 0.1.0
1025 JAYLINK_API int jaylink_get_caps(struct jaylink_device_handle *devh,
1026 uint8_t *caps)
1028 int ret;
1029 struct jaylink_context *ctx;
1030 uint8_t buf[1];
1032 if (!devh || !caps)
1033 return JAYLINK_ERR_ARG;
1035 ctx = devh->dev->ctx;
1036 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CAPS_SIZE, true);
1038 if (ret != JAYLINK_OK) {
1039 log_err(ctx, "transport_start_write_read() failed: %s.",
1040 jaylink_strerror(ret));
1041 return ret;
1044 buf[0] = CMD_GET_CAPS;
1046 ret = transport_write(devh, buf, 1);
1048 if (ret != JAYLINK_OK) {
1049 log_err(ctx, "transport_write() failed: %s.",
1050 jaylink_strerror(ret));
1051 return ret;
1054 ret = transport_read(devh, caps, JAYLINK_DEV_CAPS_SIZE);
1056 if (ret != JAYLINK_OK) {
1057 log_err(ctx, "transport_read() failed: %s.",
1058 jaylink_strerror(ret));
1059 return ret;
1062 return JAYLINK_OK;
1066 * Retrieve the extended capabilities of a device.
1068 * The extended capabilities are stored in a 256-bit bit array consisting of
1069 * #JAYLINK_DEV_EXT_CAPS_SIZE bytes. See jaylink_get_caps() for a further
1070 * description of how the capabilities are represented in this bit array. For a
1071 * description of the capabilities and their bit positions, see
1072 * #jaylink_device_capability.
1074 * @note This function must only be used if the device has the
1075 * #JAYLINK_DEV_CAP_GET_EXT_CAPS capability.
1077 * @param[in,out] devh Device handle.
1078 * @param[out] caps Buffer to store capabilities on success. Its content is
1079 * undefined on failure. The buffer must be large enough to
1080 * contain at least #JAYLINK_DEV_EXT_CAPS_SIZE bytes.
1082 * @retval JAYLINK_OK Success.
1083 * @retval JAYLINK_ERR_ARG Invalid arguments.
1084 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1085 * @retval JAYLINK_ERR_IO Input/output error.
1086 * @retval JAYLINK_ERR Other error conditions.
1088 * @see jaylink_get_caps()
1090 * @since 0.1.0
1092 JAYLINK_API int jaylink_get_extended_caps(struct jaylink_device_handle *devh,
1093 uint8_t *caps)
1095 int ret;
1096 struct jaylink_context *ctx;
1097 uint8_t buf[1];
1099 if (!devh || !caps)
1100 return JAYLINK_ERR_ARG;
1102 ctx = devh->dev->ctx;
1103 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_EXT_CAPS_SIZE,
1104 true);
1106 if (ret != JAYLINK_OK) {
1107 log_err(ctx, "transport_start_write_read() failed: %s.",
1108 jaylink_strerror(ret));
1109 return ret;
1112 buf[0] = CMD_GET_EXT_CAPS;
1114 ret = transport_write(devh, buf, 1);
1116 if (ret != JAYLINK_OK) {
1117 log_err(ctx, "transport_write() failed: %s.",
1118 jaylink_strerror(ret));
1119 return ret;
1122 ret = transport_read(devh, caps, JAYLINK_DEV_EXT_CAPS_SIZE);
1124 if (ret != JAYLINK_OK) {
1125 log_err(ctx, "transport_read() failed: %s.",
1126 jaylink_strerror(ret));
1127 return ret;
1130 return JAYLINK_OK;
1134 * Retrieve the size of free memory of a device.
1136 * @note This function must only be used if the device has the
1137 * #JAYLINK_DEV_CAP_GET_FREE_MEMORY capability.
1139 * @param[in,out] devh Device handle.
1140 * @param[out] size Size of free memory in bytes on success, and undefined on
1141 * failure.
1143 * @retval JAYLINK_OK Success.
1144 * @retval JAYLINK_ERR_ARG Invalid arguments.
1145 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1146 * @retval JAYLINK_ERR_IO Input/output error.
1147 * @retval JAYLINK_ERR Other error conditions.
1149 * @since 0.1.0
1151 JAYLINK_API int jaylink_get_free_memory(struct jaylink_device_handle *devh,
1152 uint32_t *size)
1154 int ret;
1155 struct jaylink_context *ctx;
1156 uint8_t buf[4];
1158 if (!devh || !size)
1159 return JAYLINK_ERR_ARG;
1161 ctx = devh->dev->ctx;
1162 ret = transport_start_write_read(devh, 1, 4, true);
1164 if (ret != JAYLINK_OK) {
1165 log_err(ctx, "transport_start_write_read() failed: %s.",
1166 jaylink_strerror(ret));
1167 return ret;
1170 buf[0] = CMD_GET_FREE_MEMORY;
1172 ret = transport_write(devh, buf, 1);
1174 if (ret != JAYLINK_OK) {
1175 log_err(ctx, "transport_write() failed: %s.",
1176 jaylink_strerror(ret));
1177 return ret;
1180 ret = transport_read(devh, buf, 4);
1182 if (ret != JAYLINK_OK) {
1183 log_err(ctx, "transport_read() failed: %s.",
1184 jaylink_strerror(ret));
1185 return ret;
1188 *size = buffer_get_u32(buf, 0);
1190 return JAYLINK_OK;
1194 * Read the raw configuration data of a device.
1196 * @note This function must only be used if the device has the
1197 * #JAYLINK_DEV_CAP_READ_CONFIG capability.
1199 * @param[in,out] devh Device handle.
1200 * @param[out] config Buffer to store configuration data on success. Its
1201 * content is undefined on failure. The buffer must be large
1202 * enough to contain at least
1203 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1205 * @retval JAYLINK_OK Success.
1206 * @retval JAYLINK_ERR_ARG Invalid arguments.
1207 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1208 * @retval JAYLINK_ERR_IO Input/output error.
1209 * @retval JAYLINK_ERR Other error conditions.
1211 * @since 0.1.0
1213 JAYLINK_API int jaylink_read_raw_config(struct jaylink_device_handle *devh,
1214 uint8_t *config)
1216 int ret;
1217 struct jaylink_context *ctx;
1218 uint8_t buf[1];
1220 if (!devh || !config)
1221 return JAYLINK_ERR_ARG;
1223 ctx = devh->dev->ctx;
1224 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CONFIG_SIZE,
1225 true);
1227 if (ret != JAYLINK_OK) {
1228 log_err(ctx, "transport_start_write_read() failed: %s.",
1229 jaylink_strerror(ret));
1230 return ret;
1233 buf[0] = CMD_READ_CONFIG;
1235 ret = transport_write(devh, buf, 1);
1237 if (ret != JAYLINK_OK) {
1238 log_err(ctx, "transport_write() failed: %s.",
1239 jaylink_strerror(ret));
1240 return ret;
1243 ret = transport_read(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1245 if (ret != JAYLINK_OK) {
1246 log_err(ctx, "transport_read() failed: %s.",
1247 jaylink_strerror(ret));
1248 return ret;
1251 return JAYLINK_OK;
1255 * Write the raw configuration data of a device.
1257 * @note This function must only be used if the device has the
1258 * #JAYLINK_DEV_CAP_WRITE_CONFIG capability.
1260 * @param[in,out] devh Device handle.
1261 * @param[in] config Buffer to write configuration data from. The size of the
1262 * configuration data is expected to be
1263 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1265 * @retval JAYLINK_OK Success.
1266 * @retval JAYLINK_ERR_ARG Invalid arguments.
1267 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1268 * @retval JAYLINK_ERR_IO Input/output error.
1269 * @retval JAYLINK_ERR Other error conditions.
1271 * @since 0.1.0
1273 JAYLINK_API int jaylink_write_raw_config(struct jaylink_device_handle *devh,
1274 const uint8_t *config)
1276 int ret;
1277 struct jaylink_context *ctx;
1278 uint8_t buf[1];
1280 if (!devh || !config)
1281 return JAYLINK_ERR_ARG;
1283 ctx = devh->dev->ctx;
1284 ret = transport_start_write(devh, 1 + JAYLINK_DEV_CONFIG_SIZE, true);
1286 if (ret != JAYLINK_OK) {
1287 log_err(ctx, "transport_start_write() failed: %s.",
1288 jaylink_strerror(ret));
1289 return ret;
1292 buf[0] = CMD_WRITE_CONFIG;
1294 ret = transport_write(devh, buf, 1);
1296 if (ret != JAYLINK_OK) {
1297 log_err(ctx, "transport_write() failed: %s.",
1298 jaylink_strerror(ret));
1299 return ret;
1302 ret = transport_write(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1304 if (ret != JAYLINK_OK) {
1305 log_err(ctx, "transport_write() failed: %s.",
1306 jaylink_strerror(ret));
1307 return ret;
1310 return JAYLINK_OK;
1313 static void parse_conn_table(struct jaylink_connection *conns,
1314 const uint8_t *buffer, uint16_t num, uint16_t entry_size)
1316 unsigned int i;
1317 size_t offset;
1318 struct in_addr in;
1320 offset = 0;
1322 for (i = 0; i < num; i++) {
1323 conns[i].pid = buffer_get_u32(buffer, offset);
1325 in.s_addr = buffer_get_u32(buffer, offset + 4);
1327 * Use inet_ntoa() instead of inet_ntop() because the latter
1328 * requires at least Windows Vista.
1330 strcpy(conns[i].hid, inet_ntoa(in));
1332 conns[i].iid = buffer[offset + 8];
1333 conns[i].cid = buffer[offset + 9];
1334 conns[i].handle = buffer_get_u16(buffer, offset + 10);
1335 conns[i].timestamp = buffer_get_u32(buffer, offset + 12);
1336 offset = offset + entry_size;
1340 static bool _inet_pton(const char *str, struct in_addr *in)
1342 #ifdef _WIN32
1343 int ret;
1344 struct sockaddr_in sock_in;
1345 int length;
1347 length = sizeof(sock_in);
1350 * Use WSAStringToAddress() instead of inet_pton() because the latter
1351 * requires at least Windows Vista.
1353 ret = WSAStringToAddress((LPTSTR)str, AF_INET, NULL,
1354 (LPSOCKADDR)&sock_in, &length);
1356 if (ret != 0)
1357 return false;
1359 *in = sock_in.sin_addr;
1360 #else
1361 if (inet_pton(AF_INET, str, in) != 1)
1362 return false;
1363 #endif
1365 return true;
1369 * Register a connection on a device.
1371 * A connection can be registered by using 0 as handle. Additional information
1372 * about the connection can be attached whereby the timestamp is a read-only
1373 * value and therefore ignored for registration. On success, a new handle
1374 * greater than 0 is obtained from the device.
1376 * However, if an obtained handle does not appear in the list of device
1377 * connections, the connection was not registered because the maximum number of
1378 * connections on the device is reached.
1380 * @note This function must only be used if the device has the
1381 * #JAYLINK_DEV_CAP_REGISTER capability.
1383 * Example code:
1384 * @code{.c}
1385 * static bool register_connection(struct jaylink_device_handle *devh,
1386 * struct jaylink_connection *conn)
1388 * int ret;
1389 * struct jaylink_connection conns[JAYLINK_MAX_CONNECTIONS];
1390 * bool found_handle;
1391 * size_t count;
1392 * size_t i;
1394 * conn->handle = 0;
1395 * conn->pid = 0;
1396 * strcpy(conn->hid, "0.0.0.0");
1397 * conn->iid = 0;
1398 * conn->cid = 0;
1400 * ret = jaylink_register(devh, conn, conns, &count);
1402 * if (ret != JAYLINK_OK) {
1403 * printf("jaylink_register() failed: %s.\n",
1404 * jaylink_strerror(ret));
1405 * return false;
1408 * found_handle = false;
1410 * for (i = 0; i < count; i++) {
1411 * if (conns[i].handle == conn->handle) {
1412 * found_handle = true;
1413 * break;
1417 * if (!found_handle) {
1418 * printf("Maximum number of connections reached.\n");
1419 * return false;
1422 * printf("Connection successfully registered.\n");
1424 * return true;
1426 * @endcode
1428 * @param[in,out] devh Device handle.
1429 * @param[in,out] connection Connection to register on the device.
1430 * @param[out] connections Array to store device connections on success.
1431 * Its content is undefined on failure. The array must
1432 * be large enough to contain at least
1433 * #JAYLINK_MAX_CONNECTIONS elements.
1434 * @param[out] count Number of device connections on success, and undefined on
1435 * failure.
1437 * @retval JAYLINK_OK Success.
1438 * @retval JAYLINK_ERR_ARG Invalid arguments.
1439 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1440 * @retval JAYLINK_ERR_PROTO Protocol violation.
1441 * @retval JAYLINK_ERR_IO Input/output error.
1442 * @retval JAYLINK_ERR Other error conditions.
1444 * @see jaylink_unregister()
1446 * @since 0.1.0
1448 JAYLINK_API int jaylink_register(struct jaylink_device_handle *devh,
1449 struct jaylink_connection *connection,
1450 struct jaylink_connection *connections, size_t *count)
1452 int ret;
1453 struct jaylink_context *ctx;
1454 uint8_t buf[REG_MAX_SIZE];
1455 uint16_t handle;
1456 uint16_t num;
1457 uint16_t entry_size;
1458 uint32_t size;
1459 uint32_t table_size;
1460 uint16_t info_size;
1461 struct in_addr in;
1463 if (!devh || !connection || !connections || !count)
1464 return JAYLINK_ERR_ARG;
1466 ctx = devh->dev->ctx;
1468 buf[0] = CMD_REGISTER;
1469 buf[1] = REG_CMD_REGISTER;
1470 buffer_set_u32(buf, connection->pid, 2);
1472 if (!_inet_pton(connection->hid, &in))
1473 return JAYLINK_ERR_ARG;
1475 buffer_set_u32(buf, in.s_addr, 6);
1477 buf[10] = connection->iid;
1478 buf[11] = connection->cid;
1479 buffer_set_u16(buf, connection->handle, 12);
1481 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1483 if (ret != JAYLINK_OK) {
1484 log_err(ctx, "transport_start_write_read() failed: %s.",
1485 jaylink_strerror(ret));
1486 return ret;
1489 ret = transport_write(devh, buf, 14);
1491 if (ret != JAYLINK_OK) {
1492 log_err(ctx, "transport_write() failed: %s.",
1493 jaylink_strerror(ret));
1494 return ret;
1497 ret = transport_read(devh, buf, REG_MIN_SIZE);
1499 if (ret != JAYLINK_OK) {
1500 log_err(ctx, "transport_read() failed: %s.",
1501 jaylink_strerror(ret));
1502 return ret;
1505 handle = buffer_get_u16(buf, 0);
1506 num = buffer_get_u16(buf, 2);
1507 entry_size = buffer_get_u16(buf, 4);
1508 info_size = buffer_get_u16(buf, 6);
1510 if (num > JAYLINK_MAX_CONNECTIONS) {
1511 log_err(ctx, "Maximum number of device connections exceeded: "
1512 "%u.", num);
1513 return JAYLINK_ERR_PROTO;
1516 if (entry_size != REG_CONN_INFO_SIZE) {
1517 log_err(ctx, "Invalid connection entry size: %u bytes.",
1518 entry_size);
1519 return JAYLINK_ERR_PROTO;
1522 table_size = num * entry_size;
1523 size = REG_HEADER_SIZE + table_size + info_size;
1525 if (size > REG_MAX_SIZE) {
1526 log_err(ctx, "Maximum registration information size exceeded: "
1527 "%u bytes.", size);
1528 return JAYLINK_ERR_PROTO;
1531 if (size > REG_MIN_SIZE) {
1532 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1534 if (ret != JAYLINK_OK) {
1535 log_err(ctx, "transport_start_read() failed: %s.",
1536 jaylink_strerror(ret));
1537 return JAYLINK_ERR;
1540 ret = transport_read(devh, buf + REG_MIN_SIZE,
1541 size - REG_MIN_SIZE);
1543 if (ret != JAYLINK_OK) {
1544 log_err(ctx, "transport_read() failed: %s.",
1545 jaylink_strerror(ret));
1546 return JAYLINK_ERR;
1550 if (!handle) {
1551 log_err(ctx, "Obtained invalid connection handle.");
1552 return JAYLINK_ERR_PROTO;
1555 connection->handle = handle;
1556 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1558 *count = num;
1560 return JAYLINK_OK;
1564 * Unregister a connection from a device.
1566 * @note This function must only be used if the device has the
1567 * #JAYLINK_DEV_CAP_REGISTER capability.
1569 * @param[in,out] devh Device handle.
1570 * @param[in,out] connection Connection to unregister from the device.
1571 * @param[out] connections Array to store device connections on success.
1572 * Its content is undefined on failure. The array must
1573 * be large enough to contain at least
1574 * #JAYLINK_MAX_CONNECTIONS elements.
1575 * @param[out] count Number of device connections on success, and undefined on
1576 * failure.
1578 * @retval JAYLINK_OK Success.
1579 * @retval JAYLINK_ERR_ARG Invalid arguments.
1580 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1581 * @retval JAYLINK_ERR_PROTO Protocol violation.
1582 * @retval JAYLINK_ERR_IO Input/output error.
1583 * @retval JAYLINK_ERR Other error conditions.
1585 * @see jaylink_register()
1587 * @since 0.1.0
1589 JAYLINK_API int jaylink_unregister(struct jaylink_device_handle *devh,
1590 const struct jaylink_connection *connection,
1591 struct jaylink_connection *connections, size_t *count)
1593 int ret;
1594 struct jaylink_context *ctx;
1595 uint8_t buf[REG_MAX_SIZE];
1596 uint16_t num;
1597 uint16_t entry_size;
1598 uint32_t size;
1599 uint32_t table_size;
1600 uint16_t info_size;
1601 struct in_addr in;
1603 if (!devh || !connection || !connections || !count)
1604 return JAYLINK_ERR_ARG;
1606 ctx = devh->dev->ctx;
1608 buf[0] = CMD_REGISTER;
1609 buf[1] = REG_CMD_UNREGISTER;
1610 buffer_set_u32(buf, connection->pid, 2);
1612 if (!_inet_pton(connection->hid, &in))
1613 return JAYLINK_ERR_ARG;
1615 buffer_set_u32(buf, in.s_addr, 6);
1617 buf[10] = connection->iid;
1618 buf[11] = connection->cid;
1619 buffer_set_u16(buf, connection->handle, 12);
1621 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1623 if (ret != JAYLINK_OK) {
1624 log_err(ctx, "transport_start_write_read() failed: %s.",
1625 jaylink_strerror(ret));
1626 return ret;
1629 ret = transport_write(devh, buf, 14);
1631 if (ret != JAYLINK_OK) {
1632 log_err(ctx, "transport_write() failed: %s.",
1633 jaylink_strerror(ret));
1634 return ret;
1637 ret = transport_read(devh, buf, REG_MIN_SIZE);
1639 if (ret != JAYLINK_OK) {
1640 log_err(ctx, "transport_read() failed: %s.",
1641 jaylink_strerror(ret));
1642 return ret;
1645 num = buffer_get_u16(buf, 2);
1646 entry_size = buffer_get_u16(buf, 4);
1647 info_size = buffer_get_u16(buf, 6);
1649 if (num > JAYLINK_MAX_CONNECTIONS) {
1650 log_err(ctx, "Maximum number of device connections exceeded: "
1651 "%u.", num);
1652 return JAYLINK_ERR_PROTO;
1655 if (entry_size != REG_CONN_INFO_SIZE) {
1656 log_err(ctx, "Invalid connection entry size: %u bytes.",
1657 entry_size);
1658 return JAYLINK_ERR_PROTO;
1661 table_size = num * entry_size;
1662 size = REG_HEADER_SIZE + table_size + info_size;
1664 if (size > REG_MAX_SIZE) {
1665 log_err(ctx, "Maximum registration information size exceeded: "
1666 "%u bytes.", size);
1667 return JAYLINK_ERR_PROTO;
1670 if (size > REG_MIN_SIZE) {
1671 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1673 if (ret != JAYLINK_OK) {
1674 log_err(ctx, "transport_start_read() failed: %s.",
1675 jaylink_strerror(ret));
1676 return JAYLINK_ERR;
1679 ret = transport_read(devh, buf + REG_MIN_SIZE,
1680 size - REG_MIN_SIZE);
1682 if (ret != JAYLINK_OK) {
1683 log_err(ctx, "transport_read() failed: %s.",
1684 jaylink_strerror(ret));
1685 return JAYLINK_ERR;
1689 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1691 *count = num;
1693 return JAYLINK_OK;