source: uKadecot/trunk/ecnl_ssp/echonet_agent.c@ 265

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

ECNL 1.0.3の修正内容を盛り込み
内蔵Webアプリで機器が取得できないのを修正

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