1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2009-2011 Richard Hughes <richard@hughsie.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "config.h"
21
22 #include <glib-object.h>
23
24 #include "gnome-pnp-ids.h"
25
26 static void gnome_pnp_ids_finalize (GObject *object);
27
28 #define GNOME_PNP_IDS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNOME_TYPE_PNP_IDSS, GnomePnpIdsPrivate))
29
30 struct _GnomePnpIdsPrivate
31 {
32 gchar *table_data;
33 GHashTable *pnp_table;
34 };
35
36 static gpointer gnome_pnp_ids_object = NULL;
37
38 G_DEFINE_TYPE (GnomePnpIds, gnome_pnp_ids, G_TYPE_OBJECT)
39
40 typedef struct Vendor Vendor;
41 struct Vendor
42 {
43 const char vendor_id[4];
44 const char vendor_name[28];
45 };
46
47 /* This list of vendor codes derived from lshw
48 *
49 * http://ezix.org/project/wiki/HardwareLiSter
50 *
51 * Note: we now prefer to use data coming from hwdata (and shipped with
52 * gnome-desktop). See
53 * http://git.fedorahosted.org/git/?p=hwdata.git;a=blob_plain;f=pnp.ids;hb=HEAD
54 * All contributions to the list of vendors should go there.
55 */
56 static const struct Vendor vendors[] =
57 {
58 { "AIC", "AG Neovo" },
59 { "ACR", "Acer" },
60 { "DEL", "DELL" },
61 { "SAM", "SAMSUNG" },
62 { "SNY", "SONY" },
63 { "SEC", "Epson" },
64 { "WAC", "Wacom" },
65 { "NEC", "NEC" },
66 { "CMO", "CMO" }, /* Chi Mei */
67 { "BNQ", "BenQ" },
68
69 { "ABP", "Advansys" },
70 { "ACC", "Accton" },
71 { "ACE", "Accton" },
72 { "ADP", "Adaptec" },
73 { "ADV", "AMD" },
74 { "AIR", "AIR" },
75 { "AMI", "AMI" },
76 { "ASU", "ASUS" },
77 { "ATI", "ATI" },
78 { "ATK", "Allied Telesyn" },
79 { "AZT", "Aztech" },
80 { "BAN", "Banya" },
81 { "BRI", "Boca Research" },
82 { "BUS", "Buslogic" },
83 { "CCI", "Cache Computers Inc." },
84 { "CHA", "Chase" },
85 { "CMD", "CMD Technology, Inc." },
86 { "COG", "Cogent" },
87 { "CPQ", "Compaq" },
88 { "CRS", "Crescendo" },
89 { "CSC", "Crystal" },
90 { "CSI", "CSI" },
91 { "CTL", "Creative Labs" },
92 { "DBI", "Digi" },
93 { "DEC", "Digital Equipment" },
94 { "DBK", "Databook" },
95 { "EGL", "Eagle Technology" },
96 { "ELS", "ELSA" },
97 { "ESS", "ESS" },
98 { "FAR", "Farallon" },
99 { "FDC", "Future Domain" },
100 { "HWP", "Hewlett-Packard" },
101 { "IBM", "IBM" },
102 { "INT", "Intel" },
103 { "ISA", "Iomega" },
104 { "LEN", "Lenovo" },
105 { "MDG", "Madge" },
106 { "MDY", "Microdyne" },
107 { "MET", "Metheus" },
108 { "MIC", "Micronics" },
109 { "MLX", "Mylex" },
110 { "NVL", "Novell" },
111 { "OLC", "Olicom" },
112 { "PRO", "Proteon" },
113 { "RII", "Racal" },
114 { "RTL", "Realtek" },
115 { "SCM", "SCM" },
116 { "SKD", "SysKonnect" },
117 { "SGI", "SGI" },
118 { "SMC", "SMC" },
119 { "SNI", "Siemens Nixdorf" },
120 { "STL", "Stallion Technologies" },
121 { "SUN", "Sun" },
122 { "SUP", "SupraExpress" },
123 { "SVE", "SVEC" },
124 { "TCC", "Thomas-Conrad" },
125 { "TCI", "Tulip" },
126 { "TCM", "3Com" },
127 { "TCO", "Thomas-Conrad" },
128 { "TEC", "Tecmar" },
129 { "TRU", "Truevision" },
130 { "TOS", "Toshiba" },
131 { "TYN", "Tyan" },
132 { "UBI", "Ungermann-Bass" },
133 { "USC", "UltraStor" },
134 { "VDM", "Vadem" },
135 { "VMI", "Vermont" },
136 { "WDC", "Western Digital" },
137 { "ZDS", "Zeos" },
138
139 /* From http://faydoc.tripod.com/structures/01/0136.htm */
140 { "ACT", "Targa" },
141 { "ADI", "ADI" },
142 { "AOC", "AOC Intl" },
143 { "API", "Acer America" },
144 { "APP", "Apple Computer" },
145 { "ART", "ArtMedia" },
146 { "AST", "AST Research" },
147 { "CPL", "Compal" },
148 { "CTX", "Chuntex Electronic Co." },
149 { "DPC", "Delta Electronics" },
150 { "DWE", "Daewoo" },
151 { "ECS", "ELITEGROUP" },
152 { "EIZ", "EIZO" },
153 { "FCM", "Funai" },
154 { "GSM", "LG Electronics" },
155 { "GWY", "Gateway 2000" },
156 { "HEI", "Hyundai" },
157 { "HIT", "Hitachi" },
158 { "HSL", "Hansol" },
159 { "HTC", "Hitachi" },
160 { "ICL", "Fujitsu ICL" },
161 { "IVM", "Idek Iiyama" },
162 { "KFC", "KFC Computek" },
163 { "LKM", "ADLAS" },
164 { "LNK", "LINK Tech" },
165 { "LTN", "Lite-On" },
166 { "MAG", "MAG InnoVision" },
167 { "MAX", "Maxdata" },
168 { "MEI", "Panasonic" },
169 { "MEL", "Mitsubishi" },
170 { "MIR", "miro" },
171 { "MTC", "MITAC" },
172 { "NAN", "NANAO" },
173 { "NEC", "NEC Tech" },
174 { "NOK", "Nokia" },
175 { "OQI", "OPTIQUEST" },
176 { "PBN", "Packard Bell" },
177 { "PGS", "Princeton" },
178 { "PHL", "Philips" },
179 { "REL", "Relisys" },
180 { "SDI", "Samtron" },
181 { "SMI", "Smile" },
182 { "SPT", "Sceptre" },
183 { "SRC", "Shamrock Technology" },
184 { "STP", "Sceptre" },
185 { "TAT", "Tatung" },
186 { "TRL", "Royal Information Company" },
187 { "TSB", "Toshiba, Inc." },
188 { "UNM", "Unisys" },
189 { "VSC", "ViewSonic" },
190 { "WTC", "Wen Tech" },
191 { "ZCM", "Zenith Data Systems" },
192
193 { "???", "Unknown" },
194 };
195
196 static gboolean
gnome_pnp_ids_load(GnomePnpIds * pnp_ids,GError ** error)197 gnome_pnp_ids_load (GnomePnpIds *pnp_ids, GError **error)
198 {
199 gchar *retval = NULL;
200 GnomePnpIdsPrivate *priv = pnp_ids->priv;
201 guint i;
202
203 /* load the contents */
204 g_debug ("loading: %s", PNP_IDS);
205 if (g_file_get_contents (PNP_IDS, &priv->table_data, NULL, error) == FALSE)
206 return FALSE;
207
208 /* parse into lines */
209 retval = priv->table_data;
210 for (i = 0; priv->table_data[i] != '\0'; i++) {
211
212 /* ignore */
213 if (priv->table_data[i] != '\n')
214 continue;
215
216 /* convert newline to NULL */
217 priv->table_data[i] = '\0';
218
219 /* the ID to text is a fixed offset */
220 if (retval[0] && retval[1] && retval[2] && retval[3] == '\t' && retval[4]) {
221 retval[3] = '\0';
222 g_hash_table_insert (priv->pnp_table,
223 retval,
224 retval+4);
225 retval = &priv->table_data[i+1];
226 }
227 }
228
229 return TRUE;
230 }
231
232 static const char *
find_vendor(const char * pnp_id)233 find_vendor (const char *pnp_id)
234 {
235 guint i;
236
237 for (i = 0; i < G_N_ELEMENTS (vendors); i++) {
238 if (g_strcmp0 (vendors[i].vendor_id, pnp_id) == 0)
239 return vendors[i].vendor_name;
240 }
241
242 return NULL;
243 }
244
245 /**
246 * gnome_pnp_ids_get_pnp_id:
247 * @pnp_ids: a #GnomePnpIds object
248 * @pnp_id: the PNP ID to look for
249 *
250 * Find the full manufacturer name for the given PNP ID.
251 *
252 * Returns: (transfer full): a new string representing the manufacturer name,
253 * or %NULL when not found.
254 */
255 gchar *
gnome_pnp_ids_get_pnp_id(GnomePnpIds * pnp_ids,const gchar * pnp_id)256 gnome_pnp_ids_get_pnp_id (GnomePnpIds *pnp_ids, const gchar *pnp_id)
257 {
258 GnomePnpIdsPrivate *priv = pnp_ids->priv;
259 const char *found;
260 guint size;
261
262 g_return_val_if_fail (GNOME_IS_PNP_IDSS (pnp_ids), NULL);
263 g_return_val_if_fail (pnp_id != NULL, NULL);
264
265 /* if table is empty, try to load it */
266 size = g_hash_table_size (priv->pnp_table);
267 if (size == 0) {
268 if (gnome_pnp_ids_load (pnp_ids, NULL) == FALSE)
269 return NULL;
270 }
271
272 /* look this up in the table */
273 found = g_hash_table_lookup (priv->pnp_table, pnp_id);
274 if (found == NULL) {
275 found = find_vendor (pnp_id);
276 if (found == NULL)
277 return NULL;
278 }
279
280 return g_strdup (found);
281 }
282
283 static void
gnome_pnp_ids_class_init(GnomePnpIdsClass * klass)284 gnome_pnp_ids_class_init (GnomePnpIdsClass *klass)
285 {
286 GObjectClass *object_class = G_OBJECT_CLASS (klass);
287 object_class->finalize = gnome_pnp_ids_finalize;
288 g_type_class_add_private (klass, sizeof (GnomePnpIdsPrivate));
289 }
290
291 static void
gnome_pnp_ids_init(GnomePnpIds * pnp_ids)292 gnome_pnp_ids_init (GnomePnpIds *pnp_ids)
293 {
294 pnp_ids->priv = GNOME_PNP_IDS_GET_PRIVATE (pnp_ids);
295
296 /* we don't keep malloc'd data in the hash; instead we read it
297 * out into priv->table_data and then link to it in the hash */
298 pnp_ids->priv->pnp_table = g_hash_table_new_full (g_str_hash,
299 g_str_equal,
300 NULL,
301 NULL);
302 }
303
304 static void
gnome_pnp_ids_finalize(GObject * object)305 gnome_pnp_ids_finalize (GObject *object)
306 {
307 GnomePnpIds *pnp_ids = GNOME_PNP_IDS (object);
308 GnomePnpIdsPrivate *priv = pnp_ids->priv;
309
310 g_free (priv->table_data);
311 g_hash_table_unref (priv->pnp_table);
312
313 G_OBJECT_CLASS (gnome_pnp_ids_parent_class)->finalize (object);
314 }
315
316 /**
317 * gnome_pnp_ids_new:
318 *
319 * Returns a reference to a #GnomePnpIds object, or creates
320 * a new one if none have been created.
321 *
322 * Returns: (transfer full): a #GnomePnpIds object.
323 */
324 GnomePnpIds *
gnome_pnp_ids_new(void)325 gnome_pnp_ids_new (void)
326 {
327 if (gnome_pnp_ids_object != NULL) {
328 g_object_ref (gnome_pnp_ids_object);
329 } else {
330 gnome_pnp_ids_object = g_object_new (GNOME_TYPE_PNP_IDSS, NULL);
331 g_object_add_weak_pointer (gnome_pnp_ids_object, &gnome_pnp_ids_object);
332 }
333 return GNOME_PNP_IDS (gnome_pnp_ids_object);
334 }
335
336