rfkill: support hard block reason in python code

Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
diff --git a/rfkill.py b/rfkill.py
index fe65e6a..2c9cdc6 100755
--- a/rfkill.py
+++ b/rfkill.py
@@ -28,6 +28,9 @@
  _OP_CHANGE,
  _OP_CHANGE_ALL) = range(4)
 
+HARD_BLOCK_SIGNAL = 1 << 0
+HARD_BLOCK_NOT_OWNER = 1 << 1
+
 _type_names = {
     TYPE_ALL: "all",
     TYPE_WLAN: "Wireless LAN",
@@ -40,10 +43,14 @@
     TYPE_NFC: "NFC",
 }
 
-# idx, type, op, soft, hard
-_event_struct = '@IBBBB'
+# idx, type, op, soft, hard, hard_block_reasons
+_event_struct = '@IBBBBB'
 _event_sz = struct.calcsize(_event_struct)
 
+# idx, type, op, soft, hard
+_event_struct_old = '@IBBBB'
+_event_old_sz = struct.calcsize(_event_struct_old)
+
 class RFKillException(Exception):
     pass
 
@@ -63,7 +70,7 @@
     @property
     def type(self):
         if not self._type:
-            for r, s, h in RFKill.list():
+            for r, s, h, hbr in RFKill.list():
                 if r.idx == self.idx:
                     self._type = r._type
                     break
@@ -76,7 +83,7 @@
     @property
     def blocked(self):
         l = RFKill.list()
-        for r, s, h in l:
+        for r, s, h, hbr in l:
             if r.idx == self.idx:
                 return (s, h)
         raise RFKillException("RFKill instance no longer exists")
@@ -98,27 +105,27 @@
 
     def block(self):
         rfk = open('/dev/rfkill', 'wb', buffering=0)
-        s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 1, 0)
+        s = struct.pack(_event_struct_old, self.idx, TYPE_ALL, _OP_CHANGE, 1, 0)
         rfk.write(s)
         rfk.close()
 
     def unblock(self):
         rfk = open('/dev/rfkill', 'wb', buffering=0)
-        s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 0, 0)
+        s = struct.pack(_event_struct_old, self.idx, TYPE_ALL, _OP_CHANGE, 0, 0)
         rfk.write(s)
         rfk.close()
 
     @classmethod
     def block_all(cls, t=TYPE_ALL):
         rfk = open('/dev/rfkill', 'wb', buffering=0)
-        s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 1, 0)
+        s = struct.pack(_event_struct_old, 0, t, _OP_CHANGE_ALL, 1, 0)
         rfk.write(s)
         rfk.close()
 
     @classmethod
     def unblock_all(cls, t=TYPE_ALL):
         rfk = open('/dev/rfkill', 'wb', buffering=0)
-        s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 0, 0)
+        s = struct.pack(_event_struct_old, 0, t, _OP_CHANGE_ALL, 0, 0)
         rfk.write(s)
         rfk.close()
 
@@ -134,18 +141,39 @@
                 d = rfk.read(_event_sz)
                 if d is None:
                     break
-                _idx, _t, _op, _s, _h = struct.unpack(_event_struct, d)
+                read_len = len(d)
+                assert read_len >= _event_old_sz
+
+                # init additional fields of newer formats to 'None' here
+                _hbr = None
+
+                # hard block reason included ?
+                if read_len >= _event_sz:
+                    _idx, _t, _op, _s, _h, _hbr = struct.unpack(_event_struct,
+                                                                d[:_event_sz])
+                else:
+                    _idx, _t, _op, _s, _h = struct.unpack(_event_struct_old, d)
+
                 if _op != _OP_ADD:
                     continue
                 r = RFKill(_idx)
                 r._type = _t
-                res.append((r, _s, _h))
+                res.append((r, _s, _h, _hbr))
             except IOError:
                 break
         return res
 
 if __name__ == "__main__":
-    for r, s, h in RFKill.list():
+    for r, s, h, hbr in RFKill.list():
         print("%d: %s: %s" % (r.idx, r.name, r.type_name))
         print("\tSoft blocked: %s" % ("yes" if s else "no"))
         print("\tHard blocked: %s" % ("yes" if h else "no"))
+        if hbr != None:
+            print("\tHard block reasons: ", end="")
+            if hbr == 0:
+                print("[NONE]", end="")
+            if hbr & HARD_BLOCK_NOT_OWNER:
+                print("[NOT_OWNER]", end="")
+            if hbr & HARD_BLOCK_SIGNAL:
+                print("[SIGNAL]", end="")
+            print()