tizen 2.3.1 release
[framework/telephony/libtcore.git] / src / udev.c
1 /*
2  * libtcore
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Ja-young Gu <jygu@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include <glib.h>
26
27 #include "tcore.h"
28 #include "udev.h"
29
30 struct tcore_udev_type {
31         Server *server;
32
33         GUdevClient *client;
34         GUdevEnumerator *enumer;
35         GSList *enumer_callbacks;
36         GSList *callbacks;
37 };
38
39 struct udev_enumer_callback_type {
40         TcoreUdevEnumerCallback func;
41         void *user_data;
42 };
43
44 struct udev_callback_type {
45         TcoreUdevCallback func;
46         char *subsystem;
47         char *action;
48         void *user_data;
49 };
50
51 static const gchar *_default_subsystems[] = { NULL, };
52
53 static void _on_uevent(GUdevClient *client, gchar *action, GUdevDevice *device, gpointer user_data)
54 {
55         TcoreUdev *udev = user_data;
56         GSList *cb = NULL;
57         struct udev_callback_type *node;
58
59         if (!udev)
60                 return;
61
62         dbg("action = '%s'", action);
63
64         for (cb = udev->callbacks; cb; cb = cb->next) {
65                 node = cb->data;
66                 if (!node)
67                         continue;
68
69                 if (node->action)
70                         if (g_strcmp0(node->action, action) != 0)
71                                 continue;
72
73                 if (node->subsystem)
74                         if (g_strcmp0(node->subsystem, g_udev_device_get_subsystem(device)) != 0)
75                                 continue;
76
77                 if (!node->func)
78                         continue;
79
80                 node->func(udev, device, node->user_data);
81         }
82 }
83
84 TcoreUdev *tcore_udev_new(Server *s, const gchar **subsystems)
85 {
86         TcoreUdev *udev;
87
88         udev = calloc(1, sizeof(struct tcore_udev_type));
89         if (!udev)
90                 return NULL;
91
92         if (!subsystems) {
93                 subsystems = _default_subsystems;
94         }
95
96         udev->server = s;
97         udev->client = g_udev_client_new(subsystems);
98         if (!udev->client) {
99                 free(udev);
100                 return NULL;
101         }
102
103         g_signal_connect(udev->client, "uevent", G_CALLBACK(_on_uevent), udev);
104
105         udev->enumer = g_udev_enumerator_new(udev->client);
106
107         return udev;
108 }
109
110 void tcore_udev_free(TcoreUdev *udev)
111 {
112         if (!udev)
113                 return;
114
115         if (udev->client)
116                 g_object_unref(udev->client);
117
118         if (udev->enumer)
119                 g_object_unref(udev->enumer);
120
121         free(udev);
122 }
123
124 Server *tcore_udev_ref_server(TcoreUdev *udev)
125 {
126         if (!udev)
127                 return NULL;
128
129         return udev->server;
130 }
131
132 GUdevClient *tcore_udev_ref_client(TcoreUdev *udev)
133 {
134         if (!udev)
135                 return NULL;
136
137         return udev->client;
138 }
139
140 GUdevEnumerator *tcore_udev_ref_enumerator(TcoreUdev *udev)
141 {
142         if (!udev)
143                 return NULL;
144
145         return udev->enumer;
146 }
147
148 TReturn tcore_udev_add_enumerator_callback(TcoreUdev *udev, TcoreUdevEnumerCallback func, void *user_data)
149 {
150         struct udev_enumer_callback_type *node;
151
152         if (!udev || !func)
153                 return TCORE_RETURN_FAILURE;
154
155         node = calloc(1, sizeof(struct udev_enumer_callback_type));
156         if (!node)
157                 return TCORE_RETURN_ENOMEM;
158
159         node->func = func;
160         node->user_data = user_data;
161
162         udev->enumer_callbacks = g_slist_append(udev->enumer_callbacks, node);
163
164         return TCORE_RETURN_SUCCESS;
165 }
166
167 GList *tcore_udev_exec_enumerator(TcoreUdev *udev, gboolean event_emit_flag)
168 {
169         GList *list = NULL;
170         GSList *cb = NULL;
171         struct udev_enumer_callback_type *node;
172
173         if (!udev) {
174                 return NULL;
175         }
176
177         list = g_udev_enumerator_execute(udev->enumer);
178         if (!list) {
179                 return NULL;
180         }
181
182         if (event_emit_flag == FALSE)
183                 return list;
184
185         for (cb = udev->enumer_callbacks; cb; cb = cb->next) {
186                 node = cb->data;
187                 if (!node) {
188                         continue;
189                 }
190
191                 if (!node->func)
192                         continue;
193
194                 node->func(udev, list, node->user_data);
195         }
196
197         return list;
198 }
199
200 TReturn tcore_udev_add_callback(TcoreUdev *udev, const char *subsystem, const char *action, TcoreUdevCallback func, void *user_data)
201 {
202         struct udev_callback_type *node;
203
204         if (!udev || !func)
205                 return TCORE_RETURN_FAILURE;
206
207         node = calloc(1, sizeof(struct udev_callback_type));
208         if (!node)
209                 return TCORE_RETURN_ENOMEM;
210
211         node->func = func;
212         node->user_data = user_data;
213
214         if (subsystem)
215                 node->subsystem = strdup(subsystem);
216
217         if (action)
218                 node->action = strdup(action);
219
220         udev->callbacks = g_slist_append(udev->callbacks, node);
221
222         dbg("subsystem = [%s]", node->subsystem);
223         dbg("action = [%s]", node->action);
224         dbg("callbacks length = %d", g_slist_length(udev->callbacks));
225
226         return TCORE_RETURN_SUCCESS;
227 }
228