0001 #!/usr/bin/env python 0002 ### BITPIM 0003 ### 0004 ### Copyright (C) 2003 Steve Palm <n9yty@n9yty.com> 0005 ### 0006 ### This program is free software; you can redistribute it and/or modify 0007 ### it under the terms of the BitPim license as detailed in the LICENSE file. 0008 ### 0009 ### $Id: usb_ids.py 2867 2006-03-05 01:03:55Z djpham $ 0010 0011 """Parse the usb.ids file for quick access to the information contained therein""" 0012 0013 import re 0014 0015 vendor_re = re.compile(r"^([0-9A-Fa-f]{4,4})\s+(.*)$") 0016 device_re = re.compile(r"^\t([0-9A-Fa-f]{4,4})\s+(.*)$") 0017 iface_re = re.compile(r"^\t\t([0-9A-Fa-f]{2,2})\s+(.*)$") 0018 usbclass_re = re.compile(r"^C\s([0-9A-Fa-f]{2,2})\s+(.*)$") 0019 usbsubclass_re = re.compile(r"^\t([0-9A-Fa-f]{2,2})\s+(.*)$") 0020 usbprotocol_re = re.compile(r"^\t\t([0-9A-Fa-f]{2,2})\s+(.*)$") 0021 0022 ### 0023 ### USB Info superclass 0024 ### 0025 class usbInfoObject: 0026 """ Super class for all types of USB vendor/device/interface/class/sublcass/protocol 0027 classes which will be descendants of this. I chose to make and use various children 0028 of this class, as it's possible they may have unique information of their own some 0029 time later, as well as allowing a more natural name/syntax based on object use. 0030 """ 0031 def __init__(self, id, description): 0032 """ Set our ID code, description, and prepare to accept children """ 0033 self.id = id 0034 self.description = description 0035 self.children = {}; 0036 0037 def description(self): 0038 """ Return the description for this object """ 0039 return self.description 0040 0041 def id(self): 0042 """ Return our ID code """ 0043 return self.id 0044 0045 def addChild(self, child): 0046 """ Add a child to our list """ 0047 self.children[int(child.id, 16)] = child 0048 0049 def getChild(self, child): 0050 """ If we have a child matching the request, return it """ 0051 if child in self.children: 0052 return self.children[child] 0053 else: 0054 return None 0055 0056 def getChildren(self): 0057 """ Return a list of all our children """ 0058 return self.children.values() 0059 0060 ### 0061 ### USB ID file superclass --- This is our master object 0062 ### 0063 class usb_ids: 0064 """ Class that represents the data in the usb.ids file 0065 It reads/parses the file and creates the objects to match 0066 """ 0067 0068 def __init__(self, fname=None): 0069 """ Initialize the class. This includes reading the supplied file 0070 and creating/populating as many related objects as needed. 0071 """ 0072 self.vendorlist = VendorList() 0073 self.usbclasslist = USBClassList() 0074 self.inVendor = 0 0075 self.inClass = 0 0076 if fname is not None: 0077 self.add_data(fname) 0078 0079 def add_data(self, fname): 0080 try: 0081 ufile = open(fname, "rt") 0082 try: 0083 aline = ufile.readline() 0084 while aline != "": 0085 # Remove any EOL characters 0086 while (aline[:-1] in ["\r", "\n"]): 0087 aline = aline[:-1] 0088 0089 # Check for a vendor ID line 0090 m = vendor_re.match(aline) 0091 if (m): 0092 self.inVendor = 1 0093 self.inClass = 0 0094 self.curr_vendor = VendorID(m.group(1), m.group(2)) 0095 self.vendorlist.addVendor(m.group(1), self.curr_vendor) 0096 0097 if (self.inVendor): 0098 # Check for a device ID line 0099 m = device_re.match(aline) 0100 if (m): 0101 self.curr_device = DeviceID(m.group(1), m.group(2)) 0102 self.curr_vendor.addDevice(self.curr_device) 0103 0104 # Check for a interface ID line 0105 m = iface_re.match(aline) 0106 if (m): 0107 self.curr_device.addInterface(InterfaceID(m.group(1), m.group(2))) 0108 0109 # Check for a USB Class line 0110 m = usbclass_re.match(aline) 0111 if (m): 0112 self.inClass = 1 0113 self.inVendor = 0 0114 self.curr_usbclass = USBClass(m.group(1), m.group(2)) 0115 self.usbclasslist.addClass(m.group(1), self.curr_usbclass) 0116 0117 if (self.inClass): 0118 # Check for a USB SubClass line 0119 m = usbsubclass_re.match(aline) 0120 if (m): 0121 self.curr_usbsubclass = USBClassSubclass(m.group(1), m.group(2)) 0122 self.curr_usbclass.addSubclass(self.curr_usbsubclass) 0123 0124 # Check for a USB Protocol line 0125 m = usbprotocol_re.match(aline) 0126 if (m): 0127 self.curr_usbsubclass.addProtocol(USBClassProtocol(m.group(1), m.group(2))) 0128 0129 # Get next line (if it exists) 0130 aline = ufile.readline() 0131 except IOError: 0132 # We'll take a pass on it, live with what (if any) data we get 0133 pass 0134 0135 except IOError: 0136 print ("Cannot open the USB ID file: %s" % fname) 0137 raise 0138 0139 if (ufile): 0140 ufile.close() 0141 0142 def lookupdevice(self, vendor, product=None, interface=None): 0143 return self.vendorlist.getVendorInfo(vendor, product, interface) 0144 0145 def lookupclass(self, klass, subclass=None, protocol=None): 0146 return self.usbclasslist.getClassInfo(klass, subclass, protocol) 0147 0148 def getVendorList(self): 0149 """ Return the object representing the list of vendors """ 0150 return self.vendorlist 0151 0152 def getUSBClassList(self): 0153 """ Return the object representing the list of USB Classes """ 0154 return self.usbclasslist 0155 0156 ### 0157 ### USB VendorID/DeviceID information related classes 0158 ### 0159 class VendorID(usbInfoObject): 0160 """ This class abstracts USB Vendor ID information 0161 It holds the description, and a list of Device ID's 0162 """ 0163 def addDevice(self, device): 0164 """ Put this device on our list """ 0165 self.addChild(device) 0166 0167 def getDevice(self, device): 0168 """ Return the requested device by ID, if we have it """ 0169 return self.getChild(device) 0170 0171 def getDevices(self): 0172 """ Return a list of our devices """ 0173 return self.getChildren() 0174 0175 class DeviceID(usbInfoObject): 0176 """ This class abstracts USB Device ID information 0177 It holds the description and a list of the Interface ID's 0178 """ 0179 def addInterface(self, interface): 0180 """ Put this interface on our list """ 0181 self.addChild(interface) 0182 0183 def getInterface(self, interface): 0184 """ Return the requested interface by ID, if we have it """ 0185 return self.getChild(interface) 0186 0187 def getInterfaces(self): 0188 """ Return a list of our interfaces """ 0189 return self.getChildren() 0190 0191 class InterfaceID(usbInfoObject): 0192 """ This class abstracts USB Interface information 0193 It holds the description 0194 """ 0195 pass 0196 0197 class VendorList: 0198 """ This class is responsible for the collection of vendor data 0199 It allows you to ask for: 0200 - vendor info by VendorID 0201 - device info by VendorID/DeviceID 0202 - interface """ 0203 def __init__(self): 0204 """ Prepare a dict to handle all of our children vendor objects """ 0205 self.vendorlist = {} 0206 0207 def addVendor(self, vID, vDesc): 0208 """ Put this vendor into our dictionary """ 0209 self.vendorlist[int(vID,16)] = vDesc 0210 0211 def getVendorInfo(self, vID, dID=None, iID=None): 0212 """ Lookup info for vendor, device, interface - last two are optional """ 0213 # First things first... Get information if available.... 0214 self.vendor = self.device = self.iface = None 0215 self.vDesc = self.dDesc = self.iDesc = None 0216 0217 # --- Vendor 0218 if vID in self.vendorlist: 0219 self.vendor = self.vendorlist[vID] 0220 self.vDesc = self.vendor.description 0221 0222 # --- Device 0223 if self.vendor: 0224 self.device = self.vendor.getDevice(dID) 0225 if self.device: 0226 self.dDesc = self.device.description 0227 0228 # --- Interface 0229 if self.device: 0230 self.iface = self.device.getInterface(iID) 0231 if self.iface: 0232 self.iDesc = self.iface.description 0233 0234 # Now, decide how we were called, and return appropriately 0235 if ((dID is None) and (iID is None)): 0236 return (self.vDesc,) 0237 elif (iID is None): 0238 return (self.vDesc, self.dDesc) 0239 else: 0240 return (self.vDesc, self.dDesc, self.iDesc) 0241 0242 def getVendorList(self): 0243 return self.vendorlist.values() 0244 0245 0246 ### 0247 ### USB Class information related classes 0248 ### 0249 class USBClass(usbInfoObject): 0250 """ This class abstracts USB Class information 0251 It holds the description, and a list of Subclasses 0252 """ 0253 def addSubclass(self, subclass): 0254 """ Put this subclass on our list """ 0255 self.addChild(subclass) 0256 0257 def getSubclass(self, subclass): 0258 """ Return subclass by ID, if we have it """ 0259 return self.getChild(subclass) 0260 0261 def getSubclasses(self): 0262 """ Return a list of our subclasses """ 0263 return self.getChildren() 0264 0265 0266 class USBClassSubclass(usbInfoObject): 0267 """ This class abstracts USB Device SubClass information 0268 It holds the description and a list of the protocols 0269 """ 0270 def addProtocol(self, protocol): 0271 """ Put this protocol on our list """ 0272 self.addChild(protocol) 0273 0274 def getProtocol(self, protocol): 0275 """ Return protocol as ID, if we have it """ 0276 return self.getChild(protocol) 0277 0278 def getProtocols(self): 0279 """ Return a list of our protocols """ 0280 return self.getChildren() 0281 0282 class USBClassProtocol(usbInfoObject): 0283 """ This class abstracts USB Interface information 0284 It holds the description 0285 """ 0286 pass 0287 0288 0289 class USBClassList: 0290 """ This class is responsible for the collection of USB Class data 0291 It allows you to ask for: 0292 - USB Class info by Class ID 0293 - USB SubClass info by ClassID/SubclassID 0294 - USB Protocol info by ClassID/SubclassID/ProtocolID 0295 """ 0296 def __init__(self): 0297 self.classlist = {} 0298 0299 def addClass(self, cID, cDesc): 0300 self.classlist[int(cID, 16)] = cDesc 0301 0302 def getClassInfo(self, cID, sID=None, pID=None): 0303 """ Lookup info for class, subclass, protocol - last two are optional """ 0304 # First things first... Get information if available.... 0305 self.usbclass = self.subclass = self.protocol = None 0306 self.cDesc = self.sDesc = self.pDesc = None 0307 0308 # --- USB Class 0309 if cID in self.classlist: 0310 self.usbclass = self.classlist[cID] 0311 self.cDesc = self.usbclass.description 0312 0313 # --- USB Subclass 0314 if self.usbclass: 0315 self.subclass = self.usbclass.getSubclass(sID) 0316 if self.subclass: 0317 self.sDesc = self.subclass.description 0318 0319 # --- USB Protocol 0320 if self.subclass: 0321 self.protocol = self.subclass.getProtocol(pID) 0322 if self.protocol: 0323 self.pDesc = self.protocol.description 0324 0325 # Now, decide how we were called, and return appropriately 0326 if ((sID is None) and (pID is None)): 0327 return (self.cDesc,) 0328 elif (pID is None): 0329 return (self.cDesc, self.sDesc) 0330 else: 0331 return (self.cDesc, self.sDesc, self.pDesc) 0332 0333 def getUSBClassList(self): 0334 return self.classlist.values() 0335 0336 0337 0338 ### 0339 ### Interactive testing code 0340 ### 0341 if (__name__ == "__main__"): 0342 import os, guihelper 0343 def print_vendor_info(USBids): 0344 # Print out vendor / device / interface info 0345 vlist = USBids.getVendorList() 0346 for v in vlist.getVendorList(): 0347 print ("VENDOR: %s %s" % (v.id, v.description)) 0348 for d in v.getDevices(): 0349 print ("\tDEVICE: %s %s" % (d.id, d.description)) 0350 for i in d.getInterfaces(): 0351 print ("\t\tIFACE: %s %s" % (i.id, i.description)) 0352 0353 def print_class_info(USBids): 0354 # Print out class / subclass / protocol 0355 clist = USBids.getUSBClassList() 0356 for c in clist.getUSBClassList(): 0357 print ("CLASS: %s %s" % (c.id, c.description)) 0358 for s in c.getSubclasses(): 0359 print ("\tSUBCLASS: %s %s" % (s.id, s.description)) 0360 for p in s.getProtocols(): 0361 print ("\t\tPROTOCOL: %s %s" % (p.id, p.description)) 0362 0363 myUSBids = usb_ids(os.path.join(guihelper.resourcedirectory, 0364 "usb.ids")) 0365 0366 # PRINT OUT THE WHOLE TREE AS A TEST CASE 0367 # print_vendor_info(myUSBids) 0368 # print_class_info(myUSBids) 0369 0370 # Our list is now internally decimal, so to lookup/inquire by hex 0371 # You must convert to decimal before passing your inquiry in... 0372 0373 # Test lookup for various bits of USB Vendor/Device/Interface information 0374 print "Inquire on Vendor 1452, Device 518, Iface 1 using various levels of detail:" 0375 vlist = myUSBids.getVendorList() 0376 print vlist.getVendorInfo(1452) 0377 print vlist.getVendorInfo(1452, 518) 0378 print vlist.getVendorInfo(1452, 518, 1) 0379 print 0380 0381 # Test lookup for various bits of USB Class/Subclass/Protocol information 0382 print "Inquire on Class 8, Subclass 4, Protocol 0 using various levels of detail:" 0383 clist = myUSBids.getUSBClassList() 0384 print clist.getClassInfo(8) 0385 print clist.getClassInfo(8, 4) 0386 print clist.getClassInfo(8, 4, 0) 0387 print 0388 0389 # For reference, this is how you'd inquire on hex values 0390 # print vlist.getVendorInfo(int("05ac", 16)) 0391 # print vlist.getVendorInfo(int("05ac", 16), int("0206", 16)) 0392 # print vlist.getVendorInfo(int("05ac", 16), int("0206", 16), int("01", 16)) 0393 # print clist.getClassInfo(int("08", 16)) 0394 # print clist.getClassInfo(int("08", 16), int("04", 16)) 0395 # print clist.getClassInfo(int("08", 16), int("04", 16), int("00", 16)) 0396 0397 # The following are in hex just becuase that way I can visually match them 0398 # up with the entries in the test.ids file 0399 0400 # Now, let's test for something that doesn't exist: 0401 print "Look up something with little detail in Internet file... 1004/6000/(00..02)" 0402 print vlist.getVendorInfo(int("1004", 16), int("6000", 16), int("00", 16)) 0403 print vlist.getVendorInfo(int("1004", 16), int("6000", 16), int("01", 16)) 0404 print vlist.getVendorInfo(int("1004", 16), int("6000", 16), int("02", 16)) 0405 print 0406 0407 # Put the data in from our local copy 0408 print "Add in our test data to override internet data" 0409 myUSBids.add_data(os.path.join(guihelper.resourcedirectory, 0410 "test.ids")) 0411 print 0412 0413 # Now, it should be there 0414 print "Check it again..." 0415 print vlist.getVendorInfo(int("1004", 16), int("6000", 16), int("00", 16)) 0416 print vlist.getVendorInfo(int("1004", 16), int("6000", 16), int("01", 16)) 0417 print vlist.getVendorInfo(int("1004", 16), int("6000", 16), int("02", 16)) 0418
Generated by PyXR 0.9.4