2 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <dbus/dbus.h>
26 #include <sys/socket.h>
31 #include "serial_private.h"
36 #define LOG_TAG "CAPI_NETWORK_SERIAL"
38 #define DBG(fmt, args...) SLOGD(fmt, ##args)
39 #define ERR(fmt, args...) SLOGE(fmt, ##args)
41 #define SERIAL_SOCKET_PATH "/tmp/.dr_common_stream"
42 #define SERIAL_BUF_SIZE 65536
43 #define SERIAL_INTERFACE "User.Data.Router.Introspectable"
45 DBusConnection *dbus_connection = NULL;
50 static gboolean __g_io_client_handler(GIOChannel * io, GIOCondition cond, void *data)
53 serial_s *pHandle = (serial_s *) data;
57 if (pHandle->data_handler.callback) {
58 char buffer[SERIAL_BUF_SIZE] = { 0 };
60 fd = g_io_channel_unix_get_fd(io);
61 len = recv(fd, buffer, SERIAL_BUF_SIZE, 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);
69 ((serial_data_received_cb) pHandle->data_handler.callback)
70 (buffer, len, pHandle->data_handler.user_data);
75 static void __init_client_giochannel(void *data)
78 serial_s *pHandle = (serial_s *) data;
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);
89 static int __connect_to_serial_server(void *data)
91 int client_socket = -1;
92 struct sockaddr_un server_addr;
93 serial_s *pHandle = (serial_s *) data;
97 client_socket = socket(AF_UNIX, SOCK_STREAM, 0);
98 if (client_socket < 0) {
99 ERR("Create socket failed\n");
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));
107 if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
108 ERR("Connect failed\n");
109 close(client_socket);
112 pHandle->client_socket = client_socket;
114 __init_client_giochannel(pHandle);
116 return client_socket;
119 static DBusHandlerResult __dbus_event_filter(DBusConnection * sys_conn, DBusMessage * msg, void *data)
121 static int socket = -1;
122 const char *path = dbus_message_get_path(msg);
124 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
125 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
127 if (path == NULL || strcmp(path, "/") == 0)
128 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
130 if (dbus_message_is_signal(msg, SERIAL_INTERFACE, "serial_status")) {
132 dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &res, DBUS_TYPE_INVALID);
134 serial_s *pHandle = (serial_s *) data;
135 if (res == SERIAL_OPENED) {
136 socket = __connect_to_serial_server(pHandle);
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;
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) {
147 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
149 ((serial_state_changed_cb) pHandle->state_handler.callback)
150 (SERIAL_ERROR_NONE, SERIAL_STATE_CLOSED, pHandle->state_handler.user_data);
153 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
156 return DBUS_HANDLER_RESULT_HANDLED;
159 int __send_serial_ready_done_signal(void)
161 DBusMessage *msg = NULL;
162 const char *res = "OK";
164 if (dbus_connection == NULL)
165 return SERIAL_ERROR_INVALID_OPERATION;
167 msg = dbus_message_new_signal("/Network/Serial", "Capi.Network.Serial", "ready_for_serial");
169 ERR("Unable to allocate D-Bus signal\n");
170 return SERIAL_ERROR_OPERATION_FAILED;
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;
179 dbus_connection_send(dbus_connection, msg, NULL);
180 dbus_message_unref(msg);
181 return SERIAL_ERROR_NONE;
184 static int __serial_set_state_changed_cb(serial_h serial, void *callback, void *user_data)
187 ERR("Invalid parameter\n");
188 return SERIAL_ERROR_INVALID_PARAMETER;
191 serial_s *pHandle = (serial_s *) serial;
194 pHandle->state_handler.callback = callback;
195 pHandle->state_handler.user_data = user_data;
197 pHandle->state_handler.callback = NULL;
198 pHandle->state_handler.user_data = NULL;
201 return SERIAL_ERROR_NONE;
204 static int __serial_set_data_received_cb(serial_h serial, void *callback, void *user_data)
207 ERR("Invalid parameter\n");
208 return SERIAL_ERROR_INVALID_PARAMETER;
211 serial_s *pHandle = (serial_s *) serial;
214 pHandle->data_handler.callback = callback;
215 pHandle->data_handler.user_data = user_data;
217 pHandle->data_handler.callback = NULL;
218 pHandle->data_handler.user_data = NULL;
221 return SERIAL_ERROR_NONE;
228 int serial_create(serial_h * serial)
230 DBG("%s\n", __FUNCTION__);
232 DBusError dbus_error;
233 serial_s *pHandle = NULL;
236 return SERIAL_ERROR_INVALID_PARAMETER;
238 pHandle = (serial_s *) g_try_malloc0(sizeof(serial_s));
240 return SERIAL_ERROR_OUT_OF_MEMORY;
241 #if !GLIB_CHECK_VERSION(2, 35, 3)
245 dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
246 if (!dbus_connection) {
247 ERR("Couldn't connect to the System bus");
249 return SERIAL_ERROR_OPERATION_FAILED;
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);
260 return SERIAL_ERROR_OPERATION_FAILED;
263 pHandle->client_bus = dbus_connection;
265 *serial = (serial_h) pHandle;
267 return SERIAL_ERROR_NONE;
270 int serial_open(serial_h serial)
272 DBG("%s\n", __FUNCTION__);
275 ERR("Invalid parameter\n");
276 return SERIAL_ERROR_INVALID_PARAMETER;
279 return __send_serial_ready_done_signal();
282 int serial_close(serial_h serial)
284 DBG("%s\n", __FUNCTION__);
287 ERR("Invalid parameter\n");
288 return SERIAL_ERROR_INVALID_PARAMETER;
291 serial_s *pHandle = (serial_s *) serial;
293 if (pHandle->client_socket > 0) {
294 if (close(pHandle->client_socket) < 0)
295 return SERIAL_ERROR_OPERATION_FAILED;
297 pHandle->client_socket = -1;
299 return SERIAL_ERROR_NONE;
301 return SERIAL_ERROR_INVALID_OPERATION;
305 int serial_destroy(serial_h serial)
307 DBG("%s\n", __FUNCTION__);
310 ERR("Invalid parameter\n");
311 return SERIAL_ERROR_INVALID_PARAMETER;
314 serial_s *pHandle = (serial_s *) serial;
316 if (dbus_connection != NULL) {
317 dbus_connection_remove_filter(dbus_connection, __dbus_event_filter, pHandle);
318 dbus_connection = NULL;
321 if (pHandle->client_bus != NULL) {
322 dbus_connection_unref(pHandle->client_bus);
323 pHandle->client_bus = NULL;
326 if (pHandle->g_watch_id > 0) {
327 g_source_remove(pHandle->g_watch_id);
328 pHandle->g_watch_id = -1;
331 if (pHandle->client_socket > 0) {
332 close(pHandle->client_socket);
333 pHandle->client_socket = -1;
339 return SERIAL_ERROR_NONE;
342 int serial_write(serial_h serial, const char *data, int data_length)
345 ERR("Invalid parameter\n");
346 return SERIAL_ERROR_INVALID_PARAMETER;
349 serial_s *pHandle = (serial_s *) serial;
351 ret = send(pHandle->client_socket, data, data_length, MSG_EOR);
353 ERR("Send failed. ");
354 return SERIAL_ERROR_OPERATION_FAILED;
360 int serial_set_state_changed_cb(serial_h serial, serial_state_changed_cb callback, void *user_data)
362 DBG("%s\n", __FUNCTION__);
364 if (!serial || !callback) {
365 ERR("Invalid parameter\n");
366 return SERIAL_ERROR_INVALID_PARAMETER;
369 return (__serial_set_state_changed_cb(serial, callback, user_data));
372 int serial_unset_state_changed_cb(serial_h serial)
374 DBG("%s\n", __FUNCTION__);
377 ERR("Invalid parameter\n");
378 return SERIAL_ERROR_INVALID_PARAMETER;
381 return (__serial_set_state_changed_cb(serial, NULL, NULL));
384 int serial_set_data_received_cb(serial_h serial, serial_data_received_cb callback, void *user_data)
386 DBG("%s\n", __FUNCTION__);
388 if (!serial || !callback) {
389 ERR("Invalid parameter\n");
390 return SERIAL_ERROR_INVALID_PARAMETER;
393 return (__serial_set_data_received_cb(serial, callback, user_data));
396 int serial_unset_data_received_cb(serial_h serial)
398 DBG("%s\n", __FUNCTION__);
401 ERR("Invalid parameter\n");
402 return SERIAL_ERROR_INVALID_PARAMETER;
405 return (__serial_set_data_received_cb(serial, NULL, NULL));