diff options
author | RALOVICH, Kristof <tade60@freemail.hu> | 2013-12-15 01:59:47 +0100 |
---|---|---|
committer | RALOVICH, Kristof <tade60@freemail.hu> | 2013-12-15 01:59:47 +0100 |
commit | 0aba7d387334f6bce58e476fc5d7c5039fa743bb (patch) | |
tree | fd62f5e14bb4721bbdafb14a30837b50c0379bce /src | |
parent | 86fa7227befe3a3e8ba076924e5910c6a0772227 (diff) |
Blind implementation of messages seen in 405 traces.
Testing done with command "$ ANTPM_405=1 ./antpm-downloader --v 6"
Diffstat (limited to 'src')
-rw-r--r-- | src/AntFr405.cpp | 42 | ||||
-rw-r--r-- | src/AntMessage.cpp | 7 | ||||
-rw-r--r-- | src/AntMessage.hpp | 36 | ||||
-rw-r--r-- | src/AntMessenger.cpp | 204 | ||||
-rw-r--r-- | src/AntMessenger.hpp | 4 | ||||
-rw-r--r-- | src/antdefs.hpp | 2 | ||||
-rw-r--r-- | src/antpm-downloader.cpp | 1 | ||||
-rw-r--r-- | src/common.cpp | 22 | ||||
-rw-r--r-- | src/common.hpp | 3 |
9 files changed, 291 insertions, 30 deletions
diff --git a/src/AntFr405.cpp b/src/AntFr405.cpp index 535551a..437dde3 100644 --- a/src/AntFr405.cpp +++ b/src/AntFr405.cpp @@ -155,6 +155,7 @@ AntFr405::onAntReceived(const AntMessage m) void AntFr405::onAntSent(const AntMessage m) { + LOG(antpm::LOG_DBG) << m.strDt(0.0) << "\n"; } @@ -441,37 +442,24 @@ AntFr405::handleEvents() } else if(state == ST_ANTFS_DL_DIRECTORY) { - CHECK_RETURN_FALSE(createDownloadFolder()); + // when authentication succeeds, State=Transport beacon arrives + //R 96.026 MESG_BROADCAST_DATA_ID chan=0x00 ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Transport, Auth=PasskeyAndPairingOnly + //R 124.999 MESG_BROADCAST_DATA_ID chan=0x00 ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Transport, Auth=PasskeyAndPairingOnly + //S 114.743 MESG_REQUEST_ID chan=0x00 reqMsgId=MESG_CHANNEL_STATUS_ID + //R 3.247 MESG_CHANNEL_STATUS_ID chan=00 chanSt=Tracking + //S 12.451 MESG_BURST_DATA_ID chan=0x00, seq=0, last=no ANTFS_CMD(0x44) ANTFS_CmdDirect fd=0xffff, offset=0x0000, data=0x0000 + //R 1.546 MESG_BROADCAST_DATA_ID chan=0x00 ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Transport, Auth=PasskeyAndPairingOnly + //S 2.477 MESG_BURST_DATA_ID chan=0x00, seq=1, last=yes fe00000000000000 ........ - //ANTFS_Upload(); //command pipe - //ANTFS_UploadData(); + CHECK_RETURN_FALSE_LOG_OK(m_antMessenger->ANTFS_Direct(chan, SwapDWord(0xfe00000000000000))); - std::vector<uchar> dir; - if(!m_antMessenger->ANTFS_Download(chan, 0x0000, dir)) - { - changeStateSafe(ST_ANTFS_RESTART); - return true; - } - LOG(LOG_RAW) << "\n\nDownloaded directory file idx=0x0000\n\n\n"; - - AntFsFile file0; - file0.bytes=dir; - LOG_VAR(file0.checkCrc()); - file0.saveToFile((folder+"0000.fit").c_str()); + CHECK_RETURN_FALSE_LOG_OK(m_antMessenger->ANTFS_Direct(chan, SwapDWord(0x06000200ff000000))); - CHECK_RETURN_FALSE(fit.parseZeroFile(dir, zfc)); - LOG_VAR(zfc.activityFiles.size()); - LOG_VAR(zfc.courseFiles.size()); - LOG_VAR(zfc.waypointsFiles.size()); + // 06000200f8000000 + CHECK_RETURN_FALSE_LOG_OK(m_antMessenger->ANTFS_Direct(chan, SwapDWord(0x06000200f8000000))); - // TODO: read bcast here? - - // channel status <> - //CHECK_RETURN_FALSE_LOG_OK(ANT_RequestMessage(chan, MESG_CHANNEL_STATUS_ID)); - if(mode==MD_DIRECTORY_LISTING) - changeStateSafe(ST_ANTFS_LAST); - else - changeStateSafe(ST_ANTFS_DL_FILES); + // just exit + changeStateSafe(ST_ANTFS_LAST); } else if(state==ST_ANTFS_DL_FILES) { diff --git a/src/AntMessage.cpp b/src/AntMessage.cpp index 702b03f..9ba8daf 100644 --- a/src/AntMessage.cpp +++ b/src/AntMessage.cpp @@ -78,7 +78,9 @@ isAntFSCommandOrResponse(const uchar command, bool& isCommand) || command==ANTFS_ReqDownload || command==ANTFS_ReqUpload || command==ANTFS_ReqErase - || command==ANTFS_UploadData ) + || command==ANTFS_UploadData + || command==ANTFS_CmdDirect + ) { isCommand=true; return true; @@ -88,6 +90,7 @@ isAntFSCommandOrResponse(const uchar command, bool& isCommand) || command==ANTFS_RespUpload || command==ANTFS_RespErase || command==ANTFS_RespUploadData + || command==ANTFS_RespDirect ) { isCommand=false; @@ -312,6 +315,7 @@ AntMessage::str2() const } +// whether packet was sent or received, and time as string const string AntMessage::strDt(const double &dt) const { if(bytes.empty()) @@ -514,6 +518,7 @@ bool AntMessage::fromStringOfBytes(const char *s) } +/// Convert string of hexadecimal digits into binary byte array template <class Container> bool AntMessage::stringToBytes(const char *s, Container& bytes) diff --git a/src/AntMessage.hpp b/src/AntMessage.hpp index dee31f9..15947cf 100644 --- a/src/AntMessage.hpp +++ b/src/AntMessage.hpp @@ -290,6 +290,21 @@ struct M_ANTFS_Command return sstr.str(); } } uploadData; + + struct DirectResponse + { + ushort fd; + ushort offset; + ushort data; + const std::string toString() const + { + std::stringstream sstr; + sstr << "fd=0x" << antpm::toString(fd, 4, '0') + << ", offset=0x" << antpm::toString(offset, 4, '0') + << ", data=0x" << antpm::toString(data, 4, '0') ; + return sstr.str(); + } + } direct; } detail; const std::string toString() const { @@ -304,6 +319,7 @@ struct M_ANTFS_Command else if(command==ANTFS_ReqUpload) sstr << " " << detail.uploadRequest.toString(); else if(command==ANTFS_ReqErase) sstr << " " << detail.eraseRequest.toString(); else if(command==ANTFS_UploadData) sstr << " " << detail.uploadData.toString(); + else if(command==ANTFS_CmdDirect) sstr << " " << detail.direct.toString(); return sstr.str(); } }; @@ -323,11 +339,16 @@ struct M_ANTFS_Command_Pairing : public M_ANTFS_Command { uchar name[8]; // seems like 310XT can display properly up to 8 chars during the pairing screen }; +struct M_ANTFS_Command_Direct : public M_ANTFS_Command +{ + uint64_t code; +}; #pragma pack(pop) BOOST_STATIC_ASSERT(sizeof(M_ANTFS_Command)==8); BOOST_STATIC_ASSERT(sizeof(M_ANTFS_Command_Authenticate)==24); BOOST_STATIC_ASSERT(sizeof(M_ANTFS_Command_Download)==16); BOOST_STATIC_ASSERT(sizeof(M_ANTFS_Command_Pairing)==16); +BOOST_STATIC_ASSERT(sizeof(M_ANTFS_Command_Direct)==16); #pragma pack(push,1) struct M_ANTFS_Response @@ -464,6 +485,20 @@ struct M_ANTFS_Response return sstr.str(); } } uploadDataResponse; + struct DirectResponse + { + ushort fd; + ushort offset; + ushort data; + const std::string toString() const + { + std::stringstream sstr; + sstr << "fd=0x" << antpm::toString(fd, 4, '0') + << ", offset=0x" << antpm::toString(offset, 4, '0') + << ", data=0x" << antpm::toString(data, 4, '0') ; + return sstr.str(); + } + } directResponse; } detail; const std::string toString() const { @@ -476,6 +511,7 @@ struct M_ANTFS_Response else if(response==ANTFS_RespUpload) sstr << " " << detail.uploadRequestResponse.toString(); else if(response==ANTFS_RespErase) sstr << " " << detail.eraseRequestResponse.toString(); else if(response==ANTFS_RespUploadData) sstr << " " << detail.uploadDataResponse.toString(); + else if(response==ANTFS_RespDirect) sstr << " " << detail.directResponse.toString(); return sstr.str(); } }; diff --git a/src/AntMessenger.cpp b/src/AntMessenger.cpp index 37ca6cc..3786294 100644 --- a/src/AntMessenger.cpp +++ b/src/AntMessenger.cpp @@ -771,6 +771,210 @@ AntMessenger::ANTFS_RequestClientDeviceSerialNumber(const uchar chan, const uint return true; } + +bool +AntMessenger::ANTFS_Direct1(const uchar chan) +{ + // when authentication succeeds, State=Transport beacon arrives + //R 96.026 MESG_BROADCAST_DATA_ID chan=0x00 ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Transport, Auth=PasskeyAndPairingOnly + //R 124.999 MESG_BROADCAST_DATA_ID chan=0x00 ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Transport, Auth=PasskeyAndPairingOnly + //S 114.743 MESG_REQUEST_ID chan=0x00 reqMsgId=MESG_CHANNEL_STATUS_ID + //R 3.247 MESG_CHANNEL_STATUS_ID chan=00 chanSt=Tracking + //S 12.451 MESG_BURST_DATA_ID chan=0x00, seq=0, last=no ANTFS_CMD(0x44) ANTFS_CmdDirect fd=0xffff, offset=0x0000, data=0x0000 + //R 1.546 MESG_BROADCAST_DATA_ID chan=0x00 ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Transport, Auth=PasskeyAndPairingOnly + //S 2.477 MESG_BURST_DATA_ID chan=0x00, seq=1, last=yes fe00000000000000 ........ + +// R 115.556 MESG_BROADCAST_DATA_ID chan=0x00 ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Transport, Auth=PasskeyAndPairingOnly +// R 20.969 MESG_RESPONSE_EVENT_ID chan=0x00 mId=MESG_EVENT_ID mCode=EVENT_TRANSFER_TX_COMPLETED +// R 104.031 MESG_BROADCAST_DATA_ID chan=0x00 ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Busy, Auth=PasskeyAndPairingOnly +// R 125.005 MESG_BURST_DATA_ID chan=0x00, seq=0, last=no ANTFS_BEACON(0x43) Beacon=1Hz, pairing=disabled, upload=disabled, dataAvail=no, State=Busy, Auth=PasskeyAndPairingOnly +// R 28.971 MESG_BURST_DATA_ID chan=0x00, seq=1, last=no ANTFS_RESP(0x44) ANTFS_RespDirect fd=0xffff, offset=0x0000, data=0x0006 +// R 16.021 MESG_BURST_DATA_ID chan=0x00, seq=2, last=no ff002900cd02f000 ..)..... +// R 16.021 MESG_BURST_DATA_ID chan=0x00, seq=3, last=no 466f726572756e6e Forerunn +// R 16.021 MESG_BURST_DATA_ID chan=0x00, seq=1, last=no 6572203430352053 er 405 S +// R 16.021 MESG_BURST_DATA_ID chan=0x00, seq=2, last=no 6f66747761726520 oftware +// R 16.021 MESG_BURST_DATA_ID chan=0x00, seq=3, last=no 56657273696f6e20 Version +// R 16.021 MESG_BURST_DATA_ID chan=0x00, seq=1, last=yes 322e343000000000 2.40.... + + M_ANTFS_Command_Direct cmd; + cmd.commandId = ANTFS_CommandResponseId; + cmd.command = ANTFS_CmdDirect; + cmd.detail.direct.fd = 0xffff; + cmd.detail.direct.offset = 0x0000; + cmd.detail.direct.data = 0x0000; + cmd.code = SwapDWord(0xfe00000000000000); + + bool sentDirect = false; + for(int i = 0; i < ANTPM_RETRIES; i++) + { + sentDirect = false; + + LOG_VAR(waitForBroadcast(chan)); + + //CHECK_RETURN_FALSE_LOG_OK(collectBroadcasts(chan)); + sentDirect = ANT_SendBurstData2(chan, reinterpret_cast<uchar*>(&cmd), sizeof(cmd)); + + // TODO: read bcast here? + //AntMessage reply0; + //waitForMessage(MESG_RESPONSE_EVENT_ID, &reply0, 2000); + + AntChannel& pc(chs[chan]); + AntEvListener el(pc); + //pc.addEvListener(&el); + + uint8_t responseVal; + sentDirect = sentDirect && el.waitForEvent(responseVal, 800); + //pc.rmEvListener(&el); + sentDirect = sentDirect && (responseVal==EVENT_TRANSFER_TX_COMPLETED); + + if(sentDirect) + break; + else + sleepms(ANTPM_RETRY_MS); + } + CHECK_RETURN_FALSE_LOG_OK(sentDirect); + + + + // ANTFS_RespDirect + std::vector<uchar> burstData; + CHECK_RETURN_FALSE_LOG_OK(waitForBurst(chan, burstData, 10*1000)); + +// CHECK_RETURN_FALSE_LOG_OK(burstData.size()==2*8); +// const M_ANTFS_Response* resp(reinterpret_cast<const M_ANTFS_Response*>(&burstData[8])); +// CHECK_RETURN_FALSE_LOG_OK(resp->responseId==ANTFS_CommandResponseId); +// CHECK_RETURN_FALSE_LOG_OK(resp->response==ANTFS_RespAuthenticate); +// CHECK_RETURN_FALSE_LOG_OK(resp->detail.authenticateResponse.respType==1); // accept + + logger() << "got back = \"" << burstData.size() << "\" bytes\n"; + + CHECK_RETURN_FALSE_LOG_OK(ANT_RequestMessage(chan, MESG_CHANNEL_STATUS_ID)); + + return true; +} + + +bool +AntMessenger::ANTFS_Direct2(const uchar chan) +{ + M_ANTFS_Command_Direct cmd; + cmd.commandId = ANTFS_CommandResponseId; + cmd.command = ANTFS_CmdDirect; + cmd.detail.direct.fd = 0xffff; + cmd.detail.direct.offset = 0x0000; + cmd.detail.direct.data = 0x0000; + cmd.code = SwapDWord(0x06000200ff000000); + + bool sentDirect = false; + for(int i = 0; i < ANTPM_RETRIES; i++) + { + sentDirect = false; + + LOG_VAR(waitForBroadcast(chan)); + + //CHECK_RETURN_FALSE_LOG_OK(collectBroadcasts(chan)); + sentDirect = ANT_SendBurstData2(chan, reinterpret_cast<uchar*>(&cmd), sizeof(cmd)); + + // TODO: read bcast here? + //AntMessage reply0; + //waitForMessage(MESG_RESPONSE_EVENT_ID, &reply0, 2000); + + AntChannel& pc(chs[chan]); + AntEvListener el(pc); + //pc.addEvListener(&el); + + uint8_t responseVal; + sentDirect = sentDirect && el.waitForEvent(responseVal, 800); + //pc.rmEvListener(&el); + sentDirect = sentDirect && (responseVal==EVENT_TRANSFER_TX_COMPLETED); + + if(sentDirect) + break; + else + sleepms(ANTPM_RETRY_MS); + } + CHECK_RETURN_FALSE_LOG_OK(sentDirect); + + + + // ANTFS_RespDirect + std::vector<uchar> burstData; + CHECK_RETURN_FALSE_LOG_OK(waitForBurst(chan, burstData, 10*1000)); + +// CHECK_RETURN_FALSE_LOG_OK(burstData.size()==2*8); +// const M_ANTFS_Response* resp(reinterpret_cast<const M_ANTFS_Response*>(&burstData[8])); +// CHECK_RETURN_FALSE_LOG_OK(resp->responseId==ANTFS_CommandResponseId); +// CHECK_RETURN_FALSE_LOG_OK(resp->response==ANTFS_RespAuthenticate); +// CHECK_RETURN_FALSE_LOG_OK(resp->detail.authenticateResponse.respType==1); // accept + + logger() << "got back = \"" << burstData.size() << "\" bytes\n"; + + CHECK_RETURN_FALSE_LOG_OK(ANT_RequestMessage(chan, MESG_CHANNEL_STATUS_ID)); + + return true; +} + +bool +AntMessenger::ANTFS_Direct(const uchar chan, const uint64_t code) +{ + M_ANTFS_Command_Direct cmd; + cmd.commandId = ANTFS_CommandResponseId; + cmd.command = ANTFS_CmdDirect; + cmd.detail.direct.fd = 0xffff; + cmd.detail.direct.offset = 0x0000; + cmd.detail.direct.data = 0x0000; + cmd.code = code; + + bool sentDirect = false; + for(int i = 0; i < ANTPM_RETRIES; i++) + { + sentDirect = false; + + LOG_VAR(waitForBroadcast(chan)); + + //CHECK_RETURN_FALSE_LOG_OK(collectBroadcasts(chan)); + sentDirect = ANT_SendBurstData2(chan, reinterpret_cast<uchar*>(&cmd), sizeof(cmd)); + + // TODO: read bcast here? + //AntMessage reply0; + //waitForMessage(MESG_RESPONSE_EVENT_ID, &reply0, 2000); + + AntChannel& pc(chs[chan]); + AntEvListener el(pc); + //pc.addEvListener(&el); + + uint8_t responseVal; + sentDirect = sentDirect && el.waitForEvent(responseVal, 800); + //pc.rmEvListener(&el); + sentDirect = sentDirect && (responseVal==EVENT_TRANSFER_TX_COMPLETED); + + if(sentDirect) + break; + else + sleepms(ANTPM_RETRY_MS); + } + CHECK_RETURN_FALSE_LOG_OK(sentDirect); + + + + // ANTFS_RespDirect + std::vector<uchar> burstData; + CHECK_RETURN_FALSE_LOG_OK(waitForBurst(chan, burstData, 10*1000)); + +// CHECK_RETURN_FALSE_LOG_OK(burstData.size()==2*8); +// const M_ANTFS_Response* resp(reinterpret_cast<const M_ANTFS_Response*>(&burstData[8])); +// CHECK_RETURN_FALSE_LOG_OK(resp->responseId==ANTFS_CommandResponseId); +// CHECK_RETURN_FALSE_LOG_OK(resp->response==ANTFS_RespAuthenticate); +// CHECK_RETURN_FALSE_LOG_OK(resp->detail.authenticateResponse.respType==1); // accept + + logger() << "got back = \"" << burstData.size() << "\" bytes\n"; + + CHECK_RETURN_FALSE_LOG_OK(ANT_RequestMessage(chan, MESG_CHANNEL_STATUS_ID)); + + return true; +} + + void AntMessenger::eventLoop() { m_rpackQueue2.eventLoop(); diff --git a/src/AntMessenger.hpp b/src/AntMessenger.hpp index 067ff35..d8ecdf5 100644 --- a/src/AntMessenger.hpp +++ b/src/AntMessenger.hpp @@ -137,6 +137,10 @@ public: bool ANTFS_Erase(const uchar chan, const ushort file); bool ANTFS_RequestClientDeviceSerialNumber(const uchar chan, const uint hostSN, uint& sn, std::string& devName); + bool ANTFS_Direct1(const uchar chan); + bool ANTFS_Direct2(const uchar chan); + bool ANTFS_Direct(const uchar chan, const uint64_t code); + void eventLoop(); void kill(); private: diff --git a/src/antdefs.hpp b/src/antdefs.hpp index b117448..cd97bb6 100644 --- a/src/antdefs.hpp +++ b/src/antdefs.hpp @@ -114,6 +114,7 @@ static const unsigned char ANTP_NETKEY[8] = {0xA8,0xA4,0x23,0xB9,0xF5,0x5E,0x63, #define ANTFS_ReqUpload 0x0A #define ANTFS_ReqErase 0x0B #define ANTFS_UploadData 0x0C +#define ANTFS_CmdDirect 0x0D #define ANTFS_RespAuthenticate 0x84 @@ -121,6 +122,7 @@ static const unsigned char ANTP_NETKEY[8] = {0xA8,0xA4,0x23,0xB9,0xF5,0x5E,0x63, #define ANTFS_RespUpload 0x8A #define ANTFS_RespErase 0x8B #define ANTFS_RespUploadData 0x8C +#define ANTFS_RespDirect 0x8D diff --git a/src/antpm-downloader.cpp b/src/antpm-downloader.cpp index 7521108..86671d4 100644 --- a/src/antpm-downloader.cpp +++ b/src/antpm-downloader.cpp @@ -206,6 +206,7 @@ main(int argc, char** argv) char* ANTPM_405 = getenv("ANTPM_405"); if(ANTPM_405!=NULL && strncmp("1",ANTPM_405,1)==0) { + logger() << "\n\nApplying ANTPM_405 override mode!\n\n\n"; AntFr405 watch2(false); stopFunc = boost::bind(&AntFr405::stopAsync, &watch2); { diff --git a/src/common.cpp b/src/common.cpp index 42f686e..20e61d4 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -202,6 +202,22 @@ writeUInt64(const uint clientSN, const uint64_t& pairedKey) } } +uint64_t +SwapDWord(uint64_t a) +{ + a = ((a & 0x00000000000000FFULL) << 56) | + ((a & 0x000000000000FF00ULL) << 40) | + ((a & 0x0000000000FF0000ULL) << 24) | + ((a & 0x00000000FF000000ULL) << 8) | + ((a & 0x000000FF00000000ULL) >> 8) | + ((a & 0x0000FF0000000000ULL) >> 24) | + ((a & 0x00FF000000000000ULL) >> 40) | + ((a & 0xFF00000000000000ULL) >> 56); + return a; +} + + + std::vector<unsigned char> readFile(const char* fileName) { @@ -290,8 +306,8 @@ getVersionString() #ifdef __GNUC__ "GCC " __VERSION__ #elif defined(_MSC_VER) -# define STRINGIFY( L ) #L
-# define MAKESTRING( M, L ) M(L)
+# define STRINGIFY( L ) #L +# define MAKESTRING( M, L ) M(L) # define STRINGIZE(X) MAKESTRING( STRINGIFY, X ) + std::string("MSVC " STRINGIZE(_MSC_FULL_VER)) # undef STRINGIZE @@ -380,6 +396,7 @@ AntFSCommandNames antFSCommandNames[]={ ANTP_PAIR(ANTFS_ReqUpload), ANTP_PAIR(ANTFS_ReqErase), ANTP_PAIR(ANTFS_UploadData), + ANTP_PAIR(ANTFS_CmdDirect), {-1,"UNKNOWN"} }; @@ -389,6 +406,7 @@ AntFSResponseNames antFSResponseNames[]={ ANTP_PAIR(ANTFS_RespUpload), ANTP_PAIR(ANTFS_RespErase), ANTP_PAIR(ANTFS_RespUploadData), + ANTP_PAIR(ANTFS_RespDirect), {-1,"UNKNOWN"} }; diff --git a/src/common.hpp b/src/common.hpp index 74487ea..92ee2d9 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -66,6 +66,9 @@ readUInt64(const unsigned int clientSN, uint64_t& pairedKey); void writeUInt64(const unsigned int clientSN, const uint64_t& ui); +uint64_t +SwapDWord(uint64_t a); + std::vector<unsigned char> readFile(const char* fileName); |