From: Stanislaw Wadas Date: Wed, 27 May 2015 13:17:24 +0000 (+0200) Subject: add simple USB host CAPI X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ef048d34ebbf55d5a5ed81c9eeb72e698aa99fb9;p=platform%2Fcore%2Fapi%2Fusb-host.git add simple USB host CAPI Change-Id: I864a9625c1f45d9331e751f8c15a0a79bcc573af Signed-off-by: Stanislaw Wadas --- diff --git a/include/libhusb.h b/include/libhusb.h new file mode 100644 index 0000000..559e4ad --- /dev/null +++ b/include/libhusb.h @@ -0,0 +1,187 @@ +/* + * libhusb.h + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBHUSB_H +#define LIBHUSB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct libhusb_context; + +typedef struct libhusb_context libhusb_context; + +struct libhusb_device; + +typedef struct libhusb_device libhusb_device; + +struct libhusb_device_handle; + +typedef struct libhusb_device_handle libhusb_device_handle; + +struct libhusb_cfg_descriptor; + +typedef struct libhusb_cfg_descriptor libhusb_cfg_descriptor; + +enum libhusb_supported_speed { + LIBHUSB_SPEED_UNKNOWN = 0, + + /** Low speed (1.5MBit/s). */ + LIBHUSB_SPEED_LOW = 1, + + /** Full speed (12MBit/s). */ + LIBHUSB_SPEED_FULL = 2, + + /** High speed (480MBit/s). */ + LIBHUSB_SPEED_HIGH = 3, + + /** TSuper speed (5000MBit/s). */ + LIBHUSB_SPEED_SUPER = 4, +}; + +struct libhusb_device_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +}; + +struct libhusb_cfg_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t MaxPower; + const struct libhusb_interface *interface; + const unsigned char *extra; + int extra_length; +}; + +struct libhusb_interface { + const struct libhusb_interface_descriptor *altsetting; + int num_altsetting; +}; + +struct libhusb_interface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; + const struct libhusb_endpoint_descriptor *endpoint; + const unsigned char *extra; + int extra_length; +}; + +struct libhusb_endpoint_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; + uint8_t bRefresh; + uint8_t bSynchAddress; + const unsigned char *extra; + int extra_length; +}; + +int libhusb_init(libhusb_context **ctx); + +void libhusb_exit(libhusb_context *ctx); + +void libhusb_close(libhusb_device_handle *handle); + +ssize_t libhusb_get_devices(libhusb_context *ctx, libhusb_device ***devs); + +void libhusb_free_devices(libhusb_device **list, int unref_devices); + +int libhusb_get_max_packet_size(libhusb_device *dev, unsigned char endpoint, int iso); + +uint8_t libhusb_get_bus_number(libhusb_device *dev); + +uint8_t libhusb_get_address(libhusb_device *dev); + +int libhusb_get_port_numbers(libhusb_device *dev, uint8_t *port_numbers, int port_numbers_len); + +int libhusb_get_device_descriptor(libhusb_device *dev, struct libhusb_device_descriptor *desc); + +int libhusb_get_active_config(libhusb_device_handle *handle, int *config); + +int libhusb_set_config(libhusb_device_handle *handle, int configuration); + +int libhusb_claim_interface(libhusb_device_handle *handle, int interface_number, int force); + +int libhusb_release_interface(libhusb_device_handle *handle, int interface_number); + +int libhusb_clear_halt(libhusb_device_handle *handle, unsigned char endpoint); + +int libhusb_reset_device(libhusb_device_handle *handle); + +int libhusb_kernel_driver_active(libhusb_device_handle *handle, int interface_number); + +int libhusb_detach_kernel_driver(libhusb_device_handle *handle, int interface_number); + +int libhusb_attach_kernel_driver(libhusb_device_handle *handle, int interface_number); + +int libhusb_get_config_descriptor(libhusb_device *dev, uint8_t config_index, + struct libhusb_cfg_descriptor **config); + +void libhusb_free_config_descriptor(struct libhusb_cfg_descriptor *config); + +int libhusb_get_string_descriptor_ascii(libhusb_device_handle *handle, + uint8_t desc_index, unsigned char *data, int length); + +/* sync IO */ + +int libhusb_control_transfer(libhusb_device_handle *handle, + uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + unsigned char *data, uint16_t wLength, unsigned int timeout); + +int libhusb_bulk_transfer(libhusb_device_handle *handle, + unsigned char endpoint, unsigned char *data, int length, + int *actual_length, unsigned int timeout); + +int libhusb_interrupt_transfer(libhusb_device_handle *handle, + unsigned char endpoint, unsigned char *data, int length, + int *actual_length, unsigned int timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBHUSB_H */ diff --git a/src/libhusb.c b/src/libhusb.c new file mode 100644 index 0000000..eb80b9f --- /dev/null +++ b/src/libhusb.c @@ -0,0 +1,369 @@ +/* + * libhusb.c + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct libhusb_context { + libusb_context *lusb_ctx; +}; + +struct libhusb_device { + libusb_device *lusb_dev; +}; + +struct libhusb_device_handle { + struct libusb_device_handle *lusb_dev_handle; +}; + +/* TODO add error translation */ +/* TODO test sync transfer */ + +int libhusb_init(libhusb_context **ctx) +{ + int ret; + int count = 10; + struct libhusb_context *_ctx; + + assert(ctx); + + _ctx = malloc(sizeof(*_ctx)); + + do { + ret = libusb_init(&(_ctx->lusb_ctx)); + count--; + } while (ret == -99 && count > 0); + + *ctx = _ctx; + + return ret; +} + +void libhusb_exit(libhusb_context *context) +{ + assert(context); + + libusb_exit(context->lusb_ctx); + + free(context); +} + +void libhusb_close(libhusb_device_handle *handle) +{ + assert(handle); + + libusb_close(handle->lusb_dev_handle); + + free(handle); +} + +uint8_t libhusb_get_bus_number(libhusb_device *dev) +{ + assert(dev); + + return libusb_get_bus_number(dev->lusb_dev); +} + +uint8_t libhusb_get_address(libhusb_device *dev) +{ + uint8_t device_address; + + assert(dev); + + device_address = libusb_get_device_address(dev->lusb_dev); + + return device_address; +} + +int libhusb_get_port_numbers(libhusb_device *dev, uint8_t* port_numbers, int port_numbers_len) +{ + int port_num = 0; + + assert(dev); + + /* TODO implement */ + + return port_num; +} + +ssize_t libhusb_get_devices(libhusb_context *context, libhusb_device ***devs) +{ + ssize_t len; + int i = 0; + libusb_device **lusb_list = NULL; + struct libhusb_device *rdevice; + struct libhusb_device **list; + + assert(context); + assert(devs); + + len = libusb_get_device_list(context->lusb_ctx, &lusb_list); + if (len < 0) + return -1; + + list = calloc(len + 1, sizeof(*list)); + if (!list) { + libusb_free_device_list(lusb_list, 1); + return -99; /* TODO replace with propper error*/ + } + + list[len] = NULL; + for (i = 0; i < len; i++) { + rdevice = malloc(sizeof(*rdevice)); + if (!rdevice) { + libusb_free_device_list(lusb_list, 1); + return -99; /* TODO replace with propper error*/ + } + list[i] = rdevice; + list[i]->lusb_dev = lusb_list[i]; + } + + *devs = list; + + libusb_free_device_list(lusb_list, 0); + + return len; +} + +void libhusb_free_devices(libhusb_device **list, int unref_devices) +{ + int i = 0; + + if (!list) + return; + + for (i = 0; list[i] != NULL; i++) { + if (unref_devices) { + struct libusb_device *devp = list[i]->lusb_dev; + assert(devp); + libusb_unref_device(devp); + } + free(list[i]); + } + + free(list); +} + +int libhusb_get_max_packet_size(libhusb_device *dev, unsigned char endpoint, int iso) +{ + int ret; + + assert(dev); + + if (iso == 1) { + ret = libusb_get_max_iso_packet_size(dev->lusb_dev, endpoint); + } + else { + ret = libusb_get_max_packet_size(dev->lusb_dev, endpoint); + } + + if (ret < 0) + ret = usb_device_get_error_num(ret); + + return ret; +} + +int libhusb_get_active_config(libhusb_device_handle *handle, int *config) +{ + int ret; + + assert(handle); + + ret = libusb_get_configuration(handle->lusb_dev_handle, config); + + return ret; +} + +int libhusb_set_config(libhusb_device_handle *handle, int configuration) +{ + int ret; + + assert(handle); + + ret = libusb_set_configuration(handle->lusb_dev_handle, configuration); + + return ret; +} + +int libhusb_claim_interface(libhusb_device_handle *handle, int interface_number, int force) +{ + int ret; + + assert(handle); + + if (force) { + ret = libusb_set_auto_detach_kernel_driver(handle->lusb_dev_handle, 1); + if (ret == LIBUSB_ERROR_NOT_SUPPORTED) + return -1; + } + + ret = libusb_claim_interface(handle->lusb_dev_handle, interface_number); + + return ret; +} + +int libhusb_release_interface(libhusb_device_handle *handle, int interface_number) +{ + int ret; + + assert(handle); + + ret = libusb_release_interface(handle->lusb_dev_handle, interface_number); + + return ret; +} + +int libhusb_clear_halt(libhusb_device_handle *handle, unsigned char endpoint) +{ + int ret; + + assert(handle); + + ret = libusb_clear_halt(handle->lusb_dev_handle, endpoint); + + return ret; +} + +int libhusb_reset_device(libhusb_device_handle *handle) +{ + int ret; + + assert(handle); + + ret = libusb_reset_device(handle->lusb_dev_handle); + + return ret; +} + +int libhusb_kernel_driver_active(libhusb_device_handle *handle, int interface_number) +{ + int ret; + + assert(handle); + + ret = libusb_kernel_driver_active(handle->lusb_dev_handle, interface_number); + + return ret; +} + +int libhusb_detach_kernel_driver(libhusb_device_handle *handle, int interface_number) +{ + int ret; + + assert(handle); + + ret = libusb_detach_kernel_driver(handle->lusb_dev_handle, interface_number); + + return ret; +} + +int libhusb_attach_kernel_driver(libhusb_device_handle *handle, int interface_number) +{ + int ret; + + assert(handle); + + ret = libusb_attach_kernel_driver(handle->lusb_dev_handle, interface_number); + + return ret; +} + +int libhusb_get_device_descriptor(libhusb_device *dev, struct libhusb_device_descriptor *desc) +{ + int descriptor; + + assert(dev); + + descriptor = libusb_get_device_descriptor(dev->lusb_dev, + (struct libusb_device_descriptor *)desc); + + return descriptor; +} + +int libhusb_get_config_descriptor(libhusb_device *dev, uint8_t config_index, + struct libhusb_cfg_descriptor **config) +{ + int ret = 0; + + /* TODO implement */ + + return ret; +} + +void libhusb_free_config_descriptor(struct libhusb_cfg_descriptor *config) +{ + /* TODO implement */ +} + +int libhusb_get_string_descriptor_ascii(libhusb_device_handle *handle, + uint8_t desc_index, unsigned char *data, int length) +{ + int ret; + + assert(handle); + + ret = libusb_get_string_descriptor_ascii(handle->lusb_dev_handle, desc_index, data, length); + + return ret; +} + +int libhusb_control_transfer(libhusb_device_handle *handle, uint8_t request_type, + uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + unsigned char *data, uint16_t wLength, unsigned int timeout) +{ + int ret; + + assert(handle); + + ret = libusb_control_transfer(handle->lusb_dev_handle, request_type, bRequest, + wValue, wIndex, data, wLength, timeout); + + return ret; +} + +int libhusb_bulk_transfer(libhusb_device_handle *handle, unsigned char endpoint, + unsigned char *data, int length, int *actual_length, + unsigned int timeout) +{ + int ret; + + assert(handle); + + ret = libusb_bulk_transfer(handle->lusb_dev_handle, endpoint, data, length, + actual_length, timeout); + + return ret; +} + +int libhusb_interrupt_transfer(libhusb_device_handle *handle, + unsigned char endpoint, unsigned char *data, int length, + int *actual_length, unsigned int timeout) +{ + int ret; + + assert(handle); + + ret = libusb_interrupt_transfer(handle->lusb_dev_handle, endpoint, data, length, + actual_length, timeout); + + return ret; +}