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