Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: media/midi/usb_midi_descriptor_parser.cc

Issue 105043008: Introduce USB MIDI descriptor parser (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "media/midi/usb_midi_descriptor_parser.h"
6
7 #include "base/logging.h"
8
9 namespace media {
10
11 namespace {
12
13 enum DescriptorType {
14 DEVICE = 1,
Takashi Toyoshima 2013/12/19 05:54:23 optional: I prefer to have TYPE_ prefix, e.g. TYPE
yhirano 2013/12/19 07:15:05 Done.
15 CONFIGURATION = 2,
16 STRING = 3,
17 INTERFACE = 4,
18 ENDPOINT = 5,
19 DEVICE_QUALIFIER = 6,
20 OTHER_SPEED_CONFIGURATION = 7,
21 INTERFACE_POWER = 8,
22
23 CS_INTERFACE = 36,
24 CS_ENDPOINT = 37,
25 };
26
27 enum DescriptorSubType {
28 MS_DESCRIPTOR_UNDEFINED = 0,
29 MS_HEADER = 1,
30 MIDI_IN_JACK = 2,
31 MIDI_OUT_JACK = 3,
32 ELEMENT = 4,
33 };
34
35 enum JackType {
36 JACK_TYPE_UNDEFINED = 0,
37 EMBEDDED = 1,
38 EXTERNAL = 2,
39 };
40
41 const uint8 kAudioInterfaceClass = 1;
Takashi Toyoshima 2013/12/19 05:54:23 Can you add some comments on them for someone who
yhirano 2013/12/19 07:15:05 Done in L13
42 const uint8 kAudioMidiInterfaceSubclass = 3;
43
44 } // namespace
45
46 UsbMidiDescriptorParser::UsbMidiDescriptorParser()
47 : is_parsing_usb_midi_interface_(false),
48 current_endpoint_address_(0),
49 current_cable_number_(0) {}
50
51 UsbMidiDescriptorParser::~UsbMidiDescriptorParser() {}
52
53 bool UsbMidiDescriptorParser::Parse(UsbMidiDevice* device,
54 const uint8* data,
55 size_t size) {
56 Clear();
57 bool result = ParseInternal(device, data, size);
58 if (result)
59 ClearExceptJacks();
60 else
61 Clear();
62 return result;
63 }
64
65 bool UsbMidiDescriptorParser::ParseInternal(UsbMidiDevice* device,
66 const uint8* data,
67 size_t size) {
Takashi Toyoshima 2013/12/19 05:54:23 If this function assumes that jacks_ is empty, it'
yhirano 2013/12/19 07:15:05 Done.
68 const uint8* current = data;
69 while (current < &data[size]) {
70 uint8 length = current[0];
71 if (length <= 1) {
72 DVLOG(1) << "Descriptor Type is not accessible.";
73 return false;
74 }
75 if (&current[length] > &data[size]) {
76 DVLOG(1) << "The header size is incorrect.";
77 return false;
78 }
79 uint8 descriptor_type = current[1];
Takashi Toyoshima 2013/12/19 05:54:23 Why don't you use DescriptorType instead of uint8?
yhirano 2013/12/19 07:15:05 Done.
80 switch (descriptor_type) {
81 case INTERFACE:
82 if (!ParseInterface(device, current, length)) return false;
Takashi Toyoshima 2013/12/19 05:54:23 I don't think this style is common in chromium. Ca
yhirano 2013/12/19 07:15:05 Done.
83 break;
84 case CS_INTERFACE:
85 if (!ParseCSInterface(device, current, length)) return false;
86 break;
87 case ENDPOINT:
88 if (!ParseEndpoint(device, current, length)) return false;
89 break;
90 case CS_ENDPOINT:
91 if (!ParseCSEndpoint(device, current, length)) return false;
92 break;
93 default:
94 break;
95 }
96 current += length;
97 }
98 return true;
99 }
100
101 bool UsbMidiDescriptorParser::ParseInterface(UsbMidiDevice* device,
102 const uint8* data,
103 size_t size) {
104 if (size != 9) {
105 DVLOG(1) << "INTERFACE header size is incorrect.";
106 return false;
107 }
108 incomplete_jacks_.clear();
109
110 uint8 interface_class = data[5];
111 uint8 interface_subclass = data[6];
112
113 is_parsing_usb_midi_interface_ =
114 (interface_class == kAudioInterfaceClass &&
115 interface_subclass == kAudioMidiInterfaceSubclass);
116 return true;
117 }
118
119 bool UsbMidiDescriptorParser::ParseCSInterface(UsbMidiDevice* device,
120 const uint8* data,
121 size_t size) {
122 if (!is_parsing_usb_midi_interface_) return true;
Takashi Toyoshima 2013/12/19 05:54:23 style
yhirano 2013/12/19 07:15:05 Done.
123
124 // Descriptor Type and Descriptor Subtype should be accessible.
125 if (size <= 2) {
126 DVLOG(1) << "CS_INTERFACE header size is incorrect.";
127 return false;
128 }
129
130 uint8 subtype = data[2];
Takashi Toyoshima 2013/12/19 05:54:23 DescriptorSubType
yhirano 2013/12/19 07:15:05 Done.
131
132 switch (subtype) {
133 case MIDI_IN_JACK:
134 // FALL_THROUGH
135 case MIDI_OUT_JACK: {
136 if (size < 6) {
137 DVLOG(1) << "CS_INTERFACE (MIDI JACK) header size is incorrect.";
138 return false;
139 }
140 uint8 jack_type = data[3];
141 uint8 id = data[4];
142 if (jack_type == EMBEDDED) {
143 // We can't determine the associated endpoint now.
144 incomplete_jacks_.insert(
145 std::make_pair(id, UsbMidiJack(device, id, 0, 0)));
146 }
147 }
148 break;
Takashi Toyoshima 2013/12/19 05:54:23 break at line 148 should be between line 146 and 1
yhirano 2013/12/19 07:15:05 Done.
149 default:
150 break;
151 }
152 return true;
153 }
154
155 bool UsbMidiDescriptorParser::ParseEndpoint(UsbMidiDevice* device,
156 const uint8* data,
157 size_t size) {
158 if (!is_parsing_usb_midi_interface_) return true;
159
160 if (size < 4) {
161 DVLOG(1) << "ENDPOINT header size is incorrect.";
162 return false;
163 }
164 current_endpoint_address_ = data[2];
165 current_cable_number_ = 0;
166 return true;
167 }
168
169 bool UsbMidiDescriptorParser::ParseCSEndpoint(UsbMidiDevice* device,
170 const uint8* data,
171 size_t size) {
172 if (!is_parsing_usb_midi_interface_) return true;
173 // CS_ENDPOINT must be of size 4 + n where n is the number of associated
174 // jacks.
175 if (size < 4) {
176 DVLOG(1) << "CS_ENDPOINT header size is incorrect.";
177 return false;
178 }
179 uint8 num_jacks = data[3];
180 if (size != 4 + num_jacks) {
181 DVLOG(1) << "CS_ENDPOINT header size is incorrect.";
182 return false;
183 }
184
185 for (size_t i = 0; i < num_jacks; ++i) {
186 uint8 jack = data[4 + i];
187 base::hash_map<uint8, UsbMidiJack>::iterator it =
188 incomplete_jacks_.find(jack);
189 if (it == incomplete_jacks_.end()) {
190 DVLOG(1) << "A non-existing MIDI jack is associated.";
191 return false;
192 }
193 if (current_cable_number_ >= 0x10) {
194 DVLOG(1) << "Cable number should range from 0x0 to 0xf.";
195 return false;
196 }
Takashi Toyoshima 2013/12/19 05:54:23 Can we assume CS_ENDPOINT always follows associate
yhirano 2013/12/19 07:15:05 Done here and at L121
197 it->second.cable_number = current_cable_number_++;
198 it->second.endpoint_address = current_endpoint_address_;
199 jacks_.push_back(it->second);
200 incomplete_jacks_.erase(it);
201 }
202 return true;
203 }
204
205 void UsbMidiDescriptorParser::Clear() {
206 ClearExceptJacks();
207 jacks_.clear();
208 }
209
210 void UsbMidiDescriptorParser::ClearExceptJacks() {
211 is_parsing_usb_midi_interface_ = false;
212 current_endpoint_address_ = 0;
213 current_cable_number_ = 0;
214 incomplete_jacks_.clear();
215 }
216
217 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698