1 /*
2  *    Copyright (C) 2013 SAMSUNG S.LSI
3  *
4  *   Licensed under the Apache License, Version 2.0 (the "License");
5  *   you may not use this file except in compliance with the License.
6  *   You may obtain a copy of the License at:
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *   Unless required by applicable law or agreed to in writing, software
11  *   distributed under the License is distributed on an "AS IS" BASIS,
12  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *   See the License for the specific language governing permissions and
14  *   limitations under the License.
15  *
16  *
17  */
18 
19 #include <ctype.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "util.h"
26 
27 /* START [H17080801] HAL config file path */
28 #define CFG_FILE_1 "/vendor/etc/libnfc-sec-vendor.conf"
29 #define CFG_FILE_2 "/etc/libnfc-sec-vendor.conf"
30 /* END [H17080801] HAL config file path */
31 
32 #define isToken(x) (x == ':' || x == '=' || x == ' ' || x == '\t')
33 #define skipToken(x) \
34   while (isToken(*x)) x++
35 #define skipSpace(x) \
36   while (isspace(*x)) x++
37 
willBeContinuous(char * buffer,size_t maxlen)38 bool willBeContinuous(char* buffer, size_t maxlen) {
39   char* p;
40   size_t len;
41   if (!buffer) return false;
42 
43   len = strnlen(buffer, maxlen);
44   if (len == maxlen && buffer[len - 2] != '\n') return true;
45 
46   p = buffer + len - 1;
47   while (isspace(*p) && p > buffer) p--;
48   if (*p == '\\') return true;
49   return false;
50 }
51 
find_by_name_from_current(FILE * file,const char * field)52 bool find_by_name_from_current(FILE* file, const char* field) {
53   char *p, buffer[256] = {
54                '\0',
55            };
56   size_t len;
57   int fp;
58   bool skip = false;
59 
60   if (!file || !field) return false;
61 
62   len = strlen(field);
63   while (!feof(file) && fgets(buffer, sizeof(buffer) - 1, file)) {
64     if (skip) {
65       skip = willBeContinuous(buffer, sizeof(buffer));
66       continue;
67     }
68     skip = willBeContinuous(buffer, sizeof(buffer));
69 
70     p = buffer;
71     skipSpace(p);
72     if (*p == '#') continue;
73 
74     if (!strncmp((char const*)field, (char const*)p, len)) {
75       fp = -strlen(p);
76       fp += len;
77       return (fseek(file, fp, SEEK_CUR) == 0) ? true : false;
78     }
79   }
80   return false;
81 }
82 
find_by_name(FILE * file,const char * field)83 bool find_by_name(FILE* file, const char* field) {
84   fseek(file, 0x00, SEEK_SET);
85   return find_by_name_from_current(file, field);
86 }
87 
__get_config_int(char * file_path,const char * field,int * data,int option)88 bool __get_config_int(__attribute__((unused)) char* file_path,
89                       const char* field, int* data, int option) {
90   FILE* file;
91   char buffer[10], *p, *endp;
92   size_t len;
93   long int val;
94 
95   if (!field || !data) return false;
96 
97   /* START [H17080801] HAL config file path */
98   if ((file = fopen(CFG_FILE_1, "rb")) == NULL) {
99     OSI_loge("Cannot open config file %s", CFG_FILE_1);
100     if ((file = fopen(CFG_FILE_2, "rb")) == NULL) {
101       OSI_loge("Cannot open config file %s", CFG_FILE_2);
102       return 0;
103     }
104   }
105   /* END [H17080801] HAL config file path */
106 
107   if (!find_by_name(file, field)) {
108     OSI_loge("Cannot find the field name [%s]", field);
109     goto fail;
110   }
111 
112   if (!fgets(buffer, sizeof(buffer) - 1, file)) {
113     OSI_loge("Read failed");
114     goto fail;
115   }
116 
117   if (willBeContinuous(buffer, sizeof(buffer)))  // not supported multi line
118     goto fail;
119 
120   if ((len = strlen(buffer)) == sizeof(buffer) - 1) {
121     OSI_loge("It is too long data [%s~]; max", buffer);
122     goto fail;
123   }
124 
125   p = buffer;
126   skipToken(p);
127   if (*p == '\0') {
128     OSI_loge("It is empty data");
129     goto fail;
130   }
131 
132   if (((*p == '0') && (*(p + 1) == 'x')) || option == HAL_UTIL_GET_INT_16)
133     val = strtol(p, &endp, 0x10);
134   else
135     val = strtol(p, &endp, 10);
136 
137   if (p == endp) {
138     OSI_loge("Read failed [%s]", buffer);
139     goto fail;
140   }
141 
142   OSI_logd("Get config %s: %ld(0x%lx)", field, val, val);
143 
144   fclose(file);
145 
146   *data = val;
147   return true;
148 
149 fail:
150   fclose(file);
151   return false;
152 }
153 
get_config_int(const char * field,int * data)154 bool get_config_int(const char* field, int* data) {
155   /* START [17080801] HAL config file path */
156   return __get_config_int((char*)CFG_FILE_1, field, data, 0);
157   /* END [17080801] HAL config file path */
158 }
159 
get_config_string(const char * field,char * strBuffer,size_t bufferSize)160 int get_config_string(const char* field, char* strBuffer, size_t bufferSize) {
161   FILE* file;
162   char data[256], *buffer, *p;
163   bool readmore = true;
164   size_t count = 0;
165 
166   if (!field || !strBuffer || bufferSize < 1) return 0;
167 
168   /* START [H17080801] HAL config file path */
169   if ((file = fopen(CFG_FILE_1, "rb")) == NULL) {
170     OSI_loge("Cannot open config file %s", CFG_FILE_1);
171     if ((file = fopen(CFG_FILE_2, "rb")) == NULL) {
172       OSI_loge("Cannot open config file %s", CFG_FILE_2);
173       return 0;
174     }
175   }
176   /* END [H17080801] HAL config file path */
177 
178   if (!find_by_name(file, field)) {
179     OSI_logd("Cannot find the field name [%s]", field);
180     goto fail;
181   }
182 
183   if ((buffer = (char*)malloc(bufferSize)) == NULL) {
184     OSI_logd("Cannot allocate temporary buffer for [%s]", field);
185     goto fail;
186   }
187 
188   while (count < bufferSize - 1 && readmore) {
189     if (!fgets(data, sizeof(data) - 1, file)) {
190       OSI_loge("Read failed");
191       goto fail_free;
192     }
193 
194     readmore = willBeContinuous(data, sizeof(data));
195     p = data;
196     while ((p = strchr(p, '"')) != NULL)  // start string
197     {
198       for (p++; *p != '"'; p++)  // end string
199       {
200         if (*p == '\n' || *p == '\0' || *p == '\\') {
201           OSI_loge("Cannot find ending point of string");
202           goto fail_free;
203         }
204         buffer[count++] = *p;
205       }
206       p++;
207     }
208   }
209   buffer[count] = '\0';
210 
211   OSI_logd("Get config %s: %s", field, buffer);
212   if (count == bufferSize) {
213     if (p == NULL)
214       goto fail_free;
215     else if (*p != '\n')
216       OSI_loge("Overflower!, remained data is [%s]", p);
217     else if (readmore)
218       OSI_loge("Overflower!, data is remained! (multi line)");
219   }
220 
221   count++;
222   memcpy(strBuffer, buffer, count);
223   free(buffer);
224 
225   fclose(file);
226   return count;
227 
228 fail_free:
229   free(buffer);
230 fail:
231   fclose(file);
232   return 0;
233 }
234 
get_config_count(const char * field)235 int get_config_count(const char* field) {
236   FILE* file;
237   int count = 0;
238 
239   /* START [H17080801] HAL config file path */
240   if ((file = fopen(CFG_FILE_1, "rb")) == NULL) {
241     OSI_loge("Cannot open config file %s", CFG_FILE_1);
242     if ((file = fopen(CFG_FILE_2, "rb")) == NULL) {
243       OSI_loge("Cannot open config file %s", CFG_FILE_2);
244       return 0;
245     }
246   }
247   /* END [H17080801] HAL config file path */
248 
249   while (find_by_name_from_current(file, field)) count++;
250 
251   fclose(file);
252   return count;
253 }
254 
get_hw_rev()255 int get_hw_rev() {
256   char* info_file = (char*)"/proc/cpuinfo";
257   char* field = (char*)"Revision";
258   int rev = -1;
259 
260   OSI_logd("%s enter;", __func__);
261   __get_config_int(info_file, field, &rev, HAL_UTIL_GET_INT_16);
262   OSI_logd("%s exit; rev = %d", __func__, rev);
263 
264   return rev;
265 }
266