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 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/>.
24 #include "libjaylink.h"
25 #include "libjaylink-internal.h"
30 * Transport abstraction layer.
33 /** Timeout of an USB transfer in milliseconds. */
34 #define USB_TIMEOUT 1000
37 * Number of consecutive timeouts before an USB transfer will be treated as
40 #define NUM_TIMEOUTS 2
42 /** Chunk size in bytes in which data is transferred. */
43 #define CHUNK_SIZE 2048
46 * Buffer size in bytes.
48 * Note that both write and read operations require a buffer size of at least
51 #define BUFFER_SIZE CHUNK_SIZE
53 static int initialize_handle(struct jaylink_device_handle
*devh
)
56 struct jaylink_context
*ctx
;
57 struct libusb_config_descriptor
*config
;
58 const struct libusb_interface
*interface
;
59 const struct libusb_interface_descriptor
*desc
;
60 const struct libusb_endpoint_descriptor
*epdesc
;
62 int found_endpoint_in
;
63 int found_endpoint_out
;
67 devh
->interface_number
= 0;
70 * Retrieve active configuration descriptor to determine the endpoints
71 * for the interface number of the device.
73 ret
= libusb_get_active_config_descriptor(devh
->dev
->usb_dev
, &config
);
75 if (ret
!= LIBUSB_SUCCESS
) {
76 log_err(ctx
, "Failed to get configuration descriptor: %s.",
77 libusb_error_name(ret
));
83 for (i
= 0; i
< config
->bNumInterfaces
; i
++) {
84 interface
= &config
->interface
[i
];
85 desc
= &interface
->altsetting
[0];
87 if (desc
->bInterfaceClass
!= LIBUSB_CLASS_VENDOR_SPEC
)
90 if (desc
->bInterfaceSubClass
!= LIBUSB_CLASS_VENDOR_SPEC
)
93 if (desc
->bNumEndpoints
< 2)
97 devh
->interface_number
= i
;
101 if (!found_interface
) {
102 log_err(ctx
, "No suitable interface found.");
103 libusb_free_config_descriptor(config
);
107 found_endpoint_in
= 0;
108 found_endpoint_out
= 0;
110 for (i
= 0; i
< desc
->bNumEndpoints
; i
++) {
111 epdesc
= &desc
->endpoint
[i
];
113 if (epdesc
->bEndpointAddress
& LIBUSB_ENDPOINT_IN
) {
114 devh
->endpoint_in
= epdesc
->bEndpointAddress
;
115 found_endpoint_in
= 1;
117 devh
->endpoint_out
= epdesc
->bEndpointAddress
;
118 found_endpoint_out
= 1;
122 libusb_free_config_descriptor(config
);
124 if (!found_endpoint_in
) {
125 log_err(ctx
, "Interface IN endpoint not found.");
129 if (!found_endpoint_out
) {
130 log_err(ctx
, "Interface OUT endpoint not found.");
134 log_dbg(ctx
, "Using endpoint %02x (IN) and %02x (OUT).",
135 devh
->endpoint_in
, devh
->endpoint_out
);
137 devh
->buffer
= malloc(BUFFER_SIZE
);
140 log_err(ctx
, "Transport buffer malloc failed.");
141 return JAYLINK_ERR_MALLOC
;
144 devh
->read_length
= 0;
145 devh
->bytes_available
= 0;
148 devh
->write_length
= 0;
154 static void cleanup_handle(struct jaylink_device_handle
*devh
)
162 * This function must be called before any other function of the transport
163 * abstraction layer for the given device handle is called.
165 * @param devh Device handle.
167 * @retval JAYLINK_OK Success.
168 * @retval JAYLINK_ERR Other error conditions.
170 JAYLINK_PRIV
int transport_open(struct jaylink_device_handle
*devh
)
173 struct jaylink_device
*dev
;
174 struct jaylink_context
*ctx
;
175 struct libusb_device_handle
*usb_devh
;
180 log_dbg(ctx
, "Trying to open device (bus:address = %03u:%03u).",
181 libusb_get_bus_number(dev
->usb_dev
),
182 libusb_get_device_address(dev
->usb_dev
));
184 ret
= initialize_handle(devh
);
186 if (ret
!= JAYLINK_OK
) {
187 log_err(ctx
, "Initialize device handle failed.");
191 ret
= libusb_open(dev
->usb_dev
, &usb_devh
);
193 if (ret
!= LIBUSB_SUCCESS
) {
194 log_err(ctx
, "Failed to open device: %s.",
195 libusb_error_name(ret
));
196 cleanup_handle(devh
);
200 ret
= libusb_claim_interface(usb_devh
, devh
->interface_number
);
202 if (ret
!= LIBUSB_SUCCESS
) {
203 log_err(ctx
, "Failed to claim interface: %s.",
204 libusb_error_name(ret
));
205 cleanup_handle(devh
);
206 libusb_close(usb_devh
);
210 log_dbg(ctx
, "Device opened successfully.");
212 devh
->usb_devh
= usb_devh
;
220 * After this function has been called no other function of the transport
221 * abstraction layer for the given device handle must be called.
223 * @param devh Device handle.
225 * @retval JAYLINK_OK Success.
226 * @retval JAYLINK_ERR Other error conditions.
228 JAYLINK_PRIV
int transport_close(struct jaylink_device_handle
*devh
)
231 struct jaylink_device
*dev
;
232 struct jaylink_context
*ctx
;
237 log_dbg(ctx
, "Closing device (bus:address = %03u:%03u).",
238 libusb_get_bus_number(dev
->usb_dev
),
239 libusb_get_device_address(dev
->usb_dev
));
241 ret
= libusb_release_interface(devh
->usb_devh
, devh
->interface_number
);
243 libusb_close(devh
->usb_devh
);
244 cleanup_handle(devh
);
246 if (ret
!= LIBUSB_SUCCESS
) {
247 log_err(ctx
, "Failed to release interface: %s.",
248 libusb_error_name(ret
));
256 * Start a write operation for a device.
258 * The data of a write operation must be written with at least one call of
259 * transport_write(). It is required that all data of a write operation is
260 * written before an other write and/or read operation is started.
262 * @param devh Device handle.
263 * @param length Number of bytes of the write operation.
264 * @param has_command Determines whether the data of the write operation
265 * contains the protocol command.
267 * @retval JAYLINK_OK Success.
268 * @retval JAYLINK_ERR_ARG Invalid arguments.
270 JAYLINK_PRIV
int transport_start_write(struct jaylink_device_handle
*devh
,
271 uint16_t length
, int has_command
)
273 struct jaylink_context
*ctx
;
278 return JAYLINK_ERR_ARG
;
280 ctx
= devh
->dev
->ctx
;
282 log_dbg(ctx
, "Starting write operation (length = %u bytes).", length
);
284 if (devh
->write_pos
> 0)
285 log_warn(ctx
, "Last write operation left %u bytes in the "
286 "buffer.", devh
->write_pos
);
288 if (devh
->write_length
> 0)
289 log_warn(ctx
, "Last write operation was not performed.");
291 devh
->write_length
= length
;
298 * Start a read operation for a device.
300 * The data of a read operation must be read with at least one call of
301 * transport_read(). It is required that all data of a read operation is read
302 * before an other write and/or read operation is started.
304 * @param devh Device handle.
305 * @param length Number of bytes of the read operation.
307 * @retval JAYLINK_OK Success.
308 * @retval JAYLINK_ERR_ARG Invalid arguments.
310 JAYLINK_PRIV
int transport_start_read(struct jaylink_device_handle
*devh
,
313 struct jaylink_context
*ctx
;
316 return JAYLINK_ERR_ARG
;
318 ctx
= devh
->dev
->ctx
;
320 log_dbg(ctx
, "Starting read operation (length = %u bytes).", length
);
322 if (devh
->bytes_available
> 0)
323 log_dbg(ctx
, "Last read operation left %u bytes in the "
324 "buffer.", devh
->bytes_available
);
326 if (devh
->read_length
> 0)
327 log_warn(ctx
, "Last read operation left %u bytes.",
330 devh
->read_length
= length
;
336 * Start a write and read operation for a device.
338 * This function starts a write and read operation as the consecutive call of
339 * transport_start_write() and transport_start_read() but has a different
340 * meaning from the protocol perspective and can therefore not be replaced by
341 * these functions and vice versa.
343 * @note The write operation must be completed first before the read operation
346 * @param devh Device handle.
347 * @param write_length Number of bytes of the write operation.
348 * @param read_length Number of bytes of the read operation.
349 * @param has_command Determines whether the data of the write operation
350 * contains the protocol command.
352 * @retval JAYLINK_OK Success.
353 * @retval JAYLINK_ERR_ARG Invalid arguments.
355 JAYLINK_PRIV
int transport_start_write_read(struct jaylink_device_handle
*devh
,
356 uint16_t write_length
, uint16_t read_length
, int has_command
)
358 struct jaylink_context
*ctx
;
362 if (!read_length
|| !write_length
)
363 return JAYLINK_ERR_ARG
;
365 ctx
= devh
->dev
->ctx
;
367 log_dbg(ctx
, "Starting write / read operation (length = "
368 "%u / %u bytes).", write_length
, read_length
);
370 if (devh
->write_pos
> 0)
371 log_warn(ctx
, "Last write operation left %u bytes in the "
372 "buffer.", devh
->write_pos
);
374 if (devh
->write_length
> 0)
375 log_warn(ctx
, "Last write operation was not performed.");
377 if (devh
->bytes_available
> 0)
378 log_warn(ctx
, "Last read operation left %u bytes in the "
379 "buffer.", devh
->bytes_available
);
381 if (devh
->read_length
> 0)
382 log_warn(ctx
, "Last read operation left %u bytes.",
385 devh
->write_length
= write_length
;
388 devh
->read_length
= read_length
;
389 devh
->bytes_available
= 0;
395 static int usb_recv(struct jaylink_device_handle
*devh
, uint8_t *buffer
,
399 struct jaylink_context
*ctx
;
403 ctx
= devh
->dev
->ctx
;
404 tries
= NUM_TIMEOUTS
;
407 while (tries
> 0 && !transferred
) {
408 /* Always request CHUNK_SIZE bytes from the device. */
409 ret
= libusb_bulk_transfer(devh
->usb_devh
, devh
->endpoint_in
,
410 (unsigned char *)buffer
, CHUNK_SIZE
, &transferred
,
413 if (ret
== LIBUSB_ERROR_TIMEOUT
) {
414 log_warn(ctx
, "Failed to receive data from "
415 "device: %s.", libusb_error_name(ret
));
418 } else if (ret
!= LIBUSB_SUCCESS
) {
419 log_err(ctx
, "Failed to receive data from "
420 "device: %s.", libusb_error_name(ret
));
424 log_dbg(ctx
, "Received %u bytes from device.", transferred
);
427 /* Ignore a possible timeout if at least one byte was received. */
428 if (transferred
> 0) {
429 *length
= transferred
;
433 log_err(ctx
, "Receiving data from device timed out.");
435 return JAYLINK_ERR_TIMEOUT
;
438 static int usb_send(struct jaylink_device_handle
*devh
, const uint8_t *buffer
,
442 struct jaylink_context
*ctx
;
446 ctx
= devh
->dev
->ctx
;
447 tries
= NUM_TIMEOUTS
;
449 while (tries
> 0 && length
> 0) {
450 /* Send data in chunks of CHUNK_SIZE bytes to the device. */
451 ret
= libusb_bulk_transfer(devh
->usb_devh
, devh
->endpoint_out
,
452 (unsigned char *)buffer
, MIN(CHUNK_SIZE
, length
),
453 &transferred
, USB_TIMEOUT
);
455 if (ret
== LIBUSB_SUCCESS
) {
456 tries
= NUM_TIMEOUTS
;
457 } else if (ret
== LIBUSB_ERROR_TIMEOUT
) {
458 log_warn(ctx
, "Failed to send data to device: %s.",
459 libusb_error_name(ret
));
462 log_err(ctx
, "Failed to send data to device: %s.",
463 libusb_error_name(ret
));
467 buffer
+= transferred
;
468 length
-= transferred
;
470 log_dbg(ctx
, "Sent %u bytes to device.", transferred
);
476 log_err(ctx
, "Sending data to device timed out.");
478 return JAYLINK_ERR_TIMEOUT
;
482 * Write data to a device.
484 * Before this function is used transport_start_write() or
485 * transport_start_write_read() must be called to start a write operation. The
486 * total number of written bytes must not exceed the number of bytes of the
489 * @note A write operation will be performed and the data will be sent to the
490 * device when the number of written bytes reaches the number of bytes of
491 * the write operation. Before that the data will be written into a
494 * @param devh Device handle.
495 * @param buffer Buffer to write data from.
496 * @param length Number of bytes to write.
498 * @retval JAYLINK_OK Success.
499 * @retval JAYLINK_ERR_ARG Invalid arguments.
500 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
501 * @retval JAYLINK_ERR Other error conditions.
503 JAYLINK_PRIV
int transport_write(struct jaylink_device_handle
*devh
,
504 const uint8_t *buffer
, uint16_t length
)
507 struct jaylink_context
*ctx
;
512 ctx
= devh
->dev
->ctx
;
514 if (length
> devh
->write_length
) {
515 log_err(ctx
, "Requested to write %u bytes but only %u bytes "
516 "are expected for the write operation.", length
,
518 return JAYLINK_ERR_ARG
;
522 * Store data in the buffer if the expected number of bytes for the
523 * write operation is not reached.
525 if (length
< devh
->write_length
) {
526 if (devh
->write_pos
+ length
> BUFFER_SIZE
) {
527 log_err(ctx
, "Write request is too large for the "
529 return JAYLINK_ERR_ARG
;
532 memcpy(devh
->buffer
+ devh
->write_pos
, buffer
, length
);
534 devh
->write_length
-= length
;
535 devh
->write_pos
+= length
;
537 log_dbg(ctx
, "Wrote %u bytes into buffer.", length
);
542 * Expected number of bytes for this write operation is reached and
543 * therefore the write operation will be performed.
545 devh
->write_length
= 0;
547 /* Send data directly to the device if the buffer is empty. */
548 if (!devh
->write_pos
)
549 return usb_send(devh
, buffer
, length
);
552 * Calculate the number of bytes to fill up the buffer to reach a
553 * multiple of CHUNK_SIZE bytes. This ensures that the data from the
554 * buffer will be sent to the device in chunks of CHUNK_SIZE bytes.
555 * Note that this is why the buffer size must be at least CHUNK_SIZE
558 num_chunks
= devh
->write_pos
/ CHUNK_SIZE
;
560 if (devh
->write_pos
% CHUNK_SIZE
)
563 fill_bytes
= (num_chunks
* CHUNK_SIZE
) - devh
->write_pos
;
564 tmp
= MIN(length
, fill_bytes
);
567 memcpy(devh
->buffer
+ devh
->write_pos
, buffer
, tmp
);
572 log_dbg(ctx
, "Buffer filled up with %u bytes.", tmp
);
575 /* Send buffered data to the device. */
576 ret
= usb_send(devh
, devh
->buffer
, devh
->write_pos
+ tmp
);
579 if (ret
!= JAYLINK_OK
)
585 /* Send remaining data to the device. */
586 return usb_send(devh
, buffer
, length
);
590 * Read data from a device.
592 * Before this function is used transport_start_read() or
593 * transport_start_write_read() must be called to start a read operation. The
594 * total number of read bytes must not exceed the number of bytes of the read
597 * @param devh Device handle.
598 * @param buffer Buffer to read data into on success. Its content is undefined
600 * @param length Number of bytes to read.
602 * @retval JAYLINK_OK Success.
603 * @retval JAYLINK_ERR_ARG Invalid arguments.
604 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
605 * @retval JAYLINK_ERR Other error conditions.
607 JAYLINK_PRIV
int transport_read(struct jaylink_device_handle
*devh
,
608 uint8_t *buffer
, uint16_t length
)
611 struct jaylink_context
*ctx
;
612 uint16_t bytes_received
;
615 ctx
= devh
->dev
->ctx
;
617 if (length
> devh
->read_length
) {
618 log_err(ctx
, "Requested to read %u bytes but only %u bytes "
619 "are expected for the read operation.", length
,
621 return JAYLINK_ERR_ARG
;
624 if (length
<= devh
->bytes_available
) {
625 memcpy(buffer
, devh
->buffer
+ devh
->read_pos
, length
);
627 devh
->read_length
-= length
;
628 devh
->bytes_available
-= length
;
629 devh
->read_pos
+= length
;
631 log_dbg(ctx
, "Read %u bytes from buffer.", length
);
635 if (devh
->bytes_available
) {
636 memcpy(buffer
, devh
->buffer
+ devh
->read_pos
,
637 devh
->bytes_available
);
639 buffer
+= devh
->bytes_available
;
640 length
-= devh
->bytes_available
;
641 devh
->read_length
-= devh
->bytes_available
;
643 log_dbg(ctx
, "Read %u bytes from buffer to flush it.",
644 devh
->bytes_available
);
646 devh
->bytes_available
= 0;
652 * If less than CHUNK_SIZE bytes are requested from the device,
653 * store the received data in the internal buffer instead of
654 * directly into the user provided buffer. This is necessary to
655 * prevent a possible buffer overflow because the number of
656 * requested bytes from the device is always CHUNK_SIZE and
657 * therefore up to CHUNK_SIZE bytes may be received.
659 if (length
< CHUNK_SIZE
) {
660 ret
= usb_recv(devh
, devh
->buffer
, &bytes_received
);
662 if (ret
!= JAYLINK_OK
)
665 tmp
= MIN(bytes_received
, length
);
666 memcpy(buffer
, devh
->buffer
, tmp
);
669 * Setup the buffer for the remaining data if more data
670 * was received from the device than was requested.
672 if (bytes_received
> length
) {
673 devh
->bytes_available
= bytes_received
- tmp
;
674 devh
->read_pos
= tmp
;
679 devh
->read_length
-= tmp
;
681 log_dbg(ctx
, "Read %u bytes from buffer.", tmp
);
683 ret
= usb_recv(devh
, buffer
, &bytes_received
);
685 if (ret
!= JAYLINK_OK
)
688 buffer
+= bytes_received
;
689 length
-= bytes_received
;
690 devh
->read_length
-= bytes_received
;
692 log_dbg(ctx
, "Read %u bytes from device.",