2021-01-16 12:56:05

by Markus Theil

[permalink] [raw]
Subject: [PATCH 0/4] Updates for rfkill

- Include older patch which updates rfkill.py to use Python 3 as
the Python patch is based on this change.
- Update rfkill.h to include hard block reasons.
- Include support for hard block reasons to rfkill userspace.

Markus Theil (4):
rfkill.py: migrate to python3
rfkill: update rfkill.h
rfkill: support hard block reason in python code
rfkill: support hard block reason in C code

rfkill.c | 19 +++++++++++---
rfkill.h | 18 ++++++++++++-
rfkill.py | 78 ++++++++++++++++++++++++++++++++++++++-----------------
3 files changed, 86 insertions(+), 29 deletions(-)

--
2.30.0


2021-01-16 17:07:28

by Markus Theil

[permalink] [raw]
Subject: [PATCH 2/4] rfkill: update rfkill.h

Signed-off-by: Markus Theil <[email protected]>
---
rfkill.h | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/rfkill.h b/rfkill.h
index 058757f..03e8af8 100644
--- a/rfkill.h
+++ b/rfkill.h
@@ -59,6 +59,8 @@ enum rfkill_type {
* @RFKILL_OP_DEL: a device was removed
* @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device
* @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all)
+ * into a state, also updating the default state used for devices that
+ * are hot-plugged later.
*/
enum rfkill_operation {
RFKILL_OP_ADD = 0,
@@ -67,6 +69,16 @@ enum rfkill_operation {
RFKILL_OP_CHANGE_ALL,
};

+/**
+ * enum rfkill_hard_block_reasons - hard block reasons
+ * @RFKILL_HARD_BLOCK_SIGNAL: the hardware rfkill signal is active
+ * @RFKILL_HARD_BLOCK_NOT_OWNER: the NIC is not owned by the host
+ */
+enum rfkill_hard_block_reasons {
+ RFKILL_HARD_BLOCK_SIGNAL = 1 << 0,
+ RFKILL_HARD_BLOCK_NOT_OWNER = 1 << 1,
+};
+
/**
* struct rfkill_event - events for userspace on /dev/rfkill
* @idx: index of dev rfkill
@@ -74,6 +86,8 @@ enum rfkill_operation {
* @op: operation code
* @hard: hard state (0/1)
* @soft: soft state (0/1)
+ * @hard_block_reasons: valid if hard is set. One or several reasons from
+ * &enum rfkill_hard_block_reasons.
*
* Structure used for userspace communication on /dev/rfkill,
* used for events from the kernel and control to the kernel.
@@ -82,7 +96,9 @@ struct rfkill_event {
__u32 idx;
__u8 type;
__u8 op;
- __u8 soft, hard;
+ __u8 soft;
+ __u8 hard;
+ __u8 hard_block_reasons;
} __attribute__((packed));

/*
--
2.30.0

2021-01-16 17:07:28

by Markus Theil

[permalink] [raw]
Subject: [PATCH 4/4] rfkill: support hard block reason in C code

Signed-off-by: Markus Theil <[email protected]>
---
rfkill.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/rfkill.c b/rfkill.c
index 8cd81fe..7fa5c39 100644
--- a/rfkill.c
+++ b/rfkill.c
@@ -51,15 +51,16 @@ static void rfkill_event(void)
break;
}

- if (len != RFKILL_EVENT_SIZE_V1) {
+ if (len != RFKILL_EVENT_SIZE_V1 && len != RFKILL_EVENT_SIZE_V1 + 1) {
fprintf(stderr, "Wrong size of RFKILL event\n");
continue;
}

gettimeofday(&tv, NULL);
- printf("%ld.%06u: idx %u type %u op %u soft %u hard %u\n",
+ printf("%ld.%06u: idx %u type %u op %u soft %u hard %u hard block reasons 0x%02x\n",
(long) tv.tv_sec, (unsigned int) tv.tv_usec,
- event.idx, event.type, event.op, event.soft, event.hard);
+ event.idx, event.type, event.op, event.soft, event.hard,
+ event.hard_block_reasons);
fflush(stdout);
}

@@ -214,7 +215,7 @@ static int rfkill_list(const char *param)
break;
}

- if (len != RFKILL_EVENT_SIZE_V1) {
+ if (len != RFKILL_EVENT_SIZE_V1 && len != RFKILL_EVENT_SIZE_V1 + 1) {
fprintf(stderr, "Wrong size of RFKILL event\n");
continue;
}
@@ -242,6 +243,16 @@ static int rfkill_list(const char *param)
type2string(event.type));
printf("\tSoft blocked: %s\n", event.soft ? "yes" : "no");
printf("\tHard blocked: %s\n", event.hard ? "yes" : "no");
+ if (len >= RFKILL_EVENT_SIZE_V1 + 1) {
+ printf("\tHard block reasons: ");
+ if (event.hard_block_reasons == 0)
+ printf("[NONE]");
+ if (event.hard_block_reasons & RFKILL_HARD_BLOCK_NOT_OWNER)
+ printf("[NOT_OWNER]");
+ if (event.hard_block_reasons & RFKILL_HARD_BLOCK_SIGNAL)
+ printf("[SIGNAL]");
+ printf("\n");
+ }
}

close(fd);
--
2.30.0

2021-01-16 17:07:28

by Markus Theil

[permalink] [raw]
Subject: [PATCH 1/4] rfkill.py: migrate to python3

Signed-off-by: Markus Theil <[email protected]>
---
rfkill.py | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/rfkill.py b/rfkill.py
index 57dcddc..983671f 100755
--- a/rfkill.py
+++ b/rfkill.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# rfkill control code
#
@@ -21,12 +21,12 @@ import os
TYPE_WWAN,
TYPE_GPS,
TYPE_FM,
- TYPE_NFC) = range(9)
+ TYPE_NFC) = list(range(9))

(_OP_ADD,
_OP_DEL,
_OP_CHANGE,
- _OP_CHANGE_ALL) = range(4)
+ _OP_CHANGE_ALL) = list(range(4))

_type_names = {
TYPE_ALL: "all",
@@ -84,7 +84,7 @@ class RFKill(object):
@property
def soft_blocked(self):
return self.blocked[0]
-
+
@soft_blocked.setter
def soft_blocked(self, block):
if block:
@@ -97,28 +97,28 @@ class RFKill(object):
return self.blocked[1]

def block(self):
- rfk = open('/dev/rfkill', 'w')
+ rfk = open('/dev/rfkill', 'wb')
s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 1, 0)
rfk.write(s)
rfk.close()

def unblock(self):
- rfk = open('/dev/rfkill', 'w')
+ rfk = open('/dev/rfkill', 'wb')
s = struct.pack(_event_struct, 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', 'w')
- print rfk
+ rfk = open('/dev/rfkill', 'wb')
+ print(rfk)
s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 1, 0)
rfk.write(s)
rfk.close()

@classmethod
def unblock_all(cls, t=TYPE_ALL):
- rfk = open('/dev/rfkill', 'w')
+ rfk = open('/dev/rfkill', 'wb')
s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 0, 0)
rfk.write(s)
rfk.close()
@@ -126,7 +126,7 @@ class RFKill(object):
@classmethod
def list(cls):
res = []
- rfk = open('/dev/rfkill', 'r')
+ rfk = open('/dev/rfkill', 'rb')
fd = rfk.fileno()
flgs = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, flgs | os.O_NONBLOCK)
@@ -141,10 +141,12 @@ class RFKill(object):
res.append((r, _s, _h))
except IOError:
break
+ except TypeError:
+ break
return res

if __name__ == "__main__":
for r, s, h 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")
+ 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"))
--
2.30.0

2021-01-16 17:07:28

by Markus Theil

[permalink] [raw]
Subject: [PATCH 3/4] rfkill: support hard block reason in python code

Signed-off-by: Markus Theil <[email protected]>
---
rfkill.py | 60 ++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 44 insertions(+), 16 deletions(-)

diff --git a/rfkill.py b/rfkill.py
index 983671f..57d21b0 100755
--- a/rfkill.py
+++ b/rfkill.py
@@ -28,6 +28,9 @@ import os
_OP_CHANGE,
_OP_CHANGE_ALL) = list(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_names = {
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 @@ class RFKill(object):
@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 @@ class RFKill(object):
@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")
@@ -97,48 +104,60 @@ class RFKill(object):
return self.blocked[1]

def block(self):
- rfk = open('/dev/rfkill', 'wb')
- s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 1, 0)
+ rfk = open('/dev/rfkill', 'wb', 0)
+ s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 1, 0, 0)
rfk.write(s)
rfk.close()

def unblock(self):
- rfk = open('/dev/rfkill', 'wb')
- s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 0, 0)
+ rfk = open('/dev/rfkill', 'wb', 0)
+ s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 0, 0, 0)
rfk.write(s)
rfk.close()

@classmethod
def block_all(cls, t=TYPE_ALL):
- rfk = open('/dev/rfkill', 'wb')
+ rfk = open('/dev/rfkill', 'wb', 0)
print(rfk)
- s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 1, 0)
+ s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 1, 0, 0)
rfk.write(s)
rfk.close()

@classmethod
def unblock_all(cls, t=TYPE_ALL):
- rfk = open('/dev/rfkill', 'wb')
- s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 0, 0)
+ rfk = open('/dev/rfkill', 'wb', 0)
+ s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 0, 0, 0)
rfk.write(s)
rfk.close()

@classmethod
def list(cls):
res = []
- rfk = open('/dev/rfkill', 'rb')
+ rfk = open('/dev/rfkill', 'rb', 0)
+
fd = rfk.fileno()
flgs = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, flgs | os.O_NONBLOCK)
while True:
try:
d = rfk.read(_event_sz)
- _idx, _t, _op, _s, _h = struct.unpack(_event_struct, d)
+ read_len = len(d)
+ assert read_len in [_event_sz, _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)
+ 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
except TypeError:
@@ -146,7 +165,16 @@ class RFKill(object):
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()
--
2.30.0

2021-01-21 12:29:21

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/4] Updates for rfkill

Hi Markus,

Thanks for the patches!

I separately committed a fix for the buffering=0 issue, just so it's
separate and not part of the other changes.

> rfkill.py: migrate to python3

Applied, but I made some cleanups.

> rfkill: update rfkill.h
> rfkill: support hard block reason in python code
> rfkill: support hard block reason in C code

This is broken, unfortunately. Updating rfkill.h as is causes issues
because we read more data than we are willing to accept, which you've
fixed up in the support for hard block reasons patch. Seems that should
partially be in the original patch - e.g. checking "size >= V1" instead
of "size == V1".

Additionally, the hard block reasons in C patch is wrong because if the
read was short, the field is not initialized. Need to clear the event to
zeroes before reading it, or at least at the beginnning (I guess we can
assume the kernel will not change size between two reads).

The python patch I applied with some fixups.

johannes