• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef OHOS_LIBUSB_ADAPTER_H
17 #define OHOS_LIBUSB_ADAPTER_H
18 
19 #include <memory>
20 #include <mutex>
21 #include <thread>
22 #include <list>
23 #include <map>
24 #include <queue>
25 #include <condition_variable>
26 #include <atomic>
27 #include <libusb.h>
28 
29 #include "libusb_sa_subscriber.h"
30 #include "v1_2/iusb_interface.h"
31 #include "v2_0/iusb_host_interface.h"
32 namespace OHOS {
33 namespace HDI {
34 namespace Usb {
35 namespace V2_0 {
36 class IUsbdSubscriber;
37 class IUsbdBulkCallback;
38 }
39 }
40 }
41 }
42 namespace OHOS {
43 namespace HDI {
44 namespace Usb {
45 namespace V1_2 {
46 
47 struct SyncTranfer {
48     int length;
49     int *transferred;
50     unsigned int timeout;
51 };
52 struct SendRequestAshmemParameter {
53     int32_t ashmemFd;
54     uint32_t ashmemSize;
55 };
56 
57 struct LibusbAsyncTransfer {
LibusbAsyncTransferLibusbAsyncTransfer58     explicit LibusbAsyncTransfer(uint32_t numOfIsoPackage)
59     {
60         transferRef = libusb_alloc_transfer(numOfIsoPackage);
61         ashmemRef = nullptr;
62     }
63 
~LibusbAsyncTransferLibusbAsyncTransfer64     ~LibusbAsyncTransfer()
65     {
66         if (transferRef != nullptr) {
67             libusb_free_transfer(transferRef);
68             transferRef = nullptr;
69         }
70         ashmemRef = nullptr;
71         cbRef = nullptr;
72     }
73 
74     libusb_transfer *transferRef;
75     sptr<Ashmem> ashmemRef;
76     sptr<V1_2::IUsbdTransferCallback> cbRef = nullptr;
77     int32_t busNum = 0;
78     int32_t devAddr = 0;
79     uint64_t userData = 0;
80 };
81 
82 struct LibusbAsyncWrapper {
83     std::list<LibusbAsyncTransfer *> transferList;
84     std::mutex transferLock;
85 };
86 
87 struct LibusbAsyncManager {
88     std::vector<std::pair<UsbDev, LibusbAsyncWrapper*>> transferVec;
89     std::mutex transferVecLock;
90 };
91 
92 struct DeviceInfo {
93     uint64_t deviceId;
94     uint16_t vendorId;
95 };
96 
97 struct LibusbBulkTransfer {
98     explicit LibusbBulkTransfer();
99     ~LibusbBulkTransfer();
100 
101     libusb_transfer *bulkTransferRef;
102     sptr<Ashmem> buikAshmemRef;
103     sptr<V2_0::IUsbdBulkCallback> bulkCbRef;
104     int32_t busNum = 0;
105     int32_t devAddr = 0;
106     bool isTransferring {false};
107 };
108 
109 struct LibusbBulkWrapper {
110     std::list<LibusbBulkTransfer *> bulkTransferList;
111     std::mutex bulkTransferLock;
112 };
113 
114 struct LibusbBulkManager {
115     std::vector<std::pair<UsbDev, LibusbBulkWrapper*>> bulktransferVec;
116     std::mutex bulkTransferVecLock;
117 };
118 
119 struct HotplugInfo {
120 public:
HotplugInfoHotplugInfo121     HotplugInfo() : subscriberPtr(nullptr){};
HotplugInfoHotplugInfo122     HotplugInfo(OHOS::HDI::Usb::V2_0::USBDeviceInfo &info, sptr<V2_0::IUsbdSubscriber> subscriber)
123         : hotplugInfo(info),
124         subscriberPtr(subscriber) {};
125 
126     OHOS::HDI::Usb::V2_0::USBDeviceInfo hotplugInfo = {0, 0, 0};
127     sptr<V2_0::IUsbdSubscriber> subscriberPtr;
128 };
129 
130 class HotplugEventPorcess {
131 public:
132     static std::shared_ptr<HotplugEventPorcess> GetInstance();
133     void AddHotplugTask(OHOS::HDI::Usb::V2_0::USBDeviceInfo &info,
134         sptr<V2_0::IUsbdSubscriber> subscriber = nullptr);
135     int32_t SetSubscriber(sptr<V2_0::IUsbdSubscriber> subscriber);
136     int32_t RemoveSubscriber(sptr<V2_0::IUsbdSubscriber> subscriber);
137     size_t GetSubscriberSize();
138     ~HotplugEventPorcess();
139     HotplugEventPorcess();
140 private:
141     std::queue<HotplugInfo> hotplugEventQueue_;
142     std::mutex queueMutex_;
143     std::condition_variable queueCv_;
144     std::atomic<int32_t> activeThreads_;
145     bool shutdown_;
146     std::list<sptr<V2_0::IUsbdSubscriber>> subscribers_;
147     static std::shared_ptr<HotplugEventPorcess> instance_;
148     static std::mutex mtx_;
149     void OnProcessHotplugEvent();
150 };
151 
152 class LibusbAdapter {
153 public:
154     LibusbAdapter();
155     ~LibusbAdapter();
156     int32_t OpenDevice(const UsbDev &dev);
157     int32_t CloseDevice(const UsbDev &dev, bool isDetach = false);
158     int32_t ResetDevice(const UsbDev &dev);
159     int32_t GetDeviceDescriptor(const UsbDev &dev, std::vector<uint8_t> &descriptor);
160     int32_t GetDeviceFileDescriptor(const UsbDev &dev, int32_t &fd);
161     int32_t SetConfig(const UsbDev &dev, uint8_t configIndex);
162     int32_t GetConfig(const UsbDev &dev, uint8_t &configIndex);
163     int32_t ManageInterface(const UsbDev &dev, uint8_t interfaceId, bool disable);
164     int32_t BulkTransferRead(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, std::vector<uint8_t> &data);
165     int32_t BulkTransferReadwithLength(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, int32_t length,
166         std::vector<uint8_t> &data);
167     int32_t BulkTransferWrite(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout,
168         const std::vector<uint8_t> &data);
169     int32_t IsoTransferRead(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, std::vector<uint8_t> &data);
170     int32_t IsoTransferWrite(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout,
171         const std::vector<uint8_t> &data);
172     int32_t GetConfigDescriptor(const UsbDev &dev, uint8_t descId, std::vector<uint8_t> &descriptor);
173     int32_t ReleaseInterface(const UsbDev &dev, uint8_t interfaceId);
174     int32_t SetInterface(const UsbDev &dev, uint8_t interfaceId, uint8_t altIndex);
175     int32_t ClearHalt(const UsbDev &dev, const UsbPipe &pipe);
176     int32_t InterruptTransferRead(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout, std::vector<uint8_t> &data);
177     int32_t InterruptTransferWrite(const UsbDev &dev, const UsbPipe &pipe, int32_t timeout,
178         const std::vector<uint8_t> &data);
179     int32_t GetStringDescriptor(const UsbDev &dev, uint8_t descId, std::vector<uint8_t> &descriptor);
180     int32_t ClaimInterface(const UsbDev &dev, uint8_t interfaceId, uint8_t force);
181     int32_t ControlTransferRead(const UsbDev &dev, const UsbCtrlTransfer &ctrl, std::vector<uint8_t> &data);
182     int32_t ControlTransferWrite(const UsbDev &dev, const UsbCtrlTransfer &ctrl, const std::vector<uint8_t> &data);
183     int32_t ControlTransferReadwithLength(const UsbDev &dev, const UsbCtrlTransferParams &ctrlParams,
184         std::vector<uint8_t> &data);
185     int32_t GetFileDescriptor(const UsbDev &dev, int32_t &fd);
186     int32_t GetDeviceSpeed(const UsbDev &dev, uint8_t &speed);
187     int32_t GetInterfaceActiveStatus(const UsbDev &dev, uint8_t interfaceId, bool &unactivated);
188     int32_t SendPipeRequestWithAshmem(const UsbDev &dev, unsigned char endpointAddr,
189         SendRequestAshmemParameter sendRequestAshmemParameter, uint32_t &transferredLength, unsigned int timeout);
190     int32_t SendPipeRequest(const UsbDev &dev, unsigned char endpointAddr, uint32_t size,
191         uint32_t &transferedLength, unsigned int timeout);
192     int32_t GetRawDescriptor(const UsbDev &dev, std::vector<uint8_t> &descriptor);
193     int32_t GetCurrentInterfaceSetting(const UsbDev &dev, uint8_t &settingIndex);
194     int32_t GetDeviceMemMapFd(const UsbDev &dev, int &fd);
195     int32_t GetDevices(std::vector<struct DeviceInfo> &devices);
196     int32_t SetSubscriber(sptr<V2_0::IUsbdSubscriber> subscriber);
197     int32_t RemoveSubscriber(sptr<V2_0::IUsbdSubscriber> subscriber);
198     void ReportUsbdRecognitionFailSysEvent(const std::string &operationType, int32_t code,
199         const std::string &failDescription, libusb_device *device = nullptr);
200 
201     /* Async Transfer */
202     int32_t AsyncSubmitTransfer(const UsbDev &dev, const V1_2::USBTransferInfo &info,
203         const sptr<V1_2::IUsbdTransferCallback> &cb, const sptr<Ashmem> &ashmem);
204     int32_t AsyncCancelTransfer(const UsbDev &dev, const int32_t endpoint);
205 
206     /* Bulk Transfer */
207     int32_t BulkRead(const UsbDev &dev, const UsbPipe &pipe, const sptr<Ashmem> &ashmem);
208     int32_t BulkWrite(const UsbDev &dev, const UsbPipe &pipe, const sptr<Ashmem> &ashmem);
209     int32_t BulkCancel(const UsbDev &dev, const UsbPipe &pipe);
210     int32_t RegBulkCallback(const UsbDev &dev, const UsbPipe &pipe, const sptr<V2_0::IUsbdBulkCallback> &cb);
211     int32_t UnRegBulkCallback(const UsbDev &dev, const UsbPipe &pipe);
212 
213     int32_t SetLoadUsbSaSubscriber(sptr<V1_2::LibUsbSaSubscriber> libUsbSaSubscriber);
214     static std::shared_ptr<LibusbAdapter> GetInstance();
215 
216 private:
217     int32_t LibUSBInit();
218     void LibUSBExit();
219     void GetCurrentDeviceList(libusb_context *ctx, sptr<V2_0::IUsbdSubscriber> subscriber);
220     void GetCurrentDevList(libusb_context *ctx, sptr<V1_2::LibUsbSaSubscriber> libUsbSaSubscriber);
221     int32_t GetUsbDevice(const UsbDev &dev, libusb_device **device);
222     int32_t FindHandleByDev(const UsbDev &dev, libusb_device_handle **handle);
223     void DeleteSettingsMap(libusb_device_handle* handle);
224     int32_t DoControlTransfer(const UsbDev &dev, const UsbCtrlTransfer &ctrl, std::vector<uint8_t> &data);
225     int32_t ReadDescriptors(int32_t fd, void **descriptors, size_t &descriptorsLength);
226     int32_t GetUsbDevicePath(const UsbDev &dev, char *pathBuf, size_t length);
227     void *AdapterRealloc(void *ptr, size_t oldSize, size_t newSize);
228     void *AllocateUsbDescriptorsMemory(size_t size);
229     void FreeUsbDescriptorsMemory(void *mem);
230     int32_t GetConfigDescriptor(libusb_device *dev, uint8_t descId, std::vector<uint8_t> &descriptor);
231     int32_t ProcessInterfaceDescriptors(const libusb_interface *iface, std::vector<uint8_t> &descriptor,
232         size_t &currentOffset);
233     struct libusb_config_descriptor* FindConfigDescriptorById(libusb_device *dev, uint8_t descId);
234     void ProcessExtraData(std::vector<uint8_t> &descriptor, size_t &currentOffset, const unsigned char *extra,
235         int32_t extraLength);
236     int32_t GetEndpointDesc(const UsbDev &dev, const UsbPipe &pipe, libusb_endpoint_descriptor **endpoint_desc,
237         libusb_device_handle** deviceHandle);
238     int32_t GetEndpointDescFromInterface(const UsbPipe &pipe, const libusb_interface_descriptor *intf_desc,
239     libusb_endpoint_descriptor **endpoint_desc);
240     int32_t DoSyncPipeTranfer(libusb_device_handle *dev_handle, unsigned char endpoint,
241         unsigned char *buffer, SyncTranfer &syncTranfer);
242     unsigned char *GetMmapBufferByFd(int32_t fd, size_t len);
243     unsigned char *GetMmapFdAndBuffer(uint8_t busNumber, uint8_t busAddress, int32_t &fd, size_t len);
244     int32_t CloseMmapBuffer(void *mmapBuf, size_t length);
245     bool CheckDeviceAndConfiguration(libusb_device_handle *handle);
246     int32_t GetCurrentConfiguration(libusb_device_handle *handle, int32_t &currentConfig);
247     int32_t RemoveInterfaceFromMap(const UsbDev &dev, libusb_device_handle *devHandle, uint8_t interfaceId);
248     bool IsInterfaceIdByUsbDev(const UsbDev &dev, const uint8_t intfId);
249     /* Async Transfer */
250     void TransferInit(const UsbDev &dev);
251     void TransferRelease(const UsbDev &dev);
252     uint8_t *AllocAsyncBuffer(const V1_2::USBTransferInfo &info, const sptr<Ashmem> &ashmem);
253     LibusbAsyncTransfer *CreateAsyncTransfer(const UsbDev &dev, const V1_2::USBTransferInfo &info,
254         const sptr<Ashmem> &ashmem, const sptr<V1_2::IUsbdTransferCallback> &cb);
255     int32_t FillAndSubmitTransfer(LibusbAsyncTransfer *asyncTransfer, libusb_device_handle *devHandle,
256         unsigned char *buffer, const V1_2::USBTransferInfo &info);
257     void DeleteAsyncDevRequest(const UsbDev &dev);
258     void ClearAsyncTranfer(LibusbAsyncWrapper *asyncWrapper);
259     void LibusbEventHandling();
260     static LibusbAsyncWrapper *GetAsyncWrapper(const UsbDev &dev);
261     static void HandleAsyncFailure(struct libusb_transfer *transfer);
262     static void AddTransferToList(LibusbAsyncTransfer *asyncTransfer);
263     static void DeleteTransferFromList(LibusbAsyncTransfer *asyncTransfer);
264     static void FeedbackToBase(struct libusb_transfer *transfer);
265     static void ParseIsoPacketDesc(libusb_transfer *transfer, std::vector<V1_2::UsbIsoPacketDescriptor> &isoPkgDescs);
266     static int32_t ReadAshmem(const sptr<Ashmem> &ashmem, int32_t length, uint8_t *buffer);
267     static int32_t WriteAshmem(const sptr<Ashmem> &ashmem, int32_t length, uint8_t *buffer);
268     static void LIBUSB_CALL HandleAsyncResult(struct libusb_transfer *transfer);
269 
270     /* Bulk Transfer */
271     static int32_t BulkReadAshmem(const sptr<Ashmem> &ashmem, int32_t length, uint8_t *buffer);
272     static int32_t BulkWriteAshmem(const sptr<Ashmem> &ashmem, int32_t length, uint8_t *buffer);
273     uint8_t *AllocBulkBuffer(const UsbPipe &pipe, const int32_t &length, const sptr<Ashmem> &ashmem);
274     static void DeleteBulkTransferFromList(LibusbBulkTransfer *bulkTransfer);
275     static void HandleBulkFail(struct libusb_transfer *transfer);
276     static void BulkFeedbackToBase(struct libusb_transfer *transfer);
277     static void LIBUSB_CALL HandleBulkResult(struct libusb_transfer *transfer);
278     void BulkTransferInit(const UsbDev &dev);
279     void BulkTransferRelease(const UsbDev &dev);
280     void DeleteBulkDevRequest(const UsbDev &dev);
281     void ClearBulkTranfer(LibusbBulkWrapper *bulkWrapper);
282     static LibusbBulkWrapper *GetBulkWrapper(const UsbDev &dev);
283     LibusbBulkTransfer *FindBulkTransfer(const UsbDev &dev, const UsbPipe &pipe, const sptr<Ashmem> &ashmem);
284 
285     static int HotplugCallback(libusb_context* ctx, libusb_device* device,
286         libusb_hotplug_event event, void* user_data);
287     static int LoadUsbSaCallback(libusb_context* ctx, libusb_device* device,
288         libusb_hotplug_event event, void* user_data);
289 private:
290     std::atomic<bool> isRunning;
291     std::thread eventThread;
292     libusb_hotplug_callback_handle hotplug_handle_ = 0;
293     static sptr<V1_2::LibUsbSaSubscriber> libUsbSaSubscriber_;
294 };
295 } // namespace V1_2
296 } // namespace Usb
297 } // namespace HDI
298 } // namespace OHOS
299 #endif // OHOS_LIBUSB_ADAPTER_H
300