Add missing #include for some headers
[wave300.git] / tools / mttools / drvhlpr / fshlpr.c
blob481be3843ea4d2e7b870b9ae06eada79689299bf
1 /******************************************************************************
3 Copyright (c) 2012
4 Lantiq Deutschland GmbH
6 For licensing information, see the file 'LICENSE' in the root folder of
7 this software module.
9 ******************************************************************************/
11 * $Id$
13 * wlan driver helper for file-system access
15 #include "mtlkinc.h"
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
21 #include "fshlpr.h"
22 #include "dataex.h"
23 #include "mtlkirba.h"
26 FIXME: EEPROM_CRC_ON_DRVHLPR
27 The driver helper should not know about EEPROM format.
28 To remove code after CRC generation on EEPROM data originator.
30 #if defined(EEPROM_CRC_ON_DRVHLPR)
31 #include "fshlpr_utest.h"
32 #endif /* defined(EEPROM_CRC_ON_DRVHLPR) */
34 #define LOG_LOCAL_GID GID_IRB
35 #define LOG_LOCAL_FID 3
37 /** IRB event for data storing on file-system */
38 static const mtlk_guid_t IRBE_FILE_SAVE = MTLK_IRB_GUID_FILE_SAVE;
40 /** Shell command to handle saved data */
41 static char file_saver[100];
43 #ifdef EEPROM_CRC_ON_DRVHLPR
44 /* NOTE: For temporal solution we can use unoptimized version */
45 static uint32
46 _crc32 (uint32 crc, uint8 const *p, uint32 len)
49 * There are multiple 16-bit CRC polynomials in common use, but this is
50 * *the* standard CRC-32 polynomial, first popularized by Ethernet.
51 * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
53 #define CRCPOLY_LE 0xedb88320
55 int i;
57 while (len--)
59 crc ^= *p++;
60 for (i = 0; i < 8; i++)
61 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
64 eeprom_utest_step(CRC_DONE);
66 return crc;
69 #define CIS_SECTION_HEADER_SIZE 2
71 /**
72 This function tries to find a CIS section by ID
74 \param id CIS block id to search for [I]
75 \param cis pointer to the CIS buffer [I]
76 \param cis_size size of CIS buffer in bytes [I]
78 \return
79 NULL if CIS block not found, otherwise pointer to the CIS section
81 static void*
82 _eeprom_cis_find (uint8 id, uint8 *cis, int cis_size)
84 MTLK_ASSERT(NULL != cis);
86 while (cis_size >= 1)
88 if (cis[0] == id)
89 return cis;
91 if (0xFF == cis[0])
92 return NULL;
94 if (cis_size < 2)
95 break;
97 if (cis[1] + CIS_SECTION_HEADER_SIZE > cis_size)
99 ELOG_DD("Corrupted EEPROM data detected, asked for %d bytes from %d "
100 "available bytes", cis[1] + CIS_SECTION_HEADER_SIZE, cis_size);
102 eeprom_utest_step(CIS_SIZE_WRONG);
104 return NULL;
108 cis_size -= cis[1] + CIS_SECTION_HEADER_SIZE;
109 cis += cis[1] + CIS_SECTION_HEADER_SIZE;
112 return NULL;
116 Append to the EEPROM data in the buffer CRC section
118 \param buffer handle to buffer with EEPROM data
119 \param size handle to the buffer with size of EEPROM data
121 \return
122 error code or MTLK_ERR_OK on success
124 \remark
125 The new buffer can be allocated. In that case the size value
126 will be updated also.
128 static int
129 _eeprom_crc_append(void **buffer, int *size)
131 #define EEPROM_CIS_HEADER_OFFSET 0x40
132 #define EEPROM_CIS_HEADER_SIZE 8
134 #define EEPROM_CIS_CRC_ID 0x85
135 #define EEPROM_CIS_CRC_LEN 4
136 #define EEPROM_TERMINATOR_ID 0xFF
138 #define EEPROM_CRC_SECTION_SIZE (CIS_SECTION_HEADER_SIZE + EEPROM_CIS_CRC_LEN)
139 #define EEPROM_TERMINATOR_SIZE 1
140 #define EEPROM_PUT8(v) { (*p) = (v); p++; }
142 uint8 *p, *p_crc, *dst, *src = *buffer;
143 uint16 data_size, used_data;
144 uint32 crc;
146 /* Check for minimum EEPROM data size */
147 if (*size < (EEPROM_CIS_HEADER_OFFSET + EEPROM_CIS_HEADER_SIZE))
149 ELOG_D("FS HLPR: Wrong size of EEPROM data [%d]", *size);
151 eeprom_utest_step(EEPROM_SIZE_WRONG);
153 return MTLK_ERR_EEPROM;
156 /* Check for valid EEPROM data header */
157 if ((0xFC != src[0]) || (0x1B != src[1]))
159 ELOG_DD("FS HLPR: Wrong EEPROM data header [%02x %02x]", src[0], src[1]);
161 eeprom_utest_step(EEPROM_HEAD_WRONG);
163 return MTLK_ERR_EEPROM;
166 /* Check for valid CIS area data size */
167 data_size = src[EEPROM_CIS_HEADER_OFFSET + 0];
168 data_size |= src[EEPROM_CIS_HEADER_OFFSET + 1] << 8;
169 if (*size < (EEPROM_CIS_HEADER_OFFSET + data_size))
171 ELOG_D("FS HLPR: Wrong size of EEPROM CIS data [%d]", data_size);
173 eeprom_utest_step(CIS_AREA_SIZE_WRONG);
175 return MTLK_ERR_EEPROM;
178 /* Check for valid EEPROM version */
179 if (4 != src[EEPROM_CIS_HEADER_OFFSET + 7])
181 ELOG_D("FS HLPR: Unsupported version of the EEPROM [%d]",
182 src[EEPROM_CIS_HEADER_OFFSET + 7]);
184 eeprom_utest_step(EEPROM_VERSION_WRONG);
186 return MTLK_ERR_EEPROM;
189 /* Check for CRC field presence */
190 p_crc = _eeprom_cis_find(EEPROM_CIS_CRC_ID,
191 src + EEPROM_CIS_HEADER_OFFSET + EEPROM_CIS_HEADER_SIZE,
192 data_size - EEPROM_CIS_HEADER_SIZE);
193 if(NULL != p_crc)
195 /* NOTE: The input signal to remove that code. */
196 ILOG0_V("FS HLPR: The CRC section already present in EEPROM data");
198 eeprom_utest_step(CRC_PRESENT);
201 /* Find EEPROM data terminator */
202 p = _eeprom_cis_find(EEPROM_TERMINATOR_ID,
203 src + EEPROM_CIS_HEADER_OFFSET + EEPROM_CIS_HEADER_SIZE,
204 data_size - EEPROM_CIS_HEADER_SIZE);
205 if (NULL == p)
207 ELOG_V("FS HLPR: Missed terminator for CIS section in EEPROM data");
209 eeprom_utest_step(TERMINATOR_MISSED);
211 return MTLK_ERR_EEPROM;
214 used_data = ((p - src) + EEPROM_TERMINATOR_SIZE);
215 if(NULL == p_crc)
217 used_data += EEPROM_CRC_SECTION_SIZE;
220 /* Check for available buffer */
221 if ((*size) >= used_data)
223 ILOG3_V("FS HLPR: Use the same buffer for EEPROM data");
224 /* reuse current buffer */
225 dst = src;
226 /* p: already store write pointer */
228 eeprom_utest_step(BUFFER_REUSED);
230 else
232 ILOG3_D("FS HLPR: Allocate new buffer for EEPROM data [%d]", used_data);
234 /* allocate new buffer */
235 dst = malloc(used_data);
236 if (NULL == dst)
238 ELOG_D("FS HLPR: Failed to allocate memory [%d]", used_data);
239 return MTLK_ERR_NO_MEM;
242 memcpy(dst, src, used_data - EEPROM_CRC_SECTION_SIZE);
244 *buffer = dst;
245 *size = used_data;
247 /* prepare write pointer */
248 p = dst + (p - src);
250 eeprom_utest_step(BUFFER_RECREATED);
253 /* Correct valid CIS area data size if needed */
254 if (data_size < (used_data - EEPROM_CIS_HEADER_OFFSET))
256 ILOG3_DD("FS HLPR: Valid date size in CIS area is updated from [%d] to [%d]",
257 data_size, used_data - EEPROM_CIS_HEADER_OFFSET);
259 data_size = used_data - EEPROM_CIS_HEADER_OFFSET;
261 dst[EEPROM_CIS_HEADER_OFFSET + 0] = (data_size >> 0) & 0x00FF;
262 dst[EEPROM_CIS_HEADER_OFFSET + 1] = (data_size >> 8) & 0x00FF;
264 eeprom_utest_step(CIS_AREA_SIZE_UPDATED);
267 if(p_crc)
269 /*CIS CRC already persist*/
270 /* Do CRC calculation for first chunk before CIS CRC*/
271 int chunk_size;
273 chunk_size = p_crc - src + CIS_SECTION_HEADER_SIZE;
274 crc = _crc32(~0L, dst, chunk_size);
275 ILOG1_DD("FS HLPR: Calculate CRC32 [0x%08x] for EEPROM data first chunk [%d]", crc, chunk_size);
277 /* Do CRC calculation for second chunk after CIS CRC*/
278 chunk_size = (p - dst) - (p_crc - src) - EEPROM_CRC_SECTION_SIZE;
279 crc = _crc32(crc, dst + (p_crc - src) + EEPROM_CRC_SECTION_SIZE, chunk_size);
280 ILOG1_DD("FS HLPR: Calculate CRC32 [0x%08x] for EEPROM data second chunk [%d]", crc, chunk_size);
281 crc ^= ~0L;
282 ILOG1_DD("FS HLPR: Calculate CRC32 [0x%08x] for EEPROM data second chunk [%d]", crc, chunk_size);
284 /*update pointer to CIS CRC area*/
285 p = dst + (p_crc - src) + CIS_SECTION_HEADER_SIZE;
287 else
289 /* write CIS CRC*/
290 EEPROM_PUT8(EEPROM_CIS_CRC_ID);
291 EEPROM_PUT8(EEPROM_CIS_CRC_LEN);
293 /* Do CRC calculation */
294 crc = _crc32(~0L, dst, p - dst);
295 crc ^= ~0L;
296 ILOG1_DD("FS HLPR: Calculate CRC32 [0x%08x] for EEPROM data [%d]", crc, p - dst);
299 /* Complete EEPROM data (big-endian) */
300 EEPROM_PUT8((crc >> 0) & 0x000000FF);
301 EEPROM_PUT8((crc >> 8) & 0x000000FF);
302 EEPROM_PUT8((crc >> 16) & 0x000000FF);
303 EEPROM_PUT8((crc >> 24) & 0x000000FF);
305 if(NULL == p_crc)
307 EEPROM_PUT8(EEPROM_TERMINATOR_ID);
310 return MTLK_ERR_OK;
312 #endif /* EEPROM_CRC_ON_DRVHLPR */
315 IRBE_FILE_SAVE event handler
317 \param irba Handle to the IRBD interface [I]
318 \param context unused [I]
319 \param evt IRB event GUID [I]
320 \param buffer Handle to the event data [I]
321 \param size Size of event data [I]
323 static void
324 _file_save_handler (mtlk_irba_t *irba,
325 mtlk_handle_t context,
326 const mtlk_guid_t *evt,
327 void *buffer,
328 uint32 size)
330 struct mtlk_file_save *evt_data = buffer;
331 void *data;
332 int fd, written = 0, data_size;
333 /** \note:
334 The last six characters of template must be XXXXXX and these are
335 replaced with a string that makes the filename unique. */
336 char fname_template[] = "/tmp/tmp_fshlpr.XXXXXX";
338 MTLK_UNREFERENCED_PARAM(irba);
339 MTLK_UNREFERENCED_PARAM(context);
340 MTLK_UNREFERENCED_PARAM(evt);
342 MTLK_ASSERT(mtlk_guid_compare(&IRBE_FILE_SAVE, evt) == 0);
343 MTLK_ASSERT(NULL != evt_data);
345 if (size != (evt_data->size + sizeof(struct mtlk_file_save)))
347 ELOG_D("FS HLPR: wrong event received [%u]", size);
348 return;
351 fd = mkstemp(fname_template);
352 if (-1 == fd)
354 ELOG_SS("FS HLPR: can't create temporary file '%s' [%s]",
355 fname_template, strerror(errno));
356 return;
359 /* The data to be written into the file is placed after event header */
360 data = (evt_data + 1);
361 data_size = evt_data->size;
363 #ifdef EEPROM_CRC_ON_DRVHLPR
364 if (MTLK_ERR_OK != _eeprom_crc_append(&data, &data_size))
366 ELOG_S("FS HLPR: Failed to append CRC value for EEPROM data '%s'",
367 evt_data->fname);
369 eeprom_utest_step(CRC_APPEND_FAILED);
371 goto OUT;
373 #endif /* EEPROM_CRC_ON_DRVHLPR */
375 #if defined(EEPROM_CRC_ON_DRVHLPR) && defined(RUN_EEPROM_CRC_UTEST)
376 MTLK_UNREFERENCED_PARAM(written);
377 eeprom_utest_write(data, data_size);
378 #else /* defined(EEPROM_CRC_ON_DRVHLPR) && defined(RUN_EEPROM_CRC_UTEST) */
380 written = write(fd, data, data_size);
382 close(fd);
384 if (-1 == written)
386 ELOG_SS("FS HLPR: write error in to the temporary file '%s' [%s]",
387 fname_template, strerror(errno));
389 else if (written != data_size)
391 ELOG_DSD("FS HLPR: can't write '%d' bytes to temporary file '%s' [%d]",
392 data_size, fname_template, written);
394 else
396 char cmd[0x100];
398 snprintf(cmd, sizeof(cmd), "%s '%s' '%s'", file_saver, fname_template,
399 evt_data->fname);
401 if (0 != system(cmd))
403 ELOG_S("FS HLPR: failed 'file saver' command [%s]", cmd);
406 #endif /* defined(EEPROM_CRC_ON_DRVHLPR) && defined(RUN_EEPROM_CRC_UTEST) */
408 #ifdef EEPROM_CRC_ON_DRVHLPR
409 if (data != (void*)(evt_data + 1))
411 eeprom_utest_step(NEW_BUFFER_CLEANED);
413 free(data);
414 data = NULL;
416 OUT:
417 #endif /* EEPROM_CRC_ON_DRVHLPR */
419 if (0 != remove(fname_template))
420 ELOG_SS("FS HLPR: can't remove temporary file '%s' [%s]",
421 fname_template, strerror(errno));
426 Initialization routine for file-system helper
428 \return
429 Handle to the IRB client
431 static mtlk_handle_t
432 _fs_hlpr_start (void)
434 mtlk_irba_handle_t *h =
435 mtlk_irba_register(MTLK_IRBA_ROOT, &IRBE_FILE_SAVE, 1,
436 _file_save_handler, 0);
438 #if defined(EEPROM_CRC_ON_DRVHLPR) && defined(RUN_EEPROM_CRC_UTEST)
439 run_eeprom_crc_utest(_file_save_handler);
440 #endif /* defined(EEPROM_CRC_ON_DRVHLPR) && defined(RUN_EEPROM_CRC_UTEST) */
442 return HANDLE_T(h);
446 Cleanup routine for file-system helper
448 \param ctx Handle to the IRB client [I]
450 static void
451 _fs_hlpr_stop (mtlk_handle_t ctx)
453 mtlk_irba_unregister(MTLK_IRBA_ROOT, HANDLE_T_PTR(mtlk_irba_handle_t, ctx));
457 File-system helper API
459 const mtlk_component_api_t
460 irb_fs_hlpr_api = {
461 _fs_hlpr_start,
462 NULL,
463 _fs_hlpr_stop
467 Configure shell command to handle saved data, see \ref file_saver
469 \param cmd Null-terminated string with shell command [I]
471 \return
472 error code or MTLK_ERR_OK on success
474 \remark
475 The cmd buffer can be modified during rtrim operation
477 int __MTLK_IFUNC
478 fs_hlpr_set_saver (char *cmd)
480 struct stat sb;
481 char *end;
483 if (NULL == cmd)
485 ELOG_V("FS HLPR: missed file saver name");
486 return MTLK_ERR_PARAMS;
489 /* ltrim */
490 while ((' ' == (*cmd)) || ('\t' == (*cmd))) cmd++;
492 /* rtrim */
493 end = cmd + strlen(cmd);
494 while ((end != cmd) && ((' ' == (*end)) || ('\t' == (*end)))) end--;
495 *end = '\0';
497 if (0 == strlen(cmd))
499 ELOG_V("FS HLPR: empty file saver name");
500 return MTLK_ERR_PARAMS;
503 if (strlen(cmd) > sizeof(file_saver))
505 ELOG_D("FS HLPR: file saver name exceed the limit %d", sizeof(file_saver));
506 return MTLK_ERR_PARAMS;
509 if (0 != stat(cmd, &sb))
511 ELOG_S("FS HLPR: file saver '%s' do not exists", cmd);
512 return MTLK_ERR_PARAMS;
515 if (0 == (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
517 ELOG_S("FS HLPR: file saver '%s' do not executable", cmd);
518 return MTLK_ERR_PARAMS;
521 snprintf(file_saver, sizeof(file_saver), "%s", cmd);
523 return MTLK_ERR_OK;