motu: implement block async functions since they are ultimately required when dealing...
[ffado.git] / libffado / src / DeviceStringParser.cpp
blob7579b0c65642be0ad0af5757243a3a932d7e9074
1 /*
2 * Copyright (C) 2005-2008 by Pieter Palmers
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB.
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) version 3 of the License.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "DeviceStringParser.h"
26 #include <stdlib.h>
27 #include <errno.h>
29 #include <iostream>
30 #include <sstream>
32 #include "libieee1394/configrom.h"
33 #include "libieee1394/ieee1394service.h"
35 IMPL_DEBUG_MODULE( DeviceStringParser, DeviceStringParser, DEBUG_LEVEL_NORMAL );
37 DeviceStringParser::DeviceString::DeviceString(DeviceStringParser& parent)
38 : m_Parent(parent)
39 , m_node( -1 )
40 , m_port( -1 )
41 , m_guid( 0 )
42 , m_String("")
43 , m_Type(eInvalid)
44 , m_debugModule( parent.m_debugModule )
48 DeviceStringParser::DeviceString::~DeviceString()
52 bool
53 DeviceStringParser::DeviceString::parse(std::string s)
55 m_String = s;
56 debugOutput(DEBUG_LEVEL_VERBOSE, "parse: %s\n", s.c_str());
57 std::string prefix = s.substr(0,3);
59 if(s.compare(0,3,"hw:")==0) {
60 m_Type = eBusNode;
61 std::string detail = s.substr(3);
62 std::string::size_type comma_pos = detail.find_first_of(",");
63 if(comma_pos == std::string::npos) {
64 // node is unspecified
65 m_node = -1;
66 std::string port = detail;
67 errno = 0;
68 m_port = strtol(port.c_str(), NULL, 0);
69 if(errno) {
70 m_Type = eInvalid;
71 m_port = -1;
72 m_node = -1;
73 debugOutput(DEBUG_LEVEL_VERBOSE, "failed to parse port\n");
74 return false;
76 } else {
77 std::string port = detail.substr(0, comma_pos);
78 std::string node = detail.substr(comma_pos+1);
79 errno = 0;
80 m_port = strtol(port.c_str(), NULL, 0);
81 if(errno) {
82 m_Type = eInvalid;
83 m_port = -1;
84 m_node = -1;
85 debugOutput(DEBUG_LEVEL_VERBOSE, "failed to parse port\n");
86 return false;
88 errno = 0;
89 m_node = strtol(node.c_str(), NULL, 0);
90 if(errno) {
91 m_Type = eInvalid;
92 m_port = -1;
93 m_node = -1;
94 debugOutput(DEBUG_LEVEL_VERBOSE, "failed to parse node\n");
95 return false;
98 } else if (s.compare(0,5,"guid:")==0) {
99 std::string detail = s.substr(5);
100 m_Type = eGUID;
101 errno = 0;
102 m_guid = strtoll(detail.c_str(), NULL, 0);
103 if(errno) {
104 m_Type = eInvalid;
105 m_guid = 0;
106 debugOutput(DEBUG_LEVEL_VERBOSE, "failed to parse guid\n");
107 return false;
109 } else {
110 m_Type = eInvalid;
111 debugOutput(DEBUG_LEVEL_VERBOSE, "invalid\n");
112 return false;
114 return true;
117 bool
118 DeviceStringParser::DeviceString::isValidString(std::string s)
120 std::string prefix = s.substr(0,3);
121 if(s.compare(0,3,"hw:")==0) {
122 std::string detail = s.substr(3);
123 std::string::size_type comma_pos = detail.find_first_of(",");
124 if(comma_pos == std::string::npos) {
125 std::string port = detail;
126 errno = 0;
127 strtol(port.c_str(), NULL, 0);
128 if(errno) {
129 return false;
131 } else {
132 std::string port = detail.substr(0, comma_pos);
133 std::string node = detail.substr(comma_pos+1);
134 errno = 0;
135 strtol(port.c_str(), NULL, 0);
136 if(errno) {
137 return false;
139 errno = 0;
140 strtol(node.c_str(), NULL, 0);
141 if(errno) {
142 return false;
145 } else if (s.compare(0,5,"guid:")==0) {
146 std::string detail = s.substr(5);
147 errno = 0;
148 strtoll(detail.c_str(), NULL, 0);
149 if(errno) {
150 return false;
152 } else {
153 return false;
155 return true;
158 bool
159 DeviceStringParser::DeviceString::match(ConfigRom& configRom)
161 debugOutput(DEBUG_LEVEL_VERBOSE, "match %p (%s)\n", &configRom, configRom.getGuidString().c_str());
162 bool match;
163 switch(m_Type) {
164 case eBusNode:
165 if(m_port < 0) {
166 debugWarning("Need at least a port spec\n");
167 return false;
169 match = configRom.get1394Service().getPort() == m_port;
170 if(m_node >= 0) {
171 match &= ((configRom.getNodeId() & 0x3F) == m_node);
173 if(match) {
174 debugOutput(DEBUG_LEVEL_VERBOSE, "(eBusNode) device matches device string %s\n", m_String.c_str());
176 return match;
177 case eGUID:
178 //GUID should not be 0
179 match = m_guid && (m_guid == configRom.getGuid());
180 if(match) {
181 debugOutput(DEBUG_LEVEL_VERBOSE, "(eGUID) device matches device string %s\n", m_String.c_str());
183 return match;
184 case eInvalid:
185 default:
186 debugError("invalid DeviceString type (%d)\n", m_Type);
187 return false;
189 return false;
192 bool
193 DeviceStringParser::DeviceString::operator==(const DeviceString& x)
195 bool retval;
196 switch(m_Type) {
197 case eBusNode:
198 retval = (m_port == x.m_port) && (m_node == x.m_node);
199 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "eBusNode %d,%d == %d,%d? %d\n",
200 m_port, m_node, x.m_port, x.m_node, retval);
201 return retval;
202 case eGUID:
203 retval = m_guid && (m_guid == x.m_guid);
204 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "eGUID 0x%016"PRIX64" == 0x%016"PRIX64"? %d\n",
205 m_guid, x.m_guid, retval);
206 return retval;
207 case eInvalid:
208 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "eInvalid \n");
209 default:
210 return false;
214 void
215 DeviceStringParser::DeviceString::show()
217 debugOutput(DEBUG_LEVEL_INFO, "string: %s\n", m_String.c_str());
218 switch(m_Type) {
219 case eBusNode:
220 debugOutput(DEBUG_LEVEL_INFO, "type: eBusNode\n");
221 debugOutput(DEBUG_LEVEL_INFO, " Port: %d, Node: %d\n",
222 m_port, m_node);
223 break;
224 case eGUID:
225 debugOutput(DEBUG_LEVEL_INFO, "type: eGUID\n");
226 debugOutput(DEBUG_LEVEL_INFO, " GUID: %016"PRIX64"\n", m_guid);
227 break;
228 case eInvalid:
229 default:
230 debugOutput(DEBUG_LEVEL_INFO, "type: eInvalid\n");
231 break;
235 // ------------------------
236 DeviceStringParser::DeviceStringParser()
239 DeviceStringParser::~DeviceStringParser()
241 while(m_DeviceStrings.size()) {
242 DeviceString *tmp = m_DeviceStrings.at(0);
243 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "removing device string: %p\n", tmp);
244 m_DeviceStrings.erase(m_DeviceStrings.begin());
245 delete tmp;
249 bool
250 DeviceStringParser::parseString(std::string s)
252 debugOutput(DEBUG_LEVEL_VERBOSE, "parse: %s\n", s.c_str());
254 std::string::size_type next_sep;
255 std::string tmp = s;
256 do {
257 debugOutput(DEBUG_LEVEL_VERBOSE, " left: %s\n", tmp.c_str());
258 next_sep = tmp.find_first_of(";");
259 std::string to_parse = tmp.substr(0, next_sep);
260 DeviceString *d = new DeviceString(*this);
261 if(d == NULL) {
262 debugError("failed to allocate memory for device string\n");
263 continue;
265 if(d->parse(to_parse)) {
266 addDeviceString(d);
267 } else {
268 debugWarning("Failed to parse device substring: \"%s\"\n",
269 to_parse.c_str());
270 delete d;
272 tmp = tmp.substr(next_sep+1);
273 } while(tmp.size() && next_sep != std::string::npos);
275 pruneDuplicates();
277 return true;
280 bool
281 DeviceStringParser::isValidString(std::string s)
283 debugOutput(DEBUG_LEVEL_VERBOSE, "isvalid? %s\n", s.c_str());
284 return DeviceString::isValidString(s);
287 bool
288 DeviceStringParser::match(ConfigRom& c)
290 return matchPosition(c) != -1;
294 DeviceStringParser::matchPosition(ConfigRom& c)
296 int pos = 0;
297 for ( DeviceStringVectorIterator it = m_DeviceStrings.begin();
298 it != m_DeviceStrings.end();
299 ++it )
301 if((*it)->match(c)) {
302 return pos;
304 pos++;
306 return -1;
309 bool
310 DeviceStringParser::addDeviceString(DeviceString *o)
312 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "adding device string: %p\n", o);
313 if (hasDeviceString(o)){
314 return false;
316 m_DeviceStrings.push_back(o);
317 return true;
320 bool
321 DeviceStringParser::removeDeviceString(DeviceString *o)
323 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "removing device string: %p\n", o);
324 int i=findDeviceString(o);
325 if (i<0) {
326 debugOutput(DEBUG_LEVEL_VERBOSE, "not found\n");
327 return false;
328 } else {
329 DeviceString *tmp = m_DeviceStrings.at(i);
330 m_DeviceStrings.erase(m_DeviceStrings.begin()+i);
331 delete tmp;
332 return true;
336 bool
337 DeviceStringParser::hasDeviceString(DeviceString *o)
339 return (findDeviceString(o) >= 0);
343 DeviceStringParser::findDeviceString(DeviceString *o)
345 int i=0;
346 for ( DeviceStringVectorIterator it = m_DeviceStrings.begin();
347 it != m_DeviceStrings.end();
348 ++it )
350 if(*it == o) {
351 return i;
353 i++;
355 return -1;
358 void
359 DeviceStringParser::pruneDuplicates()
361 DeviceStringVector duplicates;
362 // find duplicates
363 for ( DeviceStringVectorIterator it = m_DeviceStrings.begin();
364 it != m_DeviceStrings.end();
365 ++it )
367 for ( DeviceStringVectorIterator it2 = it+1;
368 it2 != m_DeviceStrings.end();
369 ++it2 )
372 if(**it == **it2) {
373 duplicates.push_back(*it2);
378 // remove duplicates
379 for ( DeviceStringVectorIterator it = duplicates.begin();
380 it != duplicates.end();
381 ++it )
383 removeDeviceString(*it);
387 void
388 DeviceStringParser::show()
390 debugOutput(DEBUG_LEVEL_INFO, "DeviceStringParser: %p\n", this);
391 for ( DeviceStringVectorIterator it = m_DeviceStrings.begin();
392 it != m_DeviceStrings.end();
393 ++it )
395 (*it)->show();
399 void
400 DeviceStringParser::setVerboseLevel(int i)
402 setDebugLevel(i);