Commit 5a116a27 authored by Richard Machado's avatar Richard Machado Committed by Commit Bot

Impl. UsbDeviceHandleMac

I implemented all virtual methods of UsbDeviceHandle, which includes all
the types of transfer methods. I also implemented various helper methods
to assist with the mac implementation of UsbDeviceHandle.

Bug: 1096743
Change-Id: I8f2d0edeb818ef7e80805e51edd3b32e8e038d08
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2300638
Commit-Queue: Ricky Machado <richardmachado@google.com>
Reviewed-by: default avatarMatt Reynolds <mattreynolds@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarOvidio de Jesús Ruiz-Henríquez <odejesush@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796613}
parent 3ca55e54
...@@ -12,22 +12,36 @@ ...@@ -12,22 +12,36 @@
#include <IOKit/IOReturn.h> #include <IOKit/IOReturn.h>
#include <IOKit/usb/IOUSBLib.h> #include <IOKit/usb/IOUSBLib.h>
#include <memory>
#include <vector> #include <vector>
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_ioplugininterface.h" #include "base/mac/scoped_ioplugininterface.h"
#include "base/memory/ref_counted.h"
#include "services/device/public/mojom/usb_device.mojom.h" #include "services/device/public/mojom/usb_device.mojom.h"
namespace base {
class RefCountedBytes;
}
namespace device { namespace device {
class UsbDeviceMac; class UsbDeviceMac;
struct Transfer;
class UsbDeviceHandleMac : public UsbDeviceHandle { class UsbDeviceHandleMac : public UsbDeviceHandle {
public: public:
UsbDeviceHandleMac(const UsbDeviceHandleMac&) = delete; using ScopedIOUSBDeviceInterface =
UsbDeviceHandleMac& operator=(const UsbDeviceHandleMac&) = delete; base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182>;
using ScopedIOUSBInterfaceInterface =
base::mac::ScopedIOPluginInterface<IOUSBInterfaceInterface182>;
// UsbDeviceHandle implementation: // UsbDeviceHandle implementation:
UsbDeviceHandleMac(scoped_refptr<UsbDeviceMac> device,
ScopedIOUSBDeviceInterface device_interface);
UsbDeviceHandleMac(const UsbDeviceHandleMac&) = delete;
UsbDeviceHandleMac& operator=(const UsbDeviceHandleMac&) = delete;
scoped_refptr<UsbDevice> GetDevice() const override; scoped_refptr<UsbDevice> GetDevice() const override;
void Close() override; void Close() override;
void SetConfiguration(int configuration_value, void SetConfiguration(int configuration_value,
...@@ -67,17 +81,64 @@ class UsbDeviceHandleMac : public UsbDeviceHandle { ...@@ -67,17 +81,64 @@ class UsbDeviceHandleMac : public UsbDeviceHandle {
const mojom::UsbInterfaceInfo* FindInterfaceByEndpoint( const mojom::UsbInterfaceInfo* FindInterfaceByEndpoint(
uint8_t endpoint_address) override; uint8_t endpoint_address) override;
UsbDeviceHandleMac(scoped_refptr<UsbDeviceMac> device,
base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182>
device_interface);
protected: protected:
~UsbDeviceHandleMac() override; ~UsbDeviceHandleMac() override;
friend class UsbDeviceMac;
private: private:
base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182> device_interface_; struct EndpointMapValue {
const mojom::UsbInterfaceInfo* interface;
const mojom::UsbEndpointInfo* endpoint;
uint8_t pipe_reference;
};
void BulkIn(const ScopedIOUSBInterfaceInterface& interface_interface,
uint8_t pipe_reference,
scoped_refptr<base::RefCountedBytes> buffer,
uint32_t timeout,
std::unique_ptr<Transfer> transfer);
void BulkOut(const ScopedIOUSBInterfaceInterface& interface_interface,
uint8_t pipe_reference,
scoped_refptr<base::RefCountedBytes> buffer,
uint32_t timeout,
std::unique_ptr<Transfer> transfer);
void InterruptIn(const ScopedIOUSBInterfaceInterface& interface_interface,
uint8_t pipe_reference,
scoped_refptr<base::RefCountedBytes> buffer,
std::unique_ptr<Transfer> transfer);
void InterruptOut(const ScopedIOUSBInterfaceInterface& interface_interface,
uint8_t pipe_reference,
scoped_refptr<base::RefCountedBytes> buffer,
std::unique_ptr<Transfer> transfer);
// Refresh endpoint_map_ after ClaimInterface, ReleaseInterface and
// SetInterfaceAlternateSetting. It is needed so that endpoints can be mapped
// to their respective mojom Interface.
void RefreshEndpointMap();
void ReportIsochronousTransferError(
UsbDeviceHandle::IsochronousTransferCallback callback,
std::vector<uint32_t> packet_lengths,
mojom::UsbTransferStatus status);
void Clear();
void OnAsyncGeneric(IOReturn result, size_t size, Transfer* transfer);
void OnAsyncIsochronous(IOReturn result, size_t size, Transfer* transfer);
static void AsyncIoCallback(void* refcon, IOReturn result, void* arg0);
// A map from the endpoint indices to its corresponding EndpointMapValue,
// which contains the Interface and Endpoint Mojo structures.
using EndpointMap = base::flat_map<int, EndpointMapValue>;
EndpointMap endpoint_map_;
base::flat_set<std::unique_ptr<Transfer>, base::UniquePtrComparator>
transfers_;
ScopedIOUSBDeviceInterface device_interface_;
scoped_refptr<UsbDeviceMac> device_; scoped_refptr<UsbDeviceMac> device_;
// Both maps take the interface number in as the respective key.
base::flat_map<uint8_t, ScopedIOUSBInterfaceInterface> interfaces_;
base::flat_map<uint8_t, base::ScopedCFTypeRef<CFRunLoopSourceRef>> sources_;
}; };
} // namespace device } // namespace device
......
...@@ -36,7 +36,6 @@ void UsbDeviceMac::Open(OpenCallback callback) { ...@@ -36,7 +36,6 @@ void UsbDeviceMac::Open(OpenCallback callback) {
std::move(callback).Run(nullptr); std::move(callback).Run(nullptr);
return; return;
} }
// IOServiceGetMatchingService consumes a reference to the matching dictionary // IOServiceGetMatchingService consumes a reference to the matching dictionary
// passed to it. // passed to it.
base::mac::ScopedIOObject<io_service_t> usb_device( base::mac::ScopedIOObject<io_service_t> usb_device(
...@@ -60,13 +59,12 @@ void UsbDeviceMac::Open(OpenCallback callback) { ...@@ -60,13 +59,12 @@ void UsbDeviceMac::Open(OpenCallback callback) {
} }
base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182> device_interface; base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182> device_interface;
IOReturn result = kr = (*plugin_interface)
(*plugin_interface)
->QueryInterface( ->QueryInterface(
plugin_interface.get(), plugin_interface.get(),
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
reinterpret_cast<LPVOID*>(device_interface.InitializeInto())); reinterpret_cast<LPVOID*>(device_interface.InitializeInto()));
if (result || !device_interface) { if (kr != kIOReturnSuccess || !device_interface) {
USB_LOG(ERROR) << "Couldn’t create a device interface."; USB_LOG(ERROR) << "Couldn’t create a device interface.";
std::move(callback).Run(nullptr); std::move(callback).Run(nullptr);
return; return;
...@@ -83,8 +81,7 @@ void UsbDeviceMac::Open(OpenCallback callback) { ...@@ -83,8 +81,7 @@ void UsbDeviceMac::Open(OpenCallback callback) {
this, std::move(device_interface)); this, std::move(device_interface));
handles().push_back(device_handle.get()); handles().push_back(device_handle.get());
std::move(callback).Run(device_handle);
std::move(callback).Run(nullptr);
} }
} // namespace device } // namespace device
...@@ -149,8 +149,9 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceAdded( ...@@ -149,8 +149,9 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceAdded(
return; return;
std::unique_ptr<UsbDeviceDescriptor> descriptor(new UsbDeviceDescriptor()); std::unique_ptr<UsbDeviceDescriptor> descriptor(new UsbDeviceDescriptor());
if (!descriptor->Parse(std::vector<uint8_t>(descriptors_str.begin(), if (!descriptor->Parse(base::make_span(
descriptors_str.end()))) { reinterpret_cast<const uint8_t*>(descriptors_str.data()),
descriptors_str.size()))) {
return; return;
} }
......
...@@ -158,14 +158,13 @@ void UsbServiceMac::AddDevice(io_service_t device) { ...@@ -158,14 +158,13 @@ void UsbServiceMac::AddDevice(io_service_t device) {
} }
base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182> device_interface; base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182> device_interface;
IOReturn result = kr = (*plugin_interface)
(*plugin_interface)
->QueryInterface( ->QueryInterface(
plugin_interface.get(), plugin_interface.get(),
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
reinterpret_cast<LPVOID*>(device_interface.InitializeInto())); reinterpret_cast<LPVOID*>(device_interface.InitializeInto()));
if (result || !device_interface) { if (kr != kIOReturnSuccess || !device_interface) {
USB_LOG(ERROR) << "Couldn’t create a device interface."; USB_LOG(ERROR) << "Couldn’t create a device interface.";
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment