device: Add function to retrieve counter values
[libjaylink.git] / libjaylink / device.c
blobe14a3047881fb7e4315a7cd7fca949d45c59bedf
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;
90 dev->usb_dev = NULL;
92 return dev;
95 static struct jaylink_device **allocate_device_list(size_t length)
97 struct jaylink_device **list;
99 list = malloc(sizeof(struct jaylink_device *) * (length + 1));
101 if (!list)
102 return NULL;
104 list[length] = NULL;
106 return list;
110 * Get available devices.
112 * @param[in,out] ctx libjaylink context.
113 * @param[out] devs Newly allocated array which contains instances of available
114 * devices on success, and undefined on failure. The array is
115 * NULL-terminated and must be free'd by the caller with
116 * jaylink_free_devices().
117 * @param[out] count Number of available devices on success, and undefined on
118 * failure. Can be NULL.
120 * @retval JAYLINK_OK Success.
121 * @retval JAYLINK_ERR_ARG Invalid arguments.
122 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
123 * @retval JAYLINK_ERR Other error conditions.
125 * @see jaylink_discovery_scan()
127 * @since 0.1.0
129 JAYLINK_API int jaylink_get_devices(struct jaylink_context *ctx,
130 struct jaylink_device ***devs, size_t *count)
132 size_t num;
133 struct list *item;
134 struct jaylink_device **tmp;
135 struct jaylink_device *dev;
136 size_t i;
138 if (!ctx || !devs)
139 return JAYLINK_ERR_ARG;
141 num = list_length(ctx->discovered_devs);
142 tmp = allocate_device_list(num);
144 if (!tmp) {
145 log_err(ctx, "Failed to allocate device list.");
146 return JAYLINK_ERR_MALLOC;
149 item = ctx->discovered_devs;
151 for (i = 0; i < num; i++) {
152 dev = (struct jaylink_device *)item->data;
153 tmp[i] = jaylink_ref_device(dev);
154 item = item->next;
157 if (count)
158 *count = num;
160 *devs = tmp;
162 return JAYLINK_OK;
166 * Free devices.
168 * @param[in,out] devs Array of device instances. Must be NULL-terminated.
169 * @param[in] unref Determines whether the device instances should be
170 * unreferenced.
172 * @see jaylink_get_devices()
174 * @since 0.1.0
176 JAYLINK_API void jaylink_free_devices(struct jaylink_device **devs, bool unref)
178 size_t i;
180 if (!devs)
181 return;
183 if (unref) {
184 for (i = 0; devs[i]; i++)
185 jaylink_unref_device(devs[i]);
188 free(devs);
192 * Get the host interface of a device.
194 * @param[in] dev Device instance.
195 * @param[out] iface Host interface of the device on success, and undefined on
196 * failure.
198 * @retval JAYLINK_OK Success.
199 * @retval JAYLINK_ERR_ARG Invalid arguments.
201 * @since 0.1.0
203 JAYLINK_API int jaylink_device_get_host_interface(
204 const struct jaylink_device *dev,
205 enum jaylink_host_interface *iface)
207 if (!dev || !iface)
208 return JAYLINK_ERR_ARG;
210 *iface = dev->interface;
212 return JAYLINK_OK;
216 * Get the serial number of a device.
218 * @note This serial number is for enumeration purpose only and might differ
219 * from the real serial number of the device.
221 * @param[in] dev Device instance.
222 * @param[out] serial_number Serial number of the device on success, and
223 * undefined on failure.
225 * @retval JAYLINK_OK Success.
226 * @retval JAYLINK_ERR_ARG Invalid arguments.
227 * @retval JAYLINK_ERR_NOT_AVAILABLE Serial number is not available.
229 * @since 0.1.0
231 JAYLINK_API int jaylink_device_get_serial_number(
232 const struct jaylink_device *dev, uint32_t *serial_number)
234 if (!dev || !serial_number)
235 return JAYLINK_ERR_ARG;
237 if (!dev->valid_serial_number)
238 return JAYLINK_ERR_NOT_AVAILABLE;
240 *serial_number = dev->serial_number;
242 return JAYLINK_OK;
246 * Get the USB address of a device.
248 * @note Identification of a device with the USB address is deprecated and the
249 * serial number should be used instead.
251 * @param[in] dev Device instance.
252 * @param[out] address USB address of the device on success, and undefined on
253 * failure.
255 * @retval JAYLINK_OK Success.
256 * @retval JAYLINK_ERR_ARG Invalid arguments.
257 * @retval JAYLINK_ERR_NOT_SUPPORTED Operation not supported.
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 * Increment the reference count of a device.
281 * @param[in,out] dev Device instance.
283 * @return The given device instance on success, or NULL on invalid argument.
285 * @since 0.1.0
287 JAYLINK_API struct jaylink_device *jaylink_ref_device(
288 struct jaylink_device *dev)
290 if (!dev)
291 return NULL;
293 dev->ref_count++;
295 return dev;
299 * Decrement the reference count of a device.
301 * @param[in,out] dev Device instance.
303 * @since 0.1.0
305 JAYLINK_API void jaylink_unref_device(struct jaylink_device *dev)
307 struct jaylink_context *ctx;
309 if (!dev)
310 return;
312 dev->ref_count--;
314 if (!dev->ref_count) {
315 ctx = dev->ctx;
317 log_dbg(ctx, "Device destroyed (bus:address = %03u:%03u).",
318 libusb_get_bus_number(dev->usb_dev),
319 libusb_get_device_address(dev->usb_dev));
321 ctx->devs = list_remove(dev->ctx->devs, dev);
323 if (dev->usb_dev)
324 libusb_unref_device(dev->usb_dev);
326 free(dev);
330 static struct jaylink_device_handle *allocate_device_handle(
331 struct jaylink_device *dev)
333 struct jaylink_device_handle *devh;
335 devh = malloc(sizeof(struct jaylink_device_handle));
337 if (!devh)
338 return NULL;
340 devh->dev = jaylink_ref_device(dev);
342 return devh;
345 static void free_device_handle(struct jaylink_device_handle *devh)
347 jaylink_unref_device(devh->dev);
348 free(devh);
352 * Open a device.
354 * @param[in,out] dev Device instance.
355 * @param[out] devh Newly allocated handle for the opened device on success,
356 * and undefined on failure.
358 * @retval JAYLINK_OK Success.
359 * @retval JAYLINK_ERR_ARG Invalid arguments.
360 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
361 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
362 * @retval JAYLINK_ERR_IO Input/output error.
363 * @retval JAYLINK_ERR Other error conditions.
365 * @since 0.1.0
367 JAYLINK_API int jaylink_open(struct jaylink_device *dev,
368 struct jaylink_device_handle **devh)
370 int ret;
371 struct jaylink_device_handle *handle;
373 if (!dev || !devh)
374 return JAYLINK_ERR_ARG;
376 handle = allocate_device_handle(dev);
378 if (!handle) {
379 log_err(dev->ctx, "Device handle malloc failed.");
380 return JAYLINK_ERR_MALLOC;
383 ret = transport_open(handle);
385 if (ret != JAYLINK_OK) {
386 free_device_handle(handle);
387 return ret;
390 *devh = handle;
392 return JAYLINK_OK;
396 * Close a device.
398 * @param[in,out] devh Device instance.
400 * @retval JAYLINK_OK Success.
401 * @retval JAYLINK_ERR_ARG Invalid arguments.
402 * @retval JAYLINK_ERR Other error conditions.
404 * @since 0.1.0
406 JAYLINK_API int jaylink_close(struct jaylink_device_handle *devh)
408 int ret;
410 if (!devh)
411 return JAYLINK_ERR_ARG;
413 ret = transport_close(devh);
414 free_device_handle(devh);
416 return ret;
420 * Get the device instance from a device handle.
422 * @note The reference count of the device instance is not increased.
424 * @param[in] devh Device handle.
426 * @return The device instance on success, or NULL on invalid argument.
428 * @since 0.1.0
430 JAYLINK_API struct jaylink_device *jaylink_get_device(
431 struct jaylink_device_handle *devh)
433 if (!devh)
434 return NULL;
436 return devh->dev;
440 * Retrieve the firmware version of a device.
442 * @param[in,out] devh Device handle.
443 * @param[out] version Newly allocated string which contains the firmware
444 * version on success, and undefined if @p length is zero
445 * or on failure. The string is null-terminated and must be
446 * free'd by the caller.
447 * @param[out] length Length of the firmware version string including trailing
448 * null-terminator on success, and undefined on failure.
449 * Zero if no firmware version string is available.
451 * @retval JAYLINK_OK Success.
452 * @retval JAYLINK_ERR_ARG Invalid arguments.
453 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
454 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
455 * @retval JAYLINK_ERR_IO Input/output error.
456 * @retval JAYLINK_ERR Other error conditions.
458 * @since 0.1.0
460 JAYLINK_API int jaylink_get_firmware_version(
461 struct jaylink_device_handle *devh, char **version,
462 size_t *length)
464 int ret;
465 struct jaylink_context *ctx;
466 uint8_t buf[2];
467 uint16_t dummy;
468 char *tmp;
470 if (!devh || !version || !length)
471 return JAYLINK_ERR_ARG;
473 ctx = devh->dev->ctx;
474 ret = transport_start_write_read(devh, 1, 2, true);
476 if (ret != JAYLINK_OK) {
477 log_err(ctx, "transport_start_write_read() failed: %s.",
478 jaylink_strerror(ret));
479 return ret;
482 buf[0] = CMD_GET_VERSION;
484 ret = transport_write(devh, buf, 1);
486 if (ret != JAYLINK_OK) {
487 log_err(ctx, "transport_write() failed: %s.",
488 jaylink_strerror(ret));
489 return ret;
492 ret = transport_read(devh, buf, 2);
494 if (ret != JAYLINK_OK) {
495 log_err(ctx, "transport_read() failed: %s.",
496 jaylink_strerror(ret));
497 return ret;
500 dummy = buffer_get_u16(buf, 0);
501 *length = dummy;
503 if (!dummy)
504 return JAYLINK_OK;
506 ret = transport_start_read(devh, dummy);
508 if (ret != JAYLINK_OK) {
509 log_err(ctx, "transport_start_read() failed: %s.",
510 jaylink_strerror(ret));
511 return ret;
514 tmp = malloc(dummy);
516 if (!tmp) {
517 log_err(ctx, "Firmware version string malloc failed.");
518 return JAYLINK_ERR_MALLOC;
521 ret = transport_read(devh, (uint8_t *)tmp, dummy);
523 if (ret != JAYLINK_OK) {
524 log_err(ctx, "transport_read() failed: %s.",
525 jaylink_strerror(ret));
526 free(tmp);
527 return ret;
530 /* Last byte is reserved for null-terminator. */
531 tmp[dummy - 1] = 0;
532 *version = tmp;
534 return JAYLINK_OK;
538 * Retrieve the hardware information of a device.
540 * @note This function must only be used if the device has the
541 * #JAYLINK_DEV_CAP_GET_HW_INFO capability.
543 * @param[in,out] devh Device handle.
544 * @param[in] mask A bit field where each set bit represents hardware
545 * information to request. See #jaylink_hardware_info for a
546 * description of the hardware information and their bit
547 * positions.
548 * @param[out] info Array to store the hardware information on success. Its
549 * content is undefined on failure. The array must be large
550 * enough to contain at least as many elements as bits set in
551 * @a mask.
553 * @retval JAYLINK_OK Success.
554 * @retval JAYLINK_ERR_ARG Invalid arguments.
555 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
556 * @retval JAYLINK_ERR_IO Input/output error.
557 * @retval JAYLINK_ERR Other error conditions.
559 * @since 0.1.0
561 JAYLINK_API int jaylink_get_hardware_info(struct jaylink_device_handle *devh,
562 uint32_t mask, uint32_t *info)
564 int ret;
565 struct jaylink_context *ctx;
566 uint8_t buf[5];
567 unsigned int i;
568 unsigned int num;
569 unsigned int length;
571 if (!devh || !mask || !info)
572 return JAYLINK_ERR_ARG;
574 ctx = devh->dev->ctx;
575 num = 0;
577 for (i = 0; i < 32; i++) {
578 if (mask & (1 << i))
579 num++;
582 length = num * sizeof(uint32_t);
584 ret = transport_start_write_read(devh, 5, length, true);
586 if (ret != JAYLINK_OK) {
587 log_err(ctx, "transport_start_write_read() failed: %s.",
588 jaylink_strerror(ret));
589 return ret;
592 buf[0] = CMD_GET_HW_INFO;
593 buffer_set_u32(buf, mask, 1);
595 ret = transport_write(devh, buf, 5);
597 if (ret != JAYLINK_OK) {
598 log_err(ctx, "transport_write() failed: %s.",
599 jaylink_strerror(ret));
600 return ret;
603 ret = transport_read(devh, (uint8_t *)info, length);
605 if (ret != JAYLINK_OK) {
606 log_err(ctx, "transport_read() failed: %s.",
607 jaylink_strerror(ret));
608 return ret;
611 for (i = 0; i < num; i++)
612 info[i] = buffer_get_u32((uint8_t *)info,
613 i * sizeof(uint32_t));
615 return JAYLINK_OK;
619 * Retrieve the counter values of a device.
621 * @note This function must only be used if the device has the
622 * #JAYLINK_DEV_CAP_GET_COUNTERS capability.
624 * @param[in,out] devh Device handle.
625 * @param[in] mask A bit field where each set bit represents a counter value to
626 * request. See #jaylink_counter for a description of the
627 * counters and their bit positions.
628 * @param[out] values Array to store the counter values on success. Its content
629 * is undefined on failure. The array must be large enough
630 * to contain at least as many elements as bits set in @p
631 * mask.
633 * @retval JAYLINK_OK Success.
634 * @retval JAYLINK_ERR_ARG Invalid arguments.
635 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
636 * @retval JAYLINK_ERR_IO Input/output error.
637 * @retval JAYLINK_ERR Other error conditions.
639 * @since 0.2.0
641 JAYLINK_API int jaylink_get_counters(struct jaylink_device_handle *devh,
642 uint32_t mask, uint32_t *values)
644 int ret;
645 struct jaylink_context *ctx;
646 uint8_t buf[5];
647 unsigned int i;
648 unsigned int num;
649 unsigned int length;
651 if (!devh || !mask || !values)
652 return JAYLINK_ERR_ARG;
654 ctx = devh->dev->ctx;
655 num = 0;
657 for (i = 0; i < 32; i++) {
658 if (mask & (1 << i))
659 num++;
662 length = num * sizeof(uint32_t);
663 ret = transport_start_write_read(devh, 5, length, true);
665 if (ret != JAYLINK_OK) {
666 log_err(ctx, "transport_start_write_read() failed: %s.",
667 jaylink_strerror(ret));
668 return ret;
671 buf[0] = CMD_GET_COUNTERS;
672 buffer_set_u32(buf, mask, 1);
674 ret = transport_write(devh, buf, 5);
676 if (ret != JAYLINK_OK) {
677 log_err(ctx, "transport_write() failed: %s.",
678 jaylink_strerror(ret));
679 return ret;
682 ret = transport_read(devh, (uint8_t *)values, length);
684 if (ret != JAYLINK_OK) {
685 log_err(ctx, "transport_read() failed: %s.",
686 jaylink_strerror(ret));
687 return ret;
690 for (i = 0; i < num; i++)
691 values[i] = buffer_get_u32((uint8_t *)values,
692 i * sizeof(uint32_t));
694 return JAYLINK_OK;
698 * Retrieve the hardware version of a device.
700 * @note This function must only be used if the device has the
701 * #JAYLINK_DEV_CAP_GET_HW_VERSION capability.
703 * @warning This function may return a value for @p version where
704 * #jaylink_hardware_version::type is not covered by
705 * #jaylink_hardware_type.
707 * @param[in,out] devh Device handle.
708 * @param[out] version Hardware version on success, and undefined on failure.
710 * @retval JAYLINK_OK Success.
711 * @retval JAYLINK_ERR_ARG Invalid arguments.
712 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
713 * @retval JAYLINK_ERR_IO Input/output error.
714 * @retval JAYLINK_ERR Other error conditions.
716 * @since 0.1.0
718 JAYLINK_API int jaylink_get_hardware_version(
719 struct jaylink_device_handle *devh,
720 struct jaylink_hardware_version *version)
722 int ret;
723 struct jaylink_context *ctx;
724 uint8_t buf[4];
725 uint32_t tmp;
727 if (!devh || !version)
728 return JAYLINK_ERR_ARG;
730 ctx = devh->dev->ctx;
731 ret = transport_start_write_read(devh, 1, 4, true);
733 if (ret != JAYLINK_OK) {
734 log_err(ctx, "transport_start_write_read() failed: %s.",
735 jaylink_strerror(ret));
736 return ret;
739 buf[0] = CMD_GET_HW_VERSION;
741 ret = transport_write(devh, buf, 1);
743 if (ret != JAYLINK_OK) {
744 log_err(ctx, "transport_write() failed: %s.",
745 jaylink_strerror(ret));
746 return ret;
749 ret = transport_read(devh, buf, 4);
751 if (ret != JAYLINK_OK) {
752 log_err(ctx, "transport_read() failed: %s.",
753 jaylink_strerror(ret));
754 return ret;
757 tmp = buffer_get_u32(buf, 0);
759 version->type = (tmp / 1000000) % 100;
760 version->major = (tmp / 10000) % 100;
761 version->minor = (tmp / 100) % 100;
762 version->revision = tmp % 100;
764 return JAYLINK_OK;
768 * Retrieve the hardware status of a device.
770 * @param[in,out] devh Device handle.
771 * @param[out] status Hardware status on success, and undefined on failure.
773 * @retval JAYLINK_OK Success.
774 * @retval JAYLINK_ERR_ARG Invalid arguments.
775 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
776 * @retval JAYLINK_ERR_IO Input/output error.
777 * @retval JAYLINK_ERR Other error conditions.
779 * @since 0.1.0
781 JAYLINK_API int jaylink_get_hardware_status(struct jaylink_device_handle *devh,
782 struct jaylink_hardware_status *status)
784 int ret;
785 struct jaylink_context *ctx;
786 uint8_t buf[8];
788 if (!devh || !status)
789 return JAYLINK_ERR_ARG;
791 ctx = devh->dev->ctx;
792 ret = transport_start_write_read(devh, 1, 8, true);
794 if (ret != JAYLINK_OK) {
795 log_err(ctx, "transport_start_write_read() failed: %s.",
796 jaylink_strerror(ret));
797 return ret;
800 buf[0] = CMD_GET_HW_STATUS;
802 ret = transport_write(devh, buf, 1);
804 if (ret != JAYLINK_OK) {
805 log_err(ctx, "transport_write() failed: %s.",
806 jaylink_strerror(ret));
807 return ret;
810 ret = transport_read(devh, buf, 8);
812 if (ret != JAYLINK_OK) {
813 log_err(ctx, "transport_read() failed: %s.",
814 jaylink_strerror(ret));
815 return ret;
818 status->target_voltage = buffer_get_u16(buf, 0);
819 status->tck = buf[2];
820 status->tdi = buf[3];
821 status->tdo = buf[4];
822 status->tms = buf[5];
823 status->tres = buf[6];
824 status->trst = buf[7];
826 return JAYLINK_OK;
830 * Retrieve the capabilities of a device.
832 * The capabilities are stored in a 32-bit bit array consisting of
833 * #JAYLINK_DEV_CAPS_SIZE bytes where each individual bit represents a
834 * capability. The first bit of this array is the least significant bit of the
835 * first byte and the following bits are sequentially numbered in order of
836 * increasing bit significance and byte index. A set bit indicates a supported
837 * capability. See #jaylink_device_capability for a description of the
838 * capabilities and their bit positions.
840 * @param[in,out] devh Device handle.
841 * @param[out] caps Buffer to store capabilities on success. Its content is
842 * undefined on failure. The buffer must be large enough to
843 * contain at least #JAYLINK_DEV_CAPS_SIZE bytes.
845 * @retval JAYLINK_OK Success.
846 * @retval JAYLINK_ERR_ARG Invalid arguments.
847 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
848 * @retval JAYLINK_ERR_IO Input/output error.
849 * @retval JAYLINK_ERR Other error conditions.
851 * @see jaylink_get_extended_caps()
852 * @see jaylink_has_cap()
854 * @since 0.1.0
856 JAYLINK_API int jaylink_get_caps(struct jaylink_device_handle *devh,
857 uint8_t *caps)
859 int ret;
860 struct jaylink_context *ctx;
861 uint8_t buf[1];
863 if (!devh || !caps)
864 return JAYLINK_ERR_ARG;
866 ctx = devh->dev->ctx;
867 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CAPS_SIZE, true);
869 if (ret != JAYLINK_OK) {
870 log_err(ctx, "transport_start_write_read() failed: %s.",
871 jaylink_strerror(ret));
872 return ret;
875 buf[0] = CMD_GET_CAPS;
877 ret = transport_write(devh, buf, 1);
879 if (ret != JAYLINK_OK) {
880 log_err(ctx, "transport_write() failed: %s.",
881 jaylink_strerror(ret));
882 return ret;
885 ret = transport_read(devh, caps, JAYLINK_DEV_CAPS_SIZE);
887 if (ret != JAYLINK_OK) {
888 log_err(ctx, "transport_read() failed: %s.",
889 jaylink_strerror(ret));
890 return ret;
893 return JAYLINK_OK;
897 * Retrieve the extended capabilities of a device.
899 * The extended capabilities are stored in a 256-bit bit array consisting of
900 * #JAYLINK_DEV_EXT_CAPS_SIZE bytes. See jaylink_get_caps() for a further
901 * description of how the capabilities are represented in this bit array. For a
902 * description of the capabilities and their bit positions, see
903 * #jaylink_device_capability.
905 * @note This function must only be used if the device has the
906 * #JAYLINK_DEV_CAP_GET_EXT_CAPS capability.
908 * @param[in,out] devh Device handle.
909 * @param[out] caps Buffer to store capabilities on success. Its content is
910 * undefined on failure. The buffer must be large enough to
911 * contain at least #JAYLINK_DEV_EXT_CAPS_SIZE bytes.
913 * @retval JAYLINK_OK Success.
914 * @retval JAYLINK_ERR_ARG Invalid arguments.
915 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
916 * @retval JAYLINK_ERR_IO Input/output error.
917 * @retval JAYLINK_ERR Other error conditions.
919 * @see jaylink_get_caps()
921 * @since 0.1.0
923 JAYLINK_API int jaylink_get_extended_caps(struct jaylink_device_handle *devh,
924 uint8_t *caps)
926 int ret;
927 struct jaylink_context *ctx;
928 uint8_t buf[1];
930 if (!devh || !caps)
931 return JAYLINK_ERR_ARG;
933 ctx = devh->dev->ctx;
934 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_EXT_CAPS_SIZE,
935 true);
937 if (ret != JAYLINK_OK) {
938 log_err(ctx, "transport_start_write_read() failed: %s.",
939 jaylink_strerror(ret));
940 return ret;
943 buf[0] = CMD_GET_EXT_CAPS;
945 ret = transport_write(devh, buf, 1);
947 if (ret != JAYLINK_OK) {
948 log_err(ctx, "transport_write() failed: %s.",
949 jaylink_strerror(ret));
950 return ret;
953 ret = transport_read(devh, caps, JAYLINK_DEV_EXT_CAPS_SIZE);
955 if (ret != JAYLINK_OK) {
956 log_err(ctx, "transport_read() failed: %s.",
957 jaylink_strerror(ret));
958 return ret;
961 return JAYLINK_OK;
965 * Retrieve the size of free memory of a device.
967 * @note This function must only be used if the device has the
968 * #JAYLINK_DEV_CAP_GET_FREE_MEMORY capability.
970 * @param[in,out] devh Device handle.
971 * @param[out] size Size of free memory in bytes on success, and undefined on
972 * failure.
974 * @retval JAYLINK_OK Success.
975 * @retval JAYLINK_ERR_ARG Invalid arguments.
976 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
977 * @retval JAYLINK_ERR_IO Input/output error.
978 * @retval JAYLINK_ERR Other error conditions.
980 * @since 0.1.0
982 JAYLINK_API int jaylink_get_free_memory(struct jaylink_device_handle *devh,
983 uint32_t *size)
985 int ret;
986 struct jaylink_context *ctx;
987 uint8_t buf[4];
989 if (!devh || !size)
990 return JAYLINK_ERR_ARG;
992 ctx = devh->dev->ctx;
993 ret = transport_start_write_read(devh, 1, 4, true);
995 if (ret != JAYLINK_OK) {
996 log_err(ctx, "transport_start_write_read() failed: %s.",
997 jaylink_strerror(ret));
998 return ret;
1001 buf[0] = CMD_GET_FREE_MEMORY;
1003 ret = transport_write(devh, buf, 1);
1005 if (ret != JAYLINK_OK) {
1006 log_err(ctx, "transport_write() failed: %s.",
1007 jaylink_strerror(ret));
1008 return ret;
1011 ret = transport_read(devh, buf, 4);
1013 if (ret != JAYLINK_OK) {
1014 log_err(ctx, "transport_read() failed: %s.",
1015 jaylink_strerror(ret));
1016 return ret;
1019 *size = buffer_get_u32(buf, 0);
1021 return JAYLINK_OK;
1025 * Read the raw configuration data of a device.
1027 * @note This function must only be used if the device has the
1028 * #JAYLINK_DEV_CAP_READ_CONFIG capability.
1030 * @param[in,out] devh Device handle.
1031 * @param[out] config Buffer to store configuration data on success. Its
1032 * content is undefined on failure. The buffer must be large
1033 * enough to contain at least
1034 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1036 * @retval JAYLINK_OK Success.
1037 * @retval JAYLINK_ERR_ARG Invalid arguments.
1038 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1039 * @retval JAYLINK_ERR_IO Input/output error.
1040 * @retval JAYLINK_ERR Other error conditions.
1042 * @since 0.1.0
1044 JAYLINK_API int jaylink_read_raw_config(struct jaylink_device_handle *devh,
1045 uint8_t *config)
1047 int ret;
1048 struct jaylink_context *ctx;
1049 uint8_t buf[1];
1051 if (!devh || !config)
1052 return JAYLINK_ERR_ARG;
1054 ctx = devh->dev->ctx;
1055 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CONFIG_SIZE,
1056 true);
1058 if (ret != JAYLINK_OK) {
1059 log_err(ctx, "transport_start_write_read() failed: %s.",
1060 jaylink_strerror(ret));
1061 return ret;
1064 buf[0] = CMD_READ_CONFIG;
1066 ret = transport_write(devh, buf, 1);
1068 if (ret != JAYLINK_OK) {
1069 log_err(ctx, "transport_write() failed: %s.",
1070 jaylink_strerror(ret));
1071 return ret;
1074 ret = transport_read(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1076 if (ret != JAYLINK_OK) {
1077 log_err(ctx, "transport_read() failed: %s.",
1078 jaylink_strerror(ret));
1079 return ret;
1082 return JAYLINK_OK;
1086 * Write the raw configuration data of a device.
1088 * @note This function must only be used if the device has the
1089 * #JAYLINK_DEV_CAP_WRITE_CONFIG capability.
1091 * @param[in,out] devh Device handle.
1092 * @param[in] config Buffer to write configuration data from. The size of the
1093 * configuration data is expected to be
1094 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1096 * @retval JAYLINK_OK Success.
1097 * @retval JAYLINK_ERR_ARG Invalid arguments.
1098 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1099 * @retval JAYLINK_ERR_IO Input/output error.
1100 * @retval JAYLINK_ERR Other error conditions.
1102 * @since 0.1.0
1104 JAYLINK_API int jaylink_write_raw_config(struct jaylink_device_handle *devh,
1105 const uint8_t *config)
1107 int ret;
1108 struct jaylink_context *ctx;
1109 uint8_t buf[1];
1111 if (!devh || !config)
1112 return JAYLINK_ERR_ARG;
1114 ctx = devh->dev->ctx;
1115 ret = transport_start_write(devh, 1 + JAYLINK_DEV_CONFIG_SIZE, true);
1117 if (ret != JAYLINK_OK) {
1118 log_err(ctx, "transport_start_write() failed: %s.",
1119 jaylink_strerror(ret));
1120 return ret;
1123 buf[0] = CMD_WRITE_CONFIG;
1125 ret = transport_write(devh, buf, 1);
1127 if (ret != JAYLINK_OK) {
1128 log_err(ctx, "transport_write() failed: %s.",
1129 jaylink_strerror(ret));
1130 return ret;
1133 ret = transport_write(devh, config, JAYLINK_DEV_CONFIG_SIZE);
1135 if (ret != JAYLINK_OK) {
1136 log_err(ctx, "transport_write() failed: %s.",
1137 jaylink_strerror(ret));
1138 return ret;
1141 return JAYLINK_OK;
1144 static void parse_conn_table(struct jaylink_connection *conns,
1145 const uint8_t *buffer, uint16_t num, uint16_t entry_size)
1147 unsigned int i;
1148 size_t offset;
1149 struct in_addr in;
1151 offset = 0;
1153 for (i = 0; i < num; i++) {
1154 conns[i].pid = buffer_get_u32(buffer, offset);
1156 in.s_addr = buffer_get_u32(buffer, offset + 4);
1158 * Use inet_ntoa() instead of inet_ntop() because the latter
1159 * requires at least Windows Vista.
1161 strcpy(conns[i].hid, inet_ntoa(in));
1163 conns[i].iid = buffer[offset + 8];
1164 conns[i].cid = buffer[offset + 9];
1165 conns[i].handle = buffer_get_u16(buffer, offset + 10);
1166 conns[i].timestamp = buffer_get_u32(buffer, offset + 12);
1167 offset = offset + entry_size;
1171 static bool _inet_pton(const char *str, struct in_addr *in)
1173 #ifdef _WIN32
1174 int ret;
1175 struct sockaddr_in sock_in;
1176 int length;
1178 length = sizeof(sock_in);
1181 * Use WSAStringToAddress() instead of inet_pton() because the latter
1182 * requires at least Windows Vista.
1184 ret = WSAStringToAddress((LPTSTR)str, AF_INET, NULL,
1185 (LPSOCKADDR)&sock_in, &length);
1187 if (ret != 0)
1188 return false;
1190 *in = sock_in.sin_addr;
1191 #else
1192 if (inet_pton(AF_INET, str, in) != 1)
1193 return false;
1194 #endif
1196 return true;
1200 * Register a connection on a device.
1202 * A connection can be registered by using 0 as handle. Additional information
1203 * about the connection can be attached whereby the timestamp is a read-only
1204 * value and therefore ignored for registration. On success, a new handle
1205 * greater than 0 is obtained from the device.
1207 * However, if an obtained handle does not appear in the list of device
1208 * connections, the connection was not registered because the maximum number of
1209 * connections on the device is reached.
1211 * @note This function must only be used if the device has the
1212 * #JAYLINK_DEV_CAP_REGISTER capability.
1214 * Example code:
1215 * @code{.c}
1216 * static bool register_connection(struct jaylink_device_handle *devh,
1217 * struct jaylink_connection *conn)
1219 * int ret;
1220 * struct jaylink_connection conns[JAYLINK_MAX_CONNECTIONS];
1221 * bool found_handle;
1222 * size_t count;
1223 * size_t i;
1225 * conn->handle = 0;
1226 * conn->pid = 0;
1227 * strcpy(conn->hid, "0.0.0.0");
1228 * conn->iid = 0;
1229 * conn->cid = 0;
1231 * ret = jaylink_register(devh, conn, conns, &count);
1233 * if (ret != JAYLINK_OK) {
1234 * printf("jaylink_register() failed: %s.\n",
1235 * jaylink_strerror(ret));
1236 * return false;
1239 * found_handle = false;
1241 * for (i = 0; i < count; i++) {
1242 * if (conns[i].handle == conn->handle) {
1243 * found_handle = true;
1244 * break;
1248 * if (!found_handle) {
1249 * printf("Maximum number of connections reached.\n");
1250 * return false;
1253 * printf("Connection successfully registered.\n");
1255 * return true;
1257 * @endcode
1259 * @param[in,out] devh Device handle.
1260 * @param[in,out] connection Connection to register on the device.
1261 * @param[out] connections Array to store device connections on success.
1262 * Its content is undefined on failure. The array must
1263 * be large enough to contain at least
1264 * #JAYLINK_MAX_CONNECTIONS elements.
1265 * @param[out] count Number of device connections on success, and undefined on
1266 * failure.
1268 * @retval JAYLINK_OK Success.
1269 * @retval JAYLINK_ERR_ARG Invalid arguments.
1270 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1271 * @retval JAYLINK_ERR_PROTO Protocol violation.
1272 * @retval JAYLINK_ERR_IO Input/output error.
1273 * @retval JAYLINK_ERR Other error conditions.
1275 * @see jaylink_unregister()
1277 * @since 0.1.0
1279 JAYLINK_API int jaylink_register(struct jaylink_device_handle *devh,
1280 struct jaylink_connection *connection,
1281 struct jaylink_connection *connections, size_t *count)
1283 int ret;
1284 struct jaylink_context *ctx;
1285 uint8_t buf[REG_MAX_SIZE];
1286 uint16_t handle;
1287 uint16_t num;
1288 uint16_t entry_size;
1289 uint32_t size;
1290 uint32_t table_size;
1291 uint16_t info_size;
1292 struct in_addr in;
1294 if (!devh || !connection || !connections || !count)
1295 return JAYLINK_ERR_ARG;
1297 ctx = devh->dev->ctx;
1299 buf[0] = CMD_REGISTER;
1300 buf[1] = REG_CMD_REGISTER;
1301 buffer_set_u32(buf, connection->pid, 2);
1303 if (!_inet_pton(connection->hid, &in))
1304 return JAYLINK_ERR_ARG;
1306 buffer_set_u32(buf, in.s_addr, 6);
1308 buf[10] = connection->iid;
1309 buf[11] = connection->cid;
1310 buffer_set_u16(buf, connection->handle, 12);
1312 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1314 if (ret != JAYLINK_OK) {
1315 log_err(ctx, "transport_start_write_read() failed: %s.",
1316 jaylink_strerror(ret));
1317 return ret;
1320 ret = transport_write(devh, buf, 14);
1322 if (ret != JAYLINK_OK) {
1323 log_err(ctx, "transport_write() failed: %s.",
1324 jaylink_strerror(ret));
1325 return ret;
1328 ret = transport_read(devh, buf, REG_MIN_SIZE);
1330 if (ret != JAYLINK_OK) {
1331 log_err(ctx, "transport_read() failed: %s.",
1332 jaylink_strerror(ret));
1333 return ret;
1336 handle = buffer_get_u16(buf, 0);
1337 num = buffer_get_u16(buf, 2);
1338 entry_size = buffer_get_u16(buf, 4);
1339 info_size = buffer_get_u16(buf, 6);
1341 if (num > JAYLINK_MAX_CONNECTIONS) {
1342 log_err(ctx, "Maximum number of device connections exceeded: "
1343 "%u.", num);
1344 return JAYLINK_ERR_PROTO;
1347 if (entry_size != REG_CONN_INFO_SIZE) {
1348 log_err(ctx, "Invalid connection entry size: %u bytes.",
1349 entry_size);
1350 return JAYLINK_ERR_PROTO;
1353 table_size = num * entry_size;
1354 size = REG_HEADER_SIZE + table_size + info_size;
1356 if (size > REG_MAX_SIZE) {
1357 log_err(ctx, "Maximum registration information size exceeded: "
1358 "%u bytes.", size);
1359 return JAYLINK_ERR_PROTO;
1362 if (size > REG_MIN_SIZE) {
1363 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1365 if (ret != JAYLINK_OK) {
1366 log_err(ctx, "transport_start_read() failed: %s.",
1367 jaylink_strerror(ret));
1368 return JAYLINK_ERR;
1371 ret = transport_read(devh, buf + REG_MIN_SIZE,
1372 size - REG_MIN_SIZE);
1374 if (ret != JAYLINK_OK) {
1375 log_err(ctx, "transport_read() failed: %s.",
1376 jaylink_strerror(ret));
1377 return JAYLINK_ERR;
1381 if (!handle) {
1382 log_err(ctx, "Obtained invalid connection handle.");
1383 return JAYLINK_ERR_PROTO;
1386 connection->handle = handle;
1387 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1389 *count = num;
1391 return JAYLINK_OK;
1395 * Unregister a connection from a device.
1397 * @note This function must only be used if the device has the
1398 * #JAYLINK_DEV_CAP_REGISTER capability.
1400 * @param[in,out] devh Device handle.
1401 * @param[in,out] connection Connection to unregister from the device.
1402 * @param[out] connections Array to store device connections on success.
1403 * Its content is undefined on failure. The array must
1404 * be large enough to contain at least
1405 * #JAYLINK_MAX_CONNECTIONS elements.
1406 * @param[out] count Number of device connections on success, and undefined on
1407 * failure.
1409 * @retval JAYLINK_OK Success.
1410 * @retval JAYLINK_ERR_ARG Invalid arguments.
1411 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1412 * @retval JAYLINK_ERR_PROTO Protocol violation.
1413 * @retval JAYLINK_ERR_IO Input/output error.
1414 * @retval JAYLINK_ERR Other error conditions.
1416 * @see jaylink_register()
1418 * @since 0.1.0
1420 JAYLINK_API int jaylink_unregister(struct jaylink_device_handle *devh,
1421 const struct jaylink_connection *connection,
1422 struct jaylink_connection *connections, size_t *count)
1424 int ret;
1425 struct jaylink_context *ctx;
1426 uint8_t buf[REG_MAX_SIZE];
1427 uint16_t num;
1428 uint16_t entry_size;
1429 uint32_t size;
1430 uint32_t table_size;
1431 uint16_t info_size;
1432 struct in_addr in;
1434 if (!devh || !connection || !connections || !count)
1435 return JAYLINK_ERR_ARG;
1437 ctx = devh->dev->ctx;
1439 buf[0] = CMD_REGISTER;
1440 buf[1] = REG_CMD_UNREGISTER;
1441 buffer_set_u32(buf, connection->pid, 2);
1443 if (!_inet_pton(connection->hid, &in))
1444 return JAYLINK_ERR_ARG;
1446 buffer_set_u32(buf, in.s_addr, 6);
1448 buf[10] = connection->iid;
1449 buf[11] = connection->cid;
1450 buffer_set_u16(buf, connection->handle, 12);
1452 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, true);
1454 if (ret != JAYLINK_OK) {
1455 log_err(ctx, "transport_start_write_read() failed: %s.",
1456 jaylink_strerror(ret));
1457 return ret;
1460 ret = transport_write(devh, buf, 14);
1462 if (ret != JAYLINK_OK) {
1463 log_err(ctx, "transport_write() failed: %s.",
1464 jaylink_strerror(ret));
1465 return ret;
1468 ret = transport_read(devh, buf, REG_MIN_SIZE);
1470 if (ret != JAYLINK_OK) {
1471 log_err(ctx, "transport_read() failed: %s.",
1472 jaylink_strerror(ret));
1473 return ret;
1476 num = buffer_get_u16(buf, 2);
1477 entry_size = buffer_get_u16(buf, 4);
1478 info_size = buffer_get_u16(buf, 6);
1480 if (num > JAYLINK_MAX_CONNECTIONS) {
1481 log_err(ctx, "Maximum number of device connections exceeded: "
1482 "%u.", num);
1483 return JAYLINK_ERR_PROTO;
1486 if (entry_size != REG_CONN_INFO_SIZE) {
1487 log_err(ctx, "Invalid connection entry size: %u bytes.",
1488 entry_size);
1489 return JAYLINK_ERR_PROTO;
1492 table_size = num * entry_size;
1493 size = REG_HEADER_SIZE + table_size + info_size;
1495 if (size > REG_MAX_SIZE) {
1496 log_err(ctx, "Maximum registration information size exceeded: "
1497 "%u bytes.", size);
1498 return JAYLINK_ERR_PROTO;
1501 if (size > REG_MIN_SIZE) {
1502 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1504 if (ret != JAYLINK_OK) {
1505 log_err(ctx, "transport_start_read() failed: %s.",
1506 jaylink_strerror(ret));
1507 return JAYLINK_ERR;
1510 ret = transport_read(devh, buf + REG_MIN_SIZE,
1511 size - REG_MIN_SIZE);
1513 if (ret != JAYLINK_OK) {
1514 log_err(ctx, "transport_read() failed: %s.",
1515 jaylink_strerror(ret));
1516 return JAYLINK_ERR;
1520 parse_conn_table(connections, buf + REG_HEADER_SIZE, num, entry_size);
1522 *count = num;
1524 return JAYLINK_OK;