~connman-maintainers/ofono/trunk

5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1
/*
2
 *
3
 *  oFono - Open Source Telephony
4
 *
5857 by Marcel Holtmann
plugins: Update copyright information
5
 *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
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>
8089 by Denis Kenzior
udevng: Store MBIM descriptors file
30
#include <stdio.h>
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
31
32
#include <libudev.h>
33
34
#include <glib.h>
35
36
#define OFONO_API_SUBJECT_TO_CHANGE
37
#include <ofono/plugin.h>
38
#include <ofono/modem.h>
39
#include <ofono/log.h>
40
7948 by Jonas Bonn
udevng: add serial device handling functions
41
enum modem_type {
42
	MODEM_TYPE_USB,
43
	MODEM_TYPE_SERIAL,
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
44
	MODEM_TYPE_PCIE,
7948 by Jonas Bonn
udevng: add serial device handling functions
45
};
46
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
47
struct modem_info {
48
	char *syspath;
49
	char *devname;
50
	char *driver;
6064 by Marcel Holtmann
udev: Keep vendor and product identifiers around
51
	char *vendor;
52
	char *model;
7948 by Jonas Bonn
udevng: add serial device handling functions
53
	enum modem_type type;
54
	union {
55
		GSList *devices;
56
		struct serial_device_info* serial;
57
	};
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
58
	struct ofono_modem *modem;
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
59
	const char *sysattr;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
60
};
61
62
struct device_info {
63
	char *devpath;
64
	char *devnode;
65
	char *interface;
66
	char *number;
67
	char *label;
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
68
	char *sysattr;
7782 by Martin Chaplet
udevng: Improve modem properties detection
69
	char *subsystem;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
70
};
71
7948 by Jonas Bonn
udevng: add serial device handling functions
72
struct serial_device_info {
73
	char *devpath;
74
	char *devnode;
75
	char *subsystem;
76
	struct udev_device* dev;
77
};
78
5752 by Marcel Holtmann
udev: Add support for automatic ISI USB modem detection
79
static gboolean setup_isi(struct modem_info *modem)
80
{
81
	const char *node = NULL;
82
	int addr = 0;
83
	GSList *list;
84
85
	DBG("%s", modem->syspath);
86
87
	for (list = modem->devices; list; list = list->next) {
88
		struct device_info *info = list->data;
89
90
		DBG("%s %s %s %s %s", info->devnode, info->interface,
91
				info->number, info->label, info->sysattr);
92
93
		if (g_strcmp0(info->sysattr, "820") == 0) {
94
			if (g_strcmp0(info->interface, "2/254/0") == 0)
95
				addr = 16;
96
97
			node = info->devnode;
98
		}
99
	}
100
101
	if (node == NULL)
102
		return FALSE;
103
104
	DBG("interface=%s address=%d", node, addr);
105
106
	ofono_modem_set_string(modem->modem, "Interface", node);
107
	ofono_modem_set_integer(modem->modem, "Address", addr);
108
109
	return TRUE;
110
}
111
5748 by Marcel Holtmann
udev: Add automatic detection for Ericsson MBM based devices
112
static gboolean setup_mbm(struct modem_info *modem)
113
{
114
	const char *mdm = NULL, *app = NULL, *network = NULL, *gps = NULL;
115
	GSList *list;
116
117
	DBG("%s", modem->syspath);
118
119
	for (list = modem->devices; list; list = list->next) {
120
		struct device_info *info = list->data;
121
122
		DBG("%s %s %s %s %s", info->devnode, info->interface,
123
				info->number, info->label, info->sysattr);
124
125
		if (g_str_has_suffix(info->sysattr, "Modem") == TRUE ||
126
				g_str_has_suffix(info->sysattr,
127
							"Modem 2") == TRUE) {
128
			if (mdm == NULL)
129
				mdm = info->devnode;
130
			else
131
				app = info->devnode;
132
		} else if (g_str_has_suffix(info->sysattr,
133
						"GPS Port") == TRUE ||
134
				g_str_has_suffix(info->sysattr,
135
						"Module NMEA") == TRUE) {
136
			gps = info->devnode;
137
		} else if (g_str_has_suffix(info->sysattr,
138
						"Network Adapter") == TRUE ||
139
				g_str_has_suffix(info->sysattr,
7361 by Johannes 'josch' Schauer
udevng: add support for Ericsson N5321 gw
140
						"gw") == TRUE ||
141
				g_str_has_suffix(info->sysattr,
5748 by Marcel Holtmann
udev: Add automatic detection for Ericsson MBM based devices
142
						"NetworkAdapter") == TRUE) {
143
			network = info->devnode;
144
		}
145
	}
146
147
	if (mdm == NULL || app == NULL)
148
		return FALSE;
149
150
	DBG("modem=%s data=%s network=%s gps=%s", mdm, app, network, gps);
151
152
	ofono_modem_set_string(modem->modem, "ModemDevice", mdm);
153
	ofono_modem_set_string(modem->modem, "DataDevice", app);
154
	ofono_modem_set_string(modem->modem, "GPSDevice", gps);
155
	ofono_modem_set_string(modem->modem, "NetworkInterface", network);
156
157
	return TRUE;
158
}
159
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
160
static gboolean setup_hso(struct modem_info *modem)
161
{
6135 by Marcel Holtmann
udev: Also detect modem port of Option HSO devices
162
	const char *ctl = NULL, *app = NULL, *mdm = NULL, *net = NULL;
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
163
	GSList *list;
164
165
	DBG("%s", modem->syspath);
166
167
	for (list = modem->devices; list; list = list->next) {
168
		struct device_info *info = list->data;
169
170
		DBG("%s %s %s %s %s", info->devnode, info->interface,
171
				info->number, info->label, info->sysattr);
172
173
		if (g_strcmp0(info->sysattr, "Control") == 0)
6135 by Marcel Holtmann
udev: Also detect modem port of Option HSO devices
174
			ctl = info->devnode;
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
175
		else if (g_strcmp0(info->sysattr, "Application") == 0)
6135 by Marcel Holtmann
udev: Also detect modem port of Option HSO devices
176
			app = info->devnode;
177
		else if (g_strcmp0(info->sysattr, "Modem") == 0)
178
			mdm = info->devnode;
5699 by Marcel Holtmann
udev: Fix network interface detection for Option HSO
179
		else if (info->sysattr == NULL &&
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
180
				g_str_has_prefix(info->devnode, "hso") == TRUE)
6135 by Marcel Holtmann
udev: Also detect modem port of Option HSO devices
181
			net = info->devnode;
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
182
	}
183
6135 by Marcel Holtmann
udev: Also detect modem port of Option HSO devices
184
	if (ctl == NULL || app == NULL)
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
185
		return FALSE;
186
6135 by Marcel Holtmann
udev: Also detect modem port of Option HSO devices
187
	DBG("control=%s application=%s modem=%s network=%s",
188
						ctl, app, mdm, net);
5699 by Marcel Holtmann
udev: Fix network interface detection for Option HSO
189
6135 by Marcel Holtmann
udev: Also detect modem port of Option HSO devices
190
	ofono_modem_set_string(modem->modem, "Control", ctl);
191
	ofono_modem_set_string(modem->modem, "Application", app);
192
	ofono_modem_set_string(modem->modem, "Modem", mdm);
193
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
194
195
	return TRUE;
196
}
197
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
198
static gboolean setup_gobi(struct modem_info *modem)
199
{
6287 by Marcel Holtmann
udev: Add support for detecting Gobi QMI devices
200
	const char *qmi = NULL, *mdm = NULL, *net = NULL;
201
	const char *gps = NULL, *diag = NULL;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
202
	GSList *list;
203
204
	DBG("%s", modem->syspath);
205
206
	for (list = modem->devices; list; list = list->next) {
207
		struct device_info *info = list->data;
208
7994 by Alexander Couzens
udevng/gobi: improve debug output
209
		DBG("%s %s %s %s %s %s", info->devnode, info->interface,
210
						info->number, info->label,
211
						info->sysattr, info->subsystem);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
212
7995 by Alexander Couzens
udevng/gobi: use subsystem as first identification
213
		if (g_strcmp0(info->subsystem, "usbmisc") == 0) /* cdc-wdm */
214
			qmi = info->devnode;
215
		else if (g_strcmp0(info->subsystem, "net") == 0) /* wwan */
216
			net = info->devnode;
217
		else if (g_strcmp0(info->subsystem, "tty") == 0) {
218
			if (g_strcmp0(info->interface, "255/255/255") == 0) {
7996 by Alexander Couzens
udevng/gobi: allow to detect ec20 tty devices
219
				if (g_strcmp0(info->number, "00") == 0)
220
					diag = info->devnode; /* ec20 */
221
				else if (g_strcmp0(info->number, "01") == 0)
222
					diag = info->devnode; /* gobi */
7995 by Alexander Couzens
udevng/gobi: use subsystem as first identification
223
				else if (g_strcmp0(info->number, "02") == 0)
7996 by Alexander Couzens
udevng/gobi: allow to detect ec20 tty devices
224
					mdm = info->devnode; /* gobi */
7995 by Alexander Couzens
udevng/gobi: use subsystem as first identification
225
				else if (g_strcmp0(info->number, "03") == 0)
7996 by Alexander Couzens
udevng/gobi: allow to detect ec20 tty devices
226
					gps = info->devnode; /* gobi */
227
			} else if (g_strcmp0(info->interface, "255/0/0") == 0) {
228
				if (g_strcmp0(info->number, "01") == 0)
229
					gps = info->devnode; /* ec20 */
230
				if (g_strcmp0(info->number, "02") == 0)
231
					mdm = info->devnode; /* ec20 */
232
				/* ignore the 3rd device second AT/mdm iface */
7995 by Alexander Couzens
udevng/gobi: use subsystem as first identification
233
			}
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
234
		}
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
235
	}
236
8413 by Pavel Machek
udevng: Move debug print to more useful place
237
	DBG("qmi=%s net=%s mdm=%s gps=%s diag=%s", qmi, net, mdm, gps, diag);
238
6287 by Marcel Holtmann
udev: Add support for detecting Gobi QMI devices
239
	if (qmi == NULL || mdm == NULL || net == NULL)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
240
		return FALSE;
241
242
6287 by Marcel Holtmann
udev: Add support for detecting Gobi QMI devices
243
	ofono_modem_set_string(modem->modem, "Device", qmi);
244
	ofono_modem_set_string(modem->modem, "Modem", mdm);
245
	ofono_modem_set_string(modem->modem, "Diag", diag);
246
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
247
248
	return TRUE;
249
}
250
251
static gboolean setup_sierra(struct modem_info *modem)
252
{
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
253
	const char *mdm = NULL, *app = NULL, *net = NULL, *diag = NULL, *qmi = NULL;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
254
	GSList *list;
255
256
	DBG("%s", modem->syspath);
257
258
	for (list = modem->devices; list; list = list->next) {
259
		struct device_info *info = list->data;
260
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
261
		DBG("%s %s %s %s %s", info->devnode, info->interface,
7784 by Denis Kenzior
udevng: Fixup various minor style issues
262
				info->number, info->label, info->subsystem);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
263
6133 by Marcel Holtmann
udev: Detect more ports for Sierra modems
264
		if (g_strcmp0(info->interface, "255/255/255") == 0) {
265
			if (g_strcmp0(info->number, "01") == 0)
266
				diag = info->devnode;
8044 by Alexander Couzens
plugins/udevng: use else if instead of if
267
			else if (g_strcmp0(info->number, "03") == 0)
6133 by Marcel Holtmann
udev: Detect more ports for Sierra modems
268
				mdm = info->devnode;
269
			else if (g_strcmp0(info->number, "04") == 0)
6137 by Marcel Holtmann
udev: Add support for detecting Sierra network interfaces
270
				app = info->devnode;
271
			else if (g_strcmp0(info->number, "07") == 0)
272
				net = info->devnode;
8040 by Alexander Couzens
udevng: use first cdc-wdm interface for sierra qmi
273
			else if (g_strcmp0(info->subsystem, "net") == 0) {
274
				/*
275
				 * When using the voice firmware on a mc7304
276
				 * the second cdc-wdm interface doesn't handle
277
				 * qmi messages properly.
278
				 * Some modems still have a working second
279
				 * cdc-wdm interface, some are not. But always
280
				 * the first interface works.
281
				 */
282
				if (g_strcmp0(info->number, "08") == 0) {
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
283
					net = info->devnode;
8040 by Alexander Couzens
udevng: use first cdc-wdm interface for sierra qmi
284
				} else if (g_strcmp0(info->number, "0a") == 0) {
285
					if (net == NULL)
286
						net = info->devnode;
287
				}
288
			} else if (g_strcmp0(info->subsystem, "usbmisc") == 0) {
289
				if (g_strcmp0(info->number, "08") == 0) {
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
290
					qmi = info->devnode;
8040 by Alexander Couzens
udevng: use first cdc-wdm interface for sierra qmi
291
				} else if (g_strcmp0(info->number, "0a") == 0) {
292
					if (qmi == NULL)
293
						qmi = info->devnode;
294
				}
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
295
			}
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
296
		}
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
297
	}
298
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
299
	if (qmi != NULL && net != NULL) {
300
		ofono_modem_set_driver(modem->modem, "gobi");
301
		goto done;
302
	}
303
6169 by Marcel Holtmann
udev: Only detect Sierra Wireless devices with DirectIP
304
	if (mdm == NULL || net == NULL)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
305
		return FALSE;
306
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
307
done:
308
	DBG("modem=%s app=%s net=%s diag=%s qmi=%s", mdm, app, net, diag, qmi);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
309
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
310
	ofono_modem_set_string(modem->modem, "Device", qmi);
6133 by Marcel Holtmann
udev: Detect more ports for Sierra modems
311
	ofono_modem_set_string(modem->modem, "Modem", mdm);
6137 by Marcel Holtmann
udev: Add support for detecting Sierra network interfaces
312
	ofono_modem_set_string(modem->modem, "App", app);
6133 by Marcel Holtmann
udev: Detect more ports for Sierra modems
313
	ofono_modem_set_string(modem->modem, "Diag", diag);
6137 by Marcel Holtmann
udev: Add support for detecting Sierra network interfaces
314
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
315
316
	return TRUE;
317
}
318
319
static gboolean setup_huawei(struct modem_info *modem)
320
{
6288 by Marcel Holtmann
udev: Add support for detecting Huawei QMI devices
321
	const char *qmi = NULL, *mdm = NULL, *net = NULL;
322
	const char *pcui = NULL, *diag = NULL;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
323
	GSList *list;
324
325
	DBG("%s", modem->syspath);
326
327
	for (list = modem->devices; list; list = list->next) {
328
		struct device_info *info = list->data;
329
330
		DBG("%s %s %s %s", info->devnode, info->interface,
331
						info->number, info->label);
332
333
		if (g_strcmp0(info->label, "modem") == 0 ||
334
				g_strcmp0(info->interface, "255/1/1") == 0 ||
6736 by Marcel Holtmann
udev: Handle USB descriptors from Vodafone K5005 modem
335
				g_strcmp0(info->interface, "255/2/1") == 0 ||
7821 by Frédéric Dalleau
udevng: Detect huawei E3372 modem and pcui
336
				g_strcmp0(info->interface, "255/3/1") == 0 ||
6736 by Marcel Holtmann
udev: Handle USB descriptors from Vodafone K5005 modem
337
				g_strcmp0(info->interface, "255/1/49") == 0) {
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
338
			mdm = info->devnode;
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
339
		} else if (g_strcmp0(info->label, "pcui") == 0 ||
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
340
				g_strcmp0(info->interface, "255/1/2") == 0 ||
6736 by Marcel Holtmann
udev: Handle USB descriptors from Vodafone K5005 modem
341
				g_strcmp0(info->interface, "255/2/2") == 0 ||
7820 by Frédéric Dalleau
udevng: Detect huawei E3372 pcui
342
				g_strcmp0(info->interface, "255/2/18") == 0 ||
7821 by Frédéric Dalleau
udevng: Detect huawei E3372 modem and pcui
343
				g_strcmp0(info->interface, "255/3/18") == 0 ||
6736 by Marcel Holtmann
udev: Handle USB descriptors from Vodafone K5005 modem
344
				g_strcmp0(info->interface, "255/1/50") == 0) {
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
345
			pcui = info->devnode;
5728 by Marcel Holtmann
udev: Detect Diagnostic (QCDM) port for Huawei devices
346
		} else if (g_strcmp0(info->label, "diag") == 0 ||
347
				g_strcmp0(info->interface, "255/1/3") == 0 ||
6736 by Marcel Holtmann
udev: Handle USB descriptors from Vodafone K5005 modem
348
				g_strcmp0(info->interface, "255/2/3") == 0 ||
349
				g_strcmp0(info->interface, "255/1/51") == 0) {
5728 by Marcel Holtmann
udev: Detect Diagnostic (QCDM) port for Huawei devices
350
			diag = info->devnode;
6736 by Marcel Holtmann
udev: Handle USB descriptors from Vodafone K5005 modem
351
		} else if (g_strcmp0(info->interface, "255/1/8") == 0 ||
352
				g_strcmp0(info->interface, "255/1/56") == 0) {
6288 by Marcel Holtmann
udev: Add support for detecting Huawei QMI devices
353
			net = info->devnode;
6736 by Marcel Holtmann
udev: Handle USB descriptors from Vodafone K5005 modem
354
		} else if (g_strcmp0(info->interface, "255/1/9") == 0 ||
355
				g_strcmp0(info->interface, "255/1/57") == 0) {
356
			qmi = info->devnode;
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
357
		} else if (g_strcmp0(info->interface, "255/255/255") == 0) {
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
358
			if (g_strcmp0(info->number, "00") == 0)
359
				mdm = info->devnode;
5747 by Marcel Holtmann
udev: Add support for Huawei E160 based devices with only two TTY
360
			else if (g_strcmp0(info->number, "01") == 0)
361
				pcui = info->devnode;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
362
			else if (g_strcmp0(info->number, "02") == 0)
363
				pcui = info->devnode;
364
			else if (g_strcmp0(info->number, "03") == 0)
365
				pcui = info->devnode;
366
			else if (g_strcmp0(info->number, "04") == 0)
367
				pcui = info->devnode;
368
		}
369
	}
370
6737 by Marcel Holtmann
udev: Use Qualcomm Gobi driver if QMI based modem
371
	if (qmi != NULL && net != NULL) {
372
		ofono_modem_set_driver(modem->modem, "gobi");
373
		goto done;
374
	}
375
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
376
	if (mdm == NULL || pcui == NULL)
377
		return FALSE;
378
6737 by Marcel Holtmann
udev: Use Qualcomm Gobi driver if QMI based modem
379
done:
6288 by Marcel Holtmann
udev: Add support for detecting Huawei QMI devices
380
	DBG("mdm=%s pcui=%s diag=%s qmi=%s net=%s", mdm, pcui, diag, qmi, net);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
381
6288 by Marcel Holtmann
udev: Add support for detecting Huawei QMI devices
382
	ofono_modem_set_string(modem->modem, "Device", qmi);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
383
	ofono_modem_set_string(modem->modem, "Modem", mdm);
384
	ofono_modem_set_string(modem->modem, "Pcui", pcui);
5728 by Marcel Holtmann
udev: Detect Diagnostic (QCDM) port for Huawei devices
385
	ofono_modem_set_string(modem->modem, "Diag", diag);
6288 by Marcel Holtmann
udev: Add support for detecting Huawei QMI devices
386
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
387
388
	return TRUE;
389
}
390
5703 by Marcel Holtmann
udev: Use semi-automatic detection for SpeedUp devices
391
static gboolean setup_speedup(struct modem_info *modem)
392
{
393
	const char *aux = NULL, *mdm = NULL;
394
	GSList *list;
395
396
	DBG("%s", modem->syspath);
397
398
	for (list = modem->devices; list; list = list->next) {
399
		struct device_info *info = list->data;
400
401
		DBG("%s %s %s %s", info->devnode, info->interface,
402
						info->number, info->label);
403
404
		if (g_strcmp0(info->label, "aux") == 0) {
405
			aux = info->devnode;
406
			if (mdm != NULL)
407
				break;
408
		} else if (g_strcmp0(info->label, "modem") == 0) {
409
			mdm = info->devnode;
410
			if (aux != NULL)
411
				break;
412
		}
413
	}
414
415
	if (aux == NULL || mdm == NULL)
416
		return FALSE;
417
418
	DBG("aux=%s modem=%s", aux, mdm);
419
420
	ofono_modem_set_string(modem->modem, "Aux", aux);
421
	ofono_modem_set_string(modem->modem, "Modem", mdm);
422
423
	return TRUE;
424
}
425
5755 by Marcel Holtmann
udev: Add automatic detection for Linktop devices
426
static gboolean setup_linktop(struct modem_info *modem)
427
{
428
	const char *aux = NULL, *mdm = NULL;
429
	GSList *list;
430
431
	DBG("%s", modem->syspath);
432
433
	for (list = modem->devices; list; list = list->next) {
434
		struct device_info *info = list->data;
435
436
		DBG("%s %s %s %s", info->devnode, info->interface,
437
						info->number, info->label);
438
439
		if (g_strcmp0(info->interface, "2/2/1") == 0) {
440
			if (g_strcmp0(info->number, "01") == 0)
441
				aux = info->devnode;
442
			else if (g_strcmp0(info->number, "03") == 0)
443
				mdm = info->devnode;
444
		}
445
	}
446
447
	if (aux == NULL || mdm == NULL)
448
		return FALSE;
449
450
	DBG("aux=%s modem=%s", aux, mdm);
451
452
	ofono_modem_set_string(modem->modem, "Aux", aux);
453
	ofono_modem_set_string(modem->modem, "Modem", mdm);
454
455
	return TRUE;
456
}
457
6186 by Marcel Holtmann
udev: Add detection support for Icera based devices
458
static gboolean setup_icera(struct modem_info *modem)
459
{
460
	const char *aux = NULL, *mdm = NULL, *net = NULL;
461
	GSList *list;
462
463
	DBG("%s", modem->syspath);
464
465
	for (list = modem->devices; list; list = list->next) {
466
		struct device_info *info = list->data;
467
468
		DBG("%s %s %s %s", info->devnode, info->interface,
469
						info->number, info->label);
470
471
		if (g_strcmp0(info->interface, "2/2/1") == 0) {
6274 by Marcel Holtmann
udev: Extend port mapping for Icera modems
472
			if (g_strcmp0(info->number, "00") == 0)
473
				aux = info->devnode;
474
			else if (g_strcmp0(info->number, "01") == 0)
475
				aux = info->devnode;
476
			else if (g_strcmp0(info->number, "02") == 0)
477
				mdm = info->devnode;
6186 by Marcel Holtmann
udev: Add detection support for Icera based devices
478
			else if (g_strcmp0(info->number, "03") == 0)
479
				mdm = info->devnode;
480
		} else if (g_strcmp0(info->interface, "2/6/0") == 0) {
481
			if (g_strcmp0(info->number, "05") == 0)
482
				net = info->devnode;
6274 by Marcel Holtmann
udev: Extend port mapping for Icera modems
483
			else if (g_strcmp0(info->number, "06") == 0)
484
				net = info->devnode;
485
			else if (g_strcmp0(info->number, "07") == 0)
486
				net = info->devnode;
6186 by Marcel Holtmann
udev: Add detection support for Icera based devices
487
		}
488
	}
489
490
	if (aux == NULL || mdm == NULL)
491
		return FALSE;
492
493
	DBG("aux=%s modem=%s net=%s", aux, mdm, net);
494
495
	ofono_modem_set_string(modem->modem, "Aux", aux);
496
	ofono_modem_set_string(modem->modem, "Modem", mdm);
497
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
498
499
	return TRUE;
500
}
501
5718 by Marcel Holtmann
udev: Add automatic detection for Alcatel X220L
502
static gboolean setup_alcatel(struct modem_info *modem)
503
{
504
	const char *aux = NULL, *mdm = NULL;
505
	GSList *list;
506
507
	DBG("%s", modem->syspath);
508
509
	for (list = modem->devices; list; list = list->next) {
510
		struct device_info *info = list->data;
511
512
		DBG("%s %s %s %s", info->devnode, info->interface,
513
						info->number, info->label);
514
515
		if (g_strcmp0(info->label, "aux") == 0) {
516
			aux = info->devnode;
517
			if (mdm != NULL)
518
				break;
519
		} else if (g_strcmp0(info->label, "modem") == 0) {
520
			mdm = info->devnode;
521
			if (aux != NULL)
522
				break;
523
		} else if (g_strcmp0(info->interface, "255/255/255") == 0) {
524
			if (g_strcmp0(info->number, "03") == 0)
525
				aux = info->devnode;
526
			else if (g_strcmp0(info->number, "05") == 0)
527
				mdm = info->devnode;
528
		}
529
	}
530
531
	if (aux == NULL || mdm == NULL)
532
		return FALSE;
533
534
	DBG("aux=%s modem=%s", aux, mdm);
535
536
	ofono_modem_set_string(modem->modem, "Aux", aux);
537
	ofono_modem_set_string(modem->modem, "Modem", mdm);
538
539
	return TRUE;
540
}
541
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
542
static gboolean setup_novatel(struct modem_info *modem)
543
{
544
	const char *aux = NULL, *mdm = NULL;
545
	GSList *list;
546
547
	DBG("%s", modem->syspath);
548
549
	for (list = modem->devices; list; list = list->next) {
550
		struct device_info *info = list->data;
551
552
		DBG("%s %s %s %s", info->devnode, info->interface,
553
						info->number, info->label);
554
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
555
		if (g_strcmp0(info->label, "aux") == 0) {
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
556
			aux = info->devnode;
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
557
			if (mdm != NULL)
558
				break;
559
		} else if (g_strcmp0(info->label, "modem") == 0) {
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
560
			mdm = info->devnode;
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
561
			if (aux != NULL)
562
				break;
563
		} else if (g_strcmp0(info->interface, "255/255/255") == 0) {
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
564
			if (g_strcmp0(info->number, "00") == 0)
565
				aux = info->devnode;
566
			else if (g_strcmp0(info->number, "01") == 0)
567
				mdm = info->devnode;
568
		}
569
	}
570
571
	if (aux == NULL || mdm == NULL)
572
		return FALSE;
573
574
	DBG("aux=%s modem=%s", aux, mdm);
575
5730 by Marcel Holtmann
udev: Use standard modem properties for Novatel devices
576
	ofono_modem_set_string(modem->modem, "Aux", aux);
577
	ofono_modem_set_string(modem->modem, "Modem", mdm);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
578
579
	return TRUE;
580
}
581
5724 by Marcel Holtmann
udev: udev: Add automatic detection for Nokia data cards
582
static gboolean setup_nokia(struct modem_info *modem)
583
{
584
	const char *aux = NULL, *mdm = NULL;
585
	GSList *list;
586
587
	DBG("%s", modem->syspath);
588
589
	for (list = modem->devices; list; list = list->next) {
590
		struct device_info *info = list->data;
591
592
		DBG("%s %s %s %s", info->devnode, info->interface,
593
						info->number, info->label);
594
595
		if (g_strcmp0(info->label, "aux") == 0) {
596
			aux = info->devnode;
597
			if (mdm != NULL)
598
				break;
599
		} else if (g_strcmp0(info->label, "modem") == 0) {
600
			mdm = info->devnode;
601
			if (aux != NULL)
602
				break;
603
		} else if (g_strcmp0(info->interface, "10/0/0") == 0) {
604
			if (g_strcmp0(info->number, "02") == 0)
605
				mdm = info->devnode;
606
			else if (g_strcmp0(info->number, "04") == 0)
607
				aux = info->devnode;
608
		}
609
	}
610
611
	if (aux == NULL || mdm == NULL)
612
		return FALSE;
613
614
	DBG("aux=%s modem=%s", aux, mdm);
615
616
	ofono_modem_set_string(modem->modem, "Aux", aux);
617
	ofono_modem_set_string(modem->modem, "Modem", mdm);
618
619
	return TRUE;
620
}
621
5753 by Marcel Holtmann
udev: Add automatic detection for Telit modems
622
static gboolean setup_telit(struct modem_info *modem)
623
{
7905 by Piotr Haber
udevng: setup of Telit LE910V2
624
	const char *mdm = NULL, *aux = NULL, *gps = NULL, *net = NULL;
7135 by Denis Kenzior
udevng: Add he910 detection logic
625
	GSList *list;
626
627
	DBG("%s", modem->syspath);
628
629
	for (list = modem->devices; list; list = list->next) {
630
		struct device_info *info = list->data;
631
632
		DBG("%s %s %s %s", info->devnode, info->interface,
633
						info->number, info->label);
634
7913 by Piotr Haber
udevng: unify telit and xe910
635
		if (g_strcmp0(info->label, "aux") == 0) {
636
			aux = info->devnode;
637
			if (mdm != NULL)
638
				break;
639
		} else if (g_strcmp0(info->label, "modem") == 0) {
640
			mdm = info->devnode;
641
			if (aux != NULL)
642
				break;
643
		} else if (g_strcmp0(info->interface, "255/255/255") == 0) {
644
			if (g_strcmp0(info->number, "00") == 0)
645
				mdm = info->devnode;
646
			else if (g_strcmp0(info->number, "02") == 0)
647
				gps = info->devnode;
648
			else if (g_strcmp0(info->number, "03") == 0)
649
				aux = info->devnode;
650
		} else if (g_strcmp0(info->interface, "2/2/1") == 0) {
7135 by Denis Kenzior
udevng: Add he910 detection logic
651
			if (g_strcmp0(info->number, "00") == 0)
652
				mdm = info->devnode;
653
			else if (g_strcmp0(info->number, "06") == 0)
654
				aux = info->devnode;
7286 by Kuba Pawlak
udev: add GPS port definition for HE910
655
			else if (g_strcmp0(info->number, "0a") == 0)
656
				gps = info->devnode;
7905 by Piotr Haber
udevng: setup of Telit LE910V2
657
		} else if (info->sysattr && (g_str_has_suffix(info->sysattr,
658
						"CDC NCM") == TRUE)) {
659
			net = info->devnode;
7135 by Denis Kenzior
udevng: Add he910 detection logic
660
		}
661
	}
662
663
	if (aux == NULL || mdm == NULL)
664
		return FALSE;
665
7905 by Piotr Haber
udevng: setup of Telit LE910V2
666
	DBG("modem=%s aux=%s gps=%s net=%s", mdm, aux, gps, net);
7135 by Denis Kenzior
udevng: Add he910 detection logic
667
668
	ofono_modem_set_string(modem->modem, "Modem", mdm);
669
	ofono_modem_set_string(modem->modem, "Aux", aux);
7286 by Kuba Pawlak
udev: add GPS port definition for HE910
670
	ofono_modem_set_string(modem->modem, "GPS", gps);
7135 by Denis Kenzior
udevng: Add he910 detection logic
671
7905 by Piotr Haber
udevng: setup of Telit LE910V2
672
	if (net != NULL)
673
		ofono_modem_set_string(modem->modem, "NetworkInterface", net);
674
7135 by Denis Kenzior
udevng: Add he910 detection logic
675
	return TRUE;
676
}
677
7945 by Lukasz Nowak
udevng: add Telit LE910 V1 support
678
static gboolean setup_telitqmi(struct modem_info *modem)
679
{
680
	const char *qmi = NULL, *net = NULL;
681
	GSList *list;
682
683
	DBG("%s", modem->syspath);
684
685
	for (list = modem->devices; list; list = list->next) {
686
		struct device_info *info = list->data;
687
688
		DBG("%s %s %s %s %s", info->devnode, info->interface,
689
				info->number, info->label, info->subsystem);
690
691
		if (g_strcmp0(info->interface, "255/255/255") == 0 &&
692
				g_strcmp0(info->number, "02") == 0) {
693
			if (g_strcmp0(info->subsystem, "net") == 0)
694
				net = info->devnode;
695
			else if (g_strcmp0(info->subsystem, "usbmisc") == 0)
696
				qmi = info->devnode;
697
		}
698
	}
699
700
	if (qmi == NULL || net == NULL)
701
		return FALSE;
702
703
	DBG("qmi=%s net=%s", qmi, net);
704
705
	ofono_modem_set_string(modem->modem, "Device", qmi);
706
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
707
708
	ofono_modem_set_boolean(modem->modem, "ForceSimLegacy", TRUE);
709
	ofono_modem_set_boolean(modem->modem, "AlwaysOnline", TRUE);
710
	ofono_modem_set_driver(modem->modem, "gobi");
711
712
	return TRUE;
713
}
714
8844 by Pavel Machek
droid 4: Add probing.
715
static gboolean setup_droid(struct modem_info *modem)
716
{
717
	const char *at = NULL;
718
	GSList *list;
719
720
	DBG("%s", modem->syspath);
721
722
	for (list = modem->devices; list; list = list->next) {
723
		struct device_info *info = list->data;
724
725
		DBG("%s %s %s %s %s", info->devnode, info->interface,
726
				info->number, info->label, info->subsystem);
727
728
		if (g_strcmp0(info->interface, "255/255/255") == 0 &&
729
				g_strcmp0(info->number, "04") == 0) {
730
			at = info->devnode;
731
		}
732
	}
733
734
	if (at == NULL)
735
		return FALSE;
736
737
	ofono_modem_set_string(modem->modem, "Device", at);
738
	ofono_modem_set_driver(modem->modem, "droid");
739
740
	return TRUE;
741
}
742
8372 by Denis Kenzior
udevng: Fix SIM900 detection
743
/* TODO: Not used as we have no simcom driver */
744
static gboolean setup_simcom(struct modem_info *modem)
6060 by Marcel Holtmann
udev: Add detection support for SIM COM modems
745
{
746
	const char *mdm = NULL, *aux = NULL, *gps = NULL, *diag = NULL;
747
	GSList *list;
748
749
	DBG("%s", modem->syspath);
750
751
	for (list = modem->devices; list; list = list->next) {
752
		struct device_info *info = list->data;
753
754
		DBG("%s %s %s %s", info->devnode, info->interface,
755
						info->number, info->label);
756
757
		if (g_strcmp0(info->label, "aux") == 0) {
758
			aux = info->devnode;
759
			if (mdm != NULL)
760
				break;
761
		} else if (g_strcmp0(info->label, "modem") == 0) {
762
			mdm = info->devnode;
763
			if (aux != NULL)
764
				break;
765
		} else if (g_strcmp0(info->interface, "255/255/255") == 0) {
766
			if (g_strcmp0(info->number, "00") == 0)
767
				diag = info->devnode;
768
			else if (g_strcmp0(info->number, "01") == 0)
769
				gps = info->devnode;
770
			else if (g_strcmp0(info->number, "02") == 0)
771
				aux = info->devnode;
772
			else if (g_strcmp0(info->number, "03") == 0)
773
				mdm = info->devnode;
774
		}
775
	}
776
777
	if (aux == NULL || mdm == NULL)
778
		return FALSE;
779
780
	DBG("modem=%s aux=%s gps=%s diag=%s", mdm, aux, gps, diag);
781
782
	ofono_modem_set_string(modem->modem, "Modem", mdm);
783
	ofono_modem_set_string(modem->modem, "Data", aux);
784
	ofono_modem_set_string(modem->modem, "GPS", gps);
785
786
	return TRUE;
787
}
788
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
789
static gboolean setup_zte(struct modem_info *modem)
790
{
5727 by Marcel Holtmann
udev: Detect QCDM port for ZTE devices
791
	const char *aux = NULL, *mdm = NULL, *qcdm = NULL;
6065 by Marcel Holtmann
udev: Limit ZTE port selection to specific product identifiers
792
	const char *modem_intf;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
793
	GSList *list;
794
795
	DBG("%s", modem->syspath);
796
6065 by Marcel Holtmann
udev: Limit ZTE port selection to specific product identifiers
797
	if (g_strcmp0(modem->model, "0016") == 0 ||
798
				g_strcmp0(modem->model, "0017") == 0 ||
799
				g_strcmp0(modem->model, "0117") == 0)
800
		modem_intf = "02";
801
	else
802
		modem_intf = "03";
803
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
804
	for (list = modem->devices; list; list = list->next) {
805
		struct device_info *info = list->data;
806
807
		DBG("%s %s %s %s", info->devnode, info->interface,
808
						info->number, info->label);
809
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
810
		if (g_strcmp0(info->label, "aux") == 0) {
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
811
			aux = info->devnode;
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
812
			if (mdm != NULL)
813
				break;
814
		} else if (g_strcmp0(info->label, "modem") == 0) {
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
815
			mdm = info->devnode;
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
816
			if (aux != NULL)
817
				break;
818
		} else if (g_strcmp0(info->interface, "255/255/255") == 0) {
5727 by Marcel Holtmann
udev: Detect QCDM port for ZTE devices
819
			if (g_strcmp0(info->number, "00") == 0)
820
				qcdm = info->devnode;
821
			else if (g_strcmp0(info->number, "01") == 0)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
822
				aux = info->devnode;
6065 by Marcel Holtmann
udev: Limit ZTE port selection to specific product identifiers
823
			else if (g_strcmp0(info->number, modem_intf) == 0)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
824
				mdm = info->devnode;
825
		}
826
	}
827
828
	if (aux == NULL || mdm == NULL)
829
		return FALSE;
830
5727 by Marcel Holtmann
udev: Detect QCDM port for ZTE devices
831
	DBG("aux=%s modem=%s qcdm=%s", aux, mdm, qcdm);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
832
833
	ofono_modem_set_string(modem->modem, "Aux", aux);
834
	ofono_modem_set_string(modem->modem, "Modem", mdm);
835
836
	return TRUE;
837
}
838
5700 by Marcel Holtmann
udev: Use fully automatic detection for Samsung LTE devices
839
static gboolean setup_samsung(struct modem_info *modem)
840
{
841
	const char *control = NULL, *network = NULL;
842
	GSList *list;
843
844
	DBG("%s", modem->syspath);
845
846
	for (list = modem->devices; list; list = list->next) {
847
		struct device_info *info = list->data;
848
849
		DBG("%s %s %s %s", info->devnode, info->interface,
850
						info->number, info->label);
851
852
		if (g_strcmp0(info->interface, "10/0/0") == 0)
853
			control = info->devnode;
854
		else if (g_strcmp0(info->interface, "255/0/0") == 0)
855
			network = info->devnode;
856
	}
857
858
	if (control == NULL && network == NULL)
859
		return FALSE;
860
861
	DBG("control=%s network=%s", control, network);
862
863
	ofono_modem_set_string(modem->modem, "ControlPort", control);
864
	ofono_modem_set_string(modem->modem, "NetworkInterface", network);
865
866
	return TRUE;
867
}
868
8693 by Martin Hundebøll
quectel: add basic support for serial connected modems
869
static gboolean setup_quectel_usb(struct modem_info *modem)
870
{
871
	const char *aux = NULL, *mdm = NULL;
872
	GSList *list;
873
874
	DBG("%s", modem->syspath);
875
876
	for (list = modem->devices; list; list = list->next) {
877
		struct device_info *info = list->data;
878
879
		DBG("%s %s %s %s", info->devnode, info->interface,
880
						info->number, info->label);
881
882
		if (g_strcmp0(info->label, "aux") == 0) {
883
			aux = info->devnode;
884
			if (mdm != NULL)
885
				break;
886
		} else if (g_strcmp0(info->label, "modem") == 0) {
887
			mdm = info->devnode;
888
			if (aux != NULL)
889
				break;
890
		} else if (g_strcmp0(info->interface, "255/255/255") == 0) {
891
			if (g_strcmp0(info->number, "02") == 0)
892
				aux = info->devnode;
893
			else if (g_strcmp0(info->number, "03") == 0)
894
				mdm = info->devnode;
895
		}
896
	}
897
898
	if (aux == NULL || mdm == NULL)
899
		return FALSE;
900
901
	DBG("aux=%s modem=%s", aux, mdm);
902
903
	ofono_modem_set_string(modem->modem, "Aux", aux);
904
	ofono_modem_set_string(modem->modem, "Modem", mdm);
905
906
	return TRUE;
907
}
908
909
static gboolean setup_quectel_serial(struct modem_info *modem)
910
{
911
	struct serial_device_info *info = modem->serial;
912
	const char *value;
913
914
	value = udev_device_get_property_value(info->dev,
8695 by Martin Hundebøll
quectel: support gpio to power on/off the modem
915
						"OFONO_QUECTEL_GPIO_CHIP");
916
	if (value)
917
		ofono_modem_set_string(modem->modem, "GpioChip", value);
918
919
	value = udev_device_get_property_value(info->dev,
920
						"OFONO_QUECTEL_GPIO_OFFSET");
921
	if (value)
922
		ofono_modem_set_string(modem->modem, "GpioOffset", value);
923
924
	value = udev_device_get_property_value(info->dev,
8848 by Lars Poeschel
quectel: Power on/off with a gpio pulse
925
						"OFONO_QUECTEL_GPIO_LEVEL");
926
	if (value)
927
		ofono_modem_set_boolean(modem->modem, "GpioLevel", TRUE);
928
929
	value = udev_device_get_property_value(info->dev,
8772 by Martin Hundebøll
udevng: Support quectel MUX settings
930
						"OFONO_QUECTEL_MUX");
931
	if (value)
932
		ofono_modem_set_string(modem->modem, "Mux", value);
933
934
	value = udev_device_get_property_value(info->dev,
8693 by Martin Hundebøll
quectel: add basic support for serial connected modems
935
						"OFONO_QUECTEL_RTSCTS");
936
	ofono_modem_set_string(modem->modem, "RtsCts", value ? value : "off");
937
	ofono_modem_set_string(modem->modem, "Device", info->devnode);
938
939
	return TRUE;
940
}
941
7227 by Philip Paeps
udevng: add detection logic for Quectel modems
942
static gboolean setup_quectel(struct modem_info *modem)
943
{
8861 by Sergei Golubtsov
quectel: adding support for the Quectel EC200 USB modem series
944
	if (modem->type == MODEM_TYPE_SERIAL)
8693 by Martin Hundebøll
quectel: add basic support for serial connected modems
945
		return setup_quectel_serial(modem);
8861 by Sergei Golubtsov
quectel: adding support for the Quectel EC200 USB modem series
946
	else if (modem->type == MODEM_TYPE_USB)
8693 by Martin Hundebøll
quectel: add basic support for serial connected modems
947
		return setup_quectel_usb(modem);
8861 by Sergei Golubtsov
quectel: adding support for the Quectel EC200 USB modem series
948
	else
949
		return FALSE;
7227 by Philip Paeps
udevng: add detection logic for Quectel modems
950
}
951
7981 by Jonas Bonn
Add support for Quectel EC21/25 modems
952
static gboolean setup_quectelqmi(struct modem_info *modem)
953
{
8050 by Jonas Bonn
udev: fix quectelqmi gps interface
954
	const char *qmi = NULL, *net = NULL, *gps = NULL, *aux = NULL;
7981 by Jonas Bonn
Add support for Quectel EC21/25 modems
955
	GSList *list;
956
957
	DBG("%s", modem->syspath);
958
959
	for (list = modem->devices; list; list = g_slist_next(list)) {
960
		struct device_info *info = list->data;
961
962
		DBG("%s %s %s %s %s", info->devnode, info->interface,
963
				info->number, info->label, info->subsystem);
964
965
		if (g_strcmp0(info->interface, "255/255/255") == 0 &&
966
				g_strcmp0(info->number, "04") == 0) {
967
			if (g_strcmp0(info->subsystem, "net") == 0)
968
				net = info->devnode;
969
			else if (g_strcmp0(info->subsystem, "usbmisc") == 0)
970
				qmi = info->devnode;
971
		} else if (g_strcmp0(info->interface, "255/0/0") == 0 &&
8050 by Jonas Bonn
udev: fix quectelqmi gps interface
972
				g_strcmp0(info->number, "01") == 0) {
973
			gps = info->devnode;
974
		} else if (g_strcmp0(info->interface, "255/0/0") == 0 &&
7981 by Jonas Bonn
Add support for Quectel EC21/25 modems
975
				g_strcmp0(info->number, "02") == 0) {
8050 by Jonas Bonn
udev: fix quectelqmi gps interface
976
			aux = info->devnode;
7981 by Jonas Bonn
Add support for Quectel EC21/25 modems
977
		}
978
	}
979
980
	DBG("qmi=%s net=%s", qmi, net);
981
982
	if (qmi == NULL || net == NULL)
983
		return FALSE;
984
985
	DBG("qmi=%s net=%s", qmi, net);
986
987
	ofono_modem_set_string(modem->modem, "Device", qmi);
988
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
989
8050 by Jonas Bonn
udev: fix quectelqmi gps interface
990
	DBG("gps=%s aux=%s", gps, aux);
991
7981 by Jonas Bonn
Add support for Quectel EC21/25 modems
992
	if (gps)
993
		ofono_modem_set_string(modem->modem, "GPS", gps);
8050 by Jonas Bonn
udev: fix quectelqmi gps interface
994
	if (aux)
995
		ofono_modem_set_string(modem->modem, "Aux", aux);
7981 by Jonas Bonn
Add support for Quectel EC21/25 modems
996
997
	ofono_modem_set_driver(modem->modem, "gobi");
998
999
	return TRUE;
1000
}
1001
8086 by Denis Kenzior
udevng: Add basic detection for MBIM
1002
static gboolean setup_mbim(struct modem_info *modem)
1003
{
1004
	const char *ctl = NULL, *net = NULL, *atcmd = NULL;
1005
	GSList *list;
8089 by Denis Kenzior
udevng: Store MBIM descriptors file
1006
	char descriptors[PATH_MAX];
8086 by Denis Kenzior
udevng: Add basic detection for MBIM
1007
8219 by Denis Kenzior
udevng: Save off MBIM modem's VID/PID
1008
	DBG("%s [%s:%s]", modem->syspath, modem->vendor, modem->model);
8086 by Denis Kenzior
udevng: Add basic detection for MBIM
1009
1010
	for (list = modem->devices; list; list = list->next) {
1011
		struct device_info *info = list->data;
1012
1013
		DBG("%s %s %s %s %s %s", info->devnode, info->interface,
1014
						info->number, info->label,
1015
						info->sysattr, info->subsystem);
1016
1017
		if (g_strcmp0(info->subsystem, "usbmisc") == 0) /* cdc-wdm */
1018
			ctl = info->devnode;
1019
		else if (g_strcmp0(info->subsystem, "net") == 0) /* wwan */
1020
			net = info->devnode;
1021
		else if (g_strcmp0(info->subsystem, "tty") == 0) {
1022
			if (g_strcmp0(info->number, "02") == 0)
1023
				atcmd = info->devnode;
1024
		}
1025
	}
1026
1027
	if (ctl == NULL || net == NULL)
1028
		return FALSE;
1029
1030
	DBG("ctl=%s net=%s atcmd=%s", ctl, net, atcmd);
1031
8089 by Denis Kenzior
udevng: Store MBIM descriptors file
1032
	sprintf(descriptors, "%s/descriptors", modem->syspath);
1033
8086 by Denis Kenzior
udevng: Add basic detection for MBIM
1034
	ofono_modem_set_string(modem->modem, "Device", ctl);
1035
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
8089 by Denis Kenzior
udevng: Store MBIM descriptors file
1036
	ofono_modem_set_string(modem->modem, "DescriptorFile", descriptors);
8086 by Denis Kenzior
udevng: Add basic detection for MBIM
1037
1038
	return TRUE;
1039
}
1040
7948 by Jonas Bonn
udevng: add serial device handling functions
1041
static gboolean setup_serial_modem(struct modem_info* modem)
1042
{
1043
	struct serial_device_info* info;
1044
1045
	info = modem->serial;
1046
1047
	ofono_modem_set_string(modem->modem, "Device", info->devnode);
1048
1049
	return TRUE;
1050
}
1051
1052
static gboolean setup_tc65(struct modem_info* modem)
1053
{
1054
	ofono_modem_set_driver(modem->modem, "cinterion");
1055
1056
	return setup_serial_modem(modem);
1057
}
1058
1059
static gboolean setup_ehs6(struct modem_info* modem)
1060
{
1061
	ofono_modem_set_driver(modem->modem, "cinterion");
1062
1063
	return setup_serial_modem(modem);
1064
}
1065
1066
static gboolean setup_ifx(struct modem_info* modem)
1067
{
1068
	struct serial_device_info* info;
1069
	const char *value;
1070
1071
	info = modem->serial;
1072
1073
	value = udev_device_get_property_value(info->dev, "OFONO_IFX_LDISC");
1074
	if (value)
1075
		ofono_modem_set_string(modem->modem, "LineDiscipline", value);
1076
1077
	value = udev_device_get_property_value(info->dev, "OFONO_IFX_AUDIO");
1078
	if (value)
1079
		ofono_modem_set_string(modem->modem, "AudioSetting", value);
1080
1081
	value = udev_device_get_property_value(info->dev, "OFONO_IFX_LOOPBACK");
1082
	if (value)
1083
		ofono_modem_set_string(modem->modem, "AudioLoopback", value);
1084
1085
	ofono_modem_set_string(modem->modem, "Device", info->devnode);
1086
1087
	return TRUE;
1088
}
1089
1090
static gboolean setup_wavecom(struct modem_info* modem)
1091
{
1092
	struct serial_device_info* info;
1093
	const char *value;
1094
1095
	info = modem->serial;
1096
1097
	value = udev_device_get_property_value(info->dev,
1098
						"OFONO_WAVECOM_MODEL");
1099
	if (value)
1100
		ofono_modem_set_string(modem->modem, "Model", value);
1101
1102
	ofono_modem_set_string(modem->modem, "Device", info->devnode);
1103
1104
	return TRUE;
1105
}
1106
1107
static gboolean setup_isi_serial(struct modem_info* modem)
1108
{
1109
	struct serial_device_info* info;
1110
	const char *value;
1111
1112
	info = modem->serial;
1113
1114
	if (g_strcmp0(udev_device_get_subsystem(info->dev), "net") != 0)
1115
		return FALSE;
1116
1117
	value = udev_device_get_sysattr_value(info->dev, "type");
1118
	if (g_strcmp0(value, "820") != 0)
1119
		return FALSE;
1120
1121
	/* OK, we want this device to be a modem */
1122
	value = udev_device_get_sysname(info->dev);
1123
	if (value)
1124
		ofono_modem_set_string(modem->modem, "Interface", value);
1125
1126
	value = udev_device_get_property_value(info->dev, "OFONO_ISI_ADDRESS");
1127
	if (value)
1128
		ofono_modem_set_integer(modem->modem, "Address", atoi(value));
1129
1130
	return TRUE;
1131
}
1132
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1133
static gboolean setup_ublox(struct modem_info *modem)
1134
{
7667 by Dongsu Park
udevng: Support U-blox TOBY series of devices
1135
	const char *aux = NULL, *mdm = NULL, *net = NULL;
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1136
	GSList *list;
1137
1138
	DBG("%s", modem->syspath);
1139
1140
	for (list = modem->devices; list; list = list->next) {
1141
		struct device_info *info = list->data;
1142
1143
		DBG("%s %s %s %s", info->devnode, info->interface,
1144
					info->number, info->label);
1145
1146
		if (g_strcmp0(info->label, "aux") == 0) {
1147
			aux = info->devnode;
1148
			if (mdm != NULL)
1149
				break;
1150
		} else if (g_strcmp0(info->label, "modem") == 0) {
1151
			mdm = info->devnode;
1152
			if (aux != NULL)
1153
				break;
7667 by Dongsu Park
udevng: Support U-blox TOBY series of devices
1154
		/*
1155
		 * "2/2/1"
1156
		 *  - a common modem interface both for older models like LISA,
1157
		 *    and for newer models like TOBY.
1158
		 * For TOBY-L2, NetworkInterface can be detected for each
1159
		 * profile:
1160
		 *  - low-medium throughput profile : 2/6/0
1161
		 *  - fairly backward-compatible profile : 10/0/0
1162
		 *  - high throughput profile : 224/1/3
1163
		 */
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1164
		} else if (g_strcmp0(info->interface, "2/2/1") == 0) {
8578 by Jonas Bonn
udevng: detect ublox TOBY L4
1165
			if (!g_strcmp0(modem->model, "1010")) {
1166
				if (g_strcmp0(info->number, "06") == 0)
1167
					aux = info->devnode;
1168
			} else {
1169
				if (g_strcmp0(info->number, "02") == 0)
1170
					aux = info->devnode;
1171
			}
1172
			if (g_strcmp0(info->number, "00") == 0)
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1173
				mdm = info->devnode;
7667 by Dongsu Park
udevng: Support U-blox TOBY series of devices
1174
		} else if (g_strcmp0(info->interface, "2/6/0") == 0 ||
8578 by Jonas Bonn
udevng: detect ublox TOBY L4
1175
				g_strcmp0(info->interface, "2/13/0") == 0 ||
7784 by Denis Kenzior
udevng: Fixup various minor style issues
1176
				g_strcmp0(info->interface, "10/0/0") == 0 ||
1177
				g_strcmp0(info->interface, "224/1/3") == 0) {
7667 by Dongsu Park
udevng: Support U-blox TOBY series of devices
1178
			net = info->devnode;
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1179
		}
1180
	}
1181
7667 by Dongsu Park
udevng: Support U-blox TOBY series of devices
1182
	/* Abort only if both interfaces are NULL, as it's highly possible that
1183
	 * only one of 2 interfaces is available for U-blox modem.
1184
	 */
1185
	if (aux == NULL && mdm == NULL)
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1186
		return FALSE;
1187
7667 by Dongsu Park
udevng: Support U-blox TOBY series of devices
1188
	DBG("aux=%s modem=%s net=%s", aux, mdm, net);
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1189
1190
	ofono_modem_set_string(modem->modem, "Aux", aux);
1191
	ofono_modem_set_string(modem->modem, "Modem", mdm);
7667 by Dongsu Park
udevng: Support U-blox TOBY series of devices
1192
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1193
1194
	return TRUE;
1195
}
1196
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1197
static gboolean setup_gemalto(struct modem_info* modem)
1198
{
7895 by Vincent Cesson
udevng: complete gemalto setup
1199
	const char *app = NULL, *gps = NULL, *mdm = NULL,
8835 by Sergey Matyukevich
plugins: udevng: detect gemalto network interfaces
1200
		*net = NULL, *qmi = NULL, *net2 = NULL;
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1201
1202
	GSList *list;
1203
1204
	DBG("%s", modem->syspath);
1205
1206
	for (list = modem->devices; list; list = list->next) {
1207
		struct device_info *info = list->data;
1208
1209
		DBG("%s %s %s %s %s", info->devnode, info->interface,
1210
				info->number, info->label, info->subsystem);
1211
8322 by Gabriel Lucas
gemalto: add detection of ALS3 modem
1212
		/* PHS8-P */
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1213
		if (g_strcmp0(info->interface, "255/255/255") == 0) {
1214
			if (g_strcmp0(info->number, "01") == 0)
1215
				gps = info->devnode;
1216
			else if (g_strcmp0(info->number, "02") == 0)
1217
				app = info->devnode;
1218
			else if (g_strcmp0(info->number, "03") == 0)
1219
				mdm = info->devnode;
7895 by Vincent Cesson
udevng: complete gemalto setup
1220
			else if (g_strcmp0(info->subsystem, "net") == 0)
1221
				net = info->devnode;
1222
			else if (g_strcmp0(info->subsystem, "usbmisc") == 0)
1223
				qmi = info->devnode;
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1224
		}
8322 by Gabriel Lucas
gemalto: add detection of ALS3 modem
1225
8327 by Bassem Boubaker
gemalto: Add more details in setup_gemalto comment
1226
		/* Cinterion ALS3, PLS8-E, PLS8-X */
8322 by Gabriel Lucas
gemalto: add detection of ALS3 modem
1227
		if (g_strcmp0(info->interface, "2/2/1") == 0) {
1228
			if (g_strcmp0(info->number, "00") == 0)
1229
				mdm = info->devnode;
1230
			else if (g_strcmp0(info->number, "02") == 0)
1231
				app = info->devnode;
1232
			else if (g_strcmp0(info->number, "04") == 0)
1233
				gps = info->devnode;
1234
		}
8835 by Sergey Matyukevich
plugins: udevng: detect gemalto network interfaces
1235
8322 by Gabriel Lucas
gemalto: add detection of ALS3 modem
1236
		if (g_strcmp0(info->interface, "2/6/0") == 0) {
8835 by Sergey Matyukevich
plugins: udevng: detect gemalto network interfaces
1237
			if (g_strcmp0(info->subsystem, "net") == 0) {
1238
				if (g_strcmp0(info->number, "0a") == 0)
1239
					net = info->devnode;
1240
				if (g_strcmp0(info->number, "0c") == 0)
1241
					net2 = info->devnode;
1242
			}
8322 by Gabriel Lucas
gemalto: add detection of ALS3 modem
1243
		}
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1244
	}
1245
7895 by Vincent Cesson
udevng: complete gemalto setup
1246
	DBG("application=%s gps=%s modem=%s network=%s qmi=%s",
1247
			app, gps, mdm, net, qmi);
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1248
1249
	if (app == NULL || mdm == NULL)
1250
		return FALSE;
1251
1252
	ofono_modem_set_string(modem->modem, "Application", app);
1253
	ofono_modem_set_string(modem->modem, "GPS", gps);
1254
	ofono_modem_set_string(modem->modem, "Modem", mdm);
7895 by Vincent Cesson
udevng: complete gemalto setup
1255
	ofono_modem_set_string(modem->modem, "Device", qmi);
8322 by Gabriel Lucas
gemalto: add detection of ALS3 modem
1256
	ofono_modem_set_string(modem->modem, "Model", modem->model);
7895 by Vincent Cesson
udevng: complete gemalto setup
1257
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1258
8835 by Sergey Matyukevich
plugins: udevng: detect gemalto network interfaces
1259
	if (net2)
1260
		ofono_modem_set_string(modem->modem, "NetworkInterface2", net2);
1261
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1262
	return TRUE;
1263
}
1264
8080 by Ankit Navik
udevng/xmm7xxx: Allow to detect xmm7xxx series modems
1265
static gboolean setup_xmm7xxx(struct modem_info *modem)
1266
{
8557 by Antara Borwankar
udevng: Detect multiple network interfaces for xmm7xxx
1267
	const char *mdm = NULL, *net = NULL, *net2 = NULL, *net3 = NULL;
8080 by Ankit Navik
udevng/xmm7xxx: Allow to detect xmm7xxx series modems
1268
	GSList *list;
1269
1270
	DBG("%s %s\n", __DATE__, __TIME__);
1271
	DBG("%s %s %s %s %s %s\n", modem->syspath, modem->devname,
1272
		modem->driver, modem->vendor, modem->model, modem->sysattr);
1273
1274
	for (list = modem->devices; list; list = list->next) {
1275
		struct device_info *info = list->data;
1276
1277
		DBG("%s %s %s %s %s %s %s\n", info->devpath, info->devnode,
1278
				info->interface, info->number, info->label,
1279
				info->sysattr, info->subsystem);
1280
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
1281
		if (g_strcmp0(info->subsystem, "pci") == 0) {
1282
			if ((g_strcmp0(modem->vendor, "0x8086") == 0) &&
1283
				(g_strcmp0(modem->model, "0x7560") == 0)) {
1284
				mdm = "/dev/iat";
1285
				net = "inm0";
1286
				net2 = "inm1";
1287
				net3 = "inm2";
1288
				ofono_modem_set_string(modem->modem,
1289
					"CtrlPath", "/PCIE/IOSM/CTRL/1");
1290
				ofono_modem_set_string(modem->modem, "DataPath",
1291
					"/PCIE/IOSM/IPS/");
1292
			}
1293
		} else { /* For USB */
1294
			if (g_strcmp0(modem->model, "095a") == 0) {
1295
				if (g_strcmp0(info->subsystem, "tty") == 0) {
1296
					if (g_strcmp0(info->number, "00") == 0)
1297
						mdm = info->devnode;
1298
				} else if (g_strcmp0(info->subsystem, "net")
1299
									== 0) {
1300
					if (g_strcmp0(info->number, "06") == 0)
1301
						net = info->devnode;
1302
					if (g_strcmp0(info->number, "08") == 0)
1303
						net2 = info->devnode;
1304
					if (g_strcmp0(info->number, "0a") == 0)
1305
						net3 = info->devnode;
1306
				}
1307
			} else {
1308
				if (g_strcmp0(info->subsystem, "tty") == 0) {
1309
					if (g_strcmp0(info->number, "02") == 0)
1310
						mdm = info->devnode;
1311
				} else if (g_strcmp0(info->subsystem, "net")
1312
									== 0) {
1313
					if (g_strcmp0(info->number, "00") == 0)
1314
						net = info->devnode;
1315
				}
1316
			}
1317
1318
			ofono_modem_set_string(modem->modem, "CtrlPath",
1319
								"/USBCDC/0");
1320
			ofono_modem_set_string(modem->modem, "DataPath",
1321
								"/USBHS/NCM/");
8080 by Ankit Navik
udevng/xmm7xxx: Allow to detect xmm7xxx series modems
1322
		}
1323
	}
1324
1325
	if (mdm == NULL || net == NULL)
1326
		return FALSE;
1327
1328
	DBG("modem=%s net=%s\n", mdm, net);
1329
1330
	ofono_modem_set_string(modem->modem, "Modem", mdm);
1331
	ofono_modem_set_string(modem->modem, "NetworkInterface", net);
1332
8557 by Antara Borwankar
udevng: Detect multiple network interfaces for xmm7xxx
1333
	if (net2)
1334
		ofono_modem_set_string(modem->modem, "NetworkInterface2", net2);
1335
1336
	if (net3)
1337
		ofono_modem_set_string(modem->modem, "NetworkInterface3", net3);
1338
8080 by Ankit Navik
udevng/xmm7xxx: Allow to detect xmm7xxx series modems
1339
	return TRUE;
1340
}
1341
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1342
static gboolean setup_sim7x00(struct modem_info *modem)
8353 by Bob Ham
plugins: Add support for SIM7100E by SIMCom
1343
{
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1344
	const char *audio = NULL, *diag = NULL, *gps = NULL;
1345
	const char *mdm = NULL, *net = NULL, *ppp = NULL;
1346
	const char *qmi = NULL;
8353 by Bob Ham
plugins: Add support for SIM7100E by SIMCom
1347
	GSList *list;
1348
1349
	DBG("%s", modem->syspath);
1350
1351
	for (list = modem->devices; list; list = list->next) {
1352
		struct device_info *info = list->data;
1353
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1354
		DBG("%s %s %s %s %s %s", info->devnode, info->interface,
1355
						info->number, info->label,
1356
						info->sysattr, info->subsystem);
8353 by Bob Ham
plugins: Add support for SIM7100E by SIMCom
1357
1358
		/*
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1359
		 * SIM7100 serial port layout:
8353 by Bob Ham
plugins: Add support for SIM7100E by SIMCom
1360
		 * 0: QCDM/DIAG
1361
		 * 1: NMEA
1362
		 * 2: AT
1363
		 * 3: AT/PPP
1364
		 * 4: audio
1365
		 *
1366
		 * -- https://www.spinics.net/lists/linux-usb/msg135728.html
1367
		 */
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1368
		if (g_strcmp0(info->subsystem, "usbmisc") == 0) /* cdc-wdm */
1369
			qmi = info->devnode; /* SIM7600 */
1370
		else if (g_strcmp0(info->subsystem, "net") == 0) /* wwan */
1371
			net = info->devnode; /* SIM7600 */
1372
		else if (g_strcmp0(info->subsystem, "tty") == 0) {
1373
			if (g_strcmp0(info->interface, "255/255/255") == 0) {
1374
				if (g_strcmp0(info->number, "00") == 0)
1375
					diag = info->devnode; /* SIM7x00 */
1376
			} else if (g_strcmp0(info->interface, "255/0/0") == 0) {
1377
				if (g_strcmp0(info->number, "01") == 0)
1378
					gps = info->devnode; /* SIM7x00 */
1379
				else if (g_strcmp0(info->number, "02") == 0)
1380
					mdm = info->devnode; /* SIM7x00 */
1381
				else if (g_strcmp0(info->number, "03") == 0)
1382
					ppp = info->devnode; /* SIM7100 */
1383
				else if (g_strcmp0(info->number, "04") == 0)
1384
					audio = info->devnode; /* SIM7100 */
1385
			}
1386
		}
8353 by Bob Ham
plugins: Add support for SIM7100E by SIMCom
1387
	}
1388
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1389
	if (mdm == NULL)
8353 by Bob Ham
plugins: Add support for SIM7100E by SIMCom
1390
		return FALSE;
1391
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1392
	if (qmi != NULL && net != NULL) {
1393
		DBG("qmi=%s net=%s mdm=%s gps=%s diag=%s",
1394
						qmi, net, mdm, gps, diag);
1395
1396
		ofono_modem_set_driver(modem->modem, "gobi");
1397
1398
		ofono_modem_set_string(modem->modem, "Device", qmi);
1399
		ofono_modem_set_string(modem->modem, "Modem", mdm);
1400
		ofono_modem_set_string(modem->modem, "NetworkInterface", net);
1401
	} else {
1402
		DBG("at=%s ppp=%s gps=%s diag=%s, audio=%s",
1403
						mdm, ppp, gps, diag, audio);
1404
1405
		ofono_modem_set_driver(modem->modem, "sim7100");
1406
1407
		ofono_modem_set_string(modem->modem, "AT", mdm);
1408
		ofono_modem_set_string(modem->modem, "PPP", ppp);
1409
		ofono_modem_set_string(modem->modem, "Audio", audio);
1410
	}
1411
8353 by Bob Ham
plugins: Add support for SIM7100E by SIMCom
1412
	ofono_modem_set_string(modem->modem, "GPS", gps);
1413
	ofono_modem_set_string(modem->modem, "Diag", diag);
1414
	return TRUE;
1415
}
1416
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1417
static struct {
1418
	const char *name;
1419
	gboolean (*setup)(struct modem_info *modem);
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
1420
	const char *sysattr;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1421
} driver_list[] = {
5752 by Marcel Holtmann
udev: Add support for automatic ISI USB modem detection
1422
	{ "isiusb",	setup_isi,	"type"			},
5748 by Marcel Holtmann
udev: Add automatic detection for Ericsson MBM based devices
1423
	{ "mbm",	setup_mbm,	"device/interface"	},
1424
	{ "hso",	setup_hso,	"hsotype"		},
6287 by Marcel Holtmann
udev: Add support for detecting Gobi QMI devices
1425
	{ "gobi",	setup_gobi	},
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1426
	{ "sierra",	setup_sierra	},
1427
	{ "huawei",	setup_huawei	},
5703 by Marcel Holtmann
udev: Use semi-automatic detection for SpeedUp devices
1428
	{ "speedupcdma",setup_speedup	},
1429
	{ "speedup",	setup_speedup	},
5755 by Marcel Holtmann
udev: Add automatic detection for Linktop devices
1430
	{ "linktop",	setup_linktop	},
5718 by Marcel Holtmann
udev: Add automatic detection for Alcatel X220L
1431
	{ "alcatel",	setup_alcatel	},
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1432
	{ "novatel",	setup_novatel	},
5724 by Marcel Holtmann
udev: udev: Add automatic detection for Nokia data cards
1433
	{ "nokia",	setup_nokia	},
7913 by Piotr Haber
udevng: unify telit and xe910
1434
	{ "telit",	setup_telit,	"device/interface"	},
7945 by Lukasz Nowak
udevng: add Telit LE910 V1 support
1435
	{ "telitqmi",	setup_telitqmi	},
8372 by Denis Kenzior
udevng: Fix SIM900 detection
1436
	{ "simcom",	setup_simcom	},
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1437
	{ "sim7x00",	setup_sim7x00	},
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1438
	{ "zte",	setup_zte	},
6186 by Marcel Holtmann
udev: Add detection support for Icera based devices
1439
	{ "icera",	setup_icera	},
5700 by Marcel Holtmann
udev: Use fully automatic detection for Samsung LTE devices
1440
	{ "samsung",	setup_samsung	},
7227 by Philip Paeps
udevng: add detection logic for Quectel modems
1441
	{ "quectel",	setup_quectel	},
7981 by Jonas Bonn
Add support for Quectel EC21/25 modems
1442
	{ "quectelqmi",	setup_quectelqmi},
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1443
	{ "ublox",	setup_ublox	},
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1444
	{ "gemalto",	setup_gemalto	},
8080 by Ankit Navik
udevng/xmm7xxx: Allow to detect xmm7xxx series modems
1445
	{ "xmm7xxx",	setup_xmm7xxx	},
8086 by Denis Kenzior
udevng: Add basic detection for MBIM
1446
	{ "mbim",	setup_mbim	},
8844 by Pavel Machek
droid 4: Add probing.
1447
	{ "droid",	setup_droid	},
7948 by Jonas Bonn
udevng: add serial device handling functions
1448
	/* Following are non-USB modems */
1449
	{ "ifx",	setup_ifx		},
1450
	{ "u8500",	setup_isi_serial	},
1451
	{ "n900",	setup_isi_serial	},
1452
	{ "calypso",	setup_serial_modem	},
1453
	{ "cinterion",	setup_serial_modem	},
1454
	{ "nokiacdma",	setup_serial_modem	},
1455
	{ "sim900",	setup_serial_modem	},
1456
	{ "wavecom",	setup_wavecom		},
1457
	{ "tc65",	setup_tc65		},
1458
	{ "ehs6",	setup_ehs6		},
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1459
	{ }
1460
};
1461
1462
static GHashTable *modem_list;
1463
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
1464
static const char *get_sysattr(const char *driver)
1465
{
1466
	unsigned int i;
1467
1468
	for (i = 0; driver_list[i].name; i++) {
1469
		if (g_str_equal(driver_list[i].name, driver) == TRUE)
1470
			return driver_list[i].sysattr;
1471
	}
1472
1473
	return NULL;
1474
}
1475
7948 by Jonas Bonn
udevng: add serial device handling functions
1476
static void device_info_free(struct device_info* info)
1477
{
1478
	g_free(info->devpath);
1479
	g_free(info->devnode);
1480
	g_free(info->interface);
1481
	g_free(info->number);
1482
	g_free(info->label);
1483
	g_free(info->sysattr);
1484
	g_free(info->subsystem);
1485
	g_free(info);
1486
}
1487
1488
static void serial_device_info_free(struct serial_device_info* info)
1489
{
1490
	g_free(info->devpath);
1491
	g_free(info->devnode);
1492
	g_free(info->subsystem);
1493
	udev_device_unref(info->dev);
1494
	g_free(info);
1495
}
1496
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1497
static void destroy_modem(gpointer data)
1498
{
1499
	struct modem_info *modem = data;
1500
	GSList *list;
1501
1502
	DBG("%s", modem->syspath);
1503
1504
	ofono_modem_remove(modem->modem);
1505
7948 by Jonas Bonn
udevng: add serial device handling functions
1506
	switch (modem->type) {
1507
	case MODEM_TYPE_USB:
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
1508
	case MODEM_TYPE_PCIE:
7948 by Jonas Bonn
udevng: add serial device handling functions
1509
		for (list = modem->devices; list; list = list->next) {
1510
			struct device_info *info = list->data;
1511
1512
			DBG("%s", info->devnode);
1513
			device_info_free(info);
1514
		}
1515
1516
		g_slist_free(modem->devices);
1517
		break;
1518
	case MODEM_TYPE_SERIAL:
1519
		serial_device_info_free(modem->serial);
1520
		break;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1521
	}
1522
1523
	g_free(modem->syspath);
1524
	g_free(modem->devname);
1525
	g_free(modem->driver);
6064 by Marcel Holtmann
udev: Keep vendor and product identifiers around
1526
	g_free(modem->vendor);
1527
	g_free(modem->model);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1528
	g_free(modem);
1529
}
1530
1531
static gboolean check_remove(gpointer key, gpointer value, gpointer user_data)
1532
{
5691 by Denis Kenzior
udevng: Fix minor whitespace violation
1533
	struct modem_info *modem = value;
1534
	const char *devpath = user_data;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1535
	GSList *list;
1536
8385 by Martin Hundebøll
udevng: fix removal of serial devices
1537
	switch (modem->type) {
1538
	case MODEM_TYPE_USB:
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
1539
	case MODEM_TYPE_PCIE:
8385 by Martin Hundebøll
udevng: fix removal of serial devices
1540
		for (list = modem->devices; list; list = list->next) {
1541
			struct device_info *info = list->data;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1542
8385 by Martin Hundebøll
udevng: fix removal of serial devices
1543
			if (g_strcmp0(info->devpath, devpath) == 0)
1544
				return TRUE;
1545
		}
1546
		break;
1547
	case MODEM_TYPE_SERIAL:
1548
		if (g_strcmp0(modem->serial->devpath, devpath) == 0)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1549
			return TRUE;
8385 by Martin Hundebøll
udevng: fix removal of serial devices
1550
		break;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1551
	}
1552
1553
	return FALSE;
1554
}
1555
1556
static void remove_device(struct udev_device *device)
1557
{
1558
	const char *syspath;
1559
1560
	syspath = udev_device_get_syspath(device);
1561
	if (syspath == NULL)
1562
		return;
1563
1564
	DBG("%s", syspath);
1565
5693 by Marcel Holtmann
udev: Prioritize labeled interfaces over discovered ones
1566
	g_hash_table_foreach_remove(modem_list, check_remove,
1567
						(char *) syspath);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1568
}
1569
1570
static gint compare_device(gconstpointer a, gconstpointer b)
1571
{
1572
	const struct device_info *info1 = a;
1573
	const struct device_info *info2 = b;
1574
5696 by Marcel Holtmann
udev: Sort devices by interface number and not device node
1575
	return g_strcmp0(info1->number, info2->number);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1576
}
1577
7948 by Jonas Bonn
udevng: add serial device handling functions
1578
/*
1579
 * Here we try to find the "modem device".
1580
 *
1581
 * In this variant we identify the "modem device" as simply the device
1582
 * that has the OFONO_DRIVER property.  If the device node doesn't
1583
 * have this property itself, then we do a brute force search for it
1584
 * through the device hierarchy.
1585
 *
1586
 */
1587
static struct udev_device* get_serial_modem_device(struct udev_device *dev)
1588
{
1589
	const char* driver;
1590
1591
	while (dev) {
1592
		driver = udev_device_get_property_value(dev, "OFONO_DRIVER");
1593
		if (driver)
1594
			return dev;
1595
1596
		dev = udev_device_get_parent(dev);
1597
	}
1598
1599
	return NULL;
1600
}
1601
1602
/*
1603
 * Add 'legacy' device
1604
 *
1605
 * The term legacy is a bit misleading, but this adds devices according
1606
 * to the original ofono model.
1607
 *
1608
 * - We cannot assume that these are USB devices
1609
 * - The modem consists of only a single interface
1610
 * - The device must have an OFONO_DRIVER property from udev
1611
 */
1612
static void add_serial_device(struct udev_device *dev)
1613
{
1614
	const char *syspath, *devpath, *devname, *devnode;
1615
	struct modem_info *modem;
1616
	struct serial_device_info *info;
1617
	const char *subsystem;
1618
	struct udev_device* mdev;
1619
	const char* driver;
1620
1621
	mdev = get_serial_modem_device(dev);
1622
	if (!mdev) {
1623
		DBG("Device is missing required OFONO_DRIVER property");
1624
		return;
1625
	}
1626
1627
	driver = udev_device_get_property_value(mdev, "OFONO_DRIVER");
1628
1629
	syspath = udev_device_get_syspath(mdev);
1630
	devname = udev_device_get_devnode(mdev);
1631
	devpath = udev_device_get_devpath(mdev);
1632
1633
	devnode = udev_device_get_devnode(dev);
1634
8067 by Jonas Bonn
udev: fixes for detection of non-USB modems
1635
	if (!syspath || !devpath)
7948 by Jonas Bonn
udevng: add serial device handling functions
1636
		return;
1637
1638
	modem = g_hash_table_lookup(modem_list, syspath);
1639
	if (modem == NULL) {
1640
		modem = g_try_new0(struct modem_info, 1);
1641
		if (modem == NULL)
1642
			return;
1643
1644
		modem->type = MODEM_TYPE_SERIAL;
1645
		modem->syspath = g_strdup(syspath);
1646
		modem->devname = g_strdup(devname);
8067 by Jonas Bonn
udev: fixes for detection of non-USB modems
1647
		modem->driver = g_strdup(driver);
7948 by Jonas Bonn
udevng: add serial device handling functions
1648
1649
		g_hash_table_replace(modem_list, modem->syspath, modem);
1650
	}
1651
1652
	subsystem = udev_device_get_subsystem(dev);
1653
1654
	DBG("%s", syspath);
1655
	DBG("%s", devpath);
1656
	DBG("%s (%s)", devnode, driver);
1657
1658
	info = g_try_new0(struct serial_device_info, 1);
1659
	if (info == NULL)
1660
		return;
1661
1662
	info->devpath = g_strdup(devpath);
1663
	info->devnode = g_strdup(devnode);
1664
	info->subsystem = g_strdup(subsystem);
1665
	info->dev = udev_device_ref(dev);
1666
8067 by Jonas Bonn
udev: fixes for detection of non-USB modems
1667
	modem->serial = info;
7948 by Jonas Bonn
udevng: add serial device handling functions
1668
}
1669
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1670
static void add_device(const char *syspath, const char *devname,
6064 by Marcel Holtmann
udev: Keep vendor and product identifiers around
1671
			const char *driver, const char *vendor,
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
1672
			const char *model, struct udev_device *device,
1673
			enum modem_type type)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1674
{
7951 by Jonas Bonn
udevng: get properties from interface
1675
	struct udev_device *usb_interface;
7784 by Denis Kenzior
udevng: Fixup various minor style issues
1676
	const char *devpath, *devnode, *interface, *number;
1677
	const char *label, *sysattr, *subsystem;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1678
	struct modem_info *modem;
1679
	struct device_info *info;
7782 by Martin Chaplet
udevng: Improve modem properties detection
1680
	struct udev_device *parent;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1681
1682
	devpath = udev_device_get_syspath(device);
1683
	if (devpath == NULL)
1684
		return;
1685
1686
	modem = g_hash_table_lookup(modem_list, syspath);
1687
	if (modem == NULL) {
1688
		modem = g_try_new0(struct modem_info, 1);
1689
		if (modem == NULL)
1690
			return;
1691
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
1692
		modem->type = type;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1693
		modem->syspath = g_strdup(syspath);
1694
		modem->devname = g_strdup(devname);
1695
		modem->driver = g_strdup(driver);
6064 by Marcel Holtmann
udev: Keep vendor and product identifiers around
1696
		modem->vendor = g_strdup(vendor);
1697
		modem->model = g_strdup(model);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1698
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
1699
		modem->sysattr = get_sysattr(driver);
1700
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1701
		g_hash_table_replace(modem_list, modem->syspath, modem);
1702
	}
1703
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
1704
	if (modem->type == MODEM_TYPE_USB) {
1705
		devnode = udev_device_get_devnode(device);
1706
		if (devnode == NULL) {
1707
			devnode = udev_device_get_property_value(device,
1708
							"INTERFACE");
1709
			if (devnode == NULL)
1710
				return;
1711
		}
1712
1713
		usb_interface = udev_device_get_parent_with_subsystem_devtype(
1714
							device, "usb",
1715
							"usb_interface");
1716
		if (usb_interface == NULL)
1717
			return;
1718
1719
		interface = udev_device_get_property_value(usb_interface,
1720
							"INTERFACE");
1721
		number = udev_device_get_property_value(device,
1722
						"ID_USB_INTERFACE_NUM");
1723
1724
		label = udev_device_get_property_value(device, "OFONO_LABEL");
1725
		if (!label)
1726
			label = udev_device_get_property_value(usb_interface,
1727
							"OFONO_LABEL");
1728
	} else {
1729
		devnode = NULL;
1730
		interface = udev_device_get_property_value(device,
1731
							"INTERFACE");
1732
		number = NULL;
1733
		label = NULL;
1734
	}
5725 by Marcel Holtmann
udev: Add debug output for special system attribute
1735
7782 by Martin Chaplet
udevng: Improve modem properties detection
1736
	/* If environment variable is not set, get value from attributes (or parent's ones) */
7784 by Denis Kenzior
udevng: Fixup various minor style issues
1737
	if (number == NULL) {
1738
		number = udev_device_get_sysattr_value(device,
1739
							"bInterfaceNumber");
1740
1741
		if (number == NULL) {
7782 by Martin Chaplet
udevng: Improve modem properties detection
1742
			parent = udev_device_get_parent(device);
7784 by Denis Kenzior
udevng: Fixup various minor style issues
1743
			number = udev_device_get_sysattr_value(parent,
1744
							"bInterfaceNumber");
7782 by Martin Chaplet
udevng: Improve modem properties detection
1745
		}
1746
	}
1747
1748
	subsystem = udev_device_get_subsystem(device);
5725 by Marcel Holtmann
udev: Add debug output for special system attribute
1749
1750
	if (modem->sysattr != NULL)
1751
		sysattr = udev_device_get_sysattr_value(device, modem->sysattr);
1752
	else
1753
		sysattr = NULL;
1754
6289 by Marcel Holtmann
udev: Fix matching to prefer entries with VID and PID
1755
	DBG("%s", syspath);
5725 by Marcel Holtmann
udev: Add debug output for special system attribute
1756
	DBG("%s", devpath);
1757
	DBG("%s (%s) %s [%s] ==> %s %s", devnode, driver,
1758
					interface, number, label, sysattr);
1759
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1760
	info = g_try_new0(struct device_info, 1);
1761
	if (info == NULL)
1762
		return;
1763
1764
	info->devpath = g_strdup(devpath);
1765
	info->devnode = g_strdup(devnode);
1766
	info->interface = g_strdup(interface);
1767
	info->number = g_strdup(number);
1768
	info->label = g_strdup(label);
5725 by Marcel Holtmann
udev: Add debug output for special system attribute
1769
	info->sysattr = g_strdup(sysattr);
7782 by Martin Chaplet
udevng: Improve modem properties detection
1770
	info->subsystem = g_strdup(subsystem);
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
1771
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1772
	modem->devices = g_slist_insert_sorted(modem->devices, info,
1773
							compare_device);
1774
}
1775
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1776
static struct {
1777
	const char *driver;
1778
	const char *drv;
1779
	const char *vid;
1780
	const char *pid;
1781
} vendor_list[] = {
5752 by Marcel Holtmann
udev: Add support for automatic ISI USB modem detection
1782
	{ "isiusb",	"cdc_phonet"			},
5755 by Marcel Holtmann
udev: Add automatic detection for Linktop devices
1783
	{ "linktop",	"cdc_acm",	"230d"		},
6186 by Marcel Holtmann
udev: Add detection support for Icera based devices
1784
	{ "icera",	"cdc_acm",	"19d2"		},
1785
	{ "icera",	"cdc_ether",	"19d2"		},
6275 by Marcel Holtmann
udev: Add detection for Samsung GT-Y3300 modems
1786
	{ "icera",	"cdc_acm",	"04e8", "6872"	},
1787
	{ "icera",	"cdc_ether",	"04e8", "6872"	},
6276 by Marcel Holtmann
udev: Add detection for Nokia 21M-01 modems
1788
	{ "icera",	"cdc_acm",	"0421", "0633"	},
1789
	{ "icera",	"cdc_ether",	"0421", "0633"	},
5748 by Marcel Holtmann
udev: Add automatic detection for Ericsson MBM based devices
1790
	{ "mbm",	"cdc_acm",	"0bdb"		},
6610 by Denis Kenzior
udevng: Fix MBM detection
1791
	{ "mbm",	"cdc_ether",	"0bdb"		},
7361 by Johannes 'josch' Schauer
udevng: add support for Ericsson N5321 gw
1792
	{ "mbm",	"cdc_ncm",	"0bdb"		},
5748 by Marcel Holtmann
udev: Add automatic detection for Ericsson MBM based devices
1793
	{ "mbm",	"cdc_acm",	"0fce"		},
1794
	{ "mbm",	"cdc_ether",	"0fce"		},
7361 by Johannes 'josch' Schauer
udevng: add support for Ericsson N5321 gw
1795
	{ "mbm",	"cdc_ncm",	"0fce"		},
5748 by Marcel Holtmann
udev: Add automatic detection for Ericsson MBM based devices
1796
	{ "mbm",	"cdc_acm",	"413c"		},
1797
	{ "mbm",	"cdc_ether",	"413c"		},
7361 by Johannes 'josch' Schauer
udevng: add support for Ericsson N5321 gw
1798
	{ "mbm",	"cdc_ncm",	"413c"		},
8086 by Denis Kenzior
udevng: Add basic detection for MBIM
1799
	{ "mbim",	"cdc_mbim"			},
5748 by Marcel Holtmann
udev: Add automatic detection for Ericsson MBM based devices
1800
	{ "mbm",	"cdc_acm",	"03f0"		},
1801
	{ "mbm",	"cdc_ether",	"03f0"		},
7361 by Johannes 'josch' Schauer
udevng: add support for Ericsson N5321 gw
1802
	{ "mbm",	"cdc_ncm",	"03f0"		},
5748 by Marcel Holtmann
udev: Add automatic detection for Ericsson MBM based devices
1803
	{ "mbm",	"cdc_acm",	"0930"		},
1804
	{ "mbm",	"cdc_ether",	"0930"		},
7361 by Johannes 'josch' Schauer
udevng: add support for Ericsson N5321 gw
1805
	{ "mbm",	"cdc_ncm",	"0930"		},
5698 by Marcel Holtmann
udev: Use fully automatic detection for Option HSO devices
1806
	{ "hso",	"hso"				},
6287 by Marcel Holtmann
udev: Add support for detecting Gobi QMI devices
1807
	{ "gobi",	"qmi_wwan"			},
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1808
	{ "gobi",	"qcserial"			},
7783 by Martin Chaplet
udevng: Add support for Sierra MC73xx QMI modems
1809
	{ "sierra",	"qmi_wwan",	"1199"		},
1810
	{ "sierra",	"qcserial",	"1199"		},
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1811
	{ "sierra",	"sierra"			},
6137 by Marcel Holtmann
udev: Add support for detecting Sierra network interfaces
1812
	{ "sierra",	"sierra_net"			},
6131 by Marcel Holtmann
udev: Detect old Option cards without high-speed interface
1813
	{ "option",	"option",	"0af0"		},
6013 by Guillaume Zajac
udev: Simplify vendor_list for Huawei constructor
1814
	{ "huawei",	"option",	"201e"		},
6738 by Marcel Holtmann
udev: Let Huawei detection also check for cdc_wdm drivers
1815
	{ "huawei",	"cdc_wdm",	"12d1"		},
5697 by Marcel Holtmann
udev: Add support for automatic tagging of network interfaces
1816
	{ "huawei",	"cdc_ether",	"12d1"		},
6288 by Marcel Holtmann
udev: Add support for detecting Huawei QMI devices
1817
	{ "huawei",	"qmi_wwan",	"12d1"		},
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1818
	{ "huawei",	"option",	"12d1"		},
5715 by Marcel Holtmann
udev: Use automatic detection for all SpeedUp modems
1819
	{ "speedupcdma","option",	"1c9e", "9e00"	},
5703 by Marcel Holtmann
udev: Use semi-automatic detection for SpeedUp devices
1820
	{ "speedup",	"option",	"1c9e"		},
5715 by Marcel Holtmann
udev: Use automatic detection for all SpeedUp modems
1821
	{ "speedup",	"option",	"2020"		},
5718 by Marcel Holtmann
udev: Add automatic detection for Alcatel X220L
1822
	{ "alcatel",	"option",	"1bbb", "0017"	},
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1823
	{ "novatel",	"option",	"1410"		},
1824
	{ "zte",	"option",	"19d2"		},
8372 by Denis Kenzior
udevng: Fix SIM900 detection
1825
	{ "simcom",	"option",	"05c6", "9000"	},
8640 by Stefan Herbrechtsmeier
udevng: add SIMCom SIM7600 modem support
1826
	{ "sim7x00",	"option",	"1e0e", "9001"	},
1827
	{ "sim7x00",	"qmi_wwan",	"1e0e",	"9001"	},
5889 by Gustavo F. Padovan
udev: add a driver name for telit
1828
	{ "telit",	"usbserial",	"1bc7"		},
5978 by Christopher Vogl
udevng: add another driver name for telit
1829
	{ "telit",	"option",	"1bc7"		},
7913 by Piotr Haber
udevng: unify telit and xe910
1830
	{ "telit",	"cdc_acm",	"1bc7", "0021"	},
7945 by Lukasz Nowak
udevng: add Telit LE910 V1 support
1831
	{ "telitqmi",	"qmi_wwan",	"1bc7", "1201"	},
1832
	{ "telitqmi",	"option",	"1bc7", "1201"	},
8844 by Pavel Machek
droid 4: Add probing.
1833
	{ "droid",	"qmi_wwan",	"22b8", "2a70"	},
1834
	{ "droid",	"option",	"22b8", "2a70"	},
5724 by Marcel Holtmann
udev: udev: Add automatic detection for Nokia data cards
1835
	{ "nokia",	"option",	"0421", "060e"	},
1836
	{ "nokia",	"option",	"0421", "0623"	},
5740 by Marcel Holtmann
udev: Fix minor whitespace mistakes
1837
	{ "samsung",	"option",	"04e8", "6889"	},
1838
	{ "samsung",	"kalmia"			},
7227 by Philip Paeps
udevng: add detection logic for Quectel modems
1839
	{ "quectel",	"option",	"05c6", "9090"	},
7981 by Jonas Bonn
Add support for Quectel EC21/25 modems
1840
	{ "quectelqmi",	"qmi_wwan",	"2c7c", "0121"	},
1841
	{ "quectelqmi",	"qcserial",	"2c7c", "0121"	},
1842
	{ "quectelqmi",	"qmi_wwan",	"2c7c", "0125"	},
1843
	{ "quectelqmi",	"qcserial",	"2c7c", "0125"	},
8820 by Sean Nyekjaer
udevng: Add support for Quectel BG96 modem
1844
	{ "quectelqmi",	"qmi_wwan",	"2c7c", "0296"	},
1845
	{ "quectelqmi",	"qcserial",	"2c7c", "0296"	},
8578 by Jonas Bonn
udevng: detect ublox TOBY L4
1846
	{ "ublox",	"cdc_acm",	"1546", "1010"	},
1847
	{ "ublox",	"cdc_ncm",	"1546", "1010"	},
7235 by Philip Paeps
udevng: add detection logic for u-blox modems
1848
	{ "ublox",	"cdc_acm",	"1546", "1102"	},
8718 by Jonas Bonn
udevng: detect LARA R2 series
1849
	{ "ublox",	"cdc_acm",	"1546", "110a"	},
1850
	{ "ublox",	"cdc_ncm",	"1546", "110a"	},
7654 by Dongsu Park
plugins/udevng: support the U-Blox TOBY-L2 series
1851
	{ "ublox",	"rndis_host",	"1546", "1146"	},
1852
	{ "ublox",	"cdc_acm",	"1546", "1146"	},
7893 by Vincent Cesson
udevng: Add Gemalto P-family detection
1853
	{ "gemalto",	"option",	"1e2d",	"0053"	},
7895 by Vincent Cesson
udevng: complete gemalto setup
1854
	{ "gemalto",	"cdc_wdm",	"1e2d",	"0053"	},
1855
	{ "gemalto",	"qmi_wwan",	"1e2d",	"0053"	},
8322 by Gabriel Lucas
gemalto: add detection of ALS3 modem
1856
	{ "gemalto",	"cdc_acm",	"1e2d",	"0061"	},
1857
	{ "gemalto",	"cdc_ether",	"1e2d",	"0061"	},
8815 by Sergey Matyukevich
plugins: udevng: detect Centirion ELS81x modem
1858
	{ "gemalto",	"cdc_acm",	"1e2d",	"005b"	},
1859
	{ "gemalto",	"cdc_ether",	"1e2d",	"005b"	},
7913 by Piotr Haber
udevng: unify telit and xe910
1860
	{ "telit",	"cdc_ncm",	"1bc7", "0036"	},
1861
	{ "telit",	"cdc_acm",	"1bc7", "0036"	},
8359 by Varun Gargi
udevng: remove vendor ID to make it generic for intel modem
1862
	{ "xmm7xxx",	"cdc_acm",	"8087"		},
1863
	{ "xmm7xxx",	"cdc_ncm",	"8087"		},
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1864
	{ }
1865
};
1866
5751 by Marcel Holtmann
udev: Prepare for supporting different bus types
1867
static void check_usb_device(struct udev_device *device)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1868
{
1869
	struct udev_device *usb_device;
6064 by Marcel Holtmann
udev: Keep vendor and product identifiers around
1870
	const char *syspath, *devname, *driver;
1871
	const char *vendor = NULL, *model = NULL;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1872
1873
	usb_device = udev_device_get_parent_with_subsystem_devtype(device,
1874
							"usb", "usb_device");
1875
	if (usb_device == NULL)
1876
		return;
1877
1878
	syspath = udev_device_get_syspath(usb_device);
1879
	if (syspath == NULL)
1880
		return;
1881
1882
	devname = udev_device_get_devnode(usb_device);
1883
	if (devname == NULL)
1884
		return;
1885
7935 by Jonas Bonn
udevng: simplify logic in check_usb_device
1886
	vendor = udev_device_get_property_value(usb_device, "ID_VENDOR_ID");
1887
	model = udev_device_get_property_value(usb_device, "ID_MODEL_ID");
1888
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1889
	driver = udev_device_get_property_value(usb_device, "OFONO_DRIVER");
7951 by Jonas Bonn
udevng: get properties from interface
1890
	if (!driver) {
1891
		struct udev_device *usb_interface =
1892
			udev_device_get_parent_with_subsystem_devtype(
1893
				device, "usb", "usb_interface");
1894
1895
		if (usb_interface)
1896
			driver = udev_device_get_property_value(
1897
					usb_interface, "OFONO_DRIVER");
1898
	}
1899
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1900
	if (driver == NULL) {
7935 by Jonas Bonn
udevng: simplify logic in check_usb_device
1901
		const char *drv;
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1902
		unsigned int i;
1903
1904
		drv = udev_device_get_property_value(device, "ID_USB_DRIVER");
6286 by Marcel Holtmann
udev: Add matching support for CDC WDM device nodes
1905
		if (drv == NULL) {
1906
			drv = udev_device_get_driver(device);
1907
			if (drv == NULL) {
1908
				struct udev_device *parent;
1909
1910
				parent = udev_device_get_parent(device);
1911
				if (parent == NULL)
1912
					return;
1913
1914
				drv = udev_device_get_driver(parent);
1915
				if (drv == NULL)
1916
					return;
1917
			}
1918
		}
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1919
1920
7935 by Jonas Bonn
udevng: simplify logic in check_usb_device
1921
		DBG("%s [%s:%s]", drv, vendor, model);
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1922
8391 by Anirudh Gargi
udev:fix seg fault in case of vid and pid is NULL
1923
		if (vendor == NULL || model == NULL)
1924
			return;
1925
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1926
		for (i = 0; vendor_list[i].driver; i++) {
1927
			if (g_str_equal(vendor_list[i].drv, drv) == FALSE)
1928
				continue;
1929
7935 by Jonas Bonn
udevng: simplify logic in check_usb_device
1930
			if (vendor_list[i].vid) {
1931
				if (!g_str_equal(vendor_list[i].vid, vendor))
1932
					continue;
1933
			}
1934
1935
			if (vendor_list[i].pid) {
1936
				if (!g_str_equal(vendor_list[i].pid, model))
1937
					continue;
1938
			}
1939
1940
			driver = vendor_list[i].driver;
5695 by Marcel Holtmann
udev: Add support for default driver assignments
1941
		}
1942
1943
		if (driver == NULL)
1944
			return;
1945
	}
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
1946
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
1947
	add_device(syspath, devname, driver, vendor, model, device,
1948
			MODEM_TYPE_USB);
1949
}
1950
1951
static const struct {
1952
	const char *driver;
1953
	const char *drv;
1954
	const char *vid;
1955
	const char *pid;
1956
} pci_driver_list[] = {
1957
	{ "xmm7xxx",	"imc_ipc",	"0x8086",	"0x7560"},
1958
	{ }
1959
};
1960
1961
static void check_pci_device(struct udev_device *device)
1962
{
1963
	const char *syspath, *devname, *driver;
1964
	const char *vendor = NULL, *model = NULL, *drv = NULL;
1965
	unsigned int i;
1966
1967
	syspath = udev_device_get_syspath(device);
1968
1969
	if (syspath == NULL)
1970
		return;
1971
1972
	devname = udev_device_get_devnode(device);
1973
	vendor = udev_device_get_sysattr_value(device, "vendor");
1974
	model = udev_device_get_sysattr_value(device, "device");
1975
	driver = udev_device_get_property_value(device, "OFONO_DRIVER");
1976
	drv = udev_device_get_property_value(device, "DRIVER");
1977
	DBG("%s [%s:%s]", drv, vendor, model);
1978
1979
	if (vendor == NULL || model == NULL || drv == NULL)
1980
		return;
1981
1982
	for (i = 0; pci_driver_list[i].driver; i++) {
1983
		if (g_str_equal(pci_driver_list[i].drv, drv) == FALSE)
1984
			continue;
1985
1986
		if (pci_driver_list[i].vid) {
1987
			if (!g_str_equal(pci_driver_list[i].vid, vendor))
1988
				continue;
1989
		}
1990
1991
		if (pci_driver_list[i].pid) {
1992
			if (!g_str_equal(pci_driver_list[i].pid, model))
1993
				continue;
1994
		}
1995
1996
		driver = pci_driver_list[i].driver;
1997
	}
1998
1999
	if (driver == NULL)
2000
		return;
2001
2002
	add_device(syspath, devname, driver, vendor, model, device,
2003
			MODEM_TYPE_PCIE);
2004
}
5751 by Marcel Holtmann
udev: Prepare for supporting different bus types
2005
static void check_device(struct udev_device *device)
2006
{
2007
	const char *bus;
2008
2009
	bus = udev_device_get_property_value(device, "ID_BUS");
6286 by Marcel Holtmann
udev: Add matching support for CDC WDM device nodes
2010
	if (bus == NULL) {
2011
		bus = udev_device_get_subsystem(device);
2012
		if (bus == NULL)
2013
			return;
2014
	}
5751 by Marcel Holtmann
udev: Prepare for supporting different bus types
2015
7784 by Denis Kenzior
udevng: Fixup various minor style issues
2016
	if ((g_str_equal(bus, "usb") == TRUE) ||
2017
			(g_str_equal(bus, "usbmisc") == TRUE))
5751 by Marcel Holtmann
udev: Prepare for supporting different bus types
2018
		check_usb_device(device);
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
2019
	else if (g_str_equal(bus, "pci") == TRUE)
2020
		check_pci_device(device);
7950 by Jonas Bonn
udevng: hook up legacy devices
2021
	else
2022
		add_serial_device(device);
2023
5751 by Marcel Holtmann
udev: Prepare for supporting different bus types
2024
}
2025
5750 by Marcel Holtmann
udev: Remove modem object when setup procedure fails
2026
static gboolean create_modem(gpointer key, gpointer value, gpointer user_data)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2027
{
2028
	struct modem_info *modem = value;
2029
	const char *syspath = key;
2030
	unsigned int i;
2031
5750 by Marcel Holtmann
udev: Remove modem object when setup procedure fails
2032
	if (modem->modem != NULL)
2033
		return FALSE;
2034
2035
	DBG("%s", syspath);
2036
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2037
	if (modem->devices == NULL)
5750 by Marcel Holtmann
udev: Remove modem object when setup procedure fails
2038
		return TRUE;
2039
5695 by Marcel Holtmann
udev: Add support for default driver assignments
2040
	DBG("driver=%s", modem->driver);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2041
2042
	modem->modem = ofono_modem_create(NULL, modem->driver);
2043
	if (modem->modem == NULL)
5750 by Marcel Holtmann
udev: Remove modem object when setup procedure fails
2044
		return TRUE;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2045
2046
	for (i = 0; driver_list[i].name; i++) {
2047
		if (g_str_equal(driver_list[i].name, modem->driver) == FALSE)
2048
			continue;
2049
2050
		if (driver_list[i].setup(modem) == TRUE) {
8301 by Christophe Ronco
udevng: Add modem string SystemPath
2051
			ofono_modem_set_string(modem->modem, "SystemPath",
2052
								syspath);
8358 by James Prestwood
plugins: fixed crash in udevng
2053
			if (ofono_modem_register(modem->modem) < 0) {
2054
				DBG("could not register modem '%s'", modem->driver);
2055
				return TRUE;
2056
			}
2057
5750 by Marcel Holtmann
udev: Remove modem object when setup procedure fails
2058
			return FALSE;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2059
		}
2060
	}
2061
5750 by Marcel Holtmann
udev: Remove modem object when setup procedure fails
2062
	return TRUE;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2063
}
2064
2065
static void enumerate_devices(struct udev *context)
2066
{
2067
	struct udev_enumerate *enumerate;
2068
	struct udev_list_entry *entry;
2069
2070
	DBG("");
2071
2072
	enumerate = udev_enumerate_new(context);
2073
	if (enumerate == NULL)
2074
		return;
2075
2076
	udev_enumerate_add_match_subsystem(enumerate, "tty");
6286 by Marcel Holtmann
udev: Add matching support for CDC WDM device nodes
2077
	udev_enumerate_add_match_subsystem(enumerate, "usb");
7779 by Martin Chaplet
udevng: Add usbmisc scan for QMI devices
2078
	udev_enumerate_add_match_subsystem(enumerate, "usbmisc");
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2079
	udev_enumerate_add_match_subsystem(enumerate, "net");
7949 by Jonas Bonn
udevng: match on the hsi subsystem for legacy devices
2080
	udev_enumerate_add_match_subsystem(enumerate, "hsi");
8766 by Antara Borwankar
udev: Adding PCIe as a subsystem in udev
2081
	udev_enumerate_add_match_subsystem(enumerate, "pci");
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2082
2083
	udev_enumerate_scan_devices(enumerate);
2084
2085
	entry = udev_enumerate_get_list_entry(enumerate);
2086
	while (entry) {
2087
		const char *syspath = udev_list_entry_get_name(entry);
2088
		struct udev_device *device;
2089
2090
		device = udev_device_new_from_syspath(context, syspath);
2091
		if (device != NULL) {
2092
			check_device(device);
2093
			udev_device_unref(device);
2094
		}
2095
2096
		entry = udev_list_entry_get_next(entry);
2097
	}
2098
2099
	udev_enumerate_unref(enumerate);
2100
5750 by Marcel Holtmann
udev: Remove modem object when setup procedure fails
2101
	g_hash_table_foreach_remove(modem_list, create_modem, NULL);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2102
}
2103
5692 by Marcel Holtmann
udev: Add warning in case channel gets disconnected
2104
static struct udev *udev_ctx;
2105
static struct udev_monitor *udev_mon;
2106
static guint udev_watch = 0;
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2107
static guint udev_delay = 0;
2108
2109
static gboolean check_modem_list(gpointer user_data)
2110
{
2111
	udev_delay = 0;
2112
2113
	DBG("");
2114
5750 by Marcel Holtmann
udev: Remove modem object when setup procedure fails
2115
	g_hash_table_foreach_remove(modem_list, create_modem, NULL);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2116
2117
	return FALSE;
2118
}
2119
5692 by Marcel Holtmann
udev: Add warning in case channel gets disconnected
2120
static gboolean udev_event(GIOChannel *channel, GIOCondition cond,
2121
							gpointer user_data)
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2122
{
2123
	struct udev_device *device;
2124
	const char *action;
2125
5692 by Marcel Holtmann
udev: Add warning in case channel gets disconnected
2126
	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
2127
		ofono_warn("Error with udev monitor channel");
2128
		udev_watch = 0;
2129
		return FALSE;
2130
	}
2131
2132
	device = udev_monitor_receive_device(udev_mon);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2133
	if (device == NULL)
2134
		return TRUE;
2135
2136
	action = udev_device_get_action(device);
2137
	if (action == NULL)
2138
		return TRUE;
2139
2140
	if (g_str_equal(action, "add") == TRUE) {
2141
		if (udev_delay > 0)
2142
			g_source_remove(udev_delay);
2143
2144
		check_device(device);
2145
2146
		udev_delay = g_timeout_add_seconds(1, check_modem_list, NULL);
2147
	} else if (g_str_equal(action, "remove") == TRUE)
2148
		remove_device(device);
2149
2150
	udev_device_unref(device);
2151
2152
	return TRUE;
2153
}
2154
2155
static void udev_start(void)
2156
{
2157
	GIOChannel *channel;
2158
	int fd;
2159
2160
	DBG("");
2161
2162
	if (udev_monitor_enable_receiving(udev_mon) < 0) {
2163
		ofono_error("Failed to enable udev monitor");
2164
		return;
2165
	}
2166
2167
	enumerate_devices(udev_ctx);
2168
2169
	fd = udev_monitor_get_fd(udev_mon);
2170
2171
	channel = g_io_channel_unix_new(fd);
2172
	if (channel == NULL)
2173
		return;
2174
5692 by Marcel Holtmann
udev: Add warning in case channel gets disconnected
2175
	udev_watch = g_io_add_watch(channel,
2176
				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
2177
							udev_event, NULL);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2178
2179
	g_io_channel_unref(channel);
2180
}
2181
2182
static int detect_init(void)
2183
{
2184
	udev_ctx = udev_new();
2185
	if (udev_ctx == NULL) {
2186
		ofono_error("Failed to create udev context");
2187
		return -EIO;
2188
	}
2189
2190
	udev_mon = udev_monitor_new_from_netlink(udev_ctx, "udev");
2191
	if (udev_mon == NULL) {
2192
		ofono_error("Failed to create udev monitor");
2193
		udev_unref(udev_ctx);
2194
		udev_ctx = NULL;
2195
		return -EIO;
2196
	}
2197
2198
	modem_list = g_hash_table_new_full(g_str_hash, g_str_equal,
2199
						NULL, destroy_modem);
2200
2201
	udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "tty", NULL);
6286 by Marcel Holtmann
udev: Add matching support for CDC WDM device nodes
2202
	udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "usb", NULL);
7784 by Denis Kenzior
udevng: Fixup various minor style issues
2203
	udev_monitor_filter_add_match_subsystem_devtype(udev_mon,
2204
							"usbmisc", NULL);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2205
	udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "net", NULL);
7949 by Jonas Bonn
udevng: match on the hsi subsystem for legacy devices
2206
	udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "hsi", NULL);
5690 by Marcel Holtmann
udev: Add support for cleaner modem detection
2207
2208
	udev_monitor_filter_update(udev_mon);
2209
2210
	udev_start();
2211
2212
	return 0;
2213
}
2214
2215
static void detect_exit(void)
2216
{
2217
	if (udev_delay > 0)
2218
		g_source_remove(udev_delay);
2219
2220
	if (udev_watch > 0)
2221
		g_source_remove(udev_watch);
2222
2223
	if (udev_ctx == NULL)
2224
		return;
2225
2226
	udev_monitor_filter_remove(udev_mon);
2227
2228
	g_hash_table_destroy(modem_list);
2229
2230
	udev_monitor_unref(udev_mon);
2231
	udev_unref(udev_ctx);
2232
}
2233
2234
OFONO_PLUGIN_DEFINE(udevng, "udev hardware detection", VERSION,
2235
		OFONO_PLUGIN_PRIORITY_DEFAULT, detect_init, detect_exit)