4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Injun Yang <injun.yang@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
25 #include <dbus/dbus.h>
26 #include <dbus/dbus-glib.h>
27 #include <dbus/dbus-glib-lowlevel.h>
28 #include <dbus/dbus-glib-bindings.h>
32 #include <sys/socket.h>
37 #include "dr-common.h"
42 #define SOCK_WAIT_TIME 10000
43 #define SOCK_WAIT_CNT 200
44 #define COM_SOCKET_PATH "/tmp/.dr_common_stream"
45 #define BUF_SIZE 65536
46 #define NETWORK_SERIAL_INTERFACE "Capi.Network.Serial"
48 DBusConnection *dbus_connection = NULL;
51 SERIAL_SESSION_DISCONNECTED,
52 SERIAL_SESSION_CONNECTED
58 int g_watch_id_server;
59 int g_watch_id_client;
64 dr_socket_info_t serial_session = {0, };
67 static DBusHandlerResult __dbus_event_filter(DBusConnection *sys_conn,
68 DBusMessage *msg, void *data)
70 const char *path = dbus_message_get_path(msg);
72 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
73 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
75 if (path == NULL || strcmp(path, "/") == 0)
76 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
78 if (dbus_message_is_signal(msg, NETWORK_SERIAL_INTERFACE,
79 "ready_for_serial")) {
81 dbus_message_get_args(msg, NULL,
82 DBUS_TYPE_STRING, &res,
85 if (g_strcmp0(res, "OK") == 0)
86 _send_serial_status_signal(SERIAL_OPENED);
88 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
91 return DBUS_HANDLER_RESULT_HANDLED;
94 gboolean _init_dbus_signal(void)
97 DBusGConnection *conn;
101 conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
103 ERR(" DBUS get failed\n");
107 dbus_connection = dbus_g_connection_get_connection(conn);
109 /* Add the filter for network client functions */
110 dbus_error_init(&dbus_error);
111 dbus_connection_add_filter(dbus_connection, __dbus_event_filter, NULL, NULL);
112 dbus_bus_add_match(dbus_connection,
113 "type=signal,interface=" NETWORK_SERIAL_INTERFACE
114 ",member=ready_for_serial", &dbus_error);
115 if (dbus_error_is_set(&dbus_error)) {
116 ERR("Fail to add dbus filter signal\n");
117 dbus_error_free(&dbus_error);
124 void _send_serial_status_signal(int event)
126 DBusMessage *msg = NULL;
127 if(dbus_connection == NULL) return;
129 msg = dbus_message_new_signal("/DataRouter",
130 "User.Data.Router.Introspectable",
133 ERR("Unable to allocate D-Bus signal\n");
137 if (!dbus_message_append_args(msg,
138 DBUS_TYPE_INT32, &event,
139 DBUS_TYPE_INVALID)) {
140 ERR("Event sending failed\n");
141 dbus_message_unref(msg);
144 DBG("Send dbus signal : %s\n", event ? "SERIAL_OPENED":"SERIAL_CLOSED");
145 dbus_connection_send(dbus_connection, msg, NULL);
146 dbus_message_unref(msg);
151 int _write_to_serial_client(char *buf, int buf_len)
154 if (buf == NULL || buf_len == 0) {
155 ERR("Invalid param\n");
158 len = send(serial_session.client_socket, buf, buf_len, MSG_EOR);
160 char err_buf[ERRMSG_SIZE] = { 0, };
161 strerror_r(errno, err_buf, ERRMSG_SIZE);
162 ERR("Send failed\n");
170 static void __close_client_socket()
173 DBG("Closing socket\n");
174 ret = close(serial_session.client_socket);
176 perror("close error: ");
178 serial_session.state = SERIAL_SESSION_DISCONNECTED;
183 static gboolean __g_io_server_handler(GIOChannel *io, GIOCondition cond, void *data)
185 char buffer[BUF_SIZE+1];
188 fd = g_io_channel_unix_get_fd(io);
189 memset(buffer, 0, sizeof(buffer));
190 len = recv(fd, buffer, BUF_SIZE, 0);
192 ERR("Connection closed or Error occured : %d\n", len);
193 g_source_remove(serial_session.g_watch_id_server);
194 g_source_remove(serial_session.g_watch_id_client);
195 __close_client_socket();
196 unlink(COM_SOCKET_PATH);
200 _write_to_usb(buffer, len);
205 static gboolean __g_io_accept_handler(GIOChannel *chan, GIOCondition cond, gpointer data)
210 struct sockaddr_un client_addr;
212 addrlen = sizeof(client_addr);
214 if ( cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR) ) {
215 DBG("GIOCondition %d \n", cond);
217 if(serial_session.server_socket >= 0) {
218 close(serial_session.server_socket);
219 serial_session.server_socket = 0;
224 if(serial_session.state == SERIAL_SESSION_CONNECTED) {
225 DBG("Connection already exists.....\n");
229 DBG("Waiting for connection request\n");
230 serverfd = g_io_channel_unix_get_fd(chan);
231 clientfd = accept(serverfd, (struct sockaddr *)&client_addr, &addrlen);
233 DBG("serverfd:%d clientfd:%d\n", serverfd, clientfd);
235 io = g_io_channel_unix_new(clientfd);
236 g_io_channel_set_close_on_unref(io, TRUE);
237 serial_session.g_watch_id_client = g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
238 __g_io_server_handler, NULL);
239 g_io_channel_unref(io);
241 serial_session.client_socket= clientfd;
242 serial_session.state = SERIAL_SESSION_CONNECTED;
244 ERR("Accept failed\n");
251 static void __create_serial_server()
254 struct sockaddr_un server_addr;
257 if ((server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
258 ERR("sock create error\n");
262 bzero(&server_addr, sizeof(server_addr));
263 server_addr.sun_family = AF_UNIX;
264 g_strlcpy(server_addr.sun_path, COM_SOCKET_PATH, sizeof(server_addr.sun_path));
265 unlink(COM_SOCKET_PATH);
267 /*---Assign a port number to the socket---*/
268 if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {
269 perror("bind error: ");
273 sock_mode = (S_IRWXU | S_IRWXG | S_IRWXO); // has 777 permission
274 if (chmod(COM_SOCKET_PATH, sock_mode) < 0) {
275 perror("chmod error: ");
276 close(server_socket);
280 /*---Make it a "listening socket"---*/
281 if (listen(server_socket, 1) != 0) {
282 perror("listen error: ");
283 close(server_socket);
286 serial_session.server_socket = server_socket;
287 serial_session.g_io = g_io_channel_unix_new(server_socket);
288 g_io_channel_set_close_on_unref(serial_session.g_io, TRUE);
289 serial_session.g_watch_id_server = g_io_add_watch(serial_session.g_io,
290 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
291 __g_io_accept_handler, NULL);
292 g_io_channel_unref(serial_session.g_io);
298 void _init_serial_server(void)
300 __create_serial_server();
303 gboolean _deinit_serial_server(void)
305 __close_client_socket();
310 gboolean _is_exist_serial_session(void)
312 return (serial_session.state == SERIAL_SESSION_CONNECTED) ? TRUE: FALSE;
315 gboolean _wait_serial_session(void)
318 while (_is_exist_serial_session() == FALSE) {
319 usleep(SOCK_WAIT_TIME);
320 if (cnt++ > SOCK_WAIT_CNT)