Update jaylink_device_get_usb_address() documentation
[libjaylink.git] / libjaylink / device.c
blob5b79b43377b56a501610d8495df9ab472a66079d
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 Supported for devices with host interface
257 * #JAYLINK_HIF_USB only.
259 * @see jaylink_device_get_serial_number()
261 * @since 0.1.0
263 JAYLINK_API int jaylink_device_get_usb_address(
264 const struct jaylink_device *dev,
265 enum jaylink_usb_address *address)
267 if (!dev || !address)
268 return JAYLINK_ERR_ARG;
270 if (dev->interface != JAYLINK_HIF_USB)
271 return JAYLINK_ERR_NOT_SUPPORTED;
273 *address = dev->usb_address;
275 return JAYLINK_OK;
279 * Get the IPv4 address string of a device.
281 * @param[in] dev Device instance.
282 * @param[out] address IPv4 address string in quad-dotted decimal format of the
283 * device on success and undefined on failure.
285 * @retval JAYLINK_OK Success.
286 * @retval JAYLINK_ERR_ARG Invalid arguments.
287 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
288 * #JAYLINK_HIF_TCP only.
290 * @since 0.2.0
292 JAYLINK_API int jaylink_device_get_ipv4_address(
293 const struct jaylink_device *dev, char *address)
295 if (!dev || !address)
296 return JAYLINK_ERR_ARG;
298 if (dev->interface != JAYLINK_HIF_TCP)
299 return JAYLINK_ERR_NOT_SUPPORTED;
301 memcpy(address, dev->ipv4_address, sizeof(dev->ipv4_address));
303 return JAYLINK_OK;
307 * Get the MAC address of a device.
309 * @param[in] dev Device instance.
310 * @param[out] address MAC address of the device on success and undefined on
311 * failure. The length of the MAC address is
312 * #JAYLINK_MAC_ADDRESS_LENGTH bytes.
314 * @retval JAYLINK_OK Success.
315 * @retval JAYLINK_ERR_ARG Invalid arguments.
316 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
317 * #JAYLINK_HIF_TCP only.
318 * @retval JAYLINK_ERR_NOT_AVAILABLE MAC address is not available.
320 * @since 0.2.0
322 JAYLINK_API int jaylink_device_get_mac_address(
323 const struct jaylink_device *dev, uint8_t *address)
325 if (!dev || !address)
326 return JAYLINK_ERR_ARG;
328 if (dev->interface != JAYLINK_HIF_TCP)
329 return JAYLINK_ERR_NOT_SUPPORTED;
331 if (!dev->has_mac_address)
332 return JAYLINK_ERR_NOT_AVAILABLE;
334 memcpy(address, dev->mac_address, sizeof(dev->mac_address));
336 return JAYLINK_OK;
340 * Get the hardware version of a device.
342 * @note The hardware type can not be obtained by this function, use
343 * jaylink_get_hardware_version() instead.
345 * @param[in] dev Device instance.
346 * @param[out] version Hardware version of the device on success and undefined
347 * on failure.
349 * @retval JAYLINK_OK Success.
350 * @retval JAYLINK_ERR_ARG Invalid arguments.
351 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
352 * #JAYLINK_HIF_TCP only.
353 * @retval JAYLINK_ERR_NOT_AVAILABLE Hardware version is not available.
355 * @since 0.2.0
357 JAYLINK_API int jaylink_device_get_hardware_version(
358 const struct jaylink_device *dev,
359 struct jaylink_hardware_version *version)
361 if (!dev || !version)
362 return JAYLINK_ERR_ARG;
364 if (dev->interface != JAYLINK_HIF_TCP)
365 return JAYLINK_ERR_NOT_SUPPORTED;
367 if (!dev->has_hw_version)
368 return JAYLINK_ERR_NOT_AVAILABLE;
370 *version = dev->hw_version;
372 return JAYLINK_OK;
376 * Get the product name of a device.
378 * @param[in] dev Device instance.
379 * @param[out] name Product name of the device on success and undefined on
380 * failure. The maximum length of the product name is
381 * #JAYLINK_PRODUCT_NAME_MAX_LENGTH bytes.
383 * @retval JAYLINK_OK Success.
384 * @retval JAYLINK_ERR_ARG Invalid arguments.
385 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
386 * #JAYLINK_HIF_TCP only.
387 * @retval JAYLINK_ERR_NOT_AVAILABLE Product name is not available.
389 * @since 0.2.0
391 JAYLINK_API int jaylink_device_get_product_name(
392 const struct jaylink_device *dev, char *name)
394 if (!dev || !name)
395 return JAYLINK_ERR_ARG;
397 if (dev->interface != JAYLINK_HIF_TCP)
398 return JAYLINK_ERR_NOT_SUPPORTED;
400 if (!dev->has_product_name)
401 return JAYLINK_ERR_NOT_AVAILABLE;
403 memcpy(name, dev->product_name, sizeof(dev->product_name));
405 return JAYLINK_OK;
409 * Get the nickname of a device.
411 * @param[in] dev Device instance.
412 * @param[out] nickname Nickname of the device on success and undefined on
413 * failure. The maximum length of the nickname is
414 * #JAYLINK_NICKNAME_MAX_LENGTH bytes.
416 * @retval JAYLINK_OK Success.
417 * @retval JAYLINK_ERR_ARG Invalid arguments.
418 * @retval JAYLINK_ERR_NOT_SUPPORTED Supported for devices with host interface
419 * #JAYLINK_HIF_TCP only.
420 * @retval JAYLINK_ERR_NOT_AVAILABLE Nickname is not available.
422 * @since 0.2.0
424 JAYLINK_API int jaylink_device_get_nickname(const struct jaylink_device *dev,
425 char *nickname)
427 if (!dev || !nickname)
428 return JAYLINK_ERR_ARG;
430 if (dev->interface != JAYLINK_HIF_TCP)
431 return JAYLINK_ERR_NOT_SUPPORTED;
433 if (!dev->has_nickname)
434 return JAYLINK_ERR_NOT_AVAILABLE;
436 memcpy(nickname, dev->nickname, sizeof(dev->nickname));
438 return JAYLINK_OK;
442 * Increment the reference count of a device.
444 * @param[in,out] dev Device instance.
446 * @return The given device instance on success, or NULL on invalid argument.
448 * @since 0.1.0
450 JAYLINK_API struct jaylink_device *jaylink_ref_device(
451 struct jaylink_device *dev)
453 if (!dev)
454 return NULL;
456 dev->ref_count++;
458 return dev;
462 * Decrement the reference count of a device.
464 * @param[in,out] dev Device instance.
466 * @since 0.1.0
468 JAYLINK_API void jaylink_unref_device(struct jaylink_device *dev)
470 struct jaylink_context *ctx;
472 if (!dev)
473 return;
475 dev->ref_count--;
477 if (!dev->ref_count) {
478 ctx = dev->ctx;
479 ctx->devs = list_remove(dev->ctx->devs, dev);
481 if (dev->interface == JAYLINK_HIF_USB) {
482 log_dbg(ctx, "Device destroyed (bus:address = "
483 "%03u:%03u).",
484 libusb_get_bus_number(dev->usb_dev),
485 libusb_get_device_address(dev->usb_dev));
487 libusb_unref_device(dev->usb_dev);
488 } else if (dev->interface == JAYLINK_HIF_TCP) {
489 log_dbg(ctx, "Device destroyed (IPv4 address = %s).",
490 dev->ipv4_address);
491 } else {
492 log_err(ctx, "BUG: Invalid host interface: %u.",
493 dev->interface);
496 free(dev);
500 static struct jaylink_device_handle *allocate_device_handle(
501 struct jaylink_device *dev)
503 struct jaylink_device_handle *devh;
505 devh = malloc(sizeof(struct jaylink_device_handle));
507 if (!devh)
508 return NULL;
510 devh->dev = jaylink_ref_device(dev);
512 return devh;
515 static void free_device_handle(struct jaylink_device_handle *devh)
517 jaylink_unref_device(devh->dev);
518 free(devh);
522 * Open a device.
524 * @param[in,out] dev Device instance.
525 * @param[out] devh Newly allocated handle for the opened device on success,
526 * and undefined on failure.
528 * @retval JAYLINK_OK Success.
529 * @retval JAYLINK_ERR_ARG Invalid arguments.
530 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
531 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
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 handle = allocate_device_handle(dev);
548 if (!handle) {
549 log_err(dev->ctx, "Device handle malloc failed.");
550 return JAYLINK_ERR_MALLOC;
553 ret = transport_open(handle);
555 if (ret != JAYLINK_OK) {
556 free_device_handle(handle);
557 return ret;
560 *devh = handle;
562 return JAYLINK_OK;
566 * Close a device.
568 * @param[in,out] devh Device instance.
570 * @retval JAYLINK_OK Success.
571 * @retval JAYLINK_ERR_ARG Invalid arguments.
572 * @retval JAYLINK_ERR Other error conditions.
574 * @since 0.1.0
576 JAYLINK_API int jaylink_close(struct jaylink_device_handle *devh)
578 int ret;
580 if (!devh)
581 return JAYLINK_ERR_ARG;
583 ret = transport_close(devh);
584 free_device_handle(devh);
586 return ret;
590 * Get the device instance from a device handle.
592 * @note The reference count of the device instance is not increased.
594 * @param[in] devh Device handle.
596 * @return The device instance on success, or NULL on invalid argument.
598 * @since 0.1.0
600 JAYLINK_API struct jaylink_device *jaylink_get_device(
601 struct jaylink_device_handle *devh)
603 if (!devh)
604 return NULL;
606 return devh->dev;
610 * Retrieve the firmware version of a device.
612 * @param[in,out] devh Device handle.
613 * @param[out] version Newly allocated string which contains the firmware
614 * version on success, and undefined if @p length is zero
615 * or on failure. The string is null-terminated and must be
616 * free'd by the caller.
617 * @param[out] length Length of the firmware version string including trailing
618 * null-terminator on success, and undefined on failure.
619 * Zero if no firmware version string is available.
621 * @retval JAYLINK_OK Success.
622 * @retval JAYLINK_ERR_ARG Invalid arguments.
623 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
624 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
625 * @retval JAYLINK_ERR_IO Input/output error.
626 * @retval JAYLINK_ERR Other error conditions.
628 * @since 0.1.0
630 JAYLINK_API int jaylink_get_firmware_version(
631 struct jaylink_device_handle *devh, char **version,
632 size_t *length)
634 int ret;
635 struct jaylink_context *ctx;
636 uint8_t buf[2];
637 uint16_t dummy;
638 char *tmp;
640 if (!devh || !version || !length)
641 return JAYLINK_ERR_ARG;
643 ctx = devh->dev->ctx;
644 ret = transport_start_write_read(devh, 1, 2, true);
646 if (ret != JAYLINK_OK) {
647 log_err(ctx, "transport_start_write_read() failed: %s.",
648 jaylink_strerror(ret));
649 return ret;
652 buf[0] = CMD_GET_VERSION;
654 ret = transport_write(devh, buf, 1);
656 if (ret != JAYLINK_OK) {
657 log_err(ctx, "transport_write() failed: %s.",
658 jaylink_strerror(ret));
659 return ret;
662 ret = transport_read(devh, buf, 2);
664 if (ret != JAYLINK_OK) {
665 log_err(ctx, "transport_read() failed: %s.",
666 jaylink_strerror(ret));
667 return ret;
670 dummy = buffer_get_u16(buf, 0);
671 *length = dummy;
673 if (!dummy)
674 return JAYLINK_OK;
676 ret = transport_start_read(devh, dummy);
678 if (ret != JAYLINK_OK) {
679 log_err(ctx, "transport_start_read() failed: %s.",
680 jaylink_strerror(ret));
681 return ret;
684 tmp = malloc(dummy);
686 if (!tmp) {
687 log_err(ctx, "Firmware version string malloc failed.");
688 return JAYLINK_ERR_MALLOC;
691 ret = transport_read(devh, (uint8_t *)tmp, dummy);
693 if (ret != JAYLINK_OK) {
694 log_err(ctx, "transport_read() failed: %s.",
695 jaylink_strerror(ret));
696 free(tmp);
697 return ret;
700 /* Last byte is reserved for null-terminator. */
701 tmp[dummy - 1] = 0;
702 *version = tmp;
704 return JAYLINK_OK;
708 * Retrieve the hardware information of a device.
710 * @note This function must only be used if the device has the
711 * #JAYLINK_DEV_CAP_GET_HW_INFO capability.
713 * @param[in,out] devh Device handle.
714 * @param[in] mask A bit field where each set bit represents hardware
715 * information to request. See #jaylink_hardware_info for a
716 * description of the hardware information and their bit
717 * positions.
718 * @param[out] info Array to store the hardware information on success. Its
719 * content is undefined on failure. The array must be large
720 * enough to contain at least as many elements as bits set in
721 * @a mask.
723 * @retval JAYLINK_OK Success.
724 * @retval JAYLINK_ERR_ARG Invalid arguments.
725 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
726 * @retval JAYLINK_ERR_IO Input/output error.
727 * @retval JAYLINK_ERR Other error conditions.
729 * @since 0.1.0
731 JAYLINK_API int jaylink_get_hardware_info(struct jaylink_device_handle *devh,
732 uint32_t mask, uint32_t *info)
734 int ret;
735 struct jaylink_context *ctx;
736 uint8_t buf[5];
737 unsigned int i;
738 unsigned int num;
739 unsigned int length;
741 if (!devh || !mask || !info)
742 return JAYLINK_ERR_ARG;
744 ctx = devh->dev->ctx;
745 num = 0;
747 for (i = 0; i < 32; i++) {
748 if (mask & (1 << i))
749 num++;
752 length = num * sizeof(uint32_t);
754 ret = transport_start_write_read(devh, 5, length, true);
756 if (ret != JAYLINK_OK) {
757 log_err(ctx, "transport_start_write_read() failed: %s.",
758 jaylink_strerror(ret));
759 return ret;
762 buf[0] = CMD_GET_HW_INFO;
763 buffer_set_u32(buf, mask, 1);
765 ret = transport_write(devh, buf, 5);
767 if (ret != JAYLINK_OK) {
768 log_err(ctx, "transport_write() failed: %s.",
769 jaylink_strerror(ret));
770 return ret;
773 ret = transport_read(devh, (uint8_t *)info, length);
775 if (ret != JAYLINK_OK) {
776 log_err(ctx, "transport_read() failed: %s.",
777 jaylink_strerror(ret));
778 return ret;
781 for (i = 0; i < num; i++)
782 info[i] = buffer_get_u32((uint8_t *)info,
783 i * sizeof(uint32_t));
785 return JAYLINK_OK;
789 * Retrieve the counter values of a device.
791 * @note This function must only be used if the device has the
792 * #JAYLINK_DEV_CAP_GET_COUNTERS capability.
794 * @param[in,out] devh Device handle.
795 * @param[in] mask A bit field where each set bit represents a counter value to
796 * request. See #jaylink_counter for a description of the
797 * counters and their bit positions.
798 * @param[out] values Array to store the counter values on success. Its content
799 * is undefined on failure. The array must be large enough
800 * to contain at least as many elements as bits set in @p
801 * mask.
803 * @retval JAYLINK_OK Success.
804 * @retval JAYLINK_ERR_ARG Invalid arguments.
805 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
806 * @retval JAYLINK_ERR_IO Input/output error.
807 * @retval JAYLINK_ERR Other error conditions.
809 * @since 0.2.0
811 JAYLINK_API int jaylink_get_counters(struct jaylink_device_handle *devh,
812 uint32_t mask, uint32_t *values)
814 int ret;
815 struct jaylink_context *ctx;
816 uint8_t buf[5];
817 unsigned int i;
818 unsigned int num;
819 unsigned int length;
821 if (!devh || !mask || !values)
822 return JAYLINK_ERR_ARG;
824 ctx = devh->dev->ctx;
825 num = 0;
827 for (i = 0; i < 32; i++) {
828 if (mask & (1 << i))
829 num++;
832 length = num * sizeof(uint32_t);
833 ret = transport_start_write_read(devh, 5, length, true);
835 if (ret != JAYLINK_OK) {
836 log_err(ctx, "transport_start_write_read() failed: %s.",
837 jaylink_strerror(ret));
838 return ret;
841 buf[0] = CMD_GET_COUNTERS;
842 buffer_set_u32(buf, mask, 1);
844 ret = transport_write(devh, buf, 5);
846 if (ret != JAYLINK_OK) {
847 log_err(ctx, "transport_write() failed: %s.",
848 jaylink_strerror(ret));
849 return ret;
852 ret = transport_read(devh, (uint8_t *)values, length);
854 if (ret != JAYLINK_OK) {
855 log_err(ctx, "transport_read() failed: %s.",
856 jaylink_strerror(ret));
857 return ret;
860 for (i = 0; i < num; i++)
861 values[i] = buffer_get_u32((uint8_t *)values,
862 i * sizeof(uint32_t));
864 return JAYLINK_OK;
868 * Retrieve the hardware version of a device.
870 * @note This function must only be used if the device has the
871 * #JAYLINK_DEV_CAP_GET_HW_VERSION capability.
873 * @warning This function may return a value for @p version where
874 * #jaylink_hardware_version::type is not covered by
875 * #jaylink_hardware_type.
877 * @param[in,out] devh Device handle.
878 * @param[out] version Hardware version on success, and undefined on failure.
880 * @retval JAYLINK_OK Success.
881 * @retval JAYLINK_ERR_ARG Invalid arguments.
882 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
883 * @retval JAYLINK_ERR_IO Input/output error.
884 * @retval JAYLINK_ERR Other error conditions.
886 * @since 0.1.0
888 JAYLINK_API int jaylink_get_hardware_version(
889 struct jaylink_device_handle *devh,
890 struct jaylink_hardware_version *version)
892 int ret;
893 struct jaylink_context *ctx;
894 uint8_t buf[4];
895 uint32_t tmp;
897 if (!devh || !version)
898 return JAYLINK_ERR_ARG;
900 ctx = devh->dev->ctx;
901 ret = transport_start_write_read(devh, 1, 4, true);
903 if (ret != JAYLINK_OK) {
904 log_err(ctx, "transport_start_write_read() failed: %s.",
905 jaylink_strerror(ret));
906 return ret;
909 buf[0] = CMD_GET_HW_VERSION;
911 ret = transport_write(devh, buf, 1);
913 if (ret != JAYLINK_OK) {
914 log_err(ctx, "transport_write() failed: %s.",
915 jaylink_strerror(ret));
916 return ret;
919 ret = transport_read(devh, buf, 4);
921 if (ret != JAYLINK_OK) {
922 log_err(ctx, "transport_read() failed: %s.",
923 jaylink_strerror(ret));
924 return ret;
927 tmp = buffer_get_u32(buf, 0);
929 version->type = (tmp / 1000000) % 100;
930 version->major = (tmp / 10000) % 100;
931 version->minor = (tmp / 100) % 100;
932 version->revision = tmp % 100;
934 return JAYLINK_OK;
938 * Retrieve the hardware status of a device.
940 * @param[in,out] devh Device handle.
941 * @param[out] status Hardware status on success, and undefined on failure.
943 * @retval JAYLINK_OK Success.
944 * @retval JAYLINK_ERR_ARG Invalid arguments.
945 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
946 * @retval JAYLINK_ERR_IO Input/output error.
947 * @retval JAYLINK_ERR Other error conditions.
949 * @since 0.1.0
951 JAYLINK_API int jaylink_get_hardware_status(struct jaylink_device_handle *devh,
952 struct jaylink_hardware_status *status)
954 int ret;
955 struct jaylink_context *ctx;
956 uint8_t buf[8];
958 if (!devh || !status)
959 return JAYLINK_ERR_ARG;
961 ctx = devh->dev->ctx;
962 ret = transport_start_write_read(devh, 1, 8, true);
964 if (ret != JAYLINK_OK) {
965 log_err(ctx, "transport_start_write_read() failed: %s.",
966 jaylink_strerror(ret));
967 return ret;
970 buf[0] = CMD_GET_HW_STATUS;
972 ret = transport_write(devh, buf, 1);
974 if (ret != JAYLINK_OK) {
975 log_err(ctx, "transport_write() failed: %s.",
976 jaylink_strerror(ret));
977 return ret;
980 ret = transport_read(devh, buf, 8);
982 if (ret != JAYLINK_OK) {
983 log_err(ctx, "transport_read() failed: %s.",
984 jaylink_strerror(ret));
985 return ret;
988 status->target_voltage = buffer_get_u16(buf, 0);
989 status->tck = buf[2];
990 status->tdi = buf[3];
991 status->tdo = buf[4];
992 status->tms = buf[5];
993 status->tres = buf[6];
994 status->trst = buf[7];
996 return JAYLINK_OK;
1000 * Retrieve the capabilities of a device.
1002 * The capabilities are stored in a 32-bit bit array consisting of
1003 * #JAYLINK_DEV_CAPS_SIZE bytes where each individual bit represents a
1004 * capability. The first bit of this array is the least significant bit of the
1005 * first byte and the following bits are sequentially numbered in order of
1006 * increasing bit significance and byte index. A set bit indicates a supported
1007 * capability. See #jaylink_device_capability for a description of the
1008 * capabilities and their bit positions.
1010 * @param[in,out] devh Device handle.
1011 * @param[out] caps Buffer to store capabilities on success. Its content is
1012 * undefined on failure. The buffer must be large enough to
1013 * contain at least #JAYLINK_DEV_CAPS_SIZE bytes.
1015 * @retval JAYLINK_OK Success.
1016 * @retval JAYLINK_ERR_ARG Invalid arguments.
1017 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1018 * @retval JAYLINK_ERR_IO Input/output error.
1019 * @retval JAYLINK_ERR Other error conditions.
1021 * @see jaylink_get_extended_caps()
1022 * @see jaylink_has_cap()
1024 * @since 0.1.0
1026 JAYLINK_API int jaylink_get_caps(struct jaylink_device_handle *devh,
1027 uint8_t *caps)
1029 int ret;
1030 struct jaylink_context *ctx;
1031 uint8_t buf[1];
1033 if (!devh || !caps)
1034 return JAYLINK_ERR_ARG;
1036 ctx = devh->dev->ctx;
1037 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CAPS_SIZE, true);
1039 if (ret != JAYLINK_OK) {
1040 log_err(ctx, "transport_start_write_read() failed: %s.",
1041 jaylink_strerror(ret));
1042 return ret;
1045 buf[0] = CMD_GET_CAPS;
1047 ret = transport_write(devh, buf, 1);
1049 if (ret != JAYLINK_OK) {
1050 log_err(ctx, "transport_write() failed: %s.",
1051 jaylink_strerror(ret));
1052 return ret;
1055 ret = transport_read(devh, caps, JAYLINK_DEV_CAPS_SIZE);
1057 if (ret != JAYLINK_OK) {
1058 log_err(ctx, "transport_read() failed: %s.",
1059 jaylink_strerror(ret));
1060 return ret;
1063 return JAYLINK_OK;
1067 * Retrieve the extended capabilities of a device.
1069 * The extended capabilities are stored in a 256-bit bit array consisting of
1070 * #JAYLINK_DEV_EXT_CAPS_SIZE bytes. See jaylink_get_caps() for a further
1071 * description of how the capabilities are represented in this bit array. For a
1072 * description of the capabilities and their bit positions, see
1073 * #jaylink_device_capability.
1075 * @note This function must only be used if the device has the
1076 * #JAYLINK_DEV_CAP_GET_EXT_CAPS capability.
1078 * @param[in,out] devh Device handle.
1079 * @param[out] caps Buffer to store capabilities on success. Its content is
1080 * undefined on failure. The buffer must be large enough to
1081 * contain at least #JAYLINK_DEV_EXT_CAPS_SIZE bytes.
1083 * @retval JAYLINK_OK Success.
1084 * @retval JAYLINK_ERR_ARG Invalid arguments.
1085 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1086 * @retval JAYLINK_ERR_IO Input/output error.
1087 * @retval JAYLINK_ERR Other error conditions.
1089 * @see jaylink_get_caps()
1091 * @since 0.1.0
1093 JAYLINK_API int jaylink_get_extended_caps(struct jaylink_device_handle *devh,
1094 uint8_t *caps)
1096 int ret;
1097 struct jaylink_context *ctx;
1098 uint8_t buf[1];
1100 if (!devh || !caps)
1101 return JAYLINK_ERR_ARG;
1103 ctx = devh->dev->ctx;
1104 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_EXT_CAPS_SIZE,
1105 true);
1107 if (ret != JAYLINK_OK) {
1108 log_err(ctx, "transport_start_write_read() failed: %s.",
1109 jaylink_strerror(ret));
1110 return ret;
1113 buf[0] = CMD_GET_EXT_CAPS;
1115 ret = transport_write(devh, buf, 1);
1117 if (ret != JAYLINK_OK) {
1118 log_err(ctx, "transport_write() failed: %s.",
1119 jaylink_strerror(ret));
1120 return ret;
1123 ret = transport_read(devh, caps, JAYLINK_DEV_EXT_CAPS_SIZE);
1125 if (ret != JAYLINK_OK) {
1126 log_err(ctx, "transport_read() failed: %s.",
1127 jaylink_strerror(ret));
1128 return ret;
1131 return JAYLINK_OK;
1135 * Retrieve the size of free memory of a device.
1137 * @note This function must only be used if the device has the
1138 * #JAYLINK_DEV_CAP_GET_FREE_MEMORY capability.
1140 * @param[in,out] devh Device handle.
1141 * @param[out] size Size of free memory in bytes on success, and undefined on
1142 * failure.
1144 * @retval JAYLINK_OK Success.
1145 * @retval JAYLINK_ERR_ARG Invalid arguments.
1146 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1147 * @retval JAYLINK_ERR_IO Input/output error.
1148 * @retval JAYLINK_ERR Other error conditions.
1150 * @since 0.1.0
1152 JAYLINK_API int jaylink_get_free_memory(struct jaylink_device_handle *devh,
1153 uint32_t *size)
1155 int ret;
1156 struct jaylink_context *ctx;
1157 uint8_t buf[4];
1159 if (!devh || !size)
1160 return JAYLINK_ERR_ARG;
1162 ctx = devh->dev->ctx;
1163 ret = transport_start_write_read(devh, 1, 4, true);
1165 if (ret != JAYLINK_OK) {
1166 log_err(ctx, "transport_start_write_read() failed: %s.",
1167 jaylink_strerror(ret));
1168 return ret;
1171 buf[0] = CMD_GET_FREE_MEMORY;
1173 ret = transport_write(devh, buf, 1);
1175 if (ret != JAYLINK_OK) {
1176 log_err(ctx, "transport_write() failed: %s.",
1177 jaylink_strerror(ret));
1178 return ret;
1181 ret = transport_read(devh, buf, 4);
1183 if (ret != JAYLINK_OK) {
1184 log_err(ctx, "transport_read() failed: %s.",
1185 jaylink_strerror(ret));
1186 return ret;
1189 *size = buffer_get_u32(buf, 0);
1191 return JAYLINK_OK;
1195 * Read the raw configuration data of a device.
1197 * @note This function must only be used if the device has the
1198 * #JAYLINK_DEV_CAP_READ_CONFIG capability.
1200 * @param[in,out] devh Device handle.
1201 * @param[out] config Buffer to store configuration data on success. Its
1202 * content is undefined on failure. The buffer must be large
1203 * enough to contain at least
1204 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1206 * @retval JAYLINK_OK Success.
1207 * @retval JAYLINK_ERR_ARG Invalid arguments.
1208 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1209 * @retval JAYLINK_ERR_IO Input/output error.
1210 * @retval JAYLINK_ERR Other error conditions.
1212 * @since 0.1.0
1214 JAYLINK_API int jaylink_read_raw_config(struct jaylink_device_handle *devh,
1215 uint8_t *config)
1217 int ret;
1218 struct jaylink_context *ctx;
1219 uint8_t buf[1];
1221 if (!devh || !config)
1222 return JAYLINK_ERR_ARG;
1224 ctx = devh->dev->ctx;
1225 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CONFIG_SIZE,
1226 true);
1228 if (ret != JAYLINK_OK) {
1229 log_err(ctx, "transport_start_write_read() failed: %s.",
1230 jaylink_strerror(ret));
1231 return ret;
1234 buf[0] = CMD_READ_CONFIG;
1236 ret = transport_write(devh, buf, 1);
1238 if (ret != JAYLINK_OK) {
1239 log_err(ctx, "transport_write() failed: %s.",
1240 jaylink_strerror(ret));
1241 return ret;
1244 ret = transport_read(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1246 if (ret != JAYLINK_OK) {
1247 log_err(ctx, "transport_read() failed: %s.",
1248 jaylink_strerror(ret));
1249 return ret;
1252 return JAYLINK_OK;
1256 * Write the raw configuration data of a device.
1258 * @note This function must only be used if the device has the
1259 * #JAYLINK_DEV_CAP_WRITE_CONFIG capability.
1261 * @param[in,out] devh Device handle.
1262 * @param[in] config Buffer to write configuration data from. The size of the
1263 * configuration data is expected to be
1264 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1266 * @retval JAYLINK_OK Success.
1267 * @retval JAYLINK_ERR_ARG Invalid arguments.
1268 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1269 * @retval JAYLINK_ERR_IO Input/output error.
1270 * @retval JAYLINK_ERR Other error conditions.
1272 * @since 0.1.0
1274 JAYLINK_API int jaylink_write_raw_config(struct jaylink_device_handle *devh,
1275 const uint8_t *config)
1277 int ret;
1278 struct jaylink_context *ctx;
1279 uint8_t buf[1];
1281 if (!devh || !config)
1282 return JAYLINK_ERR_ARG;
1284 ctx = devh->dev->ctx;
1285 ret = transport_start_write(devh, 1 + JAYLINK_DEV_CONFIG_SIZE, true);
1287 if (ret != JAYLINK_OK) {
1288 log_err(ctx, "transport_start_write() failed: %s.",
1289 jaylink_strerror(ret));
1290 return ret;
1293 buf[0] = CMD_WRITE_CONFIG;
1295 ret = transport_write(devh, buf, 1);
1297 if (ret != JAYLINK_OK) {
1298 log_err(ctx, "transport_write() failed: %s.",
1299 jaylink_strerror(ret));
1300 return ret;
1303 ret = transport_write(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1305 if (ret != JAYLINK_OK) {
1306 log_err(ctx, "transport_write() failed: %s.",
1307 jaylink_strerror(ret));
1308 return ret;
1311 return JAYLINK_OK;
1314 static void parse_conn_table(struct jaylink_connection *conns,
1315 const uint8_t *buffer, uint16_t num, uint16_t entry_size)
1317 unsigned int i;
1318 size_t offset;
1319 struct in_addr in;
1321 offset = 0;
1323 for (i = 0; i < num; i++) {
1324 conns[i].pid = buffer_get_u32(buffer, offset);
1326 in.s_addr = buffer_get_u32(buffer, offset + 4);
1328 * Use inet_ntoa() instead of inet_ntop() because the latter
1329 * requires at least Windows Vista.
1331 strcpy(conns[i].hid, inet_ntoa(in));
1333 conns[i].iid = buffer[offset + 8];
1334 conns[i].cid = buffer[offset + 9];
1335 conns[i].handle = buffer_get_u16(buffer, offset + 10);
1336 conns[i].timestamp = buffer_get_u32(buffer, offset + 12);
1337 offset = offset + entry_size;
1341 static bool _inet_pton(const char *str, struct in_addr *in)
1343 #ifdef _WIN32
1344 int ret;
1345 struct sockaddr_in sock_in;
1346 int length;
1348 length = sizeof(sock_in);
1351 * Use WSAStringToAddress() instead of inet_pton() because the latter
1352 * requires at least Windows Vista.
1354 ret = WSAStringToAddress((LPTSTR)str, AF_INET, NULL,
1355 (LPSOCKADDR)&sock_in, &length);
1357 if (ret != 0)
1358 return false;
1360 *in = sock_in.sin_addr;
1361 #else
1362 if (inet_pton(AF_INET, str, in) != 1)
1363 return false;
1364 #endif
1366 return true;
1370 * Register a connection on a device.
1372 * A connection can be registered by using 0 as handle. Additional information
1373 * about the connection can be attached whereby the timestamp is a read-only
1374 * value and therefore ignored for registration. On success, a new handle
1375 * greater than 0 is obtained from the device.
1377 * However, if an obtained handle does not appear in the list of device
1378 * connections, the connection was not registered because the maximum number of
1379 * connections on the device is reached.
1381 * @note This function must only be used if the device has the
1382 * #JAYLINK_DEV_CAP_REGISTER capability.
1384 * Example code:
1385 * @code{.c}
1386 * static bool register_connection(struct jaylink_device_handle *devh,
1387 * struct jaylink_connection *conn)
1389 * int ret;
1390 * struct jaylink_connection conns[JAYLINK_MAX_CONNECTIONS];
1391 * bool found_handle;
1392 * size_t count;
1393 * size_t i;
1395 * conn->handle = 0;
1396 * conn->pid = 0;
1397 * strcpy(conn->hid, "0.0.0.0");
1398 * conn->iid = 0;
1399 * conn->cid = 0;
1401 * ret = jaylink_register(devh, conn, conns, &count);
1403 * if (ret != JAYLINK_OK) {
1404 * printf("jaylink_register() failed: %s.\n",
1405 * jaylink_strerror(ret));
1406 * return false;
1409 * found_handle = false;
1411 * for (i = 0; i < count; i++) {
1412 * if (conns[i].handle == conn->handle) {
1413 * found_handle = true;
1414 * break;
1418 * if (!found_handle) {
1419 * printf("Maximum number of connections reached.\n");
1420 * return false;
1423 * printf("Connection successfully registered.\n");
1425 * return true;
1427 * @endcode
1429 * @param[in,out] devh Device handle.
1430 * @param[in,out] connection Connection to register on the device.
1431 * @param[out] connections Array to store device connections on success.
1432 * Its content is undefined on failure. The array must
1433 * be large enough to contain at least
1434 * #JAYLINK_MAX_CONNECTIONS elements.
1435 * @param[out] count Number of device connections on success, and undefined on
1436 * failure.
1438 * @retval JAYLINK_OK Success.
1439 * @retval JAYLINK_ERR_ARG Invalid arguments.
1440 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1441 * @retval JAYLINK_ERR_PROTO Protocol violation.
1442 * @retval JAYLINK_ERR_IO Input/output error.
1443 * @retval JAYLINK_ERR Other error conditions.
1445 * @see jaylink_unregister()
1447 * @since 0.1.0
1449 JAYLINK_API int jaylink_register(struct jaylink_device_handle *devh,
1450 struct jaylink_connection *connection,
1451 struct jaylink_connection *connections, size_t *count)
1453 int ret;
1454 struct jaylink_context *ctx;
1455 uint8_t buf[REG_MAX_SIZE];
1456 uint16_t handle;
1457 uint16_t num;
1458 uint16_t entry_size;
1459 uint32_t size;
1460 uint32_t table_size;
1461 uint16_t info_size;
1462 struct in_addr in;
1464 if (!devh || !connection || !connections || !count)
1465 return JAYLINK_ERR_ARG;
1467 ctx = devh->dev->ctx;
1469 buf[0] = CMD_REGISTER;
1470 buf[1] = REG_CMD_REGISTER;
1471 buffer_set_u32(buf, connection->pid, 2);
1473 if (!_inet_pton(connection->hid, &in))
1474 return JAYLINK_ERR_ARG;
1476 buffer_set_u32(buf, in.s_addr, 6);
1478 buf[10] = connection->iid;
1479 buf[11] = connection->cid;
1480 buffer_set_u16(buf, connection->handle, 12);
1482 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1484 if (ret != JAYLINK_OK) {
1485 log_err(ctx, "transport_start_write_read() failed: %s.",
1486 jaylink_strerror(ret));
1487 return ret;
1490 ret = transport_write(devh, buf, 14);
1492 if (ret != JAYLINK_OK) {
1493 log_err(ctx, "transport_write() failed: %s.",
1494 jaylink_strerror(ret));
1495 return ret;
1498 ret = transport_read(devh, buf, REG_MIN_SIZE);
1500 if (ret != JAYLINK_OK) {
1501 log_err(ctx, "transport_read() failed: %s.",
1502 jaylink_strerror(ret));
1503 return ret;
1506 handle = buffer_get_u16(buf, 0);
1507 num = buffer_get_u16(buf, 2);
1508 entry_size = buffer_get_u16(buf, 4);
1509 info_size = buffer_get_u16(buf, 6);
1511 if (num > JAYLINK_MAX_CONNECTIONS) {
1512 log_err(ctx, "Maximum number of device connections exceeded: "
1513 "%u.", num);
1514 return JAYLINK_ERR_PROTO;
1517 if (entry_size != REG_CONN_INFO_SIZE) {
1518 log_err(ctx, "Invalid connection entry size: %u bytes.",
1519 entry_size);
1520 return JAYLINK_ERR_PROTO;
1523 table_size = num * entry_size;
1524 size = REG_HEADER_SIZE + table_size + info_size;
1526 if (size > REG_MAX_SIZE) {
1527 log_err(ctx, "Maximum registration information size exceeded: "
1528 "%u bytes.", size);
1529 return JAYLINK_ERR_PROTO;
1532 if (size > REG_MIN_SIZE) {
1533 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1535 if (ret != JAYLINK_OK) {
1536 log_err(ctx, "transport_start_read() failed: %s.",
1537 jaylink_strerror(ret));
1538 return JAYLINK_ERR;
1541 ret = transport_read(devh, buf + REG_MIN_SIZE,
1542 size - REG_MIN_SIZE);
1544 if (ret != JAYLINK_OK) {
1545 log_err(ctx, "transport_read() failed: %s.",
1546 jaylink_strerror(ret));
1547 return JAYLINK_ERR;
1551 if (!handle) {
1552 log_err(ctx, "Obtained invalid connection handle.");
1553 return JAYLINK_ERR_PROTO;
1556 connection->handle = handle;
1557 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1559 *count = num;
1561 return JAYLINK_OK;
1565 * Unregister a connection from a device.
1567 * @note This function must only be used if the device has the
1568 * #JAYLINK_DEV_CAP_REGISTER capability.
1570 * @param[in,out] devh Device handle.
1571 * @param[in,out] connection Connection to unregister from the device.
1572 * @param[out] connections Array to store device connections on success.
1573 * Its content is undefined on failure. The array must
1574 * be large enough to contain at least
1575 * #JAYLINK_MAX_CONNECTIONS elements.
1576 * @param[out] count Number of device connections on success, and undefined on
1577 * failure.
1579 * @retval JAYLINK_OK Success.
1580 * @retval JAYLINK_ERR_ARG Invalid arguments.
1581 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1582 * @retval JAYLINK_ERR_PROTO Protocol violation.
1583 * @retval JAYLINK_ERR_IO Input/output error.
1584 * @retval JAYLINK_ERR Other error conditions.
1586 * @see jaylink_register()
1588 * @since 0.1.0
1590 JAYLINK_API int jaylink_unregister(struct jaylink_device_handle *devh,
1591 const struct jaylink_connection *connection,
1592 struct jaylink_connection *connections, size_t *count)
1594 int ret;
1595 struct jaylink_context *ctx;
1596 uint8_t buf[REG_MAX_SIZE];
1597 uint16_t num;
1598 uint16_t entry_size;
1599 uint32_t size;
1600 uint32_t table_size;
1601 uint16_t info_size;
1602 struct in_addr in;
1604 if (!devh || !connection || !connections || !count)
1605 return JAYLINK_ERR_ARG;
1607 ctx = devh->dev->ctx;
1609 buf[0] = CMD_REGISTER;
1610 buf[1] = REG_CMD_UNREGISTER;
1611 buffer_set_u32(buf, connection->pid, 2);
1613 if (!_inet_pton(connection->hid, &in))
1614 return JAYLINK_ERR_ARG;
1616 buffer_set_u32(buf, in.s_addr, 6);
1618 buf[10] = connection->iid;
1619 buf[11] = connection->cid;
1620 buffer_set_u16(buf, connection->handle, 12);
1622 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1624 if (ret != JAYLINK_OK) {
1625 log_err(ctx, "transport_start_write_read() failed: %s.",
1626 jaylink_strerror(ret));
1627 return ret;
1630 ret = transport_write(devh, buf, 14);
1632 if (ret != JAYLINK_OK) {
1633 log_err(ctx, "transport_write() failed: %s.",
1634 jaylink_strerror(ret));
1635 return ret;
1638 ret = transport_read(devh, buf, REG_MIN_SIZE);
1640 if (ret != JAYLINK_OK) {
1641 log_err(ctx, "transport_read() failed: %s.",
1642 jaylink_strerror(ret));
1643 return ret;
1646 num = buffer_get_u16(buf, 2);
1647 entry_size = buffer_get_u16(buf, 4);
1648 info_size = buffer_get_u16(buf, 6);
1650 if (num > JAYLINK_MAX_CONNECTIONS) {
1651 log_err(ctx, "Maximum number of device connections exceeded: "
1652 "%u.", num);
1653 return JAYLINK_ERR_PROTO;
1656 if (entry_size != REG_CONN_INFO_SIZE) {
1657 log_err(ctx, "Invalid connection entry size: %u bytes.",
1658 entry_size);
1659 return JAYLINK_ERR_PROTO;
1662 table_size = num * entry_size;
1663 size = REG_HEADER_SIZE + table_size + info_size;
1665 if (size > REG_MAX_SIZE) {
1666 log_err(ctx, "Maximum registration information size exceeded: "
1667 "%u bytes.", size);
1668 return JAYLINK_ERR_PROTO;
1671 if (size > REG_MIN_SIZE) {
1672 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1674 if (ret != JAYLINK_OK) {
1675 log_err(ctx, "transport_start_read() failed: %s.",
1676 jaylink_strerror(ret));
1677 return JAYLINK_ERR;
1680 ret = transport_read(devh, buf + REG_MIN_SIZE,
1681 size - REG_MIN_SIZE);
1683 if (ret != JAYLINK_OK) {
1684 log_err(ctx, "transport_read() failed: %s.",
1685 jaylink_strerror(ret));
1686 return JAYLINK_ERR;
1690 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1692 *count = num;
1694 return JAYLINK_OK;