db62e2d864af668de4e9272e69ea5059cedb9c30
[profile/ivi/ofono.git] / src / modem.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29
30 #include <glib.h>
31 #include <gdbus.h>
32
33 #include "ofono.h"
34
35 #include "common.h"
36
37 static GSList *g_devinfo_drivers = NULL;
38 static GSList *g_driver_list = NULL;
39 static GSList *g_modem_list = NULL;
40
41 static int next_modem_id = 0;
42 static gboolean powering_down = FALSE;
43 static int modems_remaining = 0;
44
45 static struct ofono_watchlist *g_modemwatches = NULL;
46
47 enum property_type {
48         PROPERTY_TYPE_INVALID = 0,
49         PROPERTY_TYPE_STRING,
50         PROPERTY_TYPE_INTEGER,
51         PROPERTY_TYPE_BOOLEAN,
52 };
53
54 enum modem_state {
55         MODEM_STATE_POWER_OFF,
56         MODEM_STATE_PRE_SIM,
57         MODEM_STATE_OFFLINE,
58         MODEM_STATE_ONLINE,
59 };
60
61 struct ofono_modem {
62         char                    *path;
63         enum modem_state        modem_state;
64         GSList                  *atoms;
65         struct ofono_watchlist  *atom_watches;
66         GSList                  *interface_list;
67         GSList                  *feature_list;
68         unsigned int            call_ids;
69         DBusMessage             *pending;
70         guint                   interface_update;
71         ofono_bool_t            powered;
72         ofono_bool_t            powered_pending;
73         ofono_bool_t            get_online;
74         ofono_bool_t            lockdown;
75         char                    *lock_owner;
76         guint                   lock_watch;
77         guint                   timeout;
78         ofono_bool_t            online;
79         struct ofono_watchlist  *online_watches;
80         struct ofono_watchlist  *powered_watches;
81         guint                   emergency;
82         GHashTable              *properties;
83         struct ofono_sim        *sim;
84         unsigned int            sim_watch;
85         unsigned int            sim_ready_watch;
86         const struct ofono_modem_driver *driver;
87         void                    *driver_data;
88         char                    *driver_type;
89         char                    *name;
90 };
91
92 struct ofono_devinfo {
93         char *manufacturer;
94         char *model;
95         char *revision;
96         char *serial;
97         unsigned int dun_watch;
98         const struct ofono_devinfo_driver *driver;
99         void *driver_data;
100         struct ofono_atom *atom;
101 };
102
103 struct ofono_atom {
104         enum ofono_atom_type type;
105         enum modem_state modem_state;
106         void (*destruct)(struct ofono_atom *atom);
107         void (*unregister)(struct ofono_atom *atom);
108         void *data;
109         struct ofono_modem *modem;
110 };
111
112 struct atom_watch {
113         struct ofono_watchlist_item item;
114         enum ofono_atom_type type;
115 };
116
117 struct modem_property {
118         enum property_type type;
119         void *value;
120 };
121
122 static const char *modem_type_to_string(enum ofono_modem_type type)
123 {
124         switch (type) {
125         case OFONO_MODEM_TYPE_HARDWARE:
126                 return "hardware";
127         case OFONO_MODEM_TYPE_HFP:
128                 return "hfp";
129         case OFONO_MODEM_TYPE_SAP:
130                 return "sap";
131         }
132
133         return "unknown";
134 }
135
136 unsigned int __ofono_modem_callid_next(struct ofono_modem *modem)
137 {
138         unsigned int i;
139
140         for (i = 1; i < sizeof(modem->call_ids) * 8; i++) {
141                 if (modem->call_ids & (1 << i))
142                         continue;
143
144                 return i;
145         }
146
147         return 0;
148 }
149
150 void __ofono_modem_callid_hold(struct ofono_modem *modem, int id)
151 {
152         modem->call_ids |= (1 << id);
153 }
154
155 void __ofono_modem_callid_release(struct ofono_modem *modem, int id)
156 {
157         modem->call_ids &= ~(1 << id);
158 }
159
160 void ofono_modem_set_data(struct ofono_modem *modem, void *data)
161 {
162         if (modem == NULL)
163                 return;
164
165         modem->driver_data = data;
166 }
167
168 void *ofono_modem_get_data(struct ofono_modem *modem)
169 {
170         if (modem == NULL)
171                 return NULL;
172
173         return modem->driver_data;
174 }
175
176 const char *ofono_modem_get_path(struct ofono_modem *modem)
177 {
178         if (modem)
179                 return modem->path;
180
181         return NULL;
182 }
183
184 struct ofono_atom *__ofono_modem_add_atom(struct ofono_modem *modem,
185                                         enum ofono_atom_type type,
186                                         void (*destruct)(struct ofono_atom *),
187                                         void *data)
188 {
189         struct ofono_atom *atom;
190
191         if (modem == NULL)
192                 return NULL;
193
194         atom = g_new0(struct ofono_atom, 1);
195
196         atom->type = type;
197         atom->modem_state = modem->modem_state;
198         atom->destruct = destruct;
199         atom->data = data;
200         atom->modem = modem;
201
202         modem->atoms = g_slist_prepend(modem->atoms, atom);
203
204         return atom;
205 }
206
207 struct ofono_atom *__ofono_modem_add_atom_offline(struct ofono_modem *modem,
208                                         enum ofono_atom_type type,
209                                         void (*destruct)(struct ofono_atom *),
210                                         void *data)
211 {
212         struct ofono_atom *atom;
213
214         atom = __ofono_modem_add_atom(modem, type, destruct, data);
215
216         atom->modem_state = MODEM_STATE_OFFLINE;
217
218         return atom;
219 }
220
221 void *__ofono_atom_get_data(struct ofono_atom *atom)
222 {
223         return atom->data;
224 }
225
226 const char *__ofono_atom_get_path(struct ofono_atom *atom)
227 {
228         return atom->modem->path;
229 }
230
231 struct ofono_modem *__ofono_atom_get_modem(struct ofono_atom *atom)
232 {
233         return atom->modem;
234 }
235
236 static void call_watches(struct ofono_atom *atom,
237                                 enum ofono_atom_watch_condition cond)
238 {
239         struct ofono_modem *modem = atom->modem;
240         GSList *atom_watches = modem->atom_watches->items;
241         GSList *l;
242         struct atom_watch *watch;
243         ofono_atom_watch_func notify;
244
245         for (l = atom_watches; l; l = l->next) {
246                 watch = l->data;
247
248                 if (watch->type != atom->type)
249                         continue;
250
251                 notify = watch->item.notify;
252                 notify(atom, cond, watch->item.notify_data);
253         }
254 }
255
256 void __ofono_atom_register(struct ofono_atom *atom,
257                         void (*unregister)(struct ofono_atom *))
258 {
259         if (unregister == NULL)
260                 return;
261
262         atom->unregister = unregister;
263
264         call_watches(atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED);
265 }
266
267 void __ofono_atom_unregister(struct ofono_atom *atom)
268 {
269         if (atom->unregister == NULL)
270                 return;
271
272         call_watches(atom, OFONO_ATOM_WATCH_CONDITION_UNREGISTERED);
273
274         atom->unregister(atom);
275         atom->unregister = NULL;
276 }
277
278 gboolean __ofono_atom_get_registered(struct ofono_atom *atom)
279 {
280         return atom->unregister ? TRUE : FALSE;
281 }
282
283 unsigned int __ofono_modem_add_atom_watch(struct ofono_modem *modem,
284                                         enum ofono_atom_type type,
285                                         ofono_atom_watch_func notify,
286                                         void *data, ofono_destroy_func destroy)
287 {
288         struct atom_watch *watch;
289         unsigned int id;
290         GSList *l;
291         struct ofono_atom *atom;
292
293         if (notify == NULL)
294                 return 0;
295
296         watch = g_new0(struct atom_watch, 1);
297
298         watch->type = type;
299         watch->item.notify = notify;
300         watch->item.destroy = destroy;
301         watch->item.notify_data = data;
302
303         id = __ofono_watchlist_add_item(modem->atom_watches,
304                                         (struct ofono_watchlist_item *)watch);
305
306         for (l = modem->atoms; l; l = l->next) {
307                 atom = l->data;
308
309                 if (atom->type != type || atom->unregister == NULL)
310                         continue;
311
312                 notify(atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED, data);
313         }
314
315         return id;
316 }
317
318 gboolean __ofono_modem_remove_atom_watch(struct ofono_modem *modem,
319                                                 unsigned int id)
320 {
321         return __ofono_watchlist_remove_item(modem->atom_watches, id);
322 }
323
324 struct ofono_atom *__ofono_modem_find_atom(struct ofono_modem *modem,
325                                                 enum ofono_atom_type type)
326 {
327         GSList *l;
328         struct ofono_atom *atom;
329
330         if (modem == NULL)
331                 return NULL;
332
333         for (l = modem->atoms; l; l = l->next) {
334                 atom = l->data;
335
336                 if (atom->type == type && atom->unregister != NULL)
337                         return atom;
338         }
339
340         return NULL;
341 }
342
343 void __ofono_modem_foreach_atom(struct ofono_modem *modem,
344                                 enum ofono_atom_type type,
345                                 ofono_atom_func callback, void *data)
346 {
347         GSList *l;
348         struct ofono_atom *atom;
349
350         if (modem == NULL)
351                 return;
352
353         for (l = modem->atoms; l; l = l->next) {
354                 atom = l->data;
355
356                 if (atom->type != type)
357                         continue;
358
359                 callback(atom, data);
360         }
361 }
362
363 void __ofono_modem_foreach_registered_atom(struct ofono_modem *modem,
364                                                 enum ofono_atom_type type,
365                                                 ofono_atom_func callback,
366                                                 void *data)
367 {
368         GSList *l;
369         struct ofono_atom *atom;
370
371         if (modem == NULL)
372                 return;
373
374         for (l = modem->atoms; l; l = l->next) {
375                 atom = l->data;
376
377                 if (atom->type != type)
378                         continue;
379
380                 if (atom->unregister == NULL)
381                         continue;
382
383                 callback(atom, data);
384         }
385 }
386
387 void __ofono_atom_free(struct ofono_atom *atom)
388 {
389         struct ofono_modem *modem = atom->modem;
390
391         modem->atoms = g_slist_remove(modem->atoms, atom);
392
393         __ofono_atom_unregister(atom);
394
395         if (atom->destruct)
396                 atom->destruct(atom);
397
398         g_free(atom);
399 }
400
401 static void flush_atoms(struct ofono_modem *modem, enum modem_state new_state)
402 {
403         GSList *cur;
404         GSList *prev;
405         GSList *tmp;
406
407         DBG("");
408
409         prev = NULL;
410         cur = modem->atoms;
411
412         while (cur) {
413                 struct ofono_atom *atom = cur->data;
414
415                 if (atom->modem_state <= new_state) {
416                         prev = cur;
417                         cur = cur->next;
418                         continue;
419                 }
420
421                 __ofono_atom_unregister(atom);
422
423                 if (atom->destruct)
424                         atom->destruct(atom);
425
426                 g_free(atom);
427
428                 if (prev)
429                         prev->next = cur->next;
430                 else
431                         modem->atoms = cur->next;
432
433                 tmp = cur;
434                 cur = cur->next;
435                 g_slist_free_1(tmp);
436         }
437 }
438
439 static void notify_online_watches(struct ofono_modem *modem)
440 {
441         struct ofono_watchlist_item *item;
442         GSList *l;
443         ofono_modem_online_notify_func notify;
444
445         if (modem->online_watches == NULL)
446                 return;
447
448         for (l = modem->online_watches->items; l; l = l->next) {
449                 item = l->data;
450                 notify = item->notify;
451                 notify(modem, modem->online, item->notify_data);
452         }
453 }
454
455 static void notify_powered_watches(struct ofono_modem *modem)
456 {
457         struct ofono_watchlist_item *item;
458         GSList *l;
459         ofono_modem_powered_notify_func notify;
460
461         if (modem->powered_watches == NULL)
462                 return;
463
464         for (l = modem->powered_watches->items; l; l = l->next) {
465                 item = l->data;
466                 notify = item->notify;
467                 notify(modem, modem->powered, item->notify_data);
468         }
469 }
470
471 static void set_online(struct ofono_modem *modem, ofono_bool_t new_online)
472 {
473         DBusConnection *conn = ofono_dbus_get_connection();
474
475         if (new_online == modem->online)
476                 return;
477
478         modem->online = new_online;
479
480         ofono_dbus_signal_property_changed(conn, modem->path,
481                                                 OFONO_MODEM_INTERFACE,
482                                                 "Online", DBUS_TYPE_BOOLEAN,
483                                                 &modem->online);
484
485         notify_online_watches(modem);
486 }
487
488 static void modem_change_state(struct ofono_modem *modem,
489                                 enum modem_state new_state)
490 {
491         struct ofono_modem_driver const *driver = modem->driver;
492         enum modem_state old_state = modem->modem_state;
493
494         DBG("old state: %d, new state: %d", old_state, new_state);
495
496         if (old_state == new_state)
497                 return;
498
499         modem->modem_state = new_state;
500
501         if (old_state > new_state)
502                 flush_atoms(modem, new_state);
503
504         switch (new_state) {
505         case MODEM_STATE_POWER_OFF:
506                 modem->call_ids = 0;
507                 break;
508
509         case MODEM_STATE_PRE_SIM:
510                 if (old_state < MODEM_STATE_PRE_SIM && driver->pre_sim)
511                         driver->pre_sim(modem);
512                 break;
513
514         case MODEM_STATE_OFFLINE:
515                 if (old_state < MODEM_STATE_OFFLINE) {
516                         if (driver->post_sim)
517                                 driver->post_sim(modem);
518
519                         __ofono_history_probe_drivers(modem);
520                         __ofono_nettime_probe_drivers(modem);
521                 }
522
523                 break;
524
525         case MODEM_STATE_ONLINE:
526                 if (driver->post_online)
527                         driver->post_online(modem);
528
529                 break;
530         }
531 }
532
533 unsigned int __ofono_modem_add_online_watch(struct ofono_modem *modem,
534                                         ofono_modem_online_notify_func notify,
535                                         void *data, ofono_destroy_func destroy)
536 {
537         struct ofono_watchlist_item *item;
538
539         if (modem == NULL || notify == NULL)
540                 return 0;
541
542         item = g_new0(struct ofono_watchlist_item, 1);
543
544         item->notify = notify;
545         item->destroy = destroy;
546         item->notify_data = data;
547
548         return __ofono_watchlist_add_item(modem->online_watches, item);
549 }
550
551 void __ofono_modem_remove_online_watch(struct ofono_modem *modem,
552                                         unsigned int id)
553 {
554         __ofono_watchlist_remove_item(modem->online_watches, id);
555 }
556
557 unsigned int __ofono_modem_add_powered_watch(struct ofono_modem *modem,
558                                         ofono_modem_powered_notify_func notify,
559                                         void *data, ofono_destroy_func destroy)
560 {
561         struct ofono_watchlist_item *item;
562
563         if (modem == NULL || notify == NULL)
564                 return 0;
565
566         item = g_new0(struct ofono_watchlist_item, 1);
567
568         item->notify = notify;
569         item->destroy = destroy;
570         item->notify_data = data;
571
572         return __ofono_watchlist_add_item(modem->powered_watches, item);
573 }
574
575 void __ofono_modem_remove_powered_watch(struct ofono_modem *modem,
576                                         unsigned int id)
577 {
578         __ofono_watchlist_remove_item(modem->powered_watches, id);
579 }
580
581 static gboolean modem_has_sim(struct ofono_modem *modem)
582 {
583         GSList *l;
584         struct ofono_atom *atom;
585
586         for (l = modem->atoms; l; l = l->next) {
587                 atom = l->data;
588
589                 if (atom->type == OFONO_ATOM_TYPE_SIM)
590                         return TRUE;
591         }
592
593         return FALSE;
594 }
595
596 static void common_online_cb(const struct ofono_error *error, void *data)
597 {
598         struct ofono_modem *modem = data;
599
600         if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
601                 return;
602
603         /*
604          * If we need to get online after a silent reset this callback
605          * is called.  The callback should not consider the pending dbus
606          * message.
607          *
608          * Additionally, this process can be interrupted by the following
609          * events:
610          *      - Sim being removed or reset
611          *      - SetProperty(Powered, False) being called
612          *      - SetProperty(Lockdown, True) being called
613          *
614          * We should not set the modem to the online state in these cases.
615          */
616         switch (modem->modem_state) {
617         case MODEM_STATE_OFFLINE:
618                 set_online(modem, TRUE);
619
620                 /* Will this increase emergency call setup time??? */
621                 modem_change_state(modem, MODEM_STATE_ONLINE);
622                 break;
623         case MODEM_STATE_POWER_OFF:
624                 /* The powered operation is pending */
625                 break;
626         case MODEM_STATE_PRE_SIM:
627                 /*
628                  * Its valid to be in online even without a SIM/SIM being
629                  * PIN locked. e.g.: Emergency mode
630                  */
631                 DBG("Online in PRE SIM state");
632
633                 set_online(modem, TRUE);
634                 break;
635         case MODEM_STATE_ONLINE:
636                 ofono_error("Online called when the modem is already online!");
637                 break;
638         };
639 }
640
641 static void online_cb(const struct ofono_error *error, void *data)
642 {
643         struct ofono_modem *modem = data;
644         DBusMessage *reply;
645
646         if (!modem->pending)
647                 goto out;
648
649         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
650                 reply = dbus_message_new_method_return(modem->pending);
651         else
652                 reply = __ofono_error_failed(modem->pending);
653
654         __ofono_dbus_pending_reply(&modem->pending, reply);
655
656 out:
657         common_online_cb(error, data);
658 }
659
660 static void offline_cb(const struct ofono_error *error, void *data)
661 {
662         struct ofono_modem *modem = data;
663         DBusMessage *reply;
664
665         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
666                 reply = dbus_message_new_method_return(modem->pending);
667         else
668                 reply = __ofono_error_failed(modem->pending);
669
670         __ofono_dbus_pending_reply(&modem->pending, reply);
671
672         if (error->type == OFONO_ERROR_TYPE_NO_ERROR) {
673                 switch (modem->modem_state) {
674                 case MODEM_STATE_PRE_SIM:
675                         set_online(modem, FALSE);
676                         break;
677                 case MODEM_STATE_ONLINE:
678                         set_online(modem, FALSE);
679                         modem_change_state(modem, MODEM_STATE_OFFLINE);
680                         break;
681                 default:
682                         break;
683                 }
684         }
685 }
686
687 static void sim_state_watch(enum ofono_sim_state new_state, void *user)
688 {
689         struct ofono_modem *modem = user;
690
691         switch (new_state) {
692         case OFONO_SIM_STATE_NOT_PRESENT:
693                 modem_change_state(modem, MODEM_STATE_PRE_SIM);
694         case OFONO_SIM_STATE_INSERTED:
695                 break;
696         case OFONO_SIM_STATE_LOCKED_OUT:
697                 modem_change_state(modem, MODEM_STATE_PRE_SIM);
698                 break;
699         case OFONO_SIM_STATE_READY:
700                 modem_change_state(modem, MODEM_STATE_OFFLINE);
701
702                 /*
703                  * If we don't have the set_online method, also proceed
704                  * straight to the online state
705                  */
706                 if (modem->driver->set_online == NULL)
707                         set_online(modem, TRUE);
708
709                 if (modem->online == TRUE)
710                         modem_change_state(modem, MODEM_STATE_ONLINE);
711                 else if (modem->get_online)
712                         modem->driver->set_online(modem, 1, common_online_cb,
713                                                         modem);
714
715                 modem->get_online = FALSE;
716
717                 break;
718         }
719 }
720
721 static DBusMessage *set_property_online(struct ofono_modem *modem,
722                                         DBusMessage *msg,
723                                         DBusMessageIter *var)
724 {
725         ofono_bool_t online;
726         const struct ofono_modem_driver *driver = modem->driver;
727
728         if (modem->powered == FALSE)
729                 return __ofono_error_not_available(msg);
730
731         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN)
732                 return __ofono_error_invalid_args(msg);
733
734         dbus_message_iter_get_basic(var, &online);
735
736         if (modem->pending != NULL)
737                 return __ofono_error_busy(msg);
738
739         if (modem->online == online)
740                 return dbus_message_new_method_return(msg);
741
742         if (ofono_modem_get_emergency_mode(modem) == TRUE)
743                 return __ofono_error_emergency_active(msg);
744
745         if (driver->set_online == NULL)
746                 return __ofono_error_not_implemented(msg);
747
748         modem->pending = dbus_message_ref(msg);
749
750         driver->set_online(modem, online,
751                                 online ? online_cb : offline_cb, modem);
752
753         return NULL;
754 }
755
756 ofono_bool_t ofono_modem_get_online(struct ofono_modem *modem)
757 {
758         if (modem == NULL)
759                 return FALSE;
760
761         return modem->online;
762 }
763
764 void __ofono_modem_append_properties(struct ofono_modem *modem,
765                                                 DBusMessageIter *dict)
766 {
767         char **interfaces;
768         char **features;
769         int i;
770         GSList *l;
771         struct ofono_devinfo *info;
772         dbus_bool_t emergency = ofono_modem_get_emergency_mode(modem);
773         const char *strtype;
774
775         ofono_dbus_dict_append(dict, "Online", DBUS_TYPE_BOOLEAN,
776                                 &modem->online);
777
778         ofono_dbus_dict_append(dict, "Powered", DBUS_TYPE_BOOLEAN,
779                                 &modem->powered);
780
781         ofono_dbus_dict_append(dict, "Lockdown", DBUS_TYPE_BOOLEAN,
782                                 &modem->lockdown);
783
784         ofono_dbus_dict_append(dict, "Emergency", DBUS_TYPE_BOOLEAN,
785                                 &emergency);
786
787         info = __ofono_atom_find(OFONO_ATOM_TYPE_DEVINFO, modem);
788         if (info) {
789                 if (info->manufacturer)
790                         ofono_dbus_dict_append(dict, "Manufacturer",
791                                                 DBUS_TYPE_STRING,
792                                                 &info->manufacturer);
793
794                 if (info->model)
795                         ofono_dbus_dict_append(dict, "Model", DBUS_TYPE_STRING,
796                                                 &info->model);
797
798                 if (info->revision)
799                         ofono_dbus_dict_append(dict, "Revision",
800                                                 DBUS_TYPE_STRING,
801                                                 &info->revision);
802
803                 if (info->serial)
804                         ofono_dbus_dict_append(dict, "Serial",
805                                                 DBUS_TYPE_STRING,
806                                                 &info->serial);
807         }
808
809         interfaces = g_new0(char *, g_slist_length(modem->interface_list) + 1);
810         for (i = 0, l = modem->interface_list; l; l = l->next, i++)
811                 interfaces[i] = l->data;
812         ofono_dbus_dict_append_array(dict, "Interfaces", DBUS_TYPE_STRING,
813                                         &interfaces);
814         g_free(interfaces);
815
816         features = g_new0(char *, g_slist_length(modem->feature_list) + 1);
817         for (i = 0, l = modem->feature_list; l; l = l->next, i++)
818                 features[i] = l->data;
819         ofono_dbus_dict_append_array(dict, "Features", DBUS_TYPE_STRING,
820                                         &features);
821         g_free(features);
822
823         if (modem->name)
824                 ofono_dbus_dict_append(dict, "Name", DBUS_TYPE_STRING,
825                                         &modem->name);
826
827         strtype = modem_type_to_string(modem->driver->modem_type);
828         ofono_dbus_dict_append(dict, "Type", DBUS_TYPE_STRING, &strtype);
829 }
830
831 static DBusMessage *modem_get_properties(DBusConnection *conn,
832                                                 DBusMessage *msg, void *data)
833 {
834         struct ofono_modem *modem = data;
835         DBusMessage *reply;
836         DBusMessageIter iter;
837         DBusMessageIter dict;
838
839         reply = dbus_message_new_method_return(msg);
840         if (reply == NULL)
841                 return NULL;
842
843         dbus_message_iter_init_append(reply, &iter);
844
845         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
846                                         OFONO_PROPERTIES_ARRAY_SIGNATURE,
847                                         &dict);
848         __ofono_modem_append_properties(modem, &dict);
849         dbus_message_iter_close_container(&iter, &dict);
850
851         return reply;
852 }
853
854 static int set_powered(struct ofono_modem *modem, ofono_bool_t powered)
855 {
856         const struct ofono_modem_driver *driver = modem->driver;
857         int err = -EINVAL;
858
859         if (modem->powered_pending == powered)
860                 return -EALREADY;
861
862         /* Remove the atoms even if the driver is no longer available */
863         if (powered == FALSE)
864                 modem_change_state(modem, MODEM_STATE_POWER_OFF);
865
866         modem->powered_pending = powered;
867
868         if (driver == NULL)
869                 return -EINVAL;
870
871         if (powered == TRUE) {
872                 if (driver->enable)
873                         err = driver->enable(modem);
874         } else {
875                 if (driver->disable)
876                         err = driver->disable(modem);
877         }
878
879         if (err == 0) {
880                 modem->powered = powered;
881                 notify_powered_watches(modem);
882         } else if (err != -EINPROGRESS)
883                 modem->powered_pending = modem->powered;
884
885         return err;
886 }
887
888 static void lockdown_remove(struct ofono_modem *modem)
889 {
890         DBusConnection *conn = ofono_dbus_get_connection();
891
892         if (modem->lock_watch) {
893                 g_dbus_remove_watch(conn, modem->lock_watch);
894                 modem->lock_watch = 0;
895         }
896
897         g_free(modem->lock_owner);
898         modem->lock_owner = NULL;
899
900         modem->lockdown = FALSE;
901 }
902
903 static gboolean set_powered_timeout(gpointer user)
904 {
905         struct ofono_modem *modem = user;
906
907         DBG("modem: %p", modem);
908
909         modem->timeout = 0;
910
911         if (modem->powered_pending == FALSE) {
912                 DBusConnection *conn = ofono_dbus_get_connection();
913                 dbus_bool_t powered = FALSE;
914
915                 set_online(modem, FALSE);
916
917                 modem->powered = FALSE;
918                 notify_powered_watches(modem);
919
920                 ofono_dbus_signal_property_changed(conn, modem->path,
921                                                 OFONO_MODEM_INTERFACE,
922                                                 "Powered", DBUS_TYPE_BOOLEAN,
923                                                 &powered);
924         } else {
925                 modem->powered_pending = modem->powered;
926         }
927
928         if (modem->pending != NULL) {
929                 DBusMessage *reply;
930
931                 reply = __ofono_error_timed_out(modem->pending);
932                 __ofono_dbus_pending_reply(&modem->pending, reply);
933
934                 if (modem->lockdown)
935                         lockdown_remove(modem);
936         }
937
938         return FALSE;
939 }
940
941 static void lockdown_disconnect(DBusConnection *conn, void *user_data)
942 {
943         struct ofono_modem *modem = user_data;
944
945         DBG("");
946
947         ofono_dbus_signal_property_changed(conn, modem->path,
948                                         OFONO_MODEM_INTERFACE,
949                                         "Lockdown", DBUS_TYPE_BOOLEAN,
950                                         &modem->lockdown);
951
952         modem->lock_watch = 0;
953         lockdown_remove(modem);
954 }
955
956 static DBusMessage *set_property_lockdown(struct ofono_modem *modem,
957                                         DBusMessage *msg,
958                                         DBusMessageIter *var)
959 {
960         DBusConnection *conn = ofono_dbus_get_connection();
961         ofono_bool_t lockdown;
962         dbus_bool_t powered;
963         const char *caller;
964         int err;
965
966         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN)
967                 return __ofono_error_invalid_args(msg);
968
969         dbus_message_iter_get_basic(var, &lockdown);
970
971         if (modem->pending != NULL)
972                 return __ofono_error_busy(msg);
973
974         caller = dbus_message_get_sender(msg);
975
976         if (modem->lockdown && g_strcmp0(caller, modem->lock_owner))
977                 return __ofono_error_access_denied(msg);
978
979         if (modem->lockdown == lockdown)
980                 return dbus_message_new_method_return(msg);
981
982         if (lockdown == FALSE) {
983                 lockdown_remove(modem);
984                 goto done;
985         }
986
987         if (ofono_modem_get_emergency_mode(modem) == TRUE)
988                 return __ofono_error_emergency_active(msg);
989
990         modem->lock_owner = g_strdup(caller);
991
992         modem->lock_watch = g_dbus_add_disconnect_watch(conn,
993                                 modem->lock_owner, lockdown_disconnect,
994                                 modem, NULL);
995
996         if (modem->lock_watch == 0) {
997                 g_free(modem->lock_owner);
998                 modem->lock_owner = NULL;
999
1000                 return __ofono_error_failed(msg);
1001         }
1002
1003         modem->lockdown = lockdown;
1004
1005         if (modem->powered == FALSE)
1006                 goto done;
1007
1008         err = set_powered(modem, FALSE);
1009         if (err < 0) {
1010                 if (err != -EINPROGRESS) {
1011                         lockdown_remove(modem);
1012                         return __ofono_error_failed(msg);
1013                 }
1014
1015                 modem->pending = dbus_message_ref(msg);
1016                 modem->timeout = g_timeout_add_seconds(20,
1017                                                 set_powered_timeout, modem);
1018                 return NULL;
1019         }
1020
1021         set_online(modem, FALSE);
1022
1023         powered = FALSE;
1024         ofono_dbus_signal_property_changed(conn, modem->path,
1025                                         OFONO_MODEM_INTERFACE,
1026                                         "Powered", DBUS_TYPE_BOOLEAN,
1027                                         &powered);
1028
1029 done:
1030         g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
1031
1032         ofono_dbus_signal_property_changed(conn, modem->path,
1033                                         OFONO_MODEM_INTERFACE,
1034                                         "Lockdown", DBUS_TYPE_BOOLEAN,
1035                                         &lockdown);
1036
1037         return NULL;
1038 }
1039
1040 static DBusMessage *modem_set_property(DBusConnection *conn,
1041                                         DBusMessage *msg, void *data)
1042 {
1043         struct ofono_modem *modem = data;
1044         DBusMessageIter iter, var;
1045         const char *name;
1046
1047         if (dbus_message_iter_init(msg, &iter) == FALSE)
1048                 return __ofono_error_invalid_args(msg);
1049
1050         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1051                 return __ofono_error_invalid_args(msg);
1052
1053         dbus_message_iter_get_basic(&iter, &name);
1054         dbus_message_iter_next(&iter);
1055
1056         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1057                 return __ofono_error_invalid_args(msg);
1058
1059         if (powering_down == TRUE)
1060                 return __ofono_error_failed(msg);
1061
1062         dbus_message_iter_recurse(&iter, &var);
1063
1064         if (g_str_equal(name, "Online"))
1065                 return set_property_online(modem, msg, &var);
1066
1067         if (g_str_equal(name, "Powered") == TRUE) {
1068                 ofono_bool_t powered;
1069                 int err;
1070
1071                 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BOOLEAN)
1072                         return __ofono_error_invalid_args(msg);
1073
1074                 dbus_message_iter_get_basic(&var, &powered);
1075
1076                 if (modem->pending != NULL)
1077                         return __ofono_error_busy(msg);
1078
1079                 if (modem->powered == powered)
1080                         return dbus_message_new_method_return(msg);
1081
1082                 if (ofono_modem_get_emergency_mode(modem) == TRUE)
1083                         return __ofono_error_emergency_active(msg);
1084
1085                 if (modem->lockdown)
1086                         return __ofono_error_access_denied(msg);
1087
1088                 err = set_powered(modem, powered);
1089                 if (err < 0) {
1090                         if (err != -EINPROGRESS)
1091                                 return __ofono_error_failed(msg);
1092
1093                         modem->pending = dbus_message_ref(msg);
1094                         modem->timeout = g_timeout_add_seconds(20,
1095                                                 set_powered_timeout, modem);
1096                         return NULL;
1097                 }
1098
1099                 g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
1100
1101                 ofono_dbus_signal_property_changed(conn, modem->path,
1102                                                 OFONO_MODEM_INTERFACE,
1103                                                 "Powered", DBUS_TYPE_BOOLEAN,
1104                                                 &powered);
1105
1106                 if (powered) {
1107                         modem_change_state(modem, MODEM_STATE_PRE_SIM);
1108
1109                         /* Force SIM Ready for devies with no sim atom */
1110                         if (modem_has_sim(modem) == FALSE)
1111                                 sim_state_watch(OFONO_SIM_STATE_READY, modem);
1112                 } else {
1113                         set_online(modem, FALSE);
1114                         modem_change_state(modem, MODEM_STATE_POWER_OFF);
1115                 }
1116
1117                 return NULL;
1118         }
1119
1120         if (g_str_equal(name, "Lockdown"))
1121                 return set_property_lockdown(modem, msg, &var);
1122
1123         return __ofono_error_invalid_args(msg);
1124 }
1125
1126 static const GDBusMethodTable modem_methods[] = {
1127         { GDBUS_METHOD("GetProperties",
1128                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1129                         modem_get_properties) },
1130         { GDBUS_ASYNC_METHOD("SetProperty",
1131                         GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
1132                         NULL, modem_set_property) },
1133         { }
1134 };
1135
1136 static const GDBusSignalTable modem_signals[] = {
1137         { GDBUS_SIGNAL("PropertyChanged",
1138                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1139         { }
1140 };
1141
1142 void ofono_modem_set_powered(struct ofono_modem *modem, ofono_bool_t powered)
1143 {
1144         DBusConnection *conn = ofono_dbus_get_connection();
1145         dbus_bool_t dbus_powered = powered;
1146
1147         if (modem->timeout > 0) {
1148                 g_source_remove(modem->timeout);
1149                 modem->timeout = 0;
1150         }
1151
1152         if (modem->powered_pending != modem->powered &&
1153                                                 modem->pending != NULL) {
1154                 DBusMessage *reply;
1155
1156                 if (powered == modem->powered_pending)
1157                         reply = dbus_message_new_method_return(modem->pending);
1158                 else
1159                         reply = __ofono_error_failed(modem->pending);
1160
1161                 __ofono_dbus_pending_reply(&modem->pending, reply);
1162         }
1163
1164         modem->powered_pending = powered;
1165
1166         if (modem->powered == powered)
1167                 goto out;
1168
1169         modem->powered = powered;
1170         notify_powered_watches(modem);
1171
1172         if (modem->lockdown)
1173                 ofono_dbus_signal_property_changed(conn, modem->path,
1174                                         OFONO_MODEM_INTERFACE,
1175                                         "Lockdown", DBUS_TYPE_BOOLEAN,
1176                                         &modem->lockdown);
1177
1178         if (modem->driver == NULL) {
1179                 ofono_error("Calling ofono_modem_set_powered on a"
1180                                 "modem with no driver is not valid, "
1181                                 "please fix the modem driver.");
1182                 return;
1183         }
1184
1185         ofono_dbus_signal_property_changed(conn, modem->path,
1186                                         OFONO_MODEM_INTERFACE,
1187                                         "Powered", DBUS_TYPE_BOOLEAN,
1188                                         &dbus_powered);
1189
1190         if (powered) {
1191                 modem_change_state(modem, MODEM_STATE_PRE_SIM);
1192
1193                 /* Force SIM Ready for devices with no sim atom */
1194                 if (modem_has_sim(modem) == FALSE)
1195                         sim_state_watch(OFONO_SIM_STATE_READY, modem);
1196         } else {
1197                 set_online(modem, FALSE);
1198
1199                 modem_change_state(modem, MODEM_STATE_POWER_OFF);
1200         }
1201
1202 out:
1203         if (powering_down && powered == FALSE) {
1204                 modems_remaining -= 1;
1205
1206                 if (modems_remaining == 0)
1207                         __ofono_exit();
1208         }
1209 }
1210
1211 ofono_bool_t ofono_modem_get_powered(struct ofono_modem *modem)
1212 {
1213         if (modem == NULL)
1214                 return FALSE;
1215
1216         return modem->powered;
1217 }
1218
1219 static gboolean trigger_interface_update(void *data)
1220 {
1221         struct ofono_modem *modem = data;
1222         DBusConnection *conn = ofono_dbus_get_connection();
1223         char **interfaces;
1224         char **features;
1225         GSList *l;
1226         int i;
1227
1228         interfaces = g_new0(char *, g_slist_length(modem->interface_list) + 1);
1229         for (i = 0, l = modem->interface_list; l; l = l->next, i++)
1230                 interfaces[i] = l->data;
1231         ofono_dbus_signal_array_property_changed(conn, modem->path,
1232                                                 OFONO_MODEM_INTERFACE,
1233                                                 "Interfaces", DBUS_TYPE_STRING,
1234                                                 &interfaces);
1235         g_free(interfaces);
1236
1237         features = g_new0(char *, g_slist_length(modem->feature_list) + 1);
1238         for (i = 0, l = modem->feature_list; l; l = l->next, i++)
1239                 features[i] = l->data;
1240         ofono_dbus_signal_array_property_changed(conn, modem->path,
1241                                                 OFONO_MODEM_INTERFACE,
1242                                                 "Features", DBUS_TYPE_STRING,
1243                                                 &features);
1244         g_free(features);
1245
1246         modem->interface_update = 0;
1247
1248         return FALSE;
1249 }
1250
1251 static const struct {
1252         const char *interface;
1253         const char *feature;
1254 } feature_map[] = {
1255         { OFONO_NETWORK_REGISTRATION_INTERFACE,         "net"   },
1256         { OFONO_RADIO_SETTINGS_INTERFACE,               "rat"   },
1257         { OFONO_CELL_BROADCAST_INTERFACE,               "cbs"   },
1258         { OFONO_MESSAGE_MANAGER_INTERFACE,              "sms"   },
1259         { OFONO_SIM_MANAGER_INTERFACE,                  "sim"   },
1260         { OFONO_STK_INTERFACE,                          "stk"   },
1261         { OFONO_SUPPLEMENTARY_SERVICES_INTERFACE,       "ussd"  },
1262         { OFONO_CONNECTION_MANAGER_INTERFACE,           "gprs"  },
1263         { OFONO_TEXT_TELEPHONY_INTERFACE,               "tty"   },
1264         { OFONO_LOCATION_REPORTING_INTERFACE,           "gps"   },
1265         { },
1266 };
1267
1268 static const char *get_feature(const char *interface)
1269 {
1270         int i;
1271
1272         for (i = 0; feature_map[i].interface; i++) {
1273                 if (strcmp(feature_map[i].interface, interface) == 0)
1274                         return feature_map[i].feature;
1275         }
1276
1277         return NULL;
1278 }
1279
1280 void ofono_modem_add_interface(struct ofono_modem *modem,
1281                                 const char *interface)
1282 {
1283         const char *feature;
1284
1285         modem->interface_list = g_slist_prepend(modem->interface_list,
1286                                                 g_strdup(interface));
1287
1288         feature = get_feature(interface);
1289         if (feature)
1290                 modem->feature_list = g_slist_prepend(modem->feature_list,
1291                                                         g_strdup(feature));
1292
1293         if (modem->interface_update != 0)
1294                 return;
1295
1296         modem->interface_update = g_idle_add(trigger_interface_update, modem);
1297 }
1298
1299 void ofono_modem_remove_interface(struct ofono_modem *modem,
1300                                 const char *interface)
1301 {
1302         GSList *found;
1303         const char *feature;
1304
1305         found = g_slist_find_custom(modem->interface_list, interface,
1306                                                 (GCompareFunc) strcmp);
1307         if (found == NULL) {
1308                 ofono_error("Interface %s not found on the interface_list",
1309                                 interface);
1310                 return;
1311         }
1312
1313         g_free(found->data);
1314         modem->interface_list = g_slist_remove(modem->interface_list,
1315                                                 found->data);
1316
1317         feature = get_feature(interface);
1318         if (feature) {
1319                 found = g_slist_find_custom(modem->feature_list, feature,
1320                                                 (GCompareFunc) strcmp);
1321                 if (found) {
1322                         g_free(found->data);
1323                         modem->feature_list =
1324                                 g_slist_remove(modem->feature_list,
1325                                                 found->data);
1326                 }
1327         }
1328
1329         if (modem->interface_update != 0)
1330                 return;
1331
1332         modem->interface_update = g_idle_add(trigger_interface_update, modem);
1333 }
1334
1335 static void query_serial_cb(const struct ofono_error *error,
1336                                 const char *serial, void *user)
1337 {
1338         struct ofono_devinfo *info = user;
1339         DBusConnection *conn = ofono_dbus_get_connection();
1340         const char *path = __ofono_atom_get_path(info->atom);
1341
1342         if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
1343                 return;
1344
1345         info->serial = g_strdup(serial);
1346
1347         ofono_dbus_signal_property_changed(conn, path,
1348                                                 OFONO_MODEM_INTERFACE,
1349                                                 "Serial", DBUS_TYPE_STRING,
1350                                                 &info->serial);
1351 }
1352
1353 static void query_serial(struct ofono_devinfo *info)
1354 {
1355         if (info->driver->query_serial == NULL)
1356                 return;
1357
1358         info->driver->query_serial(info, query_serial_cb, info);
1359 }
1360
1361 static void query_revision_cb(const struct ofono_error *error,
1362                                 const char *revision, void *user)
1363 {
1364         struct ofono_devinfo *info = user;
1365         DBusConnection *conn = ofono_dbus_get_connection();
1366         const char *path = __ofono_atom_get_path(info->atom);
1367
1368         if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
1369                 goto out;
1370
1371         info->revision = g_strdup(revision);
1372
1373         ofono_dbus_signal_property_changed(conn, path,
1374                                                 OFONO_MODEM_INTERFACE,
1375                                                 "Revision", DBUS_TYPE_STRING,
1376                                                 &info->revision);
1377
1378 out:
1379         query_serial(info);
1380 }
1381
1382 static void query_revision(struct ofono_devinfo *info)
1383 {
1384         if (info->driver->query_revision == NULL) {
1385                 query_serial(info);
1386                 return;
1387         }
1388
1389         info->driver->query_revision(info, query_revision_cb, info);
1390 }
1391
1392 static void query_model_cb(const struct ofono_error *error,
1393                                 const char *model, void *user)
1394 {
1395         struct ofono_devinfo *info = user;
1396         DBusConnection *conn = ofono_dbus_get_connection();
1397         const char *path = __ofono_atom_get_path(info->atom);
1398
1399         if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
1400                 goto out;
1401
1402         info->model = g_strdup(model);
1403
1404         ofono_dbus_signal_property_changed(conn, path,
1405                                                 OFONO_MODEM_INTERFACE,
1406                                                 "Model", DBUS_TYPE_STRING,
1407                                                 &info->model);
1408
1409 out:
1410         query_revision(info);
1411 }
1412
1413 static void query_model(struct ofono_devinfo *info)
1414 {
1415         if (info->driver->query_model == NULL) {
1416                 /* If model is not supported, don't bother querying revision */
1417                 query_serial(info);
1418                 return;
1419         }
1420
1421         info->driver->query_model(info, query_model_cb, info);
1422 }
1423
1424 static void query_manufacturer_cb(const struct ofono_error *error,
1425                                         const char *manufacturer, void *user)
1426 {
1427         struct ofono_devinfo *info = user;
1428         DBusConnection *conn = ofono_dbus_get_connection();
1429         const char *path = __ofono_atom_get_path(info->atom);
1430
1431         if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
1432                 goto out;
1433
1434         info->manufacturer = g_strdup(manufacturer);
1435
1436         ofono_dbus_signal_property_changed(conn, path,
1437                                                 OFONO_MODEM_INTERFACE,
1438                                                 "Manufacturer",
1439                                                 DBUS_TYPE_STRING,
1440                                                 &info->manufacturer);
1441
1442 out:
1443         query_model(info);
1444 }
1445
1446 static gboolean query_manufacturer(gpointer user)
1447 {
1448         struct ofono_devinfo *info = user;
1449
1450         if (info->driver->query_manufacturer == NULL) {
1451                 query_model(info);
1452                 return FALSE;
1453         }
1454
1455         info->driver->query_manufacturer(info, query_manufacturer_cb, info);
1456
1457         return FALSE;
1458 }
1459
1460 static void attr_template(struct ofono_emulator *em,
1461                                 struct ofono_emulator_request *req,
1462                                 const char *attr)
1463 {
1464         struct ofono_error result;
1465
1466         if (attr == NULL)
1467                 attr = "Unknown";
1468
1469         result.error = 0;
1470
1471         switch (ofono_emulator_request_get_type(req)) {
1472         case OFONO_EMULATOR_REQUEST_TYPE_COMMAND_ONLY:
1473                 ofono_emulator_send_info(em, attr, TRUE);
1474                 result.type = OFONO_ERROR_TYPE_NO_ERROR;
1475                 ofono_emulator_send_final(em, &result);
1476                 break;
1477         case OFONO_EMULATOR_REQUEST_TYPE_SUPPORT:
1478                 result.type = OFONO_ERROR_TYPE_NO_ERROR;
1479                 ofono_emulator_send_final(em, &result);
1480                 break;
1481         default:
1482                 result.type = OFONO_ERROR_TYPE_FAILURE;
1483                 ofono_emulator_send_final(em, &result);
1484         };
1485 }
1486
1487 static void gmi_cb(struct ofono_emulator *em,
1488                         struct ofono_emulator_request *req, void *userdata)
1489 {
1490         struct ofono_devinfo *info = userdata;
1491
1492         attr_template(em, req, info->manufacturer);
1493 }
1494
1495 static void gmm_cb(struct ofono_emulator *em,
1496                         struct ofono_emulator_request *req, void *userdata)
1497 {
1498         struct ofono_devinfo *info = userdata;
1499
1500         attr_template(em, req, info->model);
1501 }
1502
1503 static void gmr_cb(struct ofono_emulator *em,
1504                         struct ofono_emulator_request *req, void *userdata)
1505 {
1506         struct ofono_devinfo *info = userdata;
1507
1508         attr_template(em, req, info->revision);
1509 }
1510
1511 static void gcap_cb(struct ofono_emulator *em,
1512                         struct ofono_emulator_request *req, void *userdata)
1513 {
1514         attr_template(em, req, "+GCAP: +CGSM");
1515 }
1516
1517 static void dun_watch(struct ofono_atom *atom,
1518                         enum ofono_atom_watch_condition cond, void *data)
1519 {
1520         struct ofono_emulator *em = __ofono_atom_get_data(atom);
1521
1522         if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED)
1523                 return;
1524
1525         ofono_emulator_add_handler(em, "+GMI", gmi_cb, data, NULL);
1526         ofono_emulator_add_handler(em, "+GMM", gmm_cb, data, NULL);
1527         ofono_emulator_add_handler(em, "+GMR", gmr_cb, data, NULL);
1528         ofono_emulator_add_handler(em, "+GCAP", gcap_cb, data, NULL);
1529 }
1530
1531 int ofono_devinfo_driver_register(const struct ofono_devinfo_driver *d)
1532 {
1533         DBG("driver: %p, name: %s", d, d->name);
1534
1535         if (d->probe == NULL)
1536                 return -EINVAL;
1537
1538         g_devinfo_drivers = g_slist_prepend(g_devinfo_drivers, (void *) d);
1539
1540         return 0;
1541 }
1542
1543 void ofono_devinfo_driver_unregister(const struct ofono_devinfo_driver *d)
1544 {
1545         DBG("driver: %p, name: %s", d, d->name);
1546
1547         g_devinfo_drivers = g_slist_remove(g_devinfo_drivers, (void *) d);
1548 }
1549
1550 static void devinfo_remove(struct ofono_atom *atom)
1551 {
1552         struct ofono_devinfo *info = __ofono_atom_get_data(atom);
1553         DBG("atom: %p", atom);
1554
1555         if (info == NULL)
1556                 return;
1557
1558         if (info->driver == NULL)
1559                 return;
1560
1561         if (info->driver->remove)
1562                 info->driver->remove(info);
1563
1564         g_free(info);
1565 }
1566
1567 struct ofono_devinfo *ofono_devinfo_create(struct ofono_modem *modem,
1568                                                         unsigned int vendor,
1569                                                         const char *driver,
1570                                                         void *data)
1571 {
1572         struct ofono_devinfo *info;
1573         GSList *l;
1574
1575         info = g_new0(struct ofono_devinfo, 1);
1576
1577         info->atom = __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_DEVINFO,
1578                                                 devinfo_remove, info);
1579
1580         for (l = g_devinfo_drivers; l; l = l->next) {
1581                 const struct ofono_devinfo_driver *drv = l->data;
1582
1583                 if (g_strcmp0(drv->name, driver))
1584                         continue;
1585
1586                 if (drv->probe(info, vendor, data) < 0)
1587                         continue;
1588
1589                 info->driver = drv;
1590                 break;
1591         }
1592
1593         return info;
1594 }
1595
1596 static void devinfo_unregister(struct ofono_atom *atom)
1597 {
1598         struct ofono_devinfo *info = __ofono_atom_get_data(atom);
1599
1600         g_free(info->manufacturer);
1601         info->manufacturer = NULL;
1602
1603         g_free(info->model);
1604         info->model = NULL;
1605
1606         g_free(info->revision);
1607         info->revision = NULL;
1608
1609         g_free(info->serial);
1610         info->serial = NULL;
1611 }
1612
1613 void ofono_devinfo_register(struct ofono_devinfo *info)
1614 {
1615         struct ofono_modem *modem = __ofono_atom_get_modem(info->atom);
1616
1617         __ofono_atom_register(info->atom, devinfo_unregister);
1618
1619         info->dun_watch = __ofono_modem_add_atom_watch(modem,
1620                                                 OFONO_ATOM_TYPE_EMULATOR_DUN,
1621                                                 dun_watch, info, NULL);
1622
1623         query_manufacturer(info);
1624 }
1625
1626 void ofono_devinfo_remove(struct ofono_devinfo *info)
1627 {
1628         __ofono_atom_free(info->atom);
1629 }
1630
1631 void ofono_devinfo_set_data(struct ofono_devinfo *info, void *data)
1632 {
1633         info->driver_data = data;
1634 }
1635
1636 void *ofono_devinfo_get_data(struct ofono_devinfo *info)
1637 {
1638         return info->driver_data;
1639 }
1640
1641 static void unregister_property(gpointer data)
1642 {
1643         struct modem_property *property = data;
1644
1645         DBG("property %p", property);
1646
1647         g_free(property->value);
1648         g_free(property);
1649 }
1650
1651 static int set_modem_property(struct ofono_modem *modem, const char *name,
1652                                 enum property_type type, const void *value)
1653 {
1654         struct modem_property *property;
1655
1656         DBG("modem %p property %s", modem, name);
1657
1658         if (type != PROPERTY_TYPE_STRING &&
1659                         type != PROPERTY_TYPE_INTEGER)
1660                 return -EINVAL;
1661
1662         property = g_try_new0(struct modem_property, 1);
1663         if (property == NULL)
1664                 return -ENOMEM;
1665
1666         property->type = type;
1667
1668         switch (type) {
1669         case PROPERTY_TYPE_STRING:
1670                 property->value = g_strdup((const char *) value);
1671                 break;
1672         case PROPERTY_TYPE_INTEGER:
1673                 property->value = g_memdup(value, sizeof(int));
1674                 break;
1675         case PROPERTY_TYPE_BOOLEAN:
1676                 property->value = g_memdup(value, sizeof(ofono_bool_t));
1677                 break;
1678         default:
1679                 break;
1680         }
1681
1682         g_hash_table_replace(modem->properties, g_strdup(name), property);
1683
1684         return 0;
1685 }
1686
1687 static gboolean get_modem_property(struct ofono_modem *modem, const char *name,
1688                                         enum property_type type,
1689                                         void *value)
1690 {
1691         struct modem_property *property;
1692
1693         DBG("modem %p property %s", modem, name);
1694
1695         property = g_hash_table_lookup(modem->properties, name);
1696
1697         if (property == NULL)
1698                 return FALSE;
1699
1700         if (property->type != type)
1701                 return FALSE;
1702
1703         switch (property->type) {
1704         case PROPERTY_TYPE_STRING:
1705                 *((const char **) value) = property->value;
1706                 return TRUE;
1707         case PROPERTY_TYPE_INTEGER:
1708                 memcpy(value, property->value, sizeof(int));
1709                 return TRUE;
1710         case PROPERTY_TYPE_BOOLEAN:
1711                 memcpy(value, property->value, sizeof(ofono_bool_t));
1712                 return TRUE;
1713         default:
1714                 return FALSE;
1715         }
1716 }
1717
1718 int ofono_modem_set_string(struct ofono_modem *modem,
1719                                 const char *key, const char *value)
1720 {
1721         return set_modem_property(modem, key, PROPERTY_TYPE_STRING, value);
1722 }
1723
1724 int ofono_modem_set_integer(struct ofono_modem *modem,
1725                                 const char *key, int value)
1726 {
1727         return set_modem_property(modem, key, PROPERTY_TYPE_INTEGER, &value);
1728 }
1729
1730 int ofono_modem_set_boolean(struct ofono_modem *modem,
1731                                 const char *key, ofono_bool_t value)
1732 {
1733         return set_modem_property(modem, key, PROPERTY_TYPE_BOOLEAN, &value);
1734 }
1735
1736 const char *ofono_modem_get_string(struct ofono_modem *modem, const char *key)
1737 {
1738         const char *value;
1739
1740         if (get_modem_property(modem, key,
1741                                 PROPERTY_TYPE_STRING, &value) == FALSE)
1742                 return NULL;
1743
1744         return value;
1745 }
1746
1747 int ofono_modem_get_integer(struct ofono_modem *modem, const char *key)
1748 {
1749         int value;
1750
1751         if (get_modem_property(modem, key,
1752                                 PROPERTY_TYPE_INTEGER, &value) == FALSE)
1753                 return 0;
1754
1755         return value;
1756 }
1757
1758 ofono_bool_t ofono_modem_get_boolean(struct ofono_modem *modem, const char *key)
1759 {
1760         ofono_bool_t value;
1761
1762         if (get_modem_property(modem, key,
1763                                 PROPERTY_TYPE_BOOLEAN, &value) == FALSE)
1764                 return FALSE;
1765
1766         return value;
1767 }
1768
1769 void ofono_modem_set_name(struct ofono_modem *modem, const char *name)
1770 {
1771         if (modem->name)
1772                 g_free(modem->name);
1773
1774         modem->name = g_strdup(name);
1775
1776         if (modem->driver) {
1777                 DBusConnection *conn = ofono_dbus_get_connection();
1778
1779                 ofono_dbus_signal_property_changed(conn, modem->path,
1780                                                 OFONO_MODEM_INTERFACE,
1781                                                 "Name", DBUS_TYPE_STRING,
1782                                                 &modem->name);
1783         }
1784 }
1785
1786 void ofono_modem_set_driver(struct ofono_modem *modem, const char *type)
1787 {
1788         DBG("type: %s", type);
1789
1790         if (modem->driver)
1791                 return;
1792
1793         if (strlen(type) > 16)
1794                 return;
1795
1796         g_free(modem->driver_type);
1797         modem->driver_type = g_strdup(type);
1798 }
1799
1800 struct ofono_modem *ofono_modem_create(const char *name, const char *type)
1801 {
1802         struct ofono_modem *modem;
1803         char path[128];
1804
1805         DBG("name: %s, type: %s", name, type);
1806
1807         if (strlen(type) > 16)
1808                 return NULL;
1809
1810         if (name && strlen(name) > 64)
1811                 return NULL;
1812
1813         if (name == NULL)
1814                 snprintf(path, sizeof(path), "/%s_%d", type, next_modem_id);
1815         else
1816                 snprintf(path, sizeof(path), "/%s", name);
1817
1818         if (__ofono_dbus_valid_object_path(path) == FALSE)
1819                 return NULL;
1820
1821         modem = g_try_new0(struct ofono_modem, 1);
1822
1823         if (modem == NULL)
1824                 return modem;
1825
1826         modem->path = g_strdup(path);
1827         modem->driver_type = g_strdup(type);
1828         modem->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
1829                                                 g_free, unregister_property);
1830
1831         g_modem_list = g_slist_prepend(g_modem_list, modem);
1832
1833         if (name == NULL)
1834                 next_modem_id += 1;
1835
1836         return modem;
1837 }
1838
1839 static void sim_watch(struct ofono_atom *atom,
1840                         enum ofono_atom_watch_condition cond, void *data)
1841 {
1842         struct ofono_modem *modem = data;
1843
1844         if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
1845                 modem->sim_ready_watch = 0;
1846                 return;
1847         }
1848
1849         modem->sim = __ofono_atom_get_data(atom);
1850         modem->sim_ready_watch = ofono_sim_add_state_watch(modem->sim,
1851                                                         sim_state_watch,
1852                                                         modem, NULL);
1853 }
1854
1855 void __ofono_modemwatch_init(void)
1856 {
1857         g_modemwatches = __ofono_watchlist_new(g_free);
1858 }
1859
1860 void __ofono_modemwatch_cleanup(void)
1861 {
1862         __ofono_watchlist_free(g_modemwatches);
1863 }
1864
1865 unsigned int __ofono_modemwatch_add(ofono_modemwatch_cb_t cb, void *user,
1866                                         ofono_destroy_func destroy)
1867 {
1868         struct ofono_watchlist_item *watch;
1869
1870         if (cb == NULL)
1871                 return 0;
1872
1873         watch = g_new0(struct ofono_watchlist_item, 1);
1874
1875         watch->notify = cb;
1876         watch->destroy = destroy;
1877         watch->notify_data = user;
1878
1879         return __ofono_watchlist_add_item(g_modemwatches, watch);
1880 }
1881
1882 gboolean __ofono_modemwatch_remove(unsigned int id)
1883 {
1884         return __ofono_watchlist_remove_item(g_modemwatches, id);
1885 }
1886
1887 static void call_modemwatches(struct ofono_modem *modem, gboolean added)
1888 {
1889         GSList *l;
1890         struct ofono_watchlist_item *watch;
1891         ofono_modemwatch_cb_t notify;
1892
1893         DBG("%p added:%d", modem, added);
1894
1895         for (l = g_modemwatches->items; l; l = l->next) {
1896                 watch = l->data;
1897
1898                 notify = watch->notify;
1899                 notify(modem, added, watch->notify_data);
1900         }
1901 }
1902
1903 static void emit_modem_added(struct ofono_modem *modem)
1904 {
1905         DBusMessage *signal;
1906         DBusMessageIter iter;
1907         DBusMessageIter dict;
1908         const char *path;
1909
1910         DBG("%p", modem);
1911
1912         signal = dbus_message_new_signal(OFONO_MANAGER_PATH,
1913                                                 OFONO_MANAGER_INTERFACE,
1914                                                 "ModemAdded");
1915
1916         if (signal == NULL)
1917                 return;
1918
1919         dbus_message_iter_init_append(signal, &iter);
1920
1921         path = modem->path;
1922         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
1923         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1924                                         OFONO_PROPERTIES_ARRAY_SIGNATURE,
1925                                         &dict);
1926         __ofono_modem_append_properties(modem, &dict);
1927         dbus_message_iter_close_container(&iter, &dict);
1928
1929         g_dbus_send_message(ofono_dbus_get_connection(), signal);
1930 }
1931
1932 ofono_bool_t ofono_modem_is_registered(struct ofono_modem *modem)
1933 {
1934         if (modem == NULL)
1935                 return FALSE;
1936
1937         if (modem->driver == NULL)
1938                 return FALSE;
1939
1940         return TRUE;
1941 }
1942
1943 int ofono_modem_register(struct ofono_modem *modem)
1944 {
1945         DBusConnection *conn = ofono_dbus_get_connection();
1946         GSList *l;
1947
1948         DBG("%p", modem);
1949
1950         if (modem == NULL)
1951                 return -EINVAL;
1952
1953         if (powering_down == TRUE)
1954                 return -EBUSY;
1955
1956         if (modem->driver != NULL)
1957                 return -EALREADY;
1958
1959         for (l = g_driver_list; l; l = l->next) {
1960                 const struct ofono_modem_driver *drv = l->data;
1961
1962                 if (g_strcmp0(drv->name, modem->driver_type))
1963                         continue;
1964
1965                 if (drv->probe(modem) < 0)
1966                         continue;
1967
1968                 modem->driver = drv;
1969                 break;
1970         }
1971
1972         if (modem->driver == NULL)
1973                 return -ENODEV;
1974
1975         if (!g_dbus_register_interface(conn, modem->path,
1976                                         OFONO_MODEM_INTERFACE,
1977                                         modem_methods, modem_signals, NULL,
1978                                         modem, NULL)) {
1979                 ofono_error("Modem register failed on path %s", modem->path);
1980
1981                 if (modem->driver->remove)
1982                         modem->driver->remove(modem);
1983
1984                 modem->driver = NULL;
1985
1986                 return -EIO;
1987         }
1988
1989         g_free(modem->driver_type);
1990         modem->driver_type = NULL;
1991
1992         modem->atom_watches = __ofono_watchlist_new(g_free);
1993         modem->online_watches = __ofono_watchlist_new(g_free);
1994         modem->powered_watches = __ofono_watchlist_new(g_free);
1995
1996         emit_modem_added(modem);
1997         call_modemwatches(modem, TRUE);
1998
1999         modem->sim_watch = __ofono_modem_add_atom_watch(modem,
2000                                         OFONO_ATOM_TYPE_SIM,
2001                                         sim_watch, modem, NULL);
2002
2003         return 0;
2004 }
2005
2006 static void emit_modem_removed(struct ofono_modem *modem)
2007 {
2008         DBusConnection *conn = ofono_dbus_get_connection();
2009         const char *path = modem->path;
2010
2011         DBG("%p", modem);
2012
2013         g_dbus_emit_signal(conn, OFONO_MANAGER_PATH, OFONO_MANAGER_INTERFACE,
2014                                 "ModemRemoved", DBUS_TYPE_OBJECT_PATH, &path,
2015                                 DBUS_TYPE_INVALID);
2016 }
2017
2018 static void modem_unregister(struct ofono_modem *modem)
2019 {
2020         DBusConnection *conn = ofono_dbus_get_connection();
2021
2022         DBG("%p", modem);
2023
2024         if (modem->powered == TRUE)
2025                 set_powered(modem, FALSE);
2026
2027         __ofono_watchlist_free(modem->atom_watches);
2028         modem->atom_watches = NULL;
2029
2030         __ofono_watchlist_free(modem->online_watches);
2031         modem->online_watches = NULL;
2032
2033         __ofono_watchlist_free(modem->powered_watches);
2034         modem->powered_watches = NULL;
2035
2036         modem->sim_watch = 0;
2037         modem->sim_ready_watch = 0;
2038
2039         g_slist_foreach(modem->interface_list, (GFunc) g_free, NULL);
2040         g_slist_free(modem->interface_list);
2041         modem->interface_list = NULL;
2042
2043         g_slist_foreach(modem->feature_list, (GFunc) g_free, NULL);
2044         g_slist_free(modem->feature_list);
2045         modem->feature_list = NULL;
2046
2047         if (modem->timeout) {
2048                 g_source_remove(modem->timeout);
2049                 modem->timeout = 0;
2050         }
2051
2052         if (modem->pending) {
2053                 dbus_message_unref(modem->pending);
2054                 modem->pending = NULL;
2055         }
2056
2057         if (modem->interface_update) {
2058                 g_source_remove(modem->interface_update);
2059                 modem->interface_update = 0;
2060         }
2061
2062         if (modem->lock_watch) {
2063                 lockdown_remove(modem);
2064
2065                 ofono_dbus_signal_property_changed(conn, modem->path,
2066                                         OFONO_MODEM_INTERFACE,
2067                                         "Lockdown", DBUS_TYPE_BOOLEAN,
2068                                         &modem->lockdown);
2069         }
2070
2071         g_dbus_unregister_interface(conn, modem->path, OFONO_MODEM_INTERFACE);
2072
2073         if (modem->driver && modem->driver->remove)
2074                 modem->driver->remove(modem);
2075
2076         g_hash_table_destroy(modem->properties);
2077         modem->properties = NULL;
2078
2079         modem->driver = NULL;
2080
2081         emit_modem_removed(modem);
2082         call_modemwatches(modem, FALSE);
2083 }
2084
2085 void ofono_modem_remove(struct ofono_modem *modem)
2086 {
2087         DBG("%p", modem);
2088
2089         if (modem == NULL)
2090                 return;
2091
2092         if (modem->driver)
2093                 modem_unregister(modem);
2094
2095         g_modem_list = g_slist_remove(g_modem_list, modem);
2096
2097         g_free(modem->driver_type);
2098         g_free(modem->name);
2099         g_free(modem->path);
2100         g_free(modem);
2101 }
2102
2103 void ofono_modem_reset(struct ofono_modem *modem)
2104 {
2105         int err;
2106
2107         DBG("%p", modem);
2108
2109         if (modem->pending) {
2110                 DBusMessage *reply = __ofono_error_failed(modem->pending);
2111                 __ofono_dbus_pending_reply(&modem->pending, reply);
2112         }
2113
2114         if (modem->modem_state == MODEM_STATE_ONLINE)
2115                 modem->get_online = TRUE;
2116
2117         ofono_modem_set_powered(modem, FALSE);
2118
2119         err = set_powered(modem, TRUE);
2120         if (err == -EINPROGRESS)
2121                 return;
2122
2123         modem_change_state(modem, MODEM_STATE_PRE_SIM);
2124 }
2125
2126 void __ofono_modem_sim_reset(struct ofono_modem *modem)
2127 {
2128         DBG("%p", modem);
2129
2130         modem_change_state(modem, MODEM_STATE_PRE_SIM);
2131 }
2132
2133 int ofono_modem_driver_register(const struct ofono_modem_driver *d)
2134 {
2135         DBG("driver: %p, name: %s", d, d->name);
2136
2137         if (d->probe == NULL)
2138                 return -EINVAL;
2139
2140         g_driver_list = g_slist_prepend(g_driver_list, (void *) d);
2141
2142         return 0;
2143 }
2144
2145 void ofono_modem_driver_unregister(const struct ofono_modem_driver *d)
2146 {
2147         GSList *l;
2148         struct ofono_modem *modem;
2149
2150         DBG("driver: %p, name: %s", d, d->name);
2151
2152         g_driver_list = g_slist_remove(g_driver_list, (void *) d);
2153
2154         for (l = g_modem_list; l; l = l->next) {
2155                 modem = l->data;
2156
2157                 if (modem->driver != d)
2158                         continue;
2159
2160                 modem_unregister(modem);
2161         }
2162 }
2163
2164 void __ofono_modem_shutdown(void)
2165 {
2166         struct ofono_modem *modem;
2167         GSList *l;
2168
2169         powering_down = TRUE;
2170
2171         for (l = g_modem_list; l; l = l->next) {
2172                 modem = l->data;
2173
2174                 if (modem->driver == NULL)
2175                         continue;
2176
2177                 if (modem->powered == FALSE && modem->powered_pending == FALSE)
2178                         continue;
2179
2180                 if (set_powered(modem, FALSE) == -EINPROGRESS)
2181                         modems_remaining += 1;
2182         }
2183
2184         if (modems_remaining == 0)
2185                 __ofono_exit();
2186 }
2187
2188 void __ofono_modem_foreach(ofono_modem_foreach_func func, void *userdata)
2189 {
2190         struct ofono_modem *modem;
2191         GSList *l;
2192
2193         for (l = g_modem_list; l; l = l->next) {
2194                 modem = l->data;
2195                 func(modem, userdata);
2196         }
2197 }
2198
2199 ofono_bool_t ofono_modem_get_emergency_mode(struct ofono_modem *modem)
2200 {
2201         return modem->emergency != 0;
2202 }
2203
2204 void __ofono_modem_inc_emergency_mode(struct ofono_modem *modem)
2205 {
2206         DBusConnection *conn = ofono_dbus_get_connection();
2207         dbus_bool_t emergency = TRUE;
2208
2209         if (++modem->emergency > 1)
2210                 return;
2211
2212         ofono_dbus_signal_property_changed(conn, modem->path,
2213                                                 OFONO_MODEM_INTERFACE,
2214                                                 "Emergency", DBUS_TYPE_BOOLEAN,
2215                                                 &emergency);
2216 }
2217
2218 void __ofono_modem_dec_emergency_mode(struct ofono_modem *modem)
2219 {
2220         DBusConnection *conn = ofono_dbus_get_connection();
2221         dbus_bool_t emergency = FALSE;
2222
2223         if (modem->emergency == 0) {
2224                 ofono_error("emergency mode is already deactivated!!!");
2225                 return;
2226         }
2227
2228         if (modem->emergency > 1)
2229                 goto out;
2230
2231         ofono_dbus_signal_property_changed(conn, modem->path,
2232                                                 OFONO_MODEM_INTERFACE,
2233                                                 "Emergency", DBUS_TYPE_BOOLEAN,
2234                                                 &emergency);
2235
2236 out:
2237         modem->emergency--;
2238 }