root/branches/libfreebob-2.0/src/configrom.cpp

Revision 262, 9.8 kB (checked in by jwoithe, 16 years ago)

Make skeleton MOTU device discovery work. Proof-of-concept MOTU sample rate
control in place.

  • 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_unit_specifier_id( 0 )
64     , m_unit_version( 0 )
65     , m_vendorNameKv( 0 )
66     , m_modelNameKv( 0 )
67     , m_csr( 0 )
68 {
69 }
70
71 ConfigRom::~ConfigRom()
72 {
73 }
74
75 bool
76 ConfigRom::initialize()
77 {
78      struct config_csr_info csr_info;
79      csr_info.service = m_1394Service;
80      csr_info.nodeId = 0xffc0 | m_nodeId;
81
82      m_csr = csr1212_create_csr( &configrom_csr1212_ops,
83                                  5 * sizeof(fb_quadlet_t),   // XXX Why 5 ?!?
84                                  &csr_info );
85     if (!m_csr || csr1212_parse_csr( m_csr ) != CSR1212_SUCCESS) {
86         debugError( "Could not parse config rom" );
87         if (m_csr) {
88             csr1212_destroy_csr(m_csr);
89             m_csr = 0;
90         }
91         return false;
92     }
93
94     processRootDirectory(m_csr);
95
96     if ( m_vendorNameKv ) {
97         int len = ( m_vendorNameKv->value.leaf.len - 2) * sizeof( quadlet_t );
98         char* buf = new char[len+2];
99         memcpy( buf,
100                 ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_vendorNameKv ),
101                 len );
102
103         while ((buf + len - 1) == '\0') {
104             len--;
105         }
106         // \todo XXX seems a bit strage to do this but the nodemgr.c code does
107         // it. try to figure out why this is needed (or not)
108         buf[len++] = ' ';
109         buf[len] = '\0';
110
111
112         debugOutput( DEBUG_LEVEL_VERBOSE, "Vendor name: '%s'\n", buf );
113         m_vendorName = buf;
114         delete[] buf;
115     }
116     if ( m_modelNameKv ) {
117         int len = ( m_modelNameKv->value.leaf.len - 2) * sizeof( quadlet_t );
118         char* buf = new char[len+2];
119         memcpy( buf,
120                 ( void* )CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA( m_modelNameKv ),
121                 len );
122         while ((buf + len - 1) == '\0') {
123             len--;
124         }
125         // \todo XXX for edirol fa-66 it seems somehow broken. see above
126         // todo as well.
127         buf[len++] = ' ';
128         buf[len] = '\0';
129
130         debugOutput( DEBUG_LEVEL_VERBOSE, "Model name: '%s'\n", buf);
131         m_modelName = buf;
132         delete[] buf;
133     }
134
135     m_guid = ((u_int64_t)CSR1212_BE32_TO_CPU(m_csr->bus_info_data[3]) << 32)
136              | CSR1212_BE32_TO_CPU(m_csr->bus_info_data[4]);
137
138     if ( m_vendorNameKv ) {
139         csr1212_release_keyval( m_vendorNameKv );
140         m_vendorNameKv = 0;
141     }
142     if ( m_modelNameKv ) {
143         csr1212_release_keyval( m_modelNameKv );
144         m_modelNameKv = 0;
145     }
146     if ( m_csr ) {
147         csr1212_destroy_csr(m_csr);
148         m_csr = 0;
149     }
150     return true;
151 }
152
153 const bool
154 ConfigRom::isAvcDevice() const
155 {
156     return m_avcDevice;
157 }
158
159 // XXX This might work only for the M-Audio Audiophile
160 // but can easily extended.
161 #define VENDOR_ID_MAUDIO    0x00000d6c
162 #define MODEL_ID_MAUDIO_BOOTLOADER 0x00010060
163
164 const bool
165 ConfigRom::isBootloader() const
166 {
167     if ( ( m_vendorId == VENDOR_ID_MAUDIO )
168          && ( m_modelId == MODEL_ID_MAUDIO_BOOTLOADER ) )
169     {
170         return true;
171     }
172     return false;
173 }
174
175 static int
176 busRead( struct csr1212_csr* csr,
177          u_int64_t addr,
178          u_int16_t length,
179          void* buffer,
180          void* private_data )
181 {
182     struct config_csr_info* csr_info = (struct config_csr_info*) private_data;
183
184     if ( csr_info->service->read( csr_info->nodeId,
185                                   addr,
186                                   length,
187                                   ( quadlet_t* )buffer) )
188     {
189 //         debugOutput( DEBUG_LEVEL_VERBOSE, "ConfigRom: Read failed\n");
190         return -1;
191     }
192
193     return 0;
194 }
195
196 static int
197 getMaxRom( u_int32_t* bus_info_data,
198            void* /*private_data*/)
199 {
200     return (CSR1212_BE32_TO_CPU( bus_info_data[2] ) >> 8) & 0x3;
201 }
202
203
204 void
205 ConfigRom::processUnitDirectory( struct csr1212_csr* csr,
206                                  struct csr1212_keyval* ud_kv,
207                                  unsigned int *id )
208 {
209     struct csr1212_dentry *dentry;
210     struct csr1212_keyval *kv;
211     unsigned int last_key_id = 0;
212
213     debugOutput( DEBUG_LEVEL_VERBOSE, "process unit directory:\n" );
214     csr1212_for_each_dir_entry(csr, kv, ud_kv, dentry) {
215         switch (kv->key.id) {
216             case CSR1212_KV_ID_VENDOR:
217                 if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
218                     debugOutput( DEBUG_LEVEL_VERBOSE,
219                                  "\tvendor_id = 0x%08x\n",
220                                  kv->value.immediate);
221                     m_vendorId = kv->value.immediate;
222                 }
223                 break;
224
225             case CSR1212_KV_ID_MODEL:
226                 debugOutput( DEBUG_LEVEL_VERBOSE,
227                              "\tmodel_id = 0x%08x\n",
228                              kv->value.immediate);
229                 m_modelId = kv->value.immediate;
230                 break;
231
232             case CSR1212_KV_ID_SPECIFIER_ID:
233                 debugOutput( DEBUG_LEVEL_VERBOSE,
234                              "\tspecifier_id = 0x%08x\n",
235                              kv->value.immediate);
236                 m_unit_specifier_id = kv->value.immediate;
237                 break;
238
239             case CSR1212_KV_ID_VERSION:
240                 debugOutput( DEBUG_LEVEL_VERBOSE,
241                              "\tversion = 0x%08x\n",
242                              kv->value.immediate);
243                 m_unit_version = kv->value.immediate;
244                 if ( m_unit_specifier_id == 0x0000a02d ) // XXX
245                 {
246                     if ( kv->value.immediate == 0x10001 ) {
247                         m_avcDevice = true;
248                     }
249                 }
250                 break;
251
252             case CSR1212_KV_ID_DESCRIPTOR:
253                 if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
254                     CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
255                     CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
256                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
257                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
258                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0)
259                 {
260                     switch (last_key_id) {
261                         case CSR1212_KV_ID_VENDOR:
262                             csr1212_keep_keyval(kv);
263                             m_vendorNameKv = kv;
264                             break;
265
266                         case CSR1212_KV_ID_MODEL:
267                             m_modelNameKv = kv;
268                             csr1212_keep_keyval(kv);
269                             break;
270
271                     }
272                 } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */
273                 break;
274
275             case CSR1212_KV_ID_DEPENDENT_INFO:
276                 if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
277                     /* This should really be done in SBP2 as this is
278                      * doing SBP2 specific parsing. */
279                     processUnitDirectory(csr, kv, id);
280                 }
281
282                 break;
283
284             default:
285                 break;
286         }
287         last_key_id = kv->key.id;
288     }
289 }
290
291 void
292 ConfigRom::processRootDirectory(struct csr1212_csr* csr)
293 {
294     unsigned int ud_id = 0;
295     struct csr1212_dentry *dentry;
296     struct csr1212_keyval *kv;
297     unsigned int last_key_id = 0;
298
299     csr1212_for_each_dir_entry(csr, kv, csr->root_kv, dentry) {
300         switch (kv->key.id) {
301             case CSR1212_KV_ID_VENDOR:
302                 debugOutput( DEBUG_LEVEL_VERBOSE,
303                              "vendor id = 0x%08x\n", kv->value.immediate);
304                 break;
305
306             case CSR1212_KV_ID_NODE_CAPABILITIES:
307                 debugOutput( DEBUG_LEVEL_VERBOSE,
308                              "capabilities = 0x%08x\n", kv->value.immediate);
309                 break;
310
311             case CSR1212_KV_ID_UNIT:
312                 processUnitDirectory(csr, kv, &ud_id);
313                 break;
314
315             case CSR1212_KV_ID_DESCRIPTOR:
316                 if (last_key_id == CSR1212_KV_ID_VENDOR) {
317                     if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
318                         CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
319                         CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
320                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
321                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
322                         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0)
323                     {
324                         m_vendorNameKv = kv;
325                         csr1212_keep_keyval(kv);
326                     }
327                 }
328                 break;
329         }
330         last_key_id = kv->key.id;
331     }
332
333 }
334
335 const fb_nodeid_t
336 ConfigRom::getNodeId() const
337 {
338     return m_nodeId;
339 }
340
341 const fb_octlet_t
342 ConfigRom::getGuid() const
343 {
344     return m_guid;
345 }
346
347 const std::string
348 ConfigRom::getModelName() const
349 {
350     return m_modelName;
351 }
352
353 const std::string
354 ConfigRom::getVendorName() const
355 {
356     return m_vendorName;
357 }
358
359 const unsigned int
360 ConfigRom::getModelId() const
361 {
362     return m_modelId;
363 }
364
365 const unsigned int
366 ConfigRom::getVendorId() const
367 {
368     return m_vendorId;
369 }
370
371 const unsigned int
372 ConfigRom::getUnitSpecifierId() const
373 {
374     return m_unit_specifier_id;
375 }
376
377 const unsigned int
378 ConfigRom::getUnitVersion() const
379 {
380     return m_unit_version;
381 }
Note: See TracBrowser for help on using the browser.