add simple USB host CAPI
authorStanislaw Wadas <s.wadas@samsung.com>
Wed, 27 May 2015 13:17:24 +0000 (15:17 +0200)
committerStanislaw Wadas <s.wadas@samsung.com>
Sat, 27 Jun 2015 12:30:25 +0000 (14:30 +0200)
Change-Id: I864a9625c1f45d9331e751f8c15a0a79bcc573af
Signed-off-by: Stanislaw Wadas <s.wadas@samsung.com>
include/libhusb.h [new file with mode: 0644]
src/libhusb.c [new file with mode: 0644]

diff --git a/include/libhusb.h b/include/libhusb.h
new file mode 100644 (file)
index 0000000..559e4ad
--- /dev/null
@@ -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 <stdint.h>
+
+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 (file)
index 0000000..eb80b9f
--- /dev/null
@@ -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 <stdio.h>
+#include <libusb-1.0/libusb.h>
+#include <libhusb.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+
+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;
+}