uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fio.c
Go to the documentation of this file.
1 #include <BoardConsole.h>
2 #include <string.h>
3 #include <FreeRTOS.h>
4 #include <semphr.h>
5 #include <unistd.h>
6 #ifdef USE_NEWLIB
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #endif
11 #include "fio.h"
12 #include "filesystem.h"
13 #include "osdebug.h"
14 #include "hash-djb2.h"
15 
16 static struct fddef_t fio_fds[MAX_FDS];
17 
18 static ssize_t stdin_read(void * opaque, void * buf, size_t count) {
19  return 0;
20 }
21 
22 static ssize_t stdout_write(void * opaque, const void * buf, size_t count) {
23  int i;
24  const char * data = (const char *) buf;
25 
26  for (i = 0; i < count; i++)
27  BoardConsolePutc(data[i]);
28 
29  return count;
30 }
31 
32 static xSemaphoreHandle fio_sem = NULL;
33 
34 __attribute__((constructor)) static void fio_init() {
35  memset(fio_fds, 0, sizeof(fio_fds));
36  fio_fds[0].fdread = stdin_read;
37  fio_fds[1].fdwrite = stdout_write;
38  fio_fds[2].fdwrite = stdout_write;
39  fio_sem = xSemaphoreCreateMutex();
40 }
41 
42 struct fddef_t * fio_getfd(int fd) {
43  if ((fd < 0) || (fd >= MAX_FDS))
44  return NULL;
45  return fio_fds + fd;
46 }
47 
48 static int fio_is_open_int(int fd) {
49  if ((fd < 0) || (fd >= MAX_FDS))
50  return 0;
51  int r = !((fio_fds[fd].fdread == NULL) &&
52  (fio_fds[fd].fdwrite == NULL) &&
53  (fio_fds[fd].fdseek == NULL) &&
54  (fio_fds[fd].fdclose == NULL) &&
55  (fio_fds[fd].opaque == NULL));
56  return r;
57 }
58 
59 static int fio_findfd() {
60  int i;
61 
62  for (i = 0; i < MAX_FDS; i++) {
63  if (!fio_is_open_int(i))
64  return i;
65  }
66 
67  return -1;
68 }
69 
70 int fio_is_open(int fd) {
71  int r = 0;
72  xSemaphoreTake(fio_sem, portMAX_DELAY);
73  r = fio_is_open_int(fd);
74  xSemaphoreGive(fio_sem);
75  return r;
76 }
77 
79  int fd;
80 // DBGOUT("fio_open(%p, %p, %p, %p, %p)\r\n", fdread, fdwrite, fdseek, fdclose, opaque);
81  xSemaphoreTake(fio_sem, portMAX_DELAY);
82  fd = fio_findfd();
83 
84  if (fd >= 0) {
85  fio_fds[fd].fdread = fdread;
86  fio_fds[fd].fdwrite = fdwrite;
87  fio_fds[fd].fdseek = fdseek;
88  fio_fds[fd].fdclose = fdclose;
89  fio_fds[fd].opaque = opaque;
90  }
91  xSemaphoreGive(fio_sem);
92 
93  return fd;
94 }
95 
96 ssize_t fio_read(int fd, void * buf, size_t count) {
97  ssize_t r = 0;
98 // DBGOUT("fio_read(%i, %p, %i)\r\n", fd, buf, count);
99  if (fio_is_open_int(fd)) {
100  if (fio_fds[fd].fdread) {
101  r = fio_fds[fd].fdread(fio_fds[fd].opaque, buf, count);
102  } else {
103  r = -3;
104  }
105  } else {
106  r = -2;
107  }
108  return r;
109 }
110 
111 ssize_t fio_write(int fd, const void * buf, size_t count) {
112  ssize_t r = 0;
113 // DBGOUT("fio_write(%i, %p, %i)\r\n", fd, buf, count);
114  if (fio_is_open_int(fd)) {
115  if (fio_fds[fd].fdwrite) {
116  r = fio_fds[fd].fdwrite(fio_fds[fd].opaque, buf, count);
117  } else {
118  r = -3;
119  }
120  } else {
121  r = -2;
122  }
123  return r;
124 }
125 
126 off_t fio_seek(int fd, off_t offset, int whence) {
127  off_t r = 0;
128 // DBGOUT("fio_seek(%i, %i, %i)\r\n", fd, offset, whence);
129  if (fio_is_open_int(fd)) {
130  if (fio_fds[fd].fdseek) {
131  r = fio_fds[fd].fdseek(fio_fds[fd].opaque, offset, whence);
132  } else {
133  r = -3;
134  }
135  } else {
136  r = -2;
137  }
138  return r;
139 }
140 
141 int fio_close(int fd) {
142  int r = 0;
143 // DBGOUT("fio_close(%i)\r\n", fd);
144  if (fio_is_open_int(fd)) {
145  if (fio_fds[fd].fdclose)
146  r = fio_fds[fd].fdclose(fio_fds[fd].opaque);
147  xSemaphoreTake(fio_sem, portMAX_DELAY);
148  memset(fio_fds + fd, 0, sizeof(struct fddef_t));
149  xSemaphoreGive(fio_sem);
150  } else {
151  r = -2;
152  }
153  return r;
154 }
155 
156 void fio_set_opaque(int fd, void * opaque) {
157  if (fio_is_open_int(fd))
158  fio_fds[fd].opaque = opaque;
159 }
160 
161 #define stdin_hash 0x0BA00421
162 #define stdout_hash 0x7FA08308
163 #define stderr_hash 0x7FA058A3
164 
165 static int devfs_open(void * opaque, const char * path, int flags, int mode) {
166  uint32_t h = hash_djb2((const uint8_t *) path, -1);
167 // DBGOUT("devfs_open(%p, \"%s\", %i, %i)\r\n", opaque, path, flags, mode);
168  switch (h) {
169  case stdin_hash:
170  if (flags & (O_WRONLY | O_RDWR))
171  return -1;
172  return fio_open(stdin_read, NULL, NULL, NULL, NULL);
173  break;
174  case stdout_hash:
175  if (flags & O_RDONLY)
176  return -1;
177  return fio_open(NULL, stdout_write, NULL, NULL, NULL);
178  break;
179  case stderr_hash:
180  if (flags & O_RDONLY)
181  return -1;
182  return fio_open(NULL, stdout_write, NULL, NULL, NULL);
183  break;
184  }
185  return -1;
186 }
187 
189  DBGOUT("Registering devfs.\r\n");
190  register_fs("dev", devfs_open, NULL);
191 }