docs: def decode_eventdata(sensor_type, offset, eventdata, sdr):
      """Decode extra event data from an alert or log
  
      Provide a textual summary of eventdata per descriptions in
      Table 42-3 of the specification.  This is for sensor specific
      offset events only.
  
      :param sensor_type: The sensor type number from the event
      :param offset:  Sensor specific offset
      :param eventdata: The three bytes from the log or alert
      """
      if sensor_type == 5 and offset == 4:  # link loss, indicates which port
          return 'Port {0}'.format(eventdata[1])
      elif sensor_type == 8 and offset == 6:  # PSU cfg error
          errtype = eventdata[2] & 0b1111
          return psucfg_errors.get(errtype, 'Unknown')
      elif sensor_type == 0xc and offset == 8:  # Memory spare
          return 'Module {0}'.format(eventdata[2])
      elif sensor_type == 0xf:
          if offset == 0:  # firmware error
              return firmware_errors.get(eventdata[1], 'Unknown')
          elif offset in (1, 2):
              return firmware_progress.get(eventdata[1], 'Unknown')
      elif sensor_type == 0x10:
          if offset == 0:  # Correctable error logging on a specific memory part
              return 'Module {0}'.format(eventdata[1])
          elif offset == 1:
              return 'Reading type {0:02X}h, offset {1:02X}h'.format(
                  eventdata[1], eventdata[2] & 0b1111)
          elif offset == 5:
              return '{0}%'.format(eventdata[2])
          elif offset == 6:
              return 'Processor {0}'.format(eventdata[1])
      elif sensor_type == 0x12:
          if offset == 3:
              action = (eventdata[1] & 0b1111000) >> 4
              return auxlog_actions.get(action, 'Unknown')
          elif offset == 4:
              sysactions = []
              if eventdata[1] & 0b1 << 5:
                  sysactions.append('NMI')
              if eventdata[1] & 0b1 << 4:
                  sysactions.append('OEM action')
              if eventdata[1] & 0b1 << 3:
                  sysactions.append('Power Cycle')
              if eventdata[1] & 0b1 << 2:
                  sysactions.append('Reset')
              if eventdata[1] & 0b1 << 1:
                  sysactions.append('Power Down')
              if eventdata[1] & 0b1:
                  sysactions.append('Alert')
              return ','.join(sysactions)
          elif offset == 5:  # Clock change event, either before or after
              if eventdata[1] & 0b10000000:
                  return 'After'
              else:
                  return 'Before'
      elif sensor_type == 0x19 and offset == 0:
          return 'Requested {0] while {1}'.format(eventdata[1], eventdata[2])
      elif sensor_type == 0x1d and offset == 7:
          return restart_causes.get(eventdata[1], 'Unknown')
      elif sensor_type == 0x21:
          return '{0} {1}'.format(slot_types.get(eventdata[1], 'Unknown'),
                                  eventdata[2])
  
      elif sensor_type == 0x23:
          phase = eventdata[1] & 0b1111
          return watchdog_boot_phases.get(phase, 'Unknown')
      elif sensor_type == 0x28:
          if offset == 4:
              return 'Sensor {0}'.format(eventdata[1])
          elif offset == 5:
              islogical = (eventdata[1] & 0b10000000)
              if islogical:
                  if eventdata[2] in sdr.fru:
                      return sdr.fru[eventdata[2]].fru_name
                  else:
                      return 'FRU {0}'.format(eventdata[2])
      elif sensor_type == 0x2a and offset == 3:
          return 'User {0}'.format(eventdata[1])
      elif sensor_type == 0x2b:
          return version_changes.get(eventdata[1], 'Unknown')
      elif sensor_type == 0x2c:
          cause = (eventdata[1] & 0b11110000) >> 4
          cause = fru_states.get(cause, 'Unknown')
          oldstate = eventdata[1] & 0b1111
          if oldstate != offset:
              try:
                  cause += '(change from {0})'.format(
                      ipmiconst.sensor_type_offsets[0x2c][oldstate]['desc'])
              except KeyError:
                  pass