root/trunk/libfreebob/src/configrom.cpp

Revision 185, 9.4 kB (checked in by wagi, 16 years ago)

CVS-SVN migration developer public sync patch

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* configrom.cpp
2  * Copyright (C) 2005 by Daniel Wagner
3  *
4  * This file is part of FreeBob.
5  *
6  * FreeBob is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBob is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBob; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "configrom.h"
22 #include "libfreebobavc/ieee1394service.h"
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <iostream>
28
29 using namespace std;
30
31 IMPL_DEBUG_MODULE( ConfigRom, ConfigRom, DEBUG_LEVEL_NORMAL );
32
33 static int busRead( struct csr1212_csr* csr,
34                     u_int64_t addr,
35                     u_int16_t length,
36                     void* buffer,
37                     void* private_data );
38
39 static int getMaxRom( u_int32_t* bus_info_data,
40                       void* private_data );
41
42 static struct csr1212_bus_ops configrom_csr1212_ops = {
43     busRead,
44     0,
45     0,
46     getMaxRom
47 };
48
49 struct config_csr_info {
50     Ieee1394Service* service;
51     fb_nodeid_t      nodeId;
52 };
53
54 //-------------------------------------------------------------
55
56 ConfigRom::ConfigRom( Ieee1394Service* ieee1394service, fb_nodeid_t nodeId )
57     : m_1394Service( ieee1394service )
58     , m_nodeId( nodeId )
59     , m_avcDevice( false )
60     , m_guid( 0 )
61     , m_vendorName( "" )
62     , m_modelName( "" )
63     , m_vendorNameKv( 0 )
64     , m_modelNameKv( 0 )
65     , m_csr( 0 )
66 {
67 }
68
69 ConfigRom::~ConfigRom()
70 {
71 }
72
73 bool
74 ConfigRom::initialize()
75 {
76      struct config_csr_info csr_info;
77      csr_info.service = m_1394Service;
78      csr_info.nodeId = 0xffc0 | m_nodeId;
79
80      m_csr = csr1212_create_csr( &configrom_csr1212_ops,
81                                  5 * sizeof(fb_quadlet_t),   // XXX Why 5 ?!?
82                                  &csr_info );
83     if (!m_csr || csr1212_parse_csr( m_csr ) != CSR1212_SUCCESS) {
84         debugError( "Could not parse config rom" );
85         if (m_csr) {
86             csr1212_destroy_csr(m_csr);
87             m_csr = 0;
88         }
89         return false;
90     }
91
92     processRootDirectory(m_csr);
93
94     if ( m_vendorNameKv ) {
95         int len = ( m_vendorNameKv->value.leaf.len - 2) * sizeof( quadlet_t );
96         char* buf = new char[len+2];
97         memcpy( buf,
98                 ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_vendorNameKv ),
99                 len );
100
101         while ((buf + len - 1) == '\0') {
102             len--;
103         }
104         // \todo XXX seems a bit strage to do this but the nodemgr.c code does
105         // it. try to figure out why this is needed (or not)
106         buf[len++] = ' ';
107         buf[len] = '\0';
108
109
110         debugOutput( DEBUG_LEVEL_VERBOSE, "Vendor name: '%s'\n", buf );
111         m_vendorName = buf;
112         delete[] buf;
113     }
114     if ( m_modelNameKv ) {
115         int len = ( m_modelNameKv->value.leaf.len - 2) * sizeof( quadlet_t );
116         char* buf = new char[len+2];
117         memcpy( buf,
118                 ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_modelNameKv ),
119                 len );
120         while ((buf + len - 1) == '\0') {
121             len--;
122         }
123         // \todo XXX for edirol fa-66 it seems somehow broken. see above
124         // todo as well.
125         buf[len++] = ' ';
126         buf[len] = '\0';
127
128         debugOutput( DEBUG_LEVEL_VERBOSE, "Model name: '%s'\n", buf);
129         m_modelName = buf;
130         delete[] buf;
131     }
132
133     m_guid = ((u_int64_t)CSR1212_BE32_TO_CPU(m_csr->bus_info_data[3]) << 32)
134              | CSR1212_BE32_TO_CPU(m_csr->bus_info_data[4]);
135
136     if ( m_vendorNameKv ) {
137         csr1212_release_keyval( m_vendorNameKv );
138         m_vendorNameKv = 0;
139     }
140     if ( m_modelNameKv ) {
141         csr1212_release_keyval( m_modelNameKv );
142         m_modelNameKv = 0;
143     }
144     if ( m_csr ) {
145         csr1212_destroy_csr(m_csr);
146         m_csr = 0;
147     }
148     return true;
149 }
150
151 const bool
152 ConfigRom::isAvcDevice() const
153 {
154     return m_avcDevice;
155 }
156
157 // XXX This might work only for the M-Audio Audiophile
158 // but can easily extended.
159 #define VENDOR_ID_MAUDIO    0x00000d6c
160 #define MODEL_ID_MAUDIO_BOOTLOADER 0x00010060
161
162 const bool
163 ConfigRom::isBootloader() const
164 {
165     if ( ( m_vendorId == VENDOR_ID_MAUDIO )
166          && ( m_modelId == MODEL_ID_MAUDIO_BOOTLOADER ) )
167     {
168         return true;
169     }
170     return false;
171 }
172
173 static int
174 busRead( struct csr1212_csr* csr,
175          u_int64_t addr,
176          u_int16_t length,
177          void* buffer,
178          void* private_data )
179 {
180     struct config_csr_info* csr_info = (struct config_csr_info*) private_data;
181
182     if ( csr_info->service->read( csr_info->nodeId,
183                                   addr,
184                                   length,
185                                   ( quadlet_t* )buffer) )
186     {
187         cerr << "ConfigRom: Read failed" << endl;
188         return -1;
189     }
190
191     return 0;
192 }
193
194 static int
195 getMaxRom( u_int32_t* bus_info_data,
196            void* /*private_data*/)
197 {
198     return (CSR1212_BE32_TO_CPU( bus_info_data[2] ) >> 8) & 0x3;
199 }
200
201
202 void
203 ConfigRom::processUnitDirectory( struct csr1212_csr* csr,
204                                  struct csr1212_keyval* ud_kv,
205                                  unsigned int *id )
206 {
207     struct csr1212_dentry *dentry;
208     struct csr1212_keyval *kv;
209     unsigned int last_key_id = 0;
210     unsigned int specifier_id = 0;
211
212     debugOutput( DEBUG_LEVEL_VERBOSE, "process unit directory:\n" );
213     csr1212_for_each_dir_entry(csr, kv, ud_kv, dentry) {
214         switch (kv->key.id) {
215             case CSR1212_KV_ID_VENDOR:
216                 if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
217                     debugOutput( DEBUG_LEVEL_VERBOSE,
218                                  "\tvendor_id = 0x%08x\n",
219                                  kv->value.immediate);
220                     m_vendorId = kv->value.immediate;
221                 }
222                 break;
223
224             case CSR1212_KV_ID_MODEL:
225                 debugOutput( DEBUG_LEVEL_VERBOSE,
226                              "\tmodel_id = 0x%08x\n",
227                              kv->value.immediate);
228                 m_modelId = kv->value.immediate;
229                 break;
230
231             case CSR1212_KV_ID_SPECIFIER_ID:
232                 debugOutput( DEBUG_LEVEL_VERBOSE,
233                              "\tspecifier_id = 0x%08x\n",
234                              kv->value.immediate);
235                 specifier_id = kv->value.immediate;
236                 break;
237
238             case CSR1212_KV_ID_VERSION:
239                 debugOutput( DEBUG_LEVEL_VERBOSE,
240                              "\tversion = 0x%08x\n",
241                              kv->value.immediate);
242                 if ( specifier_id == 0x0000a02d ) // XXX
243                 {
244                     if ( kv->value.immediate == 0x10001 ) {
245                         m_avcDevice = true;
246                     }
247                 }
248                 break;
249
250             case CSR1212_KV_ID_DESCRIPTOR:
251                 if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
252                     CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
253                     CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
254                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
255                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
256                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0)
257                 {
258                     switch (last_key_id) {
259                         case CSR1212_KV_ID_VENDOR:
260                             csr1212_keep_keyval(kv);
261                             m_vendorNameKv = kv;
262                             break;
263
264                         case CSR1212_KV_ID_MODEL:
265                             m_modelNameKv = kv;
266                             csr1212_keep_keyval(kv);
267                             break;
268
269                     }
270                 } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */
271                 break;
272
273             case CSR1212_KV_ID_DEPENDENT_INFO:
274                 if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
275                     /* This should really be done in SBP2 as this is
276                      * doing SBP2 specific parsing. */
277                     processUnitDirectory(csr, kv, id);
278                 }
279
280                 break;
281
282             default:
283                 break;
284         }
285         last_key_id = kv->key.id;
286     }
287 }
288
289 void
290 ConfigRom::processRootDirectory(struct csr1212_csr* csr)
291 {
292     unsigned int ud_id = 0;
293     struct csr1212_dentry *dentry;
294     struct csr1212_keyval *kv;
295     unsigned int last_key_id = 0;
296
297     csr1212_for_each_dir_entry(csr, kv, csr->root_kv, dentry) {
298         switch (kv->key.id) {
299             case CSR1212_KV_ID_VENDOR:
300                 debugOutput( DEBUG_LEVEL_VERBOSE,
301                              "vendor id = 0x%08x\n", kv->value.immediate);
302                 break;
303
304             case CSR1212_KV_ID_NODE_CAPABILITIES:
305                 debugOutput( DEBUG_LEVEL_VERBOSE,
306                              "capabilities = 0x%08x\n", kv->value.immediate);
307                 break;
308
309             case CSR1212_KV_ID_UNIT:
310                 processUnitDirectory(csr, kv, &ud_id);
311                 break;
312
313             case CSR1212_KV_ID_DESCRIPTOR:
314                 if (last_key_id == CSR1212_KV_ID_VENDOR) {
315                     if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
316                         CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
317                         CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
318                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
319                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
320                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0)
321                     {
322                         m_vendorNameKv = kv;
323                         csr1212_keep_keyval(kv);
324                     }
325                 }
326                 break;
327         }
328         last_key_id = kv->key.id;
329     }
330
331 }
332
333 const fb_nodeid_t
334 ConfigRom::getNodeId() const
335 {
336     return m_nodeId;
337 }
338
339 const fb_octlet_t
340 ConfigRom::getGuid() const
341 {
342     return m_guid;
343 }
344
345 const std::string
346 ConfigRom::getModelName() const
347 {
348     return m_modelName;
349 }
350
351 const std::string
352 ConfigRom::getVendorName() const
353 {
354     return m_vendorName;
355 }
Note: See TracBrowser for help on using the browser.