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 |