LPCOpen Platform
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 "fs.h"
38 #include "dosfs.h"
39 #include "lpc43xx_dualcore_config.h"
40 
41 #include "httpd_structs.h"
42 
50 /*****************************************************************************
51  * Private types/enumerations/variables
52  ****************************************************************************/
53 
54 /* Default html file */
55 const static char http_index_html[] =
56  "<html><head><title>Congrats!</title></head>"
57  "<body><h1>Welcome to our lwIP HTTP server!</h1>"
58  "<p>This is a small test page, served by httpd of "
59  "lwip.</p></body></html>";
60 
61 /* Internal File descriptor structure */
62 struct file_ds {
64  uint8_t scratch[SECTOR_SIZE];
66  struct fs_file fs;
67 
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  OS_ERR os_err;
132  OSMutexCreate(&open_lock, "DOS_FS_Mutex", &os_err);
133  if (os_err == OS_ERR_NONE) {
134  return 0;
135  }
136  else {
137  return 1;
138  }
139 }
140 
141 #else
142 static int open_lock;
143 /* Mutex lock function for standalone */
144 static int mutex_lock(int *mx)
145 {
146  return 0;
147 }
148 
149 /* Mutex init for standalone */
150 static int mutex_init(void)
151 {
152  open_lock = 1;
153  return 0;
154 }
155 
156 /* Mutex lock for standalone */
157 static void mutex_unlock(int *mx)
158 {}
159 
160 #endif
161 
166 static int
167 get_http_headers(const char *fName, char *buff)
168 {
169  unsigned int iLoop;
170  const char *pszExt = NULL;
171  const char *hdrs[4];
172 
173  /* Ensure that we initialize the loop counter. */
174  iLoop = 0;
175 
176  /* In all cases, the second header we send is the server identification
177  so set it here. */
178  hdrs[1] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER];
179 
180  /* Is this a normal file or the special case we use to send back the
181  default "404: Page not found" response? */
182  if (( fName == NULL) || ( *fName == 0) ) {
183  hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
184  hdrs[2] = g_psHTTPHeaderStrings[DEFAULT_404_HTML];
185  goto end_fn;
186  }
187  /* We are dealing with a particular filename. Look for one other
188  special case. We assume that any filename with "404" in it must be
189  indicative of a 404 server error whereas all other files require
190  the 200 OK header. */
191  if (strstr(fName, "404")) {
192  iLoop = HTTP_HDR_NOT_FOUND;
193  }
194  else if (strstr(fName, "400")) {
195  iLoop = HTTP_HDR_BAD_REQUEST;
196  }
197  else if (strstr(fName, "501")) {
198  iLoop = HTTP_HDR_NOT_IMPL;
199  }
200  else {
201  iLoop = HTTP_HDR_OK;
202  }
203  hdrs[0] = g_psHTTPHeaderStrings[iLoop];
204 
205  /* Get a pointer to the file extension. We find this by looking for the
206  last occurrence of "." in the filename passed. */
207  pszExt = strrchr(fName, '.');
208 
209  /* Does the FileName passed have any file extension? If not, we assume it
210  is a special-case URL used for control state notification and we do
211  not send any HTTP headers with the response. */
212  if (pszExt == NULL) {
213  return 0;
214  }
215 
216  pszExt++;
217  /* Now determine the content type and add the relevant header for that. */
218  for (iLoop = 0; (iLoop < NUM_HTTP_HEADERS); iLoop++)
219  /* Have we found a matching extension? */
220  if (!strcmp(g_psHTTPHeaders[iLoop].extension, pszExt)) {
221  hdrs[2] =
222  g_psHTTPHeaderStrings[g_psHTTPHeaders[iLoop].headerIndex];
223  break;
224  }
225 
226  /* Did we find a matching extension? */
227  if (iLoop == NUM_HTTP_HEADERS) {
228  /* No - use the default, plain text file type. */
229  hdrs[2] = g_psHTTPHeaderStrings[HTTP_HDR_DEFAULT_TYPE];
230  }
231 
232 end_fn:
233  iLoop = strlen(hdrs[0]);
234  strcpy(buff, hdrs[0]);
235  strcat(buff, hdrs[1]);
236  strcat(buff, hdrs[2]);
237  return strlen(buff);
238 }
239 
240 /*****************************************************************************
241  * Public functions
242  ****************************************************************************/
243 
252 int GetHTTP_Header(const char *fName, char *buff)
253 {
254  return get_http_headers(fName, buff);
255 }
256 
266 struct fs_file *fs_open_default(void) {
267  int hlen;
268 
269  struct file_ds *fds;
270 
271  struct fs_file *fs;
272 
273  fds = malloc(sizeof(*fds));
274  if (fds == NULL) {
275  DEBUGSTR("Malloc Failure, Out of Memory!\r\n");
276  return NULL;
277  }
278  memset(fds, 0, sizeof(*fds));
279  fs = &fds->fs;
280  fs->pextension = (void *) fds; /* Store this for later use */
281  hlen = get_http_headers("default.htm", (char *) fds->scratch);
282  fs->data = (const char *) fds->scratch;
283  memcpy((void *) &fs->data[hlen], (void *) http_index_html, sizeof(http_index_html) - 1);
284  fs->len = hlen + sizeof(http_index_html) - 1;
285  fs->index = fs->len;
286  fs->http_header_included = 1;
287  return fs;
288 }
289 
297 struct fs_file *fs_open(const char *name) {
298  int hlen;
299 
300  struct file_ds *fds;
301 
302  struct fs_file *fs;
303 
304  static struct file_ds tmpds;
305 
306  if (mutex_init()) {
307  LWIP_DEBUGF(HTTPD_DEBUG, ("DFS: ERROR: Mutex Init!\r\n"));
308  return NULL;
309  }
310 
311  if (mutex_lock(&open_lock)) {
312  LWIP_DEBUGF(HTTPD_DEBUG, ("DFS: ERROR: Mutex Timeout!\r\n"));
313  return NULL;
314  }
315  memset(&tmpds, 0, sizeof(tmpds));
316  fds = &tmpds;
317 
318  if (DFS_GetVolInfo(0, fds->scratch, 0, &fds->vi)) {
319  LWIP_DEBUGF(HTTPD_DEBUG, ("DFS: VOLUME: Read Error!\r\n"));
320  mutex_unlock(&open_lock);
321  return NULL;
322  }
323 
324  if (DFS_OpenFile(&fds->vi, (uint8_t *) name, DFS_READ, fds->scratch, &fds->fi) != DFS_OK) {
325  LWIP_DEBUGF(HTTPD_DEBUG, ("DFS: OPEN: File %s does not exist\r\n", name));
326  mutex_unlock(&open_lock);
327  return NULL;
328  }
329 
330  fds = malloc(sizeof(*fds));
331  if (fds == NULL) {
332  DEBUGSTR("Malloc Failure, Out of Memory!\r\n");
333  mutex_unlock(&open_lock);
334  return NULL;
335  }
336  memcpy(fds, &tmpds, sizeof(*fds));
337  mutex_unlock(&open_lock);
338 
339  fs = &fds->fs;
340  fs->pextension = (void *) fds; /* Store this for later use */
341  hlen = get_http_headers(name, (char *) fds->scratch);
342  fs->data = (const char *) fds->scratch;
343  fs->index = hlen;
344  fs->len = fds->fi.filelen + hlen;
345  fs->http_header_included = 1;
346  return fs;
347 }
348 
355 void fs_close(struct fs_file *file)
356 {
357  if(!file)
358  return;
359  free(file->pextension);
360 }
361 
370 int fs_read(struct fs_file *file, char *buffer, int count)
371 {
372  uint32_t i;
373  struct file_ds *fds = (struct file_ds *) file->pextension;
374  DFS_ReadFile(&fds->fi, fds->scratch, (uint8_t *) buffer, &i, count);
375  file->index += i;
376  return i;
377 }
378 
385 int fs_bytes_left(struct fs_file *file)
386 {
387  return file->len - file->index;
388 }
389 
390 #ifdef LWIP_DEBUG
391 
399 void assert_printf(char *msg, int line, char *file)
400 {
401  DEBUGOUT("ASSERT: %s at %s:%d\r\n", msg, file, line);
402 }
403 
409 const char *lwip_strerr(err_t eno)
410 {
411  return "";
412 }
413 
414 #endif
415 
426 uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count)
427 {
428  memcpy(buffer, (void *) (FAT12_DISK_IMAGE + (sector * SECTOR_SIZE)), count * SECTOR_SIZE);
429  return 0;
430 }
431 
432 /*
433  * @brief Function to write data to filesystem buffer
434  * @param unit : Unit number of the filesystem
435  * @param buffer : Pointer to data which has to be written to filesystem
436  * @param sector : Starting sector to which the \a buffer data to be written
437  * @param count : Number of sections to be written
438  * @return 0 on success, non zero on failure
439  * This function is called by DOS Filesystem library to write sectors
440  * to the filesystem.
441  */
442 uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count)
443 {
444  memcpy((void *) (FAT12_DISK_IMAGE + (sector * SECTOR_SIZE)), buffer, count * SECTOR_SIZE);
445  return 0;
446 }
447