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