17 #if defined (AJALinux) || defined (AJAMac)
18 #include <arpa/inet.h>
26 #define MAX_BITFILEHEADERSIZE 512
27 static const unsigned char gSignature[8]= {0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x99, 0x55, 0x66};
28 static const unsigned char gHead13[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01};
32 #define BUMPPOS(_inc_) pos += (_inc_); \
33 if (pos >= headerLength) \
35 oss << "Failed, offset " << DEC(pos) << " is past end, length=" << DEC(headerLength); \
39 #define CHKDIGIT(_s_,_pos_) if (_s_.at(_pos_) < '0' || _s_.at(_pos_) > '9') \
41 oss << "Expected digit at " << DEC(_pos_) << " in '" << _s_ << "'"; \
45 #define CHKCHAR(_c_,_s_,_pos_) if (_s_.at(_pos_) < (_c_)) \
47 oss << "Expected '" << (_c_) << "' at " << DEC(_pos_) << " in '" << _s_ << "'"; \
53 mDate = mTime = mPartName = mRawDesignName =
"";
54 mUserID = mDesignID = mDesignVersion = mBitfileID = mBitfileVersion = mProgSizeBytes = 0;
61 for (
size_t pos(0); pos < mRawDesignName.length(); pos++)
63 const char ch (mRawDesignName.at(pos));
64 if ((ch < 'A' || ch >
'Z') && (ch < 'a' || ch >
'z') && (ch < '0' || ch >
'9') && ch !=
'_')
73 mRawDesignName = inStr;
74 if (inStr.length() < 8)
75 {oss <<
"Raw design '" << inStr <<
"' < 8 chars";
return false;}
76 if (inStr.at(inStr.length()-1) == 0)
77 mRawDesignName.resize(inStr.length()-1);
79 ULWord userID (0xFFFFFFFF);
80 string lowerStr(mRawDesignName);
aja::lower(lowerStr);
84 if (it->find(
"userid=") == 0)
86 if (userIDSegment.empty())
89 {oss <<
"Raw design '" << mRawDesignName <<
"' has multiple 'UserID' params: '" << userIDSegment <<
"', '" << *it <<
"', ...";
return false;}
91 if (userIDSegment.empty())
97 if (halves.size() < 2)
98 {oss <<
"UserID '" << userIDSegment <<
"' has no '=' character";
return false;}
99 else if (halves.size() > 2)
100 {oss <<
"UserID '" << userIDSegment <<
"' has " <<
DEC(halves.size()) <<
" '=' chars";
return false;}
101 string userIDValue (halves.at(1));
102 if (userIDValue.length() < 3)
103 {oss <<
"UserID '" << userIDValue <<
"' length=" <<
DEC(userIDValue.length()) <<
" is too small";
return false;}
104 if (userIDValue.find(
"0x") == 0)
105 userIDValue = userIDValue.substr(2, userIDValue.length()-2);
106 for (
size_t ndx(0); ndx < userIDValue.length(); ndx++)
107 {
const char hexDigit(userIDValue.at(ndx));
108 if (hexDigit >=
'0' && hexDigit <=
'9')
110 if (hexDigit >=
'a' && hexDigit <=
'f')
112 oss <<
"Bad hex digit '" << hexDigit <<
"' (" <<
xHEX0N(
UWord(hexDigit),4) <<
") in UserID '" << userIDValue <<
"'";
118 mDesignID = GetDesignID(userID);
119 mDesignVersion = GetDesignVersion(userID);
120 mBitfileID = GetBitfileID(userID);
121 mBitfileVersion = GetBitfileVersion(userID);
127 if (inStr.length() != 10)
128 {oss <<
"10-byte date expected, instead got " <<
DEC(inStr.length()) <<
"-char '" << inStr <<
"'";
return false;}
145 if (inStr.length() != 8)
146 {oss <<
"8-byte time expected, instead got " <<
DEC(inStr.length()) <<
"-char '" << inStr <<
"'";
return false;}
162 {oss <<
"Non-zero program offset expected";
return false;}
163 mProgOffsetBytes = inValue;
170 {oss <<
"Non-zero program size expected";
return false;}
171 mProgSizeBytes = inValue;
178 uint32_t fieldLen (0);
184 const int headerLength(
int(inHdrBuffer.
GetByteCount()));
191 {oss <<
"Failed, byte mismatch in first 13 bytes";
break;}
196 testByte = inHdrBuffer.
I8(pos);
198 {oss <<
"Failed at byte offset " <<
DEC(pos) <<
", expected " <<
xHEX0N(
UWord(
'a'),2) <<
", instead got " <<
xHEX0N(
UWord(testByte),2);
break;}
202 {oss <<
"Failed fetching 2-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
206 if (inHdrBuffer.
Segment(portion,
ULWord(pos), fieldLen).IsNULL())
207 {oss <<
"Failed fetching " <<
DEC(fieldLen) <<
"-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
208 const string designBuffer (portion.
GetString());
209 if (!SetRawDesign(designBuffer, oss))
211 if (DesignName().empty())
212 {oss <<
"Bad design name in '" << designBuffer <<
"', offset=" <<
DEC(pos) <<
", headerLength=" <<
DEC(headerLength);
break;}
217 testByte = inHdrBuffer.
I8(pos);
219 {oss <<
"Failed at byte offset " <<
DEC(pos) <<
", expected " <<
xHEX0N(
UWord(
'b'),2) <<
", instead got " <<
xHEX0N(
UWord(testByte),2);
break;}
223 {oss <<
"Failed fetching 2-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
227 if (inHdrBuffer.
Segment(portion,
ULWord(pos), fieldLen).IsNULL())
228 {oss <<
"Failed fetching " <<
DEC(fieldLen) <<
"-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
234 testByte = inHdrBuffer.
I8(pos);
236 {oss <<
"Failed at byte offset " <<
DEC(pos) <<
", expected " <<
xHEX0N(
UWord(
'c'),2) <<
", instead got " <<
xHEX0N(
UWord(testByte),2);
break;}
240 {oss <<
"Failed fetching 2-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
244 if (inHdrBuffer.
Segment(portion,
ULWord(pos), fieldLen).IsNULL())
245 {oss <<
"Failed fetching " <<
DEC(fieldLen) <<
"-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
246 if (!SetDate(portion.
GetString(0, 10), oss))
break;
251 testByte = inHdrBuffer.
I8(pos);
253 {oss <<
"Failed at byte offset " <<
DEC(pos) <<
", expected " <<
xHEX0N(
UWord(
'd'),2) <<
", instead got " <<
xHEX0N(
UWord(testByte),2);
break;}
257 {oss <<
"Failed fetching 2-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
261 if (inHdrBuffer.
Segment(portion,
ULWord(pos), fieldLen).IsNULL())
262 {oss <<
"Failed fetching " <<
DEC(fieldLen) <<
"-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
263 if (!SetTime(portion.
GetString(0, 8), oss))
break;
268 testByte = inHdrBuffer.
I8(pos);
270 {oss <<
"Failed at byte offset " <<
DEC(pos) <<
", expected " <<
xHEX0N(
UWord(
'e'),2) <<
", instead got " <<
xHEX0N(
UWord(testByte),2);
break;}
274 {oss <<
"Failed fetching 4-byte segment starting at offset " <<
DEC(pos) <<
" from " <<
DEC(headerLength) <<
"-byte header";
break;}
278 if (!SetProgramOffsetBytes(
ULWord(pos), oss))
break;
281 bool bFound(
false);
int ndx(0);
282 while (!bFound && ndx < 1000 && pos < headerLength)
291 {oss <<
"Failed at byte offset " <<
DEC(pos) <<
", missing signature";
break;}
294 if (!oss.str().empty())
296 outMsgs << oss.str();
297 return oss.str().empty();
317 mHeaderBuffer.Deallocate();
318 mHeaderParser.Clear();
328 ::stat(inBitfileName.c_str(), &fsinfo);
329 mFileSize = size_t(fsinfo.st_size);
330 mFileStream.open (inBitfileName.c_str(), std::ios::binary | std::ios::in);
334 if (mFileStream.fail())
335 {oss <<
"Unable to open bitfile '" << inBitfileName <<
"'";
break;}
338 if (mFileStream.read(mHeaderBuffer, streamsize(mHeaderBuffer.GetByteCount())).fail())
339 {oss <<
"Read failure in bitfile '" << inBitfileName <<
"'";
break;}
340 mReady = mHeaderParser.ParseHeader(mHeaderBuffer, oss) && oss.str().empty();
343 SetLastError(oss.str());
351 if (!inStr.empty() && inAppend)
353 if (!mLastError.empty())
363 return ParseHeaderFromBuffer (
NTV2Buffer(inBitfileBuffer, inBufferSize));
371 mReady = mHeaderParser.ParseHeader(inBitfileBuffer, oss) && oss.str().empty();
372 SetLastError (oss.str());
379 if (!mHeaderParser.IsValid())
380 {SetLastError(
"No header info");
return 0;}
382 {SetLastError(
"File not open/ready");
return 0;}
384 size_t programStreamLength (mHeaderParser.ProgramSizeBytes());
385 const size_t programOffset (mHeaderParser.ProgramOffsetBytes());
392 oss <<
"Provided buffer size " <<
DEC(outBuffer.
GetByteCount()) <<
" < " <<
DEC(programStreamLength) <<
" prog bytes";
393 SetLastError(oss.str());
396 if (!outBuffer.
Allocate(programStreamLength))
397 { oss <<
"Buffer reallocation failed, requested size = " <<
DEC(programStreamLength) <<
" prog bytes";
398 SetLastError(oss.str());
402 if (!mFileStream.seekg (ios::off_type(programOffset), ios::beg))
403 {oss <<
"Seek failed to offset " <<
xHEX0N(programOffset,8) <<
DEC(programOffset); SetLastError(oss.str());
return 0;}
404 mFileStream.read(outBuffer, streamsize(programStreamLength));
405 if (mFileStream.eof())
407 oss <<
"Unexpected EOF reading prog " <<
xHEX0N(programStreamLength,8) <<
" (" <<
DEC(programStreamLength) <<
") bytes";
408 SetLastError(oss.str());
411 else if (mFileStream.bad())
413 oss <<
"I/O error reading prog " <<
xHEX0N(programStreamLength,8) <<
" (" <<
DEC(programStreamLength) <<
") bytes";
414 SetLastError(oss.str());
417 return programStreamLength;
423 const size_t fileStreamLength(GetFileStreamLength());
424 if (!fileStreamLength)
425 {SetLastError(
"fileStreamLength is zero");
return 0;}
427 {SetLastError(
"File not open/ready");
return 0;}
434 oss <<
"Provided buffer size " <<
DEC(outBuffer.
GetByteCount()) <<
" < " <<
DEC(fileStreamLength);
435 SetLastError(oss.str());
438 if (!outBuffer.
Allocate(fileStreamLength))
439 { oss <<
"Buffer reallocation failed, requested size = " <<
DEC(fileStreamLength) <<
" bytes";
440 SetLastError(oss.str());
445 if (!mFileStream.seekg (0, std::ios::beg))
446 {SetLastError(
"Seek failed to offset 0");
return 0;}
447 mFileStream.read(outBuffer, streamsize(fileStreamLength));
448 if (mFileStream.eof())
450 oss <<
"Unexpected EOF reading " <<
xHEX0N(fileStreamLength,8) <<
" (" <<
DEC(fileStreamLength) <<
") bytes";
451 SetLastError(oss.str());
454 else if (mFileStream.bad())
456 oss <<
"I/O error reading " <<
xHEX0N(fileStreamLength,8) <<
" (" <<
DEC(fileStreamLength) <<
") bytes";
457 SetLastError(oss.str());
460 return fileStreamLength;
546 if (IsPartial() || IsClear())
549 const string designName(mHeaderParser.DesignName());
550 if (designName == GetPrimaryHardwareDesignName(inDeviceID))
557 || designName ==
"corvid_446";
559 || designName ==
"K3G_quad_p2p";
561 || designName ==
"K3G_p2p";
570 || designName ==
"CORVID88"
571 || designName ==
"corvid88_top";
573 || designName ==
"ZARTAN";
581 || designName ==
"Corvid_HDMI_4Rx_Top";
610 || designName ==
"kona5"
611 || designName ==
"kona5_12g"
627 || designName == GetPrimaryHardwareDesignName (
DEVICE_ID_KONA5).append(
"_tprom")
650 || designName ==
"c44_12g";
671 static AJALock sDesignNameToIDMapLock;
673 if (sDesignNameToIDMap.empty())
718 if (iter->second == deviceID)
719 return iter->first.first;
728 if (iter->second == deviceID)
729 return iter->first.second;
734 static void Init (
void)
782 if (mHeaderParser.UserID() && (mHeaderParser.UserID() != 0xffffffff))
805 static AJALock gDesignNameDeviceIDsLock;
807 string inName(inDesignName);
815 string designName(GetPrimaryHardwareDesignName(devID));
816 if (designName.empty())