root/trunk/libffado/src/DeviceStringParser.cpp

Revision 1763, 10.9 kB (checked in by ppalmers, 14 years ago)

Merged revisions 1536,1541,1544-1546,1549,1554-1562,1571,1579-1581,1618,1632,1634-1635,1661,1677-1679,1703-1704,1715,1720-1723,1743-1745,1755 via svnmerge from
svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

Also fix remaining format string warnings.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
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.
13  *
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.
18  *
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/>.
21  *
22  */
23
24 #include "DeviceStringParser.h"
25
26 #include <stdlib.h>
27 #include <errno.h>
28
29 #include <iostream>
30 #include <sstream>
31
32 #include "libieee1394/configrom.h"
33 #include "libieee1394/ieee1394service.h"
34
35 IMPL_DEBUG_MODULE( DeviceStringParser, DeviceStringParser, DEBUG_LEVEL_NORMAL );
36
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 )
45 {
46 }
47
48 DeviceStringParser::DeviceString::~DeviceString()
49 {
50 }
51
52 bool
53 DeviceStringParser::DeviceString::parse(std::string s)
54 {
55     m_String = s;
56     debugOutput(DEBUG_LEVEL_VERBOSE, "parse: %s\n", s.c_str());
57     std::string prefix = s.substr(0,3);
58    
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;
75             }
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;
87             }
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;
96             }
97         }
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;
108         }
109     } else {
110         m_Type = eInvalid;
111         debugOutput(DEBUG_LEVEL_VERBOSE, "invalid\n");
112         return false;
113     }
114     return true;
115 }
116
117 bool
118 DeviceStringParser::DeviceString::isValidString(std::string s)
119 {
120     std::string prefix = s.substr(0,3);
121     uint64_t tmp;
122     if(s.compare(0,3,"hw:")==0) {
123         std::string detail = s.substr(3);
124         std::string::size_type comma_pos = detail.find_first_of(",");
125         if(comma_pos == std::string::npos) {
126             std::string port = detail;
127             errno = 0;
128             tmp = strtol(port.c_str(), NULL, 0);
129             if(errno) {
130                 return false;
131             }
132         } else {
133             std::string port = detail.substr(0, comma_pos);
134             std::string node = detail.substr(comma_pos+1);
135             errno = 0;
136             tmp = strtol(port.c_str(), NULL, 0);
137             if(errno) {
138                 return false;
139             }
140             errno = 0;
141             tmp = strtol(node.c_str(), NULL, 0);
142             if(errno) {
143                 return false;
144             }
145         }
146     } else if (s.compare(0,5,"guid:")==0) {
147         std::string detail = s.substr(5);
148         errno = 0;
149         tmp = strtoll(detail.c_str(), NULL, 0);
150         if(errno) {
151             return false;
152         }
153     } else {
154         return false;
155     }
156     return true;
157 }
158
159 bool
160 DeviceStringParser::DeviceString::match(ConfigRom& configRom)
161 {
162     debugOutput(DEBUG_LEVEL_VERBOSE, "match %p (%s)\n", &configRom, configRom.getGuidString().c_str());
163     bool match;
164     switch(m_Type) {
165         case eBusNode:
166             if(m_port < 0) {
167                 debugWarning("Need at least a port spec\n");
168                 return false;
169             }
170             match = configRom.get1394Service().getPort() == m_port;
171             if(m_node >= 0) {
172                 match &= ((configRom.getNodeId() & 0x3F) == m_node);
173             }
174             if(match) {
175                 debugOutput(DEBUG_LEVEL_VERBOSE, "(eBusNode) device matches device string %s\n", m_String.c_str());
176             }
177             return match;
178         case eGUID:
179             //GUID should not be 0
180             match = m_guid && (m_guid == configRom.getGuid());
181             if(match) {
182                 debugOutput(DEBUG_LEVEL_VERBOSE, "(eGUID) device matches device string %s\n", m_String.c_str());
183             }
184             return match;
185         case eInvalid:
186         default:
187             debugError("invalid DeviceString type (%d)\n", m_Type);
188             return false;
189     }
190     return false;
191 }
192
193 bool
194 DeviceStringParser::DeviceString::operator==(const DeviceString& x)
195 {
196     bool retval;
197     switch(m_Type) {
198         case eBusNode:
199             retval = (m_port == x.m_port) && (m_node == x.m_node);
200             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "eBusNode %d,%d == %d,%d? %d\n",
201                         m_port, m_node, x.m_port, x.m_node, retval);
202             return retval;
203         case eGUID:
204             retval = m_guid && (m_guid == x.m_guid);
205             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "eGUID 0x%016"PRIX64" == 0x%016"PRIX64"? %d\n",
206                         m_guid, x.m_guid, retval);
207             return retval;
208         case eInvalid:
209             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "eInvalid \n");
210         default:
211             return false;
212     }
213 }
214
215 void
216 DeviceStringParser::DeviceString::show()
217 {
218     debugOutput(DEBUG_LEVEL_INFO, "string: %s\n", m_String.c_str());
219     switch(m_Type) {
220         case eBusNode:
221             debugOutput(DEBUG_LEVEL_INFO, "type: eBusNode\n");
222             debugOutput(DEBUG_LEVEL_INFO, " Port: %d, Node: %d\n",
223                         m_port, m_node);
224             break;
225         case eGUID:
226             debugOutput(DEBUG_LEVEL_INFO, "type: eGUID\n");
227             debugOutput(DEBUG_LEVEL_INFO, " GUID: %016"PRIX64"\n", m_guid);
228             break;
229         case eInvalid:
230         default:
231             debugOutput(DEBUG_LEVEL_INFO, "type: eInvalid\n");
232             break;
233     }
234 }
235
236 // ------------------------
237 DeviceStringParser::DeviceStringParser()
238 {}
239
240 DeviceStringParser::~DeviceStringParser()
241 {
242     while(m_DeviceStrings.size()) {
243         DeviceString *tmp = m_DeviceStrings.at(0);
244         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "removing device string: %p\n", tmp);
245         m_DeviceStrings.erase(m_DeviceStrings.begin());
246         delete tmp;
247     }
248 }
249
250 bool
251 DeviceStringParser::parseString(std::string s)
252 {
253     debugOutput(DEBUG_LEVEL_VERBOSE, "parse: %s\n", s.c_str());
254
255     std::string::size_type next_sep;
256     std::string tmp = s;
257     do {
258         debugOutput(DEBUG_LEVEL_VERBOSE, " left: %s\n", tmp.c_str());
259         next_sep = tmp.find_first_of(";");
260         std::string to_parse = tmp.substr(0, next_sep);
261         DeviceString *d = new DeviceString(*this);
262         if(d == NULL) {
263             debugError("failed to allocate memory for device string\n");
264             continue;
265         }
266         if(d->parse(to_parse)) {
267             addDeviceString(d);
268         } else {
269             debugWarning("Failed to parse device substring: \"%s\"\n",
270                          to_parse.c_str());
271             delete d;
272         }
273         tmp = tmp.substr(next_sep+1);
274     } while(tmp.size() && next_sep != std::string::npos);
275
276     pruneDuplicates();
277
278     return true;
279 }
280
281 bool
282 DeviceStringParser::isValidString(std::string s)
283 {
284     debugOutput(DEBUG_LEVEL_VERBOSE, "isvalid? %s\n", s.c_str());
285     return DeviceString::isValidString(s);
286 }
287
288 bool
289 DeviceStringParser::match(ConfigRom& c)
290 {
291     return matchPosition(c) != -1;
292 }
293
294 int
295 DeviceStringParser::matchPosition(ConfigRom& c)
296 {
297     int pos = 0;
298     for ( DeviceStringVectorIterator it = m_DeviceStrings.begin();
299       it != m_DeviceStrings.end();
300       ++it )
301     {
302         if((*it)->match(c)) {
303             return pos;
304         }
305         pos++;
306     }
307     return -1;
308 }
309
310 bool
311 DeviceStringParser::addDeviceString(DeviceString *o)
312 {
313     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "adding device string: %p\n", o);
314     if (hasDeviceString(o)){
315         return false;
316     }
317     m_DeviceStrings.push_back(o);
318     return true;
319 }
320
321 bool
322 DeviceStringParser::removeDeviceString(DeviceString *o)
323 {
324     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "removing device string: %p\n", o);
325     int i=findDeviceString(o);
326     if (i<0) {
327         debugOutput(DEBUG_LEVEL_VERBOSE, "not found\n");
328         return false;
329     } else {
330         DeviceString *tmp = m_DeviceStrings.at(i);
331         m_DeviceStrings.erase(m_DeviceStrings.begin()+i);
332         delete tmp;
333         return true;
334     }
335 }
336
337 bool
338 DeviceStringParser::hasDeviceString(DeviceString *o)
339 {
340     return (findDeviceString(o) >= 0);
341 }
342
343 int
344 DeviceStringParser::findDeviceString(DeviceString *o)
345 {
346     int i=0;
347     for ( DeviceStringVectorIterator it = m_DeviceStrings.begin();
348       it != m_DeviceStrings.end();
349       ++it )
350     {
351         if(*it == o) {
352             return i;
353         }
354         i++;
355     }
356     return -1;
357 }
358
359 void
360 DeviceStringParser::pruneDuplicates()
361 {
362     DeviceStringVector duplicates;
363     // find duplicates
364     for ( DeviceStringVectorIterator it = m_DeviceStrings.begin();
365       it != m_DeviceStrings.end();
366       ++it )
367     {
368         for ( DeviceStringVectorIterator it2 = it+1;
369           it2 != m_DeviceStrings.end();
370           ++it2 )
371         {
372
373             if(**it == **it2) {
374                 duplicates.push_back(*it2);
375             }
376         }
377     }
378
379     // remove duplicates
380     for ( DeviceStringVectorIterator it = duplicates.begin();
381       it != duplicates.end();
382       ++it )
383     {
384         removeDeviceString(*it);
385     }
386 }
387
388 void
389 DeviceStringParser::show()
390 {
391     debugOutput(DEBUG_LEVEL_INFO, "DeviceStringParser: %p\n", this);
392     for ( DeviceStringVectorIterator it = m_DeviceStrings.begin();
393       it != m_DeviceStrings.end();
394       ++it )
395     {
396         (*it)->show();
397     }
398 }
399
400 void
401 DeviceStringParser::setVerboseLevel(int i)
402 {
403     setDebugLevel(i);
404 }
Note: See TracBrowser for help on using the browser.