3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
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.
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.
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
35 #define OFONO_API_SUBJECT_TO_CHANGE
36 #include <ofono/plugin.h>
37 #include <ofono/modem.h>
38 #include <ofono/log.h>
47 struct ofono_modem *modem;
60 static gboolean setup_isi(struct modem_info *modem)
62 const char *node = NULL;
66 DBG("%s", modem->syspath);
68 for (list = modem->devices; list; list = list->next) {
69 struct device_info *info = list->data;
71 DBG("%s %s %s %s %s", info->devnode, info->interface,
72 info->number, info->label, info->sysattr);
74 if (g_strcmp0(info->sysattr, "820") == 0) {
75 if (g_strcmp0(info->interface, "2/254/0") == 0)
85 DBG("interface=%s address=%d", node, addr);
87 ofono_modem_set_string(modem->modem, "Interface", node);
88 ofono_modem_set_integer(modem->modem, "Address", addr);
93 static gboolean setup_mbm(struct modem_info *modem)
95 const char *mdm = NULL, *app = NULL, *network = NULL, *gps = NULL;
98 DBG("%s", modem->syspath);
100 for (list = modem->devices; list; list = list->next) {
101 struct device_info *info = list->data;
103 DBG("%s %s %s %s %s", info->devnode, info->interface,
104 info->number, info->label, info->sysattr);
106 if (g_str_has_suffix(info->sysattr, "Modem") == TRUE ||
107 g_str_has_suffix(info->sysattr,
108 "Modem 2") == TRUE) {
113 } else if (g_str_has_suffix(info->sysattr,
114 "GPS Port") == TRUE ||
115 g_str_has_suffix(info->sysattr,
116 "Module NMEA") == TRUE) {
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;
126 if (mdm == NULL || app == NULL)
129 DBG("modem=%s data=%s network=%s gps=%s", mdm, app, network, gps);
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);
139 static gboolean setup_hso(struct modem_info *modem)
141 const char *ctl = NULL, *app = NULL, *mdm = NULL, *net = NULL;
144 DBG("%s", modem->syspath);
146 for (list = modem->devices; list; list = list->next) {
147 struct device_info *info = list->data;
149 DBG("%s %s %s %s %s", info->devnode, info->interface,
150 info->number, info->label, info->sysattr);
152 if (g_strcmp0(info->sysattr, "Control") == 0)
154 else if (g_strcmp0(info->sysattr, "Application") == 0)
156 else if (g_strcmp0(info->sysattr, "Modem") == 0)
158 else if (info->sysattr == NULL &&
159 g_str_has_prefix(info->devnode, "hso") == TRUE)
163 if (ctl == NULL || app == NULL)
166 DBG("control=%s application=%s modem=%s network=%s",
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);
177 static gboolean setup_gobi(struct modem_info *modem)
179 const char *qmi = NULL, *mdm = NULL, *net = NULL;
180 const char *gps = NULL, *diag = NULL;
183 DBG("%s", modem->syspath);
185 for (list = modem->devices; list; list = list->next) {
186 struct device_info *info = list->data;
188 DBG("%s %s %s %s", info->devnode, info->interface,
189 info->number, info->label);
191 if (g_strcmp0(info->interface, "255/255/255") == 0) {
192 if (info->number == NULL)
194 else if (g_strcmp0(info->number, "00") == 0)
196 else if (g_strcmp0(info->number, "01") == 0)
197 diag = info->devnode;
198 else if (g_strcmp0(info->number, "02") == 0)
200 else if (g_strcmp0(info->number, "03") == 0)
205 if (qmi == NULL || mdm == NULL || net == NULL)
208 DBG("qmi=%s net=%s mdm=%s gps=%s diag=%s", qmi, net, mdm, gps, diag);
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);
218 static gboolean setup_sierra(struct modem_info *modem)
220 const char *mdm = NULL, *app = NULL, *net = NULL, *diag = NULL;
223 DBG("%s", modem->syspath);
225 for (list = modem->devices; list; list = list->next) {
226 struct device_info *info = list->data;
228 DBG("%s %s %s %s", info->devnode, info->interface,
229 info->number, info->label);
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)
236 else if (g_strcmp0(info->number, "04") == 0)
238 else if (g_strcmp0(info->number, "07") == 0)
243 if (mdm == NULL || net == NULL)
246 DBG("modem=%s app=%s net=%s diag=%s", mdm, app, net, diag);
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);
256 static gboolean setup_option(struct modem_info *modem)
258 const char *aux = NULL, *mdm = NULL, *diag = NULL;
261 DBG("%s", modem->syspath);
263 for (list = modem->devices; list; list = list->next) {
264 struct device_info *info = list->data;
266 DBG("%s %s %s %s", info->devnode, info->interface,
267 info->number, info->label);
269 if (g_strcmp0(info->interface, "255/255/255") == 0) {
270 if (g_strcmp0(info->number, "00") == 0)
272 else if (g_strcmp0(info->number, "01") == 0)
273 diag = info->devnode;
274 else if (g_strcmp0(info->number, "02") == 0)
280 if (aux == NULL || mdm == NULL)
283 DBG("aux=%s modem=%s diag=%s", aux, mdm, diag);
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);
292 static gboolean setup_huawei(struct modem_info *modem)
294 const char *qmi = NULL, *mdm = NULL, *net = NULL;
295 const char *pcui = NULL, *diag = NULL;
298 DBG("%s", modem->syspath);
300 for (list = modem->devices; list; list = list->next) {
301 struct device_info *info = list->data;
303 DBG("%s %s %s %s", info->devnode, info->interface,
304 info->number, info->label);
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) {
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) {
320 } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
321 if (g_strcmp0(info->number, "00") == 0)
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;
334 if (mdm == NULL || pcui == NULL)
337 DBG("mdm=%s pcui=%s diag=%s qmi=%s net=%s", mdm, pcui, diag, qmi, net);
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);
348 static gboolean setup_speedup(struct modem_info *modem)
350 const char *aux = NULL, *mdm = NULL;
353 DBG("%s", modem->syspath);
355 for (list = modem->devices; list; list = list->next) {
356 struct device_info *info = list->data;
358 DBG("%s %s %s %s", info->devnode, info->interface,
359 info->number, info->label);
361 if (g_strcmp0(info->label, "aux") == 0) {
365 } else if (g_strcmp0(info->label, "modem") == 0) {
372 if (aux == NULL || mdm == NULL)
375 DBG("aux=%s modem=%s", aux, mdm);
377 ofono_modem_set_string(modem->modem, "Aux", aux);
378 ofono_modem_set_string(modem->modem, "Modem", mdm);
383 static gboolean setup_linktop(struct modem_info *modem)
385 const char *aux = NULL, *mdm = NULL;
388 DBG("%s", modem->syspath);
390 for (list = modem->devices; list; list = list->next) {
391 struct device_info *info = list->data;
393 DBG("%s %s %s %s", info->devnode, info->interface,
394 info->number, info->label);
396 if (g_strcmp0(info->interface, "2/2/1") == 0) {
397 if (g_strcmp0(info->number, "01") == 0)
399 else if (g_strcmp0(info->number, "03") == 0)
404 if (aux == NULL || mdm == NULL)
407 DBG("aux=%s modem=%s", aux, mdm);
409 ofono_modem_set_string(modem->modem, "Aux", aux);
410 ofono_modem_set_string(modem->modem, "Modem", mdm);
415 static gboolean setup_icera(struct modem_info *modem)
417 const char *aux = NULL, *mdm = NULL, *net = NULL;
420 DBG("%s", modem->syspath);
422 for (list = modem->devices; list; list = list->next) {
423 struct device_info *info = list->data;
425 DBG("%s %s %s %s", info->devnode, info->interface,
426 info->number, info->label);
428 if (g_strcmp0(info->interface, "2/2/1") == 0) {
429 if (g_strcmp0(info->number, "00") == 0)
431 else if (g_strcmp0(info->number, "01") == 0)
433 else if (g_strcmp0(info->number, "02") == 0)
435 else if (g_strcmp0(info->number, "03") == 0)
437 } else if (g_strcmp0(info->interface, "2/6/0") == 0) {
438 if (g_strcmp0(info->number, "05") == 0)
440 else if (g_strcmp0(info->number, "06") == 0)
442 else if (g_strcmp0(info->number, "07") == 0)
447 if (aux == NULL || mdm == NULL)
450 DBG("aux=%s modem=%s net=%s", aux, mdm, net);
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);
459 static gboolean setup_alcatel(struct modem_info *modem)
461 const char *aux = NULL, *mdm = NULL;
464 DBG("%s", modem->syspath);
466 for (list = modem->devices; list; list = list->next) {
467 struct device_info *info = list->data;
469 DBG("%s %s %s %s", info->devnode, info->interface,
470 info->number, info->label);
472 if (g_strcmp0(info->label, "aux") == 0) {
476 } else if (g_strcmp0(info->label, "modem") == 0) {
480 } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
481 if (g_strcmp0(info->number, "03") == 0)
483 else if (g_strcmp0(info->number, "05") == 0)
488 if (aux == NULL || mdm == NULL)
491 DBG("aux=%s modem=%s", aux, mdm);
493 ofono_modem_set_string(modem->modem, "Aux", aux);
494 ofono_modem_set_string(modem->modem, "Modem", mdm);
499 static gboolean setup_novatel(struct modem_info *modem)
501 const char *aux = NULL, *mdm = NULL;
504 DBG("%s", modem->syspath);
506 for (list = modem->devices; list; list = list->next) {
507 struct device_info *info = list->data;
509 DBG("%s %s %s %s", info->devnode, info->interface,
510 info->number, info->label);
512 if (g_strcmp0(info->label, "aux") == 0) {
516 } else if (g_strcmp0(info->label, "modem") == 0) {
520 } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
521 if (g_strcmp0(info->number, "00") == 0)
523 else if (g_strcmp0(info->number, "01") == 0)
528 if (aux == NULL || mdm == NULL)
531 DBG("aux=%s modem=%s", aux, mdm);
533 ofono_modem_set_string(modem->modem, "Aux", aux);
534 ofono_modem_set_string(modem->modem, "Modem", mdm);
539 static gboolean setup_nokia(struct modem_info *modem)
541 const char *aux = NULL, *mdm = NULL;
544 DBG("%s", modem->syspath);
546 for (list = modem->devices; list; list = list->next) {
547 struct device_info *info = list->data;
549 DBG("%s %s %s %s", info->devnode, info->interface,
550 info->number, info->label);
552 if (g_strcmp0(info->label, "aux") == 0) {
556 } else if (g_strcmp0(info->label, "modem") == 0) {
560 } else if (g_strcmp0(info->interface, "10/0/0") == 0) {
561 if (g_strcmp0(info->number, "02") == 0)
563 else if (g_strcmp0(info->number, "04") == 0)
568 if (aux == NULL || mdm == NULL)
571 DBG("aux=%s modem=%s", aux, mdm);
573 ofono_modem_set_string(modem->modem, "Aux", aux);
574 ofono_modem_set_string(modem->modem, "Modem", mdm);
579 static gboolean setup_telit(struct modem_info *modem)
581 const char *mdm = NULL, *aux = NULL, *gps = NULL, *diag = NULL;
584 DBG("%s", modem->syspath);
586 for (list = modem->devices; list; list = list->next) {
587 struct device_info *info = list->data;
589 DBG("%s %s %s %s", info->devnode, info->interface,
590 info->number, info->label);
592 if (g_strcmp0(info->label, "aux") == 0) {
596 } else if (g_strcmp0(info->label, "modem") == 0) {
600 } else if (g_strcmp0(info->interface, "255/255/255") == 0) {
601 if (g_strcmp0(info->number, "00") == 0)
603 else if (g_strcmp0(info->number, "01") == 0)
604 diag = info->devnode;
605 else if (g_strcmp0(info->number, "02") == 0)
607 else if (g_strcmp0(info->number, "03") == 0)
612 if (aux == NULL || mdm == NULL)
615 DBG("modem=%s aux=%s gps=%s diag=%s", mdm, aux, gps, diag);
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);
624 static gboolean setup_simcom(struct modem_info *modem)
626 const char *mdm = NULL, *aux = NULL, *gps = NULL, *diag = NULL;
629 DBG("%s", modem->syspath);
631 for (list = modem->devices; list; list = list->next) {
632 struct device_info *info = list->data;
634 DBG("%s %s %s %s", info->devnode, info->interface,
635 info->number, info->label);
637 if (g_strcmp0(info->label, "aux") == 0) {
641 } else if (g_strcmp0(info->label, "modem") == 0) {
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)
650 else if (g_strcmp0(info->number, "02") == 0)
652 else if (g_strcmp0(info->number, "03") == 0)
657 if (aux == NULL || mdm == NULL)
660 DBG("modem=%s aux=%s gps=%s diag=%s", mdm, aux, gps, diag);
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);
669 static gboolean setup_zte(struct modem_info *modem)
671 const char *aux = NULL, *mdm = NULL, *qcdm = NULL;
672 const char *modem_intf;
675 DBG("%s", modem->syspath);
677 if (g_strcmp0(modem->model, "0016") == 0 ||
678 g_strcmp0(modem->model, "0017") == 0 ||
679 g_strcmp0(modem->model, "0117") == 0)
684 for (list = modem->devices; list; list = list->next) {
685 struct device_info *info = list->data;
687 DBG("%s %s %s %s", info->devnode, info->interface,
688 info->number, info->label);
690 if (g_strcmp0(info->label, "aux") == 0) {
694 } else if (g_strcmp0(info->label, "modem") == 0) {
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)
703 else if (g_strcmp0(info->number, modem_intf) == 0)
708 if (aux == NULL || mdm == NULL)
711 DBG("aux=%s modem=%s qcdm=%s", aux, mdm, qcdm);
713 ofono_modem_set_string(modem->modem, "Aux", aux);
714 ofono_modem_set_string(modem->modem, "Modem", mdm);
719 static gboolean setup_samsung(struct modem_info *modem)
721 const char *control = NULL, *network = NULL;
724 DBG("%s", modem->syspath);
726 for (list = modem->devices; list; list = list->next) {
727 struct device_info *info = list->data;
729 DBG("%s %s %s %s", info->devnode, info->interface,
730 info->number, info->label);
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;
738 if (control == NULL && network == NULL)
741 DBG("control=%s network=%s", control, network);
743 ofono_modem_set_string(modem->modem, "ControlPort", control);
744 ofono_modem_set_string(modem->modem, "NetworkInterface", network);
751 gboolean (*setup)(struct modem_info *modem);
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 },
775 static GHashTable *modem_list;
777 static const char *get_sysattr(const char *driver)
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;
789 static void destroy_modem(gpointer data)
791 struct modem_info *modem = data;
794 DBG("%s", modem->syspath);
796 ofono_modem_remove(modem->modem);
798 for (list = modem->devices; list; list = list->next) {
799 struct device_info *info = list->data;
801 DBG("%s", info->devnode);
803 g_free(info->devpath);
804 g_free(info->devnode);
805 g_free(info->interface);
806 g_free(info->number);
808 g_free(info->sysattr);
814 g_slist_free(modem->devices);
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);
824 static gboolean check_remove(gpointer key, gpointer value, gpointer user_data)
826 struct modem_info *modem = value;
827 const char *devpath = user_data;
830 for (list = modem->devices; list; list = list->next) {
831 struct device_info *info = list->data;
833 if (g_strcmp0(info->devpath, devpath) == 0)
840 static void remove_device(struct udev_device *device)
844 syspath = udev_device_get_syspath(device);
850 g_hash_table_foreach_remove(modem_list, check_remove,
854 static gint compare_device(gconstpointer a, gconstpointer b)
856 const struct device_info *info1 = a;
857 const struct device_info *info2 = b;
859 return g_strcmp0(info1->number, info2->number);
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)
866 struct udev_device *intf;
867 const char *devpath, *devnode, *interface, *number, *label, *sysattr;
868 struct modem_info *modem;
869 struct device_info *info;
871 devpath = udev_device_get_syspath(device);
875 devnode = udev_device_get_devnode(device);
876 if (devnode == NULL) {
877 devnode = udev_device_get_property_value(device, "INTERFACE");
882 intf = udev_device_get_parent_with_subsystem_devtype(device,
883 "usb", "usb_interface");
887 modem = g_hash_table_lookup(modem_list, syspath);
889 modem = g_try_new0(struct modem_info, 1);
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);
899 modem->sysattr = get_sysattr(driver);
901 g_hash_table_replace(modem_list, modem->syspath, modem);
904 interface = udev_device_get_property_value(intf, "INTERFACE");
905 number = udev_device_get_property_value(device, "ID_USB_INTERFACE_NUM");
907 label = udev_device_get_property_value(device, "OFONO_LABEL");
909 if (modem->sysattr != NULL)
910 sysattr = udev_device_get_sysattr_value(device, modem->sysattr);
916 DBG("%s (%s) %s [%s] ==> %s %s", devnode, driver,
917 interface, number, label, sysattr);
919 info = g_try_new0(struct device_info, 1);
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);
930 modem->devices = g_slist_insert_sorted(modem->devices, info,
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" },
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" },
984 static void check_usb_device(struct udev_device *device)
986 struct udev_device *usb_device;
987 const char *syspath, *devname, *driver;
988 const char *vendor = NULL, *model = NULL;
990 usb_device = udev_device_get_parent_with_subsystem_devtype(device,
991 "usb", "usb_device");
992 if (usb_device == NULL)
995 syspath = udev_device_get_syspath(usb_device);
999 devname = udev_device_get_devnode(usb_device);
1000 if (devname == NULL)
1003 driver = udev_device_get_property_value(usb_device, "OFONO_DRIVER");
1004 if (driver == NULL) {
1005 const char *drv, *vid, *pid;
1008 drv = udev_device_get_property_value(device, "ID_USB_DRIVER");
1010 drv = udev_device_get_driver(device);
1012 struct udev_device *parent;
1014 parent = udev_device_get_parent(device);
1018 drv = udev_device_get_driver(parent);
1024 vid = udev_device_get_property_value(device, "ID_VENDOR_ID");
1025 pid = udev_device_get_property_value(device, "ID_MODEL_ID");
1027 DBG("%s [%s:%s]", drv, vid, pid);
1029 for (i = 0; vendor_list[i].driver; i++) {
1030 if (g_str_equal(vendor_list[i].drv, drv) == FALSE)
1033 if (vendor_list[i].vid == NULL) {
1034 driver = vendor_list[i].driver;
1040 if (vid == NULL || pid == NULL)
1043 if (g_str_equal(vendor_list[i].vid, vid) == TRUE) {
1044 if (vendor_list[i].pid == NULL) {
1045 driver = vendor_list[i].driver;
1051 if (g_strcmp0(vendor_list[i].pid, pid) == 0) {
1052 driver = vendor_list[i].driver;
1064 add_device(syspath, devname, driver, vendor, model, device);
1067 static void check_device(struct udev_device *device)
1071 bus = udev_device_get_property_value(device, "ID_BUS");
1073 bus = udev_device_get_subsystem(device);
1078 if (g_str_equal(bus, "usb") == TRUE)
1079 check_usb_device(device);
1082 static gboolean create_modem(gpointer key, gpointer value, gpointer user_data)
1084 struct modem_info *modem = value;
1085 const char *syspath = key;
1088 if (modem->modem != NULL)
1093 if (modem->devices == NULL)
1096 DBG("driver=%s", modem->driver);
1098 modem->modem = ofono_modem_create(NULL, modem->driver);
1099 if (modem->modem == NULL)
1102 for (i = 0; driver_list[i].name; i++) {
1103 if (g_str_equal(driver_list[i].name, modem->driver) == FALSE)
1106 if (driver_list[i].setup(modem) == TRUE) {
1107 ofono_modem_register(modem->modem);
1115 static void enumerate_devices(struct udev *context)
1117 struct udev_enumerate *enumerate;
1118 struct udev_list_entry *entry;
1122 enumerate = udev_enumerate_new(context);
1123 if (enumerate == NULL)
1126 udev_enumerate_add_match_subsystem(enumerate, "tty");
1127 udev_enumerate_add_match_subsystem(enumerate, "usb");
1128 udev_enumerate_add_match_subsystem(enumerate, "net");
1130 udev_enumerate_scan_devices(enumerate);
1132 entry = udev_enumerate_get_list_entry(enumerate);
1134 const char *syspath = udev_list_entry_get_name(entry);
1135 struct udev_device *device;
1137 device = udev_device_new_from_syspath(context, syspath);
1138 if (device != NULL) {
1139 check_device(device);
1140 udev_device_unref(device);
1143 entry = udev_list_entry_get_next(entry);
1146 udev_enumerate_unref(enumerate);
1148 g_hash_table_foreach_remove(modem_list, create_modem, NULL);
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;
1156 static gboolean check_modem_list(gpointer user_data)
1162 g_hash_table_foreach_remove(modem_list, create_modem, NULL);
1167 static gboolean udev_event(GIOChannel *channel, GIOCondition cond,
1170 struct udev_device *device;
1173 if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
1174 ofono_warn("Error with udev monitor channel");
1179 device = udev_monitor_receive_device(udev_mon);
1183 action = udev_device_get_action(device);
1187 if (g_str_equal(action, "add") == TRUE) {
1189 g_source_remove(udev_delay);
1191 check_device(device);
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);
1197 udev_device_unref(device);
1202 static void udev_start(void)
1204 GIOChannel *channel;
1209 if (udev_monitor_enable_receiving(udev_mon) < 0) {
1210 ofono_error("Failed to enable udev monitor");
1214 enumerate_devices(udev_ctx);
1216 fd = udev_monitor_get_fd(udev_mon);
1218 channel = g_io_channel_unix_new(fd);
1219 if (channel == NULL)
1222 udev_watch = g_io_add_watch(channel,
1223 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1226 g_io_channel_unref(channel);
1229 static int detect_init(void)
1231 udev_ctx = udev_new();
1232 if (udev_ctx == NULL) {
1233 ofono_error("Failed to create udev context");
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);
1245 modem_list = g_hash_table_new_full(g_str_hash, g_str_equal,
1246 NULL, destroy_modem);
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);
1252 udev_monitor_filter_update(udev_mon);
1259 static void detect_exit(void)
1262 g_source_remove(udev_delay);
1265 g_source_remove(udev_watch);
1267 if (udev_ctx == NULL)
1270 udev_monitor_filter_remove(udev_mon);
1272 g_hash_table_destroy(modem_list);
1274 udev_monitor_unref(udev_mon);
1275 udev_unref(udev_ctx);
1278 OFONO_PLUGIN_DEFINE(udevng, "udev hardware detection", VERSION,
1279 OFONO_PLUGIN_PRIORITY_DEFAULT, detect_init, detect_exit)