tizen 2.3.1 release
[framework/connectivity/bluez.git] / profiles / input / suspend-dummy.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2012  Nordic Semiconductor Inc.
6  *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
7  *
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37
38 #include <glib.h>
39
40 #include "src/log.h"
41 #include "suspend.h"
42
43 #define HOG_SUSPEND_FIFO        "/tmp/hogsuspend"
44
45 static suspend_event suspend_cb = NULL;
46 static resume_event resume_cb = NULL;
47 static guint watch = 0;
48
49 static int fifo_open(void);
50
51 static gboolean read_fifo(GIOChannel *io, GIOCondition cond, gpointer user_data)
52 {
53         char buffer[12];
54         gsize offset, left, bread;
55         GIOStatus iostatus;
56
57         if (cond & (G_IO_ERR | G_IO_HUP)) {
58                 /*
59                  * Both ends needs to be open simultaneously before proceeding
60                  * any input or output operation. When the remote closes the
61                  * channel, hup signal is received on this end.
62                  */
63                 fifo_open();
64                 return FALSE;
65         }
66
67         offset = 0;
68         left = sizeof(buffer) - 1;
69         memset(buffer, 0, sizeof(buffer));
70
71         do {
72                 iostatus = g_io_channel_read_chars(io, &buffer[offset], left,
73                                                                 &bread, NULL);
74
75                 offset += bread;
76                 left -= bread;
77                 if (left == 0)
78                         break;
79         } while (iostatus == G_IO_STATUS_NORMAL);
80
81         if (g_ascii_strncasecmp("suspend", buffer, 7) == 0)
82                 suspend_cb();
83         else if (g_ascii_strncasecmp("resume", buffer, 6) == 0)
84                 resume_cb();
85
86         return TRUE;
87 }
88
89 static int fifo_open(void)
90 {
91         GIOCondition condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
92         GIOChannel *fifoio;
93         int fd;
94
95         fd = open(HOG_SUSPEND_FIFO, O_RDONLY | O_NONBLOCK);
96         if (fd < 0) {
97                 int err = -errno;
98                 error("Can't open FIFO (%s): %s(%d)", HOG_SUSPEND_FIFO,
99                                                         strerror(-err), -err);
100                 return err;
101         }
102
103         fifoio = g_io_channel_unix_new(fd);
104         g_io_channel_set_close_on_unref(fifoio, TRUE);
105
106         watch = g_io_add_watch(fifoio, condition, read_fifo, NULL);
107
108         g_io_channel_unref(fifoio);
109
110         return 0;
111 }
112
113 int suspend_init(suspend_event suspend, resume_event resume)
114 {
115         struct stat st;
116         int ret;
117
118         DBG("");
119
120         suspend_cb = suspend;
121         resume_cb = resume;
122
123         if (stat(HOG_SUSPEND_FIFO, &st) == 0) {
124                 if (!S_ISFIFO(st.st_mode)) {
125                         error("Unexpected non-FIFO %s file", HOG_SUSPEND_FIFO);
126                         return -EIO;
127                 }
128
129                 if (unlink(HOG_SUSPEND_FIFO) < 0) {
130                         int err = -errno;
131                         error("Failed to remove FIFO (%s): %s (%d)",
132                                 HOG_SUSPEND_FIFO, strerror(-err), -err);
133                         return err;
134                 }
135         }
136
137         if (mkfifo(HOG_SUSPEND_FIFO, S_IRUSR | S_IWUSR) < 0) {
138                 int err = -errno;
139
140                 error("Can't create FIFO (%s): %s (%d)", HOG_SUSPEND_FIFO,
141                                                         strerror(-err), -err);
142                 return err;
143         }
144
145         DBG("Created suspend-dummy FIFO on %s", HOG_SUSPEND_FIFO);
146
147         ret = fifo_open();
148         if (ret < 0)
149                 unlink(HOG_SUSPEND_FIFO);
150
151         return ret;
152 }
153
154 void suspend_exit(void)
155 {
156         if (watch > 0) {
157                 g_source_remove(watch);
158                 watch = 0;
159         }
160
161         unlink(HOG_SUSPEND_FIFO);
162 }