source: azure_iot_hub_mbedtls/trunk/ntshell/src/fdtable.c@ 400

Last change on this file since 400 was 400, checked in by coas-nagasima, 5 years ago

ファイルヘッダーの更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 11.7 KB
Line 
1/*
2 * TOPPERS PROJECT Home Network Working Group Software
3 *
4 * Copyright (C) 2017-2019 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37#include "shellif.h"
38#include <stdint.h>
39#include <kernel.h>
40#include <t_syslog.h>
41#include <t_stdlib.h>
42#include <sil.h>
43#include "syssvc/serial.h"
44#include "syssvc/syslog.h"
45#include "target_syssvc.h"
46#include "fdtable.h"
47#include "kernel_cfg.h"
48#include <string.h>
49#include "util/ntstdio.h"
50#include "hal/serial_api.h"
51
52#ifdef _DEBUG
53static const char THIS_FILE[] = __FILE__;
54#endif
55
56extern IO_TYPE IO_TYPE_STDIN;
57extern IO_TYPE IO_TYPE_STDOUT;
58extern IO_TYPE IO_TYPE_STDERR;
59
60static struct SHELL_FILE fd_table[8 * sizeof(FLGPTN)] = {
61 { STDIN_FILENO, &IO_TYPE_STDIN, 0 },
62 { STDOUT_FILENO, &IO_TYPE_STDOUT, 0 },
63 { STDERR_FILENO, &IO_TYPE_STDERR, 0 },
64};
65#define fd_table_count (sizeof(fd_table) / sizeof(fd_table[0]))
66
67struct SHELL_FILE *new_fp(IO_TYPE *type, int id, int writable)
68{
69 struct SHELL_FILE *fp = NULL;
70 ER ret;
71
72 ret = wai_sem(SEM_FILEDESC);
73 if (ret < 0) {
74 syslog(LOG_ERROR, "wai_sem => %d", ret);
75 }
76
77 for (int fd = 3; fd < fd_table_count; fd++) {
78 fp = &fd_table[fd];
79 if (fp->type != NULL)
80 continue;
81
82 memset(fp, 0, sizeof(struct SHELL_FILE));
83 fp->fd = fd;
84 fp->type = type;
85 fp->handle = id;
86 fp->writable = writable;
87 break;
88 }
89
90 ret = sig_sem(SEM_FILEDESC);
91 if (ret < 0) {
92 syslog(LOG_ERROR, "sig_sem => %d", ret);
93 }
94
95 if (fp != NULL) {
96 FLGPTN flgptn = 0;
97
98 FD_SET(fp->fd, (fd_set *)&flgptn);
99
100 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
101 if (ret != E_OK) {
102 syslog(LOG_ERROR, "clr_flg => %d", ret);
103 }
104 }
105
106 return fp;
107}
108
109struct SHELL_FILE *id_to_fd(IO_TYPE *type, int id)
110{
111 struct SHELL_FILE *fp = NULL;
112 ER ret;
113
114 ret = wai_sem(SEM_FILEDESC);
115 if (ret < 0) {
116 syslog(LOG_ERROR, "wai_sem => %d", ret);
117 }
118
119 for (int fd = 3; fd < fd_table_count; fd++) {
120 fp = &fd_table[fd];
121 if ((fp->type == type) && (fp->handle == id))
122 break;
123 }
124
125 ret = sig_sem(SEM_FILEDESC);
126 if (ret < 0) {
127 syslog(LOG_ERROR, "sig_sem => %d", ret);
128 }
129
130 return fp;
131}
132
133int delete_fd_by_id(IO_TYPE *type, int id)
134{
135 struct SHELL_FILE *fp = id_to_fd(type, id);
136 if (fp == NULL)
137 return -EBADF;
138
139 return delete_fp(fp);
140}
141
142int delete_fp(struct SHELL_FILE *fp)
143{
144 ER ret;
145
146 fp->type->delete(fp);
147
148 ret = wai_sem(SEM_FILEDESC);
149 if (ret < 0) {
150 syslog(LOG_ERROR, "wai_sem => %d", ret);
151 }
152
153 memset(fp, 0, sizeof(struct SHELL_FILE));
154
155 ret = sig_sem(SEM_FILEDESC);
156 if (ret < 0) {
157 syslog(LOG_ERROR, "sig_sem => %d", ret);
158 }
159
160 return 0;
161}
162
163struct SHELL_FILE *fd_to_fp(int fd)
164{
165 if ((fd < 0) || (fd >= fd_table_count))
166 return NULL;
167 return &fd_table[fd];
168}
169
170void memand(void *dst, void *src, size_t len)
171{
172 uint8_t *d = (uint8_t *)dst;
173 uint8_t *s = (uint8_t *)src;
174 uint8_t *e = &s[len];
175
176 while (s < e) {
177 *d++ &= *s++;
178 }
179}
180
181struct fd_events {
182 int count;
183 fd_set readfds;
184 fd_set writefds;
185 fd_set errorfds;
186};
187
188ER shell_get_evts(struct fd_events *evts, TMO tmout);
189
190#define TMO_MAX INT_MAX
191
192int shell_select(int n, fd_set *__restrict rfds, fd_set *__restrict wfds, fd_set *__restrict efds, struct timeval *__restrict tv)
193{
194 ER ret;
195 TMO tmout = TMO_FEVR;
196 struct fd_events evts;
197
198 if (tv != NULL) {
199 if (tv->tv_sec < (TMO_MAX / 1000000))
200 tmout = tv->tv_sec * 1000000 + tv->tv_usec;
201 else
202 tmout = TMO_MAX;
203 }
204
205 if (rfds != NULL)
206 memcpy(&evts.readfds, rfds, sizeof(fd_set));
207 else
208 memset(&evts.readfds, 0, sizeof(fd_set));
209 if (wfds != NULL)
210 memcpy(&evts.writefds, wfds, sizeof(fd_set));
211 else
212 memset(&evts.writefds, 0, sizeof(fd_set));
213 if (efds != NULL)
214 memcpy(&evts.errorfds, efds, sizeof(fd_set));
215 else
216 memset(&evts.errorfds, 0, sizeof(fd_set));
217 evts.count = 0;
218
219 ret = shell_get_evts(&evts, tmout);
220 if (ret == E_OK) {
221 if (rfds != NULL)
222 memand(rfds, &evts.readfds, sizeof(fd_set));
223 if (wfds != NULL)
224 memand(wfds, &evts.writefds, sizeof(fd_set));
225 if (efds != NULL)
226 memand(efds, &evts.errorfds, sizeof(fd_set));
227 return evts.count;
228 }
229 if (ret == E_TMOUT) {
230 if (rfds != NULL)
231 memset(rfds, 0, sizeof(fd_set));
232 if (wfds != NULL)
233 memset(wfds, 0, sizeof(fd_set));
234 if (efds != NULL)
235 memset(efds, 0, sizeof(fd_set));
236 return 0;
237 }
238
239 return -EBADF;
240}
241
242int shell_poll(struct pollfd *fds, nfds_t nfds, int timeout)
243{
244 ER ret;
245 TMO tmout;
246 struct fd_events evts;
247
248 if(timeout < 0)
249 tmout = TMO_FEVR;
250 else if (timeout < (TMO_MAX / 1000))
251 tmout = timeout * 1000;
252 else
253 tmout = TMO_MAX;
254
255 memset(&evts, 0, sizeof(evts));
256
257 for (int i = 0; i < nfds; i++) {
258 struct pollfd *pfd = &fds[i];
259 int fd = pfd->fd;
260 if ((fd < 0) || (fd >= fd_table_count))
261 continue;
262
263 if (pfd->events & POLLIN)
264 FD_SET(fd, &evts.readfds);
265 if (pfd->events & POLLOUT)
266 FD_SET(fd, &evts.writefds);
267 if (pfd->events & POLLERR)
268 FD_SET(fd, &evts.errorfds);
269 pfd->revents = 0;
270 }
271
272 ret = shell_get_evts(&evts, tmout);
273 if (ret == E_OK) {
274 int result = 0;
275 for (int i = 0; i < nfds; i++) {
276 struct pollfd *pfd = &fds[i];
277 int fd = pfd->fd;
278 if ((fd < 0) || (fd >= fd_table_count))
279 continue;
280
281 if (FD_ISSET(fd, &evts.readfds))
282 pfd->revents |= POLLIN;
283 if (FD_ISSET(fd, &evts.writefds))
284 pfd->revents |= POLLOUT;
285 if (FD_ISSET(fd, &evts.errorfds))
286 pfd->revents |= POLLERR;
287 if (pfd->revents != 0)
288 result++;
289 }
290 return result;
291 }
292 if (ret == E_TMOUT) {
293 return 0;
294 }
295
296 return -EBADF;
297}
298
299ER shell_get_evts(struct fd_events *evts, TMO tmout)
300{
301 int count;
302 SYSTIM prev, now;
303 FLGPTN flgptn;
304
305 get_tim(&prev);
306
307 for (;;) {
308 ER ret;
309 FLGPTN waitptn, readfds = 0, writefds = 0;
310 struct SHELL_FILE *fp = NULL;
311
312#ifndef NTSHELL_NO_SOCKET
313 waitptn = *((FLGPTN *)&evts->errorfds);
314#else
315 waitptn = *((FLGPTN *)&evts->readfds) | *((FLGPTN *)&evts->errorfds);
316#endif
317 count = 0;
318 for (int fd = 0; fd < fd_table_count; fd++) {
319 fp = &fd_table[fd];
320
321 if (FD_ISSET(fd, &evts->readfds)) {
322 if (fp->type->readable(fp)) {
323 FD_SET(fd, (fd_set *)&readfds);
324 count++;
325 if (fp->readevt_w == fp->readevt_r) fp->readevt_r--;
326 }
327 else {
328 FD_SET(fd, (fd_set *)&waitptn);
329 }
330 }
331
332 if (FD_ISSET(fd, &evts->writefds)) {
333 if (fp->type->writable(fp)) {
334 FD_SET(fd, (fd_set *)&writefds);
335 count++;
336 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_r--;
337 }
338 else {
339 FD_SET(fd, (fd_set *)&waitptn);
340 }
341 }
342 }
343 memset(evts, 0, sizeof(*evts));
344
345 if (waitptn == 0) {
346 memcpy(&evts->readfds, &readfds, sizeof(evts->readfds));
347 memcpy(&evts->writefds, &writefds, sizeof(evts->writefds));
348 evts->count = count;
349 return E_OK;
350 }
351 else if ((readfds | writefds) != 0) {
352 set_flg(FLG_SELECT_WAIT, (readfds | writefds));
353 }
354
355 /* イベント待ち */
356 flgptn = 0;
357 ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, tmout);
358 if (ret != E_OK) {
359 if (ret != E_TMOUT) {
360 syslog(LOG_ERROR, "twai_flg => %d", ret);
361 return ret;
362 }
363 }
364
365 if (flgptn != 0) {
366 flgptn &= waitptn;
367
368 /* 受け取ったフラグのみクリア */
369 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
370 if (ret != E_OK) {
371 syslog(LOG_ERROR, "clr_flg => %d", ret);
372 }
373 }
374
375 count = 0;
376 for (int fd = 0; fd < fd_table_count; fd++) {
377 fp = &fd_table[fd];
378
379 if (fp->readevt_w != fp->readevt_r) {
380 fp->readevt_r++;
381 if (FD_ISSET(fd, (fd_set *)&waitptn))
382 FD_SET(fd, &evts->readfds);
383 count++;
384 }
385 if (fp->writeevt_w != fp->writeevt_r) {
386 fp->writeevt_r++;
387 if (FD_ISSET(fd, (fd_set *)&waitptn))
388 FD_SET(fd, &evts->writefds);
389 count++;
390 }
391 if (fp->errorevt_w != fp->errorevt_r) {
392 fp->errorevt_r++;
393 if (FD_ISSET(fd, (fd_set *)&waitptn))
394 FD_SET(fd, &evts->errorfds);
395 count++;
396 }
397 }
398
399 if ((flgptn == 0) || (count > 0))
400 break;
401
402 get_tim(&now);
403
404 SYSTIM elapse = now - prev;
405 if (elapse > tmout) {
406 flgptn = 0;
407 break;
408 }
409
410 prev = now;
411 tmout -= elapse;
412 }
413
414 evts->count = count;
415
416 return (flgptn == 0) ? E_TMOUT : E_OK;
417}
418
419void clean_fd()
420{
421 struct SHELL_FILE *fp = NULL;
422 for (int fd = 3; fd < fd_table_count; fd++) {
423 fp = &fd_table[fd];
424 if ((fp->type == 0) || (fp->fd == 0))
425 continue;
426
427 fp->type->close(fp);
428
429 delete_fp(fp);
430 }
431}
432
433int shell_ioctl(int fd, int request, void *arg)
434{
435 struct SHELL_FILE *fp = fd_to_fp(fd);
436 if (fp == NULL)
437 return -EBADF;
438
439 return fp->type->ioctl(fp, request, arg);
440}
441
442#ifdef NTSHELL_NO_SOCKET
443
444int shell_socket(int family, int type, int protocol)
445{
446 return -ENOMEM;
447}
448
449int shell_bind(int fd, const struct sockaddr *addr, socklen_t len)
450{
451 return -ENOMEM;
452}
453
454int shell_listen(int fd, int backlog)
455{
456 return -ENOMEM;
457}
458
459int shell_connect(int fd, const struct sockaddr *addr, socklen_t len)
460{
461 return -ENOMEM;
462}
463
464int shell_accept(int fd, struct sockaddr *__restrict addr, socklen_t *__restrict len)
465{
466 return -ENOMEM;
467}
468
469ssize_t shell_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
470{
471 return -ENOMEM;
472}
473
474ssize_t shell_sendmsg(int fd, const struct msghdr *msg, int flags)
475{
476 return -ENOMEM;
477}
478
479ssize_t shell_recvfrom(int fd, void *__restrict buf, size_t len, int flags, struct sockaddr *__restrict addr, socklen_t *__restrict alen)
480{
481 return -ENOMEM;
482}
483
484ssize_t shell_recvmsg(int fd, struct msghdr *msg, int flags)
485{
486 return -ENOMEM;
487}
488
489int shell_shutdown(int fd, int how)
490{
491 return -ENOMEM;
492}
493
494int shell_getsockopt(int fd, int level, int optname, void *optval, socklen_t *__restrict optlen)
495{
496 return -ENOMEM;
497}
498
499int shell_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
500{
501 return -ENOMEM;
502}
503
504int shell_getpeername(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
505{
506 return -ENOMEM;
507}
508
509int shell_getsockname(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
510{
511 return -ENOMEM;
512}
513#endif
Note: See TracBrowser for help on using the repository browser.