Add build support for OSX.
[libjaylink.git] / libjaylink / transport.c
blobe1e920f543bdc66230be486d101831ddfe6b35fe
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 <stdint.h>
21 #include <string.h>
23 #include "libjaylink.h"
24 #include "libjaylink-internal.h"
26 /**
27 * @file
29 * Transport abstraction layer.
32 /** Timeout of an USB transfer in milliseconds. */
33 #define USB_TIMEOUT 1000
35 /**
36 * Number of consecutive timeouts before an USB transfer will be treated as
37 * timed out.
39 #define NUM_TIMEOUTS 2
41 /** Chunk size in bytes in which data is transferred. */
42 #define CHUNK_SIZE 2048
44 /**
45 * Buffer size in bytes.
47 * Note that both write and read operations require a buffer size of at least
48 * #CHUNK_SIZE bytes.
50 #define BUFFER_SIZE CHUNK_SIZE
52 static int initialize_handle(struct jaylink_device_handle *devh)
54 int ret;
55 struct jaylink_context *ctx;
56 struct libusb_config_descriptor *config;
57 const struct libusb_interface *interface;
58 const struct libusb_interface_descriptor *desc;
59 const struct libusb_endpoint_descriptor *epdesc;
60 int found_interface;
61 int found_endpoint_in;
62 int found_endpoint_out;
63 uint8_t i;
65 ctx = devh->dev->ctx;
66 devh->interface_number = 0;
69 * Retrieve active configuration descriptor to determine the endpoints
70 * for the interface number of the device.
72 ret = libusb_get_active_config_descriptor(devh->dev->usb_dev, &config);
74 if (ret != LIBUSB_SUCCESS) {
75 log_err(ctx, "Failed to get configuration descriptor: %s.",
76 libusb_error_name(ret));
77 return JAYLINK_ERR;
80 found_interface = 0;
82 for (i = 0; i < config->bNumInterfaces; i++) {
83 interface = &config->interface[i];
84 desc = &interface->altsetting[0];
86 if (desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)
87 continue;
89 if (desc->bInterfaceSubClass != LIBUSB_CLASS_VENDOR_SPEC)
90 continue;
92 if (desc->bNumEndpoints < 2)
93 continue;
95 found_interface = 1;
96 devh->interface_number = i;
97 break;
100 if (!found_interface) {
101 log_err(ctx, "No suitable interface found.");
102 libusb_free_config_descriptor(config);
103 return JAYLINK_ERR;
106 found_endpoint_in = 0;
107 found_endpoint_out = 0;
109 for (i = 0; i < desc->bNumEndpoints; i++) {
110 epdesc = &desc->endpoint[i];
112 if (epdesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
113 devh->endpoint_in = epdesc->bEndpointAddress;
114 found_endpoint_in = 1;
115 } else {
116 devh->endpoint_out = epdesc->bEndpointAddress;
117 found_endpoint_out = 1;
121 libusb_free_config_descriptor(config);
123 if (!found_endpoint_in) {
124 log_err(ctx, "Interface IN endpoint not found.");
125 return JAYLINK_ERR;
128 if (!found_endpoint_out) {
129 log_err(ctx, "Interface OUT endpoint not found.");
130 return JAYLINK_ERR;
133 log_dbg(ctx, "Using endpoint %02x (IN) and %02x (OUT).",
134 devh->endpoint_in, devh->endpoint_out);
136 devh->buffer = malloc(BUFFER_SIZE);
138 if (!devh->buffer) {
139 log_err(ctx, "Transport buffer malloc failed.");
140 return JAYLINK_ERR_MALLOC;
143 devh->read_length = 0;
144 devh->bytes_available = 0;
145 devh->read_pos = 0;
147 devh->write_length = 0;
148 devh->write_pos = 0;
150 return JAYLINK_OK;
153 static void cleanup_handle(struct jaylink_device_handle *devh)
155 free(devh->buffer);
159 * Open a device.
161 * This function must be called before any other function of the transport
162 * abstraction layer for the given device handle is called.
164 * @param devh Device handle.
166 * @retval JAYLINK_OK Success.
167 * @retval JAYLINK_ERR Other error conditions.
169 JAYLINK_PRIV int transport_open(struct jaylink_device_handle *devh)
171 int ret;
172 struct jaylink_device *dev;
173 struct jaylink_context *ctx;
174 struct libusb_device_handle *usb_devh;
176 dev = devh->dev;
177 ctx = dev->ctx;
179 log_dbg(ctx, "Trying to open device (bus:address = %03u:%03u).",
180 libusb_get_bus_number(dev->usb_dev),
181 libusb_get_device_address(dev->usb_dev));
183 ret = initialize_handle(devh);
185 if (ret != JAYLINK_OK) {
186 log_err(ctx, "Initialize device handle failed.");
187 return ret;
190 ret = libusb_open(dev->usb_dev, &usb_devh);
192 if (ret != LIBUSB_SUCCESS) {
193 log_err(ctx, "Failed to open device: %s.",
194 libusb_error_name(ret));
195 cleanup_handle(devh);
196 return JAYLINK_ERR;
199 ret = libusb_claim_interface(usb_devh, devh->interface_number);
201 if (ret != LIBUSB_SUCCESS) {
202 log_err(ctx, "Failed to claim interface: %s.",
203 libusb_error_name(ret));
204 cleanup_handle(devh);
205 libusb_close(usb_devh);
206 return JAYLINK_ERR;
209 log_dbg(ctx, "Device opened successfully.");
211 devh->usb_devh = usb_devh;
213 return JAYLINK_OK;
217 * Close a device.
219 * After this function has been called no other function of the transport
220 * abstraction layer for the given device handle must be called.
222 * @param devh Device handle.
224 * @retval JAYLINK_OK Success.
225 * @retval JAYLINK_ERR Other error conditions.
227 JAYLINK_PRIV int transport_close(struct jaylink_device_handle *devh)
229 int ret;
230 struct jaylink_device *dev;
231 struct jaylink_context *ctx;
233 dev = devh->dev;
234 ctx = dev->ctx;
236 log_dbg(ctx, "Closing device (bus:address = %03u:%03u).",
237 libusb_get_bus_number(dev->usb_dev),
238 libusb_get_device_address(dev->usb_dev));
240 ret = libusb_release_interface(devh->usb_devh, devh->interface_number);
242 libusb_close(devh->usb_devh);
243 cleanup_handle(devh);
245 if (ret != LIBUSB_SUCCESS) {
246 log_err(ctx, "Failed to release interface: %s.",
247 libusb_error_name(ret));
248 return JAYLINK_ERR;
251 return JAYLINK_OK;
255 * Start a write operation for a device.
257 * The data of a write operation must be written with at least one call of
258 * transport_write(). It is required that all data of a write operation is
259 * written before an other write and/or read operation is started.
261 * @param devh Device handle.
262 * @param length Number of bytes of the write operation.
263 * @param has_command Determines whether the data of the write operation
264 * contains the protocol command.
266 * @retval JAYLINK_OK Success.
267 * @retval JAYLINK_ERR_ARG Invalid arguments.
269 JAYLINK_PRIV int transport_start_write(struct jaylink_device_handle *devh,
270 uint16_t length, int has_command)
272 struct jaylink_context *ctx;
274 (void)has_command;
276 if (!length)
277 return JAYLINK_ERR_ARG;
279 ctx = devh->dev->ctx;
281 log_dbg(ctx, "Starting write operation (length = %u bytes).", length);
283 if (devh->write_pos)
284 log_warn(ctx, "Last write operation left %u bytes in the "
285 "buffer.", devh->write_pos);
287 if (devh->write_length)
288 log_warn(ctx, "Last write operation was not performed.");
290 devh->write_length = length;
291 devh->write_pos = 0;
293 return JAYLINK_OK;
297 * Start a read operation for a device.
299 * The data of a read operation must be read with at least one call of
300 * transport_read(). It is required that all data of a read operation is read
301 * before an other write and/or read operation is started.
303 * @param devh Device handle.
304 * @param length Number of bytes of the read operation.
306 * @retval JAYLINK_OK Success.
307 * @retval JAYLINK_ERR_ARG Invalid arguments.
309 JAYLINK_PRIV int transport_start_read(struct jaylink_device_handle *devh,
310 uint16_t length)
312 struct jaylink_context *ctx;
314 if (!length)
315 return JAYLINK_ERR_ARG;
317 ctx = devh->dev->ctx;
319 log_dbg(ctx, "Starting read operation (length = %u bytes).", length);
321 if (devh->bytes_available)
322 log_dbg(ctx, "Last read operation left %u bytes in the "
323 "buffer.", devh->bytes_available);
325 if (devh->read_length)
326 log_warn(ctx, "Last read operation left %u bytes.",
327 devh->read_length);
329 devh->read_length = length;
331 return JAYLINK_OK;
335 * Start a write and read operation for a device.
337 * This function starts a write and read operation as the consecutive call of
338 * transport_start_write() and transport_start_read() but has a different
339 * meaning from the protocol perspective and can therefore not be replaced by
340 * these functions and vice versa.
342 * @note The write operation must be completed first before the read operation
343 * must be processed.
345 * @param devh Device handle.
346 * @param write_length Number of bytes of the write operation.
347 * @param read_length Number of bytes of the read operation.
348 * @param has_command Determines whether the data of the write operation
349 * contains the protocol command.
351 * @retval JAYLINK_OK Success.
352 * @retval JAYLINK_ERR_ARG Invalid arguments.
354 JAYLINK_PRIV int transport_start_write_read(struct jaylink_device_handle *devh,
355 uint16_t write_length, uint16_t read_length, int has_command)
357 struct jaylink_context *ctx;
359 (void)has_command;
361 if (!read_length || !write_length)
362 return JAYLINK_ERR_ARG;
364 ctx = devh->dev->ctx;
366 log_dbg(ctx, "Starting write / read operation (length = "
367 "%u / %u bytes).", write_length, read_length);
369 if (devh->write_pos)
370 log_warn(ctx, "Last write operation left %u bytes in the "
371 "buffer.", devh->write_pos);
373 if (devh->write_length)
374 log_warn(ctx, "Last write operation was not performed.");
376 if (devh->bytes_available)
377 log_warn(ctx, "Last read operation left %u bytes in the "
378 "buffer.", devh->bytes_available);
380 if (devh->read_length)
381 log_warn(ctx, "Last read operation left %u bytes.",
382 devh->read_length);
384 devh->write_length = write_length;
385 devh->write_pos = 0;
387 devh->read_length = read_length;
388 devh->bytes_available = 0;
389 devh->read_pos = 0;
391 return JAYLINK_OK;
394 static int usb_recv(struct jaylink_device_handle *devh, uint8_t *buffer,
395 uint16_t *length)
397 int ret;
398 struct jaylink_context *ctx;
399 unsigned int tries;
400 int transferred;
402 ctx = devh->dev->ctx;
403 tries = NUM_TIMEOUTS;
404 transferred = 0;
406 while (tries && !transferred) {
407 /* Always request CHUNK_SIZE bytes from the device. */
408 ret = libusb_bulk_transfer(devh->usb_devh, devh->endpoint_in,
409 (unsigned char *)buffer, CHUNK_SIZE, &transferred,
410 USB_TIMEOUT);
412 if (ret == LIBUSB_ERROR_TIMEOUT) {
413 log_warn(ctx, "Failed to receive data from "
414 "device: %s.", libusb_error_name(ret));
415 tries--;
416 continue;
417 } else if (ret != LIBUSB_SUCCESS) {
418 log_err(ctx, "Failed to receive data from "
419 "device: %s.", libusb_error_name(ret));
420 return JAYLINK_ERR;
423 log_dbg(ctx, "Received %u bytes from device.", transferred);
426 /* Ignore a possible timeout if at least one byte was received. */
427 if (transferred) {
428 *length = transferred;
429 return JAYLINK_OK;
432 log_err(ctx, "Receiving data from device timed out.");
434 return JAYLINK_ERR_TIMEOUT;
437 static int usb_send(struct jaylink_device_handle *devh, const uint8_t *buffer,
438 uint16_t length)
440 int ret;
441 struct jaylink_context *ctx;
442 unsigned int tries;
443 int transferred;
445 ctx = devh->dev->ctx;
446 tries = NUM_TIMEOUTS;
448 while (tries && length) {
449 /* Send data in chunks of CHUNK_SIZE bytes to the device. */
450 ret = libusb_bulk_transfer(devh->usb_devh, devh->endpoint_out,
451 (unsigned char *)buffer, MIN(CHUNK_SIZE, length),
452 &transferred, USB_TIMEOUT);
454 if (ret == LIBUSB_SUCCESS) {
455 tries = NUM_TIMEOUTS;
456 } else if (ret == LIBUSB_ERROR_TIMEOUT) {
457 log_warn(ctx, "Failed to send data to device: %s.",
458 libusb_error_name(ret));
459 tries--;
460 } else {
461 log_err(ctx, "Failed to send data to device: %s.",
462 libusb_error_name(ret));
463 return JAYLINK_ERR;
466 buffer += transferred;
467 length -= transferred;
469 log_dbg(ctx, "Sent %u bytes to device.", transferred);
472 if (!length)
473 return JAYLINK_OK;
475 log_err(ctx, "Sending data to device timed out.");
477 return JAYLINK_ERR_TIMEOUT;
481 * Write data to a device.
483 * Before this function is used transport_start_write() or
484 * transport_start_write_read() must be called to start a write operation. The
485 * total number of written bytes must not exceed the number of bytes of the
486 * write operation.
488 * @note A write operation will be performed and the data will be sent to the
489 * device when the number of written bytes reaches the number of bytes of
490 * the write operation. Before that the data will be written into a
491 * buffer.
493 * @param devh Device handle.
494 * @param buffer Buffer to write data from.
495 * @param length Number of bytes to write.
497 * @retval JAYLINK_OK Success.
498 * @retval JAYLINK_ERR_ARG Invalid arguments.
499 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
500 * @retval JAYLINK_ERR Other error conditions.
502 JAYLINK_PRIV int transport_write(struct jaylink_device_handle *devh,
503 const uint8_t *buffer, uint16_t length)
505 int ret;
506 struct jaylink_context *ctx;
507 uint8_t num_chunks;
508 uint16_t fill_bytes;
509 uint16_t tmp;
511 ctx = devh->dev->ctx;
513 if (length > devh->write_length) {
514 log_err(ctx, "Requested to write %u bytes but only %u bytes "
515 "are expected for the write operation.", length,
516 devh->write_length);
517 return JAYLINK_ERR_ARG;
521 * Store data in the buffer if the expected number of bytes for the
522 * write operation is not reached.
524 if (length < devh->write_length) {
525 if (devh->write_pos + length > BUFFER_SIZE) {
526 log_err(ctx, "Write request is too large for the "
527 "buffer.");
528 return JAYLINK_ERR_ARG;
531 memcpy(devh->buffer + devh->write_pos, buffer, length);
533 devh->write_length -= length;
534 devh->write_pos += length;
536 log_dbg(ctx, "Wrote %u bytes into buffer.", length);
537 return JAYLINK_OK;
541 * Expected number of bytes for this write operation is reached and
542 * therefore the write operation will be performed.
544 devh->write_length = 0;
546 /* Send data directly to the device if the buffer is empty. */
547 if (!devh->write_pos)
548 return usb_send(devh, buffer, length);
551 * Calculate the number of bytes to fill up the buffer to reach a
552 * multiple of CHUNK_SIZE bytes. This ensures that the data from the
553 * buffer will be sent to the device in chunks of CHUNK_SIZE bytes.
554 * Note that this is why the buffer size must be at least CHUNK_SIZE
555 * bytes.
557 num_chunks = devh->write_pos / CHUNK_SIZE;
559 if (devh->write_pos % CHUNK_SIZE)
560 num_chunks++;
562 fill_bytes = (num_chunks * CHUNK_SIZE) - devh->write_pos;
563 tmp = MIN(length, fill_bytes);
565 if (tmp) {
566 memcpy(devh->buffer + devh->write_pos, buffer, tmp);
568 length -= tmp;
569 buffer += tmp;
571 log_dbg(ctx, "Buffer filled up with %u bytes.", tmp);
574 /* Send buffered data to the device. */
575 ret = usb_send(devh, devh->buffer, devh->write_pos + tmp);
576 devh->write_pos = 0;
578 if (ret != JAYLINK_OK)
579 return ret;
581 if (!length)
582 return JAYLINK_OK;
584 /* Send remaining data to the device. */
585 return usb_send(devh, buffer, length);
589 * Read data from a device.
591 * Before this function is used transport_start_read() or
592 * transport_start_write_read() must be called to start a read operation. The
593 * total number of read bytes must not exceed the number of bytes of the read
594 * operation.
596 * @param devh Device handle.
597 * @param buffer Buffer to read data into on success. Its content is undefined
598 * on failure.
599 * @param length Number of bytes to read.
601 * @retval JAYLINK_OK Success.
602 * @retval JAYLINK_ERR_ARG Invalid arguments.
603 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
604 * @retval JAYLINK_ERR Other error conditions.
606 JAYLINK_PRIV int transport_read(struct jaylink_device_handle *devh,
607 uint8_t *buffer, uint16_t length)
609 int ret;
610 struct jaylink_context *ctx;
611 uint16_t bytes_received;
612 uint16_t tmp;
614 ctx = devh->dev->ctx;
616 if (length > devh->read_length) {
617 log_err(ctx, "Requested to read %u bytes but only %u bytes "
618 "are expected for the read operation.", length,
619 devh->read_length);
620 return JAYLINK_ERR_ARG;
623 if (length <= devh->bytes_available) {
624 memcpy(buffer, devh->buffer + devh->read_pos, length);
626 devh->read_length -= length;
627 devh->bytes_available -= length;
628 devh->read_pos += length;
630 log_dbg(ctx, "Read %u bytes from buffer.", length);
631 return JAYLINK_OK;
634 if (devh->bytes_available) {
635 memcpy(buffer, devh->buffer + devh->read_pos,
636 devh->bytes_available);
638 buffer += devh->bytes_available;
639 length -= devh->bytes_available;
640 devh->read_length -= devh->bytes_available;
642 log_dbg(ctx, "Read %u bytes from buffer to flush it.",
643 devh->bytes_available);
645 devh->bytes_available = 0;
646 devh->read_pos = 0;
649 while (length) {
651 * If less than CHUNK_SIZE bytes are requested from the device,
652 * store the received data in the internal buffer instead of
653 * directly into the user provided buffer. This is necessary to
654 * prevent a possible buffer overflow because the number of
655 * requested bytes from the device is always CHUNK_SIZE and
656 * therefore up to CHUNK_SIZE bytes may be received.
658 if (length < CHUNK_SIZE) {
659 ret = usb_recv(devh, devh->buffer, &bytes_received);
661 if (ret != JAYLINK_OK)
662 return ret;
664 tmp = MIN(bytes_received, length);
665 memcpy(buffer, devh->buffer, tmp);
668 * Setup the buffer for the remaining data if more data
669 * was received from the device than was requested.
671 if (bytes_received > length) {
672 devh->bytes_available = bytes_received - tmp;
673 devh->read_pos = tmp;
676 buffer += tmp;
677 length -= tmp;
678 devh->read_length -= tmp;
680 log_dbg(ctx, "Read %u bytes from buffer.", tmp);
681 } else {
682 ret = usb_recv(devh, buffer, &bytes_received);
684 if (ret != JAYLINK_OK)
685 return ret;
687 buffer += bytes_received;
688 length -= bytes_received;
689 devh->read_length -= bytes_received;
691 log_dbg(ctx, "Read %u bytes from device.",
692 bytes_received);
696 return JAYLINK_OK;