Make it build on x86_64
[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 #if !GLIB_CHECK_VERSION (2, 35, 3)
268     g_type_init ();
269 #endif
270
271         pHandle->client_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
272         if (error) {
273                 ERR("Couldn't connect to the System bus[%s]",
274                                                                 error->message);
275                 g_error_free(error);
276                 g_free(pHandle);
277                 return SERIAL_ERROR_OPERATION_FAILED;
278         }
279         dbus_connection = dbus_g_connection_get_connection(pHandle->client_bus);
280
281         /* Add the filter for network client functions */
282         dbus_error_init(&dbus_error);
283         dbus_connection_add_filter(dbus_connection, __dbus_event_filter, pHandle, NULL);
284         dbus_bus_add_match(dbus_connection,
285                            "type=signal,interface=" SERIAL_INTERFACE
286                            ",member=serial_status", &dbus_error);
287         if (dbus_error_is_set(&dbus_error)) {
288                 ERR("Fail to add dbus filter signal\n");
289                 dbus_error_free(&dbus_error);
290                 g_free(pHandle);
291                 return SERIAL_ERROR_OPERATION_FAILED;
292         }
293
294         *serial = (serial_h)pHandle;
295
296         return SERIAL_ERROR_NONE;
297 }
298
299
300 int serial_open(serial_h serial)
301 {
302         DBG("%s\n", __FUNCTION__);
303
304         if (!serial) {
305                 ERR("Invalid parameter\n");
306                 return SERIAL_ERROR_INVALID_PARAMETER;
307         }
308
309         return __send_serial_ready_done_signal();
310 }
311
312 int serial_close(serial_h serial)
313 {
314         DBG("%s\n", __FUNCTION__);
315
316         if (!serial) {
317                 ERR("Invalid parameter\n");
318                 return SERIAL_ERROR_INVALID_PARAMETER;
319         }
320
321         serial_s *pHandle = (serial_s *)serial;
322
323         if (pHandle->client_socket > 0) {
324                 if (close(pHandle->client_socket) < 0)
325                         return SERIAL_ERROR_OPERATION_FAILED;
326
327                 pHandle->client_socket = -1;
328
329                 return SERIAL_ERROR_NONE;
330         } else {
331                 return SERIAL_ERROR_INVALID_OPERATION;
332         }
333 }
334
335 int serial_destroy(serial_h serial)
336 {
337         DBG("%s\n", __FUNCTION__);
338
339         if (!serial) {
340                 ERR("Invalid parameter\n");
341                 return SERIAL_ERROR_INVALID_PARAMETER;
342         }
343
344         serial_s *pHandle = (serial_s *)serial;
345
346         if (dbus_connection != NULL) {
347                 dbus_connection_remove_filter(dbus_connection, __dbus_event_filter, pHandle);
348                 dbus_connection = NULL;
349         }
350
351         if (pHandle->client_bus != NULL) {
352                 dbus_g_connection_unref(pHandle->client_bus);
353                 pHandle->client_bus = NULL;
354         }
355
356         if (pHandle->g_watch_id > 0) {
357                 g_source_remove(pHandle->g_watch_id);
358                 pHandle->g_watch_id = -1;
359         }
360
361         if (pHandle->client_socket > 0) {
362                 close(pHandle->client_socket);
363                 pHandle->client_socket = -1;
364         }
365
366         g_free(pHandle);
367         serial = NULL;
368
369         return SERIAL_ERROR_NONE;
370 }
371
372 int serial_write(serial_h serial, const char *data, int data_length)
373 {
374         if (!serial) {
375                 ERR("Invalid parameter\n");
376                 return SERIAL_ERROR_INVALID_PARAMETER;
377         }
378         int ret;
379         serial_s *pHandle = (serial_s *)serial;
380
381         ret = send(pHandle->client_socket, data, data_length, MSG_EOR);
382         if (ret == -1) {
383                  ERR("Send failed. ");
384                  return SERIAL_ERROR_OPERATION_FAILED;
385         }
386
387         return ret;
388 }
389
390 int serial_set_state_changed_cb(serial_h serial, serial_state_changed_cb callback, void *user_data)
391 {
392         DBG("%s\n", __FUNCTION__);
393
394         if (!serial || !callback) {
395                 ERR("Invalid parameter\n");
396                 return SERIAL_ERROR_INVALID_PARAMETER;
397         }
398
399         return (__serial_set_state_changed_cb(serial, callback, user_data));
400 }
401
402 int serial_unset_state_changed_cb(serial_h serial)
403 {
404         DBG("%s\n", __FUNCTION__);
405
406         if (!serial) {
407                 ERR("Invalid parameter\n");
408                 return SERIAL_ERROR_INVALID_PARAMETER;
409         }
410
411         return (__serial_set_state_changed_cb(serial, NULL, NULL));
412 }
413
414 int serial_set_data_received_cb(serial_h serial, serial_data_received_cb callback, void *user_data)
415 {
416         DBG("%s\n", __FUNCTION__);
417
418         if (!serial || !callback) {
419                 ERR("Invalid parameter\n");
420                 return SERIAL_ERROR_INVALID_PARAMETER;
421         }
422
423         return (__serial_set_data_received_cb(serial, callback, user_data));
424 }
425
426 int serial_unset_data_received_cb(serial_h serial)
427 {
428         DBG("%s\n", __FUNCTION__);
429
430         if (!serial) {
431                 ERR("Invalid parameter\n");
432                 return SERIAL_ERROR_INVALID_PARAMETER;
433         }
434
435         return (__serial_set_data_received_cb(serial, NULL, NULL));
436 }