| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/midi/usb_midi_descriptor_parser.h" | 5 #include "media/midi/usb_midi_descriptor_parser.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/stringprintf.h" |
| 10 | 11 |
| 11 namespace media { | 12 namespace media { |
| 12 | 13 |
| 13 namespace { | 14 namespace { |
| 14 | 15 |
| 15 // The constants below are specified in USB spec, USB audio spec | 16 // The constants below are specified in USB spec, USB audio spec |
| 16 // and USB midi spec. | 17 // and USB midi spec. |
| 17 | 18 |
| 18 enum DescriptorType { | 19 enum DescriptorType { |
| 19 TYPE_DEVICE = 1, | 20 TYPE_DEVICE = 1, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 explicit JackMatcher(uint8 id) : id_(id) {} | 52 explicit JackMatcher(uint8 id) : id_(id) {} |
| 52 | 53 |
| 53 bool operator() (const UsbMidiJack& jack) const { | 54 bool operator() (const UsbMidiJack& jack) const { |
| 54 return jack.jack_id == id_; | 55 return jack.jack_id == id_; |
| 55 } | 56 } |
| 56 | 57 |
| 57 private: | 58 private: |
| 58 uint8 id_; | 59 uint8 id_; |
| 59 }; | 60 }; |
| 60 | 61 |
| 62 int DecodeBcd(uint8 byte) { |
| 63 DCHECK_LT((byte & 0xf0) >> 4, 0xa); |
| 64 DCHECK_LT(byte & 0x0f, 0xa); |
| 65 return ((byte & 0xf0) >> 4) * 10 + (byte & 0x0f); |
| 66 } |
| 67 |
| 61 } // namespace | 68 } // namespace |
| 62 | 69 |
| 70 std::string UsbMidiDescriptorParser::DeviceInfo::BcdVersionToString( |
| 71 uint16 version) { |
| 72 return base::StringPrintf("%d.%02d", DecodeBcd(version >> 8), |
| 73 DecodeBcd(version & 0xff)); |
| 74 } |
| 75 |
| 63 UsbMidiDescriptorParser::UsbMidiDescriptorParser() | 76 UsbMidiDescriptorParser::UsbMidiDescriptorParser() |
| 64 : is_parsing_usb_midi_interface_(false), | 77 : is_parsing_usb_midi_interface_(false), |
| 65 current_endpoint_address_(0), | 78 current_endpoint_address_(0), |
| 66 current_cable_number_(0) {} | 79 current_cable_number_(0) {} |
| 67 | 80 |
| 68 UsbMidiDescriptorParser::~UsbMidiDescriptorParser() {} | 81 UsbMidiDescriptorParser::~UsbMidiDescriptorParser() {} |
| 69 | 82 |
| 70 bool UsbMidiDescriptorParser::Parse(UsbMidiDevice* device, | 83 bool UsbMidiDescriptorParser::Parse(UsbMidiDevice* device, |
| 71 const uint8* data, | 84 const uint8* data, |
| 72 size_t size, | 85 size_t size, |
| 73 std::vector<UsbMidiJack>* jacks) { | 86 std::vector<UsbMidiJack>* jacks) { |
| 74 jacks->clear(); | 87 jacks->clear(); |
| 75 bool result = ParseInternal(device, data, size, jacks); | 88 bool result = ParseInternal(device, data, size, jacks); |
| 76 if (!result) | 89 if (!result) |
| 77 jacks->clear(); | 90 jacks->clear(); |
| 78 Clear(); | 91 Clear(); |
| 79 return result; | 92 return result; |
| 80 } | 93 } |
| 81 | 94 |
| 95 bool UsbMidiDescriptorParser::ParseDeviceInfo( |
| 96 const uint8* data, size_t size, DeviceInfo* info) { |
| 97 *info = DeviceInfo(); |
| 98 for (const uint8* current = data; |
| 99 current < data + size; |
| 100 current += current[0]) { |
| 101 uint8 length = current[0]; |
| 102 if (length < 2) { |
| 103 DVLOG(1) << "Descriptor Type is not accessible."; |
| 104 return false; |
| 105 } |
| 106 if (current + length > data + size) { |
| 107 DVLOG(1) << "The header size is incorrect."; |
| 108 return false; |
| 109 } |
| 110 DescriptorType descriptor_type = static_cast<DescriptorType>(current[1]); |
| 111 if (descriptor_type != TYPE_DEVICE) |
| 112 continue; |
| 113 // We assume that ParseDevice doesn't modify |*info| if it returns false. |
| 114 return ParseDevice(current, length, info); |
| 115 } |
| 116 // No DEVICE descriptor is found. |
| 117 return false; |
| 118 } |
| 119 |
| 82 bool UsbMidiDescriptorParser::ParseInternal(UsbMidiDevice* device, | 120 bool UsbMidiDescriptorParser::ParseInternal(UsbMidiDevice* device, |
| 83 const uint8* data, | 121 const uint8* data, |
| 84 size_t size, | 122 size_t size, |
| 85 std::vector<UsbMidiJack>* jacks) { | 123 std::vector<UsbMidiJack>* jacks) { |
| 86 for (const uint8* current = data; | 124 for (const uint8* current = data; |
| 87 current < data + size; | 125 current < data + size; |
| 88 current += current[0]) { | 126 current += current[0]) { |
| 89 uint8 length = current[0]; | 127 uint8 length = current[0]; |
| 90 if (length < 2) { | 128 if (length < 2) { |
| 91 DVLOG(1) << "Descriptor Type is not accessible."; | 129 DVLOG(1) << "Descriptor Type is not accessible."; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 122 return false; | 160 return false; |
| 123 break; | 161 break; |
| 124 default: | 162 default: |
| 125 // Ignore uninteresting types. | 163 // Ignore uninteresting types. |
| 126 break; | 164 break; |
| 127 } | 165 } |
| 128 } | 166 } |
| 129 return true; | 167 return true; |
| 130 } | 168 } |
| 131 | 169 |
| 170 bool UsbMidiDescriptorParser::ParseDevice( |
| 171 const uint8* data, size_t size, DeviceInfo* info) { |
| 172 if (size < 0x12) { |
| 173 DVLOG(1) << "DEVICE header size is incorrect."; |
| 174 return false; |
| 175 } |
| 176 |
| 177 info->vendor_id = data[8] | (data[9] << 8); |
| 178 info->product_id = data[0xa] | (data[0xb] << 8); |
| 179 info->bcd_device_version = data[0xc] | (data[0xd] << 8); |
| 180 info->manufacturer_index = data[0xe]; |
| 181 info->product_index = data[0xf]; |
| 182 return true; |
| 183 } |
| 184 |
| 132 bool UsbMidiDescriptorParser::ParseInterface(const uint8* data, size_t size) { | 185 bool UsbMidiDescriptorParser::ParseInterface(const uint8* data, size_t size) { |
| 133 if (size != 9) { | 186 if (size != 9) { |
| 134 DVLOG(1) << "INTERFACE header size is incorrect."; | 187 DVLOG(1) << "INTERFACE header size is incorrect."; |
| 135 return false; | 188 return false; |
| 136 } | 189 } |
| 137 incomplete_jacks_.clear(); | 190 incomplete_jacks_.clear(); |
| 138 | 191 |
| 139 uint8 interface_class = data[5]; | 192 uint8 interface_class = data[5]; |
| 140 uint8 interface_subclass = data[6]; | 193 uint8 interface_subclass = data[6]; |
| 141 | 194 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 279 } |
| 227 | 280 |
| 228 void UsbMidiDescriptorParser::Clear() { | 281 void UsbMidiDescriptorParser::Clear() { |
| 229 is_parsing_usb_midi_interface_ = false; | 282 is_parsing_usb_midi_interface_ = false; |
| 230 current_endpoint_address_ = 0; | 283 current_endpoint_address_ = 0; |
| 231 current_cable_number_ = 0; | 284 current_cable_number_ = 0; |
| 232 incomplete_jacks_.clear(); | 285 incomplete_jacks_.clear(); |
| 233 } | 286 } |
| 234 | 287 |
| 235 } // namespace media | 288 } // namespace media |
| OLD | NEW |