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/>.
27 #include <sys/socket.h>
28 #include <arpa/inet.h>
32 #include "libjaylink.h"
33 #include "libjaylink-internal.h"
38 * Device enumeration and handling.
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_FREE_MEMORY 0xd4
47 #define CMD_GET_CAPS 0xe8
48 #define CMD_GET_EXT_CAPS 0xed
49 #define CMD_GET_HW_VERSION 0xf0
50 #define CMD_READ_CONFIG 0xf2
51 #define CMD_WRITE_CONFIG 0xf3
53 #define REG_CMD_REGISTER 0x64
54 #define REG_CMD_UNREGISTER 0x65
56 /** Size of the registration header in bytes. */
57 #define REG_HEADER_SIZE 8
58 /** Minimum registration information size in bytes. */
59 #define REG_MIN_SIZE 0x4c
60 /** Maximum registration information size in bytes. */
61 #define REG_MAX_SIZE 0x200
62 /** Size of a connection entry in bytes. */
63 #define REG_CONN_INFO_SIZE 16
67 JAYLINK_PRIV
struct jaylink_device
*device_allocate(
68 struct jaylink_context
*ctx
)
70 struct jaylink_device
*dev
;
73 dev
= malloc(sizeof(struct jaylink_device
));
78 list
= list_prepend(ctx
->devs
, 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));
109 * Get available devices.
111 * @param[in,out] ctx libjaylink context.
112 * @param[out] devices Newly allocated array which contains instances of
113 * available devices on success, and undefined on failure.
114 * The array is NULL-terminated and must be free'd by the
115 * caller with 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()
128 JAYLINK_API
int jaylink_get_devices(struct jaylink_context
*ctx
,
129 struct jaylink_device
***devices
, size_t *count
)
133 struct jaylink_device
**devs
;
134 struct jaylink_device
*dev
;
137 if (!ctx
|| !devices
)
138 return JAYLINK_ERR_ARG
;
140 num
= list_length(ctx
->discovered_devs
);
141 devs
= allocate_device_list(num
);
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 devs
[i
] = jaylink_ref_device(dev
);
167 * @param[in,out] devices Array of device instances. Must be NULL-terminated.
168 * @param[in] unref Determines whether the device instances should be
171 * @see jaylink_get_devices()
175 JAYLINK_API
void jaylink_free_devices(struct jaylink_device
**devices
,
184 for (i
= 0; devices
[i
]; i
++)
185 jaylink_unref_device(devices
[i
]);
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
198 * @retval JAYLINK_OK Success.
199 * @retval JAYLINK_ERR_ARG Invalid arguments.
203 JAYLINK_API
int jaylink_device_get_host_interface(
204 const struct jaylink_device
*dev
,
205 enum jaylink_host_interface
*iface
)
208 return JAYLINK_ERR_ARG
;
210 *iface
= dev
->interface
;
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.
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
;
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
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()
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
;
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.
287 JAYLINK_API
struct jaylink_device
*jaylink_ref_device(
288 struct jaylink_device
*dev
)
299 * Decrement the reference count of a device.
301 * @param[in,out] dev Device instance.
305 JAYLINK_API
void jaylink_unref_device(struct jaylink_device
*dev
)
307 struct jaylink_context
*ctx
;
314 if (!dev
->ref_count
) {
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
);
324 libusb_unref_device(dev
->usb_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
));
340 devh
->dev
= jaylink_ref_device(dev
);
345 static void free_device_handle(struct jaylink_device_handle
*devh
)
347 jaylink_unref_device(devh
->dev
);
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 Other error conditions.
366 JAYLINK_API
int jaylink_open(struct jaylink_device
*dev
,
367 struct jaylink_device_handle
**devh
)
370 struct jaylink_device_handle
*handle
;
373 return JAYLINK_ERR_ARG
;
375 handle
= allocate_device_handle(dev
);
378 log_err(dev
->ctx
, "Device handle malloc failed.");
379 return JAYLINK_ERR_MALLOC
;
382 ret
= transport_open(handle
);
384 if (ret
!= JAYLINK_OK
) {
385 free_device_handle(handle
);
397 * @param[in,out] devh Device instance.
399 * @retval JAYLINK_OK Success.
400 * @retval JAYLINK_ERR_ARG Invalid arguments.
401 * @retval JAYLINK_ERR Other error conditions.
405 JAYLINK_API
int jaylink_close(struct jaylink_device_handle
*devh
)
410 return JAYLINK_ERR_ARG
;
412 ret
= transport_close(devh
);
413 free_device_handle(devh
);
419 * Get the device instance from a device handle.
421 * @note The reference count of the device instance is not increased.
423 * @param[in] devh Device handle.
425 * @return The device instance on success, or NULL on invalid argument.
429 JAYLINK_API
struct jaylink_device
*jaylink_get_device(
430 struct jaylink_device_handle
*devh
)
439 * Retrieve the firmware version of a device.
441 * @param[in,out] devh Device handle.
442 * @param[out] version Newly allocated string which contains the firmware
443 * version on success, and undefined if @p length is zero
444 * or on failure. The string is null-terminated and must be
445 * free'd by the caller.
446 * @param[out] length Length of the firmware version string including trailing
447 * null-terminator on success, and undefined on failure.
448 * Zero if no firmware version string is available.
450 * @retval JAYLINK_OK Success.
451 * @retval JAYLINK_ERR_ARG Invalid arguments.
452 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
453 * @retval JAYLINK_ERR_MALLOC Memory allocation error.
454 * @retval JAYLINK_ERR Other error conditions.
458 JAYLINK_API
int jaylink_get_firmware_version(
459 struct jaylink_device_handle
*devh
, char **version
,
463 struct jaylink_context
*ctx
;
468 if (!devh
|| !version
|| !length
)
469 return JAYLINK_ERR_ARG
;
471 ctx
= devh
->dev
->ctx
;
472 ret
= transport_start_write_read(devh
, 1, 2, true);
474 if (ret
!= JAYLINK_OK
) {
475 log_err(ctx
, "transport_start_write_read() failed: %s.",
476 jaylink_strerror(ret
));
480 buf
[0] = CMD_GET_VERSION
;
482 ret
= transport_write(devh
, buf
, 1);
484 if (ret
!= JAYLINK_OK
) {
485 log_err(ctx
, "transport_write() failed: %s.",
486 jaylink_strerror(ret
));
490 ret
= transport_read(devh
, buf
, 2);
492 if (ret
!= JAYLINK_OK
) {
493 log_err(ctx
, "transport_read() failed: %s.",
494 jaylink_strerror(ret
));
498 dummy
= buffer_get_u16(buf
, 0);
504 ret
= transport_start_read(devh
, dummy
);
506 if (ret
!= JAYLINK_OK
) {
507 log_err(ctx
, "transport_start_read() failed: %s.",
508 jaylink_strerror(ret
));
515 log_err(ctx
, "Firmware version string malloc failed.");
516 return JAYLINK_ERR_MALLOC
;
519 ret
= transport_read(devh
, (uint8_t *)tmp
, dummy
);
521 if (ret
!= JAYLINK_OK
) {
522 log_err(ctx
, "transport_read() failed: %s.",
523 jaylink_strerror(ret
));
528 /* Last byte is reserved for null-terminator. */
536 * Retrieve the hardware information of a device.
538 * @note This function must only be used if the device has the
539 * #JAYLINK_DEV_CAP_GET_HW_INFO capability.
541 * @param[in,out] devh Device handle.
542 * @param[in] mask A bit field where each set bit represents hardware
543 * information to request. See #jaylink_hardware_info for a
544 * description of the hardware information and their bit
546 * @param[out] info Array to store the hardware information on success. Its
547 * content is undefined on failure. The array must be large
548 * enough to contain at least as many elements as bits set in
551 * @retval JAYLINK_OK Success.
552 * @retval JAYLINK_ERR_ARG Invalid arguments.
553 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
554 * @retval JAYLINK_ERR Other error conditions.
558 JAYLINK_API
int jaylink_get_hardware_info(struct jaylink_device_handle
*devh
,
559 uint32_t mask
, uint32_t *info
)
562 struct jaylink_context
*ctx
;
568 if (!devh
|| !mask
|| !info
)
569 return JAYLINK_ERR_ARG
;
571 ctx
= devh
->dev
->ctx
;
574 for (i
= 0; i
< 32; i
++) {
579 length
= num
* sizeof(uint32_t);
581 ret
= transport_start_write_read(devh
, 5, length
, true);
583 if (ret
!= JAYLINK_OK
) {
584 log_err(ctx
, "transport_start_write_read() failed: %s.",
585 jaylink_strerror(ret
));
589 buf
[0] = CMD_GET_HW_INFO
;
590 buffer_set_u32(buf
, mask
, 1);
592 ret
= transport_write(devh
, buf
, 5);
594 if (ret
!= JAYLINK_OK
) {
595 log_err(ctx
, "transport_write() failed: %s.",
596 jaylink_strerror(ret
));
600 ret
= transport_read(devh
, (uint8_t *)info
, length
);
602 if (ret
!= JAYLINK_OK
) {
603 log_err(ctx
, "transport_read() failed: %s.",
604 jaylink_strerror(ret
));
608 for (i
= 0; i
< num
; i
++)
609 info
[i
] = buffer_get_u32((uint8_t *)info
,
610 i
* sizeof(uint32_t));
616 * Retrieve the hardware version of a device.
618 * @note This function must only be used if the device has the
619 * #JAYLINK_DEV_CAP_GET_HW_VERSION capability.
621 * @warning This function may return a value for @p version where
622 * #jaylink_hardware_version::type is not covered by
623 * #jaylink_hardware_type.
625 * @param[in,out] devh Device handle.
626 * @param[out] version Hardware version on success, and undefined on 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.
635 JAYLINK_API
int jaylink_get_hardware_version(
636 struct jaylink_device_handle
*devh
,
637 struct jaylink_hardware_version
*version
)
640 struct jaylink_context
*ctx
;
644 if (!devh
|| !version
)
645 return JAYLINK_ERR_ARG
;
647 ctx
= devh
->dev
->ctx
;
648 ret
= transport_start_write_read(devh
, 1, 4, true);
650 if (ret
!= JAYLINK_OK
) {
651 log_err(ctx
, "transport_start_write_read() failed: %s.",
652 jaylink_strerror(ret
));
656 buf
[0] = CMD_GET_HW_VERSION
;
658 ret
= transport_write(devh
, buf
, 1);
660 if (ret
!= JAYLINK_OK
) {
661 log_err(ctx
, "transport_write() failed: %s.",
662 jaylink_strerror(ret
));
666 ret
= transport_read(devh
, buf
, 4);
668 if (ret
!= JAYLINK_OK
) {
669 log_err(ctx
, "transport_read() failed: %s.",
670 jaylink_strerror(ret
));
674 tmp
= buffer_get_u32(buf
, 0);
676 version
->type
= (tmp
/ 1000000) % 100;
677 version
->major
= (tmp
/ 10000) % 100;
678 version
->minor
= (tmp
/ 100) % 100;
679 version
->revision
= tmp
% 100;
685 * Retrieve the hardware status of a device.
687 * @param[in,out] devh Device handle.
688 * @param[out] status Hardware status on success, and undefined on failure.
690 * @retval JAYLINK_OK Success.
691 * @retval JAYLINK_ERR_ARG Invalid arguments.
692 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
693 * @retval JAYLINK_ERR Other error conditions.
697 JAYLINK_API
int jaylink_get_hardware_status(struct jaylink_device_handle
*devh
,
698 struct jaylink_hardware_status
*status
)
701 struct jaylink_context
*ctx
;
704 if (!devh
|| !status
)
705 return JAYLINK_ERR_ARG
;
707 ctx
= devh
->dev
->ctx
;
708 ret
= transport_start_write_read(devh
, 1, 8, true);
710 if (ret
!= JAYLINK_OK
) {
711 log_err(ctx
, "transport_start_write_read() failed: %s.",
712 jaylink_strerror(ret
));
716 buf
[0] = CMD_GET_HW_STATUS
;
718 ret
= transport_write(devh
, buf
, 1);
720 if (ret
!= JAYLINK_OK
) {
721 log_err(ctx
, "transport_write() failed: %s.",
722 jaylink_strerror(ret
));
726 ret
= transport_read(devh
, buf
, 8);
728 if (ret
!= JAYLINK_OK
) {
729 log_err(ctx
, "transport_read() failed: %s.",
730 jaylink_strerror(ret
));
734 status
->target_voltage
= buffer_get_u16(buf
, 0);
735 status
->tck
= buf
[2];
736 status
->tdi
= buf
[3];
737 status
->tdo
= buf
[4];
738 status
->tms
= buf
[5];
739 status
->tres
= buf
[6];
740 status
->trst
= buf
[7];
746 * Retrieve the capabilities of a device.
748 * The capabilities are stored in a 32-bit bit array consisting of
749 * #JAYLINK_DEV_CAPS_SIZE bytes where each individual bit represents a
750 * capability. The first bit of this array is the least significant bit of the
751 * first byte and the following bits are sequentially numbered in order of
752 * increasing bit significance and byte index. A set bit indicates a supported
753 * capability. See #jaylink_device_capability for a description of the
754 * capabilities and their bit positions.
756 * @param[in,out] devh Device handle.
757 * @param[out] caps Buffer to store capabilities on success. Its content is
758 * undefined on failure. The buffer must be large enough to
759 * contain at least #JAYLINK_DEV_CAPS_SIZE bytes.
761 * @retval JAYLINK_OK Success.
762 * @retval JAYLINK_ERR_ARG Invalid arguments.
763 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
764 * @retval JAYLINK_ERR Other error conditions.
766 * @see jaylink_get_extended_caps()
767 * @see jaylink_has_cap()
771 JAYLINK_API
int jaylink_get_caps(struct jaylink_device_handle
*devh
,
775 struct jaylink_context
*ctx
;
779 return JAYLINK_ERR_ARG
;
781 ctx
= devh
->dev
->ctx
;
782 ret
= transport_start_write_read(devh
, 1, JAYLINK_DEV_CAPS_SIZE
, true);
784 if (ret
!= JAYLINK_OK
) {
785 log_err(ctx
, "transport_start_write_read() failed: %s.",
786 jaylink_strerror(ret
));
790 buf
[0] = CMD_GET_CAPS
;
792 ret
= transport_write(devh
, buf
, 1);
794 if (ret
!= JAYLINK_OK
) {
795 log_err(ctx
, "transport_write() failed: %s.",
796 jaylink_strerror(ret
));
800 ret
= transport_read(devh
, caps
, JAYLINK_DEV_CAPS_SIZE
);
802 if (ret
!= JAYLINK_OK
) {
803 log_err(ctx
, "transport_read() failed: %s.",
804 jaylink_strerror(ret
));
812 * Retrieve the extended capabilities of a device.
814 * The extended capabilities are stored in a 256-bit bit array consisting of
815 * #JAYLINK_DEV_EXT_CAPS_SIZE bytes. See jaylink_get_caps() for a further
816 * description of how the capabilities are represented in this bit array. For a
817 * description of the capabilities and their bit positions, see
818 * #jaylink_device_capability.
820 * @note This function must only be used if the device has the
821 * #JAYLINK_DEV_CAP_GET_EXT_CAPS capability.
823 * @param[in,out] devh Device handle.
824 * @param[out] caps Buffer to store capabilities on success. Its content is
825 * undefined on failure. The buffer must be large enough to
826 * contain at least #JAYLINK_DEV_EXT_CAPS_SIZE bytes.
828 * @retval JAYLINK_OK Success.
829 * @retval JAYLINK_ERR_ARG Invalid arguments.
830 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
831 * @retval JAYLINK_ERR Other error conditions.
833 * @see jaylink_get_caps()
837 JAYLINK_API
int jaylink_get_extended_caps(struct jaylink_device_handle
*devh
,
841 struct jaylink_context
*ctx
;
845 return JAYLINK_ERR_ARG
;
847 ctx
= devh
->dev
->ctx
;
848 ret
= transport_start_write_read(devh
, 1, JAYLINK_DEV_EXT_CAPS_SIZE
,
851 if (ret
!= JAYLINK_OK
) {
852 log_err(ctx
, "transport_start_write_read() failed: %s.",
853 jaylink_strerror(ret
));
857 buf
[0] = CMD_GET_EXT_CAPS
;
859 ret
= transport_write(devh
, buf
, 1);
861 if (ret
!= JAYLINK_OK
) {
862 log_err(ctx
, "transport_write() failed: %s.",
863 jaylink_strerror(ret
));
867 ret
= transport_read(devh
, caps
, JAYLINK_DEV_EXT_CAPS_SIZE
);
869 if (ret
!= JAYLINK_OK
) {
870 log_err(ctx
, "transport_read() failed: %s.",
871 jaylink_strerror(ret
));
879 * Retrieve the size of free memory of a device.
881 * @note This function must only be used if the device has the
882 * #JAYLINK_DEV_CAP_GET_FREE_MEMORY capability.
884 * @param[in,out] devh Device handle.
885 * @param[out] size Size of free memory in bytes on success, and undefined on
888 * @retval JAYLINK_OK Success.
889 * @retval JAYLINK_ERR_ARG Invalid arguments.
890 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
891 * @retval JAYLINK_ERR Other error conditions.
895 JAYLINK_API
int jaylink_get_free_memory(struct jaylink_device_handle
*devh
,
899 struct jaylink_context
*ctx
;
903 return JAYLINK_ERR_ARG
;
905 ctx
= devh
->dev
->ctx
;
906 ret
= transport_start_write_read(devh
, 1, 4, true);
908 if (ret
!= JAYLINK_OK
) {
909 log_err(ctx
, "transport_start_write_read() failed: %s.",
910 jaylink_strerror(ret
));
914 buf
[0] = CMD_GET_FREE_MEMORY
;
916 ret
= transport_write(devh
, buf
, 1);
918 if (ret
!= JAYLINK_OK
) {
919 log_err(ctx
, "transport_write() failed: %s.",
920 jaylink_strerror(ret
));
924 ret
= transport_read(devh
, buf
, 4);
926 if (ret
!= JAYLINK_OK
) {
927 log_err(ctx
, "transport_read() failed: %s.",
928 jaylink_strerror(ret
));
932 *size
= buffer_get_u32(buf
, 0);
938 * Read the raw configuration data of a device.
940 * @note This function must only be used if the device has the
941 * #JAYLINK_DEV_CAP_READ_CONFIG capability.
943 * @param[in,out] devh Device handle.
944 * @param[out] config Buffer to store configuration data on success. Its
945 * content is undefined on failure. The buffer must be large
946 * enough to contain at least
947 * #JAYLINK_DEV_CONFIG_SIZE bytes.
949 * @retval JAYLINK_OK Success.
950 * @retval JAYLINK_ERR_ARG Invalid arguments.
951 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
952 * @retval JAYLINK_ERR Other error conditions.
956 JAYLINK_API
int jaylink_read_raw_config(struct jaylink_device_handle
*devh
,
960 struct jaylink_context
*ctx
;
963 if (!devh
|| !config
)
964 return JAYLINK_ERR_ARG
;
966 ctx
= devh
->dev
->ctx
;
967 ret
= transport_start_write_read(devh
, 1, JAYLINK_DEV_CONFIG_SIZE
,
970 if (ret
!= JAYLINK_OK
) {
971 log_err(ctx
, "transport_start_write_read() failed: %s.",
972 jaylink_strerror(ret
));
976 buf
[0] = CMD_READ_CONFIG
;
978 ret
= transport_write(devh
, buf
, 1);
980 if (ret
!= JAYLINK_OK
) {
981 log_err(ctx
, "transport_write() failed: %s.",
982 jaylink_strerror(ret
));
986 ret
= transport_read(devh
, config
, JAYLINK_DEV_CONFIG_SIZE
);
988 if (ret
!= JAYLINK_OK
) {
989 log_err(ctx
, "transport_read() failed: %s.",
990 jaylink_strerror(ret
));
998 * Write the raw configuration data of a device.
1000 * @note This function must only be used if the device has the
1001 * #JAYLINK_DEV_CAP_WRITE_CONFIG capability.
1003 * @param[in,out] devh Device handle.
1004 * @param[in] config Buffer to write configuration data from. The size of the
1005 * configuration data is expected to be
1006 * #JAYLINK_DEV_CONFIG_SIZE bytes.
1008 * @retval JAYLINK_OK Success.
1009 * @retval JAYLINK_ERR_ARG Invalid arguments.
1010 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1011 * @retval JAYLINK_ERR Other error conditions.
1015 JAYLINK_API
int jaylink_write_raw_config(struct jaylink_device_handle
*devh
,
1016 const uint8_t *config
)
1019 struct jaylink_context
*ctx
;
1022 if (!devh
|| !config
)
1023 return JAYLINK_ERR_ARG
;
1025 ctx
= devh
->dev
->ctx
;
1026 ret
= transport_start_write(devh
, 1 + JAYLINK_DEV_CONFIG_SIZE
, true);
1028 if (ret
!= JAYLINK_OK
) {
1029 log_err(ctx
, "transport_start_write() failed: %s.",
1030 jaylink_strerror(ret
));
1034 buf
[0] = CMD_WRITE_CONFIG
;
1036 ret
= transport_write(devh
, buf
, 1);
1038 if (ret
!= JAYLINK_OK
) {
1039 log_err(ctx
, "transport_write() failed: %s.",
1040 jaylink_strerror(ret
));
1044 ret
= transport_write(devh
, config
, JAYLINK_DEV_CONFIG_SIZE
);
1046 if (ret
!= JAYLINK_OK
) {
1047 log_err(ctx
, "transport_write() failed: %s.",
1048 jaylink_strerror(ret
));
1055 static void parse_conntable(struct jaylink_connection
*conns
,
1056 const uint8_t *buffer
, uint16_t num
, uint16_t entry_size
)
1064 for (i
= 0; i
< num
; i
++) {
1065 conns
[i
].pid
= buffer_get_u32(buffer
, offset
);
1067 in
.s_addr
= buffer_get_u32(buffer
, offset
+ 4);
1069 * Use inet_ntoa() instead of inet_ntop() because the latter
1070 * requires at least Windows Vista.
1072 strcpy(conns
[i
].hid
, inet_ntoa(in
));
1074 conns
[i
].iid
= buffer
[offset
+ 8];
1075 conns
[i
].cid
= buffer
[offset
+ 9];
1076 conns
[i
].handle
= buffer_get_u16(buffer
, offset
+ 10);
1077 conns
[i
].timestamp
= buffer_get_u32(buffer
, offset
+ 12);
1078 offset
= offset
+ entry_size
;
1082 static bool _inet_pton(const char *str
, struct in_addr
*in
)
1086 struct sockaddr_in sock_in
;
1089 length
= sizeof(sock_in
);
1092 * Use WSAStringToAddress() instead of inet_pton() because the latter
1093 * requires at least Windows Vista.
1095 ret
= WSAStringToAddress((LPTSTR
)str
, AF_INET
, NULL
,
1096 (LPSOCKADDR
)&sock_in
, &length
);
1101 *in
= sock_in
.sin_addr
;
1103 if (inet_pton(AF_INET
, str
, in
) != 1)
1111 * Register a connection on a device.
1113 * A connection can be registered by using 0 as handle. Additional information
1114 * about the connection can be attached whereby the timestamp is a read-only
1115 * value and therefore ignored for registration. On success, a new handle
1116 * greater than 0 is obtained from the device.
1118 * However, if an obtained handle does not appear in the list of device
1119 * connections, the connection was not registered because the maximum number of
1120 * connections on the device is reached.
1122 * @note This function must only be used if the device has the
1123 * #JAYLINK_DEV_CAP_REGISTER capability.
1125 * @param[in,out] devh Device handle.
1126 * @param[in,out] connection Connection to register on the device.
1127 * @param[out] connections Array to store device connections on success.
1128 * Its content is undefined on failure. The array must
1129 * be large enough to contain at least
1130 * #JAYLINK_MAX_CONNECTIONS elements.
1131 * @param[out] count Number of device connections on success, and undefined on
1134 * @retval JAYLINK_OK Success.
1135 * @retval JAYLINK_ERR_ARG Invalid arguments.
1136 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1137 * @retval JAYLINK_ERR_PROTO Protocol violation.
1138 * @retval JAYLINK_ERR Other error conditions.
1140 * @see jaylink_unregister()
1144 JAYLINK_API
int jaylink_register(struct jaylink_device_handle
*devh
,
1145 struct jaylink_connection
*connection
,
1146 struct jaylink_connection
*connections
, size_t *count
)
1149 struct jaylink_context
*ctx
;
1150 uint8_t buf
[REG_MAX_SIZE
];
1153 uint16_t entry_size
;
1155 uint32_t table_size
;
1156 uint16_t addinfo_size
;
1159 if (!devh
|| !connection
|| !connections
|| !count
)
1160 return JAYLINK_ERR_ARG
;
1162 ctx
= devh
->dev
->ctx
;
1164 buf
[0] = CMD_REGISTER
;
1165 buf
[1] = REG_CMD_REGISTER
;
1166 buffer_set_u32(buf
, connection
->pid
, 2);
1168 if (!_inet_pton(connection
->hid
, &in
))
1169 return JAYLINK_ERR_ARG
;
1171 buffer_set_u32(buf
, in
.s_addr
, 6);
1173 buf
[10] = connection
->iid
;
1174 buf
[11] = connection
->cid
;
1175 buffer_set_u16(buf
, connection
->handle
, 12);
1177 ret
= transport_start_write_read(devh
, 14, REG_MIN_SIZE
, true);
1179 if (ret
!= JAYLINK_OK
) {
1180 log_err(ctx
, "transport_start_write_read() failed: %s.",
1181 jaylink_strerror(ret
));
1185 ret
= transport_write(devh
, buf
, 14);
1187 if (ret
!= JAYLINK_OK
) {
1188 log_err(ctx
, "transport_write() failed: %s.",
1189 jaylink_strerror(ret
));
1193 ret
= transport_read(devh
, buf
, REG_MIN_SIZE
);
1195 if (ret
!= JAYLINK_OK
) {
1196 log_err(ctx
, "transport_read() failed: %s.",
1197 jaylink_strerror(ret
));
1201 handle
= buffer_get_u16(buf
, 0);
1202 num
= buffer_get_u16(buf
, 2);
1203 entry_size
= buffer_get_u16(buf
, 4);
1204 addinfo_size
= buffer_get_u16(buf
, 6);
1206 if (num
> JAYLINK_MAX_CONNECTIONS
) {
1207 log_err(ctx
, "Maximum number of device connections exceeded: "
1209 return JAYLINK_ERR_PROTO
;
1212 if (entry_size
!= REG_CONN_INFO_SIZE
) {
1213 log_err(ctx
, "Invalid connection entry size: %u bytes.",
1215 return JAYLINK_ERR_PROTO
;
1218 table_size
= num
* entry_size
;
1219 size
= REG_HEADER_SIZE
+ table_size
+ addinfo_size
;
1221 if (size
> REG_MAX_SIZE
) {
1222 log_err(ctx
, "Maximum registration information size exceeded: "
1224 return JAYLINK_ERR_PROTO
;
1227 if (size
> REG_MIN_SIZE
) {
1228 ret
= transport_start_read(devh
, size
- REG_MIN_SIZE
);
1230 if (ret
!= JAYLINK_OK
) {
1231 log_err(ctx
, "transport_start_read() failed: %s.",
1232 jaylink_strerror(ret
));
1236 ret
= transport_read(devh
, buf
+ REG_MIN_SIZE
,
1237 size
- REG_MIN_SIZE
);
1239 if (ret
!= JAYLINK_OK
) {
1240 log_err(ctx
, "transport_read() failed: %s.",
1241 jaylink_strerror(ret
));
1247 log_err(ctx
, "Obtained invalid connection handle.");
1248 return JAYLINK_ERR_PROTO
;
1251 connection
->handle
= handle
;
1252 parse_conntable(connections
, buf
+ REG_HEADER_SIZE
, num
, entry_size
);
1260 * Unregister a connection from a device.
1262 * @note This function must only be used if the device has the
1263 * #JAYLINK_DEV_CAP_REGISTER capability.
1265 * @param[in,out] devh Device handle.
1266 * @param[in,out] connection Connection to unregister from the device.
1267 * @param[out] connections Array to store device connections on success.
1268 * Its content is undefined on failure. The array must
1269 * be large enough to contain at least
1270 * #JAYLINK_MAX_CONNECTIONS elements.
1271 * @param[out] count Number of device connections on success, and undefined on
1274 * @retval JAYLINK_OK Success.
1275 * @retval JAYLINK_ERR_ARG Invalid arguments.
1276 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
1277 * @retval JAYLINK_ERR_PROTO Protocol violation.
1278 * @retval JAYLINK_ERR Other error conditions.
1280 * @see jaylink_register()
1284 JAYLINK_API
int jaylink_unregister(struct jaylink_device_handle
*devh
,
1285 const struct jaylink_connection
*connection
,
1286 struct jaylink_connection
*connections
, size_t *count
)
1289 struct jaylink_context
*ctx
;
1290 uint8_t buf
[REG_MAX_SIZE
];
1292 uint16_t entry_size
;
1294 uint32_t table_size
;
1295 uint16_t addinfo_size
;
1298 if (!devh
|| !connection
|| !connections
|| !count
)
1299 return JAYLINK_ERR_ARG
;
1301 ctx
= devh
->dev
->ctx
;
1303 buf
[0] = CMD_REGISTER
;
1304 buf
[1] = REG_CMD_UNREGISTER
;
1305 buffer_set_u32(buf
, connection
->pid
, 2);
1307 if (!_inet_pton(connection
->hid
, &in
))
1308 return JAYLINK_ERR_ARG
;
1310 buffer_set_u32(buf
, in
.s_addr
, 6);
1312 buf
[10] = connection
->iid
;
1313 buf
[11] = connection
->cid
;
1314 buffer_set_u16(buf
, connection
->handle
, 12);
1316 ret
= transport_start_write_read(devh
, 14, REG_MIN_SIZE
, true);
1318 if (ret
!= JAYLINK_OK
) {
1319 log_err(ctx
, "transport_start_write_read() failed: %s.",
1320 jaylink_strerror(ret
));
1324 ret
= transport_write(devh
, buf
, 14);
1326 if (ret
!= JAYLINK_OK
) {
1327 log_err(ctx
, "transport_write() failed: %s.",
1328 jaylink_strerror(ret
));
1332 ret
= transport_read(devh
, buf
, REG_MIN_SIZE
);
1334 if (ret
!= JAYLINK_OK
) {
1335 log_err(ctx
, "transport_read() failed: %s.",
1336 jaylink_strerror(ret
));
1340 num
= buffer_get_u16(buf
, 2);
1341 entry_size
= buffer_get_u16(buf
, 4);
1342 addinfo_size
= buffer_get_u16(buf
, 6);
1344 if (num
> JAYLINK_MAX_CONNECTIONS
) {
1345 log_err(ctx
, "Maximum number of device connections exceeded: "
1347 return JAYLINK_ERR_PROTO
;
1350 if (entry_size
!= REG_CONN_INFO_SIZE
) {
1351 log_err(ctx
, "Invalid connection entry size: %u bytes.",
1353 return JAYLINK_ERR_PROTO
;
1356 table_size
= num
* entry_size
;
1357 size
= REG_HEADER_SIZE
+ table_size
+ addinfo_size
;
1359 if (size
> REG_MAX_SIZE
) {
1360 log_err(ctx
, "Maximum registration information size exceeded: "
1362 return JAYLINK_ERR_PROTO
;
1365 if (size
> REG_MIN_SIZE
) {
1366 ret
= transport_start_read(devh
, size
- REG_MIN_SIZE
);
1368 if (ret
!= JAYLINK_OK
) {
1369 log_err(ctx
, "transport_start_read() failed: %s.",
1370 jaylink_strerror(ret
));
1374 ret
= transport_read(devh
, buf
+ REG_MIN_SIZE
,
1375 size
- REG_MIN_SIZE
);
1377 if (ret
!= JAYLINK_OK
) {
1378 log_err(ctx
, "transport_read() failed: %s.",
1379 jaylink_strerror(ret
));
1384 parse_conntable(connections
, buf
+ REG_HEADER_SIZE
, num
, entry_size
);