+ def parse_serial_from_edid(self):
+ self.serial = None
+ if self.edid:
+ if self.EDID_UNAVAILABLE in self.edid:
+ return
+ if "*" in self.edid:
+ return
+ # Thx to pyedid project, the following code was
+ # copied (and modified) from pyedid/__init__py:21 [parse_edid()]
+ raw = bytes.fromhex(self.edid)
+ # Check EDID header, and checksum
+ if raw[:8] != b'\x00\xff\xff\xff\xff\xff\xff\x00' or sum(raw) % 256 != 0:
+ return
+ serial_no = int.from_bytes(raw[15:11:-1], byteorder='little')
+
+ serial_text = None
+ # Offsets of standard timing information descriptors 1-4
+ # (see https://en.wikipedia.org/wiki/Extended_Display_Identification_Data#EDID_1.4_data_format)
+ for timing_bytes in (raw[54:72], raw[72:90], raw[90:108], raw[108:126]):
+ if timing_bytes[0:2] == b'\x00\x00':
+ timing_type = timing_bytes[3]
+ if timing_type == 0xFF:
+ buffer = timing_bytes[5:]
+ buffer = buffer.partition(b'\x0a')[0]
+ serial_text = buffer.decode('cp437')
+ self.serial = serial_text if serial_text else "0x{:x}".format(serial_no) if serial_no != 0 else None
+