usb_moded  0.86.0+mer57
usb_moded-trigger.c
Go to the documentation of this file.
1 
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 
46 static void trigger_udev_error_cb (gpointer data);
47 bool trigger_init (void);
48 static gboolean trigger_udev_input_cb (GIOChannel *iochannel, GIOCondition cond, gpointer data);
49 void trigger_stop (void);
50 static void trigger_parse_udev_properties(struct udev_device *dev);
51 
52 /* ========================================================================= *
53  * Data
54  * ========================================================================= */
55 
56 static struct udev *trigger_udev_handle = 0;
57 static struct udev_monitor *trigger_udev_monitor = 0;
58 static guint trigger_udev_watch_id = 0;
59 static gchar *trigger_udev_sysname = 0;
60 
61 /* ========================================================================= *
62  * Functions
63  * ========================================================================= */
64 
65 static 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 
77 bool 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 
153 EXIT:
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 
170 static 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 
211 void 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 
234 static 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 
263 EXIT:
264  free(trigger_value);
265  free(trigger_property);
266  free(trigger_mode);
267 }
usb_moded-trigger.h
usb_moded-config-private.h
usbmoded_can_export
bool usbmoded_can_export(void)
Definition: usb_moded.c:591
usb_moded.h
usb_moded-control.h
control_select_mode
bool control_select_mode(const char *mode)
Definition: usb_moded-control.c:307
usb_moded-log.h