~morphis/phablet-extras/ofono-sms-status-report

« back to all changes in this revision

Viewing changes to plugins/udevng.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2012-08-22 19:59:08 UTC
  • mfrom: (1.3.3) (6.1.5 experimental)
  • Revision ID: package-import@ubuntu.com-20120822195908-0bmmk1hlh989bgk6
Tags: 1.9-1ubuntu1
* Merge with Debian experimental; remaining changes:
  - debian/control: explicitly Conflicts with modemmanager: having both
    installed / running at the same time causes issues causes issues with
    both claiming modem devices.
  - debian/patches/02-dont-handle-stacktraces.patch: stop catching stacktraces
    and printing the information internally, so apport can catch and report
    the possible bugs.
  - debian/ofono.postinst: on configure, notify the user that a reboot is
    required (so ofono can get started by upstart). (LP: #600501)
  - debian/rules: pass --no-restart-on-upgrade so ofono isn't automatically
    restarted when upgrades.
  - Adding upstart config / Removing standard init script
  - Adding Apport support
  - Patch for recognizing special Huawei devices with weird serial
  - Override lintian to avoid script-in-etc-init.d... warnings.
  - Update debian/compat to 7
* debian/series: add our patches to debian/patches/series now that the package
  uses quilt.
* debian/patches/02-dont-handle-stacktraces.patch: refreshed.
* debian/ofono-dev.install, debian/ofono.install:
  - Install usr/sbin/dundee and ofono.pc to the proper packages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <errno.h>
 
27
#include <ctype.h>
 
28
#include <stdlib.h>
 
29
#include <string.h>
 
30
 
 
31
#include <libudev.h>
 
32
 
 
33
#include <glib.h>
 
34
 
 
35
#define OFONO_API_SUBJECT_TO_CHANGE
 
36
#include <ofono/plugin.h>
 
37
#include <ofono/modem.h>
 
38
#include <ofono/log.h>
 
39
 
 
40
struct modem_info {
 
41
        char *syspath;
 
42
        char *devname;
 
43
        char *driver;
 
44
        char *vendor;
 
45
        char *model;
 
46
        GSList *devices;
 
47
        struct ofono_modem *modem;
 
48
        const char *sysattr;
 
49
};
 
50
 
 
51
struct device_info {
 
52
        char *devpath;
 
53
        char *devnode;
 
54
        char *interface;
 
55
        char *number;
 
56
        char *label;
 
57
        char *sysattr;
 
58
};
 
59
 
 
60
static gboolean setup_isi(struct modem_info *modem)
 
61
{
 
62
        const char *node = NULL;
 
63
        int addr = 0;
 
64
        GSList *list;
 
65
 
 
66
        DBG("%s", modem->syspath);
 
67
 
 
68
        for (list = modem->devices; list; list = list->next) {
 
69
                struct device_info *info = list->data;
 
70
 
 
71
                DBG("%s %s %s %s %s", info->devnode, info->interface,
 
72
                                info->number, info->label, info->sysattr);
 
73
 
 
74
                if (g_strcmp0(info->sysattr, "820") == 0) {
 
75
                        if (g_strcmp0(info->interface, "2/254/0") == 0)
 
76
                                addr = 16;
 
77
 
 
78
                        node = info->devnode;
 
79
                }
 
80
        }
 
81
 
 
82
        if (node == NULL)
 
83
                return FALSE;
 
84
 
 
85
        DBG("interface=%s address=%d", node, addr);
 
86
 
 
87
        ofono_modem_set_string(modem->modem, "Interface", node);
 
88
        ofono_modem_set_integer(modem->modem, "Address", addr);
 
89
 
 
90
        return TRUE;
 
91
}
 
92
 
 
93
static gboolean setup_mbm(struct modem_info *modem)
 
94
{
 
95
        const char *mdm = NULL, *app = NULL, *network = NULL, *gps = NULL;
 
96
        GSList *list;
 
97
 
 
98
        DBG("%s", modem->syspath);
 
99
 
 
100
        for (list = modem->devices; list; list = list->next) {
 
101
                struct device_info *info = list->data;
 
102
 
 
103
                DBG("%s %s %s %s %s", info->devnode, info->interface,
 
104
                                info->number, info->label, info->sysattr);
 
105
 
 
106
                if (g_str_has_suffix(info->sysattr, "Modem") == TRUE ||
 
107
                                g_str_has_suffix(info->sysattr,
 
108
                                                        "Modem 2") == TRUE) {
 
109
                        if (mdm == NULL)
 
110
                                mdm = info->devnode;
 
111
                        else
 
112
                                app = info->devnode;
 
113
                } else if (g_str_has_suffix(info->sysattr,
 
114
                                                "GPS Port") == TRUE ||
 
115
                                g_str_has_suffix(info->sysattr,
 
116
                                                "Module NMEA") == TRUE) {
 
117
                        gps = info->devnode;
 
118
                } else if (g_str_has_suffix(info->sysattr,
 
119
                                                "Network Adapter") == TRUE ||
 
120
                                g_str_has_suffix(info->sysattr,
 
121
                                                "NetworkAdapter") == TRUE) {
 
122
                        network = info->devnode;
 
123
                }
 
124
        }
 
125
 
 
126
        if (mdm == NULL || app == NULL)
 
127
                return FALSE;
 
128
 
 
129
        DBG("modem=%s data=%s network=%s gps=%s", mdm, app, network, gps);
 
130
 
 
131
        ofono_modem_set_string(modem->modem, "ModemDevice", mdm);
 
132
        ofono_modem_set_string(modem->modem, "DataDevice", app);
 
133
        ofono_modem_set_string(modem->modem, "GPSDevice", gps);
 
134
        ofono_modem_set_string(modem->modem, "NetworkInterface", network);
 
135
 
 
136
        return TRUE;
 
137
}
 
138
 
 
139
static gboolean setup_hso(struct modem_info *modem)
 
140
{
 
141
        const char *ctl = NULL, *app = NULL, *mdm = NULL, *net = NULL;
 
142
        GSList *list;
 
143
 
 
144
        DBG("%s", modem->syspath);
 
145
 
 
146
        for (list = modem->devices; list; list = list->next) {
 
147
                struct device_info *info = list->data;
 
148
 
 
149
                DBG("%s %s %s %s %s", info->devnode, info->interface,
 
150
                                info->number, info->label, info->sysattr);
 
151
 
 
152
                if (g_strcmp0(info->sysattr, "Control") == 0)
 
153
                        ctl = info->devnode;
 
154
                else if (g_strcmp0(info->sysattr, "Application") == 0)
 
155
                        app = info->devnode;
 
156
                else if (g_strcmp0(info->sysattr, "Modem") == 0)
 
157
                        mdm = info->devnode;
 
158
                else if (info->sysattr == NULL &&
 
159
                                g_str_has_prefix(info->devnode, "hso") == TRUE)
 
160
                        net = info->devnode;
 
161
        }
 
162
 
 
163
        if (ctl == NULL || app == NULL)
 
164
                return FALSE;
 
165
 
 
166
        DBG("control=%s application=%s modem=%s network=%s",
 
167
                                                ctl, app, mdm, net);
 
168
 
 
169
        ofono_modem_set_string(modem->modem, "Control", ctl);
 
170
        ofono_modem_set_string(modem->modem, "Application", app);
 
171
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
172
        ofono_modem_set_string(modem->modem, "NetworkInterface", net);
 
173
 
 
174
        return TRUE;
 
175
}
 
176
 
 
177
static gboolean setup_gobi(struct modem_info *modem)
 
178
{
 
179
        const char *qmi = NULL, *mdm = NULL, *net = NULL;
 
180
        const char *gps = NULL, *diag = NULL;
 
181
        GSList *list;
 
182
 
 
183
        DBG("%s", modem->syspath);
 
184
 
 
185
        for (list = modem->devices; list; list = list->next) {
 
186
                struct device_info *info = list->data;
 
187
 
 
188
                DBG("%s %s %s %s", info->devnode, info->interface,
 
189
                                                info->number, info->label);
 
190
 
 
191
                if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
192
                        if (info->number == NULL)
 
193
                                qmi = info->devnode;
 
194
                        else if (g_strcmp0(info->number, "00") == 0)
 
195
                                net = info->devnode;
 
196
                        else if (g_strcmp0(info->number, "01") == 0)
 
197
                                diag = info->devnode;
 
198
                        else if (g_strcmp0(info->number, "02") == 0)
 
199
                                mdm = info->devnode;
 
200
                        else if (g_strcmp0(info->number, "03") == 0)
 
201
                                gps = info->devnode;
 
202
                }
 
203
        }
 
204
 
 
205
        if (qmi == NULL || mdm == NULL || net == NULL)
 
206
                return FALSE;
 
207
 
 
208
        DBG("qmi=%s net=%s mdm=%s gps=%s diag=%s", qmi, net, mdm, gps, diag);
 
209
 
 
210
        ofono_modem_set_string(modem->modem, "Device", qmi);
 
211
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
212
        ofono_modem_set_string(modem->modem, "Diag", diag);
 
213
        ofono_modem_set_string(modem->modem, "NetworkInterface", net);
 
214
 
 
215
        return TRUE;
 
216
}
 
217
 
 
218
static gboolean setup_sierra(struct modem_info *modem)
 
219
{
 
220
        const char *mdm = NULL, *app = NULL, *net = NULL, *diag = NULL;
 
221
        GSList *list;
 
222
 
 
223
        DBG("%s", modem->syspath);
 
224
 
 
225
        for (list = modem->devices; list; list = list->next) {
 
226
                struct device_info *info = list->data;
 
227
 
 
228
                DBG("%s %s %s %s", info->devnode, info->interface,
 
229
                                                info->number, info->label);
 
230
 
 
231
                if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
232
                        if (g_strcmp0(info->number, "01") == 0)
 
233
                                diag = info->devnode;
 
234
                        if (g_strcmp0(info->number, "03") == 0)
 
235
                                mdm = info->devnode;
 
236
                        else if (g_strcmp0(info->number, "04") == 0)
 
237
                                app = info->devnode;
 
238
                        else if (g_strcmp0(info->number, "07") == 0)
 
239
                                net = info->devnode;
 
240
                }
 
241
        }
 
242
 
 
243
        if (mdm == NULL || net == NULL)
 
244
                return FALSE;
 
245
 
 
246
        DBG("modem=%s app=%s net=%s diag=%s", mdm, app, net, diag);
 
247
 
 
248
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
249
        ofono_modem_set_string(modem->modem, "App", app);
 
250
        ofono_modem_set_string(modem->modem, "Diag", diag);
 
251
        ofono_modem_set_string(modem->modem, "NetworkInterface", net);
 
252
 
 
253
        return TRUE;
 
254
}
 
255
 
 
256
static gboolean setup_option(struct modem_info *modem)
 
257
{
 
258
        const char *aux = NULL, *mdm = NULL, *diag = NULL;
 
259
        GSList *list;
 
260
 
 
261
        DBG("%s", modem->syspath);
 
262
 
 
263
        for (list = modem->devices; list; list = list->next) {
 
264
                struct device_info *info = list->data;
 
265
 
 
266
                DBG("%s %s %s %s", info->devnode, info->interface,
 
267
                                                info->number, info->label);
 
268
 
 
269
                if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
270
                        if (g_strcmp0(info->number, "00") == 0)
 
271
                                mdm = info->devnode;
 
272
                        else if (g_strcmp0(info->number, "01") == 0)
 
273
                                diag = info->devnode;
 
274
                        else if (g_strcmp0(info->number, "02") == 0)
 
275
                                aux = info->devnode;
 
276
                }
 
277
 
 
278
        }
 
279
 
 
280
        if (aux == NULL || mdm == NULL)
 
281
                return FALSE;
 
282
 
 
283
        DBG("aux=%s modem=%s diag=%s", aux, mdm, diag);
 
284
 
 
285
        ofono_modem_set_string(modem->modem, "Aux", aux);
 
286
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
287
        ofono_modem_set_string(modem->modem, "Diag", diag);
 
288
 
 
289
        return TRUE;
 
290
}
 
291
 
 
292
static gboolean setup_huawei(struct modem_info *modem)
 
293
{
 
294
        const char *qmi = NULL, *mdm = NULL, *net = NULL;
 
295
        const char *pcui = NULL, *diag = NULL;
 
296
        GSList *list;
 
297
 
 
298
        DBG("%s", modem->syspath);
 
299
 
 
300
        for (list = modem->devices; list; list = list->next) {
 
301
                struct device_info *info = list->data;
 
302
 
 
303
                DBG("%s %s %s %s", info->devnode, info->interface,
 
304
                                                info->number, info->label);
 
305
 
 
306
                if (g_strcmp0(info->label, "modem") == 0 ||
 
307
                                g_strcmp0(info->interface, "255/1/1") == 0 ||
 
308
                                g_strcmp0(info->interface, "255/2/1") == 0) {
 
309
                        mdm = info->devnode;
 
310
                } else if (g_strcmp0(info->label, "pcui") == 0 ||
 
311
                                g_strcmp0(info->interface, "255/1/2") == 0 ||
 
312
                                g_strcmp0(info->interface, "255/2/2") == 0) {
 
313
                        pcui = info->devnode;
 
314
                } else if (g_strcmp0(info->label, "diag") == 0 ||
 
315
                                g_strcmp0(info->interface, "255/1/3") == 0 ||
 
316
                                g_strcmp0(info->interface, "255/2/3") == 0) {
 
317
                        diag = info->devnode;
 
318
                } else if (g_strcmp0(info->interface, "255/1/8") == 0) {
 
319
                        net = info->devnode;
 
320
                } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
321
                        if (g_strcmp0(info->number, "00") == 0)
 
322
                                mdm = info->devnode;
 
323
                        else if (g_strcmp0(info->number, "01") == 0)
 
324
                                pcui = info->devnode;
 
325
                        else if (g_strcmp0(info->number, "02") == 0)
 
326
                                pcui = info->devnode;
 
327
                        else if (g_strcmp0(info->number, "03") == 0)
 
328
                                pcui = info->devnode;
 
329
                        else if (g_strcmp0(info->number, "04") == 0)
 
330
                                pcui = info->devnode;
 
331
                }
 
332
        }
 
333
 
 
334
        if (mdm == NULL || pcui == NULL)
 
335
                return FALSE;
 
336
 
 
337
        DBG("mdm=%s pcui=%s diag=%s qmi=%s net=%s", mdm, pcui, diag, qmi, net);
 
338
 
 
339
        ofono_modem_set_string(modem->modem, "Device", qmi);
 
340
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
341
        ofono_modem_set_string(modem->modem, "Pcui", pcui);
 
342
        ofono_modem_set_string(modem->modem, "Diag", diag);
 
343
        ofono_modem_set_string(modem->modem, "NetworkInterface", net);
 
344
 
 
345
        return TRUE;
 
346
}
 
347
 
 
348
static gboolean setup_speedup(struct modem_info *modem)
 
349
{
 
350
        const char *aux = NULL, *mdm = NULL;
 
351
        GSList *list;
 
352
 
 
353
        DBG("%s", modem->syspath);
 
354
 
 
355
        for (list = modem->devices; list; list = list->next) {
 
356
                struct device_info *info = list->data;
 
357
 
 
358
                DBG("%s %s %s %s", info->devnode, info->interface,
 
359
                                                info->number, info->label);
 
360
 
 
361
                if (g_strcmp0(info->label, "aux") == 0) {
 
362
                        aux = info->devnode;
 
363
                        if (mdm != NULL)
 
364
                                break;
 
365
                } else if (g_strcmp0(info->label, "modem") == 0) {
 
366
                        mdm = info->devnode;
 
367
                        if (aux != NULL)
 
368
                                break;
 
369
                }
 
370
        }
 
371
 
 
372
        if (aux == NULL || mdm == NULL)
 
373
                return FALSE;
 
374
 
 
375
        DBG("aux=%s modem=%s", aux, mdm);
 
376
 
 
377
        ofono_modem_set_string(modem->modem, "Aux", aux);
 
378
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
379
 
 
380
        return TRUE;
 
381
}
 
382
 
 
383
static gboolean setup_linktop(struct modem_info *modem)
 
384
{
 
385
        const char *aux = NULL, *mdm = NULL;
 
386
        GSList *list;
 
387
 
 
388
        DBG("%s", modem->syspath);
 
389
 
 
390
        for (list = modem->devices; list; list = list->next) {
 
391
                struct device_info *info = list->data;
 
392
 
 
393
                DBG("%s %s %s %s", info->devnode, info->interface,
 
394
                                                info->number, info->label);
 
395
 
 
396
                if (g_strcmp0(info->interface, "2/2/1") == 0) {
 
397
                        if (g_strcmp0(info->number, "01") == 0)
 
398
                                aux = info->devnode;
 
399
                        else if (g_strcmp0(info->number, "03") == 0)
 
400
                                mdm = info->devnode;
 
401
                }
 
402
        }
 
403
 
 
404
        if (aux == NULL || mdm == NULL)
 
405
                return FALSE;
 
406
 
 
407
        DBG("aux=%s modem=%s", aux, mdm);
 
408
 
 
409
        ofono_modem_set_string(modem->modem, "Aux", aux);
 
410
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
411
 
 
412
        return TRUE;
 
413
}
 
414
 
 
415
static gboolean setup_icera(struct modem_info *modem)
 
416
{
 
417
        const char *aux = NULL, *mdm = NULL, *net = NULL;
 
418
        GSList *list;
 
419
 
 
420
        DBG("%s", modem->syspath);
 
421
 
 
422
        for (list = modem->devices; list; list = list->next) {
 
423
                struct device_info *info = list->data;
 
424
 
 
425
                DBG("%s %s %s %s", info->devnode, info->interface,
 
426
                                                info->number, info->label);
 
427
 
 
428
                if (g_strcmp0(info->interface, "2/2/1") == 0) {
 
429
                        if (g_strcmp0(info->number, "00") == 0)
 
430
                                aux = info->devnode;
 
431
                        else if (g_strcmp0(info->number, "01") == 0)
 
432
                                aux = info->devnode;
 
433
                        else if (g_strcmp0(info->number, "02") == 0)
 
434
                                mdm = info->devnode;
 
435
                        else if (g_strcmp0(info->number, "03") == 0)
 
436
                                mdm = info->devnode;
 
437
                } else if (g_strcmp0(info->interface, "2/6/0") == 0) {
 
438
                        if (g_strcmp0(info->number, "05") == 0)
 
439
                                net = info->devnode;
 
440
                        else if (g_strcmp0(info->number, "06") == 0)
 
441
                                net = info->devnode;
 
442
                        else if (g_strcmp0(info->number, "07") == 0)
 
443
                                net = info->devnode;
 
444
                }
 
445
        }
 
446
 
 
447
        if (aux == NULL || mdm == NULL)
 
448
                return FALSE;
 
449
 
 
450
        DBG("aux=%s modem=%s net=%s", aux, mdm, net);
 
451
 
 
452
        ofono_modem_set_string(modem->modem, "Aux", aux);
 
453
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
454
        ofono_modem_set_string(modem->modem, "NetworkInterface", net);
 
455
 
 
456
        return TRUE;
 
457
}
 
458
 
 
459
static gboolean setup_alcatel(struct modem_info *modem)
 
460
{
 
461
        const char *aux = NULL, *mdm = NULL;
 
462
        GSList *list;
 
463
 
 
464
        DBG("%s", modem->syspath);
 
465
 
 
466
        for (list = modem->devices; list; list = list->next) {
 
467
                struct device_info *info = list->data;
 
468
 
 
469
                DBG("%s %s %s %s", info->devnode, info->interface,
 
470
                                                info->number, info->label);
 
471
 
 
472
                if (g_strcmp0(info->label, "aux") == 0) {
 
473
                        aux = info->devnode;
 
474
                        if (mdm != NULL)
 
475
                                break;
 
476
                } else if (g_strcmp0(info->label, "modem") == 0) {
 
477
                        mdm = info->devnode;
 
478
                        if (aux != NULL)
 
479
                                break;
 
480
                } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
481
                        if (g_strcmp0(info->number, "03") == 0)
 
482
                                aux = info->devnode;
 
483
                        else if (g_strcmp0(info->number, "05") == 0)
 
484
                                mdm = info->devnode;
 
485
                }
 
486
        }
 
487
 
 
488
        if (aux == NULL || mdm == NULL)
 
489
                return FALSE;
 
490
 
 
491
        DBG("aux=%s modem=%s", aux, mdm);
 
492
 
 
493
        ofono_modem_set_string(modem->modem, "Aux", aux);
 
494
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
495
 
 
496
        return TRUE;
 
497
}
 
498
 
 
499
static gboolean setup_novatel(struct modem_info *modem)
 
500
{
 
501
        const char *aux = NULL, *mdm = NULL;
 
502
        GSList *list;
 
503
 
 
504
        DBG("%s", modem->syspath);
 
505
 
 
506
        for (list = modem->devices; list; list = list->next) {
 
507
                struct device_info *info = list->data;
 
508
 
 
509
                DBG("%s %s %s %s", info->devnode, info->interface,
 
510
                                                info->number, info->label);
 
511
 
 
512
                if (g_strcmp0(info->label, "aux") == 0) {
 
513
                        aux = info->devnode;
 
514
                        if (mdm != NULL)
 
515
                                break;
 
516
                } else if (g_strcmp0(info->label, "modem") == 0) {
 
517
                        mdm = info->devnode;
 
518
                        if (aux != NULL)
 
519
                                break;
 
520
                } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
521
                        if (g_strcmp0(info->number, "00") == 0)
 
522
                                aux = info->devnode;
 
523
                        else if (g_strcmp0(info->number, "01") == 0)
 
524
                                mdm = info->devnode;
 
525
                }
 
526
        }
 
527
 
 
528
        if (aux == NULL || mdm == NULL)
 
529
                return FALSE;
 
530
 
 
531
        DBG("aux=%s modem=%s", aux, mdm);
 
532
 
 
533
        ofono_modem_set_string(modem->modem, "Aux", aux);
 
534
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
535
 
 
536
        return TRUE;
 
537
}
 
538
 
 
539
static gboolean setup_nokia(struct modem_info *modem)
 
540
{
 
541
        const char *aux = NULL, *mdm = NULL;
 
542
        GSList *list;
 
543
 
 
544
        DBG("%s", modem->syspath);
 
545
 
 
546
        for (list = modem->devices; list; list = list->next) {
 
547
                struct device_info *info = list->data;
 
548
 
 
549
                DBG("%s %s %s %s", info->devnode, info->interface,
 
550
                                                info->number, info->label);
 
551
 
 
552
                if (g_strcmp0(info->label, "aux") == 0) {
 
553
                        aux = info->devnode;
 
554
                        if (mdm != NULL)
 
555
                                break;
 
556
                } else if (g_strcmp0(info->label, "modem") == 0) {
 
557
                        mdm = info->devnode;
 
558
                        if (aux != NULL)
 
559
                                break;
 
560
                } else if (g_strcmp0(info->interface, "10/0/0") == 0) {
 
561
                        if (g_strcmp0(info->number, "02") == 0)
 
562
                                mdm = info->devnode;
 
563
                        else if (g_strcmp0(info->number, "04") == 0)
 
564
                                aux = info->devnode;
 
565
                }
 
566
        }
 
567
 
 
568
        if (aux == NULL || mdm == NULL)
 
569
                return FALSE;
 
570
 
 
571
        DBG("aux=%s modem=%s", aux, mdm);
 
572
 
 
573
        ofono_modem_set_string(modem->modem, "Aux", aux);
 
574
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
575
 
 
576
        return TRUE;
 
577
}
 
578
 
 
579
static gboolean setup_telit(struct modem_info *modem)
 
580
{
 
581
        const char *mdm = NULL, *aux = NULL, *gps = NULL, *diag = NULL;
 
582
        GSList *list;
 
583
 
 
584
        DBG("%s", modem->syspath);
 
585
 
 
586
        for (list = modem->devices; list; list = list->next) {
 
587
                struct device_info *info = list->data;
 
588
 
 
589
                DBG("%s %s %s %s", info->devnode, info->interface,
 
590
                                                info->number, info->label);
 
591
 
 
592
                if (g_strcmp0(info->label, "aux") == 0) {
 
593
                        aux = info->devnode;
 
594
                        if (mdm != NULL)
 
595
                                break;
 
596
                } else if (g_strcmp0(info->label, "modem") == 0) {
 
597
                        mdm = info->devnode;
 
598
                        if (aux != NULL)
 
599
                                break;
 
600
                } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
601
                        if (g_strcmp0(info->number, "00") == 0)
 
602
                                mdm = info->devnode;
 
603
                        else if (g_strcmp0(info->number, "01") == 0)
 
604
                                diag = info->devnode;
 
605
                        else if (g_strcmp0(info->number, "02") == 0)
 
606
                                gps = info->devnode;
 
607
                        else if (g_strcmp0(info->number, "03") == 0)
 
608
                                aux = info->devnode;
 
609
                }
 
610
        }
 
611
 
 
612
        if (aux == NULL || mdm == NULL)
 
613
                return FALSE;
 
614
 
 
615
        DBG("modem=%s aux=%s gps=%s diag=%s", mdm, aux, gps, diag);
 
616
 
 
617
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
618
        ofono_modem_set_string(modem->modem, "Data", aux);
 
619
        ofono_modem_set_string(modem->modem, "GPS", gps);
 
620
 
 
621
        return TRUE;
 
622
}
 
623
 
 
624
static gboolean setup_simcom(struct modem_info *modem)
 
625
{
 
626
        const char *mdm = NULL, *aux = NULL, *gps = NULL, *diag = NULL;
 
627
        GSList *list;
 
628
 
 
629
        DBG("%s", modem->syspath);
 
630
 
 
631
        for (list = modem->devices; list; list = list->next) {
 
632
                struct device_info *info = list->data;
 
633
 
 
634
                DBG("%s %s %s %s", info->devnode, info->interface,
 
635
                                                info->number, info->label);
 
636
 
 
637
                if (g_strcmp0(info->label, "aux") == 0) {
 
638
                        aux = info->devnode;
 
639
                        if (mdm != NULL)
 
640
                                break;
 
641
                } else if (g_strcmp0(info->label, "modem") == 0) {
 
642
                        mdm = info->devnode;
 
643
                        if (aux != NULL)
 
644
                                break;
 
645
                } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
646
                        if (g_strcmp0(info->number, "00") == 0)
 
647
                                diag = info->devnode;
 
648
                        else if (g_strcmp0(info->number, "01") == 0)
 
649
                                gps = info->devnode;
 
650
                        else if (g_strcmp0(info->number, "02") == 0)
 
651
                                aux = info->devnode;
 
652
                        else if (g_strcmp0(info->number, "03") == 0)
 
653
                                mdm = info->devnode;
 
654
                }
 
655
        }
 
656
 
 
657
        if (aux == NULL || mdm == NULL)
 
658
                return FALSE;
 
659
 
 
660
        DBG("modem=%s aux=%s gps=%s diag=%s", mdm, aux, gps, diag);
 
661
 
 
662
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
663
        ofono_modem_set_string(modem->modem, "Data", aux);
 
664
        ofono_modem_set_string(modem->modem, "GPS", gps);
 
665
 
 
666
        return TRUE;
 
667
}
 
668
 
 
669
static gboolean setup_zte(struct modem_info *modem)
 
670
{
 
671
        const char *aux = NULL, *mdm = NULL, *qcdm = NULL;
 
672
        const char *modem_intf;
 
673
        GSList *list;
 
674
 
 
675
        DBG("%s", modem->syspath);
 
676
 
 
677
        if (g_strcmp0(modem->model, "0016") == 0 ||
 
678
                                g_strcmp0(modem->model, "0017") == 0 ||
 
679
                                g_strcmp0(modem->model, "0117") == 0)
 
680
                modem_intf = "02";
 
681
        else
 
682
                modem_intf = "03";
 
683
 
 
684
        for (list = modem->devices; list; list = list->next) {
 
685
                struct device_info *info = list->data;
 
686
 
 
687
                DBG("%s %s %s %s", info->devnode, info->interface,
 
688
                                                info->number, info->label);
 
689
 
 
690
                if (g_strcmp0(info->label, "aux") == 0) {
 
691
                        aux = info->devnode;
 
692
                        if (mdm != NULL)
 
693
                                break;
 
694
                } else if (g_strcmp0(info->label, "modem") == 0) {
 
695
                        mdm = info->devnode;
 
696
                        if (aux != NULL)
 
697
                                break;
 
698
                } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
 
699
                        if (g_strcmp0(info->number, "00") == 0)
 
700
                                qcdm = info->devnode;
 
701
                        else if (g_strcmp0(info->number, "01") == 0)
 
702
                                aux = info->devnode;
 
703
                        else if (g_strcmp0(info->number, modem_intf) == 0)
 
704
                                mdm = info->devnode;
 
705
                }
 
706
        }
 
707
 
 
708
        if (aux == NULL || mdm == NULL)
 
709
                return FALSE;
 
710
 
 
711
        DBG("aux=%s modem=%s qcdm=%s", aux, mdm, qcdm);
 
712
 
 
713
        ofono_modem_set_string(modem->modem, "Aux", aux);
 
714
        ofono_modem_set_string(modem->modem, "Modem", mdm);
 
715
 
 
716
        return TRUE;
 
717
}
 
718
 
 
719
static gboolean setup_samsung(struct modem_info *modem)
 
720
{
 
721
        const char *control = NULL, *network = NULL;
 
722
        GSList *list;
 
723
 
 
724
        DBG("%s", modem->syspath);
 
725
 
 
726
        for (list = modem->devices; list; list = list->next) {
 
727
                struct device_info *info = list->data;
 
728
 
 
729
                DBG("%s %s %s %s", info->devnode, info->interface,
 
730
                                                info->number, info->label);
 
731
 
 
732
                if (g_strcmp0(info->interface, "10/0/0") == 0)
 
733
                        control = info->devnode;
 
734
                else if (g_strcmp0(info->interface, "255/0/0") == 0)
 
735
                        network = info->devnode;
 
736
        }
 
737
 
 
738
        if (control == NULL && network == NULL)
 
739
                return FALSE;
 
740
 
 
741
        DBG("control=%s network=%s", control, network);
 
742
 
 
743
        ofono_modem_set_string(modem->modem, "ControlPort", control);
 
744
        ofono_modem_set_string(modem->modem, "NetworkInterface", network);
 
745
 
 
746
        return TRUE;
 
747
}
 
748
 
 
749
static struct {
 
750
        const char *name;
 
751
        gboolean (*setup)(struct modem_info *modem);
 
752
        const char *sysattr;
 
753
} driver_list[] = {
 
754
        { "isiusb",     setup_isi,      "type"                  },
 
755
        { "mbm",        setup_mbm,      "device/interface"      },
 
756
        { "hso",        setup_hso,      "hsotype"               },
 
757
        { "gobi",       setup_gobi      },
 
758
        { "sierra",     setup_sierra    },
 
759
        { "option",     setup_option    },
 
760
        { "huawei",     setup_huawei    },
 
761
        { "speedupcdma",setup_speedup   },
 
762
        { "speedup",    setup_speedup   },
 
763
        { "linktop",    setup_linktop   },
 
764
        { "alcatel",    setup_alcatel   },
 
765
        { "novatel",    setup_novatel   },
 
766
        { "nokia",      setup_nokia     },
 
767
        { "telit",      setup_telit     },
 
768
        { "simcom",     setup_simcom    },
 
769
        { "zte",        setup_zte       },
 
770
        { "icera",      setup_icera     },
 
771
        { "samsung",    setup_samsung   },
 
772
        { }
 
773
};
 
774
 
 
775
static GHashTable *modem_list;
 
776
 
 
777
static const char *get_sysattr(const char *driver)
 
778
{
 
779
        unsigned int i;
 
780
 
 
781
        for (i = 0; driver_list[i].name; i++) {
 
782
                if (g_str_equal(driver_list[i].name, driver) == TRUE)
 
783
                        return driver_list[i].sysattr;
 
784
        }
 
785
 
 
786
        return NULL;
 
787
}
 
788
 
 
789
static void destroy_modem(gpointer data)
 
790
{
 
791
        struct modem_info *modem = data;
 
792
        GSList *list;
 
793
 
 
794
        DBG("%s", modem->syspath);
 
795
 
 
796
        ofono_modem_remove(modem->modem);
 
797
 
 
798
        for (list = modem->devices; list; list = list->next) {
 
799
                struct device_info *info = list->data;
 
800
 
 
801
                DBG("%s", info->devnode);
 
802
 
 
803
                g_free(info->devpath);
 
804
                g_free(info->devnode);
 
805
                g_free(info->interface);
 
806
                g_free(info->number);
 
807
                g_free(info->label);
 
808
                g_free(info->sysattr);
 
809
                g_free(info);
 
810
 
 
811
                list->data = NULL;
 
812
        }
 
813
 
 
814
        g_slist_free(modem->devices);
 
815
 
 
816
        g_free(modem->syspath);
 
817
        g_free(modem->devname);
 
818
        g_free(modem->driver);
 
819
        g_free(modem->vendor);
 
820
        g_free(modem->model);
 
821
        g_free(modem);
 
822
}
 
823
 
 
824
static gboolean check_remove(gpointer key, gpointer value, gpointer user_data)
 
825
{
 
826
        struct modem_info *modem = value;
 
827
        const char *devpath = user_data;
 
828
        GSList *list;
 
829
 
 
830
        for (list = modem->devices; list; list = list->next) {
 
831
                struct device_info *info = list->data;
 
832
 
 
833
                if (g_strcmp0(info->devpath, devpath) == 0)
 
834
                        return TRUE;
 
835
        }
 
836
 
 
837
        return FALSE;
 
838
}
 
839
 
 
840
static void remove_device(struct udev_device *device)
 
841
{
 
842
        const char *syspath;
 
843
 
 
844
        syspath = udev_device_get_syspath(device);
 
845
        if (syspath == NULL)
 
846
                return;
 
847
 
 
848
        DBG("%s", syspath);
 
849
 
 
850
        g_hash_table_foreach_remove(modem_list, check_remove,
 
851
                                                (char *) syspath);
 
852
}
 
853
 
 
854
static gint compare_device(gconstpointer a, gconstpointer b)
 
855
{
 
856
        const struct device_info *info1 = a;
 
857
        const struct device_info *info2 = b;
 
858
 
 
859
        return g_strcmp0(info1->number, info2->number);
 
860
}
 
861
 
 
862
static void add_device(const char *syspath, const char *devname,
 
863
                        const char *driver, const char *vendor,
 
864
                        const char *model, struct udev_device *device)
 
865
{
 
866
        struct udev_device *intf;
 
867
        const char *devpath, *devnode, *interface, *number, *label, *sysattr;
 
868
        struct modem_info *modem;
 
869
        struct device_info *info;
 
870
 
 
871
        devpath = udev_device_get_syspath(device);
 
872
        if (devpath == NULL)
 
873
                return;
 
874
 
 
875
        devnode = udev_device_get_devnode(device);
 
876
        if (devnode == NULL) {
 
877
                devnode = udev_device_get_property_value(device, "INTERFACE");
 
878
                if (devnode == NULL)
 
879
                        return;
 
880
        }
 
881
 
 
882
        intf = udev_device_get_parent_with_subsystem_devtype(device,
 
883
                                                "usb", "usb_interface");
 
884
        if (intf == NULL)
 
885
                return;
 
886
 
 
887
        modem = g_hash_table_lookup(modem_list, syspath);
 
888
        if (modem == NULL) {
 
889
                modem = g_try_new0(struct modem_info, 1);
 
890
                if (modem == NULL)
 
891
                        return;
 
892
 
 
893
                modem->syspath = g_strdup(syspath);
 
894
                modem->devname = g_strdup(devname);
 
895
                modem->driver = g_strdup(driver);
 
896
                modem->vendor = g_strdup(vendor);
 
897
                modem->model = g_strdup(model);
 
898
 
 
899
                modem->sysattr = get_sysattr(driver);
 
900
 
 
901
                g_hash_table_replace(modem_list, modem->syspath, modem);
 
902
        }
 
903
 
 
904
        interface = udev_device_get_property_value(intf, "INTERFACE");
 
905
        number = udev_device_get_property_value(device, "ID_USB_INTERFACE_NUM");
 
906
 
 
907
        label = udev_device_get_property_value(device, "OFONO_LABEL");
 
908
 
 
909
        if (modem->sysattr != NULL)
 
910
                sysattr = udev_device_get_sysattr_value(device, modem->sysattr);
 
911
        else
 
912
                sysattr = NULL;
 
913
 
 
914
        DBG("%s", syspath);
 
915
        DBG("%s", devpath);
 
916
        DBG("%s (%s) %s [%s] ==> %s %s", devnode, driver,
 
917
                                        interface, number, label, sysattr);
 
918
 
 
919
        info = g_try_new0(struct device_info, 1);
 
920
        if (info == NULL)
 
921
                return;
 
922
 
 
923
        info->devpath = g_strdup(devpath);
 
924
        info->devnode = g_strdup(devnode);
 
925
        info->interface = g_strdup(interface);
 
926
        info->number = g_strdup(number);
 
927
        info->label = g_strdup(label);
 
928
        info->sysattr = g_strdup(sysattr);
 
929
 
 
930
        modem->devices = g_slist_insert_sorted(modem->devices, info,
 
931
                                                        compare_device);
 
932
}
 
933
 
 
934
static struct {
 
935
        const char *driver;
 
936
        const char *drv;
 
937
        const char *vid;
 
938
        const char *pid;
 
939
} vendor_list[] = {
 
940
        { "isiusb",     "cdc_phonet"                    },
 
941
        { "linktop",    "cdc_acm",      "230d"          },
 
942
        { "icera",      "cdc_acm",      "19d2"          },
 
943
        { "icera",      "cdc_ether",    "19d2"          },
 
944
        { "icera",      "cdc_acm",      "04e8", "6872"  },
 
945
        { "icera",      "cdc_ether",    "04e8", "6872"  },
 
946
        { "icera",      "cdc_acm",      "0421", "0633"  },
 
947
        { "icera",      "cdc_ether",    "0421", "0633"  },
 
948
        { "mbm",        "cdc_acm",      "0bdb"          },
 
949
        { "mbm"         "cdc_ether",    "0bdb"          },
 
950
        { "mbm",        "cdc_acm",      "0fce"          },
 
951
        { "mbm",        "cdc_ether",    "0fce"          },
 
952
        { "mbm",        "cdc_acm",      "413c"          },
 
953
        { "mbm",        "cdc_ether",    "413c"          },
 
954
        { "mbm",        "cdc_acm",      "03f0"          },
 
955
        { "mbm",        "cdc_ether",    "03f0"          },
 
956
        { "mbm",        "cdc_acm",      "0930"          },
 
957
        { "mbm",        "cdc_ether",    "0930"          },
 
958
        { "hso",        "hso"                           },
 
959
        { "gobi",       "qmi_wwan"                      },
 
960
        { "gobi",       "qcserial"                      },
 
961
        { "sierra",     "sierra"                        },
 
962
        { "sierra",     "sierra_net"                    },
 
963
        { "option",     "option",       "0af0"          },
 
964
        { "huawei",     "option",       "201e"          },
 
965
        { "huawei",     "cdc_ether",    "12d1"          },
 
966
        { "huawei",     "qmi_wwan",     "12d1"          },
 
967
        { "huawei",     "option",       "12d1"          },
 
968
        { "speedupcdma","option",       "1c9e", "9e00"  },
 
969
        { "speedup",    "option",       "1c9e"          },
 
970
        { "speedup",    "option",       "2020"          },
 
971
        { "alcatel",    "option",       "1bbb", "0017"  },
 
972
        { "novatel",    "option",       "1410"          },
 
973
        { "zte",        "option",       "19d2"          },
 
974
        { "simcom",     "option",       "05c6", "9000"  },
 
975
        { "telit",      "usbserial",    "1bc7"          },
 
976
        { "telit",      "option",       "1bc7"          },
 
977
        { "nokia",      "option",       "0421", "060e"  },
 
978
        { "nokia",      "option",       "0421", "0623"  },
 
979
        { "samsung",    "option",       "04e8", "6889"  },
 
980
        { "samsung",    "kalmia"                        },
 
981
        { }
 
982
};
 
983
 
 
984
static void check_usb_device(struct udev_device *device)
 
985
{
 
986
        struct udev_device *usb_device;
 
987
        const char *syspath, *devname, *driver;
 
988
        const char *vendor = NULL, *model = NULL;
 
989
 
 
990
        usb_device = udev_device_get_parent_with_subsystem_devtype(device,
 
991
                                                        "usb", "usb_device");
 
992
        if (usb_device == NULL)
 
993
                return;
 
994
 
 
995
        syspath = udev_device_get_syspath(usb_device);
 
996
        if (syspath == NULL)
 
997
                return;
 
998
 
 
999
        devname = udev_device_get_devnode(usb_device);
 
1000
        if (devname == NULL)
 
1001
                return;
 
1002
 
 
1003
        driver = udev_device_get_property_value(usb_device, "OFONO_DRIVER");
 
1004
        if (driver == NULL) {
 
1005
                const char *drv, *vid, *pid;
 
1006
                unsigned int i;
 
1007
 
 
1008
                drv = udev_device_get_property_value(device, "ID_USB_DRIVER");
 
1009
                if (drv == NULL) {
 
1010
                        drv = udev_device_get_driver(device);
 
1011
                        if (drv == NULL) {
 
1012
                                struct udev_device *parent;
 
1013
 
 
1014
                                parent = udev_device_get_parent(device);
 
1015
                                if (parent == NULL)
 
1016
                                        return;
 
1017
 
 
1018
                                drv = udev_device_get_driver(parent);
 
1019
                                if (drv == NULL)
 
1020
                                        return;
 
1021
                        }
 
1022
                }
 
1023
 
 
1024
                vid = udev_device_get_property_value(device, "ID_VENDOR_ID");
 
1025
                pid = udev_device_get_property_value(device, "ID_MODEL_ID");
 
1026
 
 
1027
                DBG("%s [%s:%s]", drv, vid, pid);
 
1028
 
 
1029
                for (i = 0; vendor_list[i].driver; i++) {
 
1030
                        if (g_str_equal(vendor_list[i].drv, drv) == FALSE)
 
1031
                                continue;
 
1032
 
 
1033
                        if (vendor_list[i].vid == NULL) {
 
1034
                                driver = vendor_list[i].driver;
 
1035
                                vendor = vid;
 
1036
                                model = pid;
 
1037
                                continue;
 
1038
                        }
 
1039
 
 
1040
                        if (vid == NULL || pid == NULL)
 
1041
                                continue;
 
1042
 
 
1043
                        if (g_str_equal(vendor_list[i].vid, vid) == TRUE) {
 
1044
                                if (vendor_list[i].pid == NULL) {
 
1045
                                        driver = vendor_list[i].driver;
 
1046
                                        vendor = vid;
 
1047
                                        model = pid;
 
1048
                                        continue;
 
1049
                                }
 
1050
 
 
1051
                                if (g_strcmp0(vendor_list[i].pid, pid) == 0) {
 
1052
                                        driver = vendor_list[i].driver;
 
1053
                                        vendor = vid;
 
1054
                                        model = pid;
 
1055
                                        break;
 
1056
                                }
 
1057
                        }
 
1058
                }
 
1059
 
 
1060
                if (driver == NULL)
 
1061
                        return;
 
1062
        }
 
1063
 
 
1064
        add_device(syspath, devname, driver, vendor, model, device);
 
1065
}
 
1066
 
 
1067
static void check_device(struct udev_device *device)
 
1068
{
 
1069
        const char *bus;
 
1070
 
 
1071
        bus = udev_device_get_property_value(device, "ID_BUS");
 
1072
        if (bus == NULL) {
 
1073
                bus = udev_device_get_subsystem(device);
 
1074
                if (bus == NULL)
 
1075
                        return;
 
1076
        }
 
1077
 
 
1078
        if (g_str_equal(bus, "usb") == TRUE)
 
1079
                check_usb_device(device);
 
1080
}
 
1081
 
 
1082
static gboolean create_modem(gpointer key, gpointer value, gpointer user_data)
 
1083
{
 
1084
        struct modem_info *modem = value;
 
1085
        const char *syspath = key;
 
1086
        unsigned int i;
 
1087
 
 
1088
        if (modem->modem != NULL)
 
1089
                return FALSE;
 
1090
 
 
1091
        DBG("%s", syspath);
 
1092
 
 
1093
        if (modem->devices == NULL)
 
1094
                return TRUE;
 
1095
 
 
1096
        DBG("driver=%s", modem->driver);
 
1097
 
 
1098
        modem->modem = ofono_modem_create(NULL, modem->driver);
 
1099
        if (modem->modem == NULL)
 
1100
                return TRUE;
 
1101
 
 
1102
        for (i = 0; driver_list[i].name; i++) {
 
1103
                if (g_str_equal(driver_list[i].name, modem->driver) == FALSE)
 
1104
                        continue;
 
1105
 
 
1106
                if (driver_list[i].setup(modem) == TRUE) {
 
1107
                        ofono_modem_register(modem->modem);
 
1108
                        return FALSE;
 
1109
                }
 
1110
        }
 
1111
 
 
1112
        return TRUE;
 
1113
}
 
1114
 
 
1115
static void enumerate_devices(struct udev *context)
 
1116
{
 
1117
        struct udev_enumerate *enumerate;
 
1118
        struct udev_list_entry *entry;
 
1119
 
 
1120
        DBG("");
 
1121
 
 
1122
        enumerate = udev_enumerate_new(context);
 
1123
        if (enumerate == NULL)
 
1124
                return;
 
1125
 
 
1126
        udev_enumerate_add_match_subsystem(enumerate, "tty");
 
1127
        udev_enumerate_add_match_subsystem(enumerate, "usb");
 
1128
        udev_enumerate_add_match_subsystem(enumerate, "net");
 
1129
 
 
1130
        udev_enumerate_scan_devices(enumerate);
 
1131
 
 
1132
        entry = udev_enumerate_get_list_entry(enumerate);
 
1133
        while (entry) {
 
1134
                const char *syspath = udev_list_entry_get_name(entry);
 
1135
                struct udev_device *device;
 
1136
 
 
1137
                device = udev_device_new_from_syspath(context, syspath);
 
1138
                if (device != NULL) {
 
1139
                        check_device(device);
 
1140
                        udev_device_unref(device);
 
1141
                }
 
1142
 
 
1143
                entry = udev_list_entry_get_next(entry);
 
1144
        }
 
1145
 
 
1146
        udev_enumerate_unref(enumerate);
 
1147
 
 
1148
        g_hash_table_foreach_remove(modem_list, create_modem, NULL);
 
1149
}
 
1150
 
 
1151
static struct udev *udev_ctx;
 
1152
static struct udev_monitor *udev_mon;
 
1153
static guint udev_watch = 0;
 
1154
static guint udev_delay = 0;
 
1155
 
 
1156
static gboolean check_modem_list(gpointer user_data)
 
1157
{
 
1158
        udev_delay = 0;
 
1159
 
 
1160
        DBG("");
 
1161
 
 
1162
        g_hash_table_foreach_remove(modem_list, create_modem, NULL);
 
1163
 
 
1164
        return FALSE;
 
1165
}
 
1166
 
 
1167
static gboolean udev_event(GIOChannel *channel, GIOCondition cond,
 
1168
                                                        gpointer user_data)
 
1169
{
 
1170
        struct udev_device *device;
 
1171
        const char *action;
 
1172
 
 
1173
        if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
 
1174
                ofono_warn("Error with udev monitor channel");
 
1175
                udev_watch = 0;
 
1176
                return FALSE;
 
1177
        }
 
1178
 
 
1179
        device = udev_monitor_receive_device(udev_mon);
 
1180
        if (device == NULL)
 
1181
                return TRUE;
 
1182
 
 
1183
        action = udev_device_get_action(device);
 
1184
        if (action == NULL)
 
1185
                return TRUE;
 
1186
 
 
1187
        if (g_str_equal(action, "add") == TRUE) {
 
1188
                if (udev_delay > 0)
 
1189
                        g_source_remove(udev_delay);
 
1190
 
 
1191
                check_device(device);
 
1192
 
 
1193
                udev_delay = g_timeout_add_seconds(1, check_modem_list, NULL);
 
1194
        } else if (g_str_equal(action, "remove") == TRUE)
 
1195
                remove_device(device);
 
1196
 
 
1197
        udev_device_unref(device);
 
1198
 
 
1199
        return TRUE;
 
1200
}
 
1201
 
 
1202
static void udev_start(void)
 
1203
{
 
1204
        GIOChannel *channel;
 
1205
        int fd;
 
1206
 
 
1207
        DBG("");
 
1208
 
 
1209
        if (udev_monitor_enable_receiving(udev_mon) < 0) {
 
1210
                ofono_error("Failed to enable udev monitor");
 
1211
                return;
 
1212
        }
 
1213
 
 
1214
        enumerate_devices(udev_ctx);
 
1215
 
 
1216
        fd = udev_monitor_get_fd(udev_mon);
 
1217
 
 
1218
        channel = g_io_channel_unix_new(fd);
 
1219
        if (channel == NULL)
 
1220
                return;
 
1221
 
 
1222
        udev_watch = g_io_add_watch(channel,
 
1223
                                G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 
1224
                                                        udev_event, NULL);
 
1225
 
 
1226
        g_io_channel_unref(channel);
 
1227
}
 
1228
 
 
1229
static int detect_init(void)
 
1230
{
 
1231
        udev_ctx = udev_new();
 
1232
        if (udev_ctx == NULL) {
 
1233
                ofono_error("Failed to create udev context");
 
1234
                return -EIO;
 
1235
        }
 
1236
 
 
1237
        udev_mon = udev_monitor_new_from_netlink(udev_ctx, "udev");
 
1238
        if (udev_mon == NULL) {
 
1239
                ofono_error("Failed to create udev monitor");
 
1240
                udev_unref(udev_ctx);
 
1241
                udev_ctx = NULL;
 
1242
                return -EIO;
 
1243
        }
 
1244
 
 
1245
        modem_list = g_hash_table_new_full(g_str_hash, g_str_equal,
 
1246
                                                NULL, destroy_modem);
 
1247
 
 
1248
        udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "tty", NULL);
 
1249
        udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "usb", NULL);
 
1250
        udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "net", NULL);
 
1251
 
 
1252
        udev_monitor_filter_update(udev_mon);
 
1253
 
 
1254
        udev_start();
 
1255
 
 
1256
        return 0;
 
1257
}
 
1258
 
 
1259
static void detect_exit(void)
 
1260
{
 
1261
        if (udev_delay > 0)
 
1262
                g_source_remove(udev_delay);
 
1263
 
 
1264
        if (udev_watch > 0)
 
1265
                g_source_remove(udev_watch);
 
1266
 
 
1267
        if (udev_ctx == NULL)
 
1268
                return;
 
1269
 
 
1270
        udev_monitor_filter_remove(udev_mon);
 
1271
 
 
1272
        g_hash_table_destroy(modem_list);
 
1273
 
 
1274
        udev_monitor_unref(udev_mon);
 
1275
        udev_unref(udev_ctx);
 
1276
}
 
1277
 
 
1278
OFONO_PLUGIN_DEFINE(udevng, "udev hardware detection", VERSION,
 
1279
                OFONO_PLUGIN_PRIORITY_DEFAULT, detect_init, detect_exit)