1#!/usr/bin/env python3 2# 3# make-pci-ids - Creates a file containing PCI IDs. 4# It use the databases from 5# https://github.com/pciutils/pciids/raw/master/pci.ids 6# to create our file epan/dissectors/pci-ids.c 7# 8# Wireshark - Network traffic analyzer 9# 10# By Caleb Chiu <caleb.chiu@macnica.com> 11# Copyright 2021 12# 13# SPDX-License-Identifier: GPL-2.0-or-later 14# 15 16import string 17import sys 18import urllib.request, urllib.error, urllib.parse 19 20OUTPUT_FILE = "epan/pci-ids.c" 21 22MIN_VENDOR_COUNT = 2250 # 2261 on 2021-11-01 23MIN_DEVICE_COUNT = 33000 # 33724 on 2021-11-01 24 25CODE_PREFIX = """\ 26 * 27 * Generated by tools/make-pci-ids.py 28 * By Caleb Chiu <caleb.chiu@macnica.com> 29 * Copyright 2021 30 * 31 * 32 * SPDX-License-Identifier: GPL-2.0-or-later 33 */ 34 35#include <config.h> 36#include \"pci-ids.h\" 37 38typedef struct 39{ 40 guint16 vid; 41 guint16 did; 42 guint16 svid; 43 guint16 ssid; 44 gchar *name; 45 46} pci_id_t; 47 48typedef struct 49{ 50 guint16 vid; 51 guint16 count; 52 pci_id_t *ids_ptr; 53 54} pci_vid_index_t; 55 56""" 57 58CODE_POSTFIX = """ 59static pci_vid_index_t *get_vid_index(guint16 vid) 60{ 61 guint32 start_index = 0; 62 guint32 end_index = 0; 63 guint32 idx = 0; 64 65 end_index = sizeof(pci_vid_index)/sizeof(pci_vid_index[0]); 66 67 while(start_index != end_index) 68 { 69 if(end_index - start_index == 1) 70 { 71 if(pci_vid_index[start_index].vid == vid) 72 return &pci_vid_index[start_index]; 73 74 break; 75 } 76 77 idx = (start_index + end_index)/2; 78 79 if(pci_vid_index[idx].vid < vid) 80 start_index = idx; 81 else 82 if(pci_vid_index[idx].vid > vid) 83 end_index = idx; 84 else 85 return &pci_vid_index[idx]; 86 87 } 88 89 return NULL; 90 91} 92 93const char *pci_id_str(guint16 vid, guint16 did, guint16 svid, guint16 ssid) 94{ 95 unsigned int i; 96 static char *not_found = \"Not found\"; 97 pci_vid_index_t *index_ptr; 98 pci_id_t *ids_ptr; 99 100 index_ptr = get_vid_index(vid); 101 102 if(index_ptr == NULL) 103 return not_found; 104 105 ids_ptr = index_ptr->ids_ptr; 106 for(i = 0; i < index_ptr->count; ids_ptr++, i++) 107 if(vid == ids_ptr->vid && 108 did == ids_ptr->did && 109 svid == ids_ptr->svid && 110 ssid == ids_ptr->ssid) 111 return ids_ptr->name; 112 return not_found; 113 114} 115""" 116 117 118id_list=[] 119count_list=[] 120 121 122def exit_msg(msg=None, status=1): 123 if msg is not None: 124 sys.stderr.write(msg + '\n') 125 sys.exit(status) 126 127 128def main(): 129 req_headers = { 'User-Agent': 'Wireshark make-pci-ids' } 130 req = urllib.request.Request('https://github.com/pciutils/pciids/raw/master/pci.ids', headers=req_headers) 131 response = urllib.request.urlopen(req) 132 lines = response.read().decode('UTF-8', 'replace').splitlines() 133 134 out_lines = '''\ 135/* pci-ids.c 136 * 137 * pci-ids.c is based on the pci.ids of The PCI ID Repository at 138 * https://pci-ids.ucw.cz/, fetched indirectly via 139 * https://github.com/pciutils/pciids 140''' 141 vid = -1 142 did = -1 143 svid = -1 144 entries = 0 145 line_num = 0 146 147 for line in lines: 148 line = line.strip('\n') 149 line_num += 1 150 151 if line_num <= 15: 152 line = line.replace('#', ' ', 1) 153 line = line.lstrip() 154 line = line.replace("GNU General Public License", "GPL") 155 if line: 156 line = ' * ' + line 157 else: 158 line = ' *' + line 159 out_lines += line + '\n' 160 if line_num == 15: 161 out_lines += CODE_PREFIX 162 163 line = line.replace("\\","\\\\") 164 line = line.replace("\"","\\\"") 165 line = line.replace("?","?-") 166 tabs = len(line) - len(line.lstrip('\t')) 167 if tabs == 0: 168 #print line 169 words = line.split(" ", 1) 170 if len(words) < 2: 171 continue 172 if len(words[0]) != 4: 173 continue 174 if all(c in string.hexdigits for c in words[0]): 175 hex_int = int(words[0], 16) 176 if vid != -1: 177 out_lines += "}; /* pci_vid_%04X[] */\n\n" % (vid) 178 count_list.append(entries) 179 vid = hex_int 180 entries = 1 181 did = -1 182 svid = -1 183 ssid = -1 184 out_lines += "pci_id_t pci_vid_%04X[] = {\n" % (vid) 185 out_lines += "{0x%04X, 0xFFFF, 0xFFFF, 0xFFFF, \"%s(0x%04X)\"},\n" % (vid, words[1].strip(), vid) 186 id_list.append(vid) 187 continue 188 189 if tabs == 1: 190 line = line.strip('\t') 191 words = line.split(" ", 1) 192 if len(words) < 2: 193 continue 194 if len(words[0]) != 4: 195 continue 196 if all(c in string.hexdigits for c in words[0]): 197 hex_int = int(words[0], 16) 198 did = hex_int 199 svid = -1 200 ssid = -1 201 out_lines += "{0x%04X, 0x%04X, 0xFFFF, 0xFFFF, \"%s(0x%04X)\"},\n" % (vid, did, words[1].strip(), did) 202 entries += 1 203 continue 204 205 if tabs == 2: 206 line = line.strip('\t') 207 words = line.split(" ", 2) 208 if len(words[0]) != 4: 209 continue 210 if all(c in string.hexdigits for c in words[0]): 211 hex_int = int(words[0], 16) 212 svid = hex_int 213 214 if all(c in string.hexdigits for c in words[1]): 215 hex_int = int(words[1], 16) 216 ssid = hex_int 217 218 out_lines += "{0x%04X, 0x%04X, 0x%04X, 0x%04X, \"%s(0x%04X-0x%04X)\"},\n" % (vid, did, svid, ssid, words[2].strip(), svid, ssid) 219 entries += 1 220 svid = -1 221 ssid = -1 222 continue 223 224 out_lines += "}; /* pci_vid_%04X[] */\n" % (vid) 225 count_list.append(entries) 226 227 out_lines += "\npci_vid_index_t pci_vid_index[] = {\n" 228 229 vendor_count = len(id_list) 230 device_count = 0 231 for i in range(vendor_count): 232 out_lines += "{0x%04X, %d, pci_vid_%04X },\n" % (id_list[i], count_list[i], id_list[i]) 233 device_count += count_list[i] 234 235 out_lines += "}; /* We have %d VIDs */\n" % (vendor_count) 236 237 out_lines += CODE_POSTFIX 238 239 if vendor_count < MIN_VENDOR_COUNT: 240 exit_msg(f'Too view vendors. Wanted {MIN_VENDOR_COUNT}, got {vendor_count}.') 241 242 if device_count < MIN_DEVICE_COUNT: 243 exit_msg(f'Too view devices. Wanted {MIN_DEVICE_COUNT}, got {device_count}.') 244 245 with open(OUTPUT_FILE, "w", encoding="utf-8") as pci_ids_f: 246 pci_ids_f.write(out_lines) 247 248if __name__ == '__main__': 249 main() 250