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 * The device needs to be open before the kernel driver can be detached.<br>
184 * libusb does not validate the device handle and dereferences it right away, so a device which is not open would crash instead of returning an error.
185 * @param interfaceIndex The index of the interface for which the kernel driver will be detached
186 * @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)
187 * @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
188 * @see isOpen().
189 */
190 [[nodiscard]] ScopedSubscription detachKernelDriver(const int interfaceIndex, bool* driverWasNotActive = nullptr);
191
192 /**
193 * Claims an interface of the device.
194 * The device needs to be open before an interface can be claimed.<br>
195 * libusb does not validate the device handle and dereferences it right away, so a device which is not open would crash instead of returning an error.
196 * @param interfaceIndex The index of the interface to claim
197 * @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
198 * @see isOpen().
199 */
200 [[nodiscard]] ScopedSubscription claimInterface(const int interfaceIndex);
201
202 /**
203 * Returns the wrapped libusb device.
204 * @return The libusb device, nullptr if now device is wrapped
205 * @see isValid().
206 */
207 inline libusb_device* usbDevice();
208
209 /**
210 * Returns the handle to the wrapped libusb device.
211 * @return The libusb device handle, nullptr if the device is not yet opened
212 * @see isValid().
213 */
214 inline libusb_device_handle* usbDeviceHandle();
215
216 /**
217 * Explicitly releases the device.
218 * In case the device is opened, the device will be closed.
219 * Further, all claimed interfaces will be released and detached kernel drivers will re-attached.
220 */
221 void release();
222
223 /**
224 * The context which is associated with this device.
225 * @return The device's context, nullptr if the device is associated with the default context
226 */
227 inline SharedContext context() const;
228
229 /**
230 * Returns whether this device is valid.
231 * A valid device does not need to be open.
232 * @return True, of so
233 * @see isOpen().
234 */
235 inline bool isValid() const;
236
237 /**
238 * Returns whether this device is open.
239 * A device is open if a corresponding device handle exists.
240 * @return True, if so
241 * @see isValid().
242 */
243 inline bool isOpen() const;
244
245 /**
246 * Returns whether this device is wrapping a device based on a given system device handle.
247 * @return True, if so
248 */
249 inline bool isWrapped() const;
250
251 /**
252 * Returns the class code of this device.
253 * The device needs to be valid.
254 * @return The device's class code
255 */
256 inline libusb_class_code classCode() const;
257
258 /**
259 * Move operator.
260 * @param device The device to be moved
261 * @return The reference to this device
262 */
264
265 /**
266 * Returns a string descriptor of an opened device.
267 * @param usbDeviceHandle The handle of the device for which the string descriptor will be returned
268 * @param index The index of the string descriptor to return
269 * @return The resulting string descriptor, empty in case of an error
270 */
271 static std::string stringDescriptor(libusb_device_handle* usbDeviceHandle, const uint8_t index);
272
273 protected:
274
275 /**
276 * Initializes this device with a given opened libusb device.
277 * @param context The context which is associated with the device, nullptr to use the default context
278 * @param usbDevice The opened libusb device, must be valid
279 * @param usbDeviceHandle The handle to the opened libusb device, must be valid
280 * @return True, if succeeded
281 */
282 bool initialize(SharedContext context, libusb_device* usbDevice, libusb_device_handle* usbDeviceHandle);
283
284 /**
285 * Re-attaches a detached kernel driver for a specified interface.
286 * @param interfaceIndex The index of the interface
287 */
288 void reattachKernelDriver(const int interfaceIndex);
289
290 /**
291 * Releases a claimed interface.
292 * @param interfaceIndex The index of the interface
293 */
294 void releaseInterface(const int interfaceIndex);
295
296 /**
297 * Disabled copy constructor.
298 */
299 Device(const Device&) = delete;
300
301 /**
302 * Disabled copy operator.
303 * @return Reference to this object
304 */
305 Device& operator=(const Device&) = delete;
306
307 /**
308 * Extracts the payload buffers from a given USB transfer object.
309 * The transfer can be an isochronous transfer or a bulk transfer.<br>
310 * The memory is not copied, only pointers and size are extracted from the transfer.<br>
311 * Thus, the resulting buffers are only valid as long the transfer object is not released.<br>
312 * @param usbTransfer The transfer object from which the payload buffers will be extracted, must have status LIBUSB_TRANSFER_COMPLETED
313 * @param bufferPointers The resulting payload buffers, one in case of bulk mode, multiple buffers in case of isochronous mode
314 * @return True, if succeeded
315 */
316 static bool extractPayload(struct libusb_transfer& usbTransfer, BufferPointers& bufferPointers);
317
318 /**
319 * Determines the layout of an isochronous transfer.
320 * @param usbContext The context to be used, nullptr to use the default context
321 * @param interface The interface on which the transfer will happen
322 * @param endpointAddress The address of the endpoint on which the transfer will happen
323 * @param maxVideoFrameSize The maximal size of a video frame, in bytes, with range [1, infinity)
324 * @param maxPayloadTransferSize The maximal transfer size of payload, in bytes, with range [1, infinity)
325 * @param transferSize The resulting size of an entire transfer, in bytes
326 * @param packetsPerTransfer The resulting number of packets per transfer
327 * @param bytesPerPacket The resulting number of bytes per packet
328 * @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
329 */
330 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);
331
332 protected:
333
334 /// The context which is associated with this device, nullptr if the default context is used.
336
337 /// Optional system device handle in case this object is wrapped (e.g., on Android platforms).
338 int64_t systemDeviceHandle_ = 0;
339
340 /// The actual libusb device.
341 libusb_device* usbDevice_ = nullptr;
342
343 /// The handle to the opened libusb device.
344 libusb_device_handle* usbDeviceHandle_ = nullptr;
345
346 /// The device descriptor of this device.
347 libusb_device_descriptor usbDeviceDescriptor_ = {};
348
349 /// The usage counter for detached kernel drivers.
351
352 /// The usage counter for claimed interfaces.
354
355 /// The device's lock.
356 mutable Lock lock_;
357};
358
359inline Device::Device(Device&& device)
360{
361 *this = std::move(device);
362}
363
364inline libusb_device* Device::usbDevice()
365{
366 const ScopedLock scopedLock(lock_);
367
368 return usbDevice_;
369}
370
371inline libusb_device_handle* Device::usbDeviceHandle()
372{
373 const ScopedLock scopedLock(lock_);
374
375 return usbDeviceHandle_;
376}
377
379{
380 return context_;
381}
382
383inline bool Device::isValid() const
384{
385 const ScopedLock scopedLock(lock_);
386
387 return usbDevice_ != nullptr;
388}
389
390inline bool Device::isOpen() const
391{
392 const ScopedLock scopedLock(lock_);
393
394 return usbDeviceHandle_ != nullptr;
395}
396
397inline bool Device::isWrapped() const
398{
399 const ScopedLock scopedLock(lock_);
400
401 ocean_assert(systemDeviceHandle_ == 0 || isValid());
402
403 return systemDeviceHandle_ != 0;
404}
405
406inline libusb_class_code Device::classCode() const
407{
408 const ScopedLock scopedLock(lock_);
409
410 ocean_assert(isValid());
411
412 return libusb_class_code(usbDeviceDescriptor_.bDeviceClass);
413}
414
415}
416
417}
418
419}
420
421#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:147
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:378
bool isValid() const
Returns whether this device is valid.
Definition system/usb/Device.h:383
int64_t systemDeviceHandle_
Optional system device handle in case this object is wrapped (e.g., on Android platforms).
Definition system/usb/Device.h:338
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:335
UsageMap detachedInterfaceUsageMap_
The usage counter for detached kernel drivers.
Definition system/usb/Device.h:350
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:390
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:397
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:341
UsageMap claimedInterfaceUsageMap_
The usage counter for claimed interfaces.
Definition system/usb/Device.h:353
libusb_device_handle * usbDeviceHandle()
Returns the handle to the wrapped libusb device.
Definition system/usb/Device.h:371
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:356
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:406
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:344
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:347
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:364
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