source: UsbWattMeter/trunk/ecnl_lwip/echonet_agent.c

Last change on this file was 167, checked in by coas-nagasima, 6 years ago

MIMEにSJISを設定

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc; charset=SHIFT_JIS
File size: 26.6 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2015 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: echonet_agent.c 167 2016-03-08 11:37:45Z coas-nagasima $
36 */
37
38/*
39 * ECHONET Lite 動的生成ノード
40 */
41
42#include <kernel.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <stdarg.h>
46#include <string.h>
47#include <t_syslog.h>
48#include "echonet.h"
49#include "echonet_fbs.h"
50#include "echonet_agent.h"
51#include "echonet_task.h"
52#include "echonet_lcl_task.h"
53
54typedef struct ecn_agent_buffer
55{
56 union{
57 struct ecn_agent_buffer *free;
58 ecn_agent_queue_t queue;
59 };
60 union{
61 ecn_obj_t obj;
62 ecn_node_t node;
63 ecn_device_t device;
64 };
65} ecn_agent_buffer_t;
66
67typedef struct ecn_agent
68{
69 EPRPINIB eprpinib;
70 ecn_agent_queue_t nodes;
71 ecn_node_t *current_node;
72 bool_t msg_proced;
73 int blkpos;
74 ecn_agent_buffer_t *free;
75 ecn_agent_buffer_t blockes[TNUM_AEOBJID];
76 int requestid;
77} ecn_agent_t;
78
79static ER ecn_agent_proc_get_device_list(ecn_agent_t *agent, ECN_FBS_ID req);
80static ER ecn_agent_proc_get_device_info(ecn_agent_t *agent, ECN_FBS_ID req);
81static void ecn_node_send_set_prop_map(ecn_node_t *node);
82static void ecn_node_send_get_prop_map(ecn_node_t *node);
83static void ecn_node_send_anno_prop_map(ecn_node_t *node);
84static void ecn_node_timeout_on_start(ecn_node_t *node);
85static void ecn_node_next_proc_on_set_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj);
86static void ecn_node_timeout_on_set_prpmap_wait(ecn_node_t *node);
87static void ecn_node_next_proc_on_get_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj);
88static void ecn_node_timeout_on_get_prpmap_wait(ecn_node_t *node);
89static void ecn_node_next_proc_on_anno_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj);
90static void ecn_node_timeout_on_anno_prpmap_wait(ecn_node_t *node);
91
92int ecn_agent_eprpset(const EPRPINIB *item, const void *src, int size, bool_t *anno);
93int ecn_agent_eprpget(const EPRPINIB *item, void *dst, int size);
94
95static ecn_agent_queue_t *cast_queue(ecn_obj_t *obj)
96{
97 return (ecn_agent_queue_t *)((intptr_t)obj - offsetof(ecn_agent_buffer_t, obj));
98}
99
100static ecn_obj_t *cast_obj(ecn_agent_queue_t *queue)
101{
102 return (ecn_obj_t *)((intptr_t)queue + offsetof(ecn_agent_buffer_t, obj));
103}
104
105static ecn_node_t *cast_node(const EOBJCB *eobj)
106{
107 return (ecn_node_t *)((intptr_t)eobj - offsetof(ecn_node_t, eobj));
108}
109
110static ecn_obj_t *cast_obj2(const EOBJINIB *inib)
111{
112 return (ecn_obj_t *)((intptr_t)inib - offsetof(ecn_obj_t, inib));
113}
114
115static ecn_agent_t *cast_agent(const EPRPINIB *inib)
116{
117 return (ecn_agent_t *)((intptr_t)inib - offsetof(ecn_agent_t, eprpinib));
118}
119
120ecn_agent_t g_ecn_agent = {
121 /*eprpinib*/{
122 0x00,
123 EPC_RULE_SET | EPC_RULE_GET,
124 255,
125 (intptr_t)&g_ecn_agent,
126 ecn_agent_eprpset,
127 ecn_agent_eprpget
128 },
129};
130
131ER get_buf(ecn_agent_t *agent, ecn_agent_buffer_t **buf)
132{
133 ER ret = E_OK;
134
135 loc_cpu();
136
137 if (agent->blkpos < TNUM_AEOBJID) {
138 *buf = &agent->blockes[agent->blkpos++];
139 }
140 else if (agent->free == NULL) {
141 ret = E_TMOUT;
142 }
143 else{
144 *buf = agent->free;
145 agent->free = agent->free->free;
146 }
147
148 unl_cpu();
149
150 return ret;
151}
152
153ER rel_buf(ecn_agent_t *agent, ecn_agent_buffer_t *buf)
154{
155 if ((buf < &agent->blockes[0]) || (buf >= &agent->blockes[TNUM_AEOBJID]))
156 return E_PAR;
157
158 if ((((intptr_t)buf - (intptr_t)&agent->blockes[0]) % sizeof(ecn_agent_buffer_t)) != 0)
159 return E_PAR;
160
161 loc_cpu();
162
163 if (agent->free == NULL) {
164 agent->free = buf;
165 agent->free->free = NULL;
166 }
167 else {
168 ecn_agent_buffer_t *next = agent->free;
169 agent->free = buf;
170 agent->free->free = next;
171 }
172
173 unl_cpu();
174
175 return E_OK;
176}
177
178/*
179 * キューの初期化
180 *
181 * p_queueにはキューヘッダを指定する.
182 */
183Inline void
184ecn_agent_queue_init(ecn_agent_queue_t *p_queue)
185{
186#ifdef _DEBUG
187 p_queue->p_parent = p_queue;
188#endif
189 p_queue->p_prev = p_queue;
190 p_queue->p_next = p_queue;
191}
192
193/*
194 * キューの前エントリへの挿入
195 *
196 * p_queueの前にp_entryを挿入する.p_queueにキューヘッダを指定した場
197 * 合には,キューの末尾にp_entryを挿入することになる.
198 */
199Inline void
200ecn_agent_queue_add(ecn_agent_queue_t *p_queue, ecn_agent_queue_t *p_entry)
201{
202#ifdef _DEBUG
203 assert((p_queue->p_parent == p_queue) && (p_entry->p_parent == NULL));
204 p_entry->p_parent = p_queue;
205#endif
206 p_entry->p_prev = p_queue->p_prev;
207 p_entry->p_next = p_queue;
208 p_queue->p_prev->p_next = p_entry;
209 p_queue->p_prev = p_entry;
210}
211
212/*
213 * エントリの削除
214 *
215 * p_entryをキューから削除する.
216 */
217Inline void
218ecn_agent_queue_remove(ecn_agent_queue_t *p_queue, ecn_agent_queue_t *p_entry)
219{
220#ifdef _DEBUG
221 assert((p_queue->p_parent == p_queue) && (p_entry->p_parent == p_queue));
222 p_entry->p_parent = NULL;
223#endif
224 p_entry->p_prev->p_next = p_entry->p_next;
225 p_entry->p_next->p_prev = p_entry->p_prev;
226}
227
228ecn_node_t *ecn_agent_find_node(ECN_ENOD_ID enodid)
229{
230 ecn_agent_t *agent = &g_ecn_agent;
231 ecn_agent_queue_t *queue = agent->nodes.p_next;
232#ifdef _DEBUG
233 assert(queue->p_parent == &agent->nodes);
234#endif
235 for (; queue != &agent->nodes; queue = queue->p_next) {
236 ecn_node_t *node = (ecn_node_t *)cast_obj(queue);
237 if(node->enodId == enodid)
238 return node;
239 }
240
241 return NULL;
242}
243
244ecn_node_t *ecn_agent_find_node2(const EOBJCB *pk_eobj)
245{
246 ecn_agent_t *agent = &g_ecn_agent;
247 ecn_agent_queue_t *queue;
248
249 if(pk_eobj == NULL)
250 return NULL;
251
252 queue = agent->nodes.p_next;
253#ifdef _DEBUG
254 assert(queue->p_parent == &agent->nodes);
255#endif
256 for (; queue != &agent->nodes; queue = queue->p_next) {
257 ecn_node_t *node = (ecn_node_t *)cast_obj(queue);
258 if(&node->eobj == pk_eobj)
259 return node;
260 }
261
262 return NULL;
263}
264
265ecn_obj_t *ecn_agent_find_eobj(const EOBJCB *pk_nod, T_ECN_EOJ eoj)
266{
267 ecn_agent_queue_t *devices = &cast_node(pk_nod)->devices;
268 ecn_agent_queue_t *queue = devices->p_next;
269#ifdef _DEBUG
270 assert(queue->p_parent == devices);
271#endif
272 for (; queue != devices; queue = queue->p_next) {
273 ecn_obj_t *obj = cast_obj(queue);
274 if (obj->inib.eojx1 != eoj.eojx1)
275 continue;
276 if (obj->inib.eojx2 != eoj.eojx2)
277 continue;
278 if (obj->inib.eojx3 != eoj.eojx3)
279 continue;
280
281 return obj;
282 }
283
284 return NULL;
285}
286
287ecn_obj_t *ecn_agent_find_obj2(ecn_node_t *pk_nod, const EOBJINIB *pk_obj)
288{
289 ecn_agent_queue_t *devices = &pk_nod->devices;
290 ecn_agent_queue_t *queue = devices->p_next;
291#ifdef _DEBUG
292 assert(queue->p_parent == devices);
293#endif
294 for (; queue != devices; queue = queue->p_next) {
295 ecn_obj_t *obj = cast_obj(queue);
296 if (&obj->inib == pk_obj)
297 return obj;
298 }
299
300 return NULL;
301}
302
303ID ecn_agent_get_eobj(const EOBJINIB *pk_obj)
304{
305 return cast_obj2(pk_obj)->eobjId;
306}
307
308const EOBJINIB *ecn_agent_next_eobj(const EOBJCB *pk_nod, const EOBJINIB *pk_obj)
309{
310 ecn_agent_queue_t *devices = &cast_node(pk_nod)->devices;
311 ecn_obj_t *device = (ecn_obj_t *)pk_obj->exinf;
312 ecn_agent_queue_t *queue = cast_queue(device);
313#ifdef _DEBUG
314 assert(queue->p_parent == devices);
315#endif
316 if (queue == devices)
317 return NULL;
318
319 return &cast_obj(queue->p_next)->inib;
320}
321
322bool_t ecn_agent_get_eoj_enodid(ID eobjid, T_ECN_EOJ *eoj, ECN_ENOD_ID *enodid)
323{
324 ecn_agent_t *agent = &g_ecn_agent;
325 ecn_agent_buffer_t *buf;
326 int i = eobjid;
327
328 /* オブジェクトIDから実体を取得 */
329 i -= (tmax_eobjid + 1);
330 if ((i < 0)
331 || (i >= (sizeof(agent->blockes) / sizeof(agent->blockes[0])))){
332 return false;
333 }
334
335 buf = &agent->blockes[i];
336 if(buf->obj.eobjId != eobjid)
337 return false;
338
339 /* オブジェクトのEOJをコピー */
340 memcpy(eoj, &buf->obj.inib.eojx1, sizeof(*eoj));
341
342 /* 所属するノードのオブジェクトIDを取得 */
343 if(buf->obj.inib.enodid == 0)
344 i = buf->obj.eobjId;
345 else
346 i = buf->obj.inib.enodid;
347
348 i -= (tmax_eobjid + 1);
349 if ((i < 0)
350 || (i >= (sizeof(agent->blockes) / sizeof(agent->blockes[0])))){
351 return false;
352 }
353
354 /* ノードIDを取得 */
355 buf = &agent->blockes[i];
356 *enodid = buf->node.enodId;
357
358 return true;
359}
360
361void ecn_agent_set_epc_to_prop_map(uint8_t epc, uint8_t *propMap)
362{
363 int i, j;
364 assert((epc & 0x80) != 0);
365 i = epc & 0xF;
366 j = (epc >> 4) - 8;
367 propMap[i] |= (1 << j);
368}
369
370bool_t ecn_agent_contains_epc_in_prop_map(uint8_t epc, uint8_t *propMap)
371{
372 int i, j;
373 assert((epc & 0x80) != 0);
374 i = epc & 0xF;
375 j = (epc >> 4) - 8;
376 return (propMap[i] & (1 << j)) != 0;
377}
378
379void ecn_agent_init(void)
380{
381 ecn_agent_queue_init(&g_ecn_agent.nodes);
382}
383
384ecn_node_t *ecn_agent_create_node(ecn_agent_t *agent, T_EDATA *esv)
385{
386 ecn_agent_buffer_t *result = NULL;
387 ecn_node_t *node;
388 uint8_t epc;
389 uint8_t pdc;
390 uint8_t edt[256];
391 T_ENUM_EPC enm;
392 ER ret;
393 T_ECN_EOJ *eoj, *end;
394
395 // プロパティ通知か取得応答で、
396 switch (esv->hdr.edata.esv) {
397 case ESV_GET_RES:
398 case ESV_GET_SNA:
399 case ESV_INF:
400 break;
401 default:
402 return NULL;
403 }
404
405 // ノードプロファイル宛の場合
406 eoj = &esv->hdr.edata.seoj;
407 if ((eoj->eojx1 != EOJ_X1_PROFILE) || (eoj->eojx2 != EOJ_X2_NODE_PROFILE)
408 || (eoj->eojx3 != 0x01))
409 return NULL;
410
411 ret = ecn_itr_ini(&enm, esv);
412 if(ret != E_OK){
413 syslog(LOG_WARNING, "ecn_itr_ini");
414 }
415
416 while (ecn_itr_nxt(&enm, &epc, &pdc, &edt) == E_OK) {
417 switch (epc) {
418 // インスタンスリスト通知の場合
419 case 0xD5:
420 // 自ノードインスタンスリストS通知の場合
421 case 0xD6:
422 // サイズが合わない場合
423 if (pdc != (1 + edt[0] * sizeof(T_ECN_EOJ)))
424 return NULL;
425
426 ret = get_buf(agent, &result);
427 if(ret != E_OK){
428 syslog(LOG_WARNING, "get_buf");
429 return NULL;
430 }
431
432 memset(result, 0, sizeof(*result));
433 node = &result->node;
434 node->enodId = ((T_ECN_FST_BLK *)esv)->hdr.sender.id;
435 node->base.eobjId = tmax_eobjid + 1 + (((intptr_t)result - (intptr_t)agent->blockes) / sizeof(agent->blockes[0]));
436 node->base.inib.enodid = 0;
437 node->base.inib.eobjatr = EOBJ_SYNC_REMOTE_NODE;
438 node->base.inib.exinf = (intptr_t)node;
439 node->base.inib.eojx1 = eoj->eojx1;
440 node->base.inib.eojx2 = eoj->eojx2;
441 node->base.inib.eojx3 = eoj->eojx3;
442 node->base.inib.eprp = &agent->eprpinib;
443 node->base.inib.eprpcnt = 0;
444 ecn_agent_set_epc_to_prop_map(0xD5, node->base.pmapGet);
445 ecn_agent_set_epc_to_prop_map(0xD6, node->base.pmapGet);
446 ecn_agent_set_epc_to_prop_map(0x9D, node->base.pmapGet);
447 ecn_agent_set_epc_to_prop_map(0x9E, node->base.pmapGet);
448 ecn_agent_set_epc_to_prop_map(0x9F, node->base.pmapGet);
449 ecn_agent_queue_init(&node->devices);
450 node->eobj.profile = &node->base.inib;
451 node->eobj.eobjs = NULL;
452 node->eobj.eobjcnt = pdc / 3;
453 node->state = ecn_node_state_idle;
454 node->timer = TMO_FEVR;
455
456 end = (T_ECN_EOJ *)&edt[pdc];
457 for (eoj = (T_ECN_EOJ *)&edt[1]; eoj < end; eoj++) {
458 ecn_device_t *device;
459 ecn_agent_buffer_t *obj;
460
461 ret = get_buf(agent, &obj);
462 if(ret != E_OK){
463 syslog(LOG_WARNING, "get_buf");
464 return NULL;
465 }
466
467 memset(obj, 0, sizeof(*obj));
468 device = &obj->device;
469 device->node = node;
470 device->base.eobjId = tmax_eobjid + 1 + (((intptr_t)obj - (intptr_t)agent->blockes) / sizeof(agent->blockes[0]));
471 device->base.inib.eobjatr = EOBJ_DEVICE;
472 device->base.inib.enodid = node->base.eobjId;
473 device->base.inib.exinf = (intptr_t)device;
474 device->base.inib.eojx1 = eoj->eojx1;
475 device->base.inib.eojx2 = eoj->eojx2;
476 device->base.inib.eojx3 = eoj->eojx3;
477 device->base.inib.eprp = &agent->eprpinib;
478 device->base.inib.eprpcnt = 0;
479 ecn_agent_set_epc_to_prop_map(0x9D, device->base.pmapGet);
480 ecn_agent_set_epc_to_prop_map(0x9E, device->base.pmapGet);
481 ecn_agent_set_epc_to_prop_map(0x9F, device->base.pmapGet);
482
483 ecn_agent_queue_add(&node->devices, &obj->queue);
484 }
485 break;
486 default:
487 continue;
488 }
489 break;
490 }
491
492 if (result == NULL)
493 return NULL;
494
495 ecn_agent_queue_add(&agent->nodes, &result->queue);
496
497 return node;
498}
499
500static ER ecn_agent_proc_get_device_list(ecn_agent_t *agent, ECN_FBS_ID req)
501{
502 ER ret;
503 ECN_FBS_ID res;
504 ecn_inm_get_device_list_req_t msg;
505 ECN_FBS_SSIZE_T len;
506 ecn_agent_buffer_t *pos, *end = &agent->blockes[TNUM_AEOBJID];
507 ecn_inm_get_device_item_t item;
508
509 ret = _ecn_fbs_get_data(req, &msg, sizeof(msg), &len);
510 if (ret != E_OK) {
511 return ret;
512 }
513
514 ret = _ecn_tsk_cre_res_fbs(req, ECN_INM_GET_DEVICE_LIST_RES, &res);
515 if (ret != E_OK) {
516 return ret;
517 }
518
519 ret = _ecn_fbs_add_data_ex(res, &msg.requestid, sizeof(((ecn_inm_get_device_list_res_t *)0)->requestid));
520 if (ret != E_OK) {
521 _ecn_fbs_del(res);
522 return ret;
523 }
524
525 for (pos = &agent->blockes[0]; pos < end; pos++){
526 if(pos->obj.eobjId == 0)
527 continue;
528
529 item.eobjid = pos->obj.eobjId;
530 item.enodid = pos->obj.inib.enodid;
531 item.eojx1 = pos->obj.inib.eojx1;
532 item.eojx2 = pos->obj.inib.eojx2;
533 item.eojx3 = pos->obj.inib.eojx3;
534
535 if(pos->device.node != NULL)
536 item.addrid = pos->device.node->enodId;
537 else
538 item.addrid = pos->node.enodId;
539
540 ret = _ecn_fbs_add_data_ex(res, &item, sizeof(item));
541 if (ret != E_OK) {
542 _ecn_fbs_del(res);
543 return ret;
544 }
545 }
546
547 ret = psnd_dtq(res.ptr->hdr.target.mbxid, (intptr_t)res.ptr);
548 if (ret != E_OK) {
549 _ecn_fbs_del(res);
550 return ret;
551 }
552
553 return E_OK;
554}
555
556static ER ecn_agent_proc_get_device_info(ecn_agent_t *agent, ECN_FBS_ID req)
557{
558 ER ret;
559 ECN_FBS_ID res;
560 ecn_inm_get_device_info_req_t msg;
561 ecn_inm_get_device_info_res_t rmsg;
562 ECN_FBS_SSIZE_T len;
563 int eobjId;
564 ecn_agent_buffer_t *pos;
565
566 ret = _ecn_fbs_get_data(req, &msg, sizeof(msg), &len);
567 if (ret != E_OK) {
568 return ret;
569 }
570
571 eobjId = msg.eobjid - tmax_eobjid - 1;
572 pos = &agent->blockes[eobjId];
573
574 ret = _ecn_tsk_cre_res_fbs(req, ECN_INM_GET_DEVICE_INFO_RES, &res);
575 if (ret != E_OK) {
576 return ret;
577 }
578
579 rmsg.requestid = msg.requestid;
580 rmsg.eobjid = pos->obj.eobjId;
581 memcpy(rmsg.pmapSet, pos->obj.pmapSet, sizeof(rmsg.pmapSet));
582 memcpy(rmsg.pmapGet, pos->obj.pmapGet, sizeof(rmsg.pmapGet));
583 memcpy(rmsg.pmapAnno, pos->obj.pmapAnno, sizeof(rmsg.pmapAnno));
584 rmsg.eprpcnt = pos->obj.eprpcnt;
585
586 ret = _ecn_fbs_add_data_ex(res, &rmsg, sizeof(rmsg));
587 if (ret != E_OK) {
588 _ecn_fbs_del(res);
589 return ret;
590 }
591
592 ret = psnd_dtq(res.ptr->hdr.target.mbxid, (intptr_t)res.ptr);
593 if (ret != E_OK) {
594 _ecn_fbs_del(res);
595 return ret;
596 }
597
598 return E_OK;
599}
600
601TMO ecn_agent_get_timer()
602{
603 TMO timer = TMO_FEVR, temp;
604 ecn_agent_t *agent = &g_ecn_agent;
605 ecn_node_t *node;
606 ecn_agent_queue_t *queue;
607
608 queue = &agent->nodes;
609 for (;;) {
610 queue = queue->p_next;
611#ifdef _DEBUG
612 assert(queue->p_parent == &agent->nodes);
613#endif
614 if(&agent->nodes == queue)
615 break;
616
617 node = (ecn_node_t *)cast_obj(queue);
618 temp = node->timer;
619 if (temp != TMO_FEVR) {
620 if ((timer == TMO_FEVR) || (temp < timer)) {
621 timer = temp;
622 }
623 }
624 }
625
626 return timer;
627}
628
629void ecn_agent_progress(TMO interval)
630{
631 ecn_agent_t *agent = &g_ecn_agent;
632 ecn_node_t *node;
633 ecn_agent_queue_t *queue;
634
635 queue = &agent->nodes;
636 for (;;) {
637 queue = queue->p_next;
638#ifdef _DEBUG
639 assert(queue->p_parent == &agent->nodes);
640#endif
641 if(&agent->nodes == queue)
642 break;
643
644 node = (ecn_node_t *)cast_obj(queue);
645 if (node->timer == TMO_FEVR)
646 continue;
647
648 node->timer -= interval;
649 if (node->timer <= 0) {
650 node->timer = 0;
651 }
652 }
653}
654
655void ecn_agent_timeout()
656{
657 ecn_agent_t *agent = &g_ecn_agent;
658 ecn_node_t *node;
659 ecn_agent_queue_t *queue;
660
661 queue = &agent->nodes;
662 for (;;) {
663 queue = queue->p_next;
664#ifdef _DEBUG
665 assert(queue->p_parent == &agent->nodes);
666#endif
667 if(&agent->nodes == queue)
668 break;
669
670 node = (ecn_node_t *)cast_obj(queue);
671 if (node->timer != 0)
672 continue;
673
674 switch (node->state) {
675 case ecn_node_state_start:
676 ecn_node_timeout_on_start(node);
677 break;
678 case ecn_node_state_set_prpmap_wait:
679 ecn_node_timeout_on_set_prpmap_wait(node);
680 break;
681 case ecn_node_state_get_prpmap_wait:
682 ecn_node_timeout_on_get_prpmap_wait(node);
683 break;
684 case ecn_node_state_anno_prpmap_wait:
685 ecn_node_timeout_on_anno_prpmap_wait(node);
686 break;
687 default:
688 assert(0);
689 }
690 }
691}
692
693bool_t ecn_agent_proc_int_msg(ECN_FBS_ID fbs, uint8_t cmd)
694{
695 ecn_agent_t *agent = &g_ecn_agent;
696
697 switch(cmd)
698 {
699 case ECN_INM_GET_DEVICE_LIST_REQ:
700 ecn_agent_proc_get_device_list(agent, fbs);
701 break;
702 case ECN_INM_GET_DEVICE_INFO_REQ:
703 ecn_agent_proc_get_device_info(agent, fbs);
704 break;
705 default:
706 return false;
707 }
708
709 return true;
710}
711
712void ecn_agent_proc_ecn_msg(const EOBJCB **ppk_snod, const EOBJINIB **ppk_sobj, T_EDATA *esv)
713{
714 ecn_agent_t *agent = &g_ecn_agent;
715 ecn_node_t *snod;
716 ecn_obj_t *sobj;
717
718 /* 静的に定義された送信元の場合 */
719 if ((*ppk_snod != NULL) && (*ppk_snod)->eobjs != NULL) {
720 /* 処理しない */
721 return;
722 }
723
724 snod = ecn_agent_find_node2(*ppk_snod);
725
726 /* 送信元を知らなかったら */
727 if (snod == NULL) {
728 /* 送信元のノード情報を新規に作成 */
729 snod = ecn_agent_create_node(agent, esv);
730 if (snod == NULL)
731 return;
732 }
733
734 sobj = ecn_agent_find_obj2(snod, *ppk_sobj);
735
736 /* ノードプロファイルの場合 */
737 if ((esv->hdr.edata.seoj.eojx1 == EOJ_X1_PROFILE)
738 && (esv->hdr.edata.seoj.eojx2 == EOJ_X2_NODE_PROFILE)) {
739 sobj = &snod->base;
740 }
741 /* 機器オブジェクトの場合 */
742 else {
743 sobj = ecn_agent_find_eobj(&snod->eobj, esv->hdr.edata.seoj);
744 }
745
746 *ppk_snod = &snod->eobj;
747 *ppk_sobj = &sobj->inib;
748
749 agent->current_node = snod;
750 agent->msg_proced = false;
751}
752
753void ecn_agent_proc_ecn_msg_end()
754{
755 ecn_agent_t *agent = &g_ecn_agent;
756 ecn_node_t *node = agent->current_node;
757 ecn_obj_t *sobj;
758
759 if(node == NULL)
760 return;
761
762 sobj = node->current;
763 if(sobj == NULL)
764 return;
765
766 if (agent->msg_proced) {
767 switch (node->state) {
768 case ecn_node_state_set_prpmap_wait:
769 ecn_node_next_proc_on_set_prpmap_wait(node, sobj);
770 break;
771 case ecn_node_state_get_prpmap_wait:
772 ecn_node_next_proc_on_get_prpmap_wait(node, sobj);
773 break;
774 case ecn_node_state_anno_prpmap_wait:
775 ecn_node_next_proc_on_anno_prpmap_wait(node, sobj);
776 break;
777 }
778 }
779}
780
781static void ecn_node_send_set_prop_map(ecn_node_t *node)
782{
783 T_EDATA *esv;
784 ecn_obj_t *obj = node->current;
785
786 // プロパティ値読み出し要求
787 ecn_esv_get(&esv, obj->eobjId, 0x9E);
788 ecn_snd_esv(esv);
789
790 node->state = ecn_node_state_set_prpmap_wait;
791 node->timer = (TMO)5000;
792}
793
794static void ecn_node_send_get_prop_map(ecn_node_t *node)
795{
796 T_EDATA *esv;
797 ecn_obj_t *obj = node->current;
798
799 // プロパティ値読み出し要求
800 ecn_esv_get(&esv, obj->eobjId, 0x9F);
801 ecn_snd_esv(esv);
802
803 node->state = ecn_node_state_get_prpmap_wait;
804 node->timer = (TMO)5000;
805}
806
807static void ecn_node_send_anno_prop_map(ecn_node_t *node)
808{
809 T_EDATA *esv;
810 ecn_obj_t *obj = node->current;
811
812 // プロパティ値読み出し要求
813 ecn_esv_get(&esv, obj->eobjId, 0x9D);
814 ecn_snd_esv(esv);
815
816 node->state = ecn_node_state_anno_prpmap_wait;
817 node->timer = (TMO)5000;
818}
819
820static void ecn_node_next_obj(ecn_node_t *node)
821{
822 ecn_obj_t *obj = node->current;
823 ecn_agent_queue_t *queue;
824 ecn_device_t *device;
825
826 /* objが指定されていない場合 */
827 if(obj == NULL){
828 /* このノードを返す */
829 node->current = &node->base;
830 return;
831 }
832 /* ノードの場合 */
833 else if((obj->inib.eojx1 == EOJ_X1_PROFILE) && (obj->inib.eojx2 == EOJ_X2_NODE_PROFILE)){
834 node = (ecn_node_t *)obj;
835
836 /* 配下の機器を返す */
837 queue = node->devices.p_next;
838 device = (ecn_device_t *)cast_obj(queue);
839 }
840 /* 機器の場合 */
841 else{
842 /* 次の機器を返す */
843 node = ((ecn_device_t *)obj)->node;
844 queue = cast_queue(obj)->p_next;
845 device = (ecn_device_t *)cast_obj(queue);
846 }
847
848 /* その機器が末尾だった場合 */
849 if(&node->devices == queue){
850 node->current = NULL;
851 }
852 else {
853 node->current = &device->base;
854 }
855}
856
857static void ecn_node_timeout_on_start(ecn_node_t *node)
858{
859 for (;;) {
860 ecn_obj_t *obj = node->current;
861 if (obj == NULL) {
862 node->state = ecn_node_state_idle;
863 node->timer = TMO_FEVR;
864 return;
865 }
866
867 if((obj->pmapFlag & PMAP_FLAG_SET) == 0){
868 ecn_node_send_set_prop_map(node);
869 break;
870 }
871 else if((obj->pmapFlag & PMAP_FLAG_GET) == 0){
872 ecn_node_send_get_prop_map(node);
873 break;
874 }
875 else if((obj->pmapFlag & PMAP_FLAG_ANNO) == 0){
876 ecn_node_send_anno_prop_map(node);
877 break;
878 }
879 else{
880 ecn_node_next_obj(node);
881 }
882 }
883}
884
885static void ecn_node_next_proc_on_set_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj)
886{
887 if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
888 ecn_node_send_get_prop_map(node);
889 }
890 else if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
891 ecn_node_send_anno_prop_map(node);
892 }
893 else if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
894 ecn_node_send_set_prop_map(node);
895 }
896 else{
897 ecn_node_next_obj(node);
898 ecn_node_timeout_on_start(node);
899 }
900}
901
902static void ecn_node_timeout_on_set_prpmap_wait(ecn_node_t *node)
903{
904 ecn_obj_t *obj = node->current;
905 if(obj == NULL){
906 node->state = ecn_node_state_idle;
907 node->timer = TMO_FEVR;
908 return;
909 }
910
911 ecn_node_next_proc_on_set_prpmap_wait(node, obj);
912}
913
914static void ecn_node_next_proc_on_get_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj)
915{
916 if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
917 ecn_node_send_anno_prop_map(node);
918 }
919 else if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
920 ecn_node_send_set_prop_map(node);
921 }
922 else if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
923 ecn_node_send_get_prop_map(node);
924 }
925 else{
926 ecn_node_next_obj(node);
927 ecn_node_timeout_on_start(node);
928 }
929}
930
931static void ecn_node_timeout_on_get_prpmap_wait(ecn_node_t *node)
932{
933 ecn_obj_t *obj = node->current;
934 if(obj == NULL){
935 node->state = ecn_node_state_idle;
936 node->timer = TMO_FEVR;
937 return;
938 }
939
940 ecn_node_next_proc_on_get_prpmap_wait(node, obj);
941}
942
943static void ecn_node_next_proc_on_anno_prpmap_wait(ecn_node_t *node, ecn_obj_t *sobj)
944{
945 if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
946 ecn_node_send_set_prop_map(node);
947 }
948 else if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
949 ecn_node_send_get_prop_map(node);
950 }
951 else if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
952 ecn_node_send_anno_prop_map(node);
953 }
954 else{
955 ecn_node_next_obj(node);
956 ecn_node_timeout_on_start(node);
957 }
958}
959
960static void ecn_node_timeout_on_anno_prpmap_wait(ecn_node_t *node)
961{
962 ecn_obj_t *obj = node->current;
963 if(obj == NULL){
964 node->state = ecn_node_state_idle;
965 node->timer = TMO_FEVR;
966 return;
967 }
968
969 ecn_node_next_proc_on_anno_prpmap_wait(node, obj);
970}
971
972const EPRPINIB *ecn_agent_get_property(const EOBJINIB *fp_obj, uint8_t fa_epc, const EPRPINIB *item)
973{
974 ecn_obj_t *obj = cast_obj2(fp_obj);
975 bool_t has = false;
976
977 /* ノードの場合はインスタンスリスト通知と自ノードインスタンスリストS通知を必須で受け取る */
978 if ((fp_obj->enodid == 0) && ((fa_epc == 0xD5) || (fa_epc == 0xD6)))
979 has = true;
980 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapGet))
981 has = true;
982 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapSet))
983 has = true;
984 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapAnno))
985 has = true;
986
987 if(!has)
988 return NULL;
989
990 ((EPRPINIB *)item)->eprpcd = fa_epc;
991 ((EPRPINIB *)item)->exinf = (intptr_t)fp_obj;
992
993 return item;
994}
995
996int ecn_agent_eprpget(const EPRPINIB *item, void *dst, int size)
997{
998 return 0;
999}
1000
1001int ecn_agent_eprpset(const EPRPINIB *item, const void *src, int size, bool_t *anno)
1002{
1003 ecn_agent_t *agent = cast_agent(item);
1004 ecn_node_t *node = agent->current_node;
1005 const uint8_t *edt = (const uint8_t *)src;
1006 ecn_obj_t *sobj = cast_obj2((const EOBJINIB *)item->exinf);
1007 uint8_t eprpcnt;
1008 int i;
1009
1010 switch (item->eprpcd) {
1011 /* インスタンスリスト通知の場合 */
1012 case 0xD5:
1013 /* 自ノードインスタンスリストS通知の場合 */
1014 case 0xD6:
1015 if ((node != NULL) && (node->state == ecn_node_state_idle)) {
1016 ecn_agent_queue_t *devices = &node->devices;
1017 ecn_agent_queue_t *queue = devices->p_next;
1018#ifdef _DEBUG
1019 assert(queue->p_parent == devices);
1020#endif
1021 for (; queue != devices; queue = queue->p_next) {
1022 ecn_obj_t *obj = cast_obj(queue);
1023 obj->pmapFlag = 0;
1024 }
1025 node->base.pmapFlag = 0;
1026 node->state = ecn_node_state_start;
1027 node->timer = (TMO)1000;
1028 node->current = sobj;
1029 }
1030 break;
1031 /* 通知プロパティマップの場合 */
1032 case 0x9D:
1033 eprpcnt = edt[0];
1034
1035 if (eprpcnt < 16) {
1036 /* サイズチェック */
1037 if (eprpcnt + 1 != size)
1038 return 0;
1039
1040 for (i = 1; i < size; i++)
1041 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapAnno);
1042 }
1043 else {
1044 /* サイズチェック */
1045 if (size != 17)
1046 return 0;
1047
1048 memcpy(sobj->pmapAnno, &edt[1], 16);
1049 }
1050 sobj->eprpcnt = eprpcnt;
1051 sobj->pmapFlag |= PMAP_FLAG_ANNO;
1052 break;
1053 /* SETプロパティマップの場合 */
1054 case 0x9E:
1055 eprpcnt = edt[0];
1056
1057 if (eprpcnt < 16) {
1058 /* サイズチェック */
1059 if (eprpcnt + 1 != size)
1060 return 0;
1061
1062 for (i = 1; i < size; i++)
1063 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapSet);
1064 }
1065 else {
1066 /* サイズチェック */
1067 if (size != 17)
1068 return 0;
1069
1070 memcpy(sobj->pmapSet, &edt[1], 16);
1071 }
1072 sobj->eprpcnt = eprpcnt;
1073 sobj->pmapFlag |= PMAP_FLAG_SET;
1074 break;
1075 /* GETプロパティマップの場合 */
1076 case 0x9F:
1077 eprpcnt = edt[0];
1078
1079 if (eprpcnt < 16) {
1080 /* サイズチェック */
1081 if (eprpcnt + 1 != size)
1082 return 0;
1083
1084 for (i = 1; i < size; i++)
1085 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapGet);
1086 }
1087 else {
1088 /* サイズチェック */
1089 if (size != 17)
1090 return 0;
1091
1092 memcpy(sobj->pmapGet, &edt[1], 16);
1093 }
1094 sobj->eprpcnt = eprpcnt;
1095 sobj->pmapFlag |= PMAP_FLAG_GET;
1096 break;
1097 default:
1098 return 0;
1099 }
1100
1101 agent->msg_proced = true;
1102
1103 return size;
1104}
1105
1106ER ecn_agent_get_device_list(ID sender, int requestid, ECN_FBS_ID *pk_req)
1107{
1108 ER a_ret;
1109 ECN_FBS_ID req;
1110
1111 a_ret = _ecn_tsk_cre_req_fbs(sender, ECN_INM_GET_DEVICE_LIST_REQ, &req);
1112 if (a_ret != E_OK) {
1113 return a_ret;
1114 }
1115
1116 a_ret = _ecn_fbs_add_data_ex(req, &requestid, sizeof(((ecn_inm_get_device_list_req_t *)0)->requestid));
1117 if (a_ret != E_OK) {
1118 _ecn_fbs_del(req);
1119 return a_ret;
1120 }
1121
1122 *pk_req = req;
1123
1124 return E_OK;
1125}
1126
1127ER ecn_agent_get_device_info(ID sender, int requestid, ID eobjid, ECN_FBS_ID *pk_req)
1128{
1129 ER a_ret;
1130 ECN_FBS_ID req;
1131
1132 a_ret = _ecn_tsk_cre_req_fbs(sender, ECN_INM_GET_DEVICE_INFO_REQ, &req);
1133 if (a_ret != E_OK) {
1134 return a_ret;
1135 }
1136
1137 a_ret = _ecn_fbs_add_data_ex(req, &requestid, sizeof(((ecn_inm_get_device_info_req_t *)0)->requestid));
1138 if (a_ret != E_OK) {
1139 _ecn_fbs_del(req);
1140 return a_ret;
1141 }
1142
1143 a_ret = _ecn_fbs_add_data_ex(req, &eobjid, sizeof(((ecn_inm_get_device_info_req_t *)0)->eobjid));
1144 if (a_ret != E_OK) {
1145 _ecn_fbs_del(req);
1146 return a_ret;
1147 }
1148
1149 *pk_req = req;
1150
1151 return E_OK;
1152}
Note: See TracBrowser for help on using the repository browser.