Add build support for OSX.
[libjaylink.git] / libjaylink / device.c
blob13a0df2f30c183e86e895ef76b9d27c14a1c2412
1 /*
2 * This file is part of the libjaylink project.
4 * Copyright (C) 2014-2015 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 3 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 <string.h>
22 #include <libusb.h>
24 #include "libjaylink.h"
25 #include "libjaylink-internal.h"
27 /**
28 * @file
30 * Device enumeration and handling.
33 /** @cond PRIVATE */
34 #define CMD_GET_VERSION 0x01
35 #define CMD_GET_HW_STATUS 0x07
36 #define CMD_REGISTER 0x09
37 #define CMD_GET_FREE_MEMORY 0xd4
38 #define CMD_GET_CAPS 0xe8
39 #define CMD_GET_EXT_CAPS 0xed
40 #define CMD_GET_HW_VERSION 0xf0
41 #define CMD_READ_CONFIG 0xf2
42 #define CMD_WRITE_CONFIG 0xf3
44 #define REG_CMD_REGISTER 0x64
45 #define REG_CMD_UNREGISTER 0x65
47 /** Size of the registration header in bytes. */
48 #define REG_HEADER_SIZE 8
49 /** Minimum registration information size in bytes. */
50 #define REG_MIN_SIZE 0x4c
51 /** Maximum registration information size in bytes. */
52 #define REG_MAX_SIZE 0x200
53 /** Size of a connection entry in bytes. */
54 #define REG_CONN_INFO_SIZE 16
55 /** @endcond */
57 /** @private */
58 JAYLINK_PRIV struct jaylink_device *device_allocate(struct jaylink_context *ctx)
60 struct jaylink_device *dev;
61 struct list *list;
63 dev = malloc(sizeof(struct jaylink_device));
65 if (!dev)
66 return NULL;
68 list = list_prepend(ctx->devs, dev);
70 if (!list) {
71 free(dev);
72 return NULL;
75 ctx->devs = list;
77 dev->ctx = ctx;
78 dev->refcnt = 1;
79 dev->usb_dev = NULL;
81 return dev;
84 /** @private */
85 static struct jaylink_device_handle *allocate_device_handle(
86 struct jaylink_device *dev)
88 struct jaylink_device_handle *devh;
90 devh = malloc(sizeof(struct jaylink_device_handle));
92 if (!devh)
93 return NULL;
95 devh->dev = jaylink_ref_device(dev);
97 return devh;
100 /** @private */
101 static void free_device_handle(struct jaylink_device_handle *devh)
103 jaylink_unref_device(devh->dev);
104 free(devh);
108 * Get a list of available devices.
110 * @param[in,out] ctx libjaylink context.
111 * @param[out] devices Newly allocated array which contains instances of
112 * available devices on success, and undefined on failure.
113 * The array is NULL-terminated and must be free'd by the
114 * caller with jaylink_free_device_list().
116 * @return The length of the array excluding the trailing NULL-terminator, or a
117 * negative error code on failure.
119 JAYLINK_API ssize_t jaylink_get_device_list(struct jaylink_context *ctx,
120 struct jaylink_device ***devices)
122 if (!ctx || !devices)
123 return JAYLINK_ERR_ARG;
125 return discovery_get_device_list(ctx, devices);
129 * Free a device list.
131 * @param[in,out] devices Array of device instances. Must be NULL-terminated.
132 * @param[in] unref_devices Determines whether the device instances should be
133 * unreferenced.
135 JAYLINK_API void jaylink_free_device_list(struct jaylink_device **devices,
136 int unref_devices)
138 size_t i;
140 if (!devices)
141 return;
143 if (unref_devices) {
144 i = 0;
146 while (devices[i]) {
147 jaylink_unref_device(devices[i]);
148 i++;
152 free(devices);
156 * Get the serial number of a device.
158 * @note This serial number is for enumeration purpose only and might differ
159 * from the real serial number of the device.
161 * @param[in] dev Device instance.
162 * @param[out] serial_number Serial number of the device on success, and
163 * undefined on failure.
165 * @retval JAYLINK_OK Success.
166 * @retval JAYLINK_ERR_ARG Invalid arguments.
168 JAYLINK_API int jaylink_device_get_serial_number(
169 const struct jaylink_device *dev, uint32_t *serial_number)
171 if (!dev || !serial_number)
172 return JAYLINK_ERR_ARG;
174 *serial_number = dev->serial_number;
176 return JAYLINK_OK;
180 * Get the USB address of a device.
182 * @note Identification of a device with the USB address is deprecated and the
183 * serial number should be used instead.
185 * @param[in] dev Device instance.
187 * @return The USB address of the device on success, or #JAYLINK_ERR_ARG for
188 * invalid device instance. See #jaylink_usb_address for valid USB
189 * addresses.
191 * @see jaylink_device_get_serial_number() to get the serial number of a device.
193 JAYLINK_API int jaylink_device_get_usb_address(const struct jaylink_device *dev)
195 if (!dev)
196 return JAYLINK_ERR_ARG;
198 return dev->usb_address;
202 * Increment the reference count of a device.
204 * @param[in,out] dev Device instance.
206 * @return The given device instance on success, or NULL for invalid device
207 * instance.
209 JAYLINK_API struct jaylink_device *jaylink_ref_device(
210 struct jaylink_device *dev)
212 if (!dev)
213 return NULL;
215 dev->refcnt++;
217 return dev;
221 * Decrement the reference count of a device.
223 * @param[in,out] dev Device instance.
225 JAYLINK_API void jaylink_unref_device(struct jaylink_device *dev)
227 if (!dev)
228 return;
230 dev->refcnt--;
232 if (dev->refcnt == 0) {
233 dev->ctx->devs = list_remove(dev->ctx->devs, dev);
235 if (dev->usb_dev)
236 libusb_unref_device(dev->usb_dev);
238 free(dev);
243 * Open a device.
245 * @param[in,out] dev Device instance.
246 * @param[out] devh Newly allocated handle for the opened device on success,
247 * and undefined on failure.
249 * @retval JAYLINK_OK Success.
250 * @retval JAYLINK_ERR_ARG Invalid arguments.
251 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
252 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
253 * @retval JAYLINK_ERR Other error conditions.
255 JAYLINK_API int jaylink_open(struct jaylink_device *dev,
256 struct jaylink_device_handle **devh)
258 int ret;
259 struct jaylink_device_handle *handle;
261 if (!dev || !devh)
262 return JAYLINK_ERR_ARG;
264 handle = allocate_device_handle(dev);
266 if (!handle) {
267 log_err(dev->ctx, "Device handle malloc failed.");
268 return JAYLINK_ERR_MALLOC;
271 ret = transport_open(handle);
273 if (ret < 0) {
274 free_device_handle(handle);
275 return ret;
278 *devh = handle;
280 return JAYLINK_OK;
284 * Close a device.
286 * @param[in,out] devh Device instance.
288 JAYLINK_API void jaylink_close(struct jaylink_device_handle *devh)
290 if (!devh)
291 return;
293 transport_close(devh);
294 free_device_handle(devh);
298 * Retrieve the firmware version of a device.
300 * @param[in,out] devh Device handle.
301 * @param[out] version Newly allocated string which contains the firmware
302 * version, and undefined if the device returns no
303 * firmware version or on failure. The string is
304 * null-terminated and must be free'd by the caller.
306 * @return The length of the newly allocated firmware version string including
307 * trailing null-terminator, 0 if the device returns no firmware
308 * version, or a negative error code on failure.
310 JAYLINK_API int jaylink_get_firmware_version(struct jaylink_device_handle *devh,
311 char **version)
313 int ret;
314 struct jaylink_context *ctx;
315 uint8_t buf[2];
316 uint16_t length;
317 char *tmp;
319 if (!devh || !version)
320 return JAYLINK_ERR_ARG;
322 ctx = devh->dev->ctx;
323 ret = transport_start_write_read(devh, 1, 2, 1);
325 if (ret != JAYLINK_OK) {
326 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
327 return ret;
330 buf[0] = CMD_GET_VERSION;
332 ret = transport_write(devh, buf, 1);
334 if (ret != JAYLINK_OK) {
335 log_err(ctx, "transport_write() failed: %i.", ret);
336 return ret;
339 ret = transport_read(devh, buf, 2);
341 if (ret != JAYLINK_OK) {
342 log_err(ctx, "transport_read() failed: %i.", ret);
343 return ret;
346 length = buffer_get_u16(buf, 0);
348 if (!length)
349 return 0;
351 ret = transport_start_read(devh, length);
353 if (ret != JAYLINK_OK) {
354 log_err(ctx, "transport_start_read() failed: %i.", ret);
355 return ret;
358 tmp = malloc(length);
360 if (!tmp) {
361 log_err(ctx, "Firmware version string malloc failed.");
362 return JAYLINK_ERR_MALLOC;
365 ret = transport_read(devh, (uint8_t *)tmp, length);
367 if (ret != JAYLINK_OK) {
368 log_err(ctx, "transport_read() failed: %i.", ret);
369 free(tmp);
370 return ret;
373 /* Last byte is reserved for null-terminator. */
374 tmp[length - 1] = 0;
375 *version = tmp;
377 return length;
381 * Retrieve the hardware version of a device.
383 * @note This function must only be used if the device has the
384 * #JAYLINK_DEV_CAP_GET_HW_VERSION capability.
386 * @param[in,out] devh Device handle.
387 * @param[out] version Hardware version on success, and undefined on failure.
389 * @retval JAYLINK_OK Success.
390 * @retval JAYLINK_ERR_ARG Invalid arguments.
391 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
392 * @retval JAYLINK_ERR Other error conditions.
394 * @see jaylink_get_caps() to retrieve device capabilities.
396 JAYLINK_API int jaylink_get_hardware_version(struct jaylink_device_handle *devh,
397 struct jaylink_hardware_version *version)
399 int ret;
400 struct jaylink_context *ctx;
401 uint8_t buf[4];
402 uint32_t tmp;
404 if (!devh || !version)
405 return JAYLINK_ERR_ARG;
407 ctx = devh->dev->ctx;
408 ret = transport_start_write_read(devh, 1, 4, 1);
410 if (ret != JAYLINK_OK) {
411 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
412 return ret;
415 buf[0] = CMD_GET_HW_VERSION;
417 ret = transport_write(devh, buf, 1);
419 if (ret != JAYLINK_OK) {
420 log_err(ctx, "transport_write() failed: %i.", ret);
421 return ret;
424 ret = transport_read(devh, buf, 4);
426 if (ret != JAYLINK_OK) {
427 log_err(ctx, "transport_read() failed: %i.", ret);
428 return ret;
431 tmp = buffer_get_u32(buf, 0);
433 version->type = (tmp / 1000000) % 100;
434 version->major = (tmp / 10000) % 100;
435 version->minor = (tmp / 100) % 100;
436 version->revision = tmp % 100;
438 return JAYLINK_OK;
442 * Retrieve the hardware status of a device.
444 * @param[in,out] devh Device handle.
445 * @param[out] status Hardware status on success, and undefined on failure.
447 * @retval JAYLINK_OK Success.
448 * @retval JAYLINK_ERR_ARG Invalid arguments.
449 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
450 * @retval JAYLINK_ERR Other error conditions.
452 JAYLINK_API int jaylink_get_hardware_status(struct jaylink_device_handle *devh,
453 struct jaylink_hardware_status *status)
455 int ret;
456 struct jaylink_context *ctx;
457 uint8_t buf[8];
459 if (!devh || !status)
460 return JAYLINK_ERR_ARG;
462 ctx = devh->dev->ctx;
463 ret = transport_start_write_read(devh, 1, 8, 1);
465 if (ret != JAYLINK_OK) {
466 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
467 return ret;
470 buf[0] = CMD_GET_HW_STATUS;
472 ret = transport_write(devh, buf, 1);
474 if (ret != JAYLINK_OK) {
475 log_err(ctx, "transport_write() failed: %i.", ret);
476 return ret;
479 ret = transport_read(devh, buf, 8);
481 if (ret != JAYLINK_OK) {
482 log_err(ctx, "transport_read() failed: %i.", ret);
483 return ret;
486 status->target_voltage = buffer_get_u16(buf, 0);
487 status->tck = buf[2];
488 status->tdi = buf[3];
489 status->tdo = buf[4];
490 status->tms = buf[5];
491 status->tres = buf[6];
492 status->trst = buf[7];
494 return JAYLINK_OK;
498 * Retrieve the capabilities of a device.
500 * The capabilities are stored in a 32-bit bit array consisting of
501 * #JAYLINK_DEV_CAPS_SIZE bytes where each individual bit represents a
502 * capability. The first bit of this array is the least significant bit of the
503 * first byte and the following bits are sequentially numbered in order of
504 * increasing bit significance and byte index. A set bit indicates a supported
505 * capability. See #jaylink_device_capability for a description of the
506 * capabilities and their bit positions.
508 * @param[in,out] devh Device handle.
509 * @param[out] caps Buffer to store capabilities on success. Its content is
510 * undefined on failure. The size of the buffer must be large
511 * enough to contain at least #JAYLINK_DEV_CAPS_SIZE bytes.
513 * @retval JAYLINK_OK Success.
514 * @retval JAYLINK_ERR_ARG Invalid arguments.
515 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
516 * @retval JAYLINK_ERR Other error conditions.
518 * @see jaylink_get_extended_caps() to retrieve extended device capabilities.
520 JAYLINK_API int jaylink_get_caps(struct jaylink_device_handle *devh,
521 uint8_t *caps)
523 int ret;
524 struct jaylink_context *ctx;
525 uint8_t buf[1];
527 if (!devh || !caps)
528 return JAYLINK_ERR_ARG;
530 ctx = devh->dev->ctx;
531 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CAPS_SIZE, 1);
533 if (ret != JAYLINK_OK) {
534 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
535 return ret;
538 buf[0] = CMD_GET_CAPS;
540 ret = transport_write(devh, buf, 1);
542 if (ret != JAYLINK_OK) {
543 log_err(ctx, "transport_write() failed: %i.", ret);
544 return ret;
547 ret = transport_read(devh, caps, JAYLINK_DEV_CAPS_SIZE);
549 if (ret != JAYLINK_OK) {
550 log_err(ctx, "transport_read() failed: %i.", ret);
551 return ret;
554 return JAYLINK_OK;
558 * Retrieve the extended capabilities of a device.
560 * The extended capabilities are stored in a 256-bit bit array consisting of
561 * #JAYLINK_DEV_EXT_CAPS_SIZE bytes. See jaylink_get_caps() for a further
562 * description of how the capabilities are represented in this bit array. For a
563 * description of the capabilities and their bit positions, see
564 * #jaylink_device_capability.
566 * @note This function must only be used if the device has the
567 * #JAYLINK_DEV_CAP_GET_EXT_CAPS capability.
569 * @param[in,out] devh Device handle.
570 * @param[out] caps Buffer to store capabilities on success. Its content is
571 * undefined on failure. The size of the buffer must be large
572 * enough to contain at least #JAYLINK_DEV_EXT_CAPS_SIZE bytes.
574 * @retval JAYLINK_OK Success.
575 * @retval JAYLINK_ERR_ARG Invalid arguments.
576 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
577 * @retval JAYLINK_ERR Other error conditions.
579 * @see jaylink_get_caps() to retrieve device capabilities.
581 JAYLINK_API int jaylink_get_extended_caps(struct jaylink_device_handle *devh,
582 uint8_t *caps)
584 int ret;
585 struct jaylink_context *ctx;
586 uint8_t buf[1];
588 if (!devh || !caps)
589 return JAYLINK_ERR_ARG;
591 ctx = devh->dev->ctx;
592 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_EXT_CAPS_SIZE, 1);
594 if (ret != JAYLINK_OK) {
595 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
596 return ret;
599 buf[0] = CMD_GET_EXT_CAPS;
601 ret = transport_write(devh, buf, 1);
603 if (ret != JAYLINK_OK) {
604 log_err(ctx, "transport_write() failed: %i.", ret);
605 return ret;
608 ret = transport_read(devh, caps, JAYLINK_DEV_EXT_CAPS_SIZE);
610 if (ret != JAYLINK_OK) {
611 log_err(ctx, "transport_read() failed: %i.", ret);
612 return ret;
615 return JAYLINK_OK;
619 * Retrieve the size of free memory of a device.
621 * @note This function must only be used if the device has the
622 * #JAYLINK_DEV_CAP_GET_FREE_MEMORY capability.
624 * @param[in,out] devh Device handle.
625 * @param[out] size Size of free memory in bytes on success, and undefined on
626 * failure.
628 * @retval JAYLINK_OK Success.
629 * @retval JAYLINK_ERR_ARG Invalid arguments.
630 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
631 * @retval JAYLINK_ERR Other error conditions.
633 * @see jaylink_get_caps() to retrieve device capabilities.
635 JAYLINK_API int jaylink_get_free_memory(struct jaylink_device_handle *devh,
636 uint32_t *size)
638 int ret;
639 struct jaylink_context *ctx;
640 uint8_t buf[4];
642 if (!devh || !size)
643 return JAYLINK_ERR_ARG;
645 ctx = devh->dev->ctx;
646 ret = transport_start_write_read(devh, 1, 4, 1);
648 if (ret != JAYLINK_OK) {
649 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
650 return ret;
653 buf[0] = CMD_GET_FREE_MEMORY;
655 ret = transport_write(devh, buf, 1);
657 if (ret != JAYLINK_OK) {
658 log_err(ctx, "transport_write() failed: %i.", ret);
659 return ret;
662 ret = transport_read(devh, buf, 4);
664 if (ret != JAYLINK_OK) {
665 log_err(ctx, "transport_read() failed: %i.", ret);
666 return ret;
669 *size = buffer_get_u32(buf, 0);
671 return JAYLINK_OK;
675 * Read the raw configuration data of a device.
677 * @note This function must only be used if the device has the
678 * #JAYLINK_DEV_CAP_READ_CONFIG capability.
680 * @param[in,out] devh Device handle.
681 * @param[out] config Buffer to store configuration data on success. Its
682 * content is undefined on failure. The size of the buffer
683 * must be large enough to contain at least
684 * #JAYLINK_DEV_CONFIG_SIZE bytes.
686 * @retval JAYLINK_OK Success.
687 * @retval JAYLINK_ERR_ARG Invalid arguments.
688 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
689 * @retval JAYLINK_ERR Other error conditions.
691 JAYLINK_API int jaylink_read_raw_config(struct jaylink_device_handle *devh,
692 uint8_t *config)
694 int ret;
695 struct jaylink_context *ctx;
696 uint8_t buf[1];
698 if (!devh || !config)
699 return JAYLINK_ERR_ARG;
701 ctx = devh->dev->ctx;
702 ret = transport_start_write_read(devh, 1, JAYLINK_DEV_CONFIG_SIZE, 1);
704 if (ret != JAYLINK_OK) {
705 log_err(ctx, "transport_start_write_read() failed: %i.",
706 ret);
707 return ret;
710 buf[0] = CMD_READ_CONFIG;
712 ret = transport_write(devh, buf, 1);
714 if (ret != JAYLINK_OK) {
715 log_err(ctx, "transport_write() failed: %i.", ret);
716 return ret;
719 ret = transport_read(devh, config, JAYLINK_DEV_CONFIG_SIZE);
721 if (ret != JAYLINK_OK) {
722 log_err(ctx, "transport_read() failed: %i.", ret);
723 return ret;
726 return JAYLINK_OK;
730 * Write the raw configuration data of a device.
732 * @note This function must only be used if the device has the
733 * #JAYLINK_DEV_CAP_WRITE_CONFIG capability.
735 * @param[in,out] devh Device handle.
736 * @param[in] config Buffer to write configuration data from. The size of the
737 * configuration data is expected to be
738 * #JAYLINK_DEV_CONFIG_SIZE bytes.
740 * @retval JAYLINK_OK Success.
741 * @retval JAYLINK_ERR_ARG Invalid arguments.
742 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
743 * @retval JAYLINK_ERR Other error conditions.
745 JAYLINK_API int jaylink_write_raw_config(struct jaylink_device_handle *devh,
746 const uint8_t *config)
748 int ret;
749 struct jaylink_context *ctx;
750 uint8_t buf[1];
752 if (!devh || !config)
753 return JAYLINK_ERR_ARG;
755 ctx = devh->dev->ctx;
756 ret = transport_start_write(devh, 1 + JAYLINK_DEV_CONFIG_SIZE, 1);
758 if (ret != JAYLINK_OK) {
759 log_err(ctx, "transport_start_write_read() failed: %i.",
760 ret);
761 return ret;
764 buf[0] = CMD_WRITE_CONFIG;
766 ret = transport_write(devh, buf, 1);
768 if (ret != JAYLINK_OK) {
769 log_err(ctx, "transport_write() failed: %i.", ret);
770 return ret;
773 ret = transport_write(devh, config, JAYLINK_DEV_CONFIG_SIZE);
775 if (ret != JAYLINK_OK) {
776 log_err(ctx, "transport_read() failed: %i.", ret);
777 return ret;
780 return JAYLINK_OK;
783 static void parse_conntable(struct jaylink_connection *conns,
784 const uint8_t *buffer, uint16_t num, uint16_t entry_size)
786 unsigned int i;
787 size_t offset;
789 offset = 0;
791 for (i = 0; i < num; i++) {
792 conns[i].pid = buffer_get_u32(buffer, offset);
793 conns[i].hid = buffer_get_u32(buffer, offset + 4);
794 conns[i].iid = buffer[offset + 8];
795 conns[i].cid = buffer[offset + 9];
796 conns[i].handle = buffer_get_u16(buffer, offset + 10);
797 conns[i].timestamp = buffer_get_u32(buffer, offset + 12);
798 offset = offset + entry_size;
803 * Register a connection on a device.
805 * A connection can be registered by using 0 as handle. Additional information
806 * about the connection can be attached whereby the timestamp is a read-only
807 * value and therefore ignored for registration. On success, a new handle
808 * greater than 0 is obtained from the device.
810 * However, if an obtained handle does not appear in the list of device
811 * connections, the connection was not registered because the maximum number of
812 * connections on the device is reached.
814 * @note This function must only be used if the device has the
815 * #JAYLINK_DEV_CAP_REGISTER capability.
817 * @param[in,out] devh Device handle.
818 * @param[in,out] connection Connection to register on the device.
819 * @param[out] connections Array to store device connections on success.
820 * Its content is undefined on failure. The array must
821 * be large enough to contain at least
822 * #JAYLINK_MAX_CONNECTIONS elements.
823 * @param[out] info Buffer to store additional information on success, or NULL.
824 * The content of the buffer is undefined on failure.
825 * @param[out] info_size Size of the additional information in bytes on success,
826 * and undefined on failure. Can be NULL.
828 * @return The number of device connections on success, a negative error code on
829 * failure.
831 * @see jaylink_unregister() to unregister a connection from a device.
833 JAYLINK_API int jaylink_register(struct jaylink_device_handle *devh,
834 struct jaylink_connection *connection,
835 struct jaylink_connection *connections, uint8_t *info,
836 uint16_t *info_size)
838 int ret;
839 struct jaylink_context *ctx;
840 uint8_t buf[REG_MAX_SIZE];
841 uint16_t handle;
842 uint16_t num;
843 uint16_t entry_size;
844 uint32_t size;
845 uint32_t table_size;
846 uint16_t addinfo_size;
848 if (!devh || !connection || !connections)
849 return JAYLINK_ERR_ARG;
851 ctx = devh->dev->ctx;
852 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, 1);
854 if (ret != JAYLINK_OK) {
855 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
856 return ret;
859 buf[0] = CMD_REGISTER;
860 buf[1] = REG_CMD_REGISTER;
861 buffer_set_u32(buf, connection->pid, 2);
862 buffer_set_u32(buf, connection->hid, 6);
863 buf[10] = connection->iid;
864 buf[11] = connection->cid;
865 buffer_set_u16(buf, connection->handle, 12);
867 ret = transport_write(devh, buf, 14);
869 if (ret != JAYLINK_OK) {
870 log_err(ctx, "transport_write() failed: %i.", ret);
871 return ret;
874 ret = transport_read(devh, buf, REG_MIN_SIZE);
876 if (ret != JAYLINK_OK) {
877 log_err(ctx, "transport_read() failed: %i.", ret);
878 return ret;
881 handle = buffer_get_u16(buf, 0);
882 num = buffer_get_u16(buf, 2);
883 entry_size = buffer_get_u16(buf, 4);
884 addinfo_size = buffer_get_u16(buf, 6);
886 if (num > JAYLINK_MAX_CONNECTIONS) {
887 log_err(ctx, "Maximum number of device connections exceeded: "
888 "%u.", num);
889 return JAYLINK_ERR;
892 if (entry_size != REG_CONN_INFO_SIZE) {
893 log_err(ctx, "Invalid connection entry size: %u bytes.",
894 entry_size);
895 return JAYLINK_ERR;
898 table_size = num * entry_size;
899 size = REG_HEADER_SIZE + table_size + addinfo_size;
901 if (size > REG_MAX_SIZE) {
902 log_err(ctx, "Maximum registration information size exceeded: "
903 "%u bytes.", size);
904 return JAYLINK_ERR;
907 if (size > REG_MIN_SIZE) {
908 ret = transport_start_read(devh, size - REG_MIN_SIZE);
910 if (ret != JAYLINK_OK) {
911 log_err(ctx, "transport_start_read() failed: %i.", ret);
912 return JAYLINK_ERR;
915 ret = transport_read(devh, buf + REG_MIN_SIZE,
916 size - REG_MIN_SIZE);
918 if (ret != JAYLINK_OK) {
919 log_err(ctx, "transport_read() failed: %i.", ret);
920 return JAYLINK_ERR;
924 if (!handle) {
925 log_err(ctx, "Obtained invalid connection handle.");
926 return JAYLINK_ERR;
929 connection->handle = handle;
930 parse_conntable(connections, buf + REG_HEADER_SIZE, num, entry_size);
932 if (info)
933 memcpy(info, buf + REG_HEADER_SIZE + table_size, addinfo_size);
935 if (info_size)
936 *info_size = addinfo_size;
938 return num;
942 * Unregister a connection from a device.
944 * @note This function must only be used if the device has the
945 * #JAYLINK_DEV_CAP_REGISTER capability.
947 * @param[in,out] devh Device handle.
948 * @param[in,out] connection Connection to unregister from the device.
949 * @param[out] connections Array to store device connections on success.
950 * Its content is undefined on failure. The array must
951 * be large enough to contain at least
952 * #JAYLINK_MAX_CONNECTIONS elements.
953 * @param[out] info Buffer to store additional information on success, or NULL.
954 * The content of the buffer is undefined on failure.
955 * @param[out] info_size Size of the additional information in bytes on success,
956 * and undefined on failure. Can be NULL.
958 * @return The number of device connections on success, a negative error code on
959 * failure.
961 JAYLINK_API int jaylink_unregister(struct jaylink_device_handle *devh,
962 const struct jaylink_connection *connection,
963 struct jaylink_connection *connections, uint8_t *info,
964 uint16_t *info_size)
966 int ret;
967 struct jaylink_context *ctx;
968 uint8_t buf[REG_MAX_SIZE];
969 uint16_t num;
970 uint16_t entry_size;
971 uint32_t size;
972 uint32_t table_size;
973 uint16_t addinfo_size;
975 if (!devh || !connection || !connections)
976 return JAYLINK_ERR_ARG;
978 ctx = devh->dev->ctx;
979 ret = transport_start_write_read(devh, 14, REG_MIN_SIZE, 1);
981 if (ret != JAYLINK_OK) {
982 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
983 return ret;
986 buf[0] = CMD_REGISTER;
987 buf[1] = REG_CMD_UNREGISTER;
988 buffer_set_u32(buf, connection->pid, 2);
989 buffer_set_u32(buf, connection->hid, 6);
990 buf[10] = connection->iid;
991 buf[11] = connection->cid;
992 buffer_set_u16(buf, connection->handle, 12);
994 ret = transport_write(devh, buf, 14);
996 if (ret != JAYLINK_OK) {
997 log_err(ctx, "transport_write() failed: %i.", ret);
998 return ret;
1001 ret = transport_read(devh, buf, REG_MIN_SIZE);
1003 if (ret != JAYLINK_OK) {
1004 log_err(ctx, "transport_read() failed: %i.", ret);
1005 return ret;
1008 num = buffer_get_u16(buf, 2);
1009 entry_size = buffer_get_u16(buf, 4);
1010 addinfo_size = buffer_get_u16(buf, 6);
1012 if (num > JAYLINK_MAX_CONNECTIONS) {
1013 log_err(ctx, "Maximum number of device connections exceeded: "
1014 "%u.", num);
1015 return JAYLINK_ERR;
1018 if (entry_size != REG_CONN_INFO_SIZE) {
1019 log_err(ctx, "Invalid connection entry size: %u bytes.",
1020 entry_size);
1021 return JAYLINK_ERR;
1024 table_size = num * entry_size;
1025 size = REG_HEADER_SIZE + table_size + addinfo_size;
1027 if (size > REG_MAX_SIZE) {
1028 log_err(ctx, "Maximum registration information size exceeded: "
1029 "%u bytes.", size);
1030 return JAYLINK_ERR;
1033 if (size > REG_MIN_SIZE) {
1034 ret = transport_start_read(devh, size - REG_MIN_SIZE);
1036 if (ret != JAYLINK_OK) {
1037 log_err(ctx, "transport_start_read() failed: %i.", ret);
1038 return JAYLINK_ERR;
1041 ret = transport_read(devh, buf + REG_MIN_SIZE,
1042 size - REG_MIN_SIZE);
1044 if (ret != JAYLINK_OK) {
1045 log_err(ctx, "transport_read() failed: %i.", ret);
1046 return JAYLINK_ERR;
1050 parse_conntable(connections, buf + REG_HEADER_SIZE, num, entry_size);
1052 if (info)
1053 memcpy(info, buf + REG_HEADER_SIZE + table_size, addinfo_size);
1055 if (info_size)
1056 *info_size = addinfo_size;
1058 return num;