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>
24 #include <dbus/dbus-glib.h>
25 #include <dbus/dbus-glib-lowlevel.h>
28 #include <sys/socket.h>
33 #include "serial_private.h"
38 #define LOG_TAG "CAPI_NETWORK_SERIAL"
40 #define DBG(fmt, args...) SLOGD(fmt, ##args)
41 #define ERR(fmt, args...) SLOGE(fmt, ##args)
43 #define SERIAL_SOCKET_PATH "/tmp/.dr_common_stream"
44 #define SERIAL_BUF_SIZE 65536
45 #define SERIAL_INTERFACE "User.Data.Router.Introspectable"
47 DBusConnection *dbus_connection = NULL;
52 static gboolean __g_io_client_handler(GIOChannel * io, GIOCondition cond, void *data)
55 serial_s *pHandle = (serial_s *) data;
59 if (pHandle->data_handler.callback) {
60 char buffer[SERIAL_BUF_SIZE] = { 0 };
62 fd = g_io_channel_unix_get_fd(io);
63 len = recv(fd, buffer, SERIAL_BUF_SIZE, 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);
71 ((serial_data_received_cb) pHandle->data_handler.callback)
72 (buffer, len, pHandle->data_handler.user_data);
77 static void __init_client_giochannel(void *data)
80 serial_s *pHandle = (serial_s *) data;
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);
91 static int __connect_to_serial_server(void *data)
93 int client_socket = -1;
94 struct sockaddr_un server_addr;
95 serial_s *pHandle = (serial_s *) data;
99 client_socket = socket(AF_UNIX, SOCK_STREAM, 0);
100 if (client_socket < 0) {
101 ERR("Create socket failed\n");
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));
109 if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
110 ERR("Connect failed\n");
111 close(client_socket);
114 pHandle->client_socket = client_socket;
116 __init_client_giochannel(pHandle);
118 return client_socket;
121 static DBusHandlerResult __dbus_event_filter(DBusConnection * sys_conn, DBusMessage * msg, void *data)
123 static int socket = -1;
124 const char *path = dbus_message_get_path(msg);
126 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
127 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
129 if (path == NULL || strcmp(path, "/") == 0)
130 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
132 if (dbus_message_is_signal(msg, SERIAL_INTERFACE, "serial_status")) {
134 dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &res, DBUS_TYPE_INVALID);
136 serial_s *pHandle = (serial_s *) data;
137 if (res == SERIAL_OPENED) {
138 socket = __connect_to_serial_server(pHandle);
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;
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) {
149 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
151 ((serial_state_changed_cb) pHandle->state_handler.callback)
152 (SERIAL_ERROR_NONE, SERIAL_STATE_CLOSED, pHandle->state_handler.user_data);
155 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
158 return DBUS_HANDLER_RESULT_HANDLED;
161 int __send_serial_ready_done_signal(void)
163 DBusMessage *msg = NULL;
164 const char *res = "OK";
166 if (dbus_connection == NULL)
167 return SERIAL_ERROR_INVALID_OPERATION;
169 msg = dbus_message_new_signal("/Network/Serial", "Capi.Network.Serial", "ready_for_serial");
171 ERR("Unable to allocate D-Bus signal\n");
172 return SERIAL_ERROR_OPERATION_FAILED;
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;
181 dbus_connection_send(dbus_connection, msg, NULL);
182 dbus_message_unref(msg);
183 return SERIAL_ERROR_NONE;
186 static int __serial_set_state_changed_cb(serial_h serial, void *callback, void *user_data)
189 ERR("Invalid parameter\n");
190 return SERIAL_ERROR_INVALID_PARAMETER;
193 serial_s *pHandle = (serial_s *) serial;
196 pHandle->state_handler.callback = callback;
197 pHandle->state_handler.user_data = user_data;
199 pHandle->state_handler.callback = NULL;
200 pHandle->state_handler.user_data = NULL;
203 return SERIAL_ERROR_NONE;
206 static int __serial_set_data_received_cb(serial_h serial, void *callback, void *user_data)
209 ERR("Invalid parameter\n");
210 return SERIAL_ERROR_INVALID_PARAMETER;
213 serial_s *pHandle = (serial_s *) serial;
216 pHandle->data_handler.callback = callback;
217 pHandle->data_handler.user_data = user_data;
219 pHandle->data_handler.callback = NULL;
220 pHandle->data_handler.user_data = NULL;
223 return SERIAL_ERROR_NONE;
230 int serial_create(serial_h * serial)
232 DBG("%s\n", __FUNCTION__);
234 GError *error = NULL;
235 DBusError dbus_error;
236 serial_s *pHandle = NULL;
239 return SERIAL_ERROR_INVALID_PARAMETER;
241 pHandle = (serial_s *) g_try_malloc0(sizeof(serial_s));
243 return SERIAL_ERROR_OUT_OF_MEMORY;
244 #if !GLIB_CHECK_VERSION(2, 35, 3)
248 pHandle->client_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
250 ERR("Couldn't connect to the System bus[%s]", error->message);
253 return SERIAL_ERROR_OPERATION_FAILED;
255 dbus_connection = dbus_g_connection_get_connection(pHandle->client_bus);
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);
265 return SERIAL_ERROR_OPERATION_FAILED;
268 *serial = (serial_h) pHandle;
270 return SERIAL_ERROR_NONE;
273 int serial_open(serial_h serial)
275 DBG("%s\n", __FUNCTION__);
278 ERR("Invalid parameter\n");
279 return SERIAL_ERROR_INVALID_PARAMETER;
282 return __send_serial_ready_done_signal();
285 int serial_close(serial_h serial)
287 DBG("%s\n", __FUNCTION__);
290 ERR("Invalid parameter\n");
291 return SERIAL_ERROR_INVALID_PARAMETER;
294 serial_s *pHandle = (serial_s *) serial;
296 if (pHandle->client_socket > 0) {
297 if (close(pHandle->client_socket) < 0)
298 return SERIAL_ERROR_OPERATION_FAILED;
300 pHandle->client_socket = -1;
302 return SERIAL_ERROR_NONE;
304 return SERIAL_ERROR_INVALID_OPERATION;
308 int serial_destroy(serial_h serial)
310 DBG("%s\n", __FUNCTION__);
313 ERR("Invalid parameter\n");
314 return SERIAL_ERROR_INVALID_PARAMETER;
317 serial_s *pHandle = (serial_s *) serial;
319 if (dbus_connection != NULL) {
320 dbus_connection_remove_filter(dbus_connection, __dbus_event_filter, pHandle);
321 dbus_connection = NULL;
324 if (pHandle->client_bus != NULL) {
325 dbus_g_connection_unref(pHandle->client_bus);
326 pHandle->client_bus = NULL;
329 if (pHandle->g_watch_id > 0) {
330 g_source_remove(pHandle->g_watch_id);
331 pHandle->g_watch_id = -1;
334 if (pHandle->client_socket > 0) {
335 close(pHandle->client_socket);
336 pHandle->client_socket = -1;
342 return SERIAL_ERROR_NONE;
345 int serial_write(serial_h serial, const char *data, int data_length)
348 ERR("Invalid parameter\n");
349 return SERIAL_ERROR_INVALID_PARAMETER;
352 serial_s *pHandle = (serial_s *) serial;
354 ret = send(pHandle->client_socket, data, data_length, MSG_EOR);
356 ERR("Send failed. ");
357 return SERIAL_ERROR_OPERATION_FAILED;
363 int serial_set_state_changed_cb(serial_h serial, serial_state_changed_cb callback, void *user_data)
365 DBG("%s\n", __FUNCTION__);
367 if (!serial || !callback) {
368 ERR("Invalid parameter\n");
369 return SERIAL_ERROR_INVALID_PARAMETER;
372 return (__serial_set_state_changed_cb(serial, callback, user_data));
375 int serial_unset_state_changed_cb(serial_h serial)
377 DBG("%s\n", __FUNCTION__);
380 ERR("Invalid parameter\n");
381 return SERIAL_ERROR_INVALID_PARAMETER;
384 return (__serial_set_state_changed_cb(serial, NULL, NULL));
387 int serial_set_data_received_cb(serial_h serial, serial_data_received_cb callback, void *user_data)
389 DBG("%s\n", __FUNCTION__);
391 if (!serial || !callback) {
392 ERR("Invalid parameter\n");
393 return SERIAL_ERROR_INVALID_PARAMETER;
396 return (__serial_set_data_received_cb(serial, callback, user_data));
399 int serial_unset_data_received_cb(serial_h serial)
401 DBG("%s\n", __FUNCTION__);
404 ERR("Invalid parameter\n");
405 return SERIAL_ERROR_INVALID_PARAMETER;
408 return (__serial_set_data_received_cb(serial, NULL, NULL));