More activation motions
[gregoa/zavai.git] / src / gsm.vala
1 /*
2  * gsm - gsm resource for zavai
3  *
4  * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 using GLib;
22
23 namespace zavai {
24 namespace gsm {
25
26 // Isolate here the insane loops we need to go through to turn on the bloody
27 // gsm
28 protected class GSMActivator : Object
29 {
30     public dynamic DBus.Object device;
31     public dynamic DBus.Object network;
32     public dynamic DBus.Object sim;
33
34     public GSMActivator()
35     {
36         device = null;
37         network = null;
38         sim = null;
39     }
40
41     public void begin()
42     {
43         if (device == null)
44         {
45             device = zavai.registry.sbus.get_object(
46                     "org.freesmartphone.ogsmd", 
47                     "/org/freesmartphone/GSM/Device",
48                     "org.freesmartphone.GSM.Device");
49             network = zavai.registry.sbus.get_object(
50                 "org.freesmartphone.ogsmd", 
51                 "/org/freesmartphone/GSM/Device",
52                 "org.freesmartphone.GSM.Network");
53             sim = zavai.registry.sbus.get_object(
54                     "org.freesmartphone.ogsmd", 
55                     "/org/freesmartphone/GSM/Device",
56                     "org.freesmartphone.GSM.SIM");
57         }
58
59         device.SetAntennaPower(true, on_antenna_power);
60     }
61
62     protected void on_antenna_power(Error e)
63     {
64         if (e != null)
65         {
66             zavai.log.warning("on_antenna_power: " + e.message);
67             if (e.message.str("current status is 'enabling'") != null
68                 || e.message.str("current status is 'unknown'") != null)
69             {
70                 zavai.log.info("trying again after 5 seconds");
71                 Timeout.add(5 * 1000, () => {
72                     device.SetAntennaPower(true, on_antenna_power);
73                     return false;
74                 });
75             } else {
76                 sim.GetAuthStatus(on_auth_status);
77             }
78             return;
79         }
80         zavai.log.warning("on_antenna_power ok");
81         network.Register(on_network_register);
82     }
83
84     protected void on_network_register(Error e)
85     {
86         if (e != null)
87         {
88             zavai.log.warning("on_network_register: " + e.message);
89             return;
90         }
91         zavai.log.info("on_network_register: registered");
92     }
93
94     protected void on_auth_status(string status, Error e)
95     {
96         if (e != null)
97         {
98             zavai.log.warning("on_auth_status: " + e.message);
99             return;
100         }
101         zavai.log.info("on_auth_status: " + status);
102         if (status == "READY")
103             device.SetAntennaPower(true, on_antenna_power);
104         else if (status == "SIM PIN")
105             sim.SendAuthCode(zavai.config.sim_pin, on_auth_code);
106         else
107             zavai.log.debug("Unknown status: " + status);
108     }
109
110     protected void on_auth_code(Error e)
111     {
112         if (e != null)
113         {
114             zavai.log.warning("on_auth_code: " + e.message);
115             return;
116         }
117         zavai.log.info("PIN OK");
118     }
119 }
120
121 public class GSM: zavai.Service
122 {
123     protected dynamic DBus.Object dbus;
124     public dynamic DBus.Object call;
125     protected Pid child_pid;
126     protected int child_watch_id;
127     protected GSMActivator activator;
128
129     public GSM()
130     {
131         Object(name: "gsm.gsm");
132
133         activator = new GSMActivator();
134
135         call = null;
136
137         child_pid = 0;
138         child_watch_id = 0;
139
140         dbus = zavai.registry.sbus.get_object(
141                 "org.freedesktop.DBus",
142                 "/org/freedesktop/DBus",
143                 "org.freedesktop.DBus");
144         dbus.NameOwnerChanged += on_name_owner_changed;
145     }
146
147     /// Request GPS resource
148     public override void start()
149     {
150         if (started) return;
151
152         string command = zavai.config.homedir + "/gsm pre";
153         try {
154             // Then run our own script
155             zavai.app.run_script(command);
156         } catch (Error e) {
157             zavai.log.error("Running " + command + ": " + e.message);
158             return;
159         }
160
161         command = zavai.config.homedir + "/gsm run";
162         zavai.log.info("Run program: " + command);
163         string[] args = command.split(" ");
164         try {
165             Process.spawn_async(
166                 Environment.get_home_dir(),
167                 args,
168                 null,
169                 SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
170                 null,
171                 out child_pid);
172         } catch (SpawnError e) {
173             zavai.log.error("Running " + command + ": " + e.message);
174         }
175
176         // Add a child watch source to know when it ends
177         ChildWatch.add(child_pid, on_child);
178
179         call = zavai.registry.sbus.get_object(
180             "org.freesmartphone.ogsmd", 
181             "/org/freesmartphone/GSM/Device",
182             "org.freesmartphone.GSM.Call");
183
184         // try {
185         //     device.Enable();
186         //     zavai.log.info("Started GSM");
187         //     base.start();
188         // } catch (GLib.Error e) {
189         //     zavai.log.error(e.message);
190         // }
191         base.start();
192     }
193
194     protected void on_name_owner_changed(DBus.Object sender, string name, string oldOwner, string newOwner)
195     {
196         zavai.log.debug("NOC " + name + " from " + oldOwner + " to " + newOwner);
197         if (name == "org.freesmartphone.ogsmd" && newOwner != "")
198             activator.begin();
199     }
200
201     // Release usage of GPS
202     public override void stop()
203     {
204         if (!started) return;
205
206         Posix.kill((Posix.pid_t)child_pid, Posix.SIGTERM);
207     }
208
209     public void on_child(Pid pid, int status)
210     {
211         zavai.log.info("Exited");
212 stderr.printf("STATUS %d\n", status);
213         Process.close_pid(pid);
214
215         // try {
216         //     device.Disable();
217         //     zavai.log.info("Stopped GSM");
218         //     base.stop();
219         // } catch (GLib.Error e) {
220         //     zavai.log.error(e.message);
221         // }
222
223         string command = zavai.config.homedir + "/gsm post";
224         try {
225             // Then run our own script
226             zavai.app.run_script(command);
227         } catch (Error e) {
228             zavai.log.error("Running " + command + ": " + e.message);
229             return;
230         }
231
232         call = null;
233
234         base.stop();
235     }
236 }
237
238 public class GPRS: zavai.Service
239 {
240     public dynamic DBus.Object device;
241
242     public GPRS()
243     {
244         Object(name: "gsm.gprs");
245
246         device = zavai.registry.sbus.get_object(
247             "org.freesmartphone.ogsmd", 
248             "/org/freesmartphone/GSM/Device",
249             "org.freesmartphone.GSM.PDP");
250     }
251
252     /// Request GPS resource
253     public override void start()
254     {
255         if (started) return;
256         try {
257             //gsm.request(name);
258             device.ActivateContext(
259                 zavai.config.gprs_apn,
260                 zavai.config.gprs_user,
261                 zavai.config.gprs_pass);
262             zavai.log.info("Started GPRS");
263             base.start();
264         } catch (GLib.Error e) {
265             zavai.log.error(e.message);
266         }
267         base.start();
268     }
269
270     // Release usage of GPS
271     public override void stop()
272     {
273         if (!started) return;
274         try {
275             //gsm.release(name);
276             device.DeactivateContext();
277             zavai.log.info("Stopped GPRS");
278             base.stop();
279         } catch (GLib.Error e) {
280             zavai.log.error(e.message);
281         }
282         base.stop();
283     }
284 }
285
286 public zavai.gsm.GSM gsm = null;
287 public zavai.gsm.GPRS gprs = null;
288
289 public void init()
290 {
291     gsm = new GSM();
292     gprs = new GPRS();
293 }
294
295 }
296 }