1 /* This program is free software; you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License as published by
3  * the Free Software Foundation; either version 2 of the License, or
4  * (at your option) any later version.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  *
15  * Copyright (C) 2009 Red Hat, Inc.
16  * Copyright (c) 2010 Michal Cihar <michal@cihar.com>
17  */
18 
19 #include <glib.h>
20 #define G_UDEV_API_IS_SUBJECT_TO_CHANGE
21 #include <gudev/gudev.h>
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 
28 #include <gammu.h>		/* For PRINTF_STYLE and locales */
29 #include "../helper/locales.h"	/* For gettext */
30 
31 #include "config.h"
32 
33 #include "udev.h"
34 #include "main.h"
35 
36 PRINTF_STYLE(2, 3)
println(guint indent,const char * fmt,...)37 static void println(guint indent, const char *fmt, ...)
38 {
39 	va_list args;
40 	char real_fmt[1000] = "; ";
41 	guint i;
42 
43 	g_return_if_fail(fmt != NULL);
44 	g_return_if_fail(indent < sizeof(real_fmt) - 2 - strlen(fmt));
45 
46 	for (i = 0; i < indent; i++)
47 		real_fmt[i + 2] = ' ';
48 	strcpy(&real_fmt[i + 2], fmt);
49 	real_fmt[i + 2 + strlen(fmt)] = '\n';
50 	real_fmt[i + 2 + strlen(fmt) + 1] = '\0';
51 
52 	va_start(args, fmt);
53 	if (debug)
54 		vprintf(real_fmt, args);
55 	va_end(args);
56 }
57 
dump_device_and_parent(GUdevDevice * device,guint indent)58 static void dump_device_and_parent(GUdevDevice * device, guint indent)
59 {
60 	const gchar *const *list;
61 	const gchar *const *iter;
62 	GUdevDevice *parent;
63 	char propstr[500];
64 	guint32 namelen = 0, i;
65 
66 	println(indent, "------------------------------------------------------");
67 	println(indent, "%-20s %s", _("Name:"), g_udev_device_get_name(device));
68 	println(indent, "%-20s %s", _("Type:"), g_udev_device_get_devtype(device));
69 	println(indent, "%-20s %s", _("Subsystem:"), g_udev_device_get_subsystem(device));
70 	println(indent, "%-20s %s", _("Number:"), g_udev_device_get_number(device));
71 	println(indent, "%-20s %s", _("Path:"), g_udev_device_get_sysfs_path(device));
72 	println(indent, "%-20s %s", _("Driver:"), g_udev_device_get_driver(device));
73 	println(indent, "%-20s %lld", _("Sequential Number:"), (long long int)g_udev_device_get_seqnum(device));
74 	println(indent, "%-20s %s", _("Device File:"), g_udev_device_get_device_file(device));
75 
76 	println(indent, " ");
77 	println(indent, _("Properties:"));
78 
79 	/* Get longest property name length for alignment */
80 	list = g_udev_device_get_property_keys(device);
81 	for (iter = list; iter && *iter; iter++) {
82 		if (strlen(*iter) > namelen)
83 			namelen = strlen(*iter);
84 	}
85 	namelen++;
86 
87 	for (iter = list; iter && *iter; iter++) {
88 		strcpy(propstr, *iter);
89 		strcat(propstr, ":");
90 		for (i = 0; i < namelen - strlen(*iter); i++)
91 			strcat(propstr, " ");
92 		strcat(propstr, g_udev_device_get_property(device, *iter));
93 		println(indent + 2, "%s", propstr);
94 	}
95 
96 	println(indent, " ");
97 
98 	parent = g_udev_device_get_parent(device);
99 	if (parent) {
100 		dump_device_and_parent(parent, indent + 4);
101 		g_object_unref(parent);
102 	}
103 }
104 
device_is_acm(GUdevDevice * device)105 static gboolean device_is_acm(GUdevDevice * device)
106 {
107 	GUdevDevice *parent;
108 	parent = g_udev_device_get_parent(device);
109 	if (parent) {
110 		/* Serial driver */
111 		if (g_strcmp0(g_udev_device_get_driver(parent), "cdc_acm") == 0) {
112 			g_object_unref(parent);
113 			return TRUE;
114 		}
115 		g_object_unref(parent);
116 	}
117 	return FALSE;
118 }
119 
device_is_usb_serial(GUdevDevice * device)120 static gboolean device_is_usb_serial(GUdevDevice * device)
121 {
122 	GUdevDevice *parent;
123 	parent = g_udev_device_get_parent(device);
124 	if (parent) {
125 		/* Serial driver */
126 		if (g_strcmp0(g_udev_device_get_subsystem(parent), "usb-serial") == 0) {
127 			g_object_unref(parent);
128 			return TRUE;
129 		}
130 		g_object_unref(parent);
131 	}
132 	return FALSE;
133 }
134 
device_is_serial(GUdevDevice * device)135 static gboolean device_is_serial(GUdevDevice * device)
136 {
137 	GUdevDevice *parent;
138 	parent = g_udev_device_get_parent(device);
139 	if (parent) {
140 		/* Serial driver */
141 		if (g_strcmp0(g_udev_device_get_name(parent), "serial8250") == 0) {
142 			g_object_unref(parent);
143 			return TRUE;
144 		}
145 		g_object_unref(parent);
146 	}
147 	return FALSE;
148 }
149 
device_is_valid(GUdevDevice * device)150 static gboolean device_is_valid(GUdevDevice * device)
151 {
152 	if (device_is_serial(device)) {
153 		return TRUE;
154 	}
155 	if (device_is_acm(device)) {
156 		return TRUE;
157 	}
158 	if (device_is_usb_serial(device)) {
159 		return TRUE;
160 	}
161 	return FALSE;
162 }
163 
device_dump_config(GUdevDevice * device)164 static void device_dump_config(GUdevDevice * device)
165 {
166 	gchar *device_name, *name;
167 	device_name = g_strdup_printf("/dev/%s", g_udev_device_get_name(device));
168 
169 	if (device_is_serial(device)) {
170 		name = g_strdup_printf(_("Phone on serial port %s"), g_udev_device_get_number(device));
171 	} else if (device_is_usb_serial(device)) {
172 		name = g_strdup_printf(_("Phone on USB serial port %s %s"), g_udev_device_get_property(device, "ID_VENDOR"), g_udev_device_get_property(device, "ID_MODEL"));
173 	} else if (device_is_acm(device)) {
174 		name = g_strdup_printf("%s %s", g_udev_device_get_property(device, "ID_VENDOR"), g_udev_device_get_property(device, "ID_MODEL"));
175 	} else {
176 		name = NULL;
177 	}
178 	print_config(device_name, name, "at");
179 	g_free(device_name);
180 	g_free(name);
181 }
182 
udev_detect(void)183 void udev_detect(void)
184 {
185 	GUdevClient *client;
186 	const char *subsys[2] = { "tty", NULL };
187 	GList *list, *iter;
188 
189 	client = g_udev_client_new(subsys);
190 
191 	list = g_udev_client_query_by_subsystem(client, subsys[0]);
192 	for (iter = list; iter; iter = g_list_next(iter)) {
193 		dump_device_and_parent(G_UDEV_DEVICE(iter->data), 0);
194 		if (device_is_valid(G_UDEV_DEVICE(iter->data))) {
195 			device_dump_config(G_UDEV_DEVICE(iter->data));
196 		}
197 		g_object_unref(G_UDEV_DEVICE(iter->data));
198 	}
199 }
200 
201 /* How should editor hadle tabs in this file? Add editor commands here.
202  * vim: noexpandtab sw=8 ts=8 sts=8:
203  */
204