Ocean
Loading...
Searching...
No Matches
system/usb/Device.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_SYSTEM_USB_DEVICE_H
9#define META_OCEAN_SYSTEM_USB_DEVICE_H
10
13
14#include "ocean/base/Lock.h"
16
17namespace Ocean
18{
19
20namespace System
21{
22
23namespace USB
24{
25
26// Forward declaration.
27class Device;
28
29/**
30 * Definition of a shared pointer holding a device.
31 * @see Device.
32 * @ingroup systemusb
33 */
34using SharedDevice = std::shared_ptr<Device>;
35
36/**
37 * Definition of a vector holding SharedDevice objects.
38 * @see SharedDevice.
39 * @ingroup systemusb
40 */
41using SharedDevices = std::vector<SharedDevice>;
42
43/**
44 * This class wraps a libusb device.
45 * The class holds a reference to the libusb device as long as the object exists.
46 * @ingroup systemusb
47 */
48class OCEAN_SYSTEM_USB_EXPORT Device
49{
50 public:
51
52 /**
53 * Definition of a scoped subscription object.
54 */
56
57 protected:
58
59 /**
60 * Definition of an unordered map mapping interface indices to usages.
61 */
62 using UsageMap = std::unordered_map<int, unsigned int>;
63
64 /**
65 * Definition of a pair combining a pointer to a buffer and the size of this buffer.
66 */
67 using BufferPointer = std::pair<const void*, size_t>;
68
69 /**
70 * Definition of a vector holding buffer pointers.
71 */
72 using BufferPointers = std::vector<BufferPointer>;
73
74 public:
75
76 /**
77 * Default constructor creating an invalid device.
78 */
79 Device() = default;
80
81 /**
82 * Move constructor.
83 * @param device The device to be moved
84 */
85 inline Device(Device&& device);
86
87 /**
88 * Creates a new device object based on a given (not yet opened) libusb device.
89 * @param context The USB context to be used, invalid to use the default context
90 * @param usbDevice The libusb device to be wrapped, the device is not yet open (otherwise a handle would exist), must be valid
91 */
92 Device(SharedContext context, libusb_device* usbDevice);
93
94 /**
95 * Creates a new device object based on a given libusb device handle (which means that the devices is already opened).
96 * @param context The USB context to be used, invalid to use the default context
97 * @param usbDeviceHandle The handle of the device, must be valid
98 */
99 Device(SharedContext context, libusb_device_handle* usbDeviceHandle);
100
101 /**
102 * Creates a new device object based on a given (already opened) libusb device and its device handle.
103 * @param context The USB context to be used, invalid to use the default context
104 * @param usbDevice The libusb device to be wrapped, the device has been opened already (because a device handle exists), must be valid
105 * @param usbDeviceHandle The handle of the device, must be valid
106 */
107 Device(SharedContext context, libusb_device* usbDevice, libusb_device_handle* usbDeviceHandle);
108
109 /**
110 * Creates a new device object (for an already opened device) based on a given system handle.
111 * On some platforms like e.g., Android, the device must be opened on the Java side (resulting in a file descriptor), this file descriptor can then be used as a system handle.
112 * @param context The USB context to be used, invalid to use the default context
113 * @param systemDeviceHandle The system specific handle to the device (e.g., a file descriptor received from Java on Android platforms), must be valid
114 */
115 Device(SharedContext context, const int64_t systemDeviceHandle);
116
117 /**
118 * Destructs the device and releases all resources.
119 */
120 virtual ~Device();
121
122 /**
123 * Returns the vendor id of the device.
124 * @return The device's vendor id
125 */
126 uint16_t vendorId() const;
127
128 /**
129 * Returns the product id of the device.
130 * @return The device's product id
131 */
132 uint16_t productId() const;
133
134 /**
135 * Returns the name of the device (not the product name).
136 * @return The device's name
137 */
138 std::string name() const;
139
140 /**
141 * Returns the product name of the device.
142 * The device needs to be open before the product name can be queried.<br>
143 * In case the name of the product is not available, a lookup table is used based on the vendor id and product id.
144 * @return The device's product name, empty if not available
145 * @see isOpen().
146 */
147 std::string productName() const;
148
149 /**
150 * Returns the manufacturer name of this device.
151 * The device needs to be open before the manufacturer name can be queried.<br>
152 * In case the name of the manufacturer is not available, a lookup table is used based on the vendor id.
153 * @return The device's manufacturer name, empty if not available
154 * @see isOpen().
155 */
156 std::string manufacturerName() const;
157
158 /**
159 * Returns the serial number of this device.
160 * The device needs to be open before the serial number can be queried.
161 * @return The device's serial number, empty if not available
162 * @see isOpen().
163 */
164 std::string serialNumber() const;
165
166 /**
167 * Opens the device.
168 * @return True, if succeeded
169 * @see isOpen().
170 */
171 bool open();
172
173 /**
174 * Closes an opened device.
175 * In case the device was opened via a system device handle (e.g., a file descriptor on Android platforms, calling this function does have no effect).
176 * @return True, if succeeded
177 * @see isOpen().
178 */
179 bool close();
180
181 /**
182 * Detaches the kernel driver for the device.
183 * @param interfaceIndex The index of the interface for which the kernel driver will be detached
184 * @param driverWasNotActive Optional resulting information why the resulting subscription object may be invalid; True, in case no kernel driver was active (may indicate that there was no need to detach the driver)
185 * @return The scoped subscription object which will keep the driver detached as long as the subscription object exists, an invalid subscription in case of an error
186 */
187 [[nodiscard]] ScopedSubscription detachKernelDriver(const int interfaceIndex, bool* driverWasNotActive = nullptr);
188
189 /**
190 * Claims an interface of the device.
191 * @param interfaceIndex The index of the interface to claim
192 * @return The scoped subscription object which will keep the interface claimed as long as the subscription object exists, an invalid subscription in case of an error
193 */
194 [[nodiscard]] ScopedSubscription claimInterface(const int interfaceIndex);
195
196 /**
197 * Returns the wrapped libusb device.
198 * @return The libusb device, nullptr if now device is wrapped
199 * @see isValid().
200 */
201 inline libusb_device* usbDevice();
202
203 /**
204 * Returns the handle to the wrapped libusb device.
205 * @return The libusb device handle, nullptr if the device is not yet opened
206 * @see isValid().
207 */
208 inline libusb_device_handle* usbDeviceHandle();
209
210 /**
211 * Explicitly releases the device.
212 * In case the device is opened, the device will be closed.
213 * Further, all claimed interfaces will be released and detached kernel drivers will re-attached.
214 */
215 void release();
216
217 /**
218 * The context which is associated with this device.
219 * @return The device's context, nullptr if the device is associated with the default context
220 */
221 inline SharedContext context() const;
222
223 /**
224 * Returns whether this device is valid.
225 * A valid device does not need to be open.
226 * @return True, of so
227 * @see isOpen().
228 */
229 inline bool isValid() const;
230
231 /**
232 * Returns whether this device is open.
233 * A device is open if a corresponding device handle exists.
234 * @return True, if so
235 * @see isValid().
236 */
237 inline bool isOpen() const;
238
239 /**
240 * Returns whether this device is wrapping a device based on a given system device handle.
241 * @return True, if so
242 */
243 inline bool isWrapped() const;
244
245 /**
246 * Returns the class code of this device.
247 * The device needs to be valid.
248 * @return The device's class code
249 */
250 inline libusb_class_code classCode() const;
251
252 /**
253 * Move operator.
254 * @param device The device to be moved
255 * @return The reference to this device
256 */
258
259 /**
260 * Returns a string descriptor of an opened device.
261 * @param usbDeviceHandle The handle of the device for which the string descriptor will be returned
262 * @param index The index of the string descriptor to return
263 * @return The resulting string descriptor, empty in case of an error
264 */
265 static std::string stringDescriptor(libusb_device_handle* usbDeviceHandle, const uint8_t index);
266
267 protected:
268
269 /**
270 * Initializes this device with a given opened libusb device.
271 * @param context The context which is associated with the device, nullptr to use the default context
272 * @param usbDevice The opened libusb device, must be valid
273 * @param usbDeviceHandle The handle to the opened libusb device, must be valid
274 * @return True, if succeeded
275 */
276 bool initialize(SharedContext context, libusb_device* usbDevice, libusb_device_handle* usbDeviceHandle);
277
278 /**
279 * Re-attaches a detached kernel driver for a specified interface.
280 * @param interfaceIndex The index of the interface
281 */
282 void reattachKernelDriver(const int interfaceIndex);
283
284 /**
285 * Releases a claimed interface.
286 * @param interfaceIndex The index of the interface
287 */
288 void releaseInterface(const int interfaceIndex);
289
290 /**
291 * Disabled copy constructor.
292 */
293 Device(const Device&) = delete;
294
295 /**
296 * Disabled copy operator.
297 * @return Reference to this object
298 */
299 Device& operator=(const Device&) = delete;
300
301 /**
302 * Extracts the payload buffers from a given USB transfer object.
303 * The transfer can be an isochronous transfer or a bulk transfer.<br>
304 * The memory is not copied, only pointers and size are extracted from the transfer.<br>
305 * Thus, the resulting buffers are only valid as long the transfer object is not released.<br>
306 * @param usbTransfer The transfer object from which the payload buffers will be extracted, must have status LIBUSB_TRANSFER_COMPLETED
307 * @param bufferPointers The resulting payload buffers, one in case of bulk mode, multiple buffers in case of isochronous mode
308 * @return True, if succeeded
309 */
310 static bool extractPayload(struct libusb_transfer& usbTransfer, BufferPointers& bufferPointers);
311
312 /**
313 * Determines the layout of an isochronous transfer.
314 * @param usbContext The context to be used, nullptr to use the default context
315 * @param interface The interface on which the transfer will happen
316 * @param endpointAddress The address of the endpoint on which the transfer will happen
317 * @param maxVideoFrameSize The maximal size of a video frame, in bytes, with range [1, infinity)
318 * @param maxPayloadTransferSize The maximal transfer size of payload, in bytes, with range [1, infinity)
319 * @param transferSize The resulting size of an entire transfer, in bytes
320 * @param packetsPerTransfer The resulting number of packets per transfer
321 * @param bytesPerPacket The resulting number of bytes per packet
322 * @return The index of the altsetting which supports the specified maximal video frame size and payload size, -1 if no matching altsetting could be found
323 */
324 static int determineIsochronousTransferLayout(libusb_context* usbContext, const libusb_interface& interface, const uint8_t endpointAddress, const uint32_t maxVideoFrameSize, const uint32_t maxPayloadTransferSize, size_t& transferSize, size_t& packetsPerTransfer, size_t& bytesPerPacket);
325
326 protected:
327
328 /// The context which is associated with this device, nullptr if the default context is used.
330
331 /// Optional system device handle in case this object is wrapped (e.g., on Android platforms).
332 int64_t systemDeviceHandle_ = 0;
333
334 /// The actual libusb device.
335 libusb_device* usbDevice_ = nullptr;
336
337 /// The handle to the opened libusb device.
338 libusb_device_handle* usbDeviceHandle_ = nullptr;
339
340 /// The device descriptor of this device.
341 libusb_device_descriptor usbDeviceDescriptor_ = {};
342
343 /// The usage counter for detached kernel drivers.
345
346 /// The usage counter for claimed interfaces.
348
349 /// The device's lock.
350 mutable Lock lock_;
351};
352
353inline Device::Device(Device&& device)
354{
355 *this = std::move(device);
356}
357
358inline libusb_device* Device::usbDevice()
359{
360 const ScopedLock scopedLock(lock_);
361
362 return usbDevice_;
363}
364
365inline libusb_device_handle* Device::usbDeviceHandle()
366{
367 const ScopedLock scopedLock(lock_);
368
369 return usbDeviceHandle_;
370}
371
373{
374 return context_;
375}
376
377inline bool Device::isValid() const
378{
379 const ScopedLock scopedLock(lock_);
380
381 return usbDevice_ != nullptr;
382}
383
384inline bool Device::isOpen() const
385{
386 const ScopedLock scopedLock(lock_);
387
388 return usbDeviceHandle_ != nullptr;
389}
390
391inline bool Device::isWrapped() const
392{
393 const ScopedLock scopedLock(lock_);
394
395 ocean_assert(systemDeviceHandle_ == 0 || isValid());
396
397 return systemDeviceHandle_ != 0;
398}
399
400inline libusb_class_code Device::classCode() const
401{
402 const ScopedLock scopedLock(lock_);
403
404 ocean_assert(isValid());
405
406 return libusb_class_code(usbDeviceDescriptor_.bDeviceClass);
407}
408
409}
410
411}
412
413}
414
415#endif // META_OCEAN_SYSTEM_USB_DEVICE_H
This class implements a recursive lock object.
Definition Lock.h:31
This class implements a scoped lock object for recursive lock objects.
Definition Lock.h:135
This class implements a subscription object which can be used unique subscriptions to e....
Definition ScopedSubscription.h:28
This class wraps a libusb device.
Definition system/usb/Device.h:49
SharedContext context() const
The context which is associated with this device.
Definition system/usb/Device.h:372
bool isValid() const
Returns whether this device is valid.
Definition system/usb/Device.h:377
int64_t systemDeviceHandle_
Optional system device handle in case this object is wrapped (e.g., on Android platforms).
Definition system/usb/Device.h:332
void releaseInterface(const int interfaceIndex)
Releases a claimed interface.
SharedContext context_
The context which is associated with this device, nullptr if the default context is used.
Definition system/usb/Device.h:329
UsageMap detachedInterfaceUsageMap_
The usage counter for detached kernel drivers.
Definition system/usb/Device.h:344
uint16_t vendorId() const
Returns the vendor id of the device.
std::string serialNumber() const
Returns the serial number of this device.
Device(const Device &)=delete
Disabled copy constructor.
static std::string stringDescriptor(libusb_device_handle *usbDeviceHandle, const uint8_t index)
Returns a string descriptor of an opened device.
Device(SharedContext context, const int64_t systemDeviceHandle)
Creates a new device object (for an already opened device) based on a given system handle.
bool isOpen() const
Returns whether this device is open.
Definition system/usb/Device.h:384
std::string manufacturerName() const
Returns the manufacturer name of this device.
std::string productName() const
Returns the product name of the device.
std::string name() const
Returns the name of the device (not the product name).
Device & operator=(const Device &)=delete
Disabled copy operator.
static bool extractPayload(struct libusb_transfer &usbTransfer, BufferPointers &bufferPointers)
Extracts the payload buffers from a given USB transfer object.
static int determineIsochronousTransferLayout(libusb_context *usbContext, const libusb_interface &interface, const uint8_t endpointAddress, const uint32_t maxVideoFrameSize, const uint32_t maxPayloadTransferSize, size_t &transferSize, size_t &packetsPerTransfer, size_t &bytesPerPacket)
Determines the layout of an isochronous transfer.
void reattachKernelDriver(const int interfaceIndex)
Re-attaches a detached kernel driver for a specified interface.
ScopedSubscription claimInterface(const int interfaceIndex)
Claims an interface of the device.
bool isWrapped() const
Returns whether this device is wrapping a device based on a given system device handle.
Definition system/usb/Device.h:391
std::unordered_map< int, unsigned int > UsageMap
Definition of an unordered map mapping interface indices to usages.
Definition system/usb/Device.h:62
Device & operator=(Device &&device)
Move operator.
ScopedSubscription detachKernelDriver(const int interfaceIndex, bool *driverWasNotActive=nullptr)
Detaches the kernel driver for the device.
std::pair< const void *, size_t > BufferPointer
Definition of a pair combining a pointer to a buffer and the size of this buffer.
Definition system/usb/Device.h:67
libusb_device * usbDevice_
The actual libusb device.
Definition system/usb/Device.h:335
UsageMap claimedInterfaceUsageMap_
The usage counter for claimed interfaces.
Definition system/usb/Device.h:347
libusb_device_handle * usbDeviceHandle()
Returns the handle to the wrapped libusb device.
Definition system/usb/Device.h:365
virtual ~Device()
Destructs the device and releases all resources.
Device()=default
Default constructor creating an invalid device.
bool close()
Closes an opened device.
Lock lock_
The device's lock.
Definition system/usb/Device.h:350
Device(SharedContext context, libusb_device *usbDevice, libusb_device_handle *usbDeviceHandle)
Creates a new device object based on a given (already opened) libusb device and its device handle.
libusb_class_code classCode() const
Returns the class code of this device.
Definition system/usb/Device.h:400
Device(SharedContext context, libusb_device_handle *usbDeviceHandle)
Creates a new device object based on a given libusb device handle (which means that the devices is al...
libusb_device_handle * usbDeviceHandle_
The handle to the opened libusb device.
Definition system/usb/Device.h:338
void release()
Explicitly releases the device.
Device(SharedContext context, libusb_device *usbDevice)
Creates a new device object based on a given (not yet opened) libusb device.
libusb_device_descriptor usbDeviceDescriptor_
The device descriptor of this device.
Definition system/usb/Device.h:341
std::vector< BufferPointer > BufferPointers
Definition of a vector holding buffer pointers.
Definition system/usb/Device.h:72
bool initialize(SharedContext context, libusb_device *usbDevice, libusb_device_handle *usbDeviceHandle)
Initializes this device with a given opened libusb device.
libusb_device * usbDevice()
Returns the wrapped libusb device.
Definition system/usb/Device.h:358
uint16_t productId() const
Returns the product id of the device.
bool open()
Opens the device.
std::shared_ptr< Device > SharedDevice
Definition of a shared pointer holding a device.
Definition system/usb/Device.h:34
std::vector< SharedDevice > SharedDevices
Definition of a vector holding SharedDevice objects.
Definition system/usb/Device.h:41
std::shared_ptr< Context > SharedContext
Definition of a shared pointer holding a context.
Definition system/usb/Context.h:32
The namespace covering the entire Ocean framework.
Definition Accessor.h:15