iplemented 1st part of BBM player app: finding files and parsing BBM header
Stefan Schuermans

Stefan Schuermans commited on 2012-05-06 15:16:58
Showing 8 changed files, with 471 additions and 111 deletions.

... ...
@@ -60,7 +60,7 @@ SRC = $(TARGET).c
60 60
 
61 61
 # If there is more than one source file, append them above, or modify and
62 62
 # uncomment the following:
63
-SRC += app_cfg.c apps.c \
63
+SRC += app_bbm.c app_cfg.c apps.c apps_tools.c \
64 64
        arp.c bus.c cf.c checksum.c config.c dhcp.c dosfs.c dosfs_user.c \
65 65
        eeprom.c ethernet.c http.c icmp.c ip.c random.c rtl8019.c \
66 66
        ser62500.c status.c tasks.c tcp.c timing.c uart.c udp.c \
... ...
@@ -0,0 +1,237 @@
1
+/* flaneth - flash and ethernet
2
+   Copyright (C) 2007-2012 Stefan Schuermans <stefan@schuermans.info>
3
+   Copyleft: GNU public license V2 - http://www.gnu.org/copyleft/gpl.html
4
+   a BlinkenArea project - http://www.blinkenarea.org/ */
5
+
6
+#include <stdio.h>
7
+#include <string.h>
8
+
9
+#include "apps_tools.h"
10
+#include "app_bbm.h"
11
+#include "debug.h"
12
+#include "dosfs.h"
13
+#include "nethelp.h"
14
+#include "timing.h"
15
+
16
+///< BBM file header
17
+typedef struct app_bbm_header {
18
+  uint32_t magic;
19
+  uint16_t height;
20
+  uint16_t width;
21
+  uint16_t channels;
22
+  uint16_t maxval;
23
+  uint32_t framecnt;
24
+  uint32_t duration;
25
+  uint32_t frameptr;
26
+} AppBbmHeader;
27
+
28
+/**
29
+ * @brief get name of next file from playlist directory
30
+ * @param[in,out] state internal state of application
31
+ * @param[out] filename name of file
32
+ * @param[in] filename_sz length of filename buffer
33
+ * @return 0 if success ful, -1 if not
34
+ */
35
+static char AppBbmNextName(AppBbmState *state, char *filename,
36
+                           unsigned char filename_sz)
37
+{
38
+  // assemble filename of playlist directory
39
+  char dirname[10];
40
+  sprintf(dirname, "bbm%hhu/pl", state->no);
41
+
42
+  // open playlist directory
43
+  DIRINFO di;
44
+  di.scratch = *state->sectorBuf;
45
+  if (DFS_OpenDir(state->vi, (uint8_t *)dirname, &di) != DFS_OK) {
46
+    // no playlist dir -> deactivate application
47
+    state->isInit = 0;
48
+    debug_app_bbm_printf("%hhu: cannot open directory %s",
49
+                         state->no, filename);
50
+    return -1;
51
+  }
52
+
53
+  // get file with index idxFile
54
+  DIRENT de;
55
+  unsigned short idx;
56
+  char firstName[11], haveFirst;
57
+  haveFirst = 0;
58
+  for (idx = 0; idx <= /* file 0 -> loop once */ state->idxFile; ++idx) {
59
+
60
+    // get next file
61
+    do {
62
+      if (DFS_GetNext(state->vi, &di, &de) != 0) {
63
+        // no files at all -> deactivate application
64
+        if (!haveFirst) {
65
+          state->isInit = 0;
66
+          debug_app_bbm_printf("%hhu: no files in playlist directory",
67
+                               state->no);
68
+          return -1;
69
+        }
70
+        // end of (non-empty) playlist reached -> restart playlist
71
+        // -> return first file name, next file index 1
72
+        snprintf(filename, filename_sz,
73
+                 "bbm%hhu/pl/%-11.11s", state->no, firstName);
74
+        filename[filename_sz - 1] = 0;
75
+        state->idxFile = 1;
76
+        return 0;
77
+      }
78
+    } while (de.name[0] == 0 ||                            // ignore deleted
79
+             de.attr & (ATTR_VOLUME_ID | ATTR_DIRECTORY)); // ignore volumeIDs,
80
+                                                           // dirs, long names
81
+
82
+    // first file found -> save name (for restarting playlist when end reached)
83
+    if (!haveFirst) {
84
+      memcpy(firstName, de.name, sizeof(firstName));
85
+      haveFirst = 1;
86
+    }
87
+
88
+  } // for idx
89
+
90
+  // found name of file with index idxFile
91
+  // -> return file name, increment file index for next file
92
+  snprintf(filename, filename_sz,
93
+           "bbm%hhu/pl/%-11.11s", state->no, de.name);
94
+  filename[filename_sz - 1] = 0;
95
+  state->idxFile++;
96
+  return 0;
97
+}
98
+
99
+/**
100
+ * @brief parse header of BBM file
101
+ * @param[in,out] state internal state of application
102
+ */
103
+static void AppBbmParseHeader(AppBbmState *state)
104
+{
105
+  // read BBM header
106
+  AppBbmHeader hdr;
107
+  uint32_t len;
108
+  if (DFS_ReadFile(&state->fi, *state->sectorBuf,
109
+                   (uint8_t *)&hdr, &len, sizeof(hdr)) != DFS_OK)
110
+    len = 0;
111
+  if (len < sizeof(hdr)) {
112
+    debug_app_bbm_printf("%hhu: truncated BBM file", state->no);
113
+    return; // retry with next file in next iteration
114
+  }
115
+
116
+  // check header
117
+  if (ntohl(hdr.magic) != 0x23542666) {
118
+    debug_app_bbm_printf("%hhu: invalid magic %lX in BBM file",
119
+                         state->no, hdr.magic);
120
+    return; // retry with next file in next iteration
121
+  }
122
+  state->height   = ntohs(hdr.height);
123
+  state->width    = ntohs(hdr.width);
124
+  state->channels = ntohs(hdr.channels);
125
+  state->maxval   = ntohs(hdr.maxval);
126
+  if (state->height < 1 || state->height > 1000 ||
127
+      state->width < 1 || state->width > 1000 ||
128
+      state->channels < 1 || state->channels > 3 ||
129
+      state->maxval < 1 || state->maxval > 255) {
130
+    debug_app_bbm_printf("%hhu: invalid dimensions in BBM file", state->no);
131
+    return; // retry with next file in next iteration
132
+  }
133
+  if (state->height * state->width * state->channels > 1000) {
134
+    debug_app_bbm_printf("%hhu: BBM frame size too large", state->no);
135
+    return; // retry with next file in next iteration
136
+  }
137
+  uint32_t frameptr = ntohl(hdr.frameptr);
138
+  if (frameptr < sizeof(hdr)) {
139
+    debug_app_bbm_printf("%hhu: invalid framepointer in BBM", state->no);
140
+    return; // retry with next file in next iteration
141
+  }
142
+
143
+  // seek to start of first frame
144
+  DFS_Seek(&state->fi, frameptr, *state->sectorBuf);
145
+  if (state->fi.pointer != frameptr) {
146
+    debug_app_bbm_printf("%hhu: seek to first frame failed", state->no);
147
+    return; // retry with next file in next iteration
148
+  }
149
+
150
+  // a file has been found and opened, header is parsed
151
+  debug_app_bbm_printf("%hhu: header parsed: %hux%hu-%hu/%hu", state->no,
152
+                       state->width, state->height, state->channels,
153
+                       state->maxval + 1);
154
+}
155
+
156
+/**
157
+ * @brief open next file from playlist directory
158
+ * @param[in,out] state internal state of application
159
+ */
160
+static void AppBbmNextFile(AppBbmState *state)
161
+{
162
+  // get name of next file to open
163
+  char filename[22];
164
+  if (AppBbmNextName(state, filename, sizeof(filename)) != 0)
165
+    return;
166
+
167
+  // open file
168
+  if (DFS_OpenFile(state->vi, (uint8_t *)filename, DFS_READ,
169
+                   *state->sectorBuf, &state->fi) != 0) {
170
+    debug_app_bbm_printf("%hhu: cannot open file %s", state->no, filename);
171
+    return; // retry with next file in next iteration
172
+  }
173
+  debug_app_bbm_printf("%hhu: file %s", state->no, filename);
174
+
175
+  // parse header
176
+  AppBbmParseHeader(state);
177
+}
178
+
179
+/**
180
+ * @brief initialize BBM play application
181
+ * @param[in,out] state internal state of application
182
+ *
183
+ * state.sectorBuf, state.vi, state.no have to be initialized before calling
184
+ */
185
+void AppBbmInit(AppBbmState *state) // (extern)
186
+{
187
+  // default: not initialized
188
+  state->isInit = 0;
189
+
190
+  // get destination address for MCUF frames
191
+  char filename[12];
192
+  sprintf(filename, "bbm%hhu/addr", state->no);
193
+  if (AppsToolsReadIp(*state->sectorBuf, state->vi,
194
+                      filename, state->addr) == 0) {
195
+    state->haveAddr = 1;
196
+    debug_app_bbm_printf("%hhu: address %hhu.%hhu.%hhu.%hhu", state->no,
197
+                         state->addr[0], state->addr[1],
198
+                         state->addr[2], state->addr[3]);
199
+  } else {
200
+    state->haveAddr = 0;
201
+    debug_app_bbm_printf("%hhu: no address", state->no);
202
+  }
203
+
204
+  // initialize internal state
205
+  state->idxFile = 0;
206
+  state->haveFile = 0;
207
+
208
+  // initialized, start with first action now
209
+  state->isInit = 1;
210
+  TimingGetMs(&state->nextActMs);
211
+}
212
+
213
+/**
214
+ * @brief run BBM play application
215
+ * @param[in,out] state internal state of application
216
+ */
217
+void AppBbmRun(AppBbmState *state) // (extern)
218
+{
219
+  // not initialized -> leave
220
+  if (!state->isInit)
221
+    return;
222
+
223
+  // time for next action not yet reached -> leave
224
+  unsigned long ms;
225
+  TimingGetMs(&ms);
226
+  if ((long)(state->nextActMs - ms) > 0)
227
+    return;
228
+
229
+  // no file -> open next one
230
+  if (!state->haveFile) {
231
+    AppBbmNextFile(state);
232
+    return; // do not work too much in one step / app might be deactivated now
233
+  }
234
+
235
+  // TODO
236
+}
237
+
... ...
@@ -0,0 +1,46 @@
1
+/* flaneth - flash and ethernet
2
+   Copyright (C) 2007-2012 Stefan Schuermans <stefan@schuermans.info>
3
+   Copyleft: GNU public license V2 - http://www.gnu.org/copyleft/gpl.html
4
+   a BlinkenArea project - http://www.blinkenarea.org/ */
5
+
6
+#ifndef INC_app_bbm
7
+#define INC_app_bbm
8
+
9
+#include "dosfs.h"
10
+
11
+/// internal state of BBM play application
12
+typedef struct app_bbm_state {
13
+  // initialize before calling init
14
+  uint8_t (*sectorBuf)[SECTOR_SIZE]; ///< scratch buffer to store a sector
15
+  VOLINFO *vi;                       ///< volume information structure
16
+  uint8_t no;                        ///< number of BBM play application
17
+  // internal stuff
18
+  char          isInit;    ///< if successfully initialized
19
+  unsigned long nextActMs; ///< when to do next action
20
+  char          haveAddr;  ///< if destination address for MCUF is known
21
+  unsigned char addr[4];   ///< destination address for MCUF packets
22
+  unsigned int  idxFile;   ///< index of file to open next
23
+  char          haveFile;  ///< if a file is open
24
+  FILEINFO      fi;        ///< information about open file
25
+  uint16_t      height;    ///< height of current movie
26
+  uint16_t      width;     ///< width of current movie
27
+  uint16_t      channels;  ///< channels in current movie
28
+  uint16_t      maxval;    ///< maxval of current movie
29
+} AppBbmState;
30
+
31
+/**
32
+ * @brief initialize BBM play application
33
+ * @param[in,out] state internal state of application
34
+ *
35
+ * state.sectorBuf, state.vi, state.no have to be initialized before calling
36
+ */
37
+extern void AppBbmInit(AppBbmState *state);
38
+
39
+/**
40
+ * @brief run BBM play application
41
+ * @param[in,out] state internal state of application
42
+ */
43
+extern void AppBbmRun(AppBbmState *state);
44
+
45
+#endif // #ifndef INC_app_bbm
46
+
... ...
@@ -3,112 +3,13 @@
3 3
    Copyleft: GNU public license V2 - http://www.gnu.org/copyleft/gpl.html
4 4
    a BlinkenArea project - http://www.blinkenarea.org/ */
5 5
 
6
-#include <stdio.h>
7
-#include <string.h>
8
-
6
+#include "apps_tools.h"
9 7
 #include "app_cfg.h"
10 8
 #include "config.h"
11 9
 #include "debug.h"
12 10
 #include "dosfs.h"
13 11
 #include "rtl8019.h"
14 12
 
15
-/**
16
- * @brief read string from file
17
- * @param[in] sectorBuf scratch buffer to store a sector
18
- * @param[in] vi volume information structure
19
- * @param[in] filename name of file to read
20
- * @param[out] buf buffer to put string to
21
- * @param[in] sz size of buffer
22
- * @return 0 on success, -1 on error
23
- */
24
-static char AppCfgReadStr(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
25
-                          const char *filename, char *buf, unsigned int sz)
26
-{
27
-  FILEINFO fi;
28
-  uint32_t len;
29
-
30
-  // open file
31
-  if (DFS_OpenFile(vi, (uint8_t *)filename, DFS_READ, sectorBuf, &fi) != 0) {
32
-    debug_app_cfg_printf("cannot open file %s", filename);
33
-    return -1;
34
-  }
35
-
36
-  // read string from file
37
-  len = 0;
38
-  DFS_ReadFile(&fi, sectorBuf, (uint8_t *)buf, &len, sz - 1);
39
-  if (len > sz - 1)
40
-    len = sz - 1;
41
-  buf[len] = 0; // terminate string
42
-  debug_apps_printf("string read from file %s: %s", filename, buf);
43
-  return 0;
44
-}
45
-
46
-/**
47
- * @brief read MAC address from file
48
- * @param[in] sectorBuf scratch buffer to store a sector
49
- * @param[in] vi volume information structure
50
- * @param[in] filename name of file to read
51
- * @param[out] mac MAC address read
52
- * @return 0 on success, -1 on error
53
- */
54
-static char AppCfgReadMac(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
55
-                          const char *filename, unsigned char mac[6])
56
-{
57
-  char bufStr[18];
58
-  unsigned char bufMac[6];
59
-
60
-  // get string from file
61
-  if (AppCfgReadStr(sectorBuf, vi, filename, bufStr, sizeof(bufStr)) != 0)
62
-    return -1;
63
-
64
-  // parse string
65
-  if (sscanf(bufStr, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
66
-             &bufMac[0], &bufMac[1], &bufMac[2],
67
-             &bufMac[3], &bufMac[4], &bufMac[5]) != 6) {
68
-    debug_apps_printf("MAC parse error");
69
-    return -1;
70
-  }
71
-
72
-  // copy MAC to output
73
-  debug_apps_printf("MAC read: %02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX",
74
-                    bufMac[0], bufMac[1], bufMac[2],
75
-                    bufMac[3], bufMac[4], bufMac[5]);
76
-  memcpy(mac, bufMac, 6);
77
-  return 0;
78
-}
79
-
80
-/**
81
- * @brief read IP address from file
82
- * @param[in] sectorBuf scratch buffer to store a sector
83
- * @param[in] vi volume information structure
84
- * @param[in] filename name of file to read
85
- * @param[out] ip IP address read
86
- * @return 0 on success, -1 on error
87
- */
88
-static char AppCfgReadIp(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
89
-                         const char *filename, unsigned char ip[4])
90
-{
91
-  char bufStr[16];
92
-  unsigned char bufIp[4];
93
-
94
-  // get string from file
95
-  if (AppCfgReadStr(sectorBuf, vi, filename, bufStr, sizeof(bufStr)) != 0)
96
-    return -1;
97
-
98
-  // parse string
99
-  if (sscanf(bufStr, "%hhu.%hhu.%hhu.%hhu",
100
-             &bufIp[0], &bufIp[1], &bufIp[2], &bufIp[3]) != 4) {
101
-    debug_apps_printf("IP parse error");
102
-    return -1;
103
-  }
104
-
105
-  // copy IP to output
106
-  debug_apps_printf("IP read: %hhu.%hhu.%hhu.%hhu",
107
-                    bufIp[0], bufIp[1], bufIp[2], bufIp[3]);
108
-  memcpy(ip, bufIp, 4);
109
-  return 0;
110
-}
111
-
112 13
 /**
113 14
  * @brief update configuration
114 15
  * @param[in] sectorBuf scratch buffer to store a sector
... ...
@@ -117,10 +18,11 @@ static char AppCfgReadIp(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
117 18
 void AppCfgRun(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi) // (extern)
118 19
 {
119 20
   // load config
120
-  if (AppCfgReadMac(sectorBuf, vi, "cfg/mac", ConfigMac) == 0)
21
+  debug_app_cfg_printf("reading config");
22
+  if (AppsToolsReadMac(sectorBuf, vi, "cfg/mac", ConfigMac) == 0)
121 23
     RtlInit();
122
-  AppCfgReadIp(sectorBuf, vi, "cfg/ip", ConfigIp);
123
-  AppCfgReadIp(sectorBuf, vi, "cfg/mask", ConfigMask);
124
-  AppCfgReadIp(sectorBuf, vi, "cfg/gw", ConfigGw);
24
+  AppsToolsReadIp(sectorBuf, vi, "cfg/ip", ConfigIp);
25
+  AppsToolsReadIp(sectorBuf, vi, "cfg/mask", ConfigMask);
26
+  AppsToolsReadIp(sectorBuf, vi, "cfg/gw", ConfigGw);
125 27
 }
126 28
 
... ...
@@ -5,10 +5,13 @@
5 5
 
6 6
 #include <string.h>
7 7
 
8
+#include "app_bbm.h"
8 9
 #include "app_cfg.h"
9 10
 #include "apps.h"
11
+#include "cf.h"
10 12
 #include "debug.h"
11 13
 #include "dosfs.h"
14
+#include "tasks.h"
12 15
 
13 16
 /**
14 17
  * @brief list directory and dump file
... ...
@@ -26,13 +29,15 @@ static void AppsListDump(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi)
26 29
 
27 30
   // list files in root directory
28 31
   di.scratch = sectorBuf;
29
-  if (DFS_OpenDir(vi, (uint8_t *)"", &di) != 0) {
32
+  if (DFS_OpenDir(vi, (uint8_t *)"", &di) != DFS_OK) {
30 33
     debug_apps_printf("cannot open root directory");
31 34
     return;
32 35
   }
33 36
   debug_apps_printf("files in root directory:");
34
-  while (DFS_GetNext(vi, &di, &de) == 0) {
35
-    if (de.attr == ATTR_LONG_NAME) {
37
+  while (DFS_GetNext(vi, &di, &de) == DFS_OK) {
38
+    if (de.name[0] == 0) {
39
+      // ignore deleted files
40
+    } else if (de.attr == ATTR_LONG_NAME) {
36 41
       // ignore long names
37 42
     } else if (de.attr & ATTR_VOLUME_ID) {
38 43
       debug_apps_printf("volume ID: %-11.11s", de.name);
... ...
@@ -46,13 +51,13 @@ static void AppsListDump(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi)
46 51
   }
47 52
 
48 53
   // dump last file
49
-  if (DFS_OpenFile(vi, filename, DFS_READ, sectorBuf, &fi) != 0) {
54
+  if (DFS_OpenFile(vi, filename, DFS_READ, sectorBuf, &fi) != DFS_OK) {
50 55
     debug_apps_printf("cannot open file %s", filename);
51 56
     return;
52 57
   }
53 58
   debug_apps_printf("dumping file %s (max. %u bytes):", filename, sizeof(buf));
59
+  if (DFS_ReadFile(&fi, sectorBuf, buf, &len, sizeof(buf)) != DFS_OK)
54 60
     len = 0;
55
-  DFS_ReadFile(&fi, sectorBuf, buf, &len, sizeof(buf));
56 61
   for (i = 0; i < len; ++i)
57 62
     debug_apps_printf("%3lu: %02hX", i, buf[i]);
58 63
   debug_apps_printf("done", filename);
... ...
@@ -76,7 +81,7 @@ void AppsRun(void) // (extern)
76 81
   debug_apps_printf("partition: start %lu size %lu", partStart, partSize);
77 82
 
78 83
   // get volume info
79
-  if (DFS_GetVolInfo(0, sectorBuf, partStart, &vi) != 0) {
84
+  if (DFS_GetVolInfo(0, sectorBuf, partStart, &vi) != DFS_OK) {
80 85
     debug_apps_printf("cannot get volume info");
81 86
     return;
82 87
   }
... ...
@@ -104,5 +109,15 @@ void AppsRun(void) // (extern)
104 109
 
105 110
   // run one-short applications
106 111
   AppCfgRun(sectorBuf, &vi);
112
+
113
+  // initialize applications
114
+  AppBbmState bbm0 = { .sectorBuf = &sectorBuf, .vi = &vi, .no = 0 };
115
+  AppBbmInit(&bbm0);
116
+
117
+  // run applications
118
+  while (CfIsPresent()) {
119
+    AppBbmRun(&bbm0);
120
+    Tasks();
121
+  }
107 122
 }
108 123
 
... ...
@@ -0,0 +1,110 @@
1
+/* flaneth - flash and ethernet
2
+   Copyright (C) 2007-2012 Stefan Schuermans <stefan@schuermans.info>
3
+   Copyleft: GNU public license V2 - http://www.gnu.org/copyleft/gpl.html
4
+   a BlinkenArea project - http://www.blinkenarea.org/ */
5
+
6
+#include <stdio.h>
7
+#include <string.h>
8
+
9
+#include "apps_tools.h"
10
+#include "debug.h"
11
+#include "dosfs.h"
12
+
13
+/**
14
+ * @brief read string from file
15
+ * @param[in] sectorBuf scratch buffer to store a sector
16
+ * @param[in] vi volume information structure
17
+ * @param[in] filename name of file to read
18
+ * @param[out] buf buffer to put string to
19
+ * @param[in] sz size of buffer
20
+ * @return 0 on success, -1 on error
21
+ */
22
+char AppsToolsReadStr(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
23
+                      const char *filename, char *buf, unsigned int sz) // (extern)
24
+{
25
+  FILEINFO fi;
26
+  uint32_t len;
27
+
28
+  // open file
29
+  if (DFS_OpenFile(vi, (uint8_t *)filename, DFS_READ,
30
+                   sectorBuf, &fi) != DFS_OK) {
31
+    debug_app_cfg_printf("cannot open file %s", filename);
32
+    return -1;
33
+  }
34
+
35
+  // read string from file
36
+  if (DFS_ReadFile(&fi, sectorBuf, (uint8_t *)buf, &len, sz - 1) != DFS_OK)
37
+    len = 0;
38
+  if (len > sz - 1)
39
+    len = sz - 1;
40
+  buf[len] = 0; // terminate string
41
+  debug_apps_tools_printf("string read from file %s: %s", filename, buf);
42
+  return 0;
43
+}
44
+
45
+/**
46
+ * @brief read MAC address from file
47
+ * @param[in] sectorBuf scratch buffer to store a sector
48
+ * @param[in] vi volume information structure
49
+ * @param[in] filename name of file to read
50
+ * @param[out] mac MAC address read
51
+ * @return 0 on success, -1 on error
52
+ */
53
+char AppsToolsReadMac(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
54
+                      const char *filename, unsigned char mac[6]) // (extern)
55
+{
56
+  char bufStr[18];
57
+  unsigned char bufMac[6];
58
+
59
+  // get string from file
60
+  if (AppsToolsReadStr(sectorBuf, vi, filename, bufStr, sizeof(bufStr)) != 0)
61
+    return -1;
62
+
63
+  // parse string
64
+  if (sscanf(bufStr, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
65
+             &bufMac[0], &bufMac[1], &bufMac[2],
66
+             &bufMac[3], &bufMac[4], &bufMac[5]) != 6) {
67
+    debug_apps_tools_printf("MAC parse error");
68
+    return -1;
69
+  }
70
+
71
+  // copy MAC to output
72
+  debug_apps_tools_printf("MAC read: %02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX",
73
+                          bufMac[0], bufMac[1], bufMac[2],
74
+                          bufMac[3], bufMac[4], bufMac[5]);
75
+  memcpy(mac, bufMac, 6);
76
+  return 0;
77
+}
78
+
79
+/**
80
+ * @brief read IP address from file
81
+ * @param[in] sectorBuf scratch buffer to store a sector
82
+ * @param[in] vi volume information structure
83
+ * @param[in] filename name of file to read
84
+ * @param[out] ip IP address read
85
+ * @return 0 on success, -1 on error
86
+ */
87
+char AppsToolsReadIp(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
88
+                     const char *filename, unsigned char ip[4]) // (extern)
89
+{
90
+  char bufStr[16];
91
+  unsigned char bufIp[4];
92
+
93
+  // get string from file
94
+  if (AppsToolsReadStr(sectorBuf, vi, filename, bufStr, sizeof(bufStr)) != 0)
95
+    return -1;
96
+
97
+  // parse string
98
+  if (sscanf(bufStr, "%hhu.%hhu.%hhu.%hhu",
99
+             &bufIp[0], &bufIp[1], &bufIp[2], &bufIp[3]) != 4) {
100
+    debug_apps_tools_printf("IP parse error");
101
+    return -1;
102
+  }
103
+
104
+  // copy IP to output
105
+  debug_apps_tools_printf("IP read: %hhu.%hhu.%hhu.%hhu",
106
+                          bufIp[0], bufIp[1], bufIp[2], bufIp[3]);
107
+  memcpy(ip, bufIp, 4);
108
+  return 0;
109
+}
110
+
... ...
@@ -0,0 +1,46 @@
1
+/* flaneth - flash and ethernet
2
+   Copyright (C) 2007-2012 Stefan Schuermans <stefan@schuermans.info>
3
+   Copyleft: GNU public license V2 - http://www.gnu.org/copyleft/gpl.html
4
+   a BlinkenArea project - http://www.blinkenarea.org/ */
5
+
6
+#ifndef INC_apps_tools
7
+#define INC_spps_tools
8
+
9
+#include "dosfs.h"
10
+
11
+/**
12
+ * @brief read string from file
13
+ * @param[in] sectorBuf scratch buffer to store a sector
14
+ * @param[in] vi volume information structure
15
+ * @param[in] filename name of file to read
16
+ * @param[out] buf buffer to put string to
17
+ * @param[in] sz size of buffer
18
+ * @return 0 on success, -1 on error
19
+ */
20
+extern char AppsToolsReadStr(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
21
+                             const char *filename, char *buf, unsigned int sz);
22
+
23
+/**
24
+ * @brief read MAC address from file
25
+ * @param[in] sectorBuf scratch buffer to store a sector
26
+ * @param[in] vi volume information structure
27
+ * @param[in] filename name of file to read
28
+ * @param[out] mac MAC address read
29
+ * @return 0 on success, -1 on error
30
+ */
31
+extern char AppsToolsReadMac(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
32
+                             const char *filename, unsigned char mac[6]);
33
+
34
+/**
35
+ * @brief read IP address from file
36
+ * @param[in] sectorBuf scratch buffer to store a sector
37
+ * @param[in] vi volume information structure
38
+ * @param[in] filename name of file to read
39
+ * @param[out] ip IP address read
40
+ * @return 0 on success, -1 on error
41
+ */
42
+extern char AppsToolsReadIp(uint8_t sectorBuf[SECTOR_SIZE], VOLINFO *vi,
43
+                            const char *filename, unsigned char ip[4]);
44
+
45
+#endif // #ifndef INC_apps_tools
46
+
... ...
@@ -23,6 +23,8 @@
23 23
 #define DEBUG_TCP 1
24 24
 #define DEBUG_HTTP 1
25 25
 #define DEBUG_APPS 1
26
+#define DEBUG_APPS_TOOLS 1
27
+#define DEBUG_APP_BBM 1
26 28
 #define DEBUG_APP_CFG 1
27 29
 
28 30
 // debug version of printf
... ...
@@ -54,6 +56,8 @@
54 56
 #define debug_tcp_printf(fmt, arg...) debug_specialized_printf(DEBUG_TCP, "tcp: "fmt, ##arg)
55 57
 #define debug_http_printf(fmt, arg...) debug_specialized_printf(DEBUG_HTTP, "http: "fmt, ##arg)
56 58
 #define debug_apps_printf(fmt, arg...) debug_specialized_printf(DEBUG_APPS, "apps: "fmt, ##arg)
59
+#define debug_apps_tools_printf(fmt, arg...) debug_specialized_printf(DEBUG_APPS_TOOLS, "apps_tools: "fmt, ##arg)
60
+#define debug_app_bbm_printf(fmt, arg...) debug_specialized_printf(DEBUG_APP_BBM, "app_bbm: "fmt, ##arg)
57 61
 #define debug_app_cfg_printf(fmt, arg...) debug_specialized_printf(DEBUG_APP_CFG, "app_cfg: "fmt, ##arg)
58 62
 
59 63
 #endif // #ifndef INC_debug
60 64