[BeBoB/MAudio] Add PreSonus::FireboxDevice class to support functionality to switch...
[ffado.git] / libffado / src / bebob / bebob_dl_bcd.cpp
blob9a48e16462607927d34e22a77d7ee5836de874a9
1 /*
2 * Copyright (C) 2005-2008 by Daniel Wagner
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 "bebob_dl_bcd.h"
26 #include <cstdio>
28 namespace BeBoB {
29 enum {
30 BCDMagic = 0x446f4362,
33 // XXX not very nice tool box function?
34 std::string makeString( fb_octlet_t v )
36 std::string s;
38 for ( unsigned int i=0; i<sizeof( v ); ++i ) {
39 s += reinterpret_cast<char*> ( &v )[i];
42 return s;
45 std::string makeDate( fb_octlet_t v )
47 std::string s;
48 char* vc = reinterpret_cast<char*> ( &v );
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];
61 return s;
64 std::string makeTime( fb_octlet_t v )
66 std::string s;
67 char* vc = reinterpret_cast<char*>( &v );
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];
80 return s;
83 enum {
84 BCDFileVersionOffset = 0x28,
86 V0HeaderCRCOffset = 0x2c,
87 V0HeaderSize = 0x60,
89 V1HeaderCRC0ffset = 0x2c,
90 V1HeaderSize = 0x70,
93 IMPL_DEBUG_MODULE( BCD, BCD, DEBUG_LEVEL_NORMAL );
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 )
114 initCRC32Table();
117 BeBoB::BCD::~BCD()
119 if ( m_file ) {
120 fclose( m_file );
124 bool
125 BeBoB::BCD::parse()
127 using namespace std;
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;
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;
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;
149 if ( fseek( m_file, BCDFileVersionOffset, SEEK_SET ) == -1 ) {
150 debugError( "parse: fseek failed\n" );
151 return false;
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;
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;
179 if ( !checkHeaderCRC( crcOffset, headerSize ) ) {
180 debugError( "parse: Header CRC check failed\n" );
181 return false;
184 if ( !readHeaderInfo() ) {
185 debugError( "parse: Could not read all header info\n" );
186 return false;
189 return true;
192 bool
193 BeBoB::BCD::readHeaderInfo()
195 if ( !read( 0x08, &m_softwareDate ) ) {
196 return false;
198 if ( !read( 0x10, &m_softwareTime ) ) {
199 return false;
201 if ( !read( 0x18, &m_softwareId ) ) {
202 return false;
204 if ( !read( 0x1c, &m_softwareVersion ) ) {
205 return false;
207 if ( !read( 0x20, &m_hardwareId ) ) {
208 return false;
210 if ( !read( 0x24, &m_vendorOUI ) ) {
211 return false;
213 if ( !read( 0x30, &m_imageOffset ) ) {
214 return false;
216 if ( !read( 0x34, &m_imageBaseAddress ) ) {
217 return false;
219 if ( !read( 0x38, &m_imageLength ) ) {
220 return false;
222 if ( !read( 0x3c, &m_imageCRC ) ) {
223 return false;
225 if ( !read( 0x50, &m_cneOffset ) ) {
226 return false;
228 if ( !read( 0x58, &m_cneLength ) ) {
229 return false;
231 if ( !read( 0x5c, &m_cneCRC ) ) {
232 return false;
234 return true;
237 bool
238 BeBoB::BCD::read( int addr, fb_quadlet_t* q )
240 if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
241 debugError( "read: seek to position 0x%08x failed\n", addr );
242 return false;
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;
252 return true;
255 bool
256 BeBoB::BCD::read( int addr, fb_octlet_t* o )
258 if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
259 debugError( "read: seek to position 0x%08x failed\n", addr );
260 return false;
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;
270 return true;
273 bool
274 BeBoB::BCD::read( int addr, unsigned char* b, size_t len )
276 if ( std::fseek( m_file, addr, SEEK_SET ) == -1 ) {
277 debugError( "read: seek to position 0x%08x failed\n", addr );
278 return false;
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;
288 return true;
291 void
292 BeBoB::BCD::initCRC32Table()
294 unsigned long polynomial = 0x04c11db7;
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);
303 crc32_table[i] = reflect( crc32_table[i], 32 );
307 unsigned long
308 BeBoB::BCD::reflect( unsigned long ref, char ch )
310 unsigned long value = 0;
312 for ( int i = 1; i < (ch + 1); ++i ) {
313 if(ref & 1) {
314 value |= 1 << (ch - i);
316 ref >>= 1;
318 return value;
321 unsigned int
322 BeBoB::BCD::getCRC( unsigned char* text, size_t len )
324 unsigned long crc = 0xffffffff;
325 unsigned char* buffer;
327 buffer = text;
328 while ( len-- ) {
329 crc = (crc >> 8) ^ crc32_table[(crc & 0xff) ^ *buffer++];
332 return crc ^ 0xffffffff;
335 bool
336 BeBoB::BCD::checkHeaderCRC( unsigned int crcOffset, unsigned int headerSize )
338 fb_quadlet_t headerCRC;
339 if ( !read( crcOffset, &headerCRC ) ) {
340 debugError( "checkHeaderCRC: Could not read header CRC\n" );
341 return false;
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;
350 buf[crcOffset+0] = 0x00;
351 buf[crcOffset+1] = 0x00;
352 buf[crcOffset+2] = 0x00;
353 buf[crcOffset+3] = 0x00;
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;
362 return true;
365 void
366 BeBoB::BCD::displayInfo()
368 using namespace std;
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 );