root/trunk/libffado/src/bebob/bebob_dl_bcd.cpp

Revision 2802, 9.5 kB (checked in by jwoithe, 3 years ago)

Cosmetic: "Firewire" becomes "FireWire?".

Officially both the "F" and "W" were capitalised in the FireWire? name, so
reflect this throughout FFADO's source tree. This mostly affects comments.

This patch originated from pander on the ffado-devel mailing list. To
maintain consistency, the committed version has been expanded to include
files not originally included in the original patch.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
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 "bebob_dl_bcd.h"
25
26 #include <cstdio>
27
28 namespace BeBoB {
29     enum {
30         BCDMagic = 0x446f4362,
31     };
32
33     // XXX not very nice tool box function?
34     std::string makeString( fb_octlet_t v )
35     {
36         std::string s;
37
38         for ( unsigned int i=0; i<sizeof( v ); ++i ) {
39             s += reinterpret_cast<char*> ( &v )[i];
40         }
41
42         return s;
43     }
44
45     std::string makeDate( fb_octlet_t v )
46     {
47         std::string s;
48         char* vc = reinterpret_cast<char*> ( &v );
49
50         s += vc[6];
51         s += vc[7];
52         s += '.';
53         s += vc[4];
54         s += vc[5];
55         s += '.';
56         s += vc[0];
57         s += vc[1];
58         s += vc[2];
59         s += vc[3];
60
61         return s;
62     }
63
64     std::string makeTime( fb_octlet_t v )
65     {
66         std::string s;
67         char* vc = reinterpret_cast<char*>( &v );
68
69         s += vc[0];
70         s += vc[1];
71         s += ':';
72         s += vc[2];
73         s += vc[3];
74         s += ':';
75         s += vc[4];
76         s += vc[5];
77         s += vc[6];
78         s += vc[7];
79
80         return s;
81     }
82
83     enum {
84         BCDFileVersionOffset = 0x28,
85
86         V0HeaderCRCOffset    = 0x2c,
87         V0HeaderSize         = 0x60,
88
89         V1HeaderCRC0ffset    = 0x2c,
90         V1HeaderSize         = 0x70,
91     };
92
93     IMPL_DEBUG_MODULE( BCD, BCD, DEBUG_LEVEL_NORMAL );
94 };
95
96 BeBoB::BCD::BCD( std::string filename )
97     : m_file( 0 )
98     , m_filename( filename )
99     , m_bcd_version( -1 )
100     , m_softwareDate( 0 )
101     , m_softwareTime( 0 )
102     , m_softwareId( 0 )
103     , m_softwareVersion( 0 )
104     , m_hardwareId( 0 )
105     , m_vendorOUI( 0 )
106     , m_imageBaseAddress( 0 )
107     , m_imageLength( 0 )
108     , m_imageOffset( 0 )
109     , m_imageCRC( 0 )
110     , m_cneLength( 0 )
111     , m_cneOffset( 0 )
112     , m_cneCRC( 0 )
113 {
114     initCRC32Table();
115 }
116
117 BeBoB::BCD::~BCD()
118 {
119     if ( m_file ) {
120         fclose( m_file );
121     }
122 }
123
124 bool
125 BeBoB::BCD::parse()
126 {
127     using namespace std;
128
129     m_file = fopen( m_filename.c_str(), "r" );
130     if ( !m_file ) {
131         debugError( "parse: Could not open file '%s'\n",
132                     m_filename.c_str() );
133         return false;
134     }
135
136     fb_quadlet_t identifier;
137     size_t bytes_read = fread( &identifier, 1, sizeof( identifier ), m_file );
138     if ( bytes_read  != sizeof( identifier ) ) {
139         debugError( "parse: 4 bytes read failed at position 0\n" );
140         return false;
141     }
142
143     if ( identifier != BCDMagic ) {
144         debugError( "parse: File has not BCD header magic, 0x%08x expected, "
145                     "0x%08x found\n", BCDMagic, identifier );
146         return false;
147     }
148
149     if ( fseek( m_file, BCDFileVersionOffset, SEEK_SET ) == -1 ) {
150         debugError( "parse: fseek failed\n" );
151         return false;
152     }
153
154     bytes_read = fread( &m_bcd_version, 1, sizeof( fb_quadlet_t ), m_file );
155     if ( bytes_read != sizeof( fb_quadlet_t ) ) {
156         debugError( "parse: %zd bytes read at position %d failed\n",
157                     sizeof( fb_quadlet_t ),
158                     BCDFileVersionOffset );
159         return false;
160     }
161
162     unsigned int headerSize = 0;
163     unsigned int crcOffset = 0;
164     switch( m_bcd_version ) {
165     case 0:
166         headerSize = V0HeaderSize;
167         crcOffset = V0HeaderCRCOffset;
168         break;
169     case 1:
170         headerSize = V1HeaderSize;
171         crcOffset = V1HeaderCRC0ffset;
172         break;
173     default:
174         debugError( "parse: Unknown BCD file version %d found\n",
175                     m_bcd_version );
176         return false;
177     }
178
179     if ( !checkHeaderCRC( crcOffset, headerSize ) ) {
180         debugError( "parse: Header CRC check failed\n" );
181         return false;
182     }
183
184     if ( !readHeaderInfo() ) {
185         debugError( "parse: Could not read all header info\n" );
186         return false;
187     }
188
189     return true;
190 }
191
192 bool
193 BeBoB::BCD::readHeaderInfo()
194 {
195     if ( !read( 0x08, &m_softwareDate ) ) {
196         return false;
197     }
198     if ( !read( 0x10, &m_softwareTime ) ) {
199         return false;
200     }
201     if ( !read( 0x18, &m_softwareId ) ) {
202         return false;
203     }
204     if ( !read( 0x1c, &m_softwareVersion ) ) {
205         return false;
206     }
207     if ( !read( 0x20, &m_hardwareId ) ) {
208         return false;
209     }
210     if ( !read( 0x24, &m_vendorOUI ) ) {
211         return false;
212     }
213     if ( !read( 0x30, &m_imageOffset ) ) {
214         return false;
215     }
216     if ( !read( 0x34, &m_imageBaseAddress ) ) {
217         return false;
218     }
219     if ( !read( 0x38, &m_imageLength ) ) {
220         return false;
221     }
222     if ( !read( 0x3c, &m_imageCRC ) ) {
223         return false;
224     }
225     if ( !read( 0x50, &m_cneOffset ) ) {
226         return false;
227     }
228     if ( !read( 0x58, &m_cneLength ) ) {
229         return false;
230     }
231     if ( !read( 0x5c, &m_cneCRC ) ) {
232         return false;
233     }
234     return true;
235 }
236
237 bool
238 BeBoB::BCD::read( int addr, fb_quadlet_t* q )
239 {
240     if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
241         debugError( "read: seek to position 0x%08x failed\n", addr );
242         return false;
243     }
244
245     size_t bytes_read = std::fread( q, 1, sizeof( *q ), m_file );
246     if ( bytes_read  != sizeof( *q ) ) {
247         debugError( "read: %zd byte read failed at position 0x%08x\n",
248                     sizeof( *q ),  addr );
249         return false;
250     }
251
252     return true;
253 }
254
255 bool
256 BeBoB::BCD::read( int addr, fb_octlet_t* o )
257 {
258     if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
259         debugError( "read: seek to position 0x%08x failed\n", addr );
260         return false;
261     }
262
263     size_t bytes_read = std::fread( o, 1, sizeof( *o ), m_file );
264     if ( bytes_read  != sizeof( *o ) ) {
265         debugError( "read: %zd byte read failed at position 0x%08x\n",
266                     sizeof( *o ), addr );
267         return false;
268     }
269
270     return true;
271 }
272
273 bool
274 BeBoB::BCD::read( int addr, unsigned char* b, size_t len )
275 {
276     if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
277         debugError( "read: seek to position 0x%08x failed\n", addr );
278         return false;
279     }
280
281     size_t bytes_read = std::fread( b, 1, len, m_file );
282     if ( bytes_read  != len ) {
283         debugError( "read: %zd byte read failed at position 0x%08x\n",
284                     len, addr );
285         return false;
286     }
287
288     return true;
289 }
290
291 void
292 BeBoB::BCD::initCRC32Table()
293 {
294     unsigned long polynomial = 0x04c11db7;
295
296     for ( int i = 0; i <= 0xff; ++i ) {
297         crc32_table[i] = reflect( i, 8 ) << 24;
298         for ( int j = 0; j < 8; ++j ) {
299             crc32_table[i] =
300                 (crc32_table[i] << 1)
301                 ^ (crc32_table[i] & (1 << 31) ? polynomial : 0);
302         }
303         crc32_table[i] = reflect( crc32_table[i], 32 );
304     }
305 }
306
307 unsigned long
308 BeBoB::BCD::reflect( unsigned long ref, char ch )
309 {
310     unsigned long value = 0;
311
312     for ( int i = 1; i < (ch + 1); ++i ) {
313         if(ref & 1) {
314             value |= 1 << (ch - i);
315         }
316         ref >>= 1;
317     }
318     return value;
319 }
320
321 unsigned int
322 BeBoB::BCD::getCRC( unsigned char* text, size_t len )
323 {
324     unsigned long crc = 0xffffffff;
325     unsigned char* buffer;
326
327     buffer = text;
328     while ( len-- ) {
329         crc = (crc >> 8) ^ crc32_table[(crc & 0xff) ^ *buffer++];
330     }
331
332     return crc ^ 0xffffffff;
333 }
334
335 bool
336 BeBoB::BCD::checkHeaderCRC( unsigned int crcOffset, unsigned int headerSize )
337 {
338     fb_quadlet_t headerCRC;
339     if ( !read( crcOffset, &headerCRC ) ) {
340         debugError( "checkHeaderCRC: Could not read header CRC\n" );
341         return false;
342     }
343
344     const int headerLength = headerSize;
345     unsigned char buf[headerLength];
346     if ( !read( 0x00, buf, headerLength ) ) {
347         debugError( "checkHeaderCRC: Could not read complete header from file\n" );
348         return false;
349     }
350     buf[crcOffset+0] = 0x00;
351     buf[crcOffset+1] = 0x00;
352     buf[crcOffset+2] = 0x00;
353     buf[crcOffset+3] = 0x00;
354
355     fb_quadlet_t calcCRC = getCRC( buf, headerLength );
356     if ( headerCRC != calcCRC ) {
357         debugError( "checkHeaderCRC: CRC check failed, 0x%08x expected, "
358                     "0x%08x calculated\n", headerCRC, calcCRC );
359         return false;
360     }
361
362     return true;
363 }
364
365 void
366 BeBoB::BCD::displayInfo()
367 {
368     using namespace std;
369
370     printf( "BCD Info\n" );
371     printf( "\tBCD File Version\t%d\n", m_bcd_version );
372     printf( "\tSoftware Date:\t\t%s, %s\n",
373             makeDate( m_softwareDate ).c_str(),
374             makeTime( m_softwareTime ).c_str() );
375     printf( "\tSoftware Version:\t0x%08x\n", m_softwareVersion );
376     printf( "\tSoftware Id:\t\t0x%08x\n", m_softwareId );
377     printf( "\tHardware ID:\t\t0x%08x\n", m_hardwareId );
378     printf( "\tVendor OUI:\t\t0x%08x\n", m_vendorOUI );
379     printf( "\tImage Offset:\t\t0x%08x\n", m_imageOffset );
380     printf( "\tImage Base Address:\t0x%08x\n", m_imageBaseAddress );
381     printf( "\tImage Length:\t\t0x%08x\n", m_imageLength );
382     printf( "\tImage CRC:\t\t0x%08x\n", m_imageCRC );
383     printf( "\tCNE Length:\t\t0x%08x\n", m_cneLength );
384     printf( "\tCNE Offset:\t\t0x%08x\n", m_cneOffset );
385     printf( "\tCNE CRC:\t\t0x%08x\n", m_cneCRC );
386 }
Note: See TracBrowser for help on using the browser.