33892155018f622d34d743daa201c325328c7237
[platform/core/connectivity/zigbee-manager.git] / zigbee-daemon / zigbee-interface / src / zigbee_service_dbus_interface_custom.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Contact: Suresh Kumar N (suresh.n@samsung.com)
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include "zigbee_service_interface_common.h"
20
21 #include <zblib_driver_custom.h>
22
23 static void *_service_interface_ref_zigbee_custom(
24         ZigBeeServiceInterface *service_interface)
25 {
26         ZigbeeObjectSkeleton *zigbee_object = NULL;
27         ZigbeeCustomData_t *custom_data = NULL;
28         ZigbeeCustom *custom_object = NULL;
29
30         custom_data = (ZigbeeCustomData_t *)zblib_service_interface_ref_user_data(service_interface);
31         if (NULL == custom_data) {
32                 Z_LOGE("D-BUS service interface custom_data is NULL!");
33                 return NULL;
34         }
35
36         /* Get zigbee object */
37         zigbee_object = g_hash_table_lookup(custom_data->objects, ZIGBEE_SERVICE_PATH);
38         if (NULL == zigbee_object) {
39                 Z_LOGW("Cannot find ZigBee D-BUS interface object!", zigbee_object);
40                 return NULL;
41         }
42
43         custom_object = zigbee_object_get_custom(ZIGBEE_OBJECT(zigbee_object));
44         return custom_object;
45 }
46
47 static void on_custom_aps_send_resp(ZigBeeServiceInterface *service_interface,
48         guint request_id, gpointer resp_data, guint resp_data_len, gpointer resp_cb_data)
49 {
50         ZigbeeServiceInterfaceRespCbData_t *cb_data =
51                 (ZigbeeServiceInterfaceRespCbData_t *)resp_cb_data;
52
53         ZigbeeCustom *custom_object = NULL;
54         GDBusMethodInvocation *invocation = NULL;
55
56         ZigbeeGeneralResp_t *payload = (ZigbeeGeneralResp_t *)resp_data;
57
58         NOT_USED(service_interface);
59         NOT_USED(request_id);
60
61         if (NULL == resp_data || 0 == resp_data_len) {
62                 Z_LOGE("resp_data=%p or resp_data_len=%d is null", resp_data, resp_data_len);
63                 g_free(cb_data);
64                 return;
65         }
66
67         custom_object = zigbee_service_dbus_interface_ref_interface_object(cb_data);
68         zblib_check_null_free_and_ret("custom_object", custom_object, cb_data);
69
70         invocation = zigbee_service_dbus_interface_ref_invocation(cb_data);
71         zblib_check_null_free_and_ret("invocation", invocation, cb_data);
72
73         zigbee_custom_complete_aps_send(custom_object, invocation, payload->result);
74
75         g_free(cb_data);
76 }
77
78 static gboolean on_custom_aps_send(ZigbeeCustom *custom_object,
79         GDBusMethodInvocation *invocation,
80         gshort node_id,
81         gchar aps_frame_ctrl,
82         gchar src_ep,
83         gchar dest_ep,
84         gshort cluster_id,
85         gshort profile_id,
86         gchar zcl_frame_ctrl,
87         gshort mfg_code,
88         gchar cmd_id,
89         gshort payload_len,
90         GVariant *payload,
91         gpointer user_data)
92 {
93         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
94         ZigbeeCustomApsSend_t req;
95         ZigbeeServiceInterfaceRespCbData_t *resp_cb_data = NULL;
96
97         GVariantIter *iter = NULL;
98         guint i = 0;
99
100         gboolean ret;
101
102         memset(&req, 0x0, sizeof(ZigbeeCustomApsSend_t));
103
104         /* Update request structure */
105         req.node_id = node_id;
106         req.aps_frame_ctrl = aps_frame_ctrl;
107         req.src_ep = src_ep;
108         req.dest_ep = dest_ep;
109         req.cluster_id = cluster_id;
110         req.profile_id = profile_id;
111         req.zcl_frame_ctrl = zcl_frame_ctrl;
112         req.mfg_code = mfg_code;
113         req.cmd_id = cmd_id;
114         req.payload_len = payload_len;
115         g_variant_get(payload, "a(y)", &iter);
116         while (g_variant_iter_loop(iter, "(y)", req.payload[i])) {
117                 i++;
118                 if (i >= ZIGBEE_CUSTOM_SEND_PAYLOAD_LEN)
119                         break;
120         }
121
122         /* Allocate response callback data */
123         resp_cb_data =
124                 zigbee_service_dbus_interface_create_resp_cb_data(custom_object,
125                         invocation, NULL, 0);
126         if (NULL == resp_cb_data) {
127                 Z_LOGE("zigbee_service_dbus_interface_create_resp_cb_data failed!");
128
129                 /* Send failure response */
130                 ZIGBEE_DBUS_FAIL_RESPONSE(invocation, ZIGBEE_DBUS_DEFAULT_REQ_FAILED_MSG);
131
132                 return TRUE;
133         }
134
135         /* Dispatch request */
136         ret = zigbee_service_dbus_interface_dispatch_request(service_interface,
137                 ZBLIB_DRIVER_TYPE_CUSTOM,
138                 ZBLIB_CUSTOM_OPS_APS_SEND,
139                 &req, sizeof(req),
140                 on_custom_aps_send_resp, resp_cb_data);
141         if (FALSE == ret) {
142                 Z_LOGE("zigbee_service_dbus_interface_dispatch_request failed!");
143
144                 /* Free response callback data */
145                 zigbee_service_dbus_interface_destroy_resp_cb_data(resp_cb_data);
146
147                 /* Send failure response */
148                 ZIGBEE_DBUS_FAIL_RESPONSE(invocation, ZIGBEE_DBUS_DEFAULT_REQ_FAILED_MSG);
149
150                 return TRUE;
151         }
152
153         return TRUE;
154 }
155
156 static void on_custom_zcl_send_resp(ZigBeeServiceInterface *service_interface,
157         guint request_id, gpointer resp_data, guint resp_data_len, gpointer resp_cb_data)
158 {
159         ZigbeeServiceInterfaceRespCbData_t *cb_data =
160                 (ZigbeeServiceInterfaceRespCbData_t *)resp_cb_data;
161
162         ZigbeeCustom *custom_object = NULL;
163         GDBusMethodInvocation *invocation = NULL;
164
165         ZigbeeGeneralResp_t *payload = (ZigbeeGeneralResp_t *)resp_data;
166
167         NOT_USED(service_interface);
168         NOT_USED(request_id);
169
170         if (NULL == resp_data || 0 == resp_data_len) {
171                 Z_LOGE("resp_data=%p or resp_data_len=%d is null", resp_data, resp_data_len);
172                 g_free(cb_data);
173                 return;
174         }
175
176         custom_object = zigbee_service_dbus_interface_ref_interface_object(cb_data);
177         zblib_check_null_free_and_ret("custom_object", custom_object, cb_data);
178
179         invocation = zigbee_service_dbus_interface_ref_invocation(cb_data);
180         zblib_check_null_free_and_ret("invocation", invocation, cb_data);
181
182         zigbee_custom_complete_zcl_send(custom_object, invocation, payload->result);
183
184         g_free(cb_data);
185 }
186
187 static gboolean on_custom_zcl_send(ZigbeeCustom *custom_object,
188         GDBusMethodInvocation *invocation,
189         gshort node_id,
190         gchar src_ep,
191         gchar dest_ep,
192         gshort cluster_id,
193         gchar zcl_frame_ctrl,
194         gchar cmd_id,
195         gshort payload_len,
196         GVariant *payload,
197         gpointer user_data)
198 {
199         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
200         ZigbeeCustomZclSend_t req;
201         ZigbeeServiceInterfaceRespCbData_t *resp_cb_data = NULL;
202
203         GVariantIter *iter = NULL;
204         guint i = 0;
205
206         gboolean ret;
207
208         memset(&req, 0x0, sizeof(ZigbeeCustomZclSend_t));
209
210         /* Update request structure */
211         req.node_id = node_id;
212         req.src_ep = src_ep;
213         req.dest_ep = dest_ep;
214         req.cluster_id = cluster_id;
215         req.zcl_frame_ctrl = zcl_frame_ctrl;
216         req.cmd_id = cmd_id;
217         req.payload_len = payload_len;
218         g_variant_get(payload, "a(y)", &iter);
219         while (g_variant_iter_loop(iter, "(y)", req.payload[i])) {
220                 i++;
221                 if (i >= ZIGBEE_CUSTOM_SEND_PAYLOAD_LEN)
222                         break;
223         }
224
225         /* Allocate response callback data */
226         resp_cb_data =
227                 zigbee_service_dbus_interface_create_resp_cb_data(custom_object,
228                         invocation, NULL, 0);
229         if (NULL == resp_cb_data) {
230                 Z_LOGE("zigbee_service_dbus_interface_create_resp_cb_data failed!");
231
232                 /* Send failure response */
233                 ZIGBEE_DBUS_FAIL_RESPONSE(invocation, ZIGBEE_DBUS_DEFAULT_REQ_FAILED_MSG);
234
235                 return TRUE;
236         }
237
238         /* Dispatch request */
239         ret = zigbee_service_dbus_interface_dispatch_request(service_interface,
240                 ZBLIB_DRIVER_TYPE_CUSTOM,
241                 ZBLIB_CUSTOM_OPS_ZCL_SEND,
242                 &req, sizeof(req),
243                 on_custom_zcl_send_resp, resp_cb_data);
244         if (FALSE == ret) {
245                 Z_LOGE("zigbee_service_dbus_interface_dispatch_request failed!");
246
247                 /* Free response callback data */
248                 zigbee_service_dbus_interface_destroy_resp_cb_data(resp_cb_data);
249
250                 /* Send failure response */
251                 ZIGBEE_DBUS_FAIL_RESPONSE(invocation, ZIGBEE_DBUS_DEFAULT_REQ_FAILED_MSG);
252
253                 return TRUE;
254         }
255
256         return TRUE;
257 }
258
259 static void on_custom_send_to_local_resp(ZigBeeServiceInterface *service_interface,
260         guint request_id, gpointer resp_data, guint resp_data_len, gpointer resp_cb_data)
261 {
262         ZigbeeServiceInterfaceRespCbData_t *cb_data =
263                 (ZigbeeServiceInterfaceRespCbData_t *)resp_cb_data;
264
265         ZigbeeCustom *custom_object = NULL;
266         GDBusMethodInvocation *invocation = NULL;
267
268         ZigbeeGeneralResp_t *payload = (ZigbeeGeneralResp_t *)resp_data;
269
270         NOT_USED(service_interface);
271         NOT_USED(request_id);
272
273         if (NULL == resp_data || 0 == resp_data_len) {
274                 Z_LOGE("resp_data=%p or resp_data_len=%d is null", resp_data, resp_data_len);
275                 g_free(cb_data);
276                 return;
277         }
278
279         custom_object = zigbee_service_dbus_interface_ref_interface_object(cb_data);
280         zblib_check_null_free_and_ret("custom_object", custom_object, cb_data);
281
282         invocation = zigbee_service_dbus_interface_ref_invocation(cb_data);
283         zblib_check_null_free_and_ret("invocation", invocation, cb_data);
284
285         zigbee_custom_complete_send_to_local(custom_object, invocation, payload->result);
286
287         g_free(cb_data);
288 }
289
290 static gboolean on_custom_send_to_local(ZigbeeCustom *custom_object,
291         GDBusMethodInvocation *invocation,
292         gshort length,
293         GVariant *data,
294         gpointer user_data)
295 {
296         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
297         ZigbeeCustomSendToLocal_t req;
298         ZigbeeServiceInterfaceRespCbData_t *resp_cb_data = NULL;
299
300         GVariantIter *iter = NULL;
301         guint i = 0;
302
303         gboolean ret;
304
305         memset(&req, 0x0, sizeof(ZigbeeCustomSendToLocal_t));
306
307         /* Update request structure */
308         req.length = length;
309         g_variant_get(data, "a(y)", &iter);
310         while (g_variant_iter_loop(iter, "(y)", req.data[i])) {
311                 i++;
312                 if (i >= ZIGBEE_CUSTOM_SEND_PAYLOAD_LEN)
313                         break;
314         }
315
316         /* Allocate response callback data */
317         resp_cb_data =
318                 zigbee_service_dbus_interface_create_resp_cb_data(custom_object,
319                         invocation, NULL, 0);
320         if (NULL == resp_cb_data) {
321                 Z_LOGE("zigbee_service_dbus_interface_create_resp_cb_data failed!");
322
323                 /* Send failure response */
324                 ZIGBEE_DBUS_FAIL_RESPONSE(invocation, ZIGBEE_DBUS_DEFAULT_REQ_FAILED_MSG);
325
326                 return TRUE;
327         }
328
329         /* Dispatch request */
330         ret = zigbee_service_dbus_interface_dispatch_request(service_interface,
331                 ZBLIB_DRIVER_TYPE_CUSTOM,
332                 ZBLIB_CUSTOM_OPS_SEND_TO_LOCAL,
333                 &req, sizeof(req),
334                 on_custom_send_to_local_resp, resp_cb_data);
335         if (FALSE == ret) {
336                 Z_LOGE("zigbee_service_dbus_interface_dispatch_request failed!");
337
338                 /* Free response callback data */
339                 zigbee_service_dbus_interface_destroy_resp_cb_data(resp_cb_data);
340
341                 /* Send failure response */
342                 ZIGBEE_DBUS_FAIL_RESPONSE(invocation, ZIGBEE_DBUS_DEFAULT_REQ_FAILED_MSG);
343
344                 return TRUE;
345         }
346
347         return TRUE;
348 }
349
350 void zigbee_service_dbus_interface_custom_notification(ZigBeeServiceInterface *service_interface,
351         guint noti_id, gpointer noti_data, guint noti_data_len, gpointer noti_cb_data)
352 {
353         ZigbeeCustom *custom_object;
354
355         zblib_check_null_ret("service_interface", service_interface);
356
357         if (NULL == noti_data || 0 == noti_data_len) {
358                 Z_LOGE("noti_data=%p or noti_data_len=%d is null", noti_data, noti_data_len);
359                 return;
360         }
361
362         custom_object = _service_interface_ref_zigbee_custom(service_interface);
363         zblib_check_null_ret("custom_object", custom_object);
364
365         NOT_USED(noti_cb_data);
366
367         switch (noti_id) {
368         case ZBLIB_CUSTOM_NOTI_APS_SEND: {
369                 int i;
370                 GVariant* payload = NULL;
371                 GVariantBuilder *attr_builder = NULL;
372                 ZigbeeCustomApsSendNoti_t *rsp = (ZigbeeCustomApsSendNoti_t*)noti_data;
373
374                 Z_LOGD("'aps_send_rsp' from : [0x%X]", rsp->node_id);
375
376                 Z_LOGD("rsp->node_id=%x", rsp->node_id);
377                 Z_LOGD("rsp->src_ep = %x", rsp->src_ep);
378                 Z_LOGD("rsp->dest_ep = %x", rsp->dest_ep);
379                 Z_LOGD("rsp->cluster_id = %x", rsp->cluster_id);
380                 Z_LOGD("rsp->profile_id = %x", rsp->profile_id);
381                 Z_LOGD("rsp->cmd_id = %x", rsp->cmd_id);
382                 Z_LOGD("rsp->payload_len = %x", rsp->payload_len);
383
384                 attr_builder = g_variant_builder_new(G_VARIANT_TYPE("a(y)"));
385                 for (i = 0; i < rsp->payload_len; i++) {
386                         g_variant_builder_add(attr_builder, "(y)", rsp->payload[i]);
387                         Z_LOGD("rsp->payload[%d] = %x", i, rsp->payload[i]);
388                 }
389                 payload = g_variant_builder_end(attr_builder);
390                 g_variant_builder_unref(attr_builder);
391
392                 zigbee_custom_emit_aps_send_rsp(custom_object, rsp->node_id, rsp->src_ep,
393                         rsp->dest_ep, rsp->cluster_id, rsp->profile_id, rsp->payload_len,
394                         payload);
395         }
396         break;
397         case ZBLIB_CUSTOM_NOTI_ZCL_SEND: {
398                 int i;
399                 GVariant* payload = NULL;
400                 GVariantBuilder *attr_builder = NULL;
401                 ZigbeeCustomZclSendNoti_t *rsp = (ZigbeeCustomZclSendNoti_t*)noti_data;
402
403                 Z_LOGD("'zcl_send_rsp' from : [0x%X]", rsp->node_id);
404
405                 Z_LOGD("rsp->node_id=%x", rsp->node_id);
406                 Z_LOGD("rsp->src_ep = %x", rsp->src_ep);
407                 Z_LOGD("rsp->dest_ep = %x", rsp->dest_ep);
408                 Z_LOGD("rsp->cluster_id = %x", rsp->cluster_id);
409                 Z_LOGD("rsp->profile_id = %x", rsp->profile_id);
410                 Z_LOGD("rsp->cmd_id = %x", rsp->cmd_id);
411                 Z_LOGD("rsp->payload_len = %x", rsp->payload_len);
412
413                 attr_builder = g_variant_builder_new(G_VARIANT_TYPE("a(y)"));
414                 for (i = 0; i < rsp->payload_len; i++) {
415                         g_variant_builder_add(attr_builder, "(y)", rsp->payload[i]);
416                         Z_LOGD("rsp->payload[%d] = %x", i, rsp->payload[i]);
417                 }
418                 payload = g_variant_builder_end(attr_builder);
419                 g_variant_builder_unref(attr_builder);
420
421                 zigbee_custom_emit_zcl_send_rsp(custom_object, rsp->node_id, rsp->src_ep,
422                         rsp->dest_ep, rsp->cluster_id, rsp->profile_id, rsp->payload_len, payload);
423         }
424         break;
425         case ZBLIB_CUSTOM_NOTI_SEND_TO_LOCAL: {
426                 int i;
427                 GVariant* data = NULL;
428                 GVariantBuilder *attr_builder = NULL;
429                 ZigbeeCustomSendToLocalNoti_t *rsp = (ZigbeeCustomSendToLocalNoti_t*)noti_data;
430
431                 Z_LOGD("'send_to_local_rsp' length : [0x%X]", rsp->length);
432
433                 attr_builder = g_variant_builder_new(G_VARIANT_TYPE("a(y)"));
434                 for (i = 0; i < rsp->length; i++) {
435                         g_variant_builder_add(attr_builder, "(y)", rsp->data[i]);
436                         Z_LOGD("rsp->data[%d] = %x", i, rsp->data[i]);
437                 }
438                 data = g_variant_builder_end(attr_builder);
439                 g_variant_builder_unref(attr_builder);
440
441                 zigbee_custom_emit_send_to_local_rsp(custom_object, rsp->length, data);
442
443                 if (data) g_variant_unref(data);
444         }
445         break;
446         default:
447                 Z_LOGE("Unexpected notification [%x]", noti_id);
448         break;
449         }
450
451         /* ZigbeeCustom should be dereferenced */
452         g_object_unref(custom_object);
453 }
454
455 gboolean zigbee_service_dbus_interface_custom_init(ZigBeeServiceInterface *service_interface,
456         ZigbeeObjectSkeleton *zigbee_object)
457 {
458         ZigbeeCustom *custom_object;
459
460         if (NULL == service_interface) {
461                 Z_LOGE("service_interface is NULL");
462                 return FALSE;
463         }
464
465         custom_object = zigbee_custom_skeleton_new();
466         zigbee_object_skeleton_set_custom(zigbee_object, custom_object);
467         g_object_unref(custom_object);
468
469         Z_LOGI("custom_object: [%p]", custom_object);
470
471         /*
472          * Register signal handlers for 'custom' interface
473          */
474         g_signal_connect(custom_object,
475                 "handle-aps-send",
476                 G_CALLBACK(on_custom_aps_send), service_interface);
477
478         g_signal_connect(custom_object,
479                 "handle-zcl-send",
480                 G_CALLBACK(on_custom_zcl_send), service_interface);
481
482         g_signal_connect(custom_object,
483                 "handle-send-to-local",
484                 G_CALLBACK(on_custom_send_to_local), service_interface);
485
486         return TRUE;
487 }