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