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