From b50ea5cf1603cd7349fa783c394ffd0b2fae7eca Mon Sep 17 00:00:00 2001 From: shawn_he Date: Fri, 14 Jan 2022 14:31:15 +0800 Subject: [PATCH] update docs Signed-off-by: shawn_he --- en/device-dev/apis/usb/usbd_client.h | 426 ++++++++++++++++++ en/device-dev/subsystems/Readme-EN.md | 4 + .../figure/USB_service_architecture.png | Bin 0 -> 35189 bytes .../subsystems/subsys-usbservice-demo.md | 187 ++++++++ .../subsystems/subsys-usbservice-guide.md | 53 +++ .../subsystems/subsys-usbservice-overview.md | 221 +++++++++ en/device-dev/subsystems/subsys-usbservice.md | 7 + 7 files changed, 898 insertions(+) create mode 100644 en/device-dev/apis/usb/usbd_client.h create mode 100644 en/device-dev/subsystems/figure/USB_service_architecture.png create mode 100644 en/device-dev/subsystems/subsys-usbservice-demo.md create mode 100644 en/device-dev/subsystems/subsys-usbservice-guide.md create mode 100644 en/device-dev/subsystems/subsys-usbservice-overview.md create mode 100644 en/device-dev/subsystems/subsys-usbservice.md diff --git a/en/device-dev/apis/usb/usbd_client.h b/en/device-dev/apis/usb/usbd_client.h new file mode 100644 index 0000000000..16934aae8d --- /dev/null +++ b/en/device-dev/apis/usb/usbd_client.h @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2021 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. + */ + +/** + * @addtogroup USB + * @{ + * + * @brief Declares USB-related APIs, including the custom data types and functions + * used to obtain descriptors, interface objects, and request objects, and to submit requests. + * + * @since 3.0 + * @version 1.0 + */ + +/** + * @file usbd_client.h + * + * @brief Defines the usbd Interface. + * + * @since 3.0 + * @version 1.0 + */ + +#ifndef USBD_CLIENT_H +#define USBD_CLIENT_H + +#include "usb_param.h" +#include "usbd_subscriber.h" + +namespace OHOS { +namespace USB { +class UsbdClient { +public: + /* * + * @brief Opens a USB device to set up a connection. + * + * @param dev Indicates the USB device address. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t OpenDevice(const UsbDev &dev); + + /* * + * @brief Closes a USB device to release all system resources related to the device. + * + * @param dev Indicates the USB device address. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t CloseDevice(const UsbDev &dev); + + /* * + * @brief Obtains the USB device descriptor. + * + * @param dev Indicates the USB device address. + * @param descriptor Indicates the USB device descriptor. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t GetDeviceDescriptor(const UsbDev &dev, std::vector &decriptor); + + /* * + * @brief Obtains the string descriptor of a USB device based on the specified string ID. + * + * @param dev Indicates the USB device address. + * @param descId Indicates string descriptor ID. + * @param descriptor Indicates the string descriptor of the USB device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t GetStringDescriptor(const UsbDev &dev, uint8_t descId, std::vector &decriptor); + + /* * + * @brief Obtains the configuration descriptor of a USB device based on the specified config ID. + * + * @param dev Indicates the USB device address. + * @param descId Indicates configuration descriptor ID. + * @param descriptor Indicates the configuration descriptor of the USB device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t GetConfigDescriptor(const UsbDev &dev, uint8_t descId, std::vector &decriptor); + + /* * + * @brief Obtains the raw descriptor. + * + * @param dev Indicates the USB device address. + * @param descriptor Indicates the raw descriptor of the USB device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t GetRawDescriptor(const UsbDev &dev, std::vector &decriptor); + + /* * + * @brief Sets the configuration information of a USB device. + * + * @param dev Indicates the USB device address. + * @param configIndex Indicates the configuration information of the USB device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t SetConfig(const UsbDev &dev, uint8_t configIndex); + + /* * + * @brief Obtains the configuration information of a USB device. + * + * @param dev Indicates the USB device address. + * @param configIndex Indicates the configuration information of the USB device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t GetConfig(const UsbDev &dev, uint8_t &configIndex); + + /* * + * @brief Claims a USB interface exclusively. This must be done before data transfer. + * + * @param dev Indicates the USB device address. + * @param interfaceid Indicates the interface ID of the USB device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t ClaimInterface(const UsbDev &dev, uint8_t interfaceid); + + /* * + * @brief Releases a USB interface. This is usually done after data transfer. + * + * @param dev Indicates the USB device address. + * @param interfaceid Indicates the interface ID of the USB device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t ReleaseInterface(const UsbDev &dev, uint8_t interfaceid); + + /* * + * @brief Sets the alternate settings for the specified USB interface. This allows you to switch between two interfaces with the same ID but different alternate settings. + * + * @param dev Indicates the USB device address. + * @param interfaceid Indicates the interface ID of the USB device. + * @param altIndex Indicates the alternate settings of the USB interface. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t SetInterface(const UsbDev &dev, uint8_t interfaceid, uint8_t altIndex); + + /* * + * @brief Reads data on a specified endpoint during bulk transfer. The endpoint must be in the data reading direction. You can specify a timeout duration if needed. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param timeout Indicates the timeout duration. + * @param data Indicates the read data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t + BulkTransferRead(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, std::vector &data); + + /* * + * @brief Writes data on a specified endpoint during bulk transfer. The endpoint must be in the data writing direction. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param timeout Indicates the timeout duration. + * @param data Indicates the written data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t + BulkTransferWrite(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, const std::vector &data); + + /* * + * @brief Performs control transfer for endpoint 0 of the device. The data transfer direction is determined by the request type. If the result of requestType& + * USB_ENDPOINT_DIR_MASK is USB_DIR_OUT, the endpoint is in the data writing direction; if the result is USB_DIR_IN, the endpoint is in the data reading direction. + * + * @param dev Indicates the USB device address. + * @param ctrl Indicates the control data packet structure. + * @param data Indicates the read data or written. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t ControlTransfer(const UsbDev &dev, const UsbCtrlTransfer &ctrl, std::vector &data); + + /* * + * @brief Reads data on a specified endpoint during interrupt transfer. The endpoint must be in the data reading direction. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param timeout Indicates the timeout duration. + * @param data Indicates the read data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t + InterruptTransferRead(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, std::vector &data); + + /* * + * @brief Writes data on a specified endpoint during interrupt transfer. The endpoint must be in the data writing direction. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param timeout Indicates the timeout duration. + * @param data Indicates the read data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t + InterruptTransferWrite(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, std::vector &data); + + /* * + * @brief Reads data on a specified endpoint during isochronous transfer. The endpoint must be in the data reading direction. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param timeout Indicates the timeout duration. + * @param data Indicates the read data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t IsoTransferRead(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, std::vector &data); + + /* * + * @brief Writes data on a specified endpoint during isochronous transfer. The endpoint must be in the data writing direction. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param timeout Indicates the timeout duration. + * @param data Indicates the written data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t + IsoTransferWrite(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, std::vector &data); + + /* * + * @brief Sends or receives requests for isochronous transfer on a specified endpoint. The data transfer direction is determined by the endpoint direction. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param clientData Indicates the client data. + * @param buffer Indicates the transferred data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t RequestQueue(const UsbDev &dev, + const UsbPipe &pipe, + const std::vector &clientData, + const std::vector &buffer); + + /* * + * @brief Waits for the operation result of the requests for isochronous transfer in RequestQueue. + * + * @param dev Indicates the USB device address. + * @param clientData Indicates the client data. + * @param buffer Indicates the transferred data. + * @param timeout Indicates the timeout duration. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t + RequestWait(const UsbDev &dev, std::vector &clientData, std::vector &buffer, int32_t timeout); + + /* * + * @brief Cancels the data transfer requests to be processed. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t RequestCancel(const UsbDev &dev, const UsbPipe &pipe); + + /* * + * @brief Obtains the list of functions (represented by bit field) supported by the current device. + * + * @param funcs Indicates the list of functions supported by the current device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t GetCurrentFunctions(int32_t &funcs); + + /* * + * @brief Sets the list of functions (represented by bit field) supported by the current device. + * + * @param funcs Indicates the list of functions supported by the current device. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t SetCurrentFunctions(int32_t funcs); + + /* * + * @brief Closes a USB device to release all system resources related to the device. + * + * @param portId Indicates the port ID of the USB interface. + * @param powerRole Indicates the power role. + * @param dataRole Indicates the data role. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t SetPortRole(int32_t portId, int32_t powerRole, int32_t dataRole); + + /* * + * @brief Queries the current settings of a port. + * + * @param portId Indicates the port ID of the USB interface. + * @param powerRole Indicates the power role. + * @param dataRole Indicates the data role. + * @param mode Indicates the mode. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t QueryPort(int32_t &portId, int32_t &powerRole, int32_t &dataRole, int32_t &mode); + + /* * + * @brief Binds a subscriber. + * + * @param subscriber Indicates the subscriber. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static ErrCode BindUsbdSubscriber(const sptr &subscriber); + + /* * + * @brief Unbinds a subscriber. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static ErrCode UnbindUsbdSubscriber(); + + /* * + * @brief Reads bulk data during isochronous transfer. This method is applicable to transfer of a huge amount of data. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param length Indicates the length of the data to read. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t BulkRequstDataSize(const UsbDev &dev, const UsbPipe &pipe, uint32_t &length); + + /* * + * @brief Obtains the data reading result. Use this method together with BulkRequstDataSize. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param data Indicates the read data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t BulkReadData(const UsbDev &dev, const UsbPipe &pipe, std::vector &data); + + /* * + * @brief Writes bulk data during isochronous transfer. This method is applicable to transfer of a huge amount of data. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param data Indicates the written data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t BulkWriteData(const UsbDev &dev, const UsbPipe &pipe, const std::vector &data); + + /* * + * @brief Obtains the data writing status based on length. Use this method together with BulkWriteData. + * + * @param dev Indicates the USB device address. + * @param pipe Indicates the pipe of the USB device. + * @param length Indicates the length of the written data. + * + * @return Returns 0 if the operation is successful; returns a non-0 value if the operation fails. + * @since 3.0 + */ + static int32_t BulkGetWriteCompleteLength(const UsbDev &dev, const UsbPipe &pipe, uint32_t &length); + +private: + static void PrintBuffer(const char *title, const uint8_t *buffer, uint32_t length); + static int32_t SetDeviceMessage(MessageParcel &data, const UsbDev &dev); + static int32_t SetBufferMessage(MessageParcel &data, const std::vector &tdata); + static int32_t GetBufferMessage(MessageParcel &data, std::vector &tdata); + static sptr GetUsbdService(); + static ErrCode DoDispatch(uint32_t cmd, MessageParcel &data, MessageParcel &reply); +}; +} // namespace USB +} // namespace OHOS +#endif // USBD_CLIENT_H diff --git a/en/device-dev/subsystems/Readme-EN.md b/en/device-dev/subsystems/Readme-EN.md index 90d19a51f4..9cc761113c 100644 --- a/en/device-dev/subsystems/Readme-EN.md +++ b/en/device-dev/subsystems/Readme-EN.md @@ -43,6 +43,10 @@ - [Sensors Overview](subsys-sensor-overview.md) - [Sensors Usage Guidelines](subsys-sensor-guide.md) - [Sensors Usage Example](subsys-sensor-demo.md) +- [USB](subsys-usbservice.md) + - [[USB Overview](subsys-usbservice-overview.md) + - [USB Usage Guidelines](subsys-usbservice-guide.md) + - [USB Usage Example](subsys-usbservice-demo.md) - [Application Framework](subsys-application-framework.md) - [Overview](subsys-application-framework-overview.md) - [Setting Up a Development Environment](subsys-application-framework-envbuild.md) diff --git a/en/device-dev/subsystems/figure/USB_service_architecture.png b/en/device-dev/subsystems/figure/USB_service_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..3aaf512454de1bee6a16925ec2346f894c5b724a GIT binary patch literal 35189 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 literal 0 HcmV?d00001 diff --git a/en/device-dev/subsystems/subsys-usbservice-demo.md b/en/device-dev/subsystems/subsys-usbservice-demo.md new file mode 100644 index 0000000000..decf0dad73 --- /dev/null +++ b/en/device-dev/subsystems/subsys-usbservice-demo.md @@ -0,0 +1,187 @@ +# USB Usage Example + + +``` +#include +#include +#include +#include +#include +#include +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iremote_object.h" +#include "iservice_registry.h" +#include "iusb_srv.h" +#include "string_ex.h" +#include "system_ability_definition.h" +#include "usb_common.h" +#include "usb_device.h" +#include "usb_errors.h" +#include "usb_request.h" +#include "usb_server_proxy.h" +#include "usb_srv_client.h" + +const int32_t REQUESTYPE = ((1 << 7) | (0 << 5) | (0 & 0x1f)); +const int32_t REQUESTCMD = 6; +const int32_t VALUE = (2 << 8) + 0; +const int32_t TIMEOUT = 5000; +const int32_t ITFCLASS = 10; +const int32_t PRAMATYPE = 2; +const int32_t BUFFERLENGTH = 21; + +void GetType(OHOS::USB::USBEndpoint &tep, OHOS::USB::USBEndpoint &outEp, bool &outEpFlg) +{ + if ((tep.GetType() == PRAMATYPE)) { + if (tep.GetDirection() == 0) { + outEp = tep; + outEpFlg = true; + } + } +} + +bool SelectEndpoint(OHOS::USB::USBConfig config, + std::vector interfaces, + OHOS::USB::UsbInterface &interface, + OHOS::USB::USBEndpoint &outEp, + bool &outEpFlg) +{ + for (int32_t i = 0; i < config.GetInterfaceCount(); ++i) { + OHOS::USB::UsbInterface tif = interfaces[i]; + std::vector mEndpoints = tif.GetEndpoints(); + for (int32_t j = 0; j < tif.GetEndpointCount(); ++j) { + OHOS::USB::USBEndpoint tep = mEndpoints[j]; + if ((tif.GetClass() == ITFCLASS) && (tif.GetSubClass() == 0) && (tif.GetProtocol() == PRAMATYPE)) { + GetType(tep, outEp, outEpFlg); + } + } + if (outEpFlg) { + interface = interfaces[i]; + return true; + } + std::cout << std::endl; + } + return false; +} + +int OpenDeviceTest(OHOS::USB::UsbSrvClient &Instran, OHOS::USB::UsbDevice device, OHOS::USB::USBDevicePipe &pip) +{ + int ret = Instran.RequestRight(device.GetName()); + std::cout << "device RequestRight ret = " << ret << std::endl; + if (0 != ret) { + std::cout << "device RequestRight failed = " << ret << std::endl; + } + ret = Instran.OpenDevice(device, pip); + return ret; +} + +int CtrTransferTest(OHOS::USB::UsbSrvClient &Instran, OHOS::USB::USBDevicePipe &pip) +{ + std::cout << "usb_device_test : << Control Transfer >> " << std::endl; + std::vector vData; + const OHOS::USB::UsbCtrlTransfer tctrl = {REQUESTYPE, REQUESTCMD, VALUE, 0, TIMEOUT}; + int ret = Instran.ControlTransfer(pip, tctrl, vData); + if (ret != 0) { + std::cout << "control message read failed width ret = " << ret << std::endl; + } else { + } + std::cout << "control message read success" << std::endl; + + return ret; +} + +int ClaimTest(OHOS::USB::UsbSrvClient &Instran, + OHOS::USB::USBDevicePipe &pip, + OHOS::USB::UsbInterface &interface, + bool interfaceFlg) +{ + if (interfaceFlg) { + std::cout << "ClaimInterface InterfaceInfo:" << interface.ToString() << std::endl; + int ret = Instran.ClaimInterface(pip, interface, true); + if (ret != 0) { + std::cout << "ClaimInterface failed width ret = " << ret << std::endl; + } else { + std::cout << "ClaimInterface success" << std::endl; + } + } + return 0; +} + +int BulkTransferTest(OHOS::USB::UsbSrvClient &Instran, + OHOS::USB::USBDevicePipe &pip, + OHOS::USB::USBEndpoint &outEp, + bool interfaceFlg, + bool outEpFlg) +{ + if (interfaceFlg) { + std::cout << "usb_device_test : << Bulk transfer start >> " << std::endl; + if (outEpFlg) { + uint8_t buffer[50] = "hello world 123456789"; + std::vector vData(buffer, buffer + BUFFERLENGTH); + int ret = Instran.BulkTransfer(pip, outEp, vData, TIMEOUT); + if (ret != 0) { + std::cout << "Bulk transfer write failed width ret = " << ret << std::endl; + } else { + std::cout << "Bulk transfer write success" << std::endl; + } + return ret; + } + } + return 0; +} + +int main(int argc, char **argv) +{ + std::cout << "usb_device_test " << std::endl; + static OHOS::USB::UsbSrvClient &Instran = OHOS::USB::UsbSrvClient::GetInstance(); + // GetDevices + std::vector deviceList; + int32_t ret = Instran.GetDevices(deviceList); + if (ret != 0) { + return OHOS::USB::UEC_SERVICE_INVALID_VALUE; + } + if (deviceList.empty()) { + return OHOS::USB::UEC_SERVICE_INVALID_VALUE; + } + + OHOS::USB::UsbDevice device = deviceList[0]; + std::vector configs = device.GetConfigs(); + OHOS::USB::USBConfig config = configs[0]; + std::vector interfaces = config.GetInterfaces(); + OHOS::USB::UsbInterface interface; + OHOS::USB::USBEndpoint outEp; + bool interfaceFlg = false; + bool outEpFlg = false; + interfaceFlg = SelectEndpoint(config, interfaces, interface, outEp, outEpFlg); + + // OpenDevice + std::cout << "usb_device_test : << OpenDevice >> test begin -> " << std::endl; + OHOS::USB::USBDevicePipe pip; + ret = OpenDeviceTest(Instran, device, pip); + if (ret != 0) { + return OHOS::USB::UEC_SERVICE_INVALID_VALUE; + } + + // ControlTransfer + CtrTransferTest(Instran, pip); + + // ClaimInterface + ClaimTest(Instran, pip, interface, interfaceFlg); + + // BulkTransferWrite + BulkTransferTest(Instran, pip, outEp, interfaceFlg, outEpFlg); + + // CloseDevice + std::cout << "usb_device_test : << Close Device >> " << std::endl; + ret = Instran.Close(pip); + if (ret == 0) { + std::cout << "Close device failed width ret = " << ret << std::endl; + return OHOS::USB::UEC_SERVICE_INVALID_VALUE; + } else { + std::cout << "Close Device success" << std::endl; + } + return 0; +} +``` + + diff --git a/en/device-dev/subsystems/subsys-usbservice-guide.md b/en/device-dev/subsystems/subsys-usbservice-guide.md new file mode 100644 index 0000000000..2b4a392ee8 --- /dev/null +++ b/en/device-dev/subsystems/subsys-usbservice-guide.md @@ -0,0 +1,53 @@ +# USB Usage Guidelines + +- [How to Use](#section18816105182315) + +The following procedure uses bulk transfer as an example. + +## Procedure + +1. Obtain a USB service instance. + +``` +static OHOS::USB::UsbSrvClient &g_usbClient = OHOS::USB::UsbSrvClient::GetInstance(); +``` + +2. Obtain the USB device list. + +``` +std::vector deviceList; +int32_t ret = g_usbClient.GetDevices(deviceList); +``` + +3. Apply for device access permissions. + +``` +int32_t ret = g_usbClient.RequestRight(device.GetName()); +``` + +4. Open the USB device. + +``` +USBDevicePipe pip; +int32_t et = g_usbClient.OpenDevice(device, pip); +``` + +5. Configure the USB interface. + +``` +ret = g_usbClient.ClaimInterface(pip, interface, true); +**interface** indicates an interface of the USB device in **deviceList**. +``` + +6. Transfer data. + +``` +srvClient.BulkTransfer(pipe, endpoint, vdata, timeout); +``` +**pipe** indicates the pipe for data transfer after the USB device is opened. **endpoint** indicates the endpoint for data transfer on the USB device. **vdata** indicates the binary data block to be transferred or read. **timeout** indicates the timeout duration of data transfer. + +7. Close the USB device. + +``` +ret = g_usbClient.Close(pip); +``` diff --git a/en/device-dev/subsystems/subsys-usbservice-overview.md b/en/device-dev/subsystems/subsys-usbservice-overview.md new file mode 100644 index 0000000000..9cbbcae2cb --- /dev/null +++ b/en/device-dev/subsystems/subsys-usbservice-overview.md @@ -0,0 +1,221 @@ +# USB Overview + +- [Introduction](#section175431838101617) +- [Available APIs](#section83365421647) + - [Host](#section83365421658) + - [Device](#section83365421669) + - [Port](#section83365421670) + +## Introduction + + USB devices are classified into two types: USB host and USB device. On OpenHarmony, you can use the port service to switch between the host mode and device mode. In host mode, you can obtain the list of connected USB devices, manage device access permissions, and perform bulk transfer or control transfer between the host and connected devices. In device mode, you can switch between functions including HDC (debugging), ACM (serial port), and ECM (Ethernet port). + +**Figure 1** USB service architecture + +![](figure/USB_service_architecture.png) + +- USB FWK/API: a layer that provides JS APIs for the upper layer through NAPI. +- USB SERVICE: a layer implemented by using the C++ programming language and logically divided into the HOST, DEVICE, and PORT modules. HDI-based APIs provided by USB SERVICE are mainly used to implement management of USB device list, USB functions, USB ports, and USB device access permissions. +- USB HAL: a layer implemented by using the C programming language. Based on the Host SDK and Device SDK, USB HAL encapsulates basic USB device operations, provides C++ APIs for the upper layer, and receives information from the kernel through the Hardware Driver Foundation (HDF) framework. + +## Available APIs + +- ### Host + + + + + + + + + + + + + + + + + + + + + +The + + + + + +The + + +The + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Header File

+

API

+

Description

+

usb_srv_client.h

+

+

+

int32_t OpenDevice(const UsbDevice &device, USBDevicePipe &pip);

+

Opens a USB device to set up a connection.

+

int32_t HasRight(std::string deviceName);

+

Checks whether the user has the permission to access the USB device.

+

int32_t RequestRight(std::string deviceName);

+

Requests the temporary permission for a given application to access the USB device.

+

int32_t GetDevices(std::vector &deviceList);

+

Obtains the USB device list.

+

int32_t ClaimInterface(USBDevicePipe &pip, const UsbInterface &interface, bool force);

+

Claims a USB interface exclusively. This must be done before data transfer.

+

int32_t ReleaseInterface(USBDevicePipe &pip, const UsbInterface &interface);

+

Releases a USB interface. This is usually done after data transfer.

+

int32_t BulkTransfer(USBDevicePipe &pip, const USBEndpoint &endpoint, std::vector &vdata, int32_t timeout);

+

Performs a bulk transfer on a specified endpoint. The data transfer direction is determined by the endpoint direction.

+

int32_t ControlTransfer(USBDevicePipe &pip, const UsbCtrlTransfer &ctrl, std::vector &vdata);

+

Performs control transaction for endpoint 0 of the device. The transmission direction is determined by the request type.

+

int32_t SetConfiguration(USBDevicePipe &pip, const USBConfig &config);

+

Sets the current configuration of the USB device.

+

int32_t SetInterface(USBDevicePipe &pipe, const UsbInterface &interface);

+

Sets the alternate settings for the specified USB interface. This allows you to switch between two interfaces with the same ID but different alternate settings.

+

int32_t GetRawDescriptors(std::vector &vdata);

+

Obtains the raw USB descriptor.

+

int32_t GetFileDescriptor();

+

Obtains the file descriptor.

+

bool Close(const USBDevicePipe &pip);

+

Closes a USB device to release all system resources related to the device.

+

int32_t PipeRequestWait(USBDevicePipe &pip, int64_t timeout, UsbRequest &req);

+

Obtains the isochronous transfer result.

+

int32_t RequestInitialize(UsbRequest &request);

+

Initializes the isochronous transfer request.

+

int32_t RequestFree(UsbRequest &request);

+

Frees the isochronous transfer request.

+
+

int32_t RequestAbort(UsbRequest &request);

+

Cancels the data transfer requests to be processed.

+

int32_t RequestQueue(UsbRequest &request);

+

Sends or receives isochronous data requests on a specified endpoint. The data transfer direction is determined by the endpoint direction.

+

int32_t BulkRequstDataSize(const UsbDev &dev, const UsbPipe &pipe, uint32_t &length);

+

Reads bulk data in isochronous manner. This method is applicable to transfer of a huge amount of data.

+

int32_t BulkReadData(const UsbDev &dev, const UsbPipe &pipe, std::vector &data);

+

Obtains the data reading result. Use this method together with BulkReadData. +

int32_t BulkWriteData(const UsbDev &dev, const UsbPipe &pipe, const std::vector &data);

+

Writes bulk data in isochronous manner. This method is applicable to transfer of a huge amount of data.

+

int32_t BulkGetWriteCompleteLength(const UsbDev &dev, const UsbPipe &pipe, uint32_t &length);

+

Obtains the data writing status based on length. Use this method together with BulkWriteData.

+
+ +- ### Device + + + + + + + + + + + + + + + + + + + + + +

Header File

+

API

+

Description

+

usb_srv_client.h

+

+

+

int32_t GetCurrentFunctions(int32_t &funcs);

+

Obtains the numeric mask combination for the current USB function list in Device mode.

+

int32_t SetCurrentFunctions(int32_t funcs);

+

Sets the current USB function list in Device mode.

+

int32_t UsbFunctionsFromString(std::string funcs);

+

Converts the string descriptor of a given USB function list to a numeric mask combination.

+

std::string UsbFunctionsToString(int32_t funcs);

+

Converts the numeric mask combination of a given USB function list to a string descriptor.

+
+ +- ### Port + + + + + + + + + + + + + + + + + + +

Header File

+

API

+

Description

+

usb_srv_client.h

+

+

+

int32_t GetSupportedModes(int32_t portId, int32_t &supportedModes);

+

Obtains the mask combination for the supported mode list of a given port.

+

int32_t SetPortRole(int32_t portId, int32_t powerRole, int32_t dataRole);

+

Sets the role types supported by a specified port, which can be powerRole (for charging) or dataRole (for data transfer).

+

int32_t GetPorts(std::vector &usbPorts);

+

Obtains the USB port descriptor list.

+
diff --git a/en/device-dev/subsystems/subsys-usbservice.md b/en/device-dev/subsystems/subsys-usbservice.md new file mode 100644 index 0000000000..369a182c4f --- /dev/null +++ b/en/device-dev/subsystems/subsys-usbservice.md @@ -0,0 +1,7 @@ +# USB + +- **[USB Overview](subsys-usbservice-overview.md)** + +- **[USB Usage Guidelines](subsys-usbservice-guide.md)** + +- **[USB Usage Example](subsys-usbservice-demo.md)** \ No newline at end of file -- GitLab