revert between 56095 -> 55830 in arch
[AROS.git] / rom / hidds / pci / pcitool / pciids.c
blob60f86d54c849a5b17ad86010d27cb71f5324f692
1 /*
2 Copyright (C) 2004-2010, The AROS Development Team.
3 $Id$
4 */
6 #include <exec/memory.h>
8 #include <proto/dos.h>
10 #include "pciids.h"
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <string.h>
16 #include <aros/debug.h>
18 // it's supposed to become a shared library one day ...
19 //
20 // current implementation:
21 // on pciids_Open(), the file is read in memory, then
22 // an index is built (in computeVendorIndexes()), as an array
23 // of couples (vendor_id, offset)
24 // where offset is the offset where the vendor stuff begins
25 // in the memory file. This array is ascending sorted by vendor_id,
26 // so a binary search can be done to retrieve the vendor offset
27 // given its id. This search is done in getVendorIndex().
28 // All the stringification functions first call this search func,
29 // then parse the memory:
30 // 1234 VendorName (so: s[0] = hex digit, s[4] == ' ', s[6+] == name)
31 // <tab>1234 DeviceName (same with a tab on linestart)
32 // todo: subvendor/subdevice parsing
33 // todo: proper memory reallocation, currently the index is fixed
34 // to 2500 vendors
36 static STRPTR mem = NULL;
37 static ULONG memsize = 0;
39 struct vendor_cell
41 UWORD vendorID;
42 LONG offset;
45 static struct vendor_cell *vendor_index = NULL;
46 static ULONG vi_allocated = 0;
47 static UWORD vi_number = 0;
49 static LONG skip_line(const char *buffer, LONG size, LONG pos)
51 buffer += pos;
52 while (pos < size)
54 if (*buffer++ == '\n')
56 pos++;
57 break;
59 pos++;
61 return pos;
64 static LONG copy_until_eol(STRPTR m, ULONG msize, LONG pos, STRPTR buf,
65 ULONG bufsize)
67 LONG j = 0;
69 m += pos;
70 while ((pos < msize) && (j < bufsize - 1) && (*m != '\n'))
72 buf[j++] = *m++;
74 buf[j] = 0;
75 return j;
78 static BOOL computeVendorIndexes(const char *buffer, LONG size)
80 LONG i, j;
82 vi_allocated = 2500;
83 vendor_index = (struct vendor_cell *)AllocVec(vi_allocated * sizeof(struct vendor_cell), MEMF_ANY);
84 if (NULL == vendor_index)
85 return FALSE;
87 i = 0;
88 j = 0;
90 while (i < size)
92 // don't use isxdigit, beware of uppercase letter
93 if ((isdigit(buffer[i]) || (buffer[i] >= 'a' && buffer[i] <= 'f'))
94 && (i + 4 < size) && (buffer[i + 4] == ' '))
96 if (sscanf(buffer + i, "%hx", &(vendor_index[j].vendorID)) != 1)
97 return FALSE;
98 vendor_index[j].offset = i;
99 //bug("%ld: %x => %ld\n", j, vendor_index[j].vendorID, vendor_index[j].offset);
100 j++;
101 if (j >= vi_allocated)
103 bug("[pcitool] pciids.c:computeVendorIndexes: vendor_index overflow\n");
104 FreeVec(vendor_index);
105 vendor_index = NULL;
106 return FALSE;
109 i = skip_line(buffer, size, i);
111 vi_number = j - 1;
112 return TRUE;
115 static LONG getVendorIndex(UWORD vendorID)
117 LONG lower = 0;
118 LONG upper = vi_number;
120 if (!mem || !vendor_index)
121 return -1;
123 while (upper != lower)
125 UWORD vid;
127 vid = vendor_index[(upper + lower) / 2].vendorID;
128 if (vid == vendorID)
129 return vendor_index[(upper + lower) / 2].offset;
130 if (vendorID > vid)
131 lower = (upper + lower) / 2 + 1;
132 else
133 upper = (upper + lower) / 2;
135 return -1;
138 static LONG getDeviceIndex(LONG vendorIndex, UWORD deviceID)
140 LONG i = vendorIndex;
142 if (i < 0)
143 return i;
145 i = skip_line(mem, memsize, i); // skip vendor
146 while ((i < memsize) && ((mem[i] == '\t') || (mem[i] == '#')))
148 UWORD did;
150 if (mem[i] != '#')
152 if ((i + 6 < memsize) && (mem[i + 5] == ' ')
153 && (sscanf(mem + i + 1, "%hx", &did) == 1) && (did == deviceID))
155 return i;
158 i = skip_line(mem, memsize, i);
160 return -1;
163 static LONG getSubDeviceIndex(LONG deviceIndex, UWORD subVendorID, UWORD subDeviceID)
165 LONG i = deviceIndex;
167 if (i < 0)
168 return i;
170 i = skip_line(mem, memsize, i);
171 while ((i < memsize) && ((mem[i] == '\t') || (mem[i] == '#')))
173 UWORD subvid, subdid;
175 if ((mem[i] != '#') && (i + 1 < memsize) && (mem[i+1] == '\t'))
177 if ((i + 11 < memsize)
178 && (mem[i + 6] == ' ')
179 && (sscanf(mem + i, "%hx", &subvid) == 1)
180 && (subvid == subVendorID)
181 && (mem[i + 11] == ' ')
182 && (sscanf(mem + i + 7, "%hx", &subdid) == 1)
183 && (subdid == subDeviceID))
185 return i;
188 i = skip_line(mem, memsize, i);
190 return -1;
193 void pciids_Open(void)
195 BPTR fh;
196 LONG size;
198 fh = Open("DEVS:pci.ids", MODE_OLDFILE);
199 if (!fh)
200 goto err_open_ids;
202 Seek(fh, 0, OFFSET_END);
203 size = Seek(fh, 0, OFFSET_CURRENT);
204 if (size <= 0)
205 goto err_size;
207 memsize = (ULONG)size;
208 Seek(fh, 0, OFFSET_BEGINNING);
210 mem = (STRPTR)AllocVec(memsize, MEMF_ANY);
211 if (NULL == mem)
212 goto err_mem;
214 if (Read(fh, mem, memsize) != size)
215 goto err_read;
217 if (!computeVendorIndexes(mem, memsize))
218 goto err_index;
220 // success !
221 return;
223 err_index:
224 err_read:
225 FreeVec(mem);
226 mem = NULL;
227 err_mem:
228 err_size:
229 Close(fh);
230 err_open_ids:
231 return;
234 void pciids_Close(void)
236 if (vendor_index)
238 FreeVec(vendor_index);
239 vendor_index = NULL;
242 if (mem)
244 FreeVec(mem);
245 mem = NULL;
249 STRPTR pciids_GetVendorName(UWORD vendorID, STRPTR buf, ULONG bufsize)
251 LONG i = getVendorIndex(vendorID);
253 buf[0] = 0;
254 if (i < 0)
255 return buf;
257 copy_until_eol(mem, memsize, i + 6, buf, bufsize);
259 return buf;
262 STRPTR pciids_GetDeviceName(UWORD vendorID, UWORD deviceID, STRPTR buf,
263 ULONG bufsize)
265 LONG i = getVendorIndex(vendorID);
267 buf[0] = 0;
268 if (i < 0) // unknown vendor
269 return buf;
271 i = getDeviceIndex(i, deviceID);
272 if (i < 0) // unknown device
273 return buf;
275 copy_until_eol(mem, memsize, i + 7, buf, bufsize);
276 return buf;
279 STRPTR pciids_GetSubDeviceName(UWORD vendorID, UWORD deviceID, UWORD subVendorID,
280 UWORD subDeviceID, STRPTR buf, ULONG bufsize)
282 LONG i;
283 LONG j;
284 LONG copied;
286 buf[0] = 0;
288 if ((0 == subVendorID) && (0 == subDeviceID))
289 return buf;
291 i = getVendorIndex(vendorID);
292 if (i < 0) // unknown vendor
293 return buf;
295 i = getDeviceIndex(i, deviceID);
296 if (i < 0) // unknown device
297 return buf;
299 j = getVendorIndex(subVendorID);
300 if (j < 0) // unknown subvendor
301 return buf;
303 copied = copy_until_eol(mem, memsize, j + 6, buf, bufsize);
305 if (copied + 4 < bufsize)
307 strcpy(buf + copied, " : ");
309 i = getSubDeviceIndex(i, subVendorID, subDeviceID);
310 if (i < 0) // unknown subdevice
312 if (bufsize - copied - 3 > 6)
313 sprintf(buf + copied + 3, "0x%04x", subDeviceID);
314 return buf;
317 copy_until_eol(mem, memsize, i + 13, buf + copied + 3,
318 bufsize - copied - 3);
321 return buf;