]> mj.ucw.cz Git - pciutils.git/blob - names.c
Intermediate version of pciutils.
[pciutils.git] / names.c
1 /*
2  *      $Id: names.c,v 1.3 1998/01/27 11:50:10 mj Exp $
3  *
4  *      Linux PCI Utilities -- Device ID to Name Translation
5  *
6  *      Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
7  *
8  *      Can be freely distributed and used under the terms of the GNU GPL.
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/stat.h>
17 #include <linux/pci.h>
18
19 #include "pciutils.h"
20
21 int show_numeric_ids;
22
23 char *pci_ids = ETC_PCI_IDS;
24
25 static byte *name_list;
26 static int name_list_loaded;
27
28 struct nl_entry {
29   struct nl_entry *next;
30   int id1, id2;
31   byte *name;
32 };
33
34 #define ID1_VENDOR -1
35 #define ID1_CLASS -2
36 #define ID1_SUBCLASS -3
37 #define ID1_ERROR -4
38
39 #define HASH_SIZE 1024
40
41 static struct nl_entry *nl_hash[HASH_SIZE];
42
43 static inline unsigned int nl_calc_hash(int id1, int id2)
44 {
45   unsigned int h;
46
47   h = id1 ^ id2;
48   h ^= (h >> 6);
49   return h & (HASH_SIZE-1);
50 }
51
52 static struct nl_entry *nl_lookup(int id1, int id2)
53 {
54   unsigned int h = nl_calc_hash(id1, id2);
55   struct nl_entry *n = nl_hash[h];
56
57   while (n && (n->id1 != id1 || n->id2 != id2))
58     n = n->next;
59   return n;
60 }
61
62 static int nl_add(int id1, int id2, byte *text)
63 {
64   unsigned int h = nl_calc_hash(id1, id2);
65   struct nl_entry *n = nl_hash[h];
66
67   while (n && (n->id1 != id1 || n->id2 != id2))
68     n = n->next;
69   if (n)
70     return 1;
71   n = xmalloc(sizeof(struct nl_entry));
72   n->id1 = id1;
73   n->id2 = id2;
74   n->name = text;
75   n->next = nl_hash[h];
76   nl_hash[h] = n;
77   return 0;
78 }
79
80 static void
81 err_name_list(char *msg)
82 {
83   fprintf(stderr, "%s: %s: %m\n", pci_ids, msg);
84   exit(1);
85 }
86
87 static void
88 parse_name_list(void)
89 {
90   byte *p = name_list;
91   byte *q, *r, *s;
92   int lino = 0;
93   int id1 = ID1_ERROR;
94   int id2 = 0;
95   int i, j;
96
97   while (*p)
98     {
99       lino++;
100       q = p;
101       while (*p && *p != '\n')
102         {
103           if (*p == '#')
104             {
105               *p++ = 0;
106               while (*p && *p != '\n')
107                 p++;
108               break;
109             }
110           if (*p == '\t')
111             *p = ' ';
112           p++;
113         }
114       if (*p == '\n')
115         *p++ = 0;
116       if (!*q)
117         continue;
118       r = p;
119       while (r > q && r[-1] == ' ')
120         *--r = 0;
121       r = q;
122       while (*q == ' ')
123         q++;
124       if (strlen(q) < 5 || q[4] != ' ')
125         goto parserr;
126       if (r == q)
127         {
128           if (q[0] == 'C' && q[1] == ' ')
129             {
130               if (sscanf(q+2, "%x", &j) != 1)
131                 goto parserr;
132               i = ID1_CLASS;
133             }
134           else
135             {
136               if (sscanf(q, "%x", &j) != 1)
137                 goto parserr;
138               i = ID1_VENDOR;
139             }
140           id1 = i;
141           id2 = j;
142         }
143       else
144         {
145           if (sscanf(q, "%x", &j) != 1)
146             goto parserr;
147           if (id1 == ID1_ERROR)
148             goto parserr;
149           if (id1 == ID1_CLASS)
150             {
151               i = ID1_SUBCLASS;
152               j |= (id2 << 8);
153             }
154           else
155             i = id2;
156         }
157       q += 4;
158       while (*q == ' ')
159         q++;
160       if (!*q)
161         goto parserr;
162       if (nl_add(i, j, q))
163         {
164           fprintf(stderr, "%s, line %d: duplicate entry\n", pci_ids, lino);
165           exit(1);
166         }
167     }
168   return;
169
170 parserr:
171   fprintf(stderr, "%s, line %d: parse error\n", pci_ids, lino);
172   exit(1);
173 }
174
175 static void
176 load_name_list(void)
177 {
178   int fd;
179   struct stat st;
180
181   fd = open(pci_ids, O_RDONLY);
182   if (fd < 0)
183     {
184       show_numeric_ids = 1;
185       return;
186     }
187   if (fstat(fd, &st) < 0)
188     err_name_list("stat");
189   name_list = xmalloc(st.st_size + 1);
190   if (read(fd, name_list, st.st_size) != st.st_size)
191     err_name_list("read");
192   name_list[st.st_size] = 0;
193   parse_name_list();
194   close(fd);
195   name_list_loaded = 1;
196 }
197
198 char *
199 lookup_vendor(word i)
200 {
201   static char vendbuf[6];
202
203   if (!show_numeric_ids && !name_list_loaded)
204     load_name_list();
205   if (!show_numeric_ids)
206     {
207       struct nl_entry *e;
208
209       e = nl_lookup(ID1_VENDOR, i);
210       if (e)
211         return e->name;
212     }
213   sprintf(vendbuf, "%04x", i);
214   return vendbuf;
215 }
216
217 char *
218 lookup_device(word v, word i)
219 {
220   static char devbuf[6];
221
222   if (!show_numeric_ids && !name_list_loaded)
223     load_name_list();
224   if (!show_numeric_ids)
225     {
226       struct nl_entry *e;
227
228       e = nl_lookup(v, i);
229       if (e)
230         return e->name;
231     }
232   sprintf(devbuf, "%04x", i);
233   return devbuf;
234 }
235
236 char *
237 lookup_device_full(word v, word i)
238 {
239   static char fullbuf[256];
240
241   if (!show_numeric_ids && !name_list_loaded)
242     load_name_list();
243   if (!show_numeric_ids)
244     {
245       struct nl_entry *e, *e2;
246
247       e = nl_lookup(ID1_VENDOR, v);
248       e2 = nl_lookup(v, i);
249       if (!e)
250         sprintf(fullbuf, "Unknown device %04x:%04x", v, i);
251       else if (!e2)
252         sprintf(fullbuf, "%s: Unknown device %04x", e->name, i);
253       else
254         sprintf(fullbuf, "%s %s", e->name, e2->name);
255     }
256   else
257     sprintf(fullbuf, "%04x:%04x", v, i);
258   return fullbuf;
259 }
260
261 char *
262 lookup_class(word c)
263 {
264   static char classbuf[80];
265
266   if (!show_numeric_ids && !name_list_loaded)
267     load_name_list();
268   if (!show_numeric_ids)
269     {
270       struct nl_entry *e;
271
272       e = nl_lookup(ID1_SUBCLASS, c);
273       if (e)
274         return e->name;
275       e = nl_lookup(ID1_CLASS, c);
276       if (e)
277         sprintf(classbuf, "%s [%04x]", e->name, c);
278       else
279         sprintf(classbuf, "Unknown class [%04x]", c);
280     }
281   else
282     sprintf(classbuf, "Class %04x", c);
283   return classbuf;
284 }