1 /*
2  ** Licensed under the Apache License, Version 2.0 (the "License");
3  ** you may not use this file except in compliance with the License.
4  ** You may obtain a copy of the License at
5  **
6  ** http://www.apache.org/licenses/LICENSE-2.0
7  **
8  ** Unless required by applicable law or agreed to in writing, software
9  ** distributed under the License is distributed on an "AS IS" BASIS,
10  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  ** See the License for the specific language governing permissions and
12  ** limitations under the License.
13  **
14  ** Copyright 2022-2023 NXP
15  **
16  */
17 #include "phNxpEventLogger.h"
18 
19 #include <errno.h>
20 #include <phNxpConfig.h>
21 #include <phNxpLog.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <unistd.h>
25 
26 #include <fstream>
27 #include <iomanip>
28 
29 #define TIMESTAMP_BUFFER_SIZE 64
30 
PhNxpEventLogger()31 PhNxpEventLogger::PhNxpEventLogger() { logging_enabled_ = false; }
GetInstance()32 PhNxpEventLogger& PhNxpEventLogger::GetInstance() {
33   static PhNxpEventLogger nxp_event_logger_;
34   return nxp_event_logger_;
35 }
36 
37 // Helper function to get current timestamp of the
38 // device in [MM:DD HH:MIN:SEC:MSEC] format
39 
GetCurrentTimestamp(char * timestamp)40 static void GetCurrentTimestamp(char* timestamp) {
41   struct timespec tv;
42   clock_gettime(CLOCK_REALTIME, &tv);
43   time_t rawtime = tv.tv_sec;
44   struct tm* timeinfo;
45   char buffer[TIMESTAMP_BUFFER_SIZE];
46 
47   timeinfo = localtime(&rawtime);
48   // Need to calculate millisec separately as timeinfo doesn't
49   // have milliseconds field
50   int milliseconds = tv.tv_nsec / 1000000;
51 
52   strftime(buffer, sizeof(buffer), "%m-%d %H:%M:%S", timeinfo);
53   sprintf(timestamp, "[%s.%03d]:", buffer, milliseconds);
54 }
55 
Initialize()56 void PhNxpEventLogger::Initialize() {
57   NXPLOG_NCIHAL_D("EventLogger: init");
58   dpd_logFile_.open(kDPDEventFilePath, std::ofstream::out |
59                                            std::ofstream::binary |
60                                            std::ofstream::app);
61   if (dpd_logFile_.fail()) {
62     NXPLOG_NCIHAL_D("EventLogger: Log file %s couldn't be opened! %d",
63                     kDPDEventFilePath, errno);
64   } else {
65     mode_t permissions = 0744;  // rwxr--r--
66     if (chmod(kDPDEventFilePath, permissions) == -1) {
67       NXPLOG_NCIHAL_D("EventLogger: chmod failed on %s errno: %d",
68                       kDPDEventFilePath, errno);
69     }
70   }
71 
72   unsigned long value = 0;
73   if (GetNxpNumValue(NAME_NXP_SMBLOG_ENABLED, &value, sizeof(value))) {
74     logging_enabled_ = (value == 1) ? true : false;
75   }
76   if (!logging_enabled_) return;
77 
78   smb_logFile_.open(kSMBLogFilePath, std::ofstream::out |
79                                          std::ofstream::binary |
80                                          std::ofstream::app);
81   if (smb_logFile_.fail()) {
82     NXPLOG_NCIHAL_D("EventLogger: Log file %s couldn't be opened! errno: %d",
83                     kSMBLogFilePath, errno);
84   }
85 }
Log(uint8_t * p_ntf,uint16_t p_len,LogEventType event)86 void PhNxpEventLogger::Log(uint8_t* p_ntf, uint16_t p_len, LogEventType event) {
87   NXPLOG_NCIHAL_D("EventLogger: event is %d", event);
88   switch (event) {
89     case LogEventType::kLogSMBEvent:
90       if (!logging_enabled_) return;
91       if (smb_logFile_.is_open()) {
92         while (p_len) {
93           smb_logFile_ << std::setfill('0') << std::hex << std::uppercase
94                        << std::setw(2) << (0xFF & *p_ntf);
95           ++p_ntf;
96           --p_len;
97         }
98         smb_logFile_ << std::endl;
99       } else {
100         NXPLOG_NCIHAL_D("EventLogger: Log file %s is not opened",
101                         kSMBLogFilePath);
102       }
103       break;
104     case LogEventType::kLogDPDEvent:
105       if (dpd_logFile_.is_open()) {
106         char timestamp[TIMESTAMP_BUFFER_SIZE];
107         memset(timestamp, 0, TIMESTAMP_BUFFER_SIZE);
108         GetCurrentTimestamp(timestamp);
109         dpd_logFile_ << timestamp;
110         while (p_len) {
111           dpd_logFile_ << std::setfill('0') << std::hex << std::uppercase
112                        << std::setw(2) << (0xFF & *p_ntf);
113           ++p_ntf;
114           --p_len;
115         }
116         dpd_logFile_ << std::endl;
117       } else {
118         NXPLOG_NCIHAL_D("EventLogger: Log file %s is not opened",
119                         kDPDEventFilePath);
120       }
121       break;
122     default:
123       NXPLOG_NCIHAL_D("EventLogger: Invalid destination");
124   }
125 }
126 
Finalize()127 void PhNxpEventLogger::Finalize() {
128   NXPLOG_NCIHAL_D("EventLogger: closing the Log file");
129   if (dpd_logFile_.is_open()) dpd_logFile_.close();
130   if (smb_logFile_.is_open()) smb_logFile_.close();
131 }
132