usb_moded 0.86.0+mer64
usb_moded-trigger.c
Go to the documentation of this file.
1
28
29#include "usb_moded-trigger.h"
30
31#include "usb_moded.h"
33#include "usb_moded-control.h"
34#include "usb_moded-log.h"
35
36#include <libudev.h>
37
38/* ========================================================================= *
39 * Prototypes
40 * ========================================================================= */
41
42/* ------------------------------------------------------------------------- *
43 * TRIGGER
44 * ------------------------------------------------------------------------- */
45
46static void trigger_udev_error_cb (gpointer data);
47bool trigger_init (void);
48static gboolean trigger_udev_input_cb (GIOChannel *iochannel, GIOCondition cond, gpointer data);
49void trigger_stop (void);
50static void trigger_parse_udev_properties(struct udev_device *dev);
51
52/* ========================================================================= *
53 * Data
54 * ========================================================================= */
55
56static struct udev *trigger_udev_handle = 0;
57static struct udev_monitor *trigger_udev_monitor = 0;
58static guint trigger_udev_watch_id = 0;
59static gchar *trigger_udev_sysname = 0;
60
61/* ========================================================================= *
62 * Functions
63 * ========================================================================= */
64
65static void trigger_udev_error_cb (gpointer data)
66{
67 LOG_REGISTER_CONTEXT;
68
69 (void)data;
70
71 log_debug("trigger watch destroyed\n!");
72 /* clean up & restart trigger */
73 trigger_stop();
74 trigger_init();
75}
76
77bool trigger_init(void)
78{
79 LOG_REGISTER_CONTEXT;
80
81 bool ack = false;
82
83 gchar *devpath = 0;
84 gchar *subsystem = 0;
85 struct udev_device *dev = 0;
86 GIOChannel *chn = 0;
87
88 int ret;
89
90 if( !(devpath = config_check_trigger()) ) {
91 log_err("No trigger path. Not starting trigger.\n");
92 goto EXIT;
93 }
94
95 if( !(subsystem = config_get_trigger_subsystem()) ) {
96 log_err("No trigger subsystem. Not starting trigger.\n");
97 goto EXIT;
98 }
99
100 /* Create the udev object */
101 if( !(trigger_udev_handle = udev_new()) ) {
102 log_err("Can't create udev\n");
103 }
104
105 dev = udev_device_new_from_syspath(trigger_udev_handle, devpath);
106 if( !dev ) {
107 log_err("Unable to find the trigger device.");
108 goto EXIT;
109 }
110
111 trigger_udev_sysname = g_strdup(udev_device_get_sysname(dev));
112 log_debug("device name = %s\n", trigger_udev_sysname);
113
114 trigger_udev_monitor = udev_monitor_new_from_netlink(trigger_udev_handle,
115 "udev");
116 if( !trigger_udev_monitor ) {
117 log_err("Unable to monitor the netlink\n");
118 goto EXIT;
119 }
120
121 ret = udev_monitor_filter_add_match_subsystem_devtype(trigger_udev_monitor,
122 subsystem,
123 NULL);
124 if (ret != 0 ) {
125 log_err("Udev match failed.\n");
126 goto EXIT;
127 }
128
129 ret = udev_monitor_enable_receiving(trigger_udev_monitor);
130 if( ret != 0 ) {
131 log_err("Failed to enable monitor recieving.\n");
132 goto EXIT;
133 }
134
135 /* check if we are already connected */
136 trigger_parse_udev_properties(dev);
137
138 chn = g_io_channel_unix_new(udev_monitor_get_fd(trigger_udev_monitor));
139 if( !chn )
140 goto EXIT;
141
142 trigger_udev_watch_id = g_io_add_watch_full(chn,
143 0,
144 G_IO_IN,
145 trigger_udev_input_cb,
146 NULL,
147 trigger_udev_error_cb);
148
149 /* everything went well */
150 log_debug("Trigger enabled!\n");
151 ack = true;
152
153EXIT:
154 if(chn)
155 g_io_channel_unref(chn);
156
157 if( dev )
158 udev_device_unref(dev);
159
160 g_free(subsystem);
161 g_free(devpath);
162
163 /* All or nothing */
164 if( !ack )
165 trigger_stop();
166
167 return ack;
168}
169
170static gboolean trigger_udev_input_cb(GIOChannel *iochannel G_GNUC_UNUSED, GIOCondition cond,
171 gpointer data G_GNUC_UNUSED)
172{
173 LOG_REGISTER_CONTEXT;
174
175 struct udev_device *dev;
176
177 if(cond & G_IO_IN)
178 {
179 /* This normally blocks but G_IO_IN indicates that we can read */
180 dev = udev_monitor_receive_device (trigger_udev_monitor);
181 if (dev)
182 {
183 /* check if it is the actual device we want to check */
184 if(strcmp(trigger_udev_sysname, udev_device_get_sysname(dev))) {
185 log_crit("name does not match, disabling udev trigger io-watch");
186 trigger_udev_watch_id = 0;
187 return FALSE;
188 }
189
190 if(!strcmp(udev_device_get_action(dev), "change"))
191 {
192 log_debug("Trigger event recieved.\n");
193 trigger_parse_udev_properties(dev);
194 }
195 udev_device_unref(dev);
196 }
197 /* if we get something else something bad happened stop watching to avoid busylooping */
198 else
199 {
200 log_debug("Bad trigger data. Stopping\n");
201 trigger_udev_watch_id = 0;
202 trigger_stop();
203 return FALSE;
204 }
205 }
206
207 /* keep watching */
208 return TRUE;
209}
210
211void trigger_stop(void)
212{
213 LOG_REGISTER_CONTEXT;
214
215 if(trigger_udev_watch_id)
216 {
217 g_source_remove(trigger_udev_watch_id);
218 trigger_udev_watch_id = 0;
219 }
220 if(trigger_udev_monitor)
221 {
222 udev_monitor_unref(trigger_udev_monitor);
223 trigger_udev_monitor = 0;
224 }
225 if(trigger_udev_handle)
226 {
227 udev_unref(trigger_udev_handle);
228 trigger_udev_handle = 0;
229 }
230 g_free(trigger_udev_sysname),
231 trigger_udev_sysname = 0;
232}
233
234static void trigger_parse_udev_properties(struct udev_device *dev)
235{
236 LOG_REGISTER_CONTEXT;
237
238 char *trigger_property = 0;
239 char *trigger_value = 0;
240 char *trigger_mode = 0;
241
242 const char *value = 0;
243
244 if( !usbmoded_can_export() )
245 goto EXIT;
246
247 if( !(trigger_mode = config_get_trigger_mode()) )
248 goto EXIT;
249
250 if( !(trigger_property = config_get_trigger_property()) )
251 goto EXIT;
252
253 if( !(value = udev_device_get_property_value(dev, trigger_property)) )
254 goto EXIT;
255
256 if( (trigger_value = config_get_trigger_value()) ) {
257 if( strcmp(trigger_value, value) )
258 goto EXIT;
259 }
260
261 control_select_mode(trigger_mode);
262
263EXIT:
264 free(trigger_value);
265 free(trigger_property);
266 free(trigger_mode);
267}
bool control_select_mode(const char *mode)
bool usbmoded_can_export(void)
Definition usb_moded.c:627