// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "device/usb/mojo/type_converters.h" #include #include #include #include #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "device/usb/usb_device.h" #include "mojo/common/url_type_converters.h" #include "mojo/public/cpp/bindings/array.h" namespace mojo { // static device::UsbDeviceFilter TypeConverter::Convert( const device::usb::DeviceFilterPtr& mojo_filter) { device::UsbDeviceFilter filter; if (mojo_filter->has_vendor_id) filter.SetVendorId(mojo_filter->vendor_id); if (mojo_filter->has_product_id) filter.SetProductId(mojo_filter->product_id); if (mojo_filter->has_class_code) filter.SetInterfaceClass(mojo_filter->class_code); if (mojo_filter->has_subclass_code) filter.SetInterfaceSubclass(mojo_filter->subclass_code); if (mojo_filter->has_protocol_code) filter.SetInterfaceProtocol(mojo_filter->protocol_code); return filter; } // static device::usb::TransferDirection TypeConverter:: Convert(const device::UsbEndpointDirection& direction) { if (direction == device::USB_DIRECTION_INBOUND) return device::usb::TransferDirection::INBOUND; DCHECK(direction == device::USB_DIRECTION_OUTBOUND); return device::usb::TransferDirection::OUTBOUND; } // static device::usb::TransferStatus TypeConverter::Convert( const device::UsbTransferStatus& status) { switch (status) { case device::USB_TRANSFER_COMPLETED: return device::usb::TransferStatus::COMPLETED; case device::USB_TRANSFER_ERROR: return device::usb::TransferStatus::TRANSFER_ERROR; case device::USB_TRANSFER_TIMEOUT: return device::usb::TransferStatus::TIMEOUT; case device::USB_TRANSFER_CANCELLED: return device::usb::TransferStatus::CANCELLED; case device::USB_TRANSFER_STALLED: return device::usb::TransferStatus::STALLED; case device::USB_TRANSFER_DISCONNECT: return device::usb::TransferStatus::DISCONNECT; case device::USB_TRANSFER_OVERFLOW: return device::usb::TransferStatus::BABBLE; case device::USB_TRANSFER_LENGTH_SHORT: return device::usb::TransferStatus::SHORT_PACKET; default: NOTREACHED(); return device::usb::TransferStatus::TRANSFER_ERROR; } } // static device::UsbDeviceHandle::TransferRequestType TypeConverter:: Convert(const device::usb::ControlTransferType& type) { switch (type) { case device::usb::ControlTransferType::STANDARD: return device::UsbDeviceHandle::STANDARD; case device::usb::ControlTransferType::CLASS: return device::UsbDeviceHandle::CLASS; case device::usb::ControlTransferType::VENDOR: return device::UsbDeviceHandle::VENDOR; case device::usb::ControlTransferType::RESERVED: return device::UsbDeviceHandle::RESERVED; default: NOTREACHED(); return device::UsbDeviceHandle::RESERVED; } } // static device::UsbDeviceHandle::TransferRecipient TypeConverter:: Convert(const device::usb::ControlTransferRecipient& recipient) { switch (recipient) { case device::usb::ControlTransferRecipient::DEVICE: return device::UsbDeviceHandle::DEVICE; case device::usb::ControlTransferRecipient::INTERFACE: return device::UsbDeviceHandle::INTERFACE; case device::usb::ControlTransferRecipient::ENDPOINT: return device::UsbDeviceHandle::ENDPOINT; case device::usb::ControlTransferRecipient::OTHER: return device::UsbDeviceHandle::OTHER; default: NOTREACHED(); return device::UsbDeviceHandle::OTHER; } } // static device::usb::EndpointType TypeConverter::Convert( const device::UsbTransferType& type) { switch (type) { case device::USB_TRANSFER_ISOCHRONOUS: return device::usb::EndpointType::ISOCHRONOUS; case device::USB_TRANSFER_BULK: return device::usb::EndpointType::BULK; case device::USB_TRANSFER_INTERRUPT: return device::usb::EndpointType::INTERRUPT; // Note that we do not expose control transfer in the public interface // because control endpoints are implied rather than explicitly enumerated // there. default: NOTREACHED(); return device::usb::EndpointType::BULK; } } // static device::usb::EndpointInfoPtr TypeConverter:: Convert(const device::UsbEndpointDescriptor& endpoint) { device::usb::EndpointInfoPtr info = device::usb::EndpointInfo::New(); info->endpoint_number = endpoint.address; info->direction = ConvertTo(endpoint.direction); info->type = ConvertTo(endpoint.transfer_type); info->packet_size = static_cast(endpoint.maximum_packet_size); return info; } // static device::usb::AlternateInterfaceInfoPtr TypeConverter:: Convert(const device::UsbInterfaceDescriptor& interface) { device::usb::AlternateInterfaceInfoPtr info = device::usb::AlternateInterfaceInfo::New(); info->alternate_setting = interface.alternate_setting; info->class_code = interface.interface_class; info->subclass_code = interface.interface_subclass; info->protocol_code = interface.interface_protocol; // Filter out control endpoints for the public interface. info->endpoints = mojo::Array::New(0); for (const auto& endpoint : interface.endpoints) { if (endpoint.transfer_type != device::USB_TRANSFER_CONTROL) info->endpoints.push_back(device::usb::EndpointInfo::From(endpoint)); } return info; } // static mojo::Array TypeConverter, std::vector>:: Convert(const std::vector& interfaces) { auto infos = mojo::Array::New(0); // Aggregate each alternate setting into an InterfaceInfo corresponding to its // interface number. std::map interface_map; for (size_t i = 0; i < interfaces.size(); ++i) { auto alternate = device::usb::AlternateInterfaceInfo::From(interfaces[i]); auto iter = interface_map.find(interfaces[i].interface_number); if (iter == interface_map.end()) { // This is the first time we're seeing an alternate with this interface // number, so add a new InterfaceInfo to the array and map the number. auto info = device::usb::InterfaceInfo::New(); iter = interface_map .insert( std::make_pair(interfaces[i].interface_number, info.get())) .first; infos.push_back(std::move(info)); } iter->second->alternates.push_back(std::move(alternate)); } return infos; } // static device::usb::ConfigurationInfoPtr TypeConverter:: Convert(const device::UsbConfigDescriptor& config) { device::usb::ConfigurationInfoPtr info = device::usb::ConfigurationInfo::New(); info->configuration_value = config.configuration_value; info->interfaces = mojo::Array::From(config.interfaces); return info; } // static device::usb::WebUsbFunctionSubsetPtr TypeConverter< device::usb::WebUsbFunctionSubsetPtr, device::WebUsbFunctionSubset>::Convert(const device::WebUsbFunctionSubset& function) { device::usb::WebUsbFunctionSubsetPtr info = device::usb::WebUsbFunctionSubset::New(); info->first_interface = function.first_interface; info->origins = mojo::Array::From(function.origins); return info; } // static device::usb::WebUsbConfigurationSubsetPtr TypeConverter:: Convert(const device::WebUsbConfigurationSubset& config) { device::usb::WebUsbConfigurationSubsetPtr info = device::usb::WebUsbConfigurationSubset::New(); info->configuration_value = config.configuration_value; info->origins = mojo::Array::From(config.origins); info->functions = mojo::Array::From(config.functions); return info; } // static device::usb::WebUsbDescriptorSetPtr TypeConverter< device::usb::WebUsbDescriptorSetPtr, device::WebUsbAllowedOrigins>::Convert(const device::WebUsbAllowedOrigins& allowed_origins) { device::usb::WebUsbDescriptorSetPtr info = device::usb::WebUsbDescriptorSet::New(); info->origins = mojo::Array::From(allowed_origins.origins); info->configurations = mojo::Array::From( allowed_origins.configurations); return info; } // static device::usb::DeviceInfoPtr TypeConverter::Convert( const device::UsbDevice& device) { device::usb::DeviceInfoPtr info = device::usb::DeviceInfo::New(); info->guid = device.guid(); info->vendor_id = device.vendor_id(); info->product_id = device.product_id(); info->manufacturer_name = base::UTF16ToUTF8(device.manufacturer_string()); info->product_name = base::UTF16ToUTF8(device.product_string()); info->serial_number = base::UTF16ToUTF8(device.serial_number()); info->configurations = mojo::Array::From( device.configurations()); if (device.webusb_allowed_origins()) { info->webusb_allowed_origins = device::usb::WebUsbDescriptorSet::From( *device.webusb_allowed_origins()); } return info; } // static device::usb::IsochronousPacketPtr TypeConverter:: Convert(const device::UsbDeviceHandle::IsochronousPacket& packet) { device::usb::IsochronousPacketPtr info = device::usb::IsochronousPacket::New(); info->length = packet.length; info->transferred_length = packet.transferred_length; info->status = mojo::ConvertTo(packet.status); return info; } } // namespace mojo