source: uKadecot/trunk/ecnl_ssp/echonet_task.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: 59.6 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014 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_task.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
49#include "syssvc/serial.h"
50#include "syssvc/syslog.h"
51
52#include "net/ip/uip.h"
53
54#include "echonet.h"
55#include "echonet_fbs.h"
56#include "echonet_task.h"
57#include "echonet_dbg.h"
58#ifdef ECHONET_CONTROLLER_EXTENTION
59#include "echonet_agent.h"
60#endif
61
62#ifndef ECHONET_TASK_GET_TIMER
63#define ECHONET_TASK_GET_TIMER TMO_FEVR
64#endif /* ECHONET_TASK_GET_TIMER */
65
66#ifndef ECHONET_TASK_PROGRESS
67#define ECHONET_TASK_PROGRESS(timer)
68#endif /* ECHONET_TASK_PROGRESS */
69
70#ifndef ECHONET_TASK_TIMEOUT
71#define ECHONET_TASK_TIMEOUT
72#endif /* ECHONET_TASK_TIMEOUT */
73
74static struct ecnl_state s;
75
76/* 受信メッセージを開放するか否か */
77static bool_t g_release_esv;
78
79/* 受信メッセージを転送するか否か */
80bool_t g_forward_esv;
81
82ER _ecn_tsk_ntf_inl(intptr_t fa_exinf);
83
84ER _ecn_tsk_snd_mbx(ECN_FBS_ID fa_rsp_fbs, bool_t from_app)
85{
86 ER a_ret;
87 intptr_t msg = (intptr_t)fa_rsp_fbs.ptr;
88 ID mbxid = ecn_udp_mailboxid;
89 ECN_ENOD_ID target = fa_rsp_fbs.ptr->hdr.target.id;
90#ifdef ECN_DBG_PUT_ENA
91 intptr_t a_fbs_sub1 = (intptr_t)fa_rsp_fbs.ptr->lnk.p_sub[0];
92#endif
93 if (from_app && (((T_EDATA *)fa_rsp_fbs.ptr)->hdr.edata.esv == ESV_INFC)) {
94 if (target < ENOD_MULTICAST_ID || tnum_enodadr <= target)
95 return E_NOEXS;
96 apitid_table[target] = ((T_EDATA *)fa_rsp_fbs.ptr)->hdr.ecn_hdr.tid;
97 mbxid = ecn_svc_mailboxid;
98 }
99 else {
100 switch (target) {
101 case ENOD_MULTICAST_ID:
102 if (from_app)
103 apitid_table[target] = ((T_EDATA *)fa_rsp_fbs.ptr)->hdr.ecn_hdr.tid;
104
105 mbxid = ecn_udp_mailboxid;
106 break;
107 case ENOD_LOCAL_ID:
108 if (from_app)
109 mbxid = ecn_svc_mailboxid;
110 else
111 mbxid = ecn_api_mailboxid;
112 break;
113 case ENOD_API_ID:
114 mbxid = ecn_api_mailboxid;
115 break;
116 default:
117 if (from_app)
118 apitid_table[target] = ((T_EDATA *)fa_rsp_fbs.ptr)->hdr.ecn_hdr.tid;
119
120 if (target < ENOD_REMOTE_ID || tnum_enodadr <= target)
121 return E_NOEXS;
122 target += - ENOD_REMOTE_ID + 1;
123 if (from_app && (target < tnum_enodid)) {
124 /* 非同期のリモートノードはサービス処理タスクで処理する */
125 switch (eobjcb_table[target].profile->eobjatr) {
126 case EOBJ_SYNC_REMOTE_NODE:
127 mbxid = ecn_udp_mailboxid;
128 break;
129 case EOBJ_ASYNC_REMOTE_NODE:
130 mbxid = ecn_svc_mailboxid;
131 break;
132 default:
133 return E_SYS;
134 }
135 }
136 else {
137 mbxid = ecn_udp_mailboxid;
138 }
139 break;
140 }
141 }
142#ifdef ECN_DBG_PUT_ENA
143 ECN_DBG_PUT("psnd_dtq(%d, 0x%08X-0x%08X)", mbxid, (intptr_t)msg, a_fbs_sub1);
144 _ecn_dbg_bindmp((const uint8_t *)msg, 256);
145#endif
146 a_ret = psnd_dtq(mbxid, msg);
147#ifdef ECN_DBG_PUT_ENA
148 ECN_DBG_PUT("psnd_dtq(%d, 0x%08X-0x%08X) result = %d:%s", mbxid, (intptr_t)msg, a_fbs_sub1, a_ret, itron_strerror(a_ret));
149#endif
150 return a_ret;
151}
152
153static void _ecn_tsk_int_module_init(intptr_t fa_exinf);
154static void _ecn_tsk_int_startup(intptr_t fa_exinf);
155static uint16_t _ecn_tsk_new_tid(void);
156static void _ecn_tsk_int_msg(intptr_t fa_exinf, ECN_FBS_ID fa_fbs_id);
157static void _ecn_tsk_ecn_msg(intptr_t fa_exinf, ECN_FBS_ID fa_fbs_id);
158
159static void _ecn_tsk_eoj_set(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_fromapp, bool_t fa_update,
160 ECN_FBS_ID fa_fbs_id, ECN_SRV_CODE fa_res_esv, ECN_SRV_CODE fa_sna_esv,
161 ECN_FBS_ID *fa_fbs_anno);
162static void _ecn_tsk_eoj_get(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_forward, ATR fa_access,
163 ECN_FBS_ID fa_fbs_id, ECN_SRV_CODE fa_res_esv, ECN_SRV_CODE fa_sna_esv);
164static void _ecn_tsk_eoj_res(ECN_FBS_ID fa_fbs_id, ECN_SRV_CODE fa_res_esv,
165 ECN_SRV_CODE fa_sna_esv);
166static void _ecn_tsk_eoj_set_get(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_fromapp,
167 ECN_FBS_ID fa_fbs_id, ECN_SRV_CODE fa_res_esv, ECN_SRV_CODE fa_sna_esv,
168 ECN_FBS_ID *fa_fbs_anno);
169static void _ecn_tsk_eoj_set_get_res(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_fromapp,
170 ECN_FBS_ID fa_fbs_id, ECN_FBS_ID *fa_fbs_anno);
171
172/* モジュール初期化フラグ */
173static uint8_t m_eobjlist_need_init = 1;
174
175/* シーケンス番号 */
176static uint16_t g_current_tid = 1;
177
178/*
179 * ECHONET Lite タスクの初期化(コンストラクタ相当)
180 */
181void echonet_task_init(intptr_t exinf)
182{
183 if (m_eobjlist_need_init)
184 _ecn_tsk_int_module_init(exinf);
185}
186
187/*
188 * モジュール初期化
189 */
190static void _ecn_tsk_int_module_init(intptr_t exinf)
191{
192 if (!m_eobjlist_need_init)
193 return;
194
195 /* ECN_DBG_PUT("[ECHONET MainTask:%d] started", tskid); */
196 syslog(LOG_NOTICE, "[ECHONET MainTask] started");
197
198 m_eobjlist_need_init = 0;
199
200#ifdef ECHONET_CONTROLLER_EXTENTION
201 ecn_agent_init();
202#endif
203}
204
205/*
206 * ECHONET Lite タスクの本体
207 */
208static
209PT_THREAD(echonet_task_pt(intptr_t fa_exinf))
210{
211 ER a_ret, a_ret2;
212 union
213 {
214 intptr_t p_msg;
215 ECN_FBS_ID fbs_id;
216 } a_mdt;
217 static SYSTIM a_prev, a_now;
218 TMO a_timer;
219#ifdef ECHONET_CONTROLLER_EXTENTION
220 TMO a_timera;
221#endif
222
223 PT_BEGIN(&s.pt);
224
225 a_ret = sta_cyc(ecn_svc_cychdrid);
226 if (a_ret != E_OK) {
227 ECN_DBG_PUT("sta_cyc() result = %d:%s", a_ret, itron_strerror(a_ret));
228 PT_EXIT(&s.pt);
229 }
230
231 _ecn_tsk_int_startup(fa_exinf);
232
233 a_ret2 = get_tim(&a_now);
234 if (a_ret2 != E_OK) {
235 ECN_DBG_PUT("get_tim() result = %d:%s", a_ret2, itron_strerror(a_ret2));
236 PT_EXIT(&s.pt);
237 }
238
239 /* メッセージループ */
240 for (;;) {
241 a_prev = a_now;
242
243 a_timer = ECHONET_TASK_GET_TIMER;
244#ifdef ECHONET_CONTROLLER_EXTENTION
245 a_timera = ecn_agent_get_timer();
246 if(a_timer == TMO_FEVR){
247 a_timer =a_timera;
248 }
249 else if((a_timera != TMO_FEVR) && (a_timera < a_timer)){
250 a_timer = a_timera;
251 }
252#endif
253 timer_set(&s.timer, a_timer);
254
255 PT_WAIT_UNTIL(&s.pt, (((a_ret = prcv_dtq(ecn_svc_mailboxid, &a_mdt.p_msg)) == E_OK)
256 || ((a_ret = timer_expired(&s.timer) ? E_TMOUT : E_WBLK) == E_TMOUT)));
257 if ((a_ret != E_OK) && (a_ret != E_TMOUT)) {
258 ECN_DBG_PUT("trcv_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
259 PT_EXIT(&s.pt);
260 }
261
262 a_ret2 = get_tim(&a_now);
263 if (a_ret2 != E_OK) {
264 ECN_DBG_PUT("get_tim() result = %d:%s", a_ret2, itron_strerror(a_ret2));
265 PT_EXIT(&s.pt);
266 }
267
268 a_timer = a_now - a_prev;
269 ECHONET_TASK_PROGRESS(a_timer);
270#ifdef ECHONET_CONTROLLER_EXTENTION
271 ecn_agent_progress(a_timer);
272#endif
273
274 if (a_ret == E_OK) {
275 ECN_DBG_PUT("trcv_dtq() mbx recv (%d byte)", _ecn_fbs_get_datalen(a_mdt.fbs_id));
276 g_release_esv = true;
277
278 switch (a_mdt.fbs_id.ptr->hdr.type) {
279 /* 内部使用メッセージ */
280 case ECN_MSG_INTERNAL:
281 _ecn_tsk_int_msg(fa_exinf, a_mdt.fbs_id);
282 break;
283
284 /* ECHONET用メッセージ */
285 case ECN_MSG_ECHONET:
286 _ecn_tsk_ecn_msg(fa_exinf, a_mdt.fbs_id);
287 break;
288
289 default:
290 syslog(LOG_WARNING, "echonet_task() a_fbs_id.ptr->k.hdr.k.t_edt.type:0x%02X undefined.", a_mdt.fbs_id.ptr->hdr.type);
291 }
292
293 /* 領域解放 */
294 if (g_release_esv)
295 _ecn_fbs_del(a_mdt.fbs_id);
296 }
297
298 ECHONET_TASK_TIMEOUT;
299#ifdef ECHONET_CONTROLLER_EXTENTION
300 ecn_agent_timeout();
301#endif
302 }
303
304 PT_END(&s.pt);
305}
306
307/*
308 * ECHONET Lite プロトスレッド起動タスク
309 */
310void echonet_task(intptr_t fa_exinf)
311{
312 echonet_task_pt(fa_exinf);
313}
314
315/*
316 * ECHONET Lite タスク起動用周期ハンドラー
317 */
318void echonet_cychdr(intptr_t exinf)
319{
320 (void)iact_tsk((ID)exinf);
321}
322
323/*
324 * シーケンス番号生成
325 */
326static uint16_t _ecn_tsk_new_tid(void)
327{
328 return g_current_tid++;
329}
330
331/*
332 * 要求電文作成
333 * 引数
334 * ECN_FBS_ID *fp_fbs_id 取得したFBS_IDの格納先
335 * ID fa_seoj 送信元のECHONETオブジェクトID
336 * ID fa_deoj 宛先のECHONETオブジェクトID
337 * uint8_t fa_epc プロパティコード
338 * uint8_t fa_pdc プロパティ値データサイズ
339 * const void *p_edt プロパティ値データ
340 * ECN_SRV_CODE fa_esv ECHONET Light サービスコード
341 */
342ER _ecn_tsk_mk_esv(ECN_FBS_ID *fp_fbs_id, ID fa_seoj, ID fa_deoj,
343 uint8_t fa_epc, uint8_t fa_pdc, const void *p_edt, ECN_SRV_CODE fa_esv)
344{
345 ER a_ret;
346 int a_size, i;
347 ECN_FBS_ID a_fbs_id = { 0 }; /* 要求電文用メモリ */
348 T_ECN_EDT_HDR a_ecn_hdp; /* ecn_hdr+edata+ecn_prp 14byte */
349 ID a_enodid;
350 const EOBJINIB *a_eobj;
351 const EOBJINIB *a_enod;
352
353 if (!fp_fbs_id)
354 return E_PAR; /* 取得したFBS_IDの格納先がNULL */
355 if (ECHONET_MEMPOOL_BLOCK_SIZE <= fa_pdc)
356 return E_PAR; /* プロパティ値サイズが大きすぎる */
357 if (!p_edt && 0 < fa_pdc)
358 return E_PAR; /* プロパティ値サイズが1以上なのにデータポインタがNULL */
359
360 if (fa_seoj <= EOBJ_NULL || tmax_eobjid < fa_seoj)
361 return E_NOEXS; /* ECHONETオブジェクトIDが未定義 */
362#ifndef ECHONET_CONTROLLER_EXTENTION
363 if (fa_deoj < EOBJ_NULL || tmax_eobjid < fa_deoj)
364 return E_NOEXS; /* ECHONETオブジェクトIDが未定義 */
365#else
366 if (fa_deoj < EOBJ_NULL || (tmax_eobjid + TNUM_AEOBJID) < fa_deoj)
367 return E_NOEXS; /* ECHONETオブジェクトIDが未定義 */
368#endif
369 if (fa_deoj == EOBJ_NULL && fa_esv == ESV_INFC)
370 return E_NOEXS; /* ECHONETオブジェクトIDが未定義 */
371
372 /* 要求最小サイズの取得 */
373 a_size = sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY) + sizeof(T_ECN_PRP);
374
375 /* 要求電文用メモリの取得 */
376 a_ret = _ecn_fbs_cre(a_size, &a_fbs_id);
377 if (a_ret != E_OK || !a_fbs_id.ptr) { /* 確保失敗 */
378 ECN_DBG_PUT("_ecn_fbs_cre(%d) result = %d:%s",
379 a_size,
380 a_ret, itron_strerror(a_ret));
381 return E_NOMEM;
382 }
383
384 /* 要求電文設定 */
385 memset(&a_ecn_hdp, 0, sizeof(a_ecn_hdp));
386 a_ecn_hdp.ecn_hdr.ehd1 = ECN_EDH1_ECHONET_LITE;
387 a_ecn_hdp.ecn_hdr.ehd2 = ECN_EDH2_FORMAT_1;
388 a_ecn_hdp.ecn_hdr.tid = _ecn_tsk_new_tid();
389 memcpy(&a_ecn_hdp.edata.seoj, &eobjinib_table[fa_seoj - 1].eojx1, sizeof(a_ecn_hdp.edata.seoj));
390 a_ecn_hdp.edata.esv = fa_esv;
391 a_ecn_hdp.edata.opc = 1; /* 処理プロパティ数 */
392 a_ecn_hdp.ecn_prp.epc = fa_epc; /* プロパティコード */
393 a_ecn_hdp.ecn_prp.pdc = fa_pdc; /* 付随データサイズ */
394
395 /* 要求電文用メモリにデータ追加 */
396 a_ret = _ecn_fbs_add_data_ex(a_fbs_id, &a_ecn_hdp, a_size);
397 if (a_ret) {
398 ECN_DBG_PUT("_ecn_fbs_add_data_ex(*, ecn_hdp{esv:0x%02X,epc:0x%02X}, %d) result = %d:%s",
399 a_ecn_hdp.edata.esv, a_ecn_hdp.ecn_prp.epc, a_size,
400 a_ret, itron_strerror(a_ret));
401 goto lb_except;
402 }
403 if (0 < fa_pdc) {
404 /* 付随データ追加 */
405 a_ret = _ecn_fbs_add_data_ex(a_fbs_id, p_edt, fa_pdc);
406 if (a_ret) {
407 ECN_DBG_PUT("_ecn_fbs_add_data_ex(*, ecn_hdp{esv:0x%02X,epc:0x%02X} edt, %d) result = %d:%s",
408 a_ecn_hdp.edata.esv, a_ecn_hdp.ecn_prp.epc, fa_pdc,
409 a_ret, itron_strerror(a_ret));
410 goto lb_except;
411 }
412 }
413 if (fa_deoj == 0) {
414 ECN_DBG_PUT("マルチキャスト");
415 /* fa_deoj == 0 : マルチキャスト */
416 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx1 = EOJ_X1_PROFILE;
417 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx2 = EOJ_X2_NODE_PROFILE;
418 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx3 = 0x01;
419 a_fbs_id.ptr->hdr.target.id = ENOD_MULTICAST_ID;
420 }
421 else if (fa_deoj <= tmax_eobjid) {
422 ECN_DBG_PUT("fa_deoj = %d", fa_deoj);
423 /* if (fa_deoj < 1 || tmax_eobjid < fa_deoj) …の異常系は関数冒頭で除外済みとする */
424 a_eobj = &eobjinib_table[fa_deoj - 1];
425 memcpy(&((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj, &a_eobj->eojx1,
426 sizeof(((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj));
427
428 /* テーブルから検索 */
429 a_fbs_id.ptr->hdr.target.id = ENOD_NOT_MATCH_ID;
430 a_enodid = (a_eobj->enodid == 0) ? fa_deoj : a_eobj->enodid;
431 a_enod = &eobjinib_table[a_enodid - 1];
432 if ((a_enod->eobjatr == EOBJ_LOCAL_NODE)
433 || ((a_enod->eobjatr == EOBJ_ASYNC_REMOTE_NODE) && (fa_esv == ESV_GET))) {
434 a_fbs_id.ptr->hdr.target.id = ENOD_LOCAL_ID;
435 }
436 else{
437 for (i = 1; i < tnum_enodid; i++) {
438 const EOBJCB *temp = &eobjcb_table[i];
439 if (a_enod != temp->profile)
440 continue;
441
442 a_fbs_id.ptr->hdr.target.id = (ECN_ENOD_ID)(i + ENOD_REMOTE_ID - 1);
443 break;
444 }
445 }
446 if (a_fbs_id.ptr->hdr.target.id == ENOD_NOT_MATCH_ID) {
447 goto lb_except;
448 ECN_DBG_PUT("deoj = %02X %02X %02x : enod not match",
449 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx1,
450 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx2,
451 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx3);
452 }
453#ifdef ECN_DBG_PUT_ENA
454 else {
455 ECN_DBG_PUT("deoj = %02X %02X %02x : %s",
456 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx1,
457 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx2,
458 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx3,
459 _ecn_dbg_enod2str(a_fbs_id.ptr->hdr.target));
460 }
461#endif
462 }
463#ifdef ECHONET_CONTROLLER_EXTENTION
464 else{
465 T_ECN_EOJ eoj;
466 ECN_ENOD_ID enodid;
467 ECN_DBG_PUT("fa_deoj = %d", fa_deoj);
468 /* オブジェクトIDからEOJとノードIDを取得 */
469 if(ecn_agent_get_eoj_enodid(fa_deoj, &eoj, &enodid)){
470 memcpy(&((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj, &eoj,
471 sizeof(((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj));
472 a_fbs_id.ptr->hdr.target.id = enodid;
473 }
474 else {
475 goto lb_except;
476 ECN_DBG_PUT("deoj = %02X %02X %02x : enod not match",
477 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx1,
478 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx2,
479 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx3);
480 }
481#ifdef ECN_DBG_PUT_ENA
482 else {
483 ECN_DBG_PUT("deoj = %02X %02X %02x : %s",
484 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx1,
485 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx2,
486 ((T_EDATA *)a_fbs_id.ptr)->hdr.edata.deoj.eojx3,
487 _ecn_dbg_enod2str(a_fbs_id.ptr->hdr.target));
488 }
489#endif
490 }
491#endif
492 a_fbs_id.ptr->hdr.type = ECN_MSG_ECHONET;
493 a_fbs_id.ptr->hdr.sender.id = ENOD_API_ID;
494 if (fa_esv == ESV_INFC)
495 a_fbs_id.ptr->hdr.reply.id = a_fbs_id.ptr->hdr.target.id;
496 else if (fa_esv == ESV_INF_REQ)
497 a_fbs_id.ptr->hdr.reply.id = ENOD_MULTICAST_ID;
498 else
499 a_fbs_id.ptr->hdr.reply.id = ENOD_API_ID;
500
501 /* 正常終了 */
502 *fp_fbs_id = a_fbs_id;
503 return E_OK;
504
505lb_except:
506 /* データ作成失敗したら領域解放 */
507 if (a_fbs_id.ptr)
508 _ecn_fbs_del(a_fbs_id);
509
510 return a_ret;
511}
512
513/*
514 * 内部使用メッセージ
515 */
516static void _ecn_tsk_int_msg(intptr_t fa_exinf, ECN_FBS_ID fa_fbs_id)
517{
518 T_ECN_INTERNAL_MSG a_im;
519 ECN_FBS_SSIZE_T a_len;
520 int a_ans;
521
522 a_im.command = 0;
523 a_len = 0;
524 a_ans = _ecn_fbs_get_data(fa_fbs_id, &a_im.command, sizeof(a_im.command), &a_len);
525 if (a_ans || !a_len) {
526 return; /* NG */
527 }
528
529 switch (a_im.command) {
530 case ECN_INM_NOTIFY_INSTANCELIST:
531 ECN_DBG_PUT("do _ecn_tsk_int_startup()");
532 _ecn_tsk_int_startup(fa_exinf);
533 break;
534 default:
535#ifdef ECHONET_CONTROLLER_EXTENTION
536 if(ecn_agent_proc_int_msg(fa_fbs_id, a_im.command))
537 break;
538#endif
539 ECN_DBG_PUT("recv: unefined internal-msg: %d", a_im.command);
540 break;
541 }
542}
543
544/*
545 * タスク初期化
546 */
547static void _ecn_tsk_int_startup(intptr_t fa_exinf)
548{
549 ER a_ret;
550
551 if (m_eobjlist_need_init)
552 _ecn_tsk_int_module_init(fa_exinf);
553
554 /* インスタンスリスト通知の送信 */
555 a_ret = _ecn_tsk_ntf_inl(fa_exinf);
556 if (a_ret) {
557 syslog(LOG_WARNING, "_ecn_tsk_ntf_inl() result = %d:%s", a_ret, itron_strerror(a_ret));
558 }
559}
560
561/*
562 * インスタンスリスト通知の送信
563 * ECHONET-Lite_Ver.1.10_02.pdf p.43 図4-1-4
564 */
565ER _ecn_tsk_ntf_inl(intptr_t fa_exinf)
566{
567 const T_ECN_EOJ a_seoj = /* 0x01 : 一般ノード、0x02:送信専用ノード */
568 { EOJ_X1_PROFILE, EOJ_X2_NODE_PROFILE, 0x01 };
569 const T_ECN_EOJ a_deoj =
570 { EOJ_X1_PROFILE, EOJ_X2_NODE_PROFILE, 0x01 };
571 T_ECN_EDT_HDR a_hdr;
572 ER a_ret = E_OK;
573 ECN_FBS_ID a_fbs = { 0 };
574 int a_eoj_ct = 0;
575 int i;
576 uint8_t a_count;
577 const EOBJCB *enod = &eobjcb_table[0]; /* ローカルノード */
578 const EOBJINIB *eobj;
579
580 ECN_DBG_PUT("do _ecn_tsk_ntf_inl()");
581
582 memset(&a_hdr, 0, sizeof(a_hdr));
583 a_hdr.ecn_hdr.ehd1 = ECN_EDH1_ECHONET_LITE;
584 a_hdr.ecn_hdr.ehd2 = ECN_EDH2_FORMAT_1;
585 a_hdr.edata.seoj = a_seoj;
586 a_hdr.edata.deoj = a_deoj;
587 a_hdr.edata.esv = ESV_INF;
588 a_hdr.edata.opc = 1;
589 a_hdr.ecn_prp.epc = ECN_EPC_INL_BCS;
590
591 for (i = 0; i < enod->eobjcnt; i++) {
592 eobj = enod->eobjs[i];
593
594 if (!a_eoj_ct) {
595 /* メモリ確保・ヘッダ格納 */
596 a_hdr.ecn_hdr.tid = (uint8_t)_ecn_tsk_new_tid(); /* シーケンス番号生成 */
597 a_ret = _ecn_fbs_cre(sizeof(a_hdr), &a_fbs);
598 if (a_ret != E_OK) /* 確保失敗 */
599 goto lb_except;
600 a_ret = _ecn_fbs_add_data(a_fbs, &a_hdr, sizeof(a_hdr));
601 if (a_ret != E_OK) /* データ追加失敗 */
602 goto lb_except;
603
604 a_fbs.ptr->hdr.type = ECN_MSG_ECHONET;
605 a_fbs.ptr->hdr.sender.id = ENOD_LOCAL_ID;
606 a_fbs.ptr->hdr.target.id = ENOD_MULTICAST_ID;
607 a_fbs.ptr->hdr.reply.id = ENOD_LOCAL_ID;
608 ((T_EDATA *)a_fbs.ptr)->hdr.ecn_prp.pdc = 1; /* 件数 */
609 /* 件数を格納 */
610 a_count = (uint8_t)(enod->eobjcnt - i);
611 if (a_count >= ECN_IST_LST_EOJ_MAX_CT)
612 a_count = ECN_IST_LST_EOJ_MAX_CT;
613 a_ret = _ecn_fbs_add_data_ex(a_fbs, &a_count, sizeof(a_count));
614 if (a_ret != E_OK) /* データ追加失敗 */
615 goto lb_except;
616 }
617 /* ECHONETオブジェクトID(3byte)を格納 */
618 a_ret = _ecn_fbs_add_data_ex(a_fbs, &eobj->eojx1, sizeof(T_ECN_EOJ));
619 if (a_ret != E_OK) /* データ追加失敗 */
620 goto lb_except;
621
622 /* 件数・edtサイズ加算 */
623 ((T_EDATA *)a_fbs.ptr)->hdr.ecn_prp.pdc += sizeof(T_ECN_EOJ);
624 if (++a_eoj_ct < ECN_IST_LST_EOJ_MAX_CT)
625 continue;
626
627 /* 1アナウンスでの上限に達したら、一旦送信 */
628 a_ret = _ecn_tsk_snd_mbx(a_fbs, false);
629 if (a_ret != E_OK) /* データ送信失敗 */
630 goto lb_except;
631 a_eoj_ct = 0;
632 a_fbs.ptr = 0;
633 }
634 if (a_eoj_ct) {
635 /* 未送信データがあったら、送信 */
636 a_ret = _ecn_tsk_snd_mbx(a_fbs, false);
637 if (a_ret != E_OK) /* データ送信失敗 */
638 goto lb_except;
639 a_fbs.ptr = 0;
640 }
641 goto lb_finally;
642
643lb_except:
644 if (a_fbs.ptr)
645 _ecn_fbs_del(a_fbs);
646
647lb_finally:
648 return a_ret;
649}
650
651const EOBJCB *_ecn_eno_fnd(ECN_ENOD_ID enodid)
652{
653 const EOBJCB *enod = NULL;
654 int i;
655
656 switch (enodid) {
657 case ENOD_MULTICAST_ID:
658 case ENOD_LOCAL_ID:
659 case ENOD_API_ID:
660 enod = &eobjcb_table[0];
661 break;
662 default:
663 i = enodid - ENOD_REMOTE_ID + 1;
664 if ((i >= 1) && (i < tnum_enodid))
665 enod = &eobjcb_table[i];
666#ifdef ECHONET_CONTROLLER_EXTENTION
667 else{
668 ecn_node_t *p_tmp = ecn_agent_find_node(enodid);
669 if (p_tmp == NULL)
670 return NULL;
671 return &p_tmp->eobj;
672 }
673#endif
674 break;
675 }
676
677 return enod;
678}
679
680/*
681 * 3byteのeobjidで配列中を検索する
682 */
683const EOBJINIB *_ecn_eoj_fnd(const EOBJCB *fp_nod, const T_ECN_EOJ *fp_eoj)
684{
685 const EOBJINIB *p_obj;
686 int i, count = fp_nod->eobjcnt;
687
688#ifdef ECHONET_CONTROLLER_EXTENTION
689 if (fp_nod->eobjs == NULL) {
690 ecn_obj_t *p_tmp = ecn_agent_find_eobj(fp_nod, *fp_eoj);
691 if(p_tmp == NULL)
692 return NULL;
693 return &p_tmp->inib;
694 }
695#endif
696
697 for (i = 0; i < count; i++) {
698 p_obj = fp_nod->eobjs[i];
699
700 if (p_obj->eojx1 != fp_eoj->eojx1)
701 continue;
702 if (p_obj->eojx2 != fp_eoj->eojx2)
703 continue;
704 if (p_obj->eojx3 != fp_eoj->eojx3)
705 continue;
706
707 return p_obj;
708 }
709
710 return 0;
711}
712
713/*
714 * 電文の構成要素数とサイズのチェックを行う
715 */
716static bool_t _ecn_tsk_check_format(T_EDATA *edata, int len)
717{
718 ER ret;
719 T_ENUM_EPC enm;
720 int opc;
721 uint8_t epc;
722 uint8_t pdc;
723
724 len -= sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY);
725
726 ret = ecn_itr_ini(&enm, edata);
727 if (ret != E_OK) {
728 return false;
729 }
730 opc = enm.count;
731 for (;;) {
732 ret = ecn_itr_nxt(&enm, &epc, &pdc, NULL);
733 if (enm.is_eof)
734 break;
735 if (ret == E_BOVR){
736 if (opc != 0)
737 return false;
738 opc = enm.count;
739 len -= 1;
740 continue;
741 }
742 if (ret != E_OK)
743 break;
744
745 opc--;
746 len -= sizeof(T_ECN_PRP) + pdc;
747 }
748
749 return (opc == 0) && (len == 0);
750}
751
752static int _ecn_tsk_ecn_msg_main(ECN_FBS_ID fa_fbs_id, const EOBJINIB *p_obj, ATR eobjatr,
753 const EOBJINIB *p_sobj, ATR sobjatr);
754
755/*
756 * ECHONET用メッセージ
757 */
758static void _ecn_tsk_ecn_msg(intptr_t fa_exinf, ECN_FBS_ID fa_fbs_id)
759{
760 const EOBJCB *p_nod, *p_snod;
761 const EOBJINIB *p_obj, *p_sobj = NULL;
762 ATR eobjatr, sobjatr = EPC_NONE;
763 T_ECN_EDT_HDR *p_esv;
764 ER a_ret;
765 int i, count;
766 T_ECN_EOJ *p_eoj;
767 bool_t a_prc;
768 bool_t a_fwd;
769 ECN_ENOD_ID sender;
770
771#ifdef ECN_DBG_PUT_ENA
772 syslog(LOG_NOTICE, "mbx recv:");
773 _ecn_dbg_bindmp(fa_fbs_id.ptr->bin, sizeof(fa_fbs_id.ptr->bin));
774#endif
775
776 p_esv = &((T_EDATA *)fa_fbs_id.ptr)->hdr;
777
778 if (p_esv->ecn_hdr.ehd1 != ECN_EDH1_ECHONET_LITE
779 || p_esv->ecn_hdr.ehd2 != ECN_EDH2_FORMAT_1) {
780 ECN_DBG_PUT("_ecn_tsk_ecn_msg() format fault: 0x%02X,0x%02X", p_esv->ecn_hdr.ehd1, p_esv->ecn_hdr.ehd2);
781 return;
782 }
783
784 if (p_esv->edata.deoj.eojx3 > 0x7F) {
785 ECN_DBG_PUT("_ecn_tsk_ecn_msg() format fault: deoj %06X",
786 p_esv->edata.deoj.eojx1 << 16 | p_esv->edata.deoj.eojx2 << 8 | p_esv->edata.deoj.eojx3);
787 return;
788 }
789
790 if ((p_esv->edata.seoj.eojx3 > 0x7F) || (p_esv->edata.seoj.eojx3 == 0x00)) {
791 ECN_DBG_PUT("_ecn_tsk_ecn_msg() format fault: seoj %06X",
792 p_esv->edata.seoj.eojx1 << 16 | p_esv->edata.seoj.eojx2 << 8 | p_esv->edata.seoj.eojx3);
793 return;
794 }
795
796 if ((p_esv->edata.esv & 0xC0) != 0x40) {
797 ECN_DBG_PUT("_ecn_tsk_ecn_msg() format fault: esv 0x%02X", p_esv->edata.esv);
798 return;
799 }
800
801 if (p_esv->edata.opc == 0x00) {
802 ECN_DBG_PUT("_ecn_tsk_ecn_msg() format fault: opc 0x%02X", p_esv->edata.opc);
803 return;
804 }
805
806 /* 電文の構成要素数とサイズのチェックを行う */
807 if (!_ecn_tsk_check_format((T_EDATA *)fa_fbs_id.ptr, fa_fbs_id.ptr->hdr.length)) {
808 ECN_DBG_PUT("_ecn_tsk_ecn_msg() format fault");
809 return;
810 }
811
812 /* 送信宛からノードを検索 */
813 p_nod = _ecn_eno_fnd(fa_fbs_id.ptr->hdr.target.id);
814 /* 送信元からノードを検索 */
815 sender = fa_fbs_id.ptr->hdr.sender.id;
816 p_snod = _ecn_eno_fnd(sender);
817 if (p_snod != NULL) {
818 sobjatr = p_snod->profile->eobjatr;
819 /* ノードプロファイルの場合 */
820 if ((p_esv->edata.seoj.eojx1 == EOJ_X1_PROFILE)
821 && (p_esv->edata.seoj.eojx2 == EOJ_X2_NODE_PROFILE)) {
822 p_sobj = p_snod->profile;
823 }
824 /* 機器オブジェクトの場合 */
825 else {
826 p_sobj = _ecn_eoj_fnd(p_snod, &p_esv->edata.seoj);
827 }
828 }
829
830#ifdef ECHONET_CONTROLLER_EXTENTION
831 ecn_agent_proc_ecn_msg(&p_snod, &p_sobj, (T_EDATA *)fa_fbs_id.ptr);
832#endif
833
834 /* ノード内の機器オブジェクトを検索 */
835 a_prc = false;
836 a_fwd = false;
837 g_forward_esv = false;
838 if (p_nod != NULL) {
839 eobjatr = p_nod->profile->eobjatr;
840 p_eoj = &p_esv->edata.deoj;
841 /* ノードプロファイルの場合 */
842 if ((p_eoj->eojx1 == EOJ_X1_PROFILE)
843 && (p_eoj->eojx2 == EOJ_X2_NODE_PROFILE)) {
844 if ((p_eoj->eojx3 == p_nod->profile->eojx3)
845 || (p_eoj->eojx3 == 0)) {
846 /* 電文処理実行 */
847 if (_ecn_tsk_ecn_msg_main(fa_fbs_id, p_nod->profile, eobjatr, p_sobj, sobjatr) == 1)
848 a_fwd = true;
849 a_prc = true;
850 }
851 /* 0x74 プロパティ値通知(応答要)の場合の場合は電文破棄 */
852 else if (p_esv->edata.esv == ESV_INFC) {
853 a_prc = true;
854 }
855 }
856 /* 機器オブジェクトの場合 */
857 else {
858 count = p_nod->eobjcnt;
859#ifdef ECHONET_CONTROLLER_EXTENTION
860 p_obj = NULL;
861#endif
862 for (i = 0; i < count; i++) {
863#ifdef ECHONET_CONTROLLER_EXTENTION
864 if(p_nod->eobjs == NULL)
865 p_obj = ecn_agent_next_eobj(p_nod, p_obj);
866 else
867 p_obj = p_nod->eobjs[i];
868#else
869 p_obj = p_nod->eobjs[i];
870#endif
871 if (p_obj->eojx1 != p_eoj->eojx1)
872 continue;
873 if (p_obj->eojx2 != p_eoj->eojx2)
874 continue;
875 /* インスタンスコードが0の場合、同じクラスの全てのインスタンス宛 */
876 if ((p_obj->eojx3 != p_eoj->eojx3) && (p_eoj->eojx3 != 0))
877 continue;
878
879 /* 電文処理実行 */
880 if (_ecn_tsk_ecn_msg_main(fa_fbs_id, p_obj, eobjatr, p_sobj, sobjatr) == 1)
881 a_fwd = true;
882 a_prc = true;
883 }
884
885 /* 機器オブジェクトが見つからず、0x74 プロパティ値通知(応答要)の場合は電文破棄 */
886 if (!a_prc && (p_esv->edata.esv == ESV_INFC)) {
887 a_prc = true;
888 }
889 }
890 }
891 /* 機器オブジェクトが見つからない場合でも */
892 if (!a_prc) {
893 /* 電文処理実行(応答受信用) */
894 if (_ecn_tsk_ecn_msg_main(fa_fbs_id, NULL, EPC_NONE, p_sobj, sobjatr) == 1)
895 a_fwd = true;
896 }
897
898 /* 応答の場合アプリケーションに転送する */
899 if (a_fwd && ((p_esv->ecn_hdr.tid == apitid_table[sender])
900 || g_forward_esv))
901 {
902 g_release_esv = false;
903
904 ECN_CAP_PUT("redirect ecn_svc_mailboxid → ecn_api_mailboxid (esv:0x%02X)",
905 p_esv->edata.esv);
906 fa_fbs_id.ptr->hdr.target.id = ENOD_API_ID;
907 a_ret = psnd_dtq(ecn_api_mailboxid, (intptr_t)fa_fbs_id.ptr);
908 if (a_ret != E_OK) {
909 syslog(LOG_WARNING, "_ecn_tsk_ecn_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
910 _ecn_fbs_del(fa_fbs_id);
911 }
912 }
913#ifdef ECHONET_CONTROLLER_EXTENTION
914 ecn_agent_proc_ecn_msg_end();
915#endif
916}
917
918static int _ecn_tsk_ecn_msg_main(ECN_FBS_ID fa_fbs_id, const EOBJINIB *p_obj, ATR eobjatr,
919 const EOBJINIB *p_sobj, ATR sobjatr)
920{
921 int result;
922 T_ECN_EDT_HDR *p_esv;
923 ECN_FBS_ID a_fbs_anno = { NULL };
924 bool_t fromapp = sobjatr == EOBJ_LOCAL_NODE;
925
926 p_esv = &((T_EDATA *)fa_fbs_id.ptr)->hdr;
927
928 switch (p_esv->edata.esv) {
929 /* 0x60 プロパティ値書き込み要求(応答不要) */
930 case ESV_SET_I:
931 if (!p_obj) {
932 ECN_DBG_PUT("_ecn_tsk_ecn_msg_main() eoj %06X not found.",
933 p_esv->edata.deoj.eojx1 << 16 | p_esv->edata.deoj.eojx2 << 8 | p_esv->edata.deoj.eojx3);
934 result = -1;
935 break;
936 }
937 _ecn_tsk_eoj_set(p_obj, eobjatr, fromapp, false, fa_fbs_id, ESV_NOP, ESV_SET_I_SNA, &a_fbs_anno); /* 0; 0x50 */
938 result = 0;
939 break;
940
941 /* 0x61 プロパティ値書き込み要求(応答要) */
942 case ESV_SET_C:
943 if (!p_obj) {
944 ECN_DBG_PUT("_ecn_tsk_ecn_msg_main() eoj %06X not found.",
945 p_esv->edata.deoj.eojx1 << 16 | p_esv->edata.deoj.eojx2 << 8 | p_esv->edata.deoj.eojx3);
946 result = -1;
947 break;
948 }
949 _ecn_tsk_eoj_set(p_obj, eobjatr, fromapp, false, fa_fbs_id, ESV_SET_RES, ESV_SET_C_SNA, &a_fbs_anno); /* 0x71; 0x51 */
950 result = 0;
951 break;
952
953 /* 0x62 プロパティ値読み出し要求 */
954 case ESV_GET:
955 if (!p_obj) {
956 ECN_DBG_PUT("_ecn_tsk_ecn_msg_main() eoj %06X not found.",
957 p_esv->edata.deoj.eojx1 << 16 | p_esv->edata.deoj.eojx2 << 8 | p_esv->edata.deoj.eojx3);
958 result = -1;
959 break;
960 }
961 _ecn_tsk_eoj_get(p_obj, eobjatr, false, EPC_RULE_GET, fa_fbs_id, ESV_GET_RES, ESV_GET_SNA); /* 0x72; 0x52 */
962 result = 0;
963 break;
964
965 /* 0x63 プロパティ値通知要求 */
966 case ESV_INF_REQ:
967 if (!p_obj) {
968 ECN_DBG_PUT("_ecn_tsk_ecn_msg_main() eoj %06X not found.",
969 p_esv->edata.deoj.eojx1 << 16 | p_esv->edata.deoj.eojx2 << 8 | p_esv->edata.deoj.eojx3);
970 result = -1;
971 break;
972 }
973 fa_fbs_id.ptr->hdr.reply.id = ENOD_MULTICAST_ID;
974 _ecn_tsk_eoj_get(p_obj, eobjatr, false, (EPC_RULE_GET|EPC_RULE_ANNO), fa_fbs_id, ESV_INF, ESV_INF_SNA); /* 0x73; 0x53 */
975 result = 0;
976 break;
977
978 /* 0x6E プロパティ値書き込み・読み出し要求 */
979 case ESV_SET_GET:
980 if (!p_obj) {
981 ECN_DBG_PUT("_ecn_tsk_ecn_msg_main() eoj %06X not found.",
982 p_esv->edata.deoj.eojx1 << 16 | p_esv->edata.deoj.eojx2 << 8 | p_esv->edata.deoj.eojx3);
983 result = -1;
984 break;
985 }
986 _ecn_tsk_eoj_set_get(p_obj, eobjatr, fromapp, fa_fbs_id, ESV_SET_GET_RES, ESV_SET_GET_SNA, &a_fbs_anno); /* 0x7E; 0x5E */
987 result = 0;
988 break;
989
990 /* 0x74 プロパティ値通知(応答要) */
991 case ESV_INFC:
992 if (!p_sobj)
993 /* 送信元が未知の他ノードであった場合、応答を返す */
994 _ecn_tsk_eoj_res(fa_fbs_id, ESV_INFC_RES, ESV_INFC_RES); /* 0x7A; 0x7A */
995 else if (fromapp)
996 /* アプリケーションからの要求の場合、プロパティ値通知(応答要)を送信する */
997 _ecn_tsk_eoj_get(p_sobj, sobjatr, true, (EPC_RULE_GET|EPC_RULE_ANNO), fa_fbs_id, ESV_INFC, ESV_NOP); /* 0x74; 0 */
998 else
999 /* 送信元が既知の他ノードであった場合、プロパティ値を更新し応答を返す */
1000 _ecn_tsk_eoj_set(p_sobj, sobjatr, fromapp, true, fa_fbs_id, ESV_INFC_RES, ESV_INFC_RES, &a_fbs_anno); /* 0x7A; 0x7A */
1001 result = 0;
1002 break;
1003
1004 /* 0x60 プロパティ値書き込み要求(応答不要) */
1005 case ESV_SET_I_SNA: /* 0x50 プロパティ値書き込み要求不可応答 */
1006 result = 1;
1007 break;
1008
1009 /* 0x61 プロパティ値書き込み要求(応答要) */
1010 case ESV_SET_RES: /* 0x71 プロパティ値書き込み応答 */
1011 case ESV_SET_C_SNA: /* 0x51 プロパティ値書き込み要求不可応答 */
1012 result = 1;
1013 break;
1014
1015 /* 0x62 プロパティ値読み出し要求 */
1016 case ESV_GET_RES: /* 0x72 プロパティ値読み出し応答 */
1017 case ESV_GET_SNA: /* 0x52 プロパティ値読み出し不可応答 */
1018 if (!p_sobj) {
1019 ECN_DBG_PUT("_ecn_tsk_ecn_msg_main() eoj %06X not found.",
1020 p_esv->edata.seoj.eojx1 << 16 | p_esv->edata.seoj.eojx2 << 8 | p_esv->edata.seoj.eojx3);
1021 result = -1;
1022 break;
1023 }
1024 _ecn_tsk_eoj_set(p_sobj, sobjatr, fromapp, true, fa_fbs_id, ESV_NOP, ESV_NOP, &a_fbs_anno); /* 0; 0 */
1025 result = 1;
1026 break;
1027
1028 /* 0x63 プロパティ値通知要求 */
1029 case ESV_INF: /* 0x73 プロパティ値通知 */
1030 case ESV_INF_SNA: /* 0x53 プロパティ値通知不可応答 */
1031 if (!p_sobj) {
1032 ECN_DBG_PUT("_ecn_tsk_ecn_msg_main() eoj %06X not found.",
1033 p_esv->edata.seoj.eojx1 << 16 | p_esv->edata.seoj.eojx2 << 8 | p_esv->edata.seoj.eojx3);
1034 result = -1;
1035 break;
1036 }
1037 _ecn_tsk_eoj_set(p_sobj, sobjatr, fromapp, true, fa_fbs_id, ESV_NOP, ESV_NOP, &a_fbs_anno); /* 0; 0 */
1038 result = 1;
1039 break;
1040
1041 /* 0x6E プロパティ値書き込み・読み出し要求 */
1042 case ESV_SET_GET_RES: /* 0x7E プロパティ値書き込み・読み出し応答 */
1043 case ESV_SET_GET_SNA: /* 0x5E プロパティ値書き込み・読み出し不可応答 */
1044 if (!p_sobj) {
1045 ECN_DBG_PUT("_ecn_tsk_ecn_msg_main() eoj %06X not found.",
1046 p_esv->edata.seoj.eojx1 << 16 | p_esv->edata.seoj.eojx2 << 8 | p_esv->edata.seoj.eojx3);
1047 result = -1;
1048 break;
1049 }
1050 _ecn_tsk_eoj_set_get_res(p_sobj, sobjatr, fromapp, fa_fbs_id, &a_fbs_anno); /* 0x7A; 0 */
1051 result = 1;
1052 break;
1053
1054 /* 0x74 プロパティ値通知(応答要) */
1055 case ESV_INFC_RES: /* 0x7A プロパティ値通知応答 */
1056 result = 1;
1057 break;
1058
1059 default:
1060 syslog(LOG_WARNING, "_ecn_tsk_ecn_msg_main() esv 0x%02X undefined.", p_esv->edata.esv);
1061 result = -1;
1062 break;
1063 }
1064
1065 /* プロパティ通知要求を送信 */
1066 if (a_fbs_anno.ptr != NULL) {
1067 ER a_ret = _ecn_tsk_snd_mbx(a_fbs_anno, true);
1068 if (a_ret != E_OK)
1069 _ecn_fbs_del(a_fbs_anno);
1070 }
1071
1072 return result;
1073}
1074
1075#ifdef ECN_DBG_PUT_ENA
1076static void f_put_fbs_eoj(const char *fp_fncnm, const char *fp_varnm,
1077 ECN_FBS_ID fa_fbs_id);
1078static void f_put_fbs_eoj(const char *fp_fncnm, const char *fp_varnm,
1079 ECN_FBS_ID fa_fbs_id)
1080{
1081 ECN_DBG_PUT("%s() %s eoj src:%06X dest:%06X",
1082 fp_fncnm, fp_varnm,
1083 ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.seoj.eojx1 << 16 | ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.seoj.eojx2 << 8 | ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.seoj.eojx3,
1084 ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.deoj.eojx1 << 16 | ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.deoj.eojx2 << 8 | ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.deoj.eojx3);
1085}
1086#else
1087#define f_put_fbs_eoj(f,v,r)
1088#endif /* #ifdef ECN_DBG_PUT_ENA */
1089
1090static const EPRPINIB *_ecn_tsk_eoj_get_property(const EOBJINIB *fp_obj, uint8_t fa_epc);
1091static const EPRPINIB *_ecn_tsk_eoj_get_property(const EOBJINIB *fp_obj, uint8_t fa_epc)
1092{
1093 const EPRPINIB *p = fp_obj->eprp;
1094 uint_t i;
1095#ifdef ECHONET_CONTROLLER_EXTENTION
1096 if (fp_obj->eprpcnt == 0) {
1097 return ecn_agent_get_property(fp_obj, fa_epc, p);
1098 }
1099#endif
1100 for (i = 0; i < fp_obj->eprpcnt; i++, p++) {
1101 if (p->eprpcd != fa_epc)
1102 continue;
1103
1104 return p;
1105 }
1106 ECN_DBG_PUT("_ecn_tsk_eoj_get_property(0x%02X-0x%02X-0x%02X, epc:0x%02X) not found.",
1107 fp_obj->eojx1, fp_obj->eojx2, fp_obj->eojx3, fa_epc);
1108
1109 return NULL;
1110}
1111
1112static int _ecn_tsk_eoj_set_edt(const EPRPINIB *fp_prp, void *fp_src, int fa_srcsz,
1113 bool_t *fa_anno);
1114static int _ecn_tsk_eoj_set_edt(const EPRPINIB *fp_prp, void *fp_src, int fa_srcsz,
1115 bool_t *fa_anno)
1116{
1117 if (!fp_prp->eprpset)
1118 return -1;
1119
1120 ECN_DBG_PUT("_ecn_tsk_eoj_set_edt(epc:0x%02X) call eprpset()", fp_prp->eprpcd);
1121
1122 return fp_prp->eprpset(fp_prp, fp_src, fa_srcsz, fa_anno);
1123}
1124
1125static int _ecn_tsk_eoj_get_edt(const EPRPINIB *fp_prp, void *fp_dst, int fa_dstsz);
1126static int _ecn_tsk_eoj_get_edt(const EPRPINIB *fp_prp, void *fp_dst, int fa_dstsz)
1127{
1128 if (fa_dstsz < fp_prp->eprpsz)
1129 return -1;
1130 if (!fp_prp->eprpget)
1131 return -1;
1132
1133 ECN_DBG_PUT("_ecn_tsk_eoj_get_edt(epc:0x%02X) call eprpget()", fp_prp->eprpcd);
1134
1135 return fp_prp->eprpget(fp_prp, fp_dst, fp_prp->eprpsz);
1136}
1137
1138static T_ECN_SUB_BLK *_ecn_tsk_get_prp_pce(ECN_FBS_ID fa_fbs_id, T_ECN_PRP *fp_prp,
1139 T_ECN_SUB_BLK *const fp_prev_blk);
1140
1141/*
1142 * ECN_FBS_IDからT_ECN_PRP1件とその付随データ(edt)を抽出し、edtのポインタを返す
1143 * 引数
1144 * ECN_FBS_ID fa_fbs_id 読み取るFBS
1145 * T_ECN_PRP *fp_prp epc+pdcの格納先
1146 * T_ECN_SUB_BLK * const fp_prev_blk 前回使ったメモリのポインタ(無ければ0)
1147 * 正常:ポインタ NG:0
1148 * ポインタは_ecn_fbs_mbx_rel()で解放する必要がある
1149 */
1150static T_ECN_SUB_BLK *_ecn_tsk_get_prp_pce(ECN_FBS_ID fa_fbs_id, T_ECN_PRP *fp_prp,
1151 T_ECN_SUB_BLK *const fp_prev_blk)
1152{
1153 T_ECN_SUB_BLK *p_blk = 0;
1154 int a_size;
1155 ER a_ret;
1156
1157 /* プロパティ用メモリの取得 */
1158 if (fp_prev_blk) {
1159 p_blk = fp_prev_blk; /* 前回使ったメモリがあるなら、再利用する */
1160 }
1161 else {
1162 p_blk = (T_ECN_SUB_BLK *)_ecn_fbs_mbx_get(sizeof(*p_blk));
1163 if (!p_blk) {
1164 ECN_DBG_PUT("_ecn_fbs_mbx_get() fault.");
1165 return 0; /* メモリ不足 */
1166 }
1167 }
1168 memset(p_blk, 0, sizeof(*p_blk));
1169
1170 /* T_ECN_PRP部分(epc,pdc)を読み取る */
1171 a_size = 0;
1172 a_ret = _ecn_fbs_get_data(fa_fbs_id, fp_prp, sizeof(*fp_prp), &a_size);
1173 if (a_ret || a_size < (int)sizeof(*fp_prp)) {
1174 ECN_DBG_PUT("_ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
1175 goto lb_except;
1176 }
1177
1178 if (0 < fp_prp->pdc) {
1179 /* 付随データ部分(edt)を読み取る */
1180 a_size = 0;
1181 a_ret = _ecn_fbs_get_data(fa_fbs_id, p_blk, fp_prp->pdc, &a_size);
1182 if (a_ret || a_size < (int)fp_prp->pdc) {
1183 ECN_DBG_PUT("_ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
1184 goto lb_except;
1185 }
1186 }
1187
1188 return p_blk;
1189
1190lb_except:
1191 /* プロパティ用メモリ解放 */
1192 if (p_blk && !fp_prev_blk)
1193 _ecn_fbs_mbx_rel(p_blk);
1194
1195 return 0; /* 0:NG */
1196}
1197
1198static ER _ecn_tsk_eoj_set_main(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_fromapp, bool_t fa_update,
1199 ECN_FBS_ID fa_fbs_id, ECN_FBS_ID a_fbs_res, ECN_FBS_ID *fa_fbs_anno, int a_count,
1200 int *p_sw_ok);
1201/* プロパティ値書き込み実行 */
1202static ER _ecn_tsk_eoj_set_main(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_fromapp, bool_t fa_update,
1203 ECN_FBS_ID fa_fbs_id, ECN_FBS_ID a_fbs_res, ECN_FBS_ID *fa_fbs_anno, int a_count,
1204 int *p_sw_ok)
1205{
1206 T_ECN_SUB_BLK *p_edt = 0;
1207 T_ECN_PRP a_prp; /* epc+pdc */
1208 const EPRPINIB *a_eprp;
1209 int i, a_ans;
1210 ER a_ret;
1211 uint8_t a_size;
1212 bool_t a_anno = false, a_update;
1213
1214 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc = 0;
1215
1216 for (i = 0; i < a_count; i++) {
1217 /* ECN_FBS_IDからT_ECN_PRP1件とその付随データを抽出し、そのポインタを返す */
1218 p_edt = _ecn_tsk_get_prp_pce(fa_fbs_id, &a_prp, p_edt);
1219 if (!p_edt) {
1220 ECN_DBG_PUT("_ecn_tsk_eoj_set_main(): _ecn_tsk_get_prp_pce() fault.");
1221 goto lb_except;
1222 }
1223
1224 /* プロパティの設定 set_prp(obj, reqp, resp) */
1225 a_size = a_prp.pdc;
1226 /* obj,epcに対応するset関数を呼ぶ */
1227 a_eprp = _ecn_tsk_eoj_get_property(fp_obj, a_prp.epc);
1228 if ((a_eprp != NULL)
1229 && (fa_update || (((a_eprp->eprpatr & EPC_RULE_SET) != 0) || fa_fromapp))) {
1230 a_anno = (fa_eobjatr == EOBJ_LOCAL_NODE) && ((a_eprp->eprpatr & EPC_ANNOUNCE) != 0);
1231 a_update = a_anno;
1232 a_ans = _ecn_tsk_eoj_set_edt(a_eprp, p_edt->payload, a_size, &a_update);
1233 if (a_anno && (a_ans > 0))
1234 a_anno = a_update;
1235 }
1236 else {
1237 a_ans = -1;
1238 }
1239 if (a_ans == a_size) {
1240 ECN_DBG_PUT("_ecn_tsk_eoj_set_edt(0x%06X, 0x%02x, 0x%02X..., %u) ok.",
1241 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1242 a_prp.epc, p_edt->payload[0], a_size);
1243 a_prp.pdc = 0;
1244 } else {
1245 ECN_DBG_PUT("_ecn_tsk_eoj_set_edt(0x%06X, 0x%02x, 0x%02X..., %u) fault.",
1246 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1247 a_prp.epc, p_edt->payload[0], a_size);
1248 *p_sw_ok = 0; /* プロパティ設定失敗 */
1249 /* 応答処理の場合EDTは設定しない */
1250 if (fa_update)
1251 a_prp.pdc = 0;
1252 }
1253
1254 /* 応答電文用メモリにデータ追加(epc,pdcの2byte) */
1255 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, &a_prp, sizeof(a_prp));
1256 if (a_ret) {
1257 ECN_DBG_PUT("_ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
1258 goto lb_except;
1259 }
1260
1261 if (0 < a_prp.pdc) {
1262 /* 応答電文用メモリにデータ追加(edt n-byte) */
1263 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, p_edt->payload, a_prp.pdc);
1264 if (a_ret) {
1265 ECN_DBG_PUT("_ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
1266 goto lb_except;
1267 }
1268 }
1269 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc ++;
1270
1271 /* プロパティ通知ありの場合 */
1272 if (a_anno && (a_ans == a_size)) {
1273 if (fa_fbs_anno->ptr == NULL) {
1274 _ecn_tsk_mk_esv(fa_fbs_anno, (ID)1, (((intptr_t)fp_obj - (intptr_t)eobjinib_table) / sizeof(EPRPINIB)) + 1,
1275 a_prp.epc, 0, NULL, ESV_INF_REQ);
1276 }
1277 else{
1278 ecn_add_edt((T_EDATA *)fa_fbs_anno->ptr, a_prp.epc, 0, 0);
1279 }
1280 }
1281 }
1282 a_ret = E_OK; /* ok */
1283 goto lb_finally;
1284
1285lb_except:
1286 a_ret = E_SYS;
1287
1288lb_finally:
1289 /* プロパティ用メモリ解放 */
1290 if (p_edt)
1291 _ecn_fbs_mbx_rel(p_edt);
1292
1293 return a_ret;
1294}
1295
1296static ER _ecn_tsk_eoj_get_main(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_forward, ATR fa_access,
1297 ECN_FBS_ID fa_fbs_id, ECN_FBS_ID a_fbs_res, int a_count, int *p_sw_ok);
1298/* プロパティ値読み出し実行 */
1299static ER _ecn_tsk_eoj_get_main(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_forward, ATR fa_access,
1300 ECN_FBS_ID fa_fbs_id, ECN_FBS_ID a_fbs_res, int a_count, int *p_sw_ok)
1301{
1302 T_ECN_SUB_BLK *p_edt = 0;
1303 void *p_prp_buf = 0; /* 作業領域 */
1304 const EPRPINIB *a_eprp;
1305 ER a_ret = E_SYS;
1306 T_ECN_PRP a_prp; /* epc+pdc */
1307 int i, a_ans;
1308
1309 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc = 0;
1310
1311 /* 作業領域確保 */
1312 p_prp_buf = _ecn_fbs_mbx_get(ECHONET_MEMPOOL_BLOCK_SIZE);
1313 if (!p_prp_buf) {
1314 ECN_DBG_PUT("_ecn_fbs_mbx_get() result = %d:%s", a_ret, itron_strerror(a_ret));
1315 goto lb_except; /* メモリ不足 */
1316 }
1317
1318 for (i = 0; i < a_count; i++) {
1319 /* ECN_FBS_IDからT_ECN_PRP1件とその付随データを抽出 */
1320 p_edt = _ecn_tsk_get_prp_pce(fa_fbs_id, &a_prp, p_edt);
1321 if (!p_edt) {
1322 ECN_DBG_PUT("_ecn_tsk_eoj_get_main(): _ecn_tsk_get_prp_pce() fault.");
1323 goto lb_except;
1324 }
1325
1326 /* プロパティの取得 get_eprp(obj, reqp, resp, size) */
1327 memset(p_prp_buf, 0, ECHONET_MEMPOOL_BLOCK_SIZE);
1328 /* obj,epcに対応するget関数を呼ぶ */
1329 a_eprp = _ecn_tsk_eoj_get_property(fp_obj, a_prp.epc);
1330 if ((a_eprp != NULL) && (((a_eprp->eprpatr & fa_access) != 0) && (fa_eobjatr == EOBJ_LOCAL_NODE) || fa_forward)) {
1331 a_ans = _ecn_tsk_eoj_get_edt(a_eprp, p_prp_buf, ECHONET_MEMPOOL_BLOCK_SIZE - 1);
1332 }
1333 else {
1334 a_ans = -1;
1335 }
1336 if (0 < a_ans && a_ans <= (int)UINT8_MAX) {
1337 a_prp.pdc = (uint8_t)a_ans;
1338 } else {
1339 *p_sw_ok = 0; /* プロパティ取得失敗 */
1340 a_ans = 0;
1341 a_prp.pdc = 0;
1342 }
1343
1344 /* 応答電文用メモリにデータ追加(epc,pdcの2byte) */
1345 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, &a_prp, sizeof(a_prp));
1346 if (a_ret) {
1347 ECN_DBG_PUT("_ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
1348 goto lb_except;
1349 }
1350 if (0 < a_ans) {
1351 /* 付随データ追加 */
1352 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, p_prp_buf, a_ans);
1353 if (a_ret) {
1354 ECN_DBG_PUT("_ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
1355 goto lb_except;
1356 }
1357 }
1358 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc ++;
1359 }
1360 a_ret = E_OK; /* ok */
1361 goto lb_finally;
1362
1363lb_except:
1364 a_ret = E_SYS;
1365
1366lb_finally:
1367 /* 作業領域解放 */
1368 if (p_prp_buf)
1369 _ecn_fbs_mbx_rel(p_prp_buf);
1370
1371 /* プロパティ用メモリ解放 */
1372 if (p_edt)
1373 _ecn_fbs_mbx_rel(p_edt);
1374
1375 return a_ret;
1376}
1377
1378static ER _ecn_tsk_eoj_res_main(ECN_FBS_ID fa_fbs_id, ECN_FBS_ID a_fbs_res, int a_count, int *p_sw_ok);
1379/* プロパティ値読み出し実行 */
1380static ER _ecn_tsk_eoj_res_main(ECN_FBS_ID fa_fbs_id, ECN_FBS_ID a_fbs_res, int a_count, int *p_sw_ok)
1381{
1382 T_ECN_SUB_BLK *p_edt = 0;
1383 void *p_prp_buf = 0; /* 作業領域 */
1384 ER a_ret = E_SYS;
1385 T_ECN_PRP a_prp; /* epc+pdc */
1386 int i;
1387
1388 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc = 0;
1389
1390 /* 作業領域確保 */
1391 p_prp_buf = _ecn_fbs_mbx_get(ECHONET_MEMPOOL_BLOCK_SIZE);
1392 if (!p_prp_buf) {
1393 ECN_DBG_PUT("_ecn_fbs_mbx_get() result = %d:%s", a_ret, itron_strerror(a_ret));
1394 goto lb_except; /* メモリ不足 */
1395 }
1396
1397 for (i = 0; i < a_count; i++) {
1398 /* ECN_FBS_IDからT_ECN_PRP1件とその付随データを抽出 */
1399 p_edt = _ecn_tsk_get_prp_pce(fa_fbs_id, &a_prp, p_edt);
1400 if (!p_edt) {
1401 ECN_DBG_PUT("_ecn_tsk_eoj_get_main(): _ecn_tsk_get_prp_pce() fault.");
1402 goto lb_except;
1403 }
1404
1405 a_prp.pdc = 0;
1406
1407 /* 応答電文用メモリにデータ追加(epc,pdcの2byte) */
1408 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, &a_prp, sizeof(a_prp));
1409 if (a_ret) {
1410 ECN_DBG_PUT("_ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
1411 goto lb_except;
1412 }
1413 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc++;
1414 }
1415 a_ret = E_OK; /* ok */
1416 goto lb_finally;
1417
1418lb_except:
1419 a_ret = E_SYS;
1420
1421lb_finally:
1422 /* 作業領域解放 */
1423 if (p_prp_buf)
1424 _ecn_fbs_mbx_rel(p_prp_buf);
1425
1426 /* プロパティ用メモリ解放 */
1427 if (p_edt)
1428 _ecn_fbs_mbx_rel(p_edt);
1429
1430 return a_ret;
1431}
1432
1433/* プロパティ値読み飛ばし実行 */
1434static ER _ecn_tsk_eoj_skip_main(const EOBJINIB *fp_obj, ECN_FBS_ID fa_fbs_id,
1435 int a_count);
1436static ER _ecn_tsk_eoj_skip_main(const EOBJINIB *fp_obj, ECN_FBS_ID fa_fbs_id,
1437 int a_count)
1438{
1439 T_ECN_PRP a_prp; /* epc+pdc */
1440 int i, a_size;
1441 ER a_ret;
1442
1443 for (i = 0; i < a_count; i++) {
1444 /* T_ECN_PRP部分(epc,pdc)を読み取る */
1445 a_size = 0;
1446 a_ret = _ecn_fbs_get_data(fa_fbs_id, &a_prp, sizeof(a_prp), &a_size);
1447 if (a_ret || a_size < (int)sizeof(a_prp)) {
1448 ECN_DBG_PUT("_ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
1449 goto lb_except;
1450 }
1451
1452 /* pdc分読み飛ばし */
1453 a_ret = _ecn_fbs_seek_rpos(fa_fbs_id, a_prp.pdc);
1454 if (a_ret) {
1455 ECN_DBG_PUT("_ecn_fbs_seek_rpos() result = %d:%s", a_ret, itron_strerror(a_ret));
1456 goto lb_except;
1457 }
1458 }
1459 a_ret = E_OK; /* ok */
1460 goto lb_finally;
1461
1462lb_except:
1463 a_ret = E_SYS;
1464
1465lb_finally:
1466 return a_ret;
1467}
1468
1469static void _ecn_tsk_mk_rsp_hdr(const EOBJINIB *fp_obj, T_ECN_EDT_HDR *fp_rsp_esv,
1470 T_ECN_EDT_HDR const *fp_req_esv);
1471/* 応答電文設定 */
1472static void _ecn_tsk_mk_rsp_hdr(const EOBJINIB *fp_obj, T_ECN_EDT_HDR *fp_rsp_esv,
1473 T_ECN_EDT_HDR const *fp_req_esv)
1474{
1475 fp_rsp_esv->ecn_hdr.ehd1 = ECN_EDH1_ECHONET_LITE;
1476 fp_rsp_esv->ecn_hdr.ehd2 = ECN_EDH2_FORMAT_1;
1477 fp_rsp_esv->ecn_hdr.tid = fp_req_esv->ecn_hdr.tid;
1478 fp_rsp_esv->edata.seoj.eojx1 = fp_obj->eojx1;
1479 fp_rsp_esv->edata.seoj.eojx2 = fp_obj->eojx2;
1480 fp_rsp_esv->edata.seoj.eojx3 = fp_obj->eojx3;
1481 fp_rsp_esv->edata.deoj = fp_req_esv->edata.seoj;
1482}
1483
1484static void _ecn_tsk_mk_rsp_hdr_res(T_ECN_EDT_HDR *fp_rsp_esv,
1485 T_ECN_EDT_HDR const *fp_req_esv);
1486static void _ecn_tsk_mk_rsp_hdr_res(T_ECN_EDT_HDR *fp_rsp_esv,
1487 T_ECN_EDT_HDR const *fp_req_esv)
1488{
1489 fp_rsp_esv->ecn_hdr.ehd1 = ECN_EDH1_ECHONET_LITE;
1490 fp_rsp_esv->ecn_hdr.ehd2 = ECN_EDH2_FORMAT_1;
1491 fp_rsp_esv->ecn_hdr.tid = fp_req_esv->ecn_hdr.tid;
1492 fp_rsp_esv->edata.seoj = fp_req_esv->edata.deoj;
1493 fp_rsp_esv->edata.deoj = fp_req_esv->edata.seoj;
1494}
1495
1496/* 応答電文用fbs設定 */
1497static void _ecn_tsk_set_rsp_fbs(ECN_FBS_ID fa_rsp_fbs, T_ECN_FST_BLK const *fp_req_ptr);
1498/* 応答電文用fbs設定(sender/targetの設定) */
1499static void _ecn_tsk_set_rsp_fbs(ECN_FBS_ID fa_rsp_fbs, T_ECN_FST_BLK const *fp_req_ptr)
1500{
1501 fa_rsp_fbs.ptr->hdr.type = ECN_MSG_ECHONET;
1502 fa_rsp_fbs.ptr->hdr.sender.id = ENOD_LOCAL_ID;
1503 fa_rsp_fbs.ptr->hdr.target.id = fp_req_ptr->hdr.reply.id;
1504 fa_rsp_fbs.ptr->hdr.reply.id = ENOD_LOCAL_ID;
1505}
1506
1507/* プロパティ値書き込み要求 */
1508static void _ecn_tsk_eoj_set(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_fromapp, bool_t fa_update,
1509 ECN_FBS_ID fa_fbs_id, ECN_SRV_CODE fa_res_esv, ECN_SRV_CODE fa_sna_esv,
1510 ECN_FBS_ID *fa_fbs_anno)
1511{
1512 T_ECN_EDT_HDR const *p_req_esv = &((T_EDATA *)fa_fbs_id.ptr)->hdr;
1513 T_ECN_EDT_HDR a_ecn_hdp;
1514 ECN_FBS_ID a_fbs_res = { 0 };
1515 ER a_ret;
1516 int a_size;
1517 int a_sw_ok = 1;
1518 T_ECN_EOJ eoj;
1519
1520 memset(&a_ecn_hdp, 0, sizeof(a_ecn_hdp));
1521
1522 /* 応答最大サイズの取得 */
1523 a_size = sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY) + sizeof(T_ECN_PRP);
1524
1525 /* 応答電文用メモリの取得 */
1526 a_ret = _ecn_fbs_cre(a_size, &a_fbs_res);
1527 if (a_ret != E_OK || !a_fbs_res.ptr) /* 確保失敗 */
1528 return;
1529
1530 /* 応答電文設定 */
1531 if(p_req_esv->edata.deoj.eojx3 != 0)
1532 _ecn_tsk_mk_rsp_hdr_res(&a_ecn_hdp, p_req_esv);
1533 else
1534 _ecn_tsk_mk_rsp_hdr(fp_obj, &a_ecn_hdp, p_req_esv);
1535
1536 /* 正常時の応答電文がプロパティ値通知応答の場合 */
1537 if (fa_res_esv == ESV_INFC_RES) {
1538 /* 送信元と宛先を入れ替え */
1539 eoj = a_ecn_hdp.edata.seoj;
1540 a_ecn_hdp.edata.seoj = a_ecn_hdp.edata.deoj;
1541 a_ecn_hdp.edata.deoj = eoj;
1542 }
1543
1544 f_put_fbs_eoj("_ecn_tsk_eoj_set", "fa_fbs_id", fa_fbs_id); /* s/deoj デバッグ出力 */
1545
1546 /* 応答電文用メモリにデータ追加 */
1547 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, &a_ecn_hdp,
1548 sizeof(a_ecn_hdp.ecn_hdr) + sizeof(a_ecn_hdp.edata));
1549 if (a_ret)
1550 goto lb_except;
1551
1552 /* payload先頭のT_ECN_HDR(ecn_hdr), T_ECN_EDATA_BODY(edata)を読み飛ばす */
1553 a_ret = _ecn_fbs_set_rpos(fa_fbs_id, offsetof(T_ECN_EDT_HDR, ecn_prp));
1554 if (a_ret)
1555 goto lb_except;
1556
1557 /* 応答電文用fbs設定 */
1558 _ecn_tsk_set_rsp_fbs(a_fbs_res, fa_fbs_id.ptr);
1559
1560 /* プロパティ値書き込み実行 */
1561 a_ret = _ecn_tsk_eoj_set_main(fp_obj, fa_eobjatr, fa_fromapp, fa_update, fa_fbs_id, a_fbs_res,
1562 fa_fbs_anno, p_req_esv->edata.opc, &a_sw_ok);
1563 if (a_ret)
1564 goto lb_except;
1565
1566 /* 応答要の場合 */
1567 if (a_sw_ok) {
1568 if (!fa_res_esv) {
1569 /* 応答不要の場合 */
1570 _ecn_fbs_del(a_fbs_res);
1571 goto lb_finally;
1572 }
1573 /* 設定処理成功 */
1574 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.esv = fa_res_esv;
1575 } else {
1576 if (!fa_sna_esv) {
1577 /* 応答不要の場合 */
1578 _ecn_fbs_del(a_fbs_res);
1579 goto lb_finally;
1580 }
1581 /* 設定処理失敗 */
1582 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.esv = fa_sna_esv;
1583 }
1584 /* 応答送信 */
1585 a_ret = _ecn_tsk_snd_mbx(a_fbs_res, false);
1586 if (a_ret == E_OK)
1587 goto lb_finally;
1588
1589lb_except:
1590 /* データ送信失敗したら領域解放 */
1591 if (a_fbs_res.ptr)
1592 _ecn_fbs_del(a_fbs_res);
1593
1594lb_finally:
1595 return;
1596}
1597
1598/* プロパティ値読み出し要求 */
1599static void _ecn_tsk_eoj_get(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_forward, ATR fa_access,
1600 ECN_FBS_ID fa_fbs_id, ECN_SRV_CODE fa_res_esv, ECN_SRV_CODE fa_sna_esv)
1601{
1602 T_ECN_EDT_HDR const *p_req_esv = &((T_EDATA *)fa_fbs_id.ptr)->hdr;
1603 T_ECN_EDT_HDR a_ecn_hdp;
1604 ECN_FBS_ID a_fbs_res = { 0 };
1605 ER a_ret;
1606 int a_size;
1607 int a_sw_ok = 1;
1608
1609 memset(&a_ecn_hdp, 0, sizeof(a_ecn_hdp));
1610
1611 /* 初期取得サイズ */
1612 a_size = sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY) + sizeof(T_ECN_PRP);
1613
1614 /* 応答電文用メモリの取得 */
1615 a_ret = _ecn_fbs_cre(a_size, &a_fbs_res);
1616 if (a_ret != E_OK || !a_fbs_res.ptr) { /* 確保失敗 */
1617 ECN_DBG_PUT("_ecn_fbs_cre() result = %d:%s", a_ret, itron_strerror(a_ret));
1618 goto lb_finally;
1619 }
1620
1621 /* 応答電文設定 */
1622 if(p_req_esv->edata.deoj.eojx3 != 0)
1623 _ecn_tsk_mk_rsp_hdr_res(&a_ecn_hdp, p_req_esv);
1624 else
1625 _ecn_tsk_mk_rsp_hdr(fp_obj, &a_ecn_hdp, p_req_esv);
1626
1627 f_put_fbs_eoj("_ecn_tsk_eoj_get", "fa_fbs_id", fa_fbs_id); /* s/deoj デバッグ出力 */
1628
1629 /* 応答電文用メモリにデータ追加 */
1630 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, &a_ecn_hdp,
1631 sizeof(a_ecn_hdp.ecn_hdr) + sizeof(a_ecn_hdp.edata));
1632 if (a_ret) {
1633 ECN_DBG_PUT("_ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
1634 goto lb_except;
1635 }
1636
1637 /* payload先頭のT_ECN_HDR(ecn_hdr), T_ECN_EDATA_BODY(edata)を読み飛ばす */
1638 a_ret = _ecn_fbs_set_rpos(fa_fbs_id, offsetof(T_ECN_EDT_HDR, ecn_prp));
1639 if (a_ret) {
1640 ECN_DBG_PUT("_ecn_fbs_set_rpos() result = %d:%s", a_ret, itron_strerror(a_ret));
1641 goto lb_except;
1642 }
1643
1644 /* 応答電文用fbs設定 */
1645 _ecn_tsk_set_rsp_fbs(a_fbs_res, fa_fbs_id.ptr);
1646
1647 /* プロパティ値読み込み実行 */
1648 a_ret = _ecn_tsk_eoj_get_main(fp_obj, fa_eobjatr, fa_forward, fa_access, fa_fbs_id, a_fbs_res,
1649 ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.opc, &a_sw_ok);
1650 if (a_ret) {
1651 ECN_DBG_PUT("_ecn_tsk_eoj_get_main() result = %d:%s", a_ret, itron_strerror(a_ret));
1652 goto lb_except;
1653 }
1654
1655 if (a_sw_ok) {
1656 if (!fa_res_esv) {
1657 /* 応答不要の場合 */
1658 _ecn_fbs_del(a_fbs_res);
1659 goto lb_finally;
1660 }
1661 /* 設定処理成功 */
1662 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.esv = fa_res_esv;
1663 } else {
1664 if (!fa_sna_esv) {
1665 /* 応答不要の場合 */
1666 _ecn_fbs_del(a_fbs_res);
1667 goto lb_finally;
1668 }
1669 /* 設定処理失敗 */
1670 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.esv = fa_sna_esv;
1671
1672 /* 不可応答の場合は個別送信する */
1673 if (a_fbs_res.ptr->hdr.target.id == ENOD_MULTICAST_ID) {
1674 a_fbs_res.ptr->hdr.target.id = fa_fbs_id.ptr->hdr.sender.id;
1675 }
1676 }
1677 /* 応答送信 */
1678 a_ret = _ecn_tsk_snd_mbx(a_fbs_res, false);
1679 if (a_ret != E_OK) {
1680 ECN_DBG_PUT("_ecn_tsk_snd_mbx() result = %d:%s", a_ret, itron_strerror(a_ret));
1681 goto lb_except;
1682 }
1683 goto lb_finally;
1684
1685lb_except:
1686 /* データ送信失敗したら領域解放 */
1687 if (a_fbs_res.ptr)
1688 _ecn_fbs_del(a_fbs_res);
1689
1690lb_finally:
1691 return;
1692}
1693
1694/* プロパティ値読み出し要求 */
1695static void _ecn_tsk_eoj_res(ECN_FBS_ID fa_fbs_id, ECN_SRV_CODE fa_res_esv,
1696 ECN_SRV_CODE fa_sna_esv)
1697{
1698 T_ECN_EDT_HDR const *p_req_esv = &((T_EDATA *)fa_fbs_id.ptr)->hdr;
1699 T_ECN_EDT_HDR a_ecn_hdp;
1700 ECN_FBS_ID a_fbs_res = { 0 };
1701 ER a_ret;
1702 int a_size;
1703 int a_sw_ok = 1;
1704
1705 memset(&a_ecn_hdp, 0, sizeof(a_ecn_hdp));
1706
1707 /* 初期取得サイズ */
1708 a_size = sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY) + sizeof(T_ECN_PRP);
1709
1710 /* 応答電文用メモリの取得 */
1711 a_ret = _ecn_fbs_cre(a_size, &a_fbs_res);
1712 if (a_ret != E_OK || !a_fbs_res.ptr) { /* 確保失敗 */
1713 ECN_DBG_PUT("_ecn_fbs_cre() result = %d:%s", a_ret, itron_strerror(a_ret));
1714 goto lb_finally;
1715 }
1716
1717 /* 応答電文設定 */
1718 _ecn_tsk_mk_rsp_hdr_res(&a_ecn_hdp, p_req_esv);
1719
1720 f_put_fbs_eoj("_ecn_tsk_eoj_res", "fa_fbs_id", fa_fbs_id); /* s/deoj デバッグ出力 */
1721
1722 /* 応答電文用メモリにデータ追加 */
1723 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, &a_ecn_hdp,
1724 sizeof(a_ecn_hdp.ecn_hdr) + sizeof(a_ecn_hdp.edata));
1725 if (a_ret) {
1726 ECN_DBG_PUT("_ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
1727 goto lb_except;
1728 }
1729
1730 /* payload先頭のT_ECN_HDR(ecn_hdr), T_ECN_EDATA_BODY(edata)を読み飛ばす */
1731 a_ret = _ecn_fbs_set_rpos(fa_fbs_id, offsetof(T_ECN_EDT_HDR, ecn_prp));
1732 if (a_ret) {
1733 ECN_DBG_PUT("_ecn_fbs_set_rpos() result = %d:%s", a_ret, itron_strerror(a_ret));
1734 goto lb_except;
1735 }
1736
1737 /* 応答電文用fbs設定 */
1738 _ecn_tsk_set_rsp_fbs(a_fbs_res, fa_fbs_id.ptr);
1739
1740 /* プロパティ値読み込み実行 */
1741 a_ret = _ecn_tsk_eoj_res_main(fa_fbs_id, a_fbs_res,
1742 ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.opc, &a_sw_ok);
1743 if (a_ret) {
1744 ECN_DBG_PUT("_ecn_tsk_eoj_res_main() result = %d:%s", a_ret, itron_strerror(a_ret));
1745 goto lb_except;
1746 }
1747
1748 if (a_sw_ok) {
1749 if (!fa_res_esv) {
1750 /* 応答不要の場合 */
1751 _ecn_fbs_del(a_fbs_res);
1752 goto lb_finally;
1753 }
1754 /* 設定処理成功 */
1755 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.esv = fa_res_esv;
1756 } else {
1757 if (!fa_sna_esv) {
1758 /* 応答不要の場合 */
1759 _ecn_fbs_del(a_fbs_res);
1760 goto lb_finally;
1761 }
1762 /* 設定処理失敗 */
1763 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.esv = fa_sna_esv;
1764 }
1765 /* 応答送信 */
1766 a_ret = _ecn_tsk_snd_mbx(a_fbs_res, false);
1767 if (a_ret != E_OK) {
1768 ECN_DBG_PUT("_ecn_tsk_snd_mbx() result = %d:%s", a_ret, itron_strerror(a_ret));
1769 goto lb_except;
1770 }
1771 goto lb_finally;
1772
1773lb_except:
1774 /* データ送信失敗したら領域解放 */
1775 if (a_fbs_res.ptr)
1776 _ecn_fbs_del(a_fbs_res);
1777
1778lb_finally:
1779 return;
1780}
1781
1782static void _ecn_tsk_eoj_set_get(const EOBJINIB *fp_obj, ATR fa_eobjatr, bool_t fa_fromapp,
1783 ECN_FBS_ID fa_fbs_id, ECN_SRV_CODE fa_res_esv, ECN_SRV_CODE fa_sna_esv,
1784 ECN_FBS_ID *fa_fbs_anno)
1785{
1786 T_ECN_EDT_HDR const *p_req_esv = &((T_EDATA *)fa_fbs_id.ptr)->hdr;
1787 T_ECN_EDT_HDR a_ecn_hdp;
1788 ECN_FBS_ID a_fbs_res = { 0 };
1789 int a_rdprp_wrpos; /* プロパティ読み込み件数書き込み時のヘッド位置 */
1790 ER a_ret;
1791 int i, a_size, a_rdlen;
1792 int a_sw_ok = 1;
1793 int a_count = ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.opc; /* 処理プロパティ数 */
1794
1795 memset(&a_ecn_hdp, 0, sizeof(a_ecn_hdp));
1796
1797 ECN_DBG_PUT("_ecn_tsk_eoj_set_get() eoj:%06X",
1798 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3);
1799
1800 /* 初期取得サイズ */
1801 a_size = sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY) + sizeof(T_ECN_PRP);
1802
1803 /* 応答電文用メモリの取得 */
1804 a_ret = _ecn_fbs_cre(a_size, &a_fbs_res);
1805 if (a_ret != E_OK || !a_fbs_res.ptr) /* 確保失敗 */
1806 goto lb_finally;
1807
1808 /* 応答電文設定 */
1809 if(p_req_esv->edata.deoj.eojx3 != 0)
1810 _ecn_tsk_mk_rsp_hdr_res(&a_ecn_hdp, p_req_esv);
1811 else
1812 _ecn_tsk_mk_rsp_hdr(fp_obj, &a_ecn_hdp, p_req_esv);
1813 a_size -= sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY);
1814
1815 f_put_fbs_eoj("_ecn_tsk_eoj_set_get", "fa_fbs_id", fa_fbs_id); /* s/deoj デバッグ出力 */
1816
1817 /* 応答電文用メモリにデータ追加 */
1818 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, &a_ecn_hdp,
1819 sizeof(a_ecn_hdp.ecn_hdr) + sizeof(a_ecn_hdp.edata));
1820 if (a_ret)
1821 goto lb_except;
1822
1823 /* payload先頭のT_ECN_HDR(ecn_hdr), T_ECN_EDATA_BODY(edata)を読み飛ばす */
1824 a_ret = _ecn_fbs_set_rpos(fa_fbs_id, offsetof(T_ECN_EDT_HDR, ecn_prp));
1825 if (a_ret)
1826 goto lb_except;
1827
1828 /* 応答電文用fbs設定 */
1829 _ecn_tsk_set_rsp_fbs(a_fbs_res, fa_fbs_id.ptr);
1830
1831 /* プロパティ値書き込み実行 */
1832 a_ret = _ecn_tsk_eoj_set_main(fp_obj, fa_eobjatr, fa_fromapp, false, fa_fbs_id, a_fbs_res,
1833 fa_fbs_anno, a_count, &a_sw_ok);
1834 if (a_ret) {
1835 syslog(LOG_WARNING, "_ecn_tsk_eoj_set_get() eoj:%06X _ecn_tsk_eoj_set_main() fault. result = %d",
1836 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1837 a_ret);
1838 goto lb_except;
1839 }
1840 ECN_DBG_PUT("_ecn_tsk_eoj_set_get() eoj:%06X _ecn_tsk_eoj_set_main() ok sw_ok:%s",
1841 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1842 (a_sw_ok ? "true" : "false"));
1843
1844 /* 次の件数を読み取る(1byte) */
1845 /* → ECHONET-Lite_Ver.1.10_02.pdf p.40 [OPCGet] */
1846 a_rdlen = i = 0;
1847 a_ret = _ecn_fbs_get_data(fa_fbs_id, &i, 1, &a_rdlen);
1848 if (a_ret < 0 || a_rdlen < 1)
1849 goto lb_except; /* NG */
1850 a_count = *(uint8_t *)&i;
1851
1852 /* プロパティ読み込み件数書き込み時のヘッド情報を記録 */
1853 a_rdprp_wrpos = _ecn_fbs_get_datalen(a_fbs_res);
1854
1855 /* 応答電文用メモリにデータ追加 (OPCGet 1byte) */
1856 a_ret = _ecn_fbs_add_data_ex(a_fbs_res, &i, 1);
1857 if (a_ret)
1858 goto lb_except;
1859
1860 /* この時点での応答電文中プロパティ件数を記録 */
1861 i = ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc;
1862 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc = 0;
1863
1864 /* プロパティ値読み込み実行 */
1865 a_ret = _ecn_tsk_eoj_get_main(fp_obj, fa_eobjatr, false, EPC_RULE_GET, fa_fbs_id, a_fbs_res,
1866 a_count, &a_sw_ok);
1867 if (a_ret) {
1868 syslog(LOG_WARNING, "_ecn_tsk_eoj_set_get() eoj:%06X _ecn_tsk_eoj_get_main() fault. result = %d",
1869 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1870 a_ret);
1871 goto lb_except;
1872 }
1873 ECN_DBG_PUT("_ecn_tsk_eoj_set_get() eoj:%06X _ecn_tsk_eoj_get_main() ok sw_ok:%s",
1874 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1875 (a_sw_ok ? "true" : "false"));
1876
1877 /* プロパティ読み込み件数書き込み時のヘッド情報で、読み出し件数を記録 */
1878 _ecn_fbs_poke(a_fbs_res, a_rdprp_wrpos, ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc);
1879
1880 /* 記録しておいたプロパティ件数(書き込み件数)を書き戻す */
1881 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.opc = (uint8_t)i;
1882
1883 /* 応答要の場合 */
1884 if (a_sw_ok) {
1885 /* 設定処理成功 */
1886 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.esv = fa_res_esv;
1887 } else {
1888 /* 設定処理失敗 */
1889 ((T_EDATA *)a_fbs_res.ptr)->hdr.edata.esv = fa_sna_esv;
1890 }
1891 /* 応答送信 */
1892 a_ret = _ecn_tsk_snd_mbx(a_fbs_res, false);
1893 if (a_ret == E_OK)
1894 goto lb_finally;
1895
1896lb_except:
1897 /* データ送信失敗したら領域解放 */
1898 if (a_fbs_res.ptr)
1899 _ecn_fbs_del(a_fbs_res);
1900
1901lb_finally:
1902 return;
1903}
1904
1905static void _ecn_tsk_eoj_set_get_res(const EOBJINIB *fp_obj, ATR fa_eobjatr,
1906 bool_t fa_fromapp, ECN_FBS_ID fa_fbs_id, ECN_FBS_ID *fa_fbs_anno)
1907{
1908 T_ECN_EDT_HDR const *p_req_esv = &((T_EDATA *)fa_fbs_id.ptr)->hdr;
1909 T_ECN_EDT_HDR a_ecn_hdp;
1910 ECN_FBS_ID a_fbs_dmy = { 0 };
1911 ER a_ret;
1912 int i, a_size, a_rdlen;
1913 int a_sw_ok = 1;
1914 int a_count = ((T_EDATA *)fa_fbs_id.ptr)->hdr.edata.opc; /* 処理プロパティ数 */
1915
1916 memset(&a_ecn_hdp, 0, sizeof(a_ecn_hdp));
1917
1918 ECN_DBG_PUT("_ecn_tsk_eoj_set_get_res() eoj:%06X",
1919 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3);
1920
1921 /* 初期取得サイズ */
1922 a_size = sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY) + sizeof(T_ECN_PRP);
1923
1924 /* 応答電文用メモリ(ダミー)の取得 */
1925 a_ret = _ecn_fbs_cre(a_size, &a_fbs_dmy);
1926 if (a_ret != E_OK || !a_fbs_dmy.ptr) /* 確保失敗 */
1927 goto lb_finally;
1928
1929 /* 応答電文設定 */
1930 _ecn_tsk_mk_rsp_hdr_res(&a_ecn_hdp, p_req_esv);
1931 a_size -= sizeof(T_ECN_HDR) + sizeof(T_ECN_EDATA_BODY);
1932
1933 /* payload先頭のT_ECN_HDR(ecn_hdr), T_ECN_EDATA_BODY(edata)を読み飛ばす */
1934 a_ret = _ecn_fbs_set_rpos(fa_fbs_id, offsetof(T_ECN_EDT_HDR, ecn_prp));
1935 if (a_ret)
1936 goto lb_except;
1937
1938 /* プロパティ値書き込み応答読み飛ばし実行 */
1939 a_ret = _ecn_tsk_eoj_skip_main(fp_obj, fa_fbs_id, a_count);
1940 if (a_ret) {
1941 syslog(LOG_WARNING, "_ecn_tsk_eoj_set_get_res() eoj:%06X _ecn_tsk_eoj_set_main() fault. result = %d",
1942 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1943 a_ret);
1944 goto lb_except;
1945 }
1946 ECN_DBG_PUT("_ecn_tsk_eoj_set_get_res() eoj:%06X _ecn_tsk_eoj_set_main() ok sw_ok:%s",
1947 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1948 (a_sw_ok ? "true" : "false"));
1949
1950 /* 次の件数を読み取る(1byte) */
1951 /* → ECHONET-Lite_Ver.1.10_02.pdf p.40 [OPCGet] */
1952 a_rdlen = i = 0;
1953 a_ret = _ecn_fbs_get_data(fa_fbs_id, &i, 1, &a_rdlen);
1954 if (a_ret < 0 || a_rdlen < 1)
1955 goto lb_except; /* NG */
1956 a_count = *(uint8_t *)&i;
1957
1958 /* プロパティ値読み出し応答の書き込み実行 */
1959 a_ret = _ecn_tsk_eoj_set_main(fp_obj, fa_eobjatr, fa_fromapp, true, fa_fbs_id, a_fbs_dmy,
1960 fa_fbs_anno, a_count, &a_sw_ok);
1961 if (a_ret) {
1962 syslog(LOG_WARNING, "_ecn_tsk_eoj_set_get_res() eoj:%06X _ecn_tsk_eoj_get_main() fault. result = %d",
1963 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1964 a_ret);
1965 goto lb_except;
1966 }
1967 ECN_DBG_PUT("_ecn_tsk_eoj_set_get_res() eoj:%06X _ecn_tsk_eoj_get_main() ok sw_ok:%s",
1968 fp_obj->eojx1 << 16 | fp_obj->eojx2 << 8 | fp_obj->eojx3,
1969 (a_sw_ok ? "true" : "false"));
1970
1971 goto lb_finally;
1972
1973lb_except:
1974 /* データ送信失敗したら領域解放 */
1975 if (a_fbs_dmy.ptr)
1976 _ecn_fbs_del(a_fbs_dmy);
1977
1978lb_finally:
1979 return;
1980}
1981
1982/*
1983 * 応答電文待ちの割り込み電文作成
1984 */
1985ER _ecn_mk_brk_wai(ECN_FBS_ID *pk_fbs_id, const void *p_dat, size_t fa_size)
1986{
1987 ER a_ret;
1988 ECN_FBS_ID a_fbs_id = { 0 }; /* 要求電文用メモリ */
1989
1990 if (!pk_fbs_id)
1991 return E_PAR;
1992 *pk_fbs_id = a_fbs_id;
1993 if (sizeof(a_fbs_id.ptr->payload) <= fa_size)
1994 return E_PAR; /* 付随データが大きすぎる */
1995 if (!p_dat && 0 < fa_size)
1996 return E_PAR; /* 付随データサイズが1以上なのにデータポインタがNULL */
1997
1998 /* 要求電文用メモリの取得 */
1999 a_ret = _ecn_fbs_cre((0 < fa_size ? fa_size : 1), &a_fbs_id);
2000 if (a_ret != E_OK || !a_fbs_id.ptr) { /* 確保失敗 */
2001 syslog(LOG_WARNING, "_ecn_fbs_cre(%d) result = %d:%s", fa_size, a_ret, itron_strerror(a_ret));
2002 return a_ret;
2003 }
2004
2005 /* 要求電文設定 */
2006 a_fbs_id.ptr->hdr.type = ECN_MSG_USER_BREAK;
2007 a_fbs_id.ptr->hdr.sender.id = ENOD_API_ID;
2008 a_fbs_id.ptr->hdr.target.id = ENOD_API_ID;
2009 a_fbs_id.ptr->hdr.reply.id = ENOD_API_ID;
2010
2011 if (0 < fa_size && p_dat) {
2012 /* 付随データ追加 */
2013 a_ret = _ecn_fbs_add_data_ex(a_fbs_id, p_dat, fa_size);
2014 if (a_ret) {
2015 syslog(LOG_WARNING, "_ecn_fbs_add_data_ex(*, dat, %lu) result = %d:%s",
2016 fa_size,
2017 a_ret, itron_strerror(a_ret));
2018 goto lb_except;
2019 }
2020 }
2021
2022 *pk_fbs_id = a_fbs_id;
2023
2024 /* 正常終了 */
2025 return a_ret;
2026
2027lb_except:
2028 /* データ作成失敗したら領域解放 */
2029 if (a_fbs_id.ptr)
2030 _ecn_fbs_del(a_fbs_id);
2031
2032 return a_ret;
2033}
2034
2035/* 応答電文用fbs設定(sender/targetの設定) */
2036ER _ecn_tsk_cre_req_fbs(ID sender, uint8_t cmd, ECN_FBS_ID *pk_req)
2037{
2038 ER ret;
2039 ECN_FBS_ID req;
2040
2041 ret = _ecn_fbs_cre(1, &req);
2042 if (ret != E_OK) {
2043 ECN_DBG_PUT("_ecn_tsk_cre_req_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
2044 return ret;
2045 }
2046
2047 ret = _ecn_fbs_add_data(req, &cmd, sizeof(cmd));
2048 if (ret != E_OK) {
2049 _ecn_fbs_del(req);
2050 ECN_DBG_PUT("_ecn_tsk_cre_req_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
2051 return ret;
2052 }
2053
2054 req.ptr->hdr.type = ECN_MSG_INTERNAL;
2055 req.ptr->hdr.sender.mbxid = sender;
2056 req.ptr->hdr.target.mbxid = ecn_svc_mailboxid;
2057 req.ptr->hdr.reply.mbxid = sender;
2058
2059 *pk_req = req;
2060
2061 return E_OK;
2062}
2063
2064/* 応答電文用fbs設定(sender/targetの設定) */
2065ER _ecn_tsk_cre_res_fbs(ECN_FBS_ID req, uint8_t cmd, ECN_FBS_ID *pk_res)
2066{
2067 ER ret;
2068 ECN_FBS_ID res;
2069
2070 ret = _ecn_fbs_cre(1, &res);
2071 if (ret != E_OK) {
2072 ECN_DBG_PUT("_ecn_tsk_cre_res_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
2073 return ret;
2074 }
2075
2076 ret = _ecn_fbs_add_data(res, &cmd, sizeof(cmd));
2077 if (ret != E_OK) {
2078 _ecn_fbs_del(res);
2079 ECN_DBG_PUT("_ecn_tsk_cre_res_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
2080 return ret;
2081 }
2082
2083 res.ptr->hdr.type = ECN_MSG_INTERNAL;
2084 res.ptr->hdr.sender.mbxid = ecn_svc_mailboxid;
2085 res.ptr->hdr.target.mbxid = req.ptr->hdr.reply.mbxid;
2086 res.ptr->hdr.reply.mbxid = ecn_svc_mailboxid;
2087
2088 *pk_res = res;
2089
2090 return E_OK;
2091}
Note: See TracBrowser for help on using the repository browser.