Remove dbus-glib-1 dependency
[platform/core/api/serial.git] / src / serial.c
1 /*
2  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <glib.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <ctype.h>
21 #include <stdio.h>
22 #include <stdbool.h>
23 #include <dbus/dbus.h>
24 #include <unistd.h>
25 #include <sys/un.h>
26 #include <sys/socket.h>
27 #include <sys/stat.h>
28 #include <dlog.h>
29
30 #include "serial.h"
31 #include "serial_private.h"
32
33 #ifdef LOG_TAG
34 #undef LOG_TAG
35 #endif
36 #define LOG_TAG "CAPI_NETWORK_SERIAL"
37
38 #define DBG(fmt, args...) SLOGD(fmt, ##args)
39 #define ERR(fmt, args...) SLOGE(fmt, ##args)
40
41 #define SERIAL_SOCKET_PATH      "/tmp/.dr_common_stream"
42 #define SERIAL_BUF_SIZE         65536
43 #define SERIAL_INTERFACE                "User.Data.Router.Introspectable"
44
45 DBusConnection *dbus_connection = NULL;
46
47 /*
48  *  Internal Functions
49  */
50 static gboolean __g_io_client_handler(GIOChannel * io, GIOCondition cond, void *data)
51 {
52         int fd;
53         serial_s *pHandle = (serial_s *) data;
54         if (pHandle == NULL)
55                 return FALSE;
56
57         if (pHandle->data_handler.callback) {
58                 char buffer[SERIAL_BUF_SIZE] = { 0 };
59                 int len = 0;
60                 fd = g_io_channel_unix_get_fd(io);
61                 len = recv(fd, buffer, SERIAL_BUF_SIZE, 0);
62                 if (len <= 0) {
63                         ERR("Error occured or the peer is shutdownd. [%d]\n", len);
64                         ((serial_state_changed_cb) pHandle->state_handler.callback)
65                                 (SERIAL_ERROR_NONE, SERIAL_STATE_CLOSED, pHandle->state_handler.user_data);
66                         return FALSE;
67                 }
68
69                 ((serial_data_received_cb) pHandle->data_handler.callback)
70                         (buffer, len, pHandle->data_handler.user_data);
71         }
72         return TRUE;
73 }
74
75 static void __init_client_giochannel(void *data)
76 {
77         GIOChannel *io;
78         serial_s *pHandle = (serial_s *) data;
79         if (pHandle == NULL)
80                 return;
81
82         io = g_io_channel_unix_new(pHandle->client_socket);
83         g_io_channel_set_close_on_unref(io, TRUE);
84         pHandle->g_watch_id = g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, __g_io_client_handler, pHandle);
85         g_io_channel_unref(io);
86         return;
87 }
88
89 static int __connect_to_serial_server(void *data)
90 {
91         int client_socket = -1;
92         struct sockaddr_un server_addr;
93         serial_s *pHandle = (serial_s *) data;
94         if (pHandle == NULL)
95                 return -1;
96
97         client_socket = socket(AF_UNIX, SOCK_STREAM, 0);
98         if (client_socket < 0) {
99                 ERR("Create socket failed\n");
100                 return -1;
101         }
102
103         memset(&server_addr, 0, sizeof(server_addr));
104         server_addr.sun_family = AF_UNIX;
105         g_strlcpy(server_addr.sun_path, SERIAL_SOCKET_PATH, sizeof(server_addr.sun_path));
106
107         if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
108                 ERR("Connect failed\n");
109                 close(client_socket);
110                 return -1;
111         }
112         pHandle->client_socket = client_socket;
113
114         __init_client_giochannel(pHandle);
115
116         return client_socket;
117 }
118
119 static DBusHandlerResult __dbus_event_filter(DBusConnection * sys_conn, DBusMessage * msg, void *data)
120 {
121         static int socket = -1;
122         const char *path = dbus_message_get_path(msg);
123
124         if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
125                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
126
127         if (path == NULL || strcmp(path, "/") == 0)
128                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
129
130         if (dbus_message_is_signal(msg, SERIAL_INTERFACE, "serial_status")) {
131                 int res = 0;
132                 dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &res, DBUS_TYPE_INVALID);
133
134                 serial_s *pHandle = (serial_s *) data;
135                 if (res == SERIAL_OPENED) {
136                         socket = __connect_to_serial_server(pHandle);
137                         if (socket < 0) {
138                                 ((serial_state_changed_cb) pHandle->state_handler.callback)
139                                         (SERIAL_ERROR_OPERATION_FAILED, SERIAL_STATE_OPENED, pHandle->state_handler.user_data);
140                                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
141                         }
142
143                         ((serial_state_changed_cb) pHandle->state_handler.callback)
144                                 (SERIAL_ERROR_NONE, SERIAL_STATE_OPENED, pHandle->state_handler.user_data);
145                 } else if (res == SERIAL_CLOSED) {
146                         if (socket < 0)
147                                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
148
149                         ((serial_state_changed_cb) pHandle->state_handler.callback)
150                                 (SERIAL_ERROR_NONE, SERIAL_STATE_CLOSED, pHandle->state_handler.user_data);
151                 }
152         } else {
153                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
154         }
155
156         return DBUS_HANDLER_RESULT_HANDLED;
157 }
158
159 int __send_serial_ready_done_signal(void)
160 {
161         DBusMessage *msg = NULL;
162         const char *res = "OK";
163
164         if (dbus_connection == NULL)
165                 return SERIAL_ERROR_INVALID_OPERATION;
166
167         msg = dbus_message_new_signal("/Network/Serial", "Capi.Network.Serial", "ready_for_serial");
168         if (!msg) {
169                 ERR("Unable to allocate D-Bus signal\n");
170                 return SERIAL_ERROR_OPERATION_FAILED;
171         }
172
173         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &res, DBUS_TYPE_INVALID)) {
174                 ERR("Event sending failed\n");
175                 dbus_message_unref(msg);
176                 return SERIAL_ERROR_OPERATION_FAILED;
177         }
178
179         dbus_connection_send(dbus_connection, msg, NULL);
180         dbus_message_unref(msg);
181         return SERIAL_ERROR_NONE;
182 }
183
184 static int __serial_set_state_changed_cb(serial_h serial, void *callback, void *user_data)
185 {
186         if (!serial) {
187                 ERR("Invalid parameter\n");
188                 return SERIAL_ERROR_INVALID_PARAMETER;
189         }
190
191         serial_s *pHandle = (serial_s *) serial;
192
193         if (callback) {
194                 pHandle->state_handler.callback = callback;
195                 pHandle->state_handler.user_data = user_data;
196         } else {
197                 pHandle->state_handler.callback = NULL;
198                 pHandle->state_handler.user_data = NULL;
199         }
200
201         return SERIAL_ERROR_NONE;
202 }
203
204 static int __serial_set_data_received_cb(serial_h serial, void *callback, void *user_data)
205 {
206         if (!serial) {
207                 ERR("Invalid parameter\n");
208                 return SERIAL_ERROR_INVALID_PARAMETER;
209         }
210
211         serial_s *pHandle = (serial_s *) serial;
212
213         if (callback) {
214                 pHandle->data_handler.callback = callback;
215                 pHandle->data_handler.user_data = user_data;
216         } else {
217                 pHandle->data_handler.callback = NULL;
218                 pHandle->data_handler.user_data = NULL;
219         }
220
221         return SERIAL_ERROR_NONE;
222 }
223
224 /*
225  *  Public Functions
226  */
227
228 int serial_create(serial_h * serial)
229 {
230         DBG("%s\n", __FUNCTION__);
231
232         DBusError dbus_error;
233         serial_s *pHandle = NULL;
234
235         if (serial == NULL)
236                 return SERIAL_ERROR_INVALID_PARAMETER;
237
238         pHandle = (serial_s *) g_try_malloc0(sizeof(serial_s));
239         if (pHandle == NULL)
240                 return SERIAL_ERROR_OUT_OF_MEMORY;
241 #if !GLIB_CHECK_VERSION(2, 35, 3)
242         g_type_init();
243 #endif
244
245         dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
246         if (!dbus_connection) {
247                 ERR("Couldn't connect to the System bus");
248                 g_free(pHandle);
249                 return SERIAL_ERROR_OPERATION_FAILED;
250         }
251
252         /* Add the filter for network client functions */
253         dbus_error_init(&dbus_error);
254         dbus_connection_add_filter(dbus_connection, __dbus_event_filter, pHandle, NULL);
255         dbus_bus_add_match(dbus_connection, "type=signal,interface=" SERIAL_INTERFACE ",member=serial_status", &dbus_error);
256         if (dbus_error_is_set(&dbus_error)) {
257                 ERR("Fail to add dbus filter signal\n");
258                 dbus_error_free(&dbus_error);
259                 g_free(pHandle);
260                 return SERIAL_ERROR_OPERATION_FAILED;
261         }
262
263         pHandle->client_bus = dbus_connection;
264
265         *serial = (serial_h) pHandle;
266
267         return SERIAL_ERROR_NONE;
268 }
269
270 int serial_open(serial_h serial)
271 {
272         DBG("%s\n", __FUNCTION__);
273
274         if (!serial) {
275                 ERR("Invalid parameter\n");
276                 return SERIAL_ERROR_INVALID_PARAMETER;
277         }
278
279         return __send_serial_ready_done_signal();
280 }
281
282 int serial_close(serial_h serial)
283 {
284         DBG("%s\n", __FUNCTION__);
285
286         if (!serial) {
287                 ERR("Invalid parameter\n");
288                 return SERIAL_ERROR_INVALID_PARAMETER;
289         }
290
291         serial_s *pHandle = (serial_s *) serial;
292
293         if (pHandle->client_socket > 0) {
294                 if (close(pHandle->client_socket) < 0)
295                         return SERIAL_ERROR_OPERATION_FAILED;
296
297                 pHandle->client_socket = -1;
298
299                 return SERIAL_ERROR_NONE;
300         } else {
301                 return SERIAL_ERROR_INVALID_OPERATION;
302         }
303 }
304
305 int serial_destroy(serial_h serial)
306 {
307         DBG("%s\n", __FUNCTION__);
308
309         if (!serial) {
310                 ERR("Invalid parameter\n");
311                 return SERIAL_ERROR_INVALID_PARAMETER;
312         }
313
314         serial_s *pHandle = (serial_s *) serial;
315
316         if (dbus_connection != NULL) {
317                 dbus_connection_remove_filter(dbus_connection, __dbus_event_filter, pHandle);
318                 dbus_connection = NULL;
319         }
320
321         if (pHandle->client_bus != NULL) {
322                 dbus_connection_unref(pHandle->client_bus);
323                 pHandle->client_bus = NULL;
324         }
325
326         if (pHandle->g_watch_id > 0) {
327                 g_source_remove(pHandle->g_watch_id);
328                 pHandle->g_watch_id = -1;
329         }
330
331         if (pHandle->client_socket > 0) {
332                 close(pHandle->client_socket);
333                 pHandle->client_socket = -1;
334         }
335
336         g_free(pHandle);
337         serial = NULL;
338
339         return SERIAL_ERROR_NONE;
340 }
341
342 int serial_write(serial_h serial, const char *data, int data_length)
343 {
344         if (!serial) {
345                 ERR("Invalid parameter\n");
346                 return SERIAL_ERROR_INVALID_PARAMETER;
347         }
348         int ret;
349         serial_s *pHandle = (serial_s *) serial;
350
351         ret = send(pHandle->client_socket, data, data_length, MSG_EOR);
352         if (ret == -1) {
353                 ERR("Send failed. ");
354                 return SERIAL_ERROR_OPERATION_FAILED;
355         }
356
357         return ret;
358 }
359
360 int serial_set_state_changed_cb(serial_h serial, serial_state_changed_cb callback, void *user_data)
361 {
362         DBG("%s\n", __FUNCTION__);
363
364         if (!serial || !callback) {
365                 ERR("Invalid parameter\n");
366                 return SERIAL_ERROR_INVALID_PARAMETER;
367         }
368
369         return (__serial_set_state_changed_cb(serial, callback, user_data));
370 }
371
372 int serial_unset_state_changed_cb(serial_h serial)
373 {
374         DBG("%s\n", __FUNCTION__);
375
376         if (!serial) {
377                 ERR("Invalid parameter\n");
378                 return SERIAL_ERROR_INVALID_PARAMETER;
379         }
380
381         return (__serial_set_state_changed_cb(serial, NULL, NULL));
382 }
383
384 int serial_set_data_received_cb(serial_h serial, serial_data_received_cb callback, void *user_data)
385 {
386         DBG("%s\n", __FUNCTION__);
387
388         if (!serial || !callback) {
389                 ERR("Invalid parameter\n");
390                 return SERIAL_ERROR_INVALID_PARAMETER;
391         }
392
393         return (__serial_set_data_received_cb(serial, callback, user_data));
394 }
395
396 int serial_unset_data_received_cb(serial_h serial)
397 {
398         DBG("%s\n", __FUNCTION__);
399
400         if (!serial) {
401                 ERR("Invalid parameter\n");
402                 return SERIAL_ERROR_INVALID_PARAMETER;
403         }
404
405         return (__serial_set_data_received_cb(serial, NULL, NULL));
406 }