LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lwip_fs.c
Go to the documentation of this file.
1 /*
2  * @brief lwIP Filesystem implementation module
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 
36 #include "board.h"
37 #include "ff.h"
38 #include "fs_mem.h"
39 #include "lwip_fs.h"
40 #include "lpc43xx_dualcore_config.h"
41 
42 #include "httpd_structs.h"
43 
49 /*****************************************************************************
50  * Private types/enumerations/variables
51  ****************************************************************************/
52 
53 /* Default html file */
54 const static char http_index_html[] =
55  "<html><head><title>Congrats!</title></head>"
56  "<body><h1>Welcome to our lwIP HTTP server!</h1>"
57  "<p>This is a small test page, served by httpd of "
58  "lwip.</p></body></html>";
59 
60 static FATFS Fatfs; /* File system object */
61 
62 /* Internal File descriptor structure */
63 struct file_ds {
64  uint8_t scratch[SECTOR_SZ];
66  struct fs_file fs;
67  int fi_valid;
68 };
69 
70 /*****************************************************************************
71  * Private functions
72  ****************************************************************************/
73 
74 #ifdef OS_FREE_RTOS
75 #include "FreeRTOS.h"
76 #include "semphr.h"
77 static xSemaphoreHandle open_lock;
78 /* FreeRTOS mutex lock */
79 static int mutex_lock(xSemaphoreHandle *mx)
80 {
81  if (xSemaphoreTake(*mx, 500) != pdTRUE) {
82  return 1;
83  }
84  return 0;
85 }
86 
87 /* FreeRTOS mutex unlock */
88 static void mutex_unlock(xSemaphoreHandle *mx)
89 {
90  xSemaphoreGive(*mx);
91 }
92 
93 /* FreeRTOS mutex init */
94 static int mutex_init(void)
95 {
96  open_lock = xSemaphoreCreateMutex();
97  return open_lock == NULL;
98 }
99 
100 #elif defined(OS_UCOS_III)
101 
102 #include "os.h"
103 #include "cpu.h"
104 #include "os_cfg_app.h"
105 
106 static OS_MUTEX *open_lock;
107 
108 /* mutex lock function for ucos-iii */
109 static int mutex_lock(OS_MUTEX **mx)
110 {
111  CPU_TS ts;
112  OS_ERR os_err;
113  OSMutexPend(*mx, 500, OS_OPT_PEND_BLOCKING, &ts, &os_err);
114  if (os_err != OS_ERR_NONE) {
115  return 1;
116  }
117 
118  return 0;
119 }
120 
121 /* Mutex unlock function for ucos-iii */
122 static void mutex_unlock(OS_MUTEX **mx)
123 {
124  OS_ERR os_err;
125  OSMutexPost(*mx, OS_OPT_POST_NONE, &os_err);
126 }
127 
128 /* Mutex init function for ucos-iii */
129 static int mutex_init(void)
130 {
131  static OS_MUTEX fsmutex;
132  OS_ERR os_err;
133  OSMutexCreate(&fsmutex, "DOS_FS_Mutex", &os_err);
134  if (os_err == OS_ERR_NONE) {
135  open_lock = &fsmutex;
136  return 0;
137  }
138  else {
139  return 1;
140  }
141 }
142 
143 #else
144 static int open_lock;
145 /* Mutex lock function for standalone */
146 static int mutex_lock(int *mx)
147 {
148  return 0;
149 }
150 
151 /* Mutex init for standalone */
152 static int mutex_init(void)
153 {
154  open_lock = 1;
155  return 0;
156 }
157 
158 /* Mutex lock for standalone */
159 static void mutex_unlock(int *mx)
160 {}
161 
162 #endif
163 
168 static int
169 get_http_headers(const char *fName, char *buff)
170 {
171  unsigned int iLoop;
172  const char *pszExt = NULL;
173  const char *hdrs[4];
174 
175  /* Ensure that we initialize the loop counter. */
176  iLoop = 0;
177 
178  /* In all cases, the second header we send is the server identification
179  so set it here. */
180  hdrs[1] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER];
181 
182  /* Is this a normal file or the special case we use to send back the
183  default "404: Page not found" response? */
184  if (( fName == NULL) || ( *fName == 0) ) {
185  hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
186  hdrs[2] = g_psHTTPHeaderStrings[DEFAULT_404_HTML];
187  goto end_fn;
188  }
189  /* We are dealing with a particular filename. Look for one other
190  special case. We assume that any filename with "404" in it must be
191  indicative of a 404 server error whereas all other files require
192  the 200 OK header. */
193  if (strstr(fName, "404")) {
194  iLoop = HTTP_HDR_NOT_FOUND;
195  }
196  else if (strstr(fName, "400")) {
197  iLoop = HTTP_HDR_BAD_REQUEST;
198  }
199  else if (strstr(fName, "501")) {
200  iLoop = HTTP_HDR_NOT_IMPL;
201  }
202  else {
203  iLoop = HTTP_HDR_OK;
204  }
205  hdrs[0] = g_psHTTPHeaderStrings[iLoop];
206 
207  /* Get a pointer to the file extension. We find this by looking for the
208  last occurrence of "." in the filename passed. */
209  pszExt = strrchr(fName, '.');
210 
211  /* Does the FileName passed have any file extension? If not, we assume it
212  is a special-case URL used for control state notification and we do
213  not send any HTTP headers with the response. */
214  if (pszExt == NULL) {
215  return 0;
216  }
217 
218  pszExt++;
219  /* Now determine the content type and add the relevant header for that. */
220  for (iLoop = 0; (iLoop < NUM_HTTP_HEADERS); iLoop++)
221  /* Have we found a matching extension? */
222  if (!strcmp(g_psHTTPHeaders[iLoop].extension, pszExt)) {
223  hdrs[2] =
224  g_psHTTPHeaderStrings[g_psHTTPHeaders[iLoop].headerIndex];
225  break;
226  }
227 
228  /* Did we find a matching extension? */
229  if (iLoop == NUM_HTTP_HEADERS) {
230  /* No - use the default, plain text file type. */
231  hdrs[2] = g_psHTTPHeaderStrings[HTTP_HDR_DEFAULT_TYPE];
232  }
233 
234 end_fn:
235  iLoop = strlen(hdrs[0]);
236  strcpy(buff, hdrs[0]);
237  strcat(buff, hdrs[1]);
238  strcat(buff, hdrs[2]);
239  return strlen(buff);
240 }
241 
242 /*****************************************************************************
243  * Public functions
244  ****************************************************************************/
245 
246 /* Read http header information into a string */
247 int GetHTTP_Header(const char *fName, char *buff)
248 {
249  return get_http_headers(fName, buff);
250 }
251 
252 /* Opens the default index html file */
253 struct fs_file *fs_open_default(void) {
254  int hlen;
255 
256  struct file_ds *fds;
257 
258  struct fs_file *fs;
259 
260  fds = malloc(sizeof(*fds));
261  if (fds == NULL) {
262  DEBUGSTR("Malloc Failure, Out of Memory!\r\n");
263  return NULL;
264  }
265  memset(fds, 0, sizeof(*fds));
266  fs = &fds->fs;
267  fs->pextension = (void *) fds; /* Store this for later use */
268  hlen = get_http_headers("default.htm", (char *) fds->scratch);
269  fs->data = (const char *) fds->scratch;
270  memcpy((void *) &fs->data[hlen], (void *) http_index_html, sizeof(http_index_html) - 1);
271  fs->len = hlen + sizeof(http_index_html) - 1;
272  fs->index = fs->len;
273  fs->http_header_included = 1;
274  return fs;
275 }
276 
277 /* File open function */
278 struct fs_file *fs_open(const char *name) {
279  FRESULT res;
280  int hlen;
281  struct file_ds *fds;
282  struct fs_file *fs;
283 
284  /* Too huge to keep in stack, must be protected with mutex */
285  static struct file_ds tmpds;
286 
287  if (!open_lock)
288  f_mount(0, &Fatfs); /* Never fails */
289 
290  /* Initialize the mutex if not done already */
291  if (!open_lock && mutex_init()) {
292  LWIP_DEBUGF(HTTPD_DEBUG, ("DFS: ERROR: Mutex Init!\r\n"));
293  return NULL;
294  }
295 
296  if (mutex_lock(&open_lock)) {
297  LWIP_DEBUGF(HTTPD_DEBUG, ("DFS: ERROR: Mutex Timeout!\r\n"));
298  return NULL;
299  }
300  memset(&tmpds, 0, sizeof(tmpds));
301  fds = &tmpds;
302 
303  res = f_open(&fds->fi, name, FA_READ);
304  if (res) {
305  LWIP_DEBUGF(HTTPD_DEBUG, ("DFS: OPEN: File %s does not exist\r\n", name));
306  mutex_unlock(&open_lock);
307  return NULL;
308  }
309 
310  fds = malloc(sizeof(*fds));
311  if (fds == NULL) {
312  DEBUGSTR("Malloc Failure, Out of Memory!\r\n");
313  mutex_unlock(&open_lock);
314  return NULL;
315  }
316  memcpy(fds, &tmpds, sizeof(*fds));
317  mutex_unlock(&open_lock);
318 
319  fs = &fds->fs;
320  fds->fi_valid = 1;
321  fs->pextension = (void *) fds; /* Store this for later use */
322  hlen = get_http_headers(name, (char *) fds->scratch);
323  fs->data = (const char *) fds->scratch;
324  fs->index = hlen;
325  fs->len = f_size(&fds->fi) + hlen;
326  fs->http_header_included = 1;
327  return fs;
328 }
329 
330 /* File close function */
331 void fs_close(struct fs_file *file)
332 {
333  struct file_ds *fds;
334 
335  if(file == NULL)
336  return;
337 
338  fds = (struct file_ds *) file->pextension;
339  if (fds->fi_valid)
340  f_close(&fds->fi);
341  free(fds);
342 }
343 
344 /* File read function */
345 int fs_read(struct fs_file *file, char *buffer, int count)
346 {
347  uint32_t i = 0;
348  struct file_ds *fds = (struct file_ds *) file->pextension;
349  if (f_read(&fds->fi, (uint8_t *) buffer, count, &i))
350  return 0; /* Error in reading file */
351  file->index += i;
352  return i;
353 }
354 
355 /* Number of bytes left in the file */
356 int fs_bytes_left(struct fs_file *file)
357 {
358  return file->len - file->index;
359 }
360 
361 /* Fat file system information function */
362 void FATFS_GetBufferInfo(uint8_t **buffer, uint32_t *size)
363 {
364  *buffer = (uint8_t *) RAMDISK_LOCATION;
365  *size = (uint32_t) RAMDISK_SIZE;
366 }
367 
368 #ifdef LWIP_DEBUG
369 /* Assert print function */
370 void assert_printf(char *msg, int line, char *file)
371 {
372  DEBUGOUT("ASSERT: %s at %s:%d\r\n", msg, file, line);
373 }
374 
375 /* LWIP str err function */
376 const char *lwip_strerr(err_t eno)
377 {
378  return "";
379 }
380 
381 #endif
382