From 80eae57f1a4efdcf91ef6fe4417abad63f41fd46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=98=8A=E8=8B=8F?= Date: Thu, 12 Sep 2024 15:22:32 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9install.py=E6=89=A7?= =?UTF-8?q?=E8=A1=8Cpatch=E4=B8=8D=E7=A8=B3=E5=AE=9A=E9=97=AE=E9=A2=98=20S?= =?UTF-8?q?igned-off-by:liuhaosu@huawei.com?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 刘昊苏 --- install.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/install.py b/install.py index dae99bb1f..e6efcc18d 100755 --- a/install.py +++ b/install.py @@ -25,16 +25,18 @@ def apply_patch(source_dir): 'usbmanager.patch' ] + reject_file = '/dev/null' + for patch in patch_list: patch_dir = os.path.join(source_dir, 'patches', patch) - try : - patch_cmd = ['patch', '-p1', "--fuzz=0", "--no-backup-if-mismatch", '-i', patch_dir, '-d', source_dir] - subprocess.run(patch_cmd, check=True) - except Exception as e: - print("apply_patch error, revserse patch") - patch_cmd = ['patch', '-R', '-p1', "--fuzz=0", "--no-backup-if-mismatch", '-i', patch_dir, '-d', source_dir] - subprocess.run(patch_cmd, check=True) - continue + patch_cmd = ['patch', '-p1', "--fuzz=0", "--no-backup-if-mismatch", '--reject-file=' + reject_file, '-i', patch_dir, '-d', source_dir] + + try: + result = subprocess.run(patch_cmd, check=True, text=True, capture_output=True) + if result.returncode != 0: + raise subprocess.CalledProcessError(result.returncode, result.args) + except subprocess.CalledProcessError: + print("//third_party/backends/patches/usbmanager.patch apply error!") def cp_file(source_dir, gen_dir): src_list = [ -- Gitee From bf401b17f4ee7c465e854b1ae2da96d52db66325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=98=8A=E8=8B=8F?= Date: Thu, 12 Sep 2024 17:01:57 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=88=A0=E9=99=A4patch=EF=BC=8C=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E6=96=B0=E5=A2=9E=E6=96=87=E4=BB=B6=E5=92=8C=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=BA=90=E7=A0=81=20Signed-off-by:liuhaosu@huawei.com?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 刘昊苏 --- BUILD.gn | 75 +- bundle.json | 12 +- include/sane/config.h | 5 +- include/sane/usb_manager.h | 421 +++++++ install.py | 75 -- patches/usbmanager.patch | 2219 ------------------------------------ sanei/sanei_usb.c | 865 ++++++++++++-- sanei/usb_manager.cpp | 573 ++++++++++ 8 files changed, 1826 insertions(+), 2419 deletions(-) create mode 100644 include/sane/usb_manager.h delete mode 100755 install.py delete mode 100644 patches/usbmanager.patch create mode 100644 sanei/usb_manager.cpp diff --git a/BUILD.gn b/BUILD.gn index 602a3c529..ba4821802 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -21,44 +21,15 @@ SANE_LIB_DIR = "/data/service/el1/public/print_service/sane/backend" SANE_V_MAJOR = 1 SANE_V_MINOR = 2 enable_hilog = true -source_dir = "//third_party/backends" -target_dir = "${target_gen_dir}/sane" -backends_usb_manager_source_file = [ - "$target_dir/src/sanei_usb.c", - "$target_dir/src/usb_manager.cpp", -] - -backends_usb_header_file = [ - "$target_dir/include/config.h", - "$target_dir/include/usb_manager.h", -] - -action("backends_action") { - print("backends_action is exec") - script = "//third_party/backends/install.py" - outputs = [] - outputs += backends_usb_manager_source_file - outputs += backends_usb_header_file - - inputs = [ "${source_dir}/patches/usbmanager.patch" ] - backends_source_dir = rebase_path("${source_dir}", root_build_dir) - backends_target_dir = rebase_path("${target_dir}", root_build_dir) - args = [ - "--gen-dir", - "$backends_target_dir", - "--source-dir", - "$backends_source_dir", - ] -} - -config("base_config") { +config("backends_public_config") { include_dirs = [ - ".", "./include", "./include/sane", ] +} +config("backends_private_config") { cflags = [ "-Wall", "-g", @@ -84,20 +55,17 @@ config("base_config") { "PATH_SANE_TMP_DIR=$SANE_TMP_DIR", "V_MAJOR=$SANE_V_MAJOR", "V_MINOR=$SANE_V_MINOR", + "LIBDIR=\"$SANE_LIB_DIR\"", ] } -config("backend_config") { - configs = [ ":base_config" ] - - defines = [ "LIBDIR=\"$SANE_LIB_DIR\"" ] -} - #build targets in /lib ohos_source_set("lib") { sources = [ "./lib/md5.c" ] - configs = [ ":base_config" ] + public_configs = [ ":backends_public_config" ] + + configs = [ ":backends_private_config" ] subsystem_name = "thirdparty" part_name = "backends" @@ -139,7 +107,9 @@ foreach(name, sanei_names) { external_deps = [ "hilog:libhilog" ] } - configs = [ ":base_config" ] + public_configs = [ ":backends_public_config" ] + + configs = [ ":backends_private_config" ] subsystem_name = "thirdparty" part_name = "backends" @@ -147,14 +117,11 @@ foreach(name, sanei_names) { } ohos_source_set("sanei_usb") { - include_dirs = [ "$target_dir/include" ] sources = [ - "$target_dir/src/sanei_usb.c", - "$target_dir/src/usb_manager.cpp", + "./sanei/sanei_usb.c", + "./sanei/usb_manager.cpp", ] - deps = [ ":backends_action" ] - external_deps = [ "bounds_checking_function:libsec_shared", "c_utils:utils", @@ -163,7 +130,9 @@ ohos_source_set("sanei_usb") { "usb_manager:usbsrv_client", ] - configs = [ ":base_config" ] + public_configs = [ ":backends_public_config" ] + + configs = [ ":backends_private_config" ] subsystem_name = "thirdparty" part_name = "backends" @@ -180,7 +149,9 @@ ohos_static_library("sanei") { external_deps = [ "hilog:libhilog" ] } - configs = [ ":base_config" ] + public_configs = [ ":backends_public_config" ] + + configs = [ ":backends_private_config" ] subsystem_name = "thirdparty" part_name = "backends" @@ -190,7 +161,9 @@ ohos_static_library("sanei") { ohos_source_set("sane_strstatus") { sources = [ "./backend/sane_strstatus.c" ] - configs = [ ":backend_config" ] + public_configs = [ ":backends_public_config" ] + + configs = [ ":backends_private_config" ] subsystem_name = "thirdparty" part_name = "backends" @@ -202,7 +175,9 @@ ohos_shared_library("sane") { "./backend/stubs.c", ] - configs = [ ":backend_config" ] + public_configs = [ ":backends_public_config" ] + + configs = [ ":backends_private_config" ] defines = [ "BACKEND_NAME=dll" ] @@ -228,4 +203,4 @@ ohos_shared_library("sane") { #the target group group("third_sane") { deps = [ ":sane" ] -} +} \ No newline at end of file diff --git a/bundle.json b/bundle.json index 14586538f..889b4b20d 100644 --- a/bundle.json +++ b/bundle.json @@ -32,14 +32,14 @@ ], "inner_kits": [ { - "name": "//third_party/backends:third_sane", "header": { + "header_base": "//third_party/backends/include/sane/", "header_files": [ - "sane/sane.h", - "sane/saneopts.h" - ], - "header_base": "//third_party/backends/include" - } + "sane.h", + "saneopts.h" + ] + }, + "name": "//third_party/backends:sane" } ], "test": [] diff --git a/include/sane/config.h b/include/sane/config.h index 22234857f..08fa8accd 100644 --- a/include/sane/config.h +++ b/include/sane/config.h @@ -207,7 +207,10 @@ #define HAVE_LIBSNMP 0 /* Define to 1 if you have libusb-1.0 */ -#define HAVE_LIBUSB 1 +// #define HAVE_LIBUSB 1 + +/* Define to 1 if you have usb_manager */ +#define HAVE_USB_MANAGER 1 /* Define to 1 if you have libusb-0.1 */ /* #undef HAVE_LIBUSB_LEGACY */ diff --git a/include/sane/usb_manager.h b/include/sane/usb_manager.h new file mode 100644 index 000000000..a25e4f67c --- /dev/null +++ b/include/sane/usb_manager.h @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2024 Huawei Device 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 USB_MANAGER_H +#define USB_MANAGER_H + +#include +#include + +#include "hilog/log.h" +#define SANE_LOG_TAG "sanekit" +#define SANE_HILOG_INFO(...) ((void)HiLogPrint(LOG_APP, LOG_INFO, 0, "sanekit", __VA_ARGS__)) + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_MANAGER_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ +#define USB_MANAGER_ENDPOINT_DIR_MASK 0x80 +#define USB_DT_CONFIGURATION 0x02 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 + +enum usb_manager_option { + USB_MANAGER_OPTION_LOG_LEVEL = 0, +}; + +/** \ingroup usb_manager_desc + * Endpoint direction. Values for bit 7 of the + * \ref usb_manager_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. + */ +enum usb_manager_endpoint_direction { + /** Out: host-to-device */ + USB_MANAGER_ENDPOINT_OUT = 0x00, + + /** In: device-to-host */ + USB_MANAGER_ENDPOINT_IN = 0x80 +}; + +enum usb_manager_transfer_type { + /** Control transfer */ + USB_MANAGER_TRANSFER_TYPE_CONTROL = 0U, + + /** Isochronous transfer */ + USB_MANAGER_TRANSFER_TYPE_ISOCHRONOUS = 1U, + + /** Bulk transfer */ + USB_MANAGER_TRANSFER_TYPE_BULK = 2U, + + /** Interrupt transfer */ + USB_MANAGER_TRANSFER_TYPE_INTERRUPT = 3U, + + /** Bulk stream transfer */ + USB_MANAGER_TRANSFER_TYPE_BULK_STREAM = 4U +}; + +enum usb_manager_error { + /** Success (no error) */ + USB_MANAGER_SUCCESS = 0, + + /** Input/output error */ + USB_MANAGER_ERROR_IO = -1, + + /** Invalid parameter */ + USB_MANAGER_ERROR_INVALID_PARAM = -2, + + /** Access denied (insufficient permissions) */ + USB_MANAGER_ERROR_ACCESS = -3, + + /** No such device (it may have been disconnected) */ + USB_MANAGER_ERROR_NO_DEVICE = -4, + + /** Entity not found */ + USB_MANAGER_ERROR_NOT_FOUND = -5, + + /** Resource busy */ + USB_MANAGER_ERROR_BUSY = -6, + + /** Operation timed out */ + USB_MANAGER_ERROR_TIMEOUT = -7, + + /** Overflow */ + USB_MANAGER_ERROR_OVERFLOW = -8, + + /** Pipe error */ + USB_MANAGER_ERROR_PIPE = -9, + + /** System call interrupted (perhaps due to signal) */ + USB_MANAGER_ERROR_INTERRUPTED = -10, + + /** Insufficient memory */ + USB_MANAGER_ERROR_NO_MEM = -11, + + /** Operation not supported or unimplemented on this platform */ + USB_MANAGER_ERROR_NOT_SUPPORTED = -12, + + /* NB: Remember to update USB_MANAGER_ERROR_COUNT below as well as the + message strings in strerror.c when adding new error codes here. */ + + /** Other error */ + USB_MANAGER_ERROR_OTHER = -99 +}; + +/** \ingroup usb_manager_desc + * Device and/or Interface Class codes */ +enum usb_manager_class_code { + /** In the context of a \ref usb_manager_device_descriptor "device descriptor", + * this bDeviceClass value indicates that each interface specifies its + * own class information and all interfaces operate independently. + */ + USB_MANAGER_CLASS_PER_INTERFACE = 0x00, + + /** Audio class */ + USB_MANAGER_CLASS_AUDIO = 0x01, + + /** Communications class */ + USB_MANAGER_CLASS_COMM = 0x02, + + /** Human Interface Device class */ + USB_MANAGER_CLASS_HID = 0x03, + + /** Physical */ + USB_MANAGER_CLASS_PHYSICAL = 0x05, + + /** Image class */ + USB_MANAGER_CLASS_IMAGE = 0x06, + USB_MANAGER_CLASS_PTP = 0x06, /* legacy name from usb manager usb.h */ + + /** Printer class */ + USB_MANAGER_CLASS_PRINTER = 0x07, + + /** Mass storage class */ + USB_MANAGER_CLASS_MASS_STORAGE = 0x08, + + /** Hub class */ + USB_MANAGER_CLASS_HUB = 0x09, + + /** Data class */ + USB_MANAGER_CLASS_DATA = 0x0a, + + /** Smart Card */ + USB_MANAGER_CLASS_SMART_CARD = 0x0b, + + /** Content Security */ + USB_MANAGER_CLASS_CONTENT_SECURITY = 0x0d, + + /** Video */ + USB_MANAGER_CLASS_VIDEO = 0x0e, + + /** Personal Healthcare */ + USB_MANAGER_CLASS_PERSONAL_HEALTHCARE = 0x0f, + + /** Diagnostic Device */ + USB_MANAGER_CLASS_DIAGNOSTIC_DEVICE = 0xdc, + + /** Wireless class */ + USB_MANAGER_CLASS_WIRELESS = 0xe0, + + /** Miscellaneous class */ + USB_MANAGER_CLASS_MISCELLANEOUS = 0xef, + + /** Application class */ + USB_MANAGER_CLASS_APPLICATION = 0xfe, + + /** Class is vendor-specific */ + USB_MANAGER_CLASS_VENDOR_SPEC = 0xff +}; + +/** \ingroup usb_manager_desc + * A structure representing the standard USB device descriptor. This + * descriptor is documented in section 9.6.1 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct usb_manager_device_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref usb_manager_descriptor_type::USB_MANAGER_DT_DEVICE USB_MANAGER_DT_DEVICE in this + * context. */ + uint8_t bDescriptorType; + + /** USB specification release number in binary-coded decimal. A value of + * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ + uint16_t bcdUSB; + + /** USB-IF class code for the device. See \ref usb_manager_class_code. */ + uint8_t bDeviceClass; + + /** USB-IF subclass code for the device, qualified by the bDeviceClass + * value */ + uint8_t bDeviceSubClass; + + /** USB-IF protocol code for the device, qualified by the bDeviceClass and + * bDeviceSubClass values */ + uint8_t bDeviceProtocol; + + /** Maximum packet size for endpoint 0 */ + uint8_t bMaxPacketSize0; + + /** USB-IF vendor ID */ + uint16_t idVendor; + + /** USB-IF product ID */ + uint16_t idProduct; + + /** Device release number in binary-coded decimal */ + uint16_t bcdDevice; + + /** Index of string descriptor describing manufacturer */ + uint8_t iManufacturer; + + /** Index of string descriptor describing product */ + uint8_t iProduct; + + /** Index of string descriptor containing device serial number */ + uint8_t iSerialNumber; + + /** Number of possible configurations */ + uint8_t bNumConfigurations; +}; + +/** \ingroup usb_manager_desc + * A structure representing the standard USB endpoint descriptor. This + * descriptor is documented in section 9.6.6 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct usb_manager_endpoint_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref usb_manager_descriptor_type::USB_MANAGER_DT_ENDPOINT USB_MANAGER_DT_ENDPOINT in + * this context. */ + uint8_t bDescriptorType; + + /** The address of the endpoint described by this descriptor. Bits 0:3 are + * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, + * see \ref usb_manager_endpoint_direction. */ + uint8_t bEndpointAddress; + + /** Attributes which apply to the endpoint when it is configured using + * the bConfigurationValue. Bits 0:1 determine the transfer type and + * correspond to \ref usb_manager_endpoint_transfer_type. Bits 2:3 are only used + * for isochronous endpoints and correspond to \ref usb_manager_iso_sync_type. + * Bits 4:5 are also only used for isochronous endpoints and correspond to + * \ref usb_manager_iso_usage_type. Bits 6:7 are reserved. */ + uint8_t bmAttributes; + + /** Maximum packet size this endpoint is capable of sending/receiving. */ + uint16_t wMaxPacketSize; + + /** Interval for polling endpoint for data transfers. */ + uint8_t bInterval; + + /** For audio devices only: the rate at which synchronization feedback + * is provided. */ + uint8_t bRefresh; + + /** For audio devices only: the address if the synch endpoint */ + uint8_t bSynchAddress; +}; + +/** \ingroup usb_manager_desc + * A structure representing the standard USB interface descriptor. This + * descriptor is documented in section 9.6.5 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct usb_manager_interface_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref usb_manager_descriptor_type::USB_MANAGER_DT_INTERFACE USB_MANAGER_DT_INTERFACE + * in this context. */ + uint8_t bDescriptorType; + + /** Number of this interface */ + uint8_t bInterfaceNumber; + + /** Value used to select this alternate setting for this interface */ + uint8_t bAlternateSetting; + + /** Number of endpoints used by this interface (excluding the control + * endpoint). */ + uint8_t bNumEndpoints; + + /** USB-IF class code for this interface. See \ref usb_manager_class_code. */ + uint8_t bInterfaceClass; + + /** USB-IF subclass code for this interface, qualified by the + * bInterfaceClass value */ + uint8_t bInterfaceSubClass; + + /** USB-IF protocol code for this interface, qualified by the + * bInterfaceClass and bInterfaceSubClass values */ + uint8_t bInterfaceProtocol; + + /** Index of string descriptor describing this interface */ + uint8_t iInterface; + + /** Array of endpoint descriptors. This length of this array is determined + * by the bNumEndpoints field. */ + struct usb_manager_endpoint_descriptor *endpoint; +}; + + +/** \ingroup usb_manager_desc + * A collection of alternate settings for a particular USB interface. + */ +struct usb_manager_interface { + /** Array of interface descriptors. The length of this array is determined + * by the num_altsetting field. */ + struct usb_manager_interface_descriptor *altsetting; + + /** The number of alternate settings that belong to this interface. + * Must be non-negative. */ + int num_altsetting; +}; + +/** \ingroup usb_manager_desc + * A structure representing the standard USB configuration descriptor. This + * descriptor is documented in section 9.6.3 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct usb_manager_config_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref usb_manager_descriptor_type::USB_MANAGER_DT_CONFIG USB_MANAGER_DT_CONFIG + * in this context. */ + uint8_t bDescriptorType; + + /** Total length of data returned for this configuration */ + uint16_t wTotalLength; + + /** Number of interfaces supported by this configuration */ + uint8_t bNumInterfaces; + + /** Identifier value for this configuration */ + uint8_t bConfigurationValue; + + /** Index of string descriptor describing this configuration */ + uint8_t iConfiguration; + + /** Configuration characteristics */ + uint8_t bmAttributes; + + /** Maximum power consumption of the USB device from this bus in this + * configuration when the device is fully operation. Expressed in units + * of 2 mA when the device is operating in high-speed mode and in units + * of 8 mA when the device is operating in super-speed mode. */ + uint8_t MaxPower; + + /** Array of interfaces supported by this configuration. The length of + * this array is determined by the bNumInterfaces field. */ + struct usb_manager_interface *interface; +}; + +struct usb_manager_device; + +struct usb_manager_device_handle; + +struct usb_manager_context { + struct usb_manager_device *devices; + uint32_t deviceCount; +}; + +typedef struct usb_manager_context usb_manager_context; +typedef struct usb_manager_device usb_manager_device; +typedef struct usb_manager_device_handle usb_manager_device_handle; +typedef struct usb_manager_device_descriptor usb_manager_device_descriptor; +typedef struct usb_manager_config_descriptor usb_manager_config_descriptor; + +int usb_manager_init(usb_manager_context **ctx); +int usb_manager_exit(usb_manager_context *ctx); +ssize_t usb_manager_get_device_list(usb_manager_context *ctx, usb_manager_device ***list); +int usb_manager_get_bus_number(usb_manager_device *dev); +int usb_manager_get_device_address(usb_manager_device *dev); +int usb_manager_get_device_descriptor(usb_manager_device *dev, usb_manager_device_descriptor *desc); +int usb_manager_open(usb_manager_device *dev, usb_manager_device_handle **dev_handle); +void usb_manager_close(usb_manager_device_handle *dev_handle); +int usb_manager_get_configuration(usb_manager_device_handle *dev, int *config); +int usb_manager_get_config_descriptor(usb_manager_device *dev, uint8_t config_index, + usb_manager_config_descriptor **config); +void usb_manager_free_config_descriptor(usb_manager_config_descriptor *config); +void usb_manager_free_device_list(usb_manager_device **list, int unref_devices); +int usb_manager_set_configuration(usb_manager_device_handle *dev_handle, int configuration); +int usb_manager_claim_interface(usb_manager_device_handle *dev_handle, int interface_number); +int usb_manager_release_interface(usb_manager_device_handle *dev_handle, int interface_number); +int usb_manager_clear_halt(usb_manager_device_handle *dev_handle, unsigned char endpoint); +int usb_manager_reset_device(usb_manager_device_handle *dev_handle); +int usb_manager_bulk_transfer(usb_manager_device_handle *dev_handle, unsigned char endpoint, + unsigned char *data, int length, int *transferred, unsigned int timeout); +int usb_manager_control_transfer(usb_manager_device_handle *dev_handle, uint8_t request_type, + uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, + unsigned int timeout); +int usb_manager_interrupt_transfer(usb_manager_device_handle *dev_handle, unsigned char endpoint, + unsigned char *data, int length, int *actual_length, unsigned int timeout); +int usb_manager_set_interface_alt_setting(usb_manager_device_handle *dev_handle, int interface_number, + int alternate_setting); +usb_manager_device * usb_manager_ref_device(usb_manager_device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* USB_MANAGER_H */ \ No newline at end of file diff --git a/install.py b/install.py deleted file mode 100755 index e6efcc18d..000000000 --- a/install.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Copyright (c) 2023 Huawei Device 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. - -import tarfile -import argparse -import os -import subprocess -import sys -import shutil - -def apply_patch(source_dir): - patch_list = [ - 'usbmanager.patch' - ] - - reject_file = '/dev/null' - - for patch in patch_list: - patch_dir = os.path.join(source_dir, 'patches', patch) - patch_cmd = ['patch', '-p1', "--fuzz=0", "--no-backup-if-mismatch", '--reject-file=' + reject_file, '-i', patch_dir, '-d', source_dir] - - try: - result = subprocess.run(patch_cmd, check=True, text=True, capture_output=True) - if result.returncode != 0: - raise subprocess.CalledProcessError(result.returncode, result.args) - except subprocess.CalledProcessError: - print("//third_party/backends/patches/usbmanager.patch apply error!") - -def cp_file(source_dir, gen_dir): - src_list = [ - 'usb_manager.cpp', - 'sanei_usb.c' - ] - head_list = [ - 'usb_manager.h', - 'config.h' - ] - for src in src_list: - source_file = os.path.join(source_dir, 'sanei', src) - dest_file = os.path.join(gen_dir, 'src', src) - cp_cmd = ['cp', source_file, dest_file] - subprocess.run(cp_cmd, check=True) - for head in head_list: - source_file = os.path.join(source_dir, 'include', 'sane', head) - dest_file = os.path.join(gen_dir, 'include', head) - cp_cmd = ['cp', source_file, dest_file] - subprocess.run(cp_cmd, check=True) - -def main(): - cups_path = argparse.ArgumentParser() - cups_path.add_argument('--gen-dir', help='generate path of log', required=True) - cups_path.add_argument('--source-dir', help='generate path of log', required=True) - args = cups_path.parse_args() - # gen_dir = "${target_gen_dir}/sane" - gen_dir = args.gen_dir - # source_dir = //third_party/backends - source_dir = args.source_dir - apply_patch(source_dir) - cp_file(source_dir, gen_dir) - return 0 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/patches/usbmanager.patch b/patches/usbmanager.patch deleted file mode 100644 index 3db91cb8e..000000000 --- a/patches/usbmanager.patch +++ /dev/null @@ -1,2219 +0,0 @@ -From b7a532f007bb10e18536d64fc53a1b182da37f21 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E5=88=98=E6=98=8A=E8=8B=8F?= -Date: Wed, 14 Aug 2024 09:45:08 +0800 -Subject: [PATCH] =?UTF-8?q?libusb=E6=8D=A2=E6=88=90usbmanager=20Signed-off?= - =?UTF-8?q?-by:liuhaosu@huawei.com?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: 刘昊苏 ---- - include/sane/config.h | 5 +- - include/sane/usb_manager.h | 421 ++++++++++++++++++ - sanei/sanei_usb.c | 865 ++++++++++++++++++++++++++++++++++--- - sanei/usb_manager.cpp | 572 ++++++++++++++++++++++++ - 4 files changed, 1794 insertions(+), 69 deletions(-) - create mode 100644 include/sane/usb_manager.h - create mode 100644 sanei/usb_manager.cpp - -diff --git a/include/sane/config.h b/include/sane/config.h -index 22234857f..08fa8accd 100644 ---- a/include/sane/config.h -+++ b/include/sane/config.h -@@ -207,7 +207,10 @@ - #define HAVE_LIBSNMP 0 - - /* Define to 1 if you have libusb-1.0 */ --#define HAVE_LIBUSB 1 -+// #define HAVE_LIBUSB 1 -+ -+/* Define to 1 if you have usb_manager */ -+#define HAVE_USB_MANAGER 1 - - /* Define to 1 if you have libusb-0.1 */ - /* #undef HAVE_LIBUSB_LEGACY */ -diff --git a/include/sane/usb_manager.h b/include/sane/usb_manager.h -new file mode 100644 -index 000000000..a25e4f67c ---- /dev/null -+++ b/include/sane/usb_manager.h -@@ -0,0 +1,421 @@ -+/* -+ * Copyright (c) 2024 Huawei Device 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 USB_MANAGER_H -+#define USB_MANAGER_H -+ -+#include -+#include -+ -+#include "hilog/log.h" -+#define SANE_LOG_TAG "sanekit" -+#define SANE_HILOG_INFO(...) ((void)HiLogPrint(LOG_APP, LOG_INFO, 0, "sanekit", __VA_ARGS__)) -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define USB_MANAGER_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ -+#define USB_MANAGER_ENDPOINT_DIR_MASK 0x80 -+#define USB_DT_CONFIGURATION 0x02 -+#define USB_DT_INTERFACE 0x04 -+#define USB_DT_ENDPOINT 0x05 -+ -+enum usb_manager_option { -+ USB_MANAGER_OPTION_LOG_LEVEL = 0, -+}; -+ -+/** \ingroup usb_manager_desc -+ * Endpoint direction. Values for bit 7 of the -+ * \ref usb_manager_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. -+ */ -+enum usb_manager_endpoint_direction { -+ /** Out: host-to-device */ -+ USB_MANAGER_ENDPOINT_OUT = 0x00, -+ -+ /** In: device-to-host */ -+ USB_MANAGER_ENDPOINT_IN = 0x80 -+}; -+ -+enum usb_manager_transfer_type { -+ /** Control transfer */ -+ USB_MANAGER_TRANSFER_TYPE_CONTROL = 0U, -+ -+ /** Isochronous transfer */ -+ USB_MANAGER_TRANSFER_TYPE_ISOCHRONOUS = 1U, -+ -+ /** Bulk transfer */ -+ USB_MANAGER_TRANSFER_TYPE_BULK = 2U, -+ -+ /** Interrupt transfer */ -+ USB_MANAGER_TRANSFER_TYPE_INTERRUPT = 3U, -+ -+ /** Bulk stream transfer */ -+ USB_MANAGER_TRANSFER_TYPE_BULK_STREAM = 4U -+}; -+ -+enum usb_manager_error { -+ /** Success (no error) */ -+ USB_MANAGER_SUCCESS = 0, -+ -+ /** Input/output error */ -+ USB_MANAGER_ERROR_IO = -1, -+ -+ /** Invalid parameter */ -+ USB_MANAGER_ERROR_INVALID_PARAM = -2, -+ -+ /** Access denied (insufficient permissions) */ -+ USB_MANAGER_ERROR_ACCESS = -3, -+ -+ /** No such device (it may have been disconnected) */ -+ USB_MANAGER_ERROR_NO_DEVICE = -4, -+ -+ /** Entity not found */ -+ USB_MANAGER_ERROR_NOT_FOUND = -5, -+ -+ /** Resource busy */ -+ USB_MANAGER_ERROR_BUSY = -6, -+ -+ /** Operation timed out */ -+ USB_MANAGER_ERROR_TIMEOUT = -7, -+ -+ /** Overflow */ -+ USB_MANAGER_ERROR_OVERFLOW = -8, -+ -+ /** Pipe error */ -+ USB_MANAGER_ERROR_PIPE = -9, -+ -+ /** System call interrupted (perhaps due to signal) */ -+ USB_MANAGER_ERROR_INTERRUPTED = -10, -+ -+ /** Insufficient memory */ -+ USB_MANAGER_ERROR_NO_MEM = -11, -+ -+ /** Operation not supported or unimplemented on this platform */ -+ USB_MANAGER_ERROR_NOT_SUPPORTED = -12, -+ -+ /* NB: Remember to update USB_MANAGER_ERROR_COUNT below as well as the -+ message strings in strerror.c when adding new error codes here. */ -+ -+ /** Other error */ -+ USB_MANAGER_ERROR_OTHER = -99 -+}; -+ -+/** \ingroup usb_manager_desc -+ * Device and/or Interface Class codes */ -+enum usb_manager_class_code { -+ /** In the context of a \ref usb_manager_device_descriptor "device descriptor", -+ * this bDeviceClass value indicates that each interface specifies its -+ * own class information and all interfaces operate independently. -+ */ -+ USB_MANAGER_CLASS_PER_INTERFACE = 0x00, -+ -+ /** Audio class */ -+ USB_MANAGER_CLASS_AUDIO = 0x01, -+ -+ /** Communications class */ -+ USB_MANAGER_CLASS_COMM = 0x02, -+ -+ /** Human Interface Device class */ -+ USB_MANAGER_CLASS_HID = 0x03, -+ -+ /** Physical */ -+ USB_MANAGER_CLASS_PHYSICAL = 0x05, -+ -+ /** Image class */ -+ USB_MANAGER_CLASS_IMAGE = 0x06, -+ USB_MANAGER_CLASS_PTP = 0x06, /* legacy name from usb manager usb.h */ -+ -+ /** Printer class */ -+ USB_MANAGER_CLASS_PRINTER = 0x07, -+ -+ /** Mass storage class */ -+ USB_MANAGER_CLASS_MASS_STORAGE = 0x08, -+ -+ /** Hub class */ -+ USB_MANAGER_CLASS_HUB = 0x09, -+ -+ /** Data class */ -+ USB_MANAGER_CLASS_DATA = 0x0a, -+ -+ /** Smart Card */ -+ USB_MANAGER_CLASS_SMART_CARD = 0x0b, -+ -+ /** Content Security */ -+ USB_MANAGER_CLASS_CONTENT_SECURITY = 0x0d, -+ -+ /** Video */ -+ USB_MANAGER_CLASS_VIDEO = 0x0e, -+ -+ /** Personal Healthcare */ -+ USB_MANAGER_CLASS_PERSONAL_HEALTHCARE = 0x0f, -+ -+ /** Diagnostic Device */ -+ USB_MANAGER_CLASS_DIAGNOSTIC_DEVICE = 0xdc, -+ -+ /** Wireless class */ -+ USB_MANAGER_CLASS_WIRELESS = 0xe0, -+ -+ /** Miscellaneous class */ -+ USB_MANAGER_CLASS_MISCELLANEOUS = 0xef, -+ -+ /** Application class */ -+ USB_MANAGER_CLASS_APPLICATION = 0xfe, -+ -+ /** Class is vendor-specific */ -+ USB_MANAGER_CLASS_VENDOR_SPEC = 0xff -+}; -+ -+/** \ingroup usb_manager_desc -+ * A structure representing the standard USB device descriptor. This -+ * descriptor is documented in section 9.6.1 of the USB 3.0 specification. -+ * All multiple-byte fields are represented in host-endian format. -+ */ -+struct usb_manager_device_descriptor { -+ /** Size of this descriptor (in bytes) */ -+ uint8_t bLength; -+ -+ /** Descriptor type. Will have value -+ * \ref usb_manager_descriptor_type::USB_MANAGER_DT_DEVICE USB_MANAGER_DT_DEVICE in this -+ * context. */ -+ uint8_t bDescriptorType; -+ -+ /** USB specification release number in binary-coded decimal. A value of -+ * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ -+ uint16_t bcdUSB; -+ -+ /** USB-IF class code for the device. See \ref usb_manager_class_code. */ -+ uint8_t bDeviceClass; -+ -+ /** USB-IF subclass code for the device, qualified by the bDeviceClass -+ * value */ -+ uint8_t bDeviceSubClass; -+ -+ /** USB-IF protocol code for the device, qualified by the bDeviceClass and -+ * bDeviceSubClass values */ -+ uint8_t bDeviceProtocol; -+ -+ /** Maximum packet size for endpoint 0 */ -+ uint8_t bMaxPacketSize0; -+ -+ /** USB-IF vendor ID */ -+ uint16_t idVendor; -+ -+ /** USB-IF product ID */ -+ uint16_t idProduct; -+ -+ /** Device release number in binary-coded decimal */ -+ uint16_t bcdDevice; -+ -+ /** Index of string descriptor describing manufacturer */ -+ uint8_t iManufacturer; -+ -+ /** Index of string descriptor describing product */ -+ uint8_t iProduct; -+ -+ /** Index of string descriptor containing device serial number */ -+ uint8_t iSerialNumber; -+ -+ /** Number of possible configurations */ -+ uint8_t bNumConfigurations; -+}; -+ -+/** \ingroup usb_manager_desc -+ * A structure representing the standard USB endpoint descriptor. This -+ * descriptor is documented in section 9.6.6 of the USB 3.0 specification. -+ * All multiple-byte fields are represented in host-endian format. -+ */ -+struct usb_manager_endpoint_descriptor { -+ /** Size of this descriptor (in bytes) */ -+ uint8_t bLength; -+ -+ /** Descriptor type. Will have value -+ * \ref usb_manager_descriptor_type::USB_MANAGER_DT_ENDPOINT USB_MANAGER_DT_ENDPOINT in -+ * this context. */ -+ uint8_t bDescriptorType; -+ -+ /** The address of the endpoint described by this descriptor. Bits 0:3 are -+ * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, -+ * see \ref usb_manager_endpoint_direction. */ -+ uint8_t bEndpointAddress; -+ -+ /** Attributes which apply to the endpoint when it is configured using -+ * the bConfigurationValue. Bits 0:1 determine the transfer type and -+ * correspond to \ref usb_manager_endpoint_transfer_type. Bits 2:3 are only used -+ * for isochronous endpoints and correspond to \ref usb_manager_iso_sync_type. -+ * Bits 4:5 are also only used for isochronous endpoints and correspond to -+ * \ref usb_manager_iso_usage_type. Bits 6:7 are reserved. */ -+ uint8_t bmAttributes; -+ -+ /** Maximum packet size this endpoint is capable of sending/receiving. */ -+ uint16_t wMaxPacketSize; -+ -+ /** Interval for polling endpoint for data transfers. */ -+ uint8_t bInterval; -+ -+ /** For audio devices only: the rate at which synchronization feedback -+ * is provided. */ -+ uint8_t bRefresh; -+ -+ /** For audio devices only: the address if the synch endpoint */ -+ uint8_t bSynchAddress; -+}; -+ -+/** \ingroup usb_manager_desc -+ * A structure representing the standard USB interface descriptor. This -+ * descriptor is documented in section 9.6.5 of the USB 3.0 specification. -+ * All multiple-byte fields are represented in host-endian format. -+ */ -+struct usb_manager_interface_descriptor { -+ /** Size of this descriptor (in bytes) */ -+ uint8_t bLength; -+ -+ /** Descriptor type. Will have value -+ * \ref usb_manager_descriptor_type::USB_MANAGER_DT_INTERFACE USB_MANAGER_DT_INTERFACE -+ * in this context. */ -+ uint8_t bDescriptorType; -+ -+ /** Number of this interface */ -+ uint8_t bInterfaceNumber; -+ -+ /** Value used to select this alternate setting for this interface */ -+ uint8_t bAlternateSetting; -+ -+ /** Number of endpoints used by this interface (excluding the control -+ * endpoint). */ -+ uint8_t bNumEndpoints; -+ -+ /** USB-IF class code for this interface. See \ref usb_manager_class_code. */ -+ uint8_t bInterfaceClass; -+ -+ /** USB-IF subclass code for this interface, qualified by the -+ * bInterfaceClass value */ -+ uint8_t bInterfaceSubClass; -+ -+ /** USB-IF protocol code for this interface, qualified by the -+ * bInterfaceClass and bInterfaceSubClass values */ -+ uint8_t bInterfaceProtocol; -+ -+ /** Index of string descriptor describing this interface */ -+ uint8_t iInterface; -+ -+ /** Array of endpoint descriptors. This length of this array is determined -+ * by the bNumEndpoints field. */ -+ struct usb_manager_endpoint_descriptor *endpoint; -+}; -+ -+ -+/** \ingroup usb_manager_desc -+ * A collection of alternate settings for a particular USB interface. -+ */ -+struct usb_manager_interface { -+ /** Array of interface descriptors. The length of this array is determined -+ * by the num_altsetting field. */ -+ struct usb_manager_interface_descriptor *altsetting; -+ -+ /** The number of alternate settings that belong to this interface. -+ * Must be non-negative. */ -+ int num_altsetting; -+}; -+ -+/** \ingroup usb_manager_desc -+ * A structure representing the standard USB configuration descriptor. This -+ * descriptor is documented in section 9.6.3 of the USB 3.0 specification. -+ * All multiple-byte fields are represented in host-endian format. -+ */ -+struct usb_manager_config_descriptor { -+ /** Size of this descriptor (in bytes) */ -+ uint8_t bLength; -+ -+ /** Descriptor type. Will have value -+ * \ref usb_manager_descriptor_type::USB_MANAGER_DT_CONFIG USB_MANAGER_DT_CONFIG -+ * in this context. */ -+ uint8_t bDescriptorType; -+ -+ /** Total length of data returned for this configuration */ -+ uint16_t wTotalLength; -+ -+ /** Number of interfaces supported by this configuration */ -+ uint8_t bNumInterfaces; -+ -+ /** Identifier value for this configuration */ -+ uint8_t bConfigurationValue; -+ -+ /** Index of string descriptor describing this configuration */ -+ uint8_t iConfiguration; -+ -+ /** Configuration characteristics */ -+ uint8_t bmAttributes; -+ -+ /** Maximum power consumption of the USB device from this bus in this -+ * configuration when the device is fully operation. Expressed in units -+ * of 2 mA when the device is operating in high-speed mode and in units -+ * of 8 mA when the device is operating in super-speed mode. */ -+ uint8_t MaxPower; -+ -+ /** Array of interfaces supported by this configuration. The length of -+ * this array is determined by the bNumInterfaces field. */ -+ struct usb_manager_interface *interface; -+}; -+ -+struct usb_manager_device; -+ -+struct usb_manager_device_handle; -+ -+struct usb_manager_context { -+ struct usb_manager_device *devices; -+ uint32_t deviceCount; -+}; -+ -+typedef struct usb_manager_context usb_manager_context; -+typedef struct usb_manager_device usb_manager_device; -+typedef struct usb_manager_device_handle usb_manager_device_handle; -+typedef struct usb_manager_device_descriptor usb_manager_device_descriptor; -+typedef struct usb_manager_config_descriptor usb_manager_config_descriptor; -+ -+int usb_manager_init(usb_manager_context **ctx); -+int usb_manager_exit(usb_manager_context *ctx); -+ssize_t usb_manager_get_device_list(usb_manager_context *ctx, usb_manager_device ***list); -+int usb_manager_get_bus_number(usb_manager_device *dev); -+int usb_manager_get_device_address(usb_manager_device *dev); -+int usb_manager_get_device_descriptor(usb_manager_device *dev, usb_manager_device_descriptor *desc); -+int usb_manager_open(usb_manager_device *dev, usb_manager_device_handle **dev_handle); -+void usb_manager_close(usb_manager_device_handle *dev_handle); -+int usb_manager_get_configuration(usb_manager_device_handle *dev, int *config); -+int usb_manager_get_config_descriptor(usb_manager_device *dev, uint8_t config_index, -+ usb_manager_config_descriptor **config); -+void usb_manager_free_config_descriptor(usb_manager_config_descriptor *config); -+void usb_manager_free_device_list(usb_manager_device **list, int unref_devices); -+int usb_manager_set_configuration(usb_manager_device_handle *dev_handle, int configuration); -+int usb_manager_claim_interface(usb_manager_device_handle *dev_handle, int interface_number); -+int usb_manager_release_interface(usb_manager_device_handle *dev_handle, int interface_number); -+int usb_manager_clear_halt(usb_manager_device_handle *dev_handle, unsigned char endpoint); -+int usb_manager_reset_device(usb_manager_device_handle *dev_handle); -+int usb_manager_bulk_transfer(usb_manager_device_handle *dev_handle, unsigned char endpoint, -+ unsigned char *data, int length, int *transferred, unsigned int timeout); -+int usb_manager_control_transfer(usb_manager_device_handle *dev_handle, uint8_t request_type, -+ uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, -+ unsigned int timeout); -+int usb_manager_interrupt_transfer(usb_manager_device_handle *dev_handle, unsigned char endpoint, -+ unsigned char *data, int length, int *actual_length, unsigned int timeout); -+int usb_manager_set_interface_alt_setting(usb_manager_device_handle *dev_handle, int interface_number, -+ int alternate_setting); -+usb_manager_device * usb_manager_ref_device(usb_manager_device *dev); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* USB_MANAGER_H */ -\ No newline at end of file -diff --git a/sanei/sanei_usb.c b/sanei/sanei_usb.c -index 022f6fab9..66dbdb730 100644 ---- a/sanei/sanei_usb.c -+++ b/sanei/sanei_usb.c -@@ -84,6 +84,10 @@ - #include - #endif /* HAVE_LIBUSB */ - -+#ifdef HAVE_USB_MANAGER -+#include "usb_manager.h" -+#endif /* HAVE_USB_MANAGER */ -+ - #ifdef HAVE_USBCALLS - #include - #include -@@ -129,7 +133,9 @@ typedef enum - (Linux, BSD) */ - sanei_usb_method_libusb, - -- sanei_usb_method_usbcalls -+ sanei_usb_method_usbcalls, -+ -+ sanei_usb_method_usb_manager - } - sanei_usb_access_method_type; - -@@ -160,6 +166,11 @@ typedef struct - libusb_device *lu_device; - libusb_device_handle *lu_handle; - #endif /* HAVE_LIBUSB */ -+#ifdef HAVE_USB_MANAGER -+ usb_manager_device *usb_manager_device; -+ usb_manager_device_handle *usb_manager_handle; -+#endif /* HAVE_USB_MANAGER */ -+ - } - device_list_type; - -@@ -212,10 +223,19 @@ static xmlNode* testing_xml_next_tx_node = NULL; - static int libusb_timeout = 30 * 1000; /* 30 seconds */ - #endif /* HAVE_LIBUSB_LEGACY */ - -+#ifdef HAVE_USB_MANAGER -+static int usb_manager_timeout = 30 * 1000; /* 30 seconds */ -+#endif /* HAVE_USB_MANAGER */ -+ -+ - #ifdef HAVE_LIBUSB - static libusb_context *sanei_usb_ctx; - #endif /* HAVE_LIBUSB */ - -+#ifdef HAVE_USB_MANAGER -+static usb_manager_context *sanei_usb_ctx; -+#endif /* HAVE_USB_MANAGER */ -+ - #if defined (__APPLE__) - /* macOS won't configure several USB scanners (i.e. ScanSnap 300M) because their - * descriptors are vendor specific. As a result the device will get configured -@@ -299,7 +319,7 @@ print_buffer (const SANE_Byte * buffer, SANE_Int size) - } - } - --#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) -+#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) - static void - kernel_get_vendor_product (int fd, const char *name, int *vendorID, int *productID) - { -@@ -373,7 +393,7 @@ kernel_get_vendor_product (int fd, const char *name, int *vendorID, int *product - #endif /* defined (__linux__), defined(__BEOS__), ... */ - /* put more os-dependant stuff ... */ - } --#endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) */ -+#endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) */ - - /** - * store the given device in device list if it isn't already -@@ -405,6 +425,9 @@ store_device (device_list_type device) - #ifdef HAVE_LIBUSB - devices[i].lu_device = device.lu_device; - #endif -+#ifdef HAVE_USB_MANAGER -+ devices[i].usb_manager_device = device.usb_manager_device; -+#endif - - devices[i].missing=0; - DBG (3, "store_device: not storing device %s\n", device.devname); -@@ -497,6 +520,62 @@ sanei_libusb_strerror (int errcode) - } - #endif /* HAVE_LIBUSB */ - -+#ifdef HAVE_USB_MANAGER -+static char * -+sanei_usb_manager_strerror (int errcode) -+{ -+ /* Error codes & descriptions from the usb_manager documentation */ -+ -+ switch (errcode) -+ { -+ case USB_MANAGER_SUCCESS: -+ return "Success (no error)"; -+ -+ case USB_MANAGER_ERROR_IO: -+ return "Input/output error"; -+ -+ case USB_MANAGER_ERROR_INVALID_PARAM: -+ return "Invalid parameter"; -+ -+ case USB_MANAGER_ERROR_ACCESS: -+ return "Access denied (insufficient permissions)"; -+ -+ case USB_MANAGER_ERROR_NO_DEVICE: -+ return "No such device (it may have been disconnected)"; -+ -+ case USB_MANAGER_ERROR_NOT_FOUND: -+ return "Entity not found"; -+ -+ case USB_MANAGER_ERROR_BUSY: -+ return "Resource busy"; -+ -+ case USB_MANAGER_ERROR_TIMEOUT: -+ return "Operation timed out"; -+ -+ case USB_MANAGER_ERROR_OVERFLOW: -+ return "Overflow"; -+ -+ case USB_MANAGER_ERROR_PIPE: -+ return "Pipe error"; -+ -+ case USB_MANAGER_ERROR_INTERRUPTED: -+ return "System call interrupted (perhaps due to signal)"; -+ -+ case USB_MANAGER_ERROR_NO_MEM: -+ return "Insufficient memory"; -+ -+ case USB_MANAGER_ERROR_NOT_SUPPORTED: -+ return "Operation not supported or unimplemented on this platform"; -+ -+ case USB_MANAGER_ERROR_OTHER: -+ return "Other error"; -+ -+ default: -+ return "Unknown usb_manager error code"; -+ } -+} -+#endif /* HAVE_USB_MANAGER */ -+ - #if WITH_USB_RECORD_REPLAY - SANE_Status sanei_usb_testing_enable_replay(SANE_String_Const path, - int development_mode) -@@ -1380,9 +1459,9 @@ void sanei_usb_testing_record_message(SANE_String_Const message) - void - sanei_usb_init (void) - { --#ifdef HAVE_LIBUSB -+#if defined(HAVE_LIBUSB) || defined(HAVE_USB_MANAGER) - int ret; --#endif /* HAVE_LIBUSB */ -+#endif /* HAVE_LIBUSB || HAVE_USB_MANAGER */ - - DBG_INIT (); - #ifdef DBG_LEVEL -@@ -1451,7 +1530,22 @@ sanei_usb_init (void) - } - #endif /* HAVE_LIBUSB */ - --#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) -+#ifdef HAVE_USB_MANAGER -+ if (!sanei_usb_ctx) -+ { -+ DBG (4, "%s: initializing usb_manager\n", __func__); -+ ret = usb_manager_init (&sanei_usb_ctx); -+ if (ret < 0) -+ { -+ DBG (1, -+ "%s: failed to initialize usb_manager, error %d\n", __func__, -+ ret); -+ return; -+ } -+ } -+#endif /* HAVE_USB_MANAGER */ -+ -+#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) - DBG (4, "%s: SANE is built without support for libusb\n", __func__); - #endif - -@@ -1498,14 +1592,21 @@ int i; - devices[i].devname=NULL; - } - } --#ifdef HAVE_LIBUSB -+#if defined(HAVE_LIBUSB) - if (sanei_usb_ctx) - { - libusb_exit (sanei_usb_ctx); - /* reset libusb-1.0 context */ - sanei_usb_ctx=NULL; - } --#endif -+#elif defined(HAVE_USB_MANAGER) -+ if (sanei_usb_ctx) -+ { -+ usb_manager_exit (sanei_usb_ctx); -+ /* reset usb_manager context */ -+ sanei_usb_ctx=NULL; -+ } -+#endif /* HAVE_LIBUSB || HAVE_USB_MANAGER */ - /* reset device_number */ - device_number=0; - } -@@ -1588,7 +1689,7 @@ static void usbcall_scan_devices(void) - } - #endif /* HAVE_USBCALLS */ - --#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) -+#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) - /** scan for devices using kernel device. - * Check for devices using kernel device - */ -@@ -1687,7 +1788,7 @@ static void kernel_scan_devices(void) - closedir (dir); - } - } --#endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) */ -+#endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) */ - - #ifdef HAVE_LIBUSB_LEGACY - /** scan for devices using old libusb -@@ -1980,6 +2081,183 @@ static void libusb_scan_devices(void) - } - #endif /* HAVE_LIBUSB */ - -+#ifdef HAVE_USB_MANAGER -+/** scan for devices using usb_manager -+ * Check for devices using usb_manager -+ */ -+static void libusb_scan_devices(void) -+{ -+ device_list_type device; -+ SANE_Char devname[1024]; -+ usb_manager_device **devlist; -+ ssize_t ndev; -+ usb_manager_device *dev; -+ usb_manager_device_handle *hdl; -+ struct usb_manager_device_descriptor desc; -+ struct usb_manager_config_descriptor *config0; -+ unsigned short vid, pid; -+ unsigned char busno, address; -+ int config; -+ int interface; -+ int ret; -+ int i; -+ -+ DBG (4, "%s: Looking for usb_manager devices\n", __func__); -+ -+ ndev = usb_manager_get_device_list (sanei_usb_ctx, &devlist); -+ if (ndev < 0) -+ { -+ DBG (1, -+ "%s: failed to get usb_manager device list, error %d\n", __func__, -+ (int) ndev); -+ return; -+ } -+ -+ for (i = 0; i < ndev; i++) -+ { -+ SANE_Bool found = SANE_FALSE; -+ -+ dev = devlist[i]; -+ -+ busno = usb_manager_get_bus_number (dev); -+ address = usb_manager_get_device_address (dev); -+ -+ ret = usb_manager_get_device_descriptor (dev, &desc); -+ if (ret < 0) -+ { -+ DBG (1, -+ "%s: could not get device descriptor for device at %03d:%03d (err %d)\n", __func__, -+ busno, address, ret); -+ continue; -+ } -+ -+ vid = desc.idVendor; -+ pid = desc.idProduct; -+ -+ if ((vid == 0) || (pid == 0)) -+ { -+ DBG (5, -+ "%s: device 0x%04x/0x%04x at %03d:%03d looks like a root hub\n", __func__, -+ vid, pid, busno, address); -+ continue; -+ } -+ -+ ret = usb_manager_open (dev, &hdl); -+ if (ret < 0) -+ { -+ DBG (1, -+ "%s: skipping device 0x%04x/0x%04x at %03d:%03d: cannot open: %s\n", __func__, -+ vid, pid, busno, address, sanei_usb_manager_strerror (ret)); -+ -+ continue; -+ } -+ -+ ret = usb_manager_get_configuration (hdl, &config); -+ -+ usb_manager_close (hdl); -+ -+ if (ret < 0) -+ { -+ DBG (1, -+ "%s: could not get configuration for device 0x%04x/0x%04x at %03d:%03d (err %d)\n", __func__, -+ vid, pid, busno, address, ret); -+ continue; -+ } -+ -+#if !defined(SANEI_ALLOW_UNCONFIGURED_DEVICES) -+ if (config == 0) -+ { -+ DBG (1, -+ "%s: device 0x%04x/0x%04x at %03d:%03d is not configured\n", __func__, -+ vid, pid, busno, address); -+ continue; -+ } -+#endif -+ -+ ret = usb_manager_get_config_descriptor (dev, 0, &config0); -+ if (ret < 0) -+ { -+ DBG (1, -+ "%s: could not get config[0] descriptor for device 0x%04x/0x%04x at %03d:%03d (err %d)\n", __func__, -+ vid, pid, busno, address, ret); -+ continue; -+ } -+ -+ for (interface = 0; (interface < config0->bNumInterfaces) && !found; interface++) -+ { -+ switch (desc.bDeviceClass) -+ { -+ case USB_MANAGER_CLASS_VENDOR_SPEC: -+ found = SANE_TRUE; -+ break; -+ -+ case USB_MANAGER_CLASS_PER_INTERFACE: -+ if ((config0->interface[interface].num_altsetting == 0) -+ || !config0->interface[interface].altsetting) -+ { -+ DBG (1, "%s: device 0x%04x/0x%04x doesn't " -+ "have an altsetting for interface %d\n", __func__, -+ vid, pid, interface); -+ continue; -+ } -+ -+ switch (config0->interface[interface].altsetting[0].bInterfaceClass) -+ { -+ case USB_MANAGER_CLASS_VENDOR_SPEC: -+ case USB_MANAGER_CLASS_PER_INTERFACE: -+ case USB_MANAGER_CLASS_PTP: -+ case 16: /* data? */ -+ found = SANE_TRUE; -+ break; -+ } -+ break; -+ } -+ -+ if (!found) -+ DBG (5, -+ "%s: device 0x%04x/0x%04x, interface %d " -+ "doesn't look like a scanner (%d/%d)\n", __func__, -+ vid, pid, interface, desc.bDeviceClass, -+ (config0->interface[interface].num_altsetting != 0) -+ ? config0->interface[interface].altsetting[0].bInterfaceClass : -1); -+ } -+ -+ usb_manager_free_config_descriptor (config0); -+ -+ interface--; -+ -+ if (!found) -+ { -+ DBG (5, -+ "%s: device 0x%04x/0x%04x at %03d:%03d: no suitable interfaces\n", __func__, -+ vid, pid, busno, address); -+ continue; -+ } -+ -+ memset (&device, 0, sizeof (device)); -+ device.usb_manager_device = usb_manager_ref_device(dev); -+ snprintf (devname, sizeof (devname), "libusb:%03d:%03d", -+ busno, address); -+ device.devname = strdup (devname); -+ if (!device.devname) -+ return; -+ device.vendor = vid; -+ device.product = pid; -+ device.method = sanei_usb_method_libusb; -+ device.interface_nr = interface; -+ device.alt_setting = 0; -+ DBG (4, -+ "%s: found usb_manager device (0x%04x/0x%04x) interface " -+ "%d at %s\n", __func__, -+ vid, pid, interface, devname); -+ -+ store_device (device); -+ } -+ -+ usb_manager_free_device_list (devlist, 1); -+ -+} -+#endif /* HAVE_USB_MANAGER */ - - void - sanei_usb_scan_devices (void) -@@ -2009,11 +2287,11 @@ sanei_usb_scan_devices (void) - } - - /* Check for devices using the kernel scanner driver */ --#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) -+#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) - kernel_scan_devices(); - #endif - --#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) -+#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) || defined(HAVE_USB_MANAGER) - /* Check for devices using libusb (old or new)*/ - libusb_scan_devices(); - #endif -@@ -2223,7 +2501,7 @@ sanei_usb_set_endpoint (SANE_Int dn, SANE_Int ep_type, SANE_Int ep) - } - } - --#if HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USBCALLS || WITH_USB_RECORD_REPLAY -+#if HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USBCALLS || WITH_USB_RECORD_REPLAY || HAVE_USB_MANAGER - static const char* sanei_usb_transfer_type_desc(SANE_Int transfer_type) - { - switch (transfer_type) -@@ -2292,7 +2570,7 @@ static void sanei_usb_add_endpoint(device_list_type* device, - *ep_out = ep_address; - } - } --#endif // HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USBCALLS -+#endif // HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USBCALLS || HAVE_USB_MANAGER - - SANE_Int - sanei_usb_get_endpoint (SANE_Int dn, SANE_Int ep_type) -@@ -2815,43 +3093,261 @@ sanei_usb_open (SANE_String_Const devname, SANE_Int * dn) - - libusb_free_config_descriptor (config); - } -+#elif defined(HAVE_USB_MANAGER) /* usb_manager */ - --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -- DBG (1, "sanei_usb_open: can't open device `%s': " -- "libusb support missing\n", devname); -- return SANE_STATUS_UNSUPPORTED; --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -- } -- else if (devices[devcount].method == sanei_usb_method_scanner_driver) -- { --#ifdef FD_CLOEXEC -- long int flag; --#endif -- /* Using kernel scanner driver */ -- devices[devcount].fd = -1; --#ifdef HAVE_RESMGR -- devices[devcount].fd = rsm_open_device (devname, O_RDWR); --#endif -- if (devices[devcount].fd == -1) -- devices[devcount].fd = open (devname, O_RDWR); -- if (devices[devcount].fd < 0) -+ int config; -+ usb_manager_device *dev; -+ struct usb_manager_device_descriptor desc; -+ struct usb_manager_config_descriptor *config0; -+ int result, num; -+ int c, i, a; -+ -+ dev = devices[devcount].usb_manager_device; -+ -+ result = usb_manager_open (dev, &devices[devcount].usb_manager_handle); -+ if (result < 0) - { - SANE_Status status = SANE_STATUS_INVAL; - -- if (errno == EACCES) -- status = SANE_STATUS_ACCESS_DENIED; -- else if (errno == ENOENT) -+ DBG (1, "sanei_usb_open: can't open device `%s': %s\n", -+ devname, sanei_usb_manager_strerror (result)); -+ if (result == USB_MANAGER_ERROR_ACCESS) - { -- DBG (5, "sanei_usb_open: open of `%s' failed: %s\n", -- devname, strerror (errno)); -- return status; -+ DBG (1, "Make sure you run as root or set appropriate " -+ "permissions\n"); -+ status = SANE_STATUS_ACCESS_DENIED; -+ } -+ else if (result == USB_MANAGER_ERROR_BUSY) -+ { -+ DBG (1, "Maybe the kernel scanner driver claims the " -+ "scanner's interface?\n"); -+ status = SANE_STATUS_DEVICE_BUSY; -+ } -+ else if (result == USB_MANAGER_ERROR_NO_MEM) -+ { -+ status = SANE_STATUS_NO_MEM; - } -- DBG (1, "sanei_usb_open: open of `%s' failed: %s\n", -- devname, strerror (errno)); - return status; - } --#ifdef FD_CLOEXEC -- flag = fcntl (devices[devcount].fd, F_GETFD); -+ -+ result = usb_manager_get_configuration (devices[devcount].usb_manager_handle, &config); -+ if (result < 0) -+ { -+ DBG (1, -+ "sanei_usb_open: could not get configuration for device `%s' (err %d)\n", -+ devname, result); -+ return SANE_STATUS_INVAL; -+ } -+ -+#if !defined(SANEI_ALLOW_UNCONFIGURED_DEVICES) -+ if (config == 0) -+ { -+ DBG (1, "sanei_usb_open: device `%s' not configured?\n", devname); -+ return SANE_STATUS_INVAL; -+ } -+#endif -+ -+ result = usb_manager_get_device_descriptor (dev, &desc); -+ if (result < 0) -+ { -+ DBG (1, -+ "sanei_usb_open: could not get device descriptor for device `%s' (err %d)\n", -+ devname, result); -+ return SANE_STATUS_INVAL; -+ } -+ -+ result = usb_manager_get_config_descriptor (dev, 0, &config0); -+ if (result < 0) -+ { -+ DBG (1, -+ "sanei_usb_open: could not get config[0] descriptor for device `%s' (err %d)\n", -+ devname, result); -+ return SANE_STATUS_INVAL; -+ } -+ -+ /* Set the configuration */ -+ if (desc.bNumConfigurations > 1) -+ { -+ DBG (3, "sanei_usb_open: more than one " -+ "configuration (%d), choosing first config (%d)\n", -+ desc.bNumConfigurations, -+ config0->bConfigurationValue); -+ -+ result = 0; -+ if (config != config0->bConfigurationValue) -+ result = usb_manager_set_configuration (devices[devcount].usb_manager_handle, -+ config0->bConfigurationValue); -+ -+ if (result < 0) -+ { -+ SANE_Status status = SANE_STATUS_INVAL; -+ -+ DBG (1, "sanei_usb_open: usb_manager complained: %s\n", -+ sanei_usb_manager_strerror (result)); -+ if (result == USB_MANAGER_ERROR_ACCESS) -+ { -+ DBG (1, "Make sure you run as root or set appropriate " -+ "permissions\n"); -+ status = SANE_STATUS_ACCESS_DENIED; -+ } -+ else if (result == USB_MANAGER_ERROR_BUSY) -+ { -+ DBG (3, "Maybe the kernel scanner driver or usblp claims " -+ "the interface? Ignoring this error...\n"); -+ status = SANE_STATUS_GOOD; -+ } -+ -+ if (status != SANE_STATUS_GOOD) -+ { -+ usb_manager_close (devices[devcount].usb_manager_handle); -+ usb_manager_free_config_descriptor (config0); -+ return status; -+ } -+ } -+ } -+ usb_manager_free_config_descriptor (config0); -+ -+ /* Claim the interface */ -+ result = usb_manager_claim_interface (devices[devcount].usb_manager_handle, -+ devices[devcount].interface_nr); -+ if (result < 0) -+ { -+ SANE_Status status = SANE_STATUS_INVAL; -+ -+ DBG (1, "sanei_usb_open: usb_manager complained: %s\n", -+ sanei_usb_manager_strerror (result)); -+ if (result == USB_MANAGER_ERROR_ACCESS) -+ { -+ DBG (1, "Make sure you run as root or set appropriate " -+ "permissions\n"); -+ status = SANE_STATUS_ACCESS_DENIED; -+ } -+ else if (result == USB_MANAGER_ERROR_BUSY) -+ { -+ DBG (1, "Maybe the kernel scanner driver claims the " -+ "scanner's interface?\n"); -+ status = SANE_STATUS_DEVICE_BUSY; -+ } -+ -+ usb_manager_close (devices[devcount].usb_manager_handle); -+ return status; -+ } -+ -+ /* Loop through all of the configurations */ -+ for (c = 0; c < desc.bNumConfigurations; c++) -+ { -+ struct usb_manager_config_descriptor *config; -+ -+ result = usb_manager_get_config_descriptor (dev, c, &config); -+ if (result < 0) -+ { -+ DBG (1, -+ "sanei_usb_open: could not get config[%d] descriptor for device `%s' (err %d)\n", -+ c, devname, result); -+ continue; -+ } -+ -+ /* Loop through all of the interfaces */ -+ for (i = 0; i < config->bNumInterfaces; i++) -+ { -+ /* Loop through all of the alternate settings */ -+ for (a = 0; a < config->interface[i].num_altsetting; a++) -+ { -+ const struct usb_manager_interface_descriptor *interface; -+ -+ DBG (5, "sanei_usb_open: configuration nr: %d\n", c); -+ DBG (5, "sanei_usb_open: interface nr: %d\n", i); -+ DBG (5, "sanei_usb_open: alt_setting nr: %d\n", a); -+ -+ /* Start by interfaces found in sanei_usb_init */ -+ if (c == 0 && i != devices[devcount].interface_nr) -+ { -+ DBG (5, "sanei_usb_open: interface %d not detected as " -+ "a scanner by sanei_usb_init, ignoring.\n", i); -+ continue; -+ } -+ -+ interface = &config->interface[i].altsetting[a]; -+ -+ /* Now we look for usable endpoints */ -+ for (num = 0; num < interface->bNumEndpoints; num++) -+ { -+ const struct usb_manager_endpoint_descriptor *endpoint; -+ int direction, transfer_type, transfer_type_usb_manager; -+ -+ endpoint = &interface->endpoint[num]; -+ DBG (5, "sanei_usb_open: endpoint nr: %d\n", num); -+ -+ transfer_type_usb_manager = -+ endpoint->bmAttributes & USB_MANAGER_TRANSFER_TYPE_MASK; -+ direction = endpoint->bEndpointAddress & USB_MANAGER_ENDPOINT_DIR_MASK; -+ -+ // don't rely on USB_MANAGER_TRANSFER_TYPE_* mapping to -+ // USB_ENDPOINT_TYPE_* even though they'll most likely be -+ // the same -+ switch (transfer_type_usb_manager) -+ { -+ case USB_MANAGER_TRANSFER_TYPE_INTERRUPT: -+ transfer_type = USB_ENDPOINT_TYPE_INTERRUPT; -+ break; -+ case USB_MANAGER_TRANSFER_TYPE_BULK: -+ transfer_type = USB_ENDPOINT_TYPE_BULK; -+ break; -+ case USB_MANAGER_TRANSFER_TYPE_ISOCHRONOUS: -+ transfer_type = USB_MANAGER_TRANSFER_TYPE_ISOCHRONOUS; -+ break; -+ case USB_MANAGER_TRANSFER_TYPE_CONTROL: -+ transfer_type = USB_ENDPOINT_TYPE_CONTROL; -+ break; -+ -+ } -+ -+ sanei_usb_add_endpoint(&devices[devcount], -+ transfer_type, -+ endpoint->bEndpointAddress, -+ direction); -+ } -+ } -+ } -+ -+ usb_manager_free_config_descriptor (config); -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ -+ DBG (1, "sanei_usb_open: can't open device `%s': " -+ "libusb support missing\n", devname); -+ return SANE_STATUS_UNSUPPORTED; -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ -+ } -+ else if (devices[devcount].method == sanei_usb_method_scanner_driver) -+ { -+#ifdef FD_CLOEXEC -+ long int flag; -+#endif -+ /* Using kernel scanner driver */ -+ devices[devcount].fd = -1; -+#ifdef HAVE_RESMGR -+ devices[devcount].fd = rsm_open_device (devname, O_RDWR); -+#endif -+ if (devices[devcount].fd == -1) -+ devices[devcount].fd = open (devname, O_RDWR); -+ if (devices[devcount].fd < 0) -+ { -+ SANE_Status status = SANE_STATUS_INVAL; -+ -+ if (errno == EACCES) -+ status = SANE_STATUS_ACCESS_DENIED; -+ else if (errno == ENOENT) -+ { -+ DBG (5, "sanei_usb_open: open of `%s' failed: %s\n", -+ devname, strerror (errno)); -+ return status; -+ } -+ DBG (1, "sanei_usb_open: open of `%s' failed: %s\n", -+ devname, strerror (errno)); -+ return status; -+ } -+#ifdef FD_CLOEXEC -+ flag = fcntl (devices[devcount].fd, F_GETFD); - if (flag >= 0) - { - if (fcntl (devices[devcount].fd, F_SETFD, flag | FD_CLOEXEC) < 0) -@@ -3061,7 +3557,22 @@ sanei_usb_close (SANE_Int dn) - devices[dn].interface_nr); - libusb_close (devices[dn].lu_handle); - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ /* This call seems to be required by Linux xhci driver -+ * even though it should be a no-op. Without it, the -+ * host or driver does not reset it's data toggle bit. -+ * We intentionally ignore the return val */ -+ if (workaround) -+ { -+ sanei_usb_set_altinterface (dn, devices[dn].alt_setting); -+ } -+ -+ usb_manager_release_interface (devices[dn].usb_manager_handle, -+ devices[dn].interface_nr); -+ usb_manager_close (devices[dn].usb_manager_handle); -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - DBG (1, "sanei_usb_close: libusb support missing\n"); - #endif - devices[dn].open = SANE_FALSE; -@@ -3074,11 +3585,13 @@ sanei_usb_set_timeout (SANE_Int __sane_unused__ timeout) - if (testing_mode == sanei_usb_testing_mode_replay) - return; - --#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) -+#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) - libusb_timeout = timeout; -+#elif defined(HAVE_USB_MANAGER) -+ usb_manager_timeout = timeout; - #else - DBG (1, "sanei_usb_set_timeout: libusb support missing\n"); --#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ -+#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USB_MANAGER */ - } - - SANE_Status -@@ -3151,9 +3664,32 @@ sanei_usb_clear_halt (SANE_Int dn) - DBG (1, "sanei_usb_clear_halt: BULK_OUT ret=%d\n", ret); - return SANE_STATUS_INVAL; - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ int ret; -+ -+ /* This call seems to be required by Linux xhci driver -+ * even though it should be a no-op. Without it, the -+ * host or driver does not send the clear to the device. -+ * We intentionally ignore the return val */ -+ if (workaround) -+ { -+ sanei_usb_set_altinterface (dn, devices[dn].alt_setting); -+ } -+ -+ ret = usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].bulk_in_ep); -+ if (ret){ -+ DBG (1, "sanei_usb_clear_halt: BULK_IN ret=%d\n", ret); -+ return SANE_STATUS_INVAL; -+ } -+ -+ ret = usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].bulk_out_ep); -+ if (ret){ -+ DBG (1, "sanei_usb_clear_halt: BULK_OUT ret=%d\n", ret); -+ return SANE_STATUS_INVAL; -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - DBG (1, "sanei_usb_clear_halt: libusb support missing\n"); --#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ -+#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USB_MANAGER */ - - return SANE_STATUS_GOOD; - } -@@ -3181,10 +3717,18 @@ sanei_usb_reset (SANE_Int __sane_unused__ dn) - DBG (1, "sanei_usb_reset: ret=%d\n", ret); - return SANE_STATUS_INVAL; - } -+#elif defined(HAVE_USB_MANAGER) -+ int ret; - --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+ ret = usb_manager_reset_device (devices[dn].usb_manager_handle); -+ if (ret){ -+ DBG (1, "sanei_usb_reset: ret=%d\n", ret); -+ return SANE_STATUS_INVAL; -+ } -+ -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - DBG (1, "sanei_usb_reset: libusb support missing\n"); --#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ -+#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USB_MANAGER */ - - return SANE_STATUS_GOOD; - } -@@ -3428,7 +3972,36 @@ sanei_usb_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) - return SANE_STATUS_INVAL; - } - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ if (devices[dn].bulk_in_ep) -+ { -+ int ret, rsize; -+ ret = usb_manager_bulk_transfer (devices[dn].usb_manager_handle, -+ devices[dn].bulk_in_ep, buffer, -+ (int) *size, &rsize, -+ usb_manager_timeout); -+ -+ if (ret < 0) -+ { -+ DBG (1, "sanei_usb_read_bulk: read failed (still got %d bytes): %s\n", -+ rsize, sanei_usb_manager_strerror (ret)); -+ -+ read_size = -1; -+ } -+ else -+ { -+ read_size = rsize; -+ } -+ } -+ else -+ { -+ DBG (1, "sanei_usb_read_bulk: can't read without a bulk-in " -+ "endpoint\n"); -+ return SANE_STATUS_INVAL; -+ } -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - { - DBG (1, "sanei_usb_read_bulk: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; -@@ -3500,6 +4073,9 @@ sanei_usb_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) - #elif defined(HAVE_LIBUSB) - if (devices[dn].method == sanei_usb_method_libusb) - libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_in_ep); -+#elif defined(HAVE_USB_MANAGER) -+ if (devices[dn].method == sanei_usb_method_usb_manager) -+ usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].bulk_in_ep); - #endif - return SANE_STATUS_IO_ERROR; - } -@@ -3763,12 +4339,40 @@ sanei_usb_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) - return SANE_STATUS_INVAL; - } - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ if (devices[dn].bulk_out_ep) -+ { -+ int ret; -+ int trans_bytes; -+ ret = usb_manager_bulk_transfer (devices[dn].usb_manager_handle, -+ devices[dn].bulk_out_ep, -+ (unsigned char *) buffer, -+ (int) *size, &trans_bytes, -+ usb_manager_timeout); -+ if (ret < 0) -+ { -+ DBG (1, "sanei_usb_write_bulk: write failed: %s\n", -+ sanei_usb_manager_strerror (ret)); -+ -+ write_size = -1; -+ } -+ else -+ write_size = trans_bytes; -+ } -+ else -+ { -+ DBG (1, "sanei_usb_write_bulk: can't write without a bulk-out " -+ "endpoint\n"); -+ return SANE_STATUS_INVAL; -+ } -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - { - DBG (1, "sanei_usb_write_bulk: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; - } --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - else if (devices[dn].method == sanei_usb_method_usbcalls) - { - #ifdef HAVE_USBCALLS -@@ -3836,6 +4440,9 @@ sanei_usb_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) - #elif defined(HAVE_LIBUSB) - if (devices[dn].method == sanei_usb_method_libusb) - libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_out_ep); -+#elif defined(HAVE_USB_MANAGER) -+ if (devices[dn].method == sanei_usb_method_usb_manager) -+ usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].bulk_out_ep); - #endif - return SANE_STATUS_IO_ERROR; - } -@@ -4103,12 +4710,28 @@ sanei_usb_control_msg (SANE_Int dn, SANE_Int rtype, SANE_Int req, - if ((rtype & 0x80) && debug_level > 10) - print_buffer (data, len); - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB*/ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ int result; -+ -+ result = usb_manager_control_transfer (devices[dn].usb_manager_handle, rtype, req, -+ value, index, data, len, -+ usb_manager_timeout); -+ if (result < 0) -+ { -+ DBG (1, "sanei_usb_control_msg: libusb complained: %s\n", -+ sanei_usb_manager_strerror (result)); -+ return SANE_STATUS_INVAL; -+ } -+ if ((rtype & 0x80) && debug_level > 10) -+ print_buffer (data, len); -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ - { - DBG (1, "sanei_usb_control_msg: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; - } --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - else if (devices[dn].method == sanei_usb_method_usbcalls) - { - #ifdef HAVE_USBCALLS -@@ -4282,7 +4905,7 @@ SANE_Status - sanei_usb_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) - { - ssize_t read_size = 0; --#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) -+#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) || defined(HAVE_USB_MANAGER) - SANE_Bool stalled = SANE_FALSE; - #endif - -@@ -4363,12 +4986,37 @@ sanei_usb_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) - return SANE_STATUS_INVAL; - } - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ if (devices[dn].int_in_ep) -+ { -+ int ret; -+ int trans_bytes; -+ ret = usb_manager_interrupt_transfer (devices[dn].usb_manager_handle, -+ devices[dn].int_in_ep, -+ buffer, (int) *size, -+ &trans_bytes, usb_manager_timeout); -+ -+ if (ret < 0) -+ read_size = -1; -+ else -+ read_size = trans_bytes; -+ -+ stalled = (ret == USB_MANAGER_ERROR_PIPE); -+ } -+ else -+ { -+ DBG (1, "sanei_usb_read_int: can't read without an int " -+ "endpoint\n"); -+ return SANE_STATUS_INVAL; -+ } -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ - { - DBG (1, "sanei_usb_read_int: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; - } --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - else if (devices[dn].method == sanei_usb_method_usbcalls) - { - #ifdef HAVE_USBCALLS -@@ -4429,6 +5077,10 @@ sanei_usb_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) - if (devices[dn].method == sanei_usb_method_libusb) - if (stalled) - libusb_clear_halt (devices[dn].lu_handle, devices[dn].int_in_ep); -+#elif defined(HAVE_USB_MANAGER) -+ if (devices[dn].method == sanei_usb_method_usb_manager) -+ if (stalled) -+ usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].int_in_ep); - #endif - return SANE_STATUS_IO_ERROR; - } -@@ -4568,12 +5220,25 @@ sanei_usb_set_configuration (SANE_Int dn, SANE_Int configuration) - } - return SANE_STATUS_GOOD; - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ int result; -+ -+ result = usb_manager_set_configuration (devices[dn].usb_manager_handle, configuration); -+ if (result < 0) -+ { -+ DBG (1, "sanei_usb_set_configuration: libusb complained: %s\n", -+ sanei_usb_manager_strerror (result)); -+ return SANE_STATUS_INVAL; -+ } -+ return SANE_STATUS_GOOD; -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - { - DBG (1, "sanei_usb_set_configuration: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; - } --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - else - { - DBG (1, -@@ -4641,12 +5306,25 @@ sanei_usb_claim_interface (SANE_Int dn, SANE_Int interface_number) - } - return SANE_STATUS_GOOD; - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ int result; -+ -+ result = usb_manager_claim_interface (devices[dn].usb_manager_handle, interface_number); -+ if (result < 0) -+ { -+ DBG (1, "sanei_usb_claim_interface: libusb complained: %s\n", -+ sanei_usb_manager_strerror (result)); -+ return SANE_STATUS_INVAL; -+ } -+ return SANE_STATUS_GOOD; -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - { - DBG (1, "sanei_usb_claim_interface: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; - } --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ - else - { - DBG (1, "sanei_usb_claim_interface: access method %d not implemented\n", -@@ -4712,12 +5390,25 @@ sanei_usb_release_interface (SANE_Int dn, SANE_Int interface_number) - } - return SANE_STATUS_GOOD; - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ int result; -+ -+ result = usb_manager_release_interface (devices[dn].usb_manager_handle, interface_number); -+ if (result < 0) -+ { -+ DBG (1, "sanei_usb_release_interface: libusb complained: %s\n", -+ sanei_usb_manager_strerror (result)); -+ return SANE_STATUS_INVAL; -+ } -+ return SANE_STATUS_GOOD; -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - { - DBG (1, "sanei_usb_release_interface: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; - } --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - else - { - DBG (1, -@@ -4783,12 +5474,26 @@ sanei_usb_set_altinterface (SANE_Int dn, SANE_Int alternate) - } - return SANE_STATUS_GOOD; - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ int result; -+ -+ result = usb_manager_set_interface_alt_setting (devices[dn].usb_manager_handle, -+ devices[dn].interface_nr, alternate); -+ if (result < 0) -+ { -+ DBG (1, "sanei_usb_set_altinterface: usb_manager complained: %s\n", -+ sanei_usb_manager_strerror (result)); -+ return SANE_STATUS_INVAL; -+ } -+ return SANE_STATUS_GOOD; -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ - { - DBG (1, "sanei_set_altinterface: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; - } --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - else - { - DBG (1, -@@ -4949,12 +5654,36 @@ sanei_usb_get_descriptor( SANE_Int dn, - desc->dev_protocol = lu_desc.bDeviceProtocol; - desc->max_packet_size = lu_desc.bMaxPacketSize0; - } --#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#elif defined(HAVE_USB_MANAGER) -+ { -+ struct usb_manager_device_descriptor usb_manager_desc; -+ int ret; -+ -+ ret = usb_manager_get_device_descriptor (devices[dn].usb_manager_device, &usb_manager_desc); -+ if (ret < 0) -+ { -+ DBG (1, -+ "sanei_usb_get_descriptor: libusb error: %s\n", -+ sanei_usb_manager_strerror (ret)); -+ -+ return SANE_STATUS_INVAL; -+ } -+ -+ desc->desc_type = usb_manager_desc.bDescriptorType; -+ desc->bcd_usb = usb_manager_desc.bcdUSB; -+ desc->bcd_dev = usb_manager_desc.bcdDevice; -+ desc->dev_class = usb_manager_desc.bDeviceClass; -+ -+ desc->dev_sub_class = usb_manager_desc.bDeviceSubClass; -+ desc->dev_protocol = usb_manager_desc.bDeviceProtocol; -+ desc->max_packet_size = usb_manager_desc.bMaxPacketSize0; -+ } -+#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ - { - DBG (1, "sanei_usb_get_descriptor: libusb support missing\n"); - return SANE_STATUS_UNSUPPORTED; - } --#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ -+#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ - - if (testing_mode == sanei_usb_testing_mode_record) - { -diff --git a/sanei/usb_manager.cpp b/sanei/usb_manager.cpp -new file mode 100644 -index 000000000..62d7931e1 ---- /dev/null -+++ b/sanei/usb_manager.cpp -@@ -0,0 +1,572 @@ -+/* -+ * Copyright (c) 2024 Huawei Device 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 "iusb_srv.h" -+#include "securec.h" -+#include "string.h" -+#include "cstring" -+#include "usb_srv_client.h" -+#include "usb_manager.h" -+#include "v1_0/iusb_interface.h" -+#include "hilog/log.h" -+ -+#define SANE_LOG_TAG "sanekit" -+#define SANE_HILOG_INFO(...) ((void)HiLogPrint(LOG_APP, LOG_INFO, 0, "sanekit", __VA_ARGS__)) -+#define SANE_HILOG_ERROR(...) ((void)HiLogPrint(LOG_APP, LOG_ERROR, 0, "sanekit", __VA_ARGS__)) -+#define SANE_HILOG_DEBUG(...) ((void)HiLogPrint(LOG_APP, LOG_DEBUG, 0, "sanekit", __VA_ARGS__)) -+#define SANE_HILOG_WARN(...) ((void)HiLogPrint(LOG_APP, LOG_WARN, 0, "sanekit", __VA_ARGS__)) -+ -+using namespace OHOS::USB; -+ -+#define DELETE_AND_NULLPTR(ptr) \ -+ if ((ptr) != nullptr) { \ -+ delete (ptr); \ -+ (ptr) = nullptr; \ -+ } -+ -+#define DELETE_ARRAY_AND_NULLPTR(ptr) \ -+ if ((ptr) != nullptr) { \ -+ delete[] (ptr); \ -+ (ptr) = nullptr; \ -+ } -+ -+std::vector g_deviceList; -+static ssize_t g_deviceCount = 0; -+static uint8_t g_interfaceNumber = 0; -+static usb_manager_config_descriptor* g_deviceConfig = nullptr; -+ -+struct usb_manager_device_handle { -+ UsbDevice device; -+ USBDevicePipe pipe; -+}; -+ -+struct usb_manager_device { -+ UsbDevice device; -+}; -+ -+static void MemoryFreeDeviceList(usb_manager_device **list) -+{ -+ if (list == nullptr) { -+ return; -+ } -+ for (ssize_t i = 0 ; i < g_deviceCount; i++) { -+ DELETE_AND_NULLPTR(list[i]); -+ } -+ DELETE_ARRAY_AND_NULLPTR(list); -+ g_deviceCount = 0; -+} -+ -+int usb_manager_init(usb_manager_context **ctx) -+{ -+ SANE_HILOG_INFO("%s: begin", __func__); -+ if (ctx == nullptr) { -+ SANE_HILOG_ERROR("%s: ctx is a nullptr.", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ usb_manager_context *usbmanagerContext = new (std::nothrow) usb_manager_context(); -+ if (usbmanagerContext == nullptr) { -+ SANE_HILOG_ERROR("%s: Not enough memory.", __func__); -+ return USB_MANAGER_ERROR_NO_MEM; -+ } -+ *ctx = usbmanagerContext; -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+int usb_manager_exit(usb_manager_context *ctx) -+{ -+ SANE_HILOG_INFO("%s: begin", __func__); -+ if (ctx == nullptr) { -+ SANE_HILOG_ERROR("%s: ctx is a nullptr.", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ DELETE_AND_NULLPTR(ctx); -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+ssize_t usb_manager_get_device_list(usb_manager_context *ctx, usb_manager_device ***list) -+{ -+ SANE_HILOG_INFO("%s: begin", __func__); -+ if (ctx == nullptr || list == nullptr) { -+ SANE_HILOG_ERROR("%s: ctx or list is a nullptr.", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ g_deviceList.clear(); -+ auto ret = UsbSrvClient::GetInstance().GetDevices(g_deviceList); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_ERROR("%s: GetDevices exception.", __func__); -+ return USB_MANAGER_ERROR_IO; -+ } -+ g_deviceCount = static_cast(g_deviceList.size()); -+ SANE_HILOG_DEBUG("%s: deviceCount : %d", __func__, g_deviceCount); -+ if (g_deviceCount == 0) { -+ SANE_HILOG_DEBUG("%s: not found device.", __func__); -+ return USB_MANAGER_SUCCESS; -+ } -+ usb_manager_device** usbManagerDeviceList = new (std::nothrow) usb_manager_device* [g_deviceCount]; -+ if (usbManagerDeviceList == nullptr) { -+ SANE_HILOG_ERROR("%s: Not enough memory.", __func__); -+ return USB_MANAGER_ERROR_NO_MEM; -+ } -+ for (ssize_t i = 0; i < g_deviceCount; i++) { -+ usb_manager_device* usbDevice = new (std::nothrow) usb_manager_device(); -+ if (usbDevice == nullptr) { -+ MemoryFreeDeviceList(usbManagerDeviceList); -+ SANE_HILOG_ERROR("%s: Not enough memory.", __func__); -+ return USB_MANAGER_ERROR_NO_MEM; -+ } -+ usbDevice->device = g_deviceList[i]; -+ usbManagerDeviceList[i] = usbDevice; -+ } -+ *list = usbManagerDeviceList; -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return g_deviceCount; -+} -+ -+int usb_manager_get_bus_number(usb_manager_device *dev) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev == nullptr) { -+ SANE_HILOG_ERROR("%s: dev is a nullptr.", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return dev->device.GetBusNum(); -+} -+ -+int usb_manager_get_device_address(usb_manager_device *dev) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev == nullptr) { -+ SANE_HILOG_ERROR("%s: dev is a nullptr.", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return dev->device.GetDevAddr(); -+} -+ -+int usb_manager_get_device_descriptor(usb_manager_device *dev, usb_manager_device_descriptor *desc) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev == nullptr || desc == nullptr) { -+ SANE_HILOG_ERROR("%s: dev or desc is a nullptr.", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ UsbDevice &device = dev->device; -+ desc->idVendor = static_cast(device.GetVendorId()); -+ desc->idProduct = static_cast(device.GetProductId()); -+ desc->bDeviceClass = static_cast(device.GetClass()); -+ desc->bNumConfigurations = static_cast(device.GetConfigCount()); -+ desc->bDeviceSubClass = static_cast(device.GetSubclass()); -+ desc->bDeviceProtocol = static_cast(device.GetProtocol()); -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+int usb_manager_open(usb_manager_device *dev, usb_manager_device_handle **dev_handle) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev == nullptr || dev_handle == nullptr) { -+ SANE_HILOG_ERROR("%s: dev or dev_handle is a nullptr.", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ auto &usbSrvClient = UsbSrvClient::GetInstance(); -+ USBDevicePipe pipe; -+ UsbDevice &device = dev->device; -+ auto ret = usbSrvClient.RequestRight(device.GetName()); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_ERROR("request right failed ret=%{public}d", ret); -+ return USB_MANAGER_ERROR_ACCESS; -+ } -+ ret = usbSrvClient.OpenDevice(device, pipe); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_ERROR("open device failed ret=%{public}d", ret); -+ return USB_MANAGER_ERROR_ACCESS; -+ } -+ auto handle = new (std::nothrow) usb_manager_device_handle(); -+ if (handle == nullptr) { -+ SANE_HILOG_ERROR("%s: Not enough memory.", __func__); -+ return USB_MANAGER_ERROR_NO_MEM; -+ } -+ handle->device = device; -+ handle->pipe = pipe; -+ *dev_handle = handle; -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+void usb_manager_close(usb_manager_device_handle *dev_handle) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev_handle == nullptr) { -+ SANE_HILOG_ERROR("%s: dev_handle is a nullptr", __func__); -+ return; -+ } -+ auto &usbSrvClient = UsbSrvClient::GetInstance(); -+ usbSrvClient.Close(dev_handle->pipe); -+ DELETE_AND_NULLPTR(dev_handle); -+ SANE_HILOG_INFO("%s: end", __func__); -+ return; -+} -+ -+int usb_manager_get_configuration(usb_manager_device_handle *dev, int *config) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev == nullptr || config == nullptr) { -+ SANE_HILOG_ERROR("%s: dev or config is a nullptr", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ UsbDevice &device = dev->device; -+ auto configCount = device.GetConfigCount(); -+ SANE_HILOG_DEBUG("%s: configCount = %d", __func__, configCount); -+ *config = configCount; -+ return USB_MANAGER_SUCCESS; -+} -+ -+struct UsbEndPointDes { -+ uint8_t bmAttributes; -+ uint8_t bEndpointAddress; -+}; -+ -+struct UsbInterfaceAltDes{ -+ uint8_t bInterfaceClass; -+ std::vector endpointDes; -+}; -+ -+struct UsbAltInterface { -+ std::vector altDes; -+}; -+ -+void InterfaceConvert(std::vector &usbInterfaces, std::vector &usbAlt) { -+ auto memCopyInter = [&](size_t &i, UsbAltInterface &altInter) { -+ UsbInterfaceAltDes des; -+ des.bInterfaceClass = static_cast(usbInterfaces[i].GetClass()); -+ std::vector &endPoints = usbInterfaces[i].GetEndpoints(); -+ for (size_t j = 0; j < endPoints.size(); j++) { -+ UsbEndPointDes pointDes; -+ pointDes.bmAttributes = static_cast(endPoints[j].GetAttributes()); -+ pointDes.bEndpointAddress = static_cast(endPoints[j].GetAddress()); -+ des.endpointDes.push_back(pointDes); -+ } -+ altInter.altDes.push_back(des); -+ }; -+ for (size_t i = 0; i < usbInterfaces.size(); i++) { -+ UsbInterface& inter = usbInterfaces[i]; -+ if (inter.GetAlternateSetting() == 0) { -+ UsbAltInterface altInter; -+ memCopyInter(i, altInter); -+ usbAlt.push_back(altInter); -+ } else { -+ int id = usbInterfaces[i].GetId(); -+ UsbAltInterface &altInter = usbAlt[id]; -+ memCopyInter(i, altInter); -+ } -+ } -+} -+ -+int usb_manager_get_config_descriptor(usb_manager_device *dev, uint8_t config_index, -+ usb_manager_config_descriptor **config) -+{ -+ SANE_HILOG_INFO("%s: begin", __func__); -+ if (dev == nullptr || config == nullptr) { -+ SANE_HILOG_ERROR("%s: dev or config is a nullptr", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ UsbDevice &device = dev->device; -+ std::vector &configs = device.GetConfigs(); -+ if (config_index >= configs.size()) { -+ SANE_HILOG_ERROR("%s: config_index(%u) is invalid.", __func__, config_index); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ USBConfig &usbConfig = configs[config_index]; -+ SANE_HILOG_DEBUG("%s: config[%u] = %s", __func__, config_index, usbConfig.getJsonString().c_str()); -+ usb_manager_config_descriptor* retConfig = new (std::nothrow) usb_manager_config_descriptor(); -+ if (retConfig == nullptr) { -+ SANE_HILOG_ERROR("%s: Not enough memory.", __func__); -+ return USB_MANAGER_ERROR_NO_MEM; -+ } -+ std::vector &usbInterfaces = usbConfig.GetInterfaces(); -+ std::vector usbAlt; -+ InterfaceConvert(usbInterfaces, usbAlt); -+ size_t bNumInterfaces = usbAlt.size(); -+ retConfig->bNumInterfaces = static_cast(bNumInterfaces); -+ retConfig->bConfigurationValue = static_cast(usbConfig.GetId()); -+ auto retInterface = new (std::nothrow) usb_manager_interface[bNumInterfaces]; -+ if (retInterface == nullptr) { -+ SANE_HILOG_ERROR("%s: Not enough memory.", __func__); -+ return USB_MANAGER_ERROR_NO_MEM; -+ } -+ for (int i = 0; i < bNumInterfaces; i++) { -+ size_t altSet = usbAlt[i].altDes.size(); -+ auto retAltsetting = new (std::nothrow) usb_manager_interface_descriptor[altSet]; -+ if (retAltsetting == nullptr) { -+ SANE_HILOG_ERROR("%s: Not enough memory.", __func__); -+ return USB_MANAGER_ERROR_NO_MEM; -+ } -+ for (size_t j = 0; j < altSet; j++) { -+ retAltsetting[j].bInterfaceClass = usbAlt[i].altDes[j].bInterfaceClass; -+ size_t endPointsNum = usbAlt[i].altDes[j].endpointDes.size(); -+ retAltsetting[j].bNumEndpoints = endPointsNum; -+ retAltsetting[j].endpoint = new usb_manager_endpoint_descriptor[endPointsNum]; -+ for (int k = 0 ; k < endPointsNum; k++) { -+ uint8_t bmAttr = usbAlt[i].altDes[j].endpointDes[k].bmAttributes; -+ uint8_t bEndpointAddress = usbAlt[i].altDes[j].endpointDes[k].bEndpointAddress; -+ retAltsetting[j].endpoint[k].bmAttributes = bmAttr; -+ retAltsetting[j].endpoint[k].bEndpointAddress = bEndpointAddress; -+ } -+ } -+ retInterface[i].altsetting = retAltsetting; -+ retInterface[i].num_altsetting = static_cast(altSet); -+ } -+ retConfig->interface = retInterface; -+ *config = retConfig; -+ g_deviceConfig = retConfig; -+ SANE_HILOG_INFO("%s: end", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+void usb_manager_free_config_descriptor(usb_manager_config_descriptor *config) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (config == nullptr) { -+ SANE_HILOG_ERROR("%s: config is a nullptr", __func__); -+ return; -+ } -+ usb_manager_interface *interface = config->interface; -+ // for each interface -+ for (uint8_t i = 0; i < config->bNumInterfaces; i++) { -+ usb_manager_interface *interfacei = interface + i; -+ if (interfacei == nullptr) { -+ break; -+ } -+ usb_manager_interface_descriptor *altsetting = interfacei->altsetting; -+ // for each altsetting interface -+ for (int j = 0; j < interfacei->num_altsetting; i++) { -+ usb_manager_interface_descriptor *altsettingj = altsetting + j; -+ if (altsettingj == nullptr) { -+ break; -+ } -+ DELETE_ARRAY_AND_NULLPTR(altsettingj->endpoint) -+ } -+ DELETE_ARRAY_AND_NULLPTR(interfacei->altsetting); -+ } -+ DELETE_ARRAY_AND_NULLPTR(interface); -+ DELETE_AND_NULLPTR(config); -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return; -+} -+ -+void usb_manager_free_device_list(usb_manager_device **list, int unref_devices) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (list == nullptr) { -+ SANE_HILOG_ERROR("%s: list is a nullptr", __func__); -+ return; -+ } -+ MemoryFreeDeviceList(list); -+ SANE_HILOG_INFO("%s: end successful", __func__); -+} -+ -+int usb_manager_set_configuration(usb_manager_device_handle *dev_handle, int configuration) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev_handle == nullptr) { -+ SANE_HILOG_ERROR("%s: dev_handle is a nullptr", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ UsbDevice &device = dev_handle->device; -+ USBDevicePipe pip; -+ pip.SetBusNum(device.GetBusNum()); -+ pip.SetDevAddr(device.GetDevAddr()); -+ USBConfig config; -+ config.SetId(configuration); -+ auto ret = UsbSrvClient::GetInstance().SetConfiguration(pip, config); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_ERROR("SetConfiguration failed ret=%{public}d", ret); -+ return USB_MANAGER_ERROR_IO; -+ } -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+int usb_manager_claim_interface(usb_manager_device_handle *dev_handle, int interface_number) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev_handle == nullptr) { -+ SANE_HILOG_ERROR("%s: dev_handle is a nullptr", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ auto &usbSrvClient = UsbSrvClient::GetInstance(); -+ UsbInterface interface; -+ interface.SetId(interface_number); -+ auto ret = usbSrvClient.ClaimInterface(dev_handle->pipe, interface, true); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_ERROR("ClaimInterface failed ret=%{public}d", ret); -+ return USB_MANAGER_ERROR_IO; -+ } -+ g_interfaceNumber = interface_number; -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+int usb_manager_release_interface(usb_manager_device_handle *dev_handle, int interface_number) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev_handle == nullptr) { -+ SANE_HILOG_ERROR("%s: dev_handle is a nullptr", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ auto &usbSrvClient = UsbSrvClient::GetInstance(); -+ USBDevicePipe &pipe = dev_handle->pipe; -+ SANE_HILOG_DEBUG("%s: interface_number : %d", __func__, interface_number); -+ UsbInterface interface; -+ interface.SetId(interface_number); -+ auto ret = usbSrvClient.ReleaseInterface(pipe, interface); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_ERROR("ReleaseInterface failed ret=%{public}d", ret); -+ return USB_MANAGER_ERROR_IO; -+ } -+ g_interfaceNumber = 0; -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+int usb_manager_bulk_transfer(usb_manager_device_handle *dev_handle, unsigned char endpoint, -+ unsigned char *data, int length, int *transferred, unsigned int timeout) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev_handle == nullptr || data == nullptr || length == 0 || transferred == nullptr) { -+ SANE_HILOG_ERROR("%s: Invalid input parameter.", __func__); -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ USBDevicePipe &pipe = dev_handle->pipe; -+ USBEndpoint usbEndpoint; -+ usbEndpoint.SetInterfaceId(g_interfaceNumber); -+ usbEndpoint.SetAddr(endpoint); -+ auto &usbSrvClient = UsbSrvClient::GetInstance(); -+ if (endpoint & USB_MANAGER_ENDPOINT_IN) { -+ // read -+ std::vector bufferData(length); -+ auto ret = usbSrvClient.BulkTransfer(pipe, usbEndpoint, bufferData, timeout); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_INFO("%s: error", __func__); -+ return USB_MANAGER_ERROR_IO; -+ } -+ for (int i = 0; i < length; i++) { -+ data[i] = bufferData[i]; -+ } -+ } else { -+ // write -+ std::vector bufferData(length); -+ for (int i = 0; i < length; i++) { -+ bufferData[i] = data[i]; -+ } -+ auto ret = usbSrvClient.BulkTransfer(pipe, usbEndpoint, bufferData, timeout); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_INFO("%s: error", __func__); -+ return USB_MANAGER_ERROR_IO; -+ } -+ } -+ *transferred = length; -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+int usb_manager_control_transfer(usb_manager_device_handle *dev_handle, uint8_t request_type, -+ uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, -+ unsigned int timeout) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev_handle == nullptr || data == nullptr || wLength == 0) { -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ USBDevicePipe &pipe = dev_handle->pipe; -+ OHOS::HDI::Usb::V1_0::UsbCtrlTransfer ctrl; -+ ctrl.requestType = static_cast(request_type); -+ ctrl.requestCmd = static_cast(bRequest); -+ ctrl.value = static_cast(wValue); -+ ctrl.index = static_cast(wIndex); -+ ctrl.timeout = static_cast(timeout); -+ -+ auto &usbSrvClient = UsbSrvClient::GetInstance(); -+ std::vector bufferData; -+ for (uint16_t i = 0; i < wLength; i++) { -+ bufferData[i] = data[i]; -+ } -+ auto ret = usbSrvClient.ControlTransfer(pipe, ctrl, bufferData); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_ERROR("ControlTransfer failed ret=%{public}d", ret); -+ return USB_MANAGER_ERROR_IO; -+ } -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+int usb_manager_set_interface_alt_setting(usb_manager_device_handle *dev_handle, int interface_number, -+ int alternate_setting) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ if (dev_handle == nullptr) { -+ return USB_MANAGER_ERROR_INVALID_PARAM; -+ } -+ auto &usbSrvClient = UsbSrvClient::GetInstance(); -+ USBDevicePipe pipe = dev_handle->pipe; -+ UsbInterface interface; -+ interface.SetId(interface_number); -+ interface.SetAlternateSetting(alternate_setting); -+ auto ret = usbSrvClient.SetInterface(pipe, interface); -+ if (ret != USB_MANAGER_SUCCESS) { -+ SANE_HILOG_ERROR("SetInterface failed ret=%{public}d", ret); -+ return USB_MANAGER_ERROR_IO; -+ } -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+// stub -+int usb_manager_interrupt_transfer(usb_manager_device_handle *dev_handle, unsigned char endpoint, -+ unsigned char *data, int length, int *actual_length, unsigned int timeout) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+// stub -+usb_manager_device * usb_manager_ref_device(usb_manager_device *dev) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return nullptr; -+} -+ -+// stub -+int usb_manager_clear_halt(usb_manager_device_handle *dev_handle, unsigned char endpoint) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -+ -+// stub -+int usb_manager_reset_device(usb_manager_device_handle *dev_handle) -+{ -+ SANE_HILOG_INFO("%s: start", __func__); -+ SANE_HILOG_INFO("%s: end successful", __func__); -+ return USB_MANAGER_SUCCESS; -+} -\ No newline at end of file --- -2.34.1 - diff --git a/sanei/sanei_usb.c b/sanei/sanei_usb.c index 022f6fab9..66dbdb730 100644 --- a/sanei/sanei_usb.c +++ b/sanei/sanei_usb.c @@ -84,6 +84,10 @@ #include #endif /* HAVE_LIBUSB */ +#ifdef HAVE_USB_MANAGER +#include "usb_manager.h" +#endif /* HAVE_USB_MANAGER */ + #ifdef HAVE_USBCALLS #include #include @@ -129,7 +133,9 @@ typedef enum (Linux, BSD) */ sanei_usb_method_libusb, - sanei_usb_method_usbcalls + sanei_usb_method_usbcalls, + + sanei_usb_method_usb_manager } sanei_usb_access_method_type; @@ -160,6 +166,11 @@ typedef struct libusb_device *lu_device; libusb_device_handle *lu_handle; #endif /* HAVE_LIBUSB */ +#ifdef HAVE_USB_MANAGER + usb_manager_device *usb_manager_device; + usb_manager_device_handle *usb_manager_handle; +#endif /* HAVE_USB_MANAGER */ + } device_list_type; @@ -212,10 +223,19 @@ static xmlNode* testing_xml_next_tx_node = NULL; static int libusb_timeout = 30 * 1000; /* 30 seconds */ #endif /* HAVE_LIBUSB_LEGACY */ +#ifdef HAVE_USB_MANAGER +static int usb_manager_timeout = 30 * 1000; /* 30 seconds */ +#endif /* HAVE_USB_MANAGER */ + + #ifdef HAVE_LIBUSB static libusb_context *sanei_usb_ctx; #endif /* HAVE_LIBUSB */ +#ifdef HAVE_USB_MANAGER +static usb_manager_context *sanei_usb_ctx; +#endif /* HAVE_USB_MANAGER */ + #if defined (__APPLE__) /* macOS won't configure several USB scanners (i.e. ScanSnap 300M) because their * descriptors are vendor specific. As a result the device will get configured @@ -299,7 +319,7 @@ print_buffer (const SANE_Byte * buffer, SANE_Int size) } } -#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) +#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) static void kernel_get_vendor_product (int fd, const char *name, int *vendorID, int *productID) { @@ -373,7 +393,7 @@ kernel_get_vendor_product (int fd, const char *name, int *vendorID, int *product #endif /* defined (__linux__), defined(__BEOS__), ... */ /* put more os-dependant stuff ... */ } -#endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) */ +#endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) */ /** * store the given device in device list if it isn't already @@ -405,6 +425,9 @@ store_device (device_list_type device) #ifdef HAVE_LIBUSB devices[i].lu_device = device.lu_device; #endif +#ifdef HAVE_USB_MANAGER + devices[i].usb_manager_device = device.usb_manager_device; +#endif devices[i].missing=0; DBG (3, "store_device: not storing device %s\n", device.devname); @@ -497,6 +520,62 @@ sanei_libusb_strerror (int errcode) } #endif /* HAVE_LIBUSB */ +#ifdef HAVE_USB_MANAGER +static char * +sanei_usb_manager_strerror (int errcode) +{ + /* Error codes & descriptions from the usb_manager documentation */ + + switch (errcode) + { + case USB_MANAGER_SUCCESS: + return "Success (no error)"; + + case USB_MANAGER_ERROR_IO: + return "Input/output error"; + + case USB_MANAGER_ERROR_INVALID_PARAM: + return "Invalid parameter"; + + case USB_MANAGER_ERROR_ACCESS: + return "Access denied (insufficient permissions)"; + + case USB_MANAGER_ERROR_NO_DEVICE: + return "No such device (it may have been disconnected)"; + + case USB_MANAGER_ERROR_NOT_FOUND: + return "Entity not found"; + + case USB_MANAGER_ERROR_BUSY: + return "Resource busy"; + + case USB_MANAGER_ERROR_TIMEOUT: + return "Operation timed out"; + + case USB_MANAGER_ERROR_OVERFLOW: + return "Overflow"; + + case USB_MANAGER_ERROR_PIPE: + return "Pipe error"; + + case USB_MANAGER_ERROR_INTERRUPTED: + return "System call interrupted (perhaps due to signal)"; + + case USB_MANAGER_ERROR_NO_MEM: + return "Insufficient memory"; + + case USB_MANAGER_ERROR_NOT_SUPPORTED: + return "Operation not supported or unimplemented on this platform"; + + case USB_MANAGER_ERROR_OTHER: + return "Other error"; + + default: + return "Unknown usb_manager error code"; + } +} +#endif /* HAVE_USB_MANAGER */ + #if WITH_USB_RECORD_REPLAY SANE_Status sanei_usb_testing_enable_replay(SANE_String_Const path, int development_mode) @@ -1380,9 +1459,9 @@ void sanei_usb_testing_record_message(SANE_String_Const message) void sanei_usb_init (void) { -#ifdef HAVE_LIBUSB +#if defined(HAVE_LIBUSB) || defined(HAVE_USB_MANAGER) int ret; -#endif /* HAVE_LIBUSB */ +#endif /* HAVE_LIBUSB || HAVE_USB_MANAGER */ DBG_INIT (); #ifdef DBG_LEVEL @@ -1451,7 +1530,22 @@ sanei_usb_init (void) } #endif /* HAVE_LIBUSB */ -#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) +#ifdef HAVE_USB_MANAGER + if (!sanei_usb_ctx) + { + DBG (4, "%s: initializing usb_manager\n", __func__); + ret = usb_manager_init (&sanei_usb_ctx); + if (ret < 0) + { + DBG (1, + "%s: failed to initialize usb_manager, error %d\n", __func__, + ret); + return; + } + } +#endif /* HAVE_USB_MANAGER */ + +#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) DBG (4, "%s: SANE is built without support for libusb\n", __func__); #endif @@ -1498,14 +1592,21 @@ int i; devices[i].devname=NULL; } } -#ifdef HAVE_LIBUSB +#if defined(HAVE_LIBUSB) if (sanei_usb_ctx) { libusb_exit (sanei_usb_ctx); /* reset libusb-1.0 context */ sanei_usb_ctx=NULL; } -#endif +#elif defined(HAVE_USB_MANAGER) + if (sanei_usb_ctx) + { + usb_manager_exit (sanei_usb_ctx); + /* reset usb_manager context */ + sanei_usb_ctx=NULL; + } +#endif /* HAVE_LIBUSB || HAVE_USB_MANAGER */ /* reset device_number */ device_number=0; } @@ -1588,7 +1689,7 @@ static void usbcall_scan_devices(void) } #endif /* HAVE_USBCALLS */ -#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) +#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) /** scan for devices using kernel device. * Check for devices using kernel device */ @@ -1687,7 +1788,7 @@ static void kernel_scan_devices(void) closedir (dir); } } -#endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) */ +#endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) */ #ifdef HAVE_LIBUSB_LEGACY /** scan for devices using old libusb @@ -1980,6 +2081,183 @@ static void libusb_scan_devices(void) } #endif /* HAVE_LIBUSB */ +#ifdef HAVE_USB_MANAGER +/** scan for devices using usb_manager + * Check for devices using usb_manager + */ +static void libusb_scan_devices(void) +{ + device_list_type device; + SANE_Char devname[1024]; + usb_manager_device **devlist; + ssize_t ndev; + usb_manager_device *dev; + usb_manager_device_handle *hdl; + struct usb_manager_device_descriptor desc; + struct usb_manager_config_descriptor *config0; + unsigned short vid, pid; + unsigned char busno, address; + int config; + int interface; + int ret; + int i; + + DBG (4, "%s: Looking for usb_manager devices\n", __func__); + + ndev = usb_manager_get_device_list (sanei_usb_ctx, &devlist); + if (ndev < 0) + { + DBG (1, + "%s: failed to get usb_manager device list, error %d\n", __func__, + (int) ndev); + return; + } + + for (i = 0; i < ndev; i++) + { + SANE_Bool found = SANE_FALSE; + + dev = devlist[i]; + + busno = usb_manager_get_bus_number (dev); + address = usb_manager_get_device_address (dev); + + ret = usb_manager_get_device_descriptor (dev, &desc); + if (ret < 0) + { + DBG (1, + "%s: could not get device descriptor for device at %03d:%03d (err %d)\n", __func__, + busno, address, ret); + continue; + } + + vid = desc.idVendor; + pid = desc.idProduct; + + if ((vid == 0) || (pid == 0)) + { + DBG (5, + "%s: device 0x%04x/0x%04x at %03d:%03d looks like a root hub\n", __func__, + vid, pid, busno, address); + continue; + } + + ret = usb_manager_open (dev, &hdl); + if (ret < 0) + { + DBG (1, + "%s: skipping device 0x%04x/0x%04x at %03d:%03d: cannot open: %s\n", __func__, + vid, pid, busno, address, sanei_usb_manager_strerror (ret)); + + continue; + } + + ret = usb_manager_get_configuration (hdl, &config); + + usb_manager_close (hdl); + + if (ret < 0) + { + DBG (1, + "%s: could not get configuration for device 0x%04x/0x%04x at %03d:%03d (err %d)\n", __func__, + vid, pid, busno, address, ret); + continue; + } + +#if !defined(SANEI_ALLOW_UNCONFIGURED_DEVICES) + if (config == 0) + { + DBG (1, + "%s: device 0x%04x/0x%04x at %03d:%03d is not configured\n", __func__, + vid, pid, busno, address); + continue; + } +#endif + + ret = usb_manager_get_config_descriptor (dev, 0, &config0); + if (ret < 0) + { + DBG (1, + "%s: could not get config[0] descriptor for device 0x%04x/0x%04x at %03d:%03d (err %d)\n", __func__, + vid, pid, busno, address, ret); + continue; + } + + for (interface = 0; (interface < config0->bNumInterfaces) && !found; interface++) + { + switch (desc.bDeviceClass) + { + case USB_MANAGER_CLASS_VENDOR_SPEC: + found = SANE_TRUE; + break; + + case USB_MANAGER_CLASS_PER_INTERFACE: + if ((config0->interface[interface].num_altsetting == 0) + || !config0->interface[interface].altsetting) + { + DBG (1, "%s: device 0x%04x/0x%04x doesn't " + "have an altsetting for interface %d\n", __func__, + vid, pid, interface); + continue; + } + + switch (config0->interface[interface].altsetting[0].bInterfaceClass) + { + case USB_MANAGER_CLASS_VENDOR_SPEC: + case USB_MANAGER_CLASS_PER_INTERFACE: + case USB_MANAGER_CLASS_PTP: + case 16: /* data? */ + found = SANE_TRUE; + break; + } + break; + } + + if (!found) + DBG (5, + "%s: device 0x%04x/0x%04x, interface %d " + "doesn't look like a scanner (%d/%d)\n", __func__, + vid, pid, interface, desc.bDeviceClass, + (config0->interface[interface].num_altsetting != 0) + ? config0->interface[interface].altsetting[0].bInterfaceClass : -1); + } + + usb_manager_free_config_descriptor (config0); + + interface--; + + if (!found) + { + DBG (5, + "%s: device 0x%04x/0x%04x at %03d:%03d: no suitable interfaces\n", __func__, + vid, pid, busno, address); + continue; + } + + memset (&device, 0, sizeof (device)); + device.usb_manager_device = usb_manager_ref_device(dev); + snprintf (devname, sizeof (devname), "libusb:%03d:%03d", + busno, address); + device.devname = strdup (devname); + if (!device.devname) + return; + device.vendor = vid; + device.product = pid; + device.method = sanei_usb_method_libusb; + device.interface_nr = interface; + device.alt_setting = 0; + DBG (4, + "%s: found usb_manager device (0x%04x/0x%04x) interface " + "%d at %s\n", __func__, + vid, pid, interface, devname); + + store_device (device); + } + + usb_manager_free_device_list (devlist, 1); + +} +#endif /* HAVE_USB_MANAGER */ void sanei_usb_scan_devices (void) @@ -2009,11 +2287,11 @@ sanei_usb_scan_devices (void) } /* Check for devices using the kernel scanner driver */ -#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) +#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USB_MANAGER) kernel_scan_devices(); #endif -#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) || defined(HAVE_USB_MANAGER) /* Check for devices using libusb (old or new)*/ libusb_scan_devices(); #endif @@ -2223,7 +2501,7 @@ sanei_usb_set_endpoint (SANE_Int dn, SANE_Int ep_type, SANE_Int ep) } } -#if HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USBCALLS || WITH_USB_RECORD_REPLAY +#if HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USBCALLS || WITH_USB_RECORD_REPLAY || HAVE_USB_MANAGER static const char* sanei_usb_transfer_type_desc(SANE_Int transfer_type) { switch (transfer_type) @@ -2292,7 +2570,7 @@ static void sanei_usb_add_endpoint(device_list_type* device, *ep_out = ep_address; } } -#endif // HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USBCALLS +#endif // HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USBCALLS || HAVE_USB_MANAGER SANE_Int sanei_usb_get_endpoint (SANE_Int dn, SANE_Int ep_type) @@ -2815,43 +3093,261 @@ sanei_usb_open (SANE_String_Const devname, SANE_Int * dn) libusb_free_config_descriptor (config); } +#elif defined(HAVE_USB_MANAGER) /* usb_manager */ -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ - DBG (1, "sanei_usb_open: can't open device `%s': " - "libusb support missing\n", devname); - return SANE_STATUS_UNSUPPORTED; -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ - } - else if (devices[devcount].method == sanei_usb_method_scanner_driver) - { -#ifdef FD_CLOEXEC - long int flag; -#endif - /* Using kernel scanner driver */ - devices[devcount].fd = -1; -#ifdef HAVE_RESMGR - devices[devcount].fd = rsm_open_device (devname, O_RDWR); -#endif - if (devices[devcount].fd == -1) - devices[devcount].fd = open (devname, O_RDWR); - if (devices[devcount].fd < 0) + int config; + usb_manager_device *dev; + struct usb_manager_device_descriptor desc; + struct usb_manager_config_descriptor *config0; + int result, num; + int c, i, a; + + dev = devices[devcount].usb_manager_device; + + result = usb_manager_open (dev, &devices[devcount].usb_manager_handle); + if (result < 0) { SANE_Status status = SANE_STATUS_INVAL; - if (errno == EACCES) - status = SANE_STATUS_ACCESS_DENIED; - else if (errno == ENOENT) + DBG (1, "sanei_usb_open: can't open device `%s': %s\n", + devname, sanei_usb_manager_strerror (result)); + if (result == USB_MANAGER_ERROR_ACCESS) { - DBG (5, "sanei_usb_open: open of `%s' failed: %s\n", - devname, strerror (errno)); - return status; + DBG (1, "Make sure you run as root or set appropriate " + "permissions\n"); + status = SANE_STATUS_ACCESS_DENIED; + } + else if (result == USB_MANAGER_ERROR_BUSY) + { + DBG (1, "Maybe the kernel scanner driver claims the " + "scanner's interface?\n"); + status = SANE_STATUS_DEVICE_BUSY; + } + else if (result == USB_MANAGER_ERROR_NO_MEM) + { + status = SANE_STATUS_NO_MEM; } - DBG (1, "sanei_usb_open: open of `%s' failed: %s\n", - devname, strerror (errno)); return status; } -#ifdef FD_CLOEXEC - flag = fcntl (devices[devcount].fd, F_GETFD); + + result = usb_manager_get_configuration (devices[devcount].usb_manager_handle, &config); + if (result < 0) + { + DBG (1, + "sanei_usb_open: could not get configuration for device `%s' (err %d)\n", + devname, result); + return SANE_STATUS_INVAL; + } + +#if !defined(SANEI_ALLOW_UNCONFIGURED_DEVICES) + if (config == 0) + { + DBG (1, "sanei_usb_open: device `%s' not configured?\n", devname); + return SANE_STATUS_INVAL; + } +#endif + + result = usb_manager_get_device_descriptor (dev, &desc); + if (result < 0) + { + DBG (1, + "sanei_usb_open: could not get device descriptor for device `%s' (err %d)\n", + devname, result); + return SANE_STATUS_INVAL; + } + + result = usb_manager_get_config_descriptor (dev, 0, &config0); + if (result < 0) + { + DBG (1, + "sanei_usb_open: could not get config[0] descriptor for device `%s' (err %d)\n", + devname, result); + return SANE_STATUS_INVAL; + } + + /* Set the configuration */ + if (desc.bNumConfigurations > 1) + { + DBG (3, "sanei_usb_open: more than one " + "configuration (%d), choosing first config (%d)\n", + desc.bNumConfigurations, + config0->bConfigurationValue); + + result = 0; + if (config != config0->bConfigurationValue) + result = usb_manager_set_configuration (devices[devcount].usb_manager_handle, + config0->bConfigurationValue); + + if (result < 0) + { + SANE_Status status = SANE_STATUS_INVAL; + + DBG (1, "sanei_usb_open: usb_manager complained: %s\n", + sanei_usb_manager_strerror (result)); + if (result == USB_MANAGER_ERROR_ACCESS) + { + DBG (1, "Make sure you run as root or set appropriate " + "permissions\n"); + status = SANE_STATUS_ACCESS_DENIED; + } + else if (result == USB_MANAGER_ERROR_BUSY) + { + DBG (3, "Maybe the kernel scanner driver or usblp claims " + "the interface? Ignoring this error...\n"); + status = SANE_STATUS_GOOD; + } + + if (status != SANE_STATUS_GOOD) + { + usb_manager_close (devices[devcount].usb_manager_handle); + usb_manager_free_config_descriptor (config0); + return status; + } + } + } + usb_manager_free_config_descriptor (config0); + + /* Claim the interface */ + result = usb_manager_claim_interface (devices[devcount].usb_manager_handle, + devices[devcount].interface_nr); + if (result < 0) + { + SANE_Status status = SANE_STATUS_INVAL; + + DBG (1, "sanei_usb_open: usb_manager complained: %s\n", + sanei_usb_manager_strerror (result)); + if (result == USB_MANAGER_ERROR_ACCESS) + { + DBG (1, "Make sure you run as root or set appropriate " + "permissions\n"); + status = SANE_STATUS_ACCESS_DENIED; + } + else if (result == USB_MANAGER_ERROR_BUSY) + { + DBG (1, "Maybe the kernel scanner driver claims the " + "scanner's interface?\n"); + status = SANE_STATUS_DEVICE_BUSY; + } + + usb_manager_close (devices[devcount].usb_manager_handle); + return status; + } + + /* Loop through all of the configurations */ + for (c = 0; c < desc.bNumConfigurations; c++) + { + struct usb_manager_config_descriptor *config; + + result = usb_manager_get_config_descriptor (dev, c, &config); + if (result < 0) + { + DBG (1, + "sanei_usb_open: could not get config[%d] descriptor for device `%s' (err %d)\n", + c, devname, result); + continue; + } + + /* Loop through all of the interfaces */ + for (i = 0; i < config->bNumInterfaces; i++) + { + /* Loop through all of the alternate settings */ + for (a = 0; a < config->interface[i].num_altsetting; a++) + { + const struct usb_manager_interface_descriptor *interface; + + DBG (5, "sanei_usb_open: configuration nr: %d\n", c); + DBG (5, "sanei_usb_open: interface nr: %d\n", i); + DBG (5, "sanei_usb_open: alt_setting nr: %d\n", a); + + /* Start by interfaces found in sanei_usb_init */ + if (c == 0 && i != devices[devcount].interface_nr) + { + DBG (5, "sanei_usb_open: interface %d not detected as " + "a scanner by sanei_usb_init, ignoring.\n", i); + continue; + } + + interface = &config->interface[i].altsetting[a]; + + /* Now we look for usable endpoints */ + for (num = 0; num < interface->bNumEndpoints; num++) + { + const struct usb_manager_endpoint_descriptor *endpoint; + int direction, transfer_type, transfer_type_usb_manager; + + endpoint = &interface->endpoint[num]; + DBG (5, "sanei_usb_open: endpoint nr: %d\n", num); + + transfer_type_usb_manager = + endpoint->bmAttributes & USB_MANAGER_TRANSFER_TYPE_MASK; + direction = endpoint->bEndpointAddress & USB_MANAGER_ENDPOINT_DIR_MASK; + + // don't rely on USB_MANAGER_TRANSFER_TYPE_* mapping to + // USB_ENDPOINT_TYPE_* even though they'll most likely be + // the same + switch (transfer_type_usb_manager) + { + case USB_MANAGER_TRANSFER_TYPE_INTERRUPT: + transfer_type = USB_ENDPOINT_TYPE_INTERRUPT; + break; + case USB_MANAGER_TRANSFER_TYPE_BULK: + transfer_type = USB_ENDPOINT_TYPE_BULK; + break; + case USB_MANAGER_TRANSFER_TYPE_ISOCHRONOUS: + transfer_type = USB_MANAGER_TRANSFER_TYPE_ISOCHRONOUS; + break; + case USB_MANAGER_TRANSFER_TYPE_CONTROL: + transfer_type = USB_ENDPOINT_TYPE_CONTROL; + break; + + } + + sanei_usb_add_endpoint(&devices[devcount], + transfer_type, + endpoint->bEndpointAddress, + direction); + } + } + } + + usb_manager_free_config_descriptor (config); + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ + DBG (1, "sanei_usb_open: can't open device `%s': " + "libusb support missing\n", devname); + return SANE_STATUS_UNSUPPORTED; +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ + } + else if (devices[devcount].method == sanei_usb_method_scanner_driver) + { +#ifdef FD_CLOEXEC + long int flag; +#endif + /* Using kernel scanner driver */ + devices[devcount].fd = -1; +#ifdef HAVE_RESMGR + devices[devcount].fd = rsm_open_device (devname, O_RDWR); +#endif + if (devices[devcount].fd == -1) + devices[devcount].fd = open (devname, O_RDWR); + if (devices[devcount].fd < 0) + { + SANE_Status status = SANE_STATUS_INVAL; + + if (errno == EACCES) + status = SANE_STATUS_ACCESS_DENIED; + else if (errno == ENOENT) + { + DBG (5, "sanei_usb_open: open of `%s' failed: %s\n", + devname, strerror (errno)); + return status; + } + DBG (1, "sanei_usb_open: open of `%s' failed: %s\n", + devname, strerror (errno)); + return status; + } +#ifdef FD_CLOEXEC + flag = fcntl (devices[devcount].fd, F_GETFD); if (flag >= 0) { if (fcntl (devices[devcount].fd, F_SETFD, flag | FD_CLOEXEC) < 0) @@ -3061,7 +3557,22 @@ sanei_usb_close (SANE_Int dn) devices[dn].interface_nr); libusb_close (devices[dn].lu_handle); } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + /* This call seems to be required by Linux xhci driver + * even though it should be a no-op. Without it, the + * host or driver does not reset it's data toggle bit. + * We intentionally ignore the return val */ + if (workaround) + { + sanei_usb_set_altinterface (dn, devices[dn].alt_setting); + } + + usb_manager_release_interface (devices[dn].usb_manager_handle, + devices[dn].interface_nr); + usb_manager_close (devices[dn].usb_manager_handle); + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ DBG (1, "sanei_usb_close: libusb support missing\n"); #endif devices[dn].open = SANE_FALSE; @@ -3074,11 +3585,13 @@ sanei_usb_set_timeout (SANE_Int __sane_unused__ timeout) if (testing_mode == sanei_usb_testing_mode_replay) return; -#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) libusb_timeout = timeout; +#elif defined(HAVE_USB_MANAGER) + usb_manager_timeout = timeout; #else DBG (1, "sanei_usb_set_timeout: libusb support missing\n"); -#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ +#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USB_MANAGER */ } SANE_Status @@ -3151,9 +3664,32 @@ sanei_usb_clear_halt (SANE_Int dn) DBG (1, "sanei_usb_clear_halt: BULK_OUT ret=%d\n", ret); return SANE_STATUS_INVAL; } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + int ret; + + /* This call seems to be required by Linux xhci driver + * even though it should be a no-op. Without it, the + * host or driver does not send the clear to the device. + * We intentionally ignore the return val */ + if (workaround) + { + sanei_usb_set_altinterface (dn, devices[dn].alt_setting); + } + + ret = usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].bulk_in_ep); + if (ret){ + DBG (1, "sanei_usb_clear_halt: BULK_IN ret=%d\n", ret); + return SANE_STATUS_INVAL; + } + + ret = usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].bulk_out_ep); + if (ret){ + DBG (1, "sanei_usb_clear_halt: BULK_OUT ret=%d\n", ret); + return SANE_STATUS_INVAL; + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ DBG (1, "sanei_usb_clear_halt: libusb support missing\n"); -#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ +#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USB_MANAGER */ return SANE_STATUS_GOOD; } @@ -3181,10 +3717,18 @@ sanei_usb_reset (SANE_Int __sane_unused__ dn) DBG (1, "sanei_usb_reset: ret=%d\n", ret); return SANE_STATUS_INVAL; } +#elif defined(HAVE_USB_MANAGER) + int ret; -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ + ret = usb_manager_reset_device (devices[dn].usb_manager_handle); + if (ret){ + DBG (1, "sanei_usb_reset: ret=%d\n", ret); + return SANE_STATUS_INVAL; + } + +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ DBG (1, "sanei_usb_reset: libusb support missing\n"); -#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ +#endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB || HAVE_USB_MANAGER */ return SANE_STATUS_GOOD; } @@ -3428,7 +3972,36 @@ sanei_usb_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) return SANE_STATUS_INVAL; } } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + if (devices[dn].bulk_in_ep) + { + int ret, rsize; + ret = usb_manager_bulk_transfer (devices[dn].usb_manager_handle, + devices[dn].bulk_in_ep, buffer, + (int) *size, &rsize, + usb_manager_timeout); + + if (ret < 0) + { + DBG (1, "sanei_usb_read_bulk: read failed (still got %d bytes): %s\n", + rsize, sanei_usb_manager_strerror (ret)); + + read_size = -1; + } + else + { + read_size = rsize; + } + } + else + { + DBG (1, "sanei_usb_read_bulk: can't read without a bulk-in " + "endpoint\n"); + return SANE_STATUS_INVAL; + } + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ { DBG (1, "sanei_usb_read_bulk: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; @@ -3500,6 +4073,9 @@ sanei_usb_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) #elif defined(HAVE_LIBUSB) if (devices[dn].method == sanei_usb_method_libusb) libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_in_ep); +#elif defined(HAVE_USB_MANAGER) + if (devices[dn].method == sanei_usb_method_usb_manager) + usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].bulk_in_ep); #endif return SANE_STATUS_IO_ERROR; } @@ -3763,12 +4339,40 @@ sanei_usb_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) return SANE_STATUS_INVAL; } } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + if (devices[dn].bulk_out_ep) + { + int ret; + int trans_bytes; + ret = usb_manager_bulk_transfer (devices[dn].usb_manager_handle, + devices[dn].bulk_out_ep, + (unsigned char *) buffer, + (int) *size, &trans_bytes, + usb_manager_timeout); + if (ret < 0) + { + DBG (1, "sanei_usb_write_bulk: write failed: %s\n", + sanei_usb_manager_strerror (ret)); + + write_size = -1; + } + else + write_size = trans_bytes; + } + else + { + DBG (1, "sanei_usb_write_bulk: can't write without a bulk-out " + "endpoint\n"); + return SANE_STATUS_INVAL; + } + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ { DBG (1, "sanei_usb_write_bulk: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ else if (devices[dn].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS @@ -3836,6 +4440,9 @@ sanei_usb_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) #elif defined(HAVE_LIBUSB) if (devices[dn].method == sanei_usb_method_libusb) libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_out_ep); +#elif defined(HAVE_USB_MANAGER) + if (devices[dn].method == sanei_usb_method_usb_manager) + usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].bulk_out_ep); #endif return SANE_STATUS_IO_ERROR; } @@ -4103,12 +4710,28 @@ sanei_usb_control_msg (SANE_Int dn, SANE_Int rtype, SANE_Int req, if ((rtype & 0x80) && debug_level > 10) print_buffer (data, len); } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB*/ +#elif defined(HAVE_USB_MANAGER) + { + int result; + + result = usb_manager_control_transfer (devices[dn].usb_manager_handle, rtype, req, + value, index, data, len, + usb_manager_timeout); + if (result < 0) + { + DBG (1, "sanei_usb_control_msg: libusb complained: %s\n", + sanei_usb_manager_strerror (result)); + return SANE_STATUS_INVAL; + } + if ((rtype & 0x80) && debug_level > 10) + print_buffer (data, len); + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ { DBG (1, "sanei_usb_control_msg: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ else if (devices[dn].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS @@ -4282,7 +4905,7 @@ SANE_Status sanei_usb_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) { ssize_t read_size = 0; -#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) || defined(HAVE_USB_MANAGER) SANE_Bool stalled = SANE_FALSE; #endif @@ -4363,12 +4986,37 @@ sanei_usb_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) return SANE_STATUS_INVAL; } } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + if (devices[dn].int_in_ep) + { + int ret; + int trans_bytes; + ret = usb_manager_interrupt_transfer (devices[dn].usb_manager_handle, + devices[dn].int_in_ep, + buffer, (int) *size, + &trans_bytes, usb_manager_timeout); + + if (ret < 0) + read_size = -1; + else + read_size = trans_bytes; + + stalled = (ret == USB_MANAGER_ERROR_PIPE); + } + else + { + DBG (1, "sanei_usb_read_int: can't read without an int " + "endpoint\n"); + return SANE_STATUS_INVAL; + } + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ { DBG (1, "sanei_usb_read_int: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ else if (devices[dn].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS @@ -4429,6 +5077,10 @@ sanei_usb_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) if (devices[dn].method == sanei_usb_method_libusb) if (stalled) libusb_clear_halt (devices[dn].lu_handle, devices[dn].int_in_ep); +#elif defined(HAVE_USB_MANAGER) + if (devices[dn].method == sanei_usb_method_usb_manager) + if (stalled) + usb_manager_clear_halt (devices[dn].usb_manager_handle, devices[dn].int_in_ep); #endif return SANE_STATUS_IO_ERROR; } @@ -4568,12 +5220,25 @@ sanei_usb_set_configuration (SANE_Int dn, SANE_Int configuration) } return SANE_STATUS_GOOD; } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + int result; + + result = usb_manager_set_configuration (devices[dn].usb_manager_handle, configuration); + if (result < 0) + { + DBG (1, "sanei_usb_set_configuration: libusb complained: %s\n", + sanei_usb_manager_strerror (result)); + return SANE_STATUS_INVAL; + } + return SANE_STATUS_GOOD; + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ { DBG (1, "sanei_usb_set_configuration: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ else { DBG (1, @@ -4641,12 +5306,25 @@ sanei_usb_claim_interface (SANE_Int dn, SANE_Int interface_number) } return SANE_STATUS_GOOD; } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + int result; + + result = usb_manager_claim_interface (devices[dn].usb_manager_handle, interface_number); + if (result < 0) + { + DBG (1, "sanei_usb_claim_interface: libusb complained: %s\n", + sanei_usb_manager_strerror (result)); + return SANE_STATUS_INVAL; + } + return SANE_STATUS_GOOD; + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ { DBG (1, "sanei_usb_claim_interface: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ else { DBG (1, "sanei_usb_claim_interface: access method %d not implemented\n", @@ -4712,12 +5390,25 @@ sanei_usb_release_interface (SANE_Int dn, SANE_Int interface_number) } return SANE_STATUS_GOOD; } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + int result; + + result = usb_manager_release_interface (devices[dn].usb_manager_handle, interface_number); + if (result < 0) + { + DBG (1, "sanei_usb_release_interface: libusb complained: %s\n", + sanei_usb_manager_strerror (result)); + return SANE_STATUS_INVAL; + } + return SANE_STATUS_GOOD; + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ { DBG (1, "sanei_usb_release_interface: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ else { DBG (1, @@ -4783,12 +5474,26 @@ sanei_usb_set_altinterface (SANE_Int dn, SANE_Int alternate) } return SANE_STATUS_GOOD; } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + int result; + + result = usb_manager_set_interface_alt_setting (devices[dn].usb_manager_handle, + devices[dn].interface_nr, alternate); + if (result < 0) + { + DBG (1, "sanei_usb_set_altinterface: usb_manager complained: %s\n", + sanei_usb_manager_strerror (result)); + return SANE_STATUS_INVAL; + } + return SANE_STATUS_GOOD; + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ { DBG (1, "sanei_set_altinterface: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ else { DBG (1, @@ -4949,12 +5654,36 @@ sanei_usb_get_descriptor( SANE_Int dn, desc->dev_protocol = lu_desc.bDeviceProtocol; desc->max_packet_size = lu_desc.bMaxPacketSize0; } -#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#elif defined(HAVE_USB_MANAGER) + { + struct usb_manager_device_descriptor usb_manager_desc; + int ret; + + ret = usb_manager_get_device_descriptor (devices[dn].usb_manager_device, &usb_manager_desc); + if (ret < 0) + { + DBG (1, + "sanei_usb_get_descriptor: libusb error: %s\n", + sanei_usb_manager_strerror (ret)); + + return SANE_STATUS_INVAL; + } + + desc->desc_type = usb_manager_desc.bDescriptorType; + desc->bcd_usb = usb_manager_desc.bcdUSB; + desc->bcd_dev = usb_manager_desc.bcdDevice; + desc->dev_class = usb_manager_desc.bDeviceClass; + + desc->dev_sub_class = usb_manager_desc.bDeviceSubClass; + desc->dev_protocol = usb_manager_desc.bDeviceProtocol; + desc->max_packet_size = usb_manager_desc.bMaxPacketSize0; + } +#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER*/ { DBG (1, "sanei_usb_get_descriptor: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } -#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ +#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB && not HAVE_USB_MANAGER */ if (testing_mode == sanei_usb_testing_mode_record) { diff --git a/sanei/usb_manager.cpp b/sanei/usb_manager.cpp new file mode 100644 index 000000000..3a6ecf89c --- /dev/null +++ b/sanei/usb_manager.cpp @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2024 Huawei Device 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 "iusb_srv.h" +#include "securec.h" +#include "string.h" +#include "cstring" +#include "usb_srv_client.h" +#include "usb_manager.h" +#include "v1_0/iusb_interface.h" +#include "hilog/log.h" + +#define SANE_LOG_TAG "sanekit" +#define SANE_HILOG_INFO(...) ((void)HiLogPrint(LOG_APP, LOG_INFO, 0, "sanekit", __VA_ARGS__)) +#define SANE_HILOG_ERROR(...) ((void)HiLogPrint(LOG_APP, LOG_ERROR, 0, "sanekit", __VA_ARGS__)) +#define SANE_HILOG_DEBUG(...) ((void)HiLogPrint(LOG_APP, LOG_DEBUG, 0, "sanekit", __VA_ARGS__)) +#define SANE_HILOG_WARN(...) ((void)HiLogPrint(LOG_APP, LOG_WARN, 0, "sanekit", __VA_ARGS__)) + +using namespace OHOS::USB; + +#define DELETE_AND_NULLPTR(ptr) \ + if ((ptr) != nullptr) { \ + delete (ptr); \ + (ptr) = nullptr; \ + } + +#define DELETE_ARRAY_AND_NULLPTR(ptr) \ + if ((ptr) != nullptr) { \ + delete[] (ptr); \ + (ptr) = nullptr; \ + } + +std::vector g_deviceList; +static ssize_t g_deviceCount = 0; +static uint8_t g_interfaceNumber = 0; +static usb_manager_config_descriptor* g_deviceConfig = nullptr; + +struct usb_manager_device_handle { + UsbDevice device; + USBDevicePipe pipe; +}; + +struct usb_manager_device { + UsbDevice device; +}; + +static void MemoryFreeDeviceList(usb_manager_device **list) +{ + if (list == nullptr) { + return; + } + for (ssize_t i = 0 ; i < g_deviceCount; i++) { + DELETE_AND_NULLPTR(list[i]); + } + DELETE_ARRAY_AND_NULLPTR(list); + g_deviceCount = 0; +} + +int usb_manager_init(usb_manager_context **ctx) +{ + SANE_HILOG_INFO("%s: begin", __func__); + if (ctx == nullptr) { + SANE_HILOG_ERROR("%s: ctx is a nullptr.", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + usb_manager_context *usbmanagerContext = new (std::nothrow) usb_manager_context(); + if (usbmanagerContext == nullptr) { + SANE_HILOG_ERROR("%s: Not enough memory.", __func__); + return USB_MANAGER_ERROR_NO_MEM; + } + *ctx = usbmanagerContext; + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +int usb_manager_exit(usb_manager_context *ctx) +{ + SANE_HILOG_INFO("%s: begin", __func__); + if (ctx == nullptr) { + SANE_HILOG_ERROR("%s: ctx is a nullptr.", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + DELETE_AND_NULLPTR(ctx); + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +ssize_t usb_manager_get_device_list(usb_manager_context *ctx, usb_manager_device ***list) +{ + SANE_HILOG_INFO("%s: begin", __func__); + if (ctx == nullptr || list == nullptr) { + SANE_HILOG_ERROR("%s: ctx or list is a nullptr.", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + g_deviceList.clear(); + auto ret = UsbSrvClient::GetInstance().GetDevices(g_deviceList); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_ERROR("%s: GetDevices exception.", __func__); + return USB_MANAGER_ERROR_IO; + } + g_deviceCount = static_cast(g_deviceList.size()); + SANE_HILOG_DEBUG("%s: deviceCount : %d", __func__, g_deviceCount); + if (g_deviceCount == 0) { + SANE_HILOG_DEBUG("%s: not found device.", __func__); + return USB_MANAGER_SUCCESS; + } + usb_manager_device** usbManagerDeviceList = new (std::nothrow) usb_manager_device* [g_deviceCount]; + if (usbManagerDeviceList == nullptr) { + SANE_HILOG_ERROR("%s: Not enough memory.", __func__); + return USB_MANAGER_ERROR_NO_MEM; + } + for (ssize_t i = 0; i < g_deviceCount; i++) { + usb_manager_device* usbDevice = new (std::nothrow) usb_manager_device(); + if (usbDevice == nullptr) { + MemoryFreeDeviceList(usbManagerDeviceList); + SANE_HILOG_ERROR("%s: Not enough memory.", __func__); + return USB_MANAGER_ERROR_NO_MEM; + } + usbDevice->device = g_deviceList[i]; + usbManagerDeviceList[i] = usbDevice; + } + *list = usbManagerDeviceList; + SANE_HILOG_INFO("%s: end successful", __func__); + return g_deviceCount; +} + +int usb_manager_get_bus_number(usb_manager_device *dev) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev == nullptr) { + SANE_HILOG_ERROR("%s: dev is a nullptr.", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + SANE_HILOG_INFO("%s: end successful", __func__); + return dev->device.GetBusNum(); +} + +int usb_manager_get_device_address(usb_manager_device *dev) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev == nullptr) { + SANE_HILOG_ERROR("%s: dev is a nullptr.", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + SANE_HILOG_INFO("%s: end successful", __func__); + return dev->device.GetDevAddr(); +} + +int usb_manager_get_device_descriptor(usb_manager_device *dev, usb_manager_device_descriptor *desc) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev == nullptr || desc == nullptr) { + SANE_HILOG_ERROR("%s: dev or desc is a nullptr.", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + UsbDevice &device = dev->device; + desc->idVendor = static_cast(device.GetVendorId()); + desc->idProduct = static_cast(device.GetProductId()); + desc->bDeviceClass = static_cast(device.GetClass()); + desc->bNumConfigurations = static_cast(device.GetConfigCount()); + desc->bDeviceSubClass = static_cast(device.GetSubclass()); + desc->bDeviceProtocol = static_cast(device.GetProtocol()); + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +int usb_manager_open(usb_manager_device *dev, usb_manager_device_handle **dev_handle) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev == nullptr || dev_handle == nullptr) { + SANE_HILOG_ERROR("%s: dev or dev_handle is a nullptr.", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + auto &usbSrvClient = UsbSrvClient::GetInstance(); + USBDevicePipe pipe; + UsbDevice &device = dev->device; + auto ret = usbSrvClient.RequestRight(device.GetName()); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_ERROR("request right failed ret=%{public}d", ret); + return USB_MANAGER_ERROR_ACCESS; + } + ret = usbSrvClient.OpenDevice(device, pipe); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_ERROR("open device failed ret=%{public}d", ret); + return USB_MANAGER_ERROR_ACCESS; + } + auto handle = new (std::nothrow) usb_manager_device_handle(); + if (handle == nullptr) { + usbSrvClient.Close(pipe); + SANE_HILOG_ERROR("%s: Not enough memory.", __func__); + return USB_MANAGER_ERROR_NO_MEM; + } + handle->device = device; + handle->pipe = pipe; + *dev_handle = handle; + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +void usb_manager_close(usb_manager_device_handle *dev_handle) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev_handle == nullptr) { + SANE_HILOG_ERROR("%s: dev_handle is a nullptr", __func__); + return; + } + auto &usbSrvClient = UsbSrvClient::GetInstance(); + usbSrvClient.Close(dev_handle->pipe); + DELETE_AND_NULLPTR(dev_handle); + SANE_HILOG_INFO("%s: end", __func__); + return; +} + +int usb_manager_get_configuration(usb_manager_device_handle *dev, int *config) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev == nullptr || config == nullptr) { + SANE_HILOG_ERROR("%s: dev or config is a nullptr", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + UsbDevice &device = dev->device; + auto configCount = device.GetConfigCount(); + SANE_HILOG_DEBUG("%s: configCount = %d", __func__, configCount); + *config = configCount; + return USB_MANAGER_SUCCESS; +} + +struct UsbEndPointDes { + uint8_t bmAttributes; + uint8_t bEndpointAddress; +}; + +struct UsbInterfaceAltDes{ + uint8_t bInterfaceClass; + std::vector endpointDes; +}; + +struct UsbAltInterface { + std::vector altDes; +}; + +void InterfaceConvert(std::vector &usbInterfaces, std::vector &usbAlt) { + auto memCopyInter = [&](size_t &i, UsbAltInterface &altInter) { + UsbInterfaceAltDes des; + des.bInterfaceClass = static_cast(usbInterfaces[i].GetClass()); + std::vector &endPoints = usbInterfaces[i].GetEndpoints(); + for (size_t j = 0; j < endPoints.size(); j++) { + UsbEndPointDes pointDes; + pointDes.bmAttributes = static_cast(endPoints[j].GetAttributes()); + pointDes.bEndpointAddress = static_cast(endPoints[j].GetAddress()); + des.endpointDes.push_back(pointDes); + } + altInter.altDes.push_back(des); + }; + for (size_t i = 0; i < usbInterfaces.size(); i++) { + UsbInterface& inter = usbInterfaces[i]; + if (inter.GetAlternateSetting() == 0) { + UsbAltInterface altInter; + memCopyInter(i, altInter); + usbAlt.push_back(altInter); + } else { + int id = usbInterfaces[i].GetId(); + UsbAltInterface &altInter = usbAlt[id]; + memCopyInter(i, altInter); + } + } +} + +int usb_manager_get_config_descriptor(usb_manager_device *dev, uint8_t config_index, + usb_manager_config_descriptor **config) +{ + SANE_HILOG_INFO("%s: begin", __func__); + if (dev == nullptr || config == nullptr) { + SANE_HILOG_ERROR("%s: dev or config is a nullptr", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + UsbDevice &device = dev->device; + std::vector &configs = device.GetConfigs(); + if (config_index >= configs.size()) { + SANE_HILOG_ERROR("%s: config_index(%u) is invalid.", __func__, config_index); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + USBConfig &usbConfig = configs[config_index]; + SANE_HILOG_DEBUG("%s: config[%u] = %s", __func__, config_index, usbConfig.getJsonString().c_str()); + usb_manager_config_descriptor* retConfig = new (std::nothrow) usb_manager_config_descriptor(); + if (retConfig == nullptr) { + SANE_HILOG_ERROR("%s: Not enough memory.", __func__); + return USB_MANAGER_ERROR_NO_MEM; + } + std::vector &usbInterfaces = usbConfig.GetInterfaces(); + std::vector usbAlt; + InterfaceConvert(usbInterfaces, usbAlt); + size_t bNumInterfaces = usbAlt.size(); + retConfig->bNumInterfaces = static_cast(bNumInterfaces); + retConfig->bConfigurationValue = static_cast(usbConfig.GetId()); + auto retInterface = new (std::nothrow) usb_manager_interface[bNumInterfaces]; + if (retInterface == nullptr) { + SANE_HILOG_ERROR("%s: Not enough memory.", __func__); + return USB_MANAGER_ERROR_NO_MEM; + } + for (int i = 0; i < bNumInterfaces; i++) { + size_t altSet = usbAlt[i].altDes.size(); + auto retAltsetting = new (std::nothrow) usb_manager_interface_descriptor[altSet]; + if (retAltsetting == nullptr) { + SANE_HILOG_ERROR("%s: Not enough memory.", __func__); + return USB_MANAGER_ERROR_NO_MEM; + } + for (size_t j = 0; j < altSet; j++) { + retAltsetting[j].bInterfaceClass = usbAlt[i].altDes[j].bInterfaceClass; + size_t endPointsNum = usbAlt[i].altDes[j].endpointDes.size(); + retAltsetting[j].bNumEndpoints = endPointsNum; + retAltsetting[j].endpoint = new usb_manager_endpoint_descriptor[endPointsNum]; + for (int k = 0 ; k < endPointsNum; k++) { + uint8_t bmAttr = usbAlt[i].altDes[j].endpointDes[k].bmAttributes; + uint8_t bEndpointAddress = usbAlt[i].altDes[j].endpointDes[k].bEndpointAddress; + retAltsetting[j].endpoint[k].bmAttributes = bmAttr; + retAltsetting[j].endpoint[k].bEndpointAddress = bEndpointAddress; + } + } + retInterface[i].altsetting = retAltsetting; + retInterface[i].num_altsetting = static_cast(altSet); + } + retConfig->interface = retInterface; + *config = retConfig; + g_deviceConfig = retConfig; + SANE_HILOG_INFO("%s: end", __func__); + return USB_MANAGER_SUCCESS; +} + +void usb_manager_free_config_descriptor(usb_manager_config_descriptor *config) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (config == nullptr) { + SANE_HILOG_ERROR("%s: config is a nullptr", __func__); + return; + } + usb_manager_interface *interface = config->interface; + // for each interface + for (uint8_t i = 0; i < config->bNumInterfaces; i++) { + usb_manager_interface *interfacei = interface + i; + if (interfacei == nullptr) { + break; + } + usb_manager_interface_descriptor *altsetting = interfacei->altsetting; + // for each altsetting interface + for (int j = 0; j < interfacei->num_altsetting; i++) { + usb_manager_interface_descriptor *altsettingj = altsetting + j; + if (altsettingj == nullptr) { + break; + } + DELETE_ARRAY_AND_NULLPTR(altsettingj->endpoint) + } + DELETE_ARRAY_AND_NULLPTR(interfacei->altsetting); + } + DELETE_ARRAY_AND_NULLPTR(interface); + DELETE_AND_NULLPTR(config); + SANE_HILOG_INFO("%s: end successful", __func__); + return; +} + +void usb_manager_free_device_list(usb_manager_device **list, int unref_devices) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (list == nullptr) { + SANE_HILOG_ERROR("%s: list is a nullptr", __func__); + return; + } + MemoryFreeDeviceList(list); + SANE_HILOG_INFO("%s: end successful", __func__); +} + +int usb_manager_set_configuration(usb_manager_device_handle *dev_handle, int configuration) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev_handle == nullptr) { + SANE_HILOG_ERROR("%s: dev_handle is a nullptr", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + UsbDevice &device = dev_handle->device; + USBDevicePipe pip; + pip.SetBusNum(device.GetBusNum()); + pip.SetDevAddr(device.GetDevAddr()); + USBConfig config; + config.SetId(configuration); + auto ret = UsbSrvClient::GetInstance().SetConfiguration(pip, config); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_ERROR("SetConfiguration failed ret=%{public}d", ret); + return USB_MANAGER_ERROR_IO; + } + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +int usb_manager_claim_interface(usb_manager_device_handle *dev_handle, int interface_number) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev_handle == nullptr) { + SANE_HILOG_ERROR("%s: dev_handle is a nullptr", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + auto &usbSrvClient = UsbSrvClient::GetInstance(); + UsbInterface interface; + interface.SetId(interface_number); + auto ret = usbSrvClient.ClaimInterface(dev_handle->pipe, interface, true); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_ERROR("ClaimInterface failed ret=%{public}d", ret); + return USB_MANAGER_ERROR_IO; + } + g_interfaceNumber = interface_number; + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +int usb_manager_release_interface(usb_manager_device_handle *dev_handle, int interface_number) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev_handle == nullptr) { + SANE_HILOG_ERROR("%s: dev_handle is a nullptr", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + auto &usbSrvClient = UsbSrvClient::GetInstance(); + USBDevicePipe &pipe = dev_handle->pipe; + SANE_HILOG_DEBUG("%s: interface_number : %d", __func__, interface_number); + UsbInterface interface; + interface.SetId(interface_number); + auto ret = usbSrvClient.ReleaseInterface(pipe, interface); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_ERROR("ReleaseInterface failed ret=%{public}d", ret); + return USB_MANAGER_ERROR_IO; + } + g_interfaceNumber = 0; + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +int usb_manager_bulk_transfer(usb_manager_device_handle *dev_handle, unsigned char endpoint, + unsigned char *data, int length, int *transferred, unsigned int timeout) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev_handle == nullptr || data == nullptr || length <= 0 || transferred == nullptr) { + SANE_HILOG_ERROR("%s: Invalid input parameter.", __func__); + return USB_MANAGER_ERROR_INVALID_PARAM; + } + USBDevicePipe &pipe = dev_handle->pipe; + USBEndpoint usbEndpoint; + usbEndpoint.SetInterfaceId(g_interfaceNumber); + usbEndpoint.SetAddr(endpoint); + auto &usbSrvClient = UsbSrvClient::GetInstance(); + if (endpoint & USB_MANAGER_ENDPOINT_IN) { + // read + std::vector bufferData(length); + auto ret = usbSrvClient.BulkTransfer(pipe, usbEndpoint, bufferData, timeout); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_INFO("%s: error", __func__); + return USB_MANAGER_ERROR_IO; + } + for (int i = 0; i < length; i++) { + data[i] = bufferData[i]; + } + } else { + // write + std::vector bufferData(length); + for (int i = 0; i < length; i++) { + bufferData[i] = data[i]; + } + auto ret = usbSrvClient.BulkTransfer(pipe, usbEndpoint, bufferData, timeout); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_INFO("%s: error", __func__); + return USB_MANAGER_ERROR_IO; + } + } + *transferred = length; + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +int usb_manager_control_transfer(usb_manager_device_handle *dev_handle, uint8_t request_type, + uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, + unsigned int timeout) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev_handle == nullptr || data == nullptr || wLength == 0) { + return USB_MANAGER_ERROR_INVALID_PARAM; + } + USBDevicePipe &pipe = dev_handle->pipe; + OHOS::HDI::Usb::V1_0::UsbCtrlTransfer ctrl; + ctrl.requestType = static_cast(request_type); + ctrl.requestCmd = static_cast(bRequest); + ctrl.value = static_cast(wValue); + ctrl.index = static_cast(wIndex); + ctrl.timeout = static_cast(timeout); + + auto &usbSrvClient = UsbSrvClient::GetInstance(); + std::vector bufferData; + for (uint16_t i = 0; i < wLength; i++) { + bufferData[i] = data[i]; + } + auto ret = usbSrvClient.ControlTransfer(pipe, ctrl, bufferData); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_ERROR("ControlTransfer failed ret=%{public}d", ret); + return USB_MANAGER_ERROR_IO; + } + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +int usb_manager_set_interface_alt_setting(usb_manager_device_handle *dev_handle, int interface_number, + int alternate_setting) +{ + SANE_HILOG_INFO("%s: start", __func__); + if (dev_handle == nullptr) { + return USB_MANAGER_ERROR_INVALID_PARAM; + } + auto &usbSrvClient = UsbSrvClient::GetInstance(); + USBDevicePipe pipe = dev_handle->pipe; + UsbInterface interface; + interface.SetId(interface_number); + interface.SetAlternateSetting(alternate_setting); + auto ret = usbSrvClient.SetInterface(pipe, interface); + if (ret != USB_MANAGER_SUCCESS) { + SANE_HILOG_ERROR("SetInterface failed ret=%{public}d", ret); + return USB_MANAGER_ERROR_IO; + } + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +// stub +int usb_manager_interrupt_transfer(usb_manager_device_handle *dev_handle, unsigned char endpoint, + unsigned char *data, int length, int *actual_length, unsigned int timeout) +{ + SANE_HILOG_INFO("%s: start", __func__); + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +// stub +usb_manager_device * usb_manager_ref_device(usb_manager_device *dev) +{ + SANE_HILOG_INFO("%s: start", __func__); + SANE_HILOG_INFO("%s: end successful", __func__); + return nullptr; +} + +// stub +int usb_manager_clear_halt(usb_manager_device_handle *dev_handle, unsigned char endpoint) +{ + SANE_HILOG_INFO("%s: start", __func__); + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} + +// stub +int usb_manager_reset_device(usb_manager_device_handle *dev_handle) +{ + SANE_HILOG_INFO("%s: start", __func__); + SANE_HILOG_INFO("%s: end successful", __func__); + return USB_MANAGER_SUCCESS; +} \ No newline at end of file -- Gitee