1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "device/usb/usb_device_filter.h" 6 7 #include "base/values.h" 8 #include "device/usb/usb_descriptors.h" 9 #include "device/usb/usb_device.h" 10 11 namespace device { 12 13 namespace { 14 15 const char kProductIdKey[] = "productId"; 16 const char kVendorIdKey[] = "vendorId"; 17 const char kInterfaceClassKey[] = "interfaceClass"; 18 const char kInterfaceSubclassKey[] = "interfaceSubclass"; 19 const char kInterfaceProtocolKey[] = "interfaceProtocol"; 20 21 } // namespace 22 23 UsbDeviceFilter::UsbDeviceFilter() 24 : vendor_id_set_(false), 25 product_id_set_(false), 26 interface_class_set_(false), 27 interface_subclass_set_(false), 28 interface_protocol_set_(false) { 29 } 30 31 UsbDeviceFilter::~UsbDeviceFilter() { 32 } 33 34 void UsbDeviceFilter::SetVendorId(uint16 vendor_id) { 35 vendor_id_set_ = true; 36 vendor_id_ = vendor_id; 37 } 38 39 void UsbDeviceFilter::SetProductId(uint16 product_id) { 40 product_id_set_ = true; 41 product_id_ = product_id; 42 } 43 44 void UsbDeviceFilter::SetInterfaceClass(uint8 interface_class) { 45 interface_class_set_ = true; 46 interface_class_ = interface_class; 47 } 48 49 void UsbDeviceFilter::SetInterfaceSubclass(uint8 interface_subclass) { 50 interface_subclass_set_ = true; 51 interface_subclass_ = interface_subclass; 52 } 53 54 void UsbDeviceFilter::SetInterfaceProtocol(uint8 interface_protocol) { 55 interface_protocol_set_ = true; 56 interface_protocol_ = interface_protocol; 57 } 58 59 bool UsbDeviceFilter::Matches(scoped_refptr<UsbDevice> device) const { 60 if (vendor_id_set_) { 61 if (device->vendor_id() != vendor_id_) { 62 return false; 63 } 64 65 if (product_id_set_ && device->product_id() != product_id_) { 66 return false; 67 } 68 } 69 70 if (interface_class_set_) { 71 bool foundMatch = false; 72 const UsbConfigDescriptor& config = device->GetConfiguration(); 73 74 // TODO(reillyg): Check device configuration if the class is not defined at 75 // a per-interface level. This is not really important because most devices 76 // have per-interface classes. The only counter-examples I know of are hubs. 77 78 for (UsbInterfaceDescriptor::Iterator ifaceIt = config.interfaces.begin(); 79 ifaceIt != config.interfaces.end() && !foundMatch; 80 ++ifaceIt) { 81 if (ifaceIt->interface_class == interface_class_ && 82 (!interface_subclass_set_ || 83 (ifaceIt->interface_subclass == interface_subclass_ && 84 (!interface_protocol_set_ || 85 ifaceIt->interface_protocol == interface_protocol_)))) { 86 foundMatch = true; 87 } 88 } 89 90 if (!foundMatch) { 91 return false; 92 } 93 } 94 95 return true; 96 } 97 98 base::Value* UsbDeviceFilter::ToValue() const { 99 scoped_ptr<base::DictionaryValue> obj(new base::DictionaryValue()); 100 101 if (vendor_id_set_) { 102 obj->SetInteger(kVendorIdKey, vendor_id_); 103 if (product_id_set_) { 104 obj->SetInteger(kProductIdKey, product_id_); 105 } 106 } 107 108 if (interface_class_set_) { 109 obj->SetInteger(kInterfaceClassKey, interface_class_); 110 if (interface_subclass_set_) { 111 obj->SetInteger(kInterfaceSubclassKey, interface_subclass_); 112 if (interface_protocol_set_) { 113 obj->SetInteger(kInterfaceProtocolKey, interface_protocol_); 114 } 115 } 116 } 117 118 return obj.release(); 119 } 120 121 // static 122 bool UsbDeviceFilter::MatchesAny(scoped_refptr<UsbDevice> device, 123 const std::vector<UsbDeviceFilter>& filters) { 124 for (std::vector<UsbDeviceFilter>::const_iterator i = filters.begin(); 125 i != filters.end(); 126 ++i) { 127 if (i->Matches(device)) { 128 return true; 129 } 130 } 131 return false; 132 } 133 134 } // namespace device 135