[5.0] api: Add asynchronous transfers 79/94379/18 accepted/tizen/unified/20180323.134337 submit/tizen/20180322.161345
authorPaweł Szewczyk <p.szewczyk@samsung.com>
Fri, 7 Oct 2016 15:22:20 +0000 (17:22 +0200)
committerPaweł Szewczyk <p.szewczyk@samsung.com>
Thu, 8 Mar 2018 16:21:49 +0000 (17:21 +0100)
Change-Id: I31b9773eee6cae0ec3cb935ef053d944cae0d619
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
doc/usb_host_doc.h
include/usb_host.h
include/usb_host_internal.h
src/usb_host.c

index e216bb2daf87d696f32b2d4916888f4533d1b7a8..6b83a8c746a2f21192f2414334c73f7800643b7d 100755 (executable)
  * Functions described here can be used to register callbacks to be called on events such as
  * device connection or disconnection.
  *
+ * @defgroup CAPI_USB_HOST_ASYNC_MODULE Asynchronous IO
+ * @brief This API is used to perform asynchronous operations
+ * @ingroup CAPI_USB_HOST_MODULE
+ * @section CAPI_USB_HOST_ASYNC_MODULE_OVERVIEW Overview
+ * Asynchronous transfers are performed by submitting previously prepared transfer handle (#usb_host_transfer_h).
+ * When the transfer is finished, the callback set by user is called.
+ * Transfer handle contains all transfer parameters and, when configured, can be submited multiple times.
+ * Most of parameters required for asynchronous transfers match those from synchronous transfer.
+ *
+ * Like in synchronous transfer, you must first obtain the endpoint handle. Then you can create a transfer handle with desired parameters.
+ * @code
+ * usb_host_transfer_h transfer;
+ * usb_host_endpoint_h ep;
+ *
+ * // Obtain the endpoint ep
+ * // ...
+ *
+ * // Create a transfer handle
+ * ret = usb_host_create_transfer(ep, transfer_callback, data, length, user_data, timeout, &transfer);
+ * if (ret < 0)
+ *     error();
+ *
+ * // Submit the transfer
+ * ret = usb_host_transfer_submit(transfer);
+ * if (ret < 0)
+ *     error();
+ *
+ * // ...
+ * // Destroy the transfer handle when no longer needed
+ * ret = usb_host_transfer_destroy(transfer);
+ * @endcode
+ *
+ * The transfer_callback() is a function which will be called when transfer is finished. It should match the usb_host_transfer_cb() type, e.g.:
+ * @code
+ * void transfer_callback(usb_host_transfer_h transfer, void user_data)
+ * {
+ *    int status;
+ *    int length;
+ *    char *data;
+ *
+ *    // Get the status value
+ *    usb_host_get_transfer_status(transfer, &status);
+ *
+ *    // Check the status value
+ *    if (status != USB_HOST_TRANSFER_COMPLETED) {
+ *        // Handle errors here
+ *    }
+ *
+ *    // Get the data buffer
+ *    usb_host_get_data(transfer, &data, &length);
+ *
+ *    // Handle received data
+ *    // ...
+ * }
+ * @endcode
+ *
+ *
+ * Note, that not always successfully submitted transfer finishes with success. The callback function is called
+ * with status code set to value from #usb_host_transfer_status_e enum. It informs what happened with the transfer.
+ *
+ * Also remember, that received data length can be different than length of buffer (i.e. requested length).
+ *
+ *
+ * You can change the transfer handle parameters by using usb_host_transfer_set_* functions and resubmit the transfer multiple times.
+ * @code
+ * void transfer_callback(usb_host_transfer_h transfer, void user_data)
+ * {
+ *    // Change parameters of the transfer if needed
+ *    // ...
+ *
+ *    usb_host_transfer_submit(transfer);
+ * }
+ * @endcode
+ *
+ * For passing additional data to callback function user_data pointer can be used. The user_data passed to callback
+ * is the same as was set for submitted transfer.
+ *
+ * After transfer is submitted, it can be canceled by calling usb_host_transfer_cancel(). This will cause the
+ * transfer callback function to be called with #USB_HOST_TRANSFER_CANCELLED status.
+ *
+ * @section CAPI_USB_HOST_ASYNC_MODULE_ISOCHRONOUS Isochronous transfers
+ * For creating isochronous transfers use usb_host_create_isochronous_transfer() function.
+ * It takes parameters similar to usb_host_create_transfer(), with addition of num_iso_packets.
+ * The data buffer is used to store all packets data and should be large enough to do so.
+ *
+ * @code
+ * ret = usb_host_create_isochronous_transfer(ep, transfer_callback, data, length, num_iso_packets, user_data, timeout, &transfer);
+ * @endcode
+ *
+ * Before submitting the transfer you must setup isochoronous packets lengths (and data, if making out transfer).
+ * @code
+ * for (i = 0; i < num_iso_packets; ++i) {
+ *    ret = usb_host_set_iso_packet_length(transfer, i, packet_lenght);
+ *    //...
+ *
+ *    ret = usb_host_get_iso_packet_data(transfer, i, &data, &len);
+ *    // fill received buffer with your data
+ *    // ...
+ * }
+ * @endcode
+ *
+ * Similarly, you can obtain received data in callback function by calling usb_host_transfer_get_iso_packet_data(). Note, that
+ * length of received data can be different than length of buffer space set for an isochronous packet.
+ *
+ * Each packet has its own status code. Check them by calling usb_host_transfer_get_iso_packet_status().
+ *
+ * @section CAPI_USB_HOST_ASYNC_MODULE_CONTROL Control transfers
+ * You can make asynchronous control transfers as well. They use the same data type as other asynchronous transfers (#usb_host_transfer_h)
+ * and can be handled in similar way.
+ *
+ * A control transfer need specific format of data in buffer, i.e. first 8 bytes of buffer need to contain a setup packet.
+ * You can find more informations about setup packets in usb protocol specification.
+ * This API provides functions helping with filling the setup packet.
+ *
+ * @code
+ * // Create a transfer handle
+ * ret = usb_host_create_control_transfer(dev, transfer_callback, data, length, user_data, timeout, &transfer);
+ * if (ret < 0)
+ *     error();
+ *
+ * // Set setup packet member values
+ *
+ * usb_host_control_transfer_set_request_type(transfer, bm_request_type);
+ * usb_host_control_transfer_set_request(transfer, b_request);
+ * usb_host_control_transfer_set_value(transfer, w_value);
+ * usb_host_control_transfer_set_index(transfer, w_index);
+ *
+ * // Submit the transfer
+ * ret = usb_host_transfer_submit(transfer);
+ * if (ret < 0)
+ *     error();
+ *
+ * // ...
+ * // Destroy the transfer handle when no longer needed
+ * ret = usb_host_transfer_destroy(transfer);
+ *
+ * @endcode
+ *
+ * When receiving data from control transfer, remember that first 8 bytes of buffer are filled with setup packet.
+ * To obtain pointer to actual data, use usb_host_control_transfer_get_data().
+ *
  */
 
 #endif /* __TIZEN_USB_HOST_DOC_H__ */
index 6c301ee1ac338352b83a61f5d68a0aa3a211ac77..d0d3f3dcb716478efa285e2b4d6372d1c7294e60 100755 (executable)
@@ -104,6 +104,22 @@ typedef enum {
        USB_HOST_HOTPLUG_EVENT_ANY,     /**< Any event */
 } usb_host_hotplug_event_e;
 
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Enumeration of transfer status codes.
+ * @since_tizen 5.0
+ */
+typedef enum {
+       USB_HOST_TRANSFER_COMPLETED, /**< Transfer completed without error*/
+       USB_HOST_TRANSFER_ERROR,     /**< Transfer failed */
+       USB_HOST_TRANSFER_TIMED_OUT, /**< Transfer timed out */
+       USB_HOST_TRANSFER_CANCELLED, /**< Transfer cancelled */
+       USB_HOST_TRANSFER_STALL,     /**< Halt condition detected */
+       USB_HOST_TRANSFER_NO_DEVICE, /**< Device was disconnected */
+       USB_HOST_TRANSFER_OVERFLOW,  /**< Device sent more data than requested */
+       USB_HOST_TRANSFER_UNKNOWN,   /**< Unknown status */
+} usb_host_transfer_status_e;
+
 /**
  * @ingroup CAPI_USB_HOST_MODULE
  * @brief Context handle to USB host.
@@ -180,6 +196,23 @@ typedef struct usb_host_hotplug_s *usb_host_hotplug_h;
  */
 typedef void (*usb_host_hotplug_cb)(usb_host_device_h dev, void *user_data);
 
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief USB asynchronous transfer handle.
+ * @details This type represents an asynchronous USB transfer.
+ * @since_tizen 5.0
+ */
+typedef struct usb_host_transfer_s *usb_host_transfer_h;
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Called when asynchronous transfers finishes.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer for which this callback was set
+ * @param[in] user_data User data pointer passed on callback registration
+ */
+typedef void (*usb_host_transferred_cb)(usb_host_transfer_h transfer, void *user_data);
+
 /* Library initialization and cleanup */
 
 /**
@@ -1045,6 +1078,422 @@ int usb_host_set_hotplug_cb(usb_host_context_h ctx, usb_host_hotplug_cb cb, usb_
  */
 int usb_host_unset_hotplug_cb(usb_host_hotplug_h handle);
 
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Prepares an asynchronous USB transfer.
+ * @details This function prepares transfer handle for asynchronous communication.
+ * Transfer handle can be used for multiple transfers after this initialization.
+ * @since_tizen 5.0
+ * @param[in] ep Endpoint handle
+ * @param[in] callback Callback to be called when transfer is finished
+ * @param[in] data Suitably-sized data buffer, similar to synchronized transfer
+ * @param[in] length For writes, the number of bytes from data to be sent; for
+ * reads, the maximum number of bytes to receive into the data buffer
+ * @param[in] user_data Pointer to data which will be passed to callback function later on
+ * @param[in] timeout Timeout (in milliseconds) that transfer should wait before giving up
+ * due to no response being received (for an unlimited timeout use value of 0)
+ * @param[out] transfer Transfer handle
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @retval #USB_HOST_ERROR_OUT_OF_MEMORY Out of memory
+ * @pre @a ep must be a valid endpoint received from usb_host_interface_get_endpoint().
+ * @post @a transfer should be destroyed by calling usb_host_transfer_destroy() when it's no longer needed.
+ */
+int usb_host_create_transfer(usb_host_endpoint_h ep, usb_host_transferred_cb callback,
+       unsigned char *data, int length, void *user_data, unsigned int timeout, usb_host_transfer_h *transfer);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Prepares an asynchronous USB isochronous transfer.
+ * @details This function prepares transfer handle for asynchronous communication.
+ * Usage is similar to usb_host_create_transfer(), except this function is intended for
+ * isochronous endpoints. Transfer handle can be used for multiple transfers after this initialization.
+ * Note however, that this function needs to allocate memory for @a num_iso_packets isochronous packets and
+ * it will be the limit for number of them in this transfer.
+ * @since_tizen 5.0
+ * @param[in] ep Endpoint handle
+ * @param[in] callback Callback to be called when transfer is finished
+ * @param[in] data Suitably-sized data buffer, similar to synchronized transfer
+ * @param[in] length For writes, the number of bytes from data to be sent; for
+ * reads, the maximum number of bytes to receive into the data buffer
+ * @param[in] num_iso_packets Number of isochronous packets
+ * @param[in] user_data Pointer to data which will be passed to callback function later on
+ * @param[in] timeout Timeout (in milliseconds) that transfer should wait before giving up
+ * due to no response being received (for an unlimited timeout use value of 0)
+ * @param[out] transfer Transfer handle
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @retval #USB_HOST_ERROR_OUT_OF_MEMORY Out of memory
+ * @pre @a ep must be a valid endpoint received from usb_host_interface_get_endpoint().
+ * @post @a transfer should be destroyed by calling usb_host_transfer_destroy() when it's no longer needed.
+ */
+int usb_host_create_isochronous_transfer(usb_host_endpoint_h ep, usb_host_transferred_cb callback,
+       unsigned char *data, int length, unsigned int num_iso_packets, void *user_data, unsigned int timeout, usb_host_transfer_h *transfer);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Prepares an asynchronous USB control transfer.
+ * @details This function prepares control transfer handle. Transfer handle can
+ * be used for multiple transfers after this initialization. Note, that first
+ * 8 bytes of data buffer are interpreted as control setup packet. You may use
+ * usb_host_control_transfer_set_* functions to set the setup packet fields.
+ * @since_tizen 5.0
+ * @param[in] dev Device handle
+ * @param[in] callback Callback to be called when transfer is finished
+ * @param[in] data Suitably-sized data buffer
+ * @param[in] length For writes, the number of bytes from data to be sent, for
+ * reads, the maximum number of bytes to receive into the data buffer
+ * @param[in] user_data Pointer to data which will be passed to callback function later on
+ * @param[in] timeout Timeout (in milliseconds) that transfer should wait before giving up
+ * due to no response being received (for an unlimited timeout use value of 0)
+ * @param[out] transfer Transfer handle
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @retval #USB_HOST_ERROR_OUT_OF_MEMORY Out of memory
+ * @pre @a dev must be an opened device handle
+ * @post @a transfer should be destroyed by calling usb_host_transfer_destroy() when it's no longer needed.
+ */
+int usb_host_create_control_transfer(usb_host_device_h dev, usb_host_transferred_cb callback,
+       unsigned char *data, int length, void *user_data, unsigned int timeout, usb_host_transfer_h *transfer);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets an endpoint for asynchronous transfer.
+ * @details This function changes the endpoint on which given transfer is performed. Next submissions will be
+ * performed on this endpoint.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] ep An endpoint handle
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be created by usb_host_create_transfer() or usb_host_create_isochronous_transfer().
+ */
+int usb_host_transfer_set_ep(usb_host_transfer_h transfer, usb_host_endpoint_h ep);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets a callback for asynchronous transfer.
+ * @details This function changes the callback to be called on transfer completion.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] callback A callback function
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be created by usb_host_create_transfer() or usb_host_create_isochronous_transfer().
+ */
+int usb_host_transfer_set_callback(usb_host_transfer_h transfer, usb_host_transferred_cb callback);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets data buffer for asynchronous transfer.
+ * @details This function changes the data buffer used for this transfer.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] data A data buffer
+ * @param[in] length Length of data buffer
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be created by usb_host_create_transfer() or usb_host_create_isochronous_transfer().
+ */
+int usb_host_transfer_set_data(usb_host_transfer_h transfer, unsigned char *data, int length);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets timeout for asynchronous transfer.
+ * @details This function changes the timeout after which transfer will be stopped due to
+ * no response being received.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] timeout A timeout in milliseconds
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be created by usb_host_create_transfer() or usb_host_create_isochronous_transfer().
+ */
+int usb_host_transfer_set_timeout(usb_host_transfer_h transfer, unsigned int timeout);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets number of isochrnous packet for isochronous transfer.
+ * @details This function changes the number of isochronous packets in transfer.
+ * This parameter affects only isochronous transfers (i.e. transfers on isochronous endpoints).
+ * Use usb_host_endpoint_get_transfer_type() for checking types of your endpoints.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] num_iso_packets Number of isochronous packets in this transfer
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @retval #USB_HOST_ERROR_OUT_OF_MEMORY Out of memory (too many packets)
+ * @pre @a transfer should be created by usb_host_create_transfer() or usb_host_create_isochronous_transfer().
+ */
+int usb_host_transfer_set_num_iso_packets(usb_host_transfer_h transfer, unsigned int num_iso_packets);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets request type for control transfer setup packet.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] bm_request_type bmRequestType type field for the setup packet
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be created by usb_host_create_control_transfer().
+ */
+int usb_host_control_transfer_set_request_type(usb_host_transfer_h transfer, uint8_t bm_request_type);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets request field for control transfer setup packet.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] b_request bRequest field for the setup packet
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be created by usb_host_create_control_transfer().
+ */
+int usb_host_control_transfer_set_request(usb_host_transfer_h transfer, uint8_t b_request);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets w_value field for control transfer setup packet.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] w_value wValue field for the setup packet
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be created by usb_host_create_control_transfer().
+ */
+int usb_host_control_transfer_set_value(usb_host_transfer_h transfer, uint16_t w_value);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets w_index field for control transfer setup packet.
+ * @since_tizen 5.0
+ * @param[in] transfer A transfer handle
+ * @param[in] w_index wIndex field for the setup packet
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be created by usb_host_create_control_transfer().
+ */
+int usb_host_control_transfer_set_index(usb_host_transfer_h transfer, uint16_t w_index);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Gets the transfer status.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle
+ * @param[out] status Status of this transfer
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ */
+int usb_host_transfer_get_status(usb_host_transfer_h transfer, int *status);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Gets the transfer data.
+ * @since_tizen 5.0
+ * @remarks @a data is part of the transfer object and should not be released
+ * separately. It should not be accessed after @a transfer is destroyed.
+ * @param[in] transfer Transfer handle
+ * @param[out] data Data buffer of this transfer
+ * @param[out] actual_length Actual length of transferred data
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ */
+int usb_host_transfer_get_data(usb_host_transfer_h transfer, unsigned char **data, unsigned int *actual_length);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Gets the *control* transfer data.
+ * @since_tizen 5.0
+ * @remarks @a data is part of the transfer object and should not be released
+ * separately. It should not be accessed after @a transfer is destroyed.
+ * @param[in] transfer Control transfer handle
+ * @param[out] data Data buffer of this transfer
+ * @param[out] actual_length Actual length of transferred data
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ */
+int usb_host_control_transfer_get_data(usb_host_transfer_h transfer, unsigned char **data, unsigned int *actual_length);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Gets length of data buffer.
+ * @details This functions gets length that was set for data buffer, not the actual transferred data length.
+ * For length of transferred data see usb_host_transfer_get_data().
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle
+ * @param[out] length Length of data buffer for this transfer
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ */
+int usb_host_transfer_get_length(usb_host_transfer_h transfer, unsigned int *length);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Gets number of isochronous packets for this transfer.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle
+ * @param[out] num_iso_packets Number of isochronous packets
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ */
+int usb_host_transfer_get_num_iso_packets(usb_host_transfer_h transfer, unsigned int *num_iso_packets);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Sets an isochronous packet length.
+ * @details This function sets length of individual packet.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle
+ * @param[in] packet_number Number of isochronous packet
+ * @param[in] length Length of the packet handle
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @retval #USB_HOST_ERROR_NOT_FOUND Packet of given number not found
+ * @retval #USB_HOST_ERROR_OVERFLOW Not enough space for this packet in data buffer
+ */
+int usb_host_transfer_set_iso_packet_length(usb_host_transfer_h transfer, unsigned int packet_number, int length);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Gets an isochronous packet status.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle
+ * @param[in] packet_number Number of isochronous packet
+ * @param[out] status Status of selected packet
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @retval #USB_HOST_ERROR_NOT_FOUND Packet of given number not found
+ */
+int usb_host_transfer_get_iso_packet_status(usb_host_transfer_h transfer, unsigned int packet_number, int *status);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Gets data buffer of isochronous packet.
+ * @since_tizen 5.0
+ * @remarks @a data is part of the transfer object and should not be released
+ * separately. It should not be accessed after @a transfer is destroyed.
+ * @param[in] transfer Transfer handle
+ * @param[in] packet_number Number of isochronous packet
+ * @param[out] data Data buffer for this packet
+ * @param[out] actual_length Length of transferred data
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @retval #USB_HOST_ERROR_NOT_FOUND Packet of given number not found
+ */
+int usb_host_transfer_get_iso_packet_data(usb_host_transfer_h transfer, unsigned int packet_number, unsigned char **data, int *actual_length);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Gets isochronous packet data buffer length.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle
+ * @param[in] packet_number Number of isochronous packet
+ * @param[out] length Length of data buffer
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @retval #USB_HOST_ERROR_NOT_FOUND Packet of given number not found
+ */
+int usb_host_transfer_get_iso_packet_length(usb_host_transfer_h transfer, unsigned int packet_number, int *length);
+
+/**
+ * @ingroup CAPI_USB_HOST_ENDPOINT_MODULE
+ * @brief Gets type of a transfer.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle
+ * @param[out] transfer_type Transfer type (a value from enum #usb_host_transfer_type_e)
+ * @return 0 on success, otherwise a negative error value
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ */
+int usb_host_transfer_get_type(usb_host_transfer_h transfer, usb_host_transfer_type_e *transfer_type);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Destroys an asynchronous transfer structure.
+ * @details When no longer needed, transfer should be destroyed by this function.
+ * It frees memory allocated for the transfer. You cannot destroy unfinished transfer,
+ * wait for its completion or cancel it.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle to be destroyed
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ */
+int usb_host_transfer_destroy(usb_host_transfer_h transfer);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Submits an asynchronous USB transfer.
+ * @details Calling this will start actual transfer.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle to be submitted
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ * @pre @a transfer should be initialized by one of initialization functions:
+ * usb_host_create_transfer(), usb_host_create_isochronous_transfer() or usb_host_create_control_transfer().
+ */
+int usb_host_transfer_submit(usb_host_transfer_h transfer);
+
+/**
+ * @ingroup CAPI_USB_HOST_ASYNC_MODULE
+ * @brief Cancels an asynchronous USB transfer.
+ * @details After calling this function the transfer will be cancelled, if only
+ * it was not finished already. The transfer callback will be called with #USB_HOST_TRANSFER_CANCELLED status.
+ * @since_tizen 5.0
+ * @param[in] transfer Transfer handle to be cancelled
+ * @return 0 on success, negative error code on error
+ * @retval #USB_HOST_ERROR_NONE Successful
+ * @retval #USB_HOST_ERROR_NOT_SUPPORTED Not supported
+ * @retval #USB_HOST_ERROR_INVALID_PARAMETER Invalid parameter was passed
+ */
+int usb_host_transfer_cancel(usb_host_transfer_h transfer);
+
 #ifdef __cplusplus
 }
 #endif
index d7d76c1f38d9d1a7395f7ddc4d8f971295132c6a..f4f2736da64e8a0e89dc3d2d23978c0c181b9e1c 100644 (file)
@@ -44,6 +44,8 @@ struct usb_host_device_s {
 
 struct usb_host_transfer_s {
        struct libusb_transfer *lusb_transfer;
+       int allocated_iso_packets;
+       int iso_buffer_usage;
 };
 
 /**
index f3afb204e0efbe8cc12ca1355e625a70a30b00b0..028f0c0cbb771666fe07d06ce058b545d00d4ad2 100644 (file)
@@ -101,6 +101,28 @@ static int translate_error(int error_code)
        }
 }
 
+static int translate_status(int status_code)
+{
+       switch (status_code) {
+       case LIBUSB_TRANSFER_COMPLETED:
+               return USB_HOST_TRANSFER_COMPLETED;
+       case LIBUSB_TRANSFER_ERROR:
+               return USB_HOST_TRANSFER_ERROR;
+       case LIBUSB_TRANSFER_TIMED_OUT:
+               return USB_HOST_TRANSFER_TIMED_OUT;
+       case LIBUSB_TRANSFER_CANCELLED:
+               return USB_HOST_TRANSFER_CANCELLED;
+       case LIBUSB_TRANSFER_STALL:
+               return USB_HOST_TRANSFER_STALL;
+       case LIBUSB_TRANSFER_NO_DEVICE:
+               return USB_HOST_TRANSFER_NO_DEVICE;
+       case LIBUSB_TRANSFER_OVERFLOW:
+               return USB_HOST_TRANSFER_OVERFLOW;
+       default:
+               return USB_HOST_TRANSFER_UNKNOWN;
+       }
+}
+
 static void free_device(struct uref *uref)
 {
        struct usb_host_device_s *dev = to_usb_host_device(uref);
@@ -1835,3 +1857,584 @@ int usb_host_unset_hotplug_cb(usb_host_hotplug_h handle)
 
        return USB_HOST_ERROR_NONE;
 }
+
+struct async_transfer_data {
+       usb_host_transferred_cb cb;
+       usb_host_transfer_h transfer;
+       void *user_data;
+};
+
+static void generic_transfer_cb(struct libusb_transfer *lusb_transfer)
+{
+       struct async_transfer_data *data;
+
+       data = lusb_transfer->user_data;
+       data->cb(data->transfer, data->user_data);
+}
+
+int usb_host_create_isochronous_transfer(usb_host_endpoint_h ep, usb_host_transferred_cb callback,
+       unsigned char *data, int length, unsigned int num_iso_packets, void *user_data, unsigned int timeout, usb_host_transfer_h *transfer)
+{
+       usb_host_transfer_h rtransfer = NULL;
+       struct async_transfer_data *transfer_data = NULL;
+       int type;
+       int ret = USB_HOST_ERROR_UNKNOWN;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!ep || !data || !transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       rtransfer = calloc(1, sizeof(*rtransfer));
+       if (!rtransfer) {
+               _E("Failed to alloc transfer structure");
+               return USB_HOST_ERROR_OUT_OF_MEMORY;
+       }
+
+       transfer_data = calloc(1, sizeof(*transfer_data));
+       if (!transfer_data) {
+               _E("Failed to alloc transfer data structure");
+               ret = USB_HOST_ERROR_OUT_OF_MEMORY;
+               goto free_rtransfer;
+       }
+
+       transfer_data->cb = callback;
+       transfer_data->transfer = rtransfer;
+       transfer_data->user_data = user_data;
+
+       rtransfer->lusb_transfer = libusb_alloc_transfer(num_iso_packets);
+       rtransfer->allocated_iso_packets = num_iso_packets;
+       rtransfer->iso_buffer_usage = 0;
+
+       type = usb_host_get_ep_type(ep);
+       switch (type) {
+       case USB_ENDPOINT_XFER_BULK:
+               libusb_fill_bulk_transfer(rtransfer->lusb_transfer, ep->dev->lusb_dev_handle,
+                               ep->desc.bEndpointAddress, data, length, generic_transfer_cb, transfer_data, timeout);
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               libusb_fill_interrupt_transfer(rtransfer->lusb_transfer, ep->dev->lusb_dev_handle,
+                               ep->desc.bEndpointAddress, data, length, generic_transfer_cb, transfer_data, timeout);
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               libusb_fill_iso_transfer(rtransfer->lusb_transfer, ep->dev->lusb_dev_handle, ep->desc.bEndpointAddress, data,
+                               length, num_iso_packets, generic_transfer_cb, transfer_data, timeout);
+               break;
+       default:
+               ret = USB_HOST_ERROR_NOT_SUPPORTED;
+               goto free_transfer_data;
+       }
+
+       *transfer = rtransfer;
+
+       return USB_HOST_ERROR_NONE;
+
+free_transfer_data:
+       free(transfer_data);
+free_rtransfer:
+       libusb_free_transfer(rtransfer->lusb_transfer);
+       free(rtransfer);
+
+       return ret;
+}
+
+int usb_host_create_transfer(usb_host_endpoint_h ep, usb_host_transferred_cb callback,
+               unsigned char *data, int length, void *user_data, unsigned int timeout, usb_host_transfer_h *transfer)
+{
+       return usb_host_create_isochronous_transfer(ep, callback, data, length, 0, user_data, timeout, transfer);
+}
+
+int usb_host_create_control_transfer(usb_host_device_h dev, usb_host_transferred_cb callback,
+       unsigned char *data, int length, void *user_data, unsigned int timeout, usb_host_transfer_h *transfer)
+{
+       usb_host_transfer_h rtransfer = NULL;
+       struct async_transfer_data *transfer_data = NULL;
+       int ret = USB_HOST_ERROR_UNKNOWN;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!dev || !data || !transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       rtransfer = calloc(1, sizeof(*rtransfer));
+       if (!rtransfer) {
+               _E("Failed to alloc transfer structure");
+               return USB_HOST_ERROR_OUT_OF_MEMORY;
+       }
+
+       transfer_data = calloc(1, sizeof(*transfer_data));
+       if (!transfer_data) {
+               _E("Failed to alloc transfer data structure");
+               ret = USB_HOST_ERROR_OUT_OF_MEMORY;
+               goto free_rtransfer;
+       }
+
+       transfer_data->cb = callback;
+       transfer_data->transfer = rtransfer;
+       transfer_data->user_data = user_data;
+
+       rtransfer->lusb_transfer = libusb_alloc_transfer(0);
+       if (!rtransfer->lusb_transfer) {
+               _E("Failed to alloc libusb transfer");
+               ret = USB_HOST_ERROR_OUT_OF_MEMORY;
+               goto out;
+       }
+
+       rtransfer->allocated_iso_packets = 0;
+       rtransfer->iso_buffer_usage = 0;
+
+       libusb_fill_control_setup(data, 0, 0, 0, 0, length - LIBUSB_CONTROL_SETUP_SIZE);
+       libusb_fill_control_transfer(rtransfer->lusb_transfer, dev->lusb_dev_handle, data, generic_transfer_cb, transfer_data, timeout);
+
+       *transfer = rtransfer;
+       return USB_HOST_ERROR_NONE;
+
+out:
+       free(transfer_data);
+       libusb_free_transfer(rtransfer->lusb_transfer);
+free_rtransfer:
+       free(rtransfer);
+       return ret;
+}
+
+int usb_host_transfer_get_status(usb_host_transfer_h transfer, int *status)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !status || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       *status = translate_status(transfer->lusb_transfer->status);
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_get_data(usb_host_transfer_h transfer, unsigned char **data, unsigned int *actual_length)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !data || !actual_length || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       *data = transfer->lusb_transfer->buffer;
+       *actual_length = transfer->lusb_transfer->actual_length;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_control_transfer_get_data(usb_host_transfer_h transfer, unsigned char **data, unsigned int *actual_length)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !data || !actual_length || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       *data = libusb_control_transfer_get_data(transfer->lusb_transfer);
+       *actual_length = transfer->lusb_transfer->actual_length;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_get_length(usb_host_transfer_h transfer, unsigned int *length)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !length || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       *length = transfer->lusb_transfer->length;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_get_num_iso_packets(usb_host_transfer_h transfer, unsigned int *num_iso_packets)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !num_iso_packets || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       *num_iso_packets = transfer->lusb_transfer->num_iso_packets;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_set_ep(usb_host_transfer_h transfer, usb_host_endpoint_h ep)
+{
+       int type;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer || !ep || !ep->dev) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       transfer->lusb_transfer->endpoint = ep->desc.bEndpointAddress;
+       transfer->lusb_transfer->dev_handle = ep->dev->lusb_dev_handle;
+
+       type = usb_host_get_ep_type(ep);
+       switch (type) {
+       case USB_ENDPOINT_XFER_BULK:
+               transfer->lusb_transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               transfer->lusb_transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               transfer->lusb_transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
+               break;
+       default:
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+       }
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_set_callback(usb_host_transfer_h transfer, usb_host_transferred_cb callback)
+{
+       struct async_transfer_data *transfer_data = NULL;
+
+       if (!transfer || !transfer->lusb_transfer || !callback) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       transfer_data = transfer->lusb_transfer->user_data;
+       transfer_data->cb = callback;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_set_data(usb_host_transfer_h transfer, unsigned char *data, int length)
+{
+       struct libusb_control_setup *setup;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       transfer->lusb_transfer->buffer = data;
+       transfer->lusb_transfer->length = length;
+
+       if (transfer->lusb_transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL) {
+               setup =  (struct libusb_control_setup *)(transfer->lusb_transfer->buffer);
+               setup->wLength = length;
+       }
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_set_timeout(usb_host_transfer_h transfer, unsigned int timeout)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       transfer->lusb_transfer->timeout = timeout;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_set_num_iso_packets(usb_host_transfer_h transfer, unsigned int num_iso_packets)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       if (num_iso_packets > transfer->allocated_iso_packets) {
+               _E("Too many packets");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       transfer->lusb_transfer->num_iso_packets = num_iso_packets;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_control_transfer_set_request_type(usb_host_transfer_h transfer, uint8_t bm_request_type)
+{
+       struct libusb_control_setup *setup;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer || !transfer->lusb_transfer->buffer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       setup =  (struct libusb_control_setup *)(transfer->lusb_transfer->buffer);
+       setup->bmRequestType = bm_request_type;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_control_transfer_set_request(usb_host_transfer_h transfer, uint8_t b_request)
+{
+       struct libusb_control_setup *setup;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer || !transfer->lusb_transfer->buffer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       setup =  (struct libusb_control_setup *)(transfer->lusb_transfer->buffer);
+       setup->bRequest = b_request;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_control_transfer_set_value(usb_host_transfer_h transfer, uint16_t w_value)
+{
+       struct libusb_control_setup *setup;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer || !transfer->lusb_transfer->buffer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       setup =  (struct libusb_control_setup *)(transfer->lusb_transfer->buffer);
+       setup->wValue = w_value;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_control_transfer_set_index(usb_host_transfer_h transfer, uint16_t w_index)
+{
+       struct libusb_control_setup *setup;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer || !transfer->lusb_transfer->buffer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       setup = (struct libusb_control_setup *)(transfer->lusb_transfer->buffer);
+       setup->wIndex = w_index;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_set_iso_packet_length(usb_host_transfer_h transfer, unsigned int packet_number, int length)
+{
+       int buffer_usage;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       if (packet_number >= transfer->lusb_transfer->num_iso_packets) {
+               _E("No such packet\n");
+               return USB_HOST_ERROR_NOT_FOUND;
+       }
+
+       buffer_usage = transfer->iso_buffer_usage + length
+               - transfer->lusb_transfer->iso_packet_desc[packet_number].length;
+       if (buffer_usage > transfer->lusb_transfer->length) {
+               _E("Buffer too short");
+               return USB_HOST_ERROR_OVERFLOW;
+       }
+
+       transfer->iso_buffer_usage = buffer_usage;
+       transfer->lusb_transfer->iso_packet_desc[packet_number].length = length;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_get_iso_packet_status(usb_host_transfer_h transfer, unsigned int packet_number, int *status)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !status || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       if (packet_number >= transfer->lusb_transfer->num_iso_packets) {
+               _E("No such packet\n");
+               return USB_HOST_ERROR_NOT_FOUND;
+       }
+
+       *status = transfer->lusb_transfer->iso_packet_desc[packet_number].status;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_get_iso_packet_data(usb_host_transfer_h transfer, unsigned int packet_number, unsigned char **data, int *actual_length)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !data || !actual_length || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       if (packet_number >= transfer->lusb_transfer->num_iso_packets) {
+               _E("No such packet\n");
+               return USB_HOST_ERROR_NOT_FOUND;
+       }
+
+       *data = libusb_get_iso_packet_buffer(transfer->lusb_transfer, packet_number);
+       if (!(*data)) {
+               _E("No such packet\n");
+               return USB_HOST_ERROR_NOT_FOUND;
+       }
+
+       *actual_length = transfer->lusb_transfer->iso_packet_desc[packet_number].actual_length;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_get_iso_packet_length(usb_host_transfer_h transfer, unsigned int packet_number, int *length)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !length || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       if (packet_number >= transfer->lusb_transfer->num_iso_packets) {
+               _E("No such packet\n");
+               return USB_HOST_ERROR_NOT_FOUND;
+       }
+
+       *length = transfer->lusb_transfer->iso_packet_desc[packet_number].length;
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_get_type(usb_host_transfer_h transfer, usb_host_transfer_type_e *transfer_type)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer_type || !transfer->lusb_transfer) {
+               _E("Invalid parameter was passed");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       switch (transfer->lusb_transfer->type) {
+       case LIBUSB_TRANSFER_TYPE_CONTROL:
+               *transfer_type = USB_HOST_TRANSFER_TYPE_CONTROL;
+               break;
+       case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+               *transfer_type = USB_HOST_TRANSFER_TYPE_ISOCHRONOUS;
+               break;
+       case LIBUSB_TRANSFER_TYPE_BULK:
+               *transfer_type = USB_HOST_TRANSFER_TYPE_BULK;
+               break;
+       case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+               *transfer_type = USB_HOST_TRANSFER_TYPE_INTERRUPT;
+               break;
+       default:
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+       }
+
+       return USB_HOST_ERROR_NONE;
+}
+
+int usb_host_transfer_submit(usb_host_transfer_h transfer)
+{
+       int ret;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       ret = libusb_submit_transfer(transfer->lusb_transfer);
+       if (ret < 0)
+               _E("Failed to submit transfer: %d", ret);
+
+       return translate_error(ret);
+}
+
+int usb_host_transfer_cancel(usb_host_transfer_h transfer)
+{
+       int ret;
+
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       ret = libusb_cancel_transfer(transfer->lusb_transfer);
+       if (ret < 0)
+               _E("Failed to cancel transfer: %d", ret);
+
+       return translate_error(ret);
+}
+
+int usb_host_transfer_destroy(usb_host_transfer_h transfer)
+{
+       if (!usb_host_feature_enabled())
+               return USB_HOST_ERROR_NOT_SUPPORTED;
+
+       if (!transfer || !transfer->lusb_transfer) {
+               _E("Invalid parameter");
+               return USB_HOST_ERROR_INVALID_PARAMETER;
+       }
+
+       free(transfer->lusb_transfer->user_data);
+       libusb_free_transfer(transfer->lusb_transfer);
+       free(transfer);
+
+       return USB_HOST_ERROR_NONE;
+}