Search Linux Wireless

Re: [PATCH 01/12] rfkill: clarify meaning of rfkill states

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 05 Jun 2008 10:46:47 -0400, "Dan Williams" <dcbw@xxxxxxxxxx> said:
> On Thu, 2008-06-05 at 10:03 -0300, Henrique de Moraes Holschuh wrote:
> > On Thu, 05 Jun 2008, Dan Williams wrote:
> > > a) hard switches that kill the radio and notify the driver
> > 
> > rfkill class material, yes.
> > 
> > > b) hard switches that notify the driver but do not directly kill the
> > > radio
> > 
> > These are input devices, and not directly related to the rfkill class
> > (but related to the rfkill subsystem).
> 
> So in your mind, these drivers would re-emit state changes of their
> rfkill switches back into the kernel input layer, correct?

Yes.  And the funny thing is, they are supposed not to ACT by themselves
at all, they are to wait for someone to tell them to through the rfkill class.

(NOTE: this applies only to scenario (b) above.  It is NOT valid for other
scenarios like (a) or (c) or any other).


To be more clear:

MODULE  FOO  (driver for the foo wireless device).
* Ties to the input layer, and reports pressure of the "hard switch that notify
the driver (MODULE FOO) but do not directly kill the radio (device foo)" using
the proper input event.

It does NOTHING further with the information that the button/switch was pressed.
Really.  It just generates the input event and sends it.

* Uses the rfkill class connected to the device foo in the device tree to receive
commands to toggle the real device rfkill state.

If some input event is indeed supposed to cause the device state to change, the
driver gets called back through the rfkill class toggle_radio() hook.

So, the button press would go through the input layer to SOMETHING ELSE (likely
to rfkill-input), which would take the **policy** decision of what to do with
that event, and then cause the appropriate rfkill class instances to change their
state.

So, MODULE FOO would get a hook call (toggle_radio) through the rfkill class, in
order to do something about the input event MODULE FOO itself generated.

Or it might not get that hook call, if the local admin wanted something different
to happen.

> > > c) hard switches that disconnect the device from its bus entirely (most
> > > BT rfkill)
> > 
> > These are also rfkill class material.
> > 
> > > d) hard switches that notify BIOS only (not the driver) and rely on
> > > special laptop drivers (hp-wmi, toshiba-laptop, etc) to notify the
> > > system
> > 
> > If they just notify the BIOS, they are input devices.  If they cause the
> > BIOS to mess with the transmitters, they are rfkill class material.
> 
> Obviously here, the laptop specific driver would re-emit the state
> change into the the kernel input layer since it is handled by a
> completely separate driver than the radio itself is handled by?

Correct.  The platform driver might actually also register notifier callbacks
on the rfkill subsystem, and, for example, automatically promote all b43
rfkill status changes into input events if this is the correct thing to
do for THAT specific platform (it is NOT the correct thing to do by
default, so b43 can't do it itself).

> > > e) keyboard "soft" switches that are simply input layer buttons (like Fn
> > > +F5 on thinkpads) and don't toggle
> > 
> > These are input devices in almost all cases.  But since you brought up
> > thinkpads, I better warn you that the Fn+F5 in a ThinkPad, depending on
> > thinkpad BIOS revision and ACPI HKEY mask state, *is* active and will
> > mess with the transmitters directly (and thus it is not an input
> > device).  thinkpad-acpi forces it to "just an input device" state by
> > default to keep things sane.
> > 
> > > Besides that, we can rfkill radios in software through commands like
> > > "iwconfig wlan0 txpower off".
> > 
> > Yeah.  This could be also rfkill material, if you want to have rfkill as
> > another *way* to interact with the same functionality.  It could cause
> > some minor issues (like which power do I set the transmitter to, if it
> > is turned off by txpower off, but someone undos that through rfkill?)
> > but it would work.
> 
> I want _one_ interface to get the radio block state (either blocked or
> unblocked) for any device that has a radio, be it WiFi, WiMAX, BT, WWAN,
> UWB, etc.

rfkill is supposed to be it, yes.

> I also want _one_ interface to determine how many rfkill switches the
> system has, and what their state is (either blocking radios or not
> blocking radios).  This is what the current rfkill system seems to
> provide.

It provides that information PARTIALLY.  Currently, you can enumerate
all rfkill interfaces through sysfs, and you can interact with each
one separately.  However, you cannot interact with the internal type-
specific global switches (which are NOT rfkill class) inside
rfkill-input.

I haven't solved that problem to my satisfaction yet, so the only patch
I have for it has not seen the light of the net.  It is too ugly to live
IMHO.

So, I'd say the individual rfkill class sysfs interface is nearly complete
(we need to add the third state or do something else to tell you when
a radio is blocked and cannot be unblocked).

But the rfkill subsystem interface (deals with rfkill-input) to userspace
is NOT feature-complete yet.   This really, really shouldn't bother NM,
it is HAL-layer level stuff.

> I don't want to have to use SIOCGIWTXPOW for wifi, something else for
> BT, something else for WWAN, something else for WiMAX, just to figure
> out whether a radio is blocked or unblocked.  That's just wrong but
> something that we can eventually fix.

Well, the problem is that SIOCGIWTXPOW is NOT a direct equivalent to rfkill,
rfkill has no concept of attenuation (or amplification, for that matter).

It is up for the wireless people to decide if their SIOCGIWTXPOW controls
are the same exposed by rfkill or not, and what to do when reenabling from
a txpower off (probably you will have to recall the last non-off txpower 
and use that).  The rfkill subsystem really doesn't care, as long as you
don't do it by adding more than one rfkill class to the same device.

> So, it seems I was confused about the scope of the current rfkill
> system.  While it probably should be "rfkill_switch" I'm not sure we can
> change that now.  While it would be nice to have a single interface to
> query radio power state, that can be a future improvement.

I think it is a better idea to fix what we have, first.  Let it settle
down, and then take the full view and check if you need to enhance it,
replace it, or design something else that goes along with it.  I'd bet on
the third option, but it is a bit early to tell.

> > > Only (a), (b), (c), and sometimes (d) actually kill the radio and block
> > > changes by the user.  Otherwise, it's up to userspace to kill the radios
> > > when events come in.
> > 
> > If it doesn't kill the radio, it is not rfkill class material.  At most,
> > it could be an input device that issues events related to rfkill.
> 
> Right, I misunderstood the original scope of the kernel rfkill stuff.  I
> thought it covered everything except case E (pure input-layer only
> buttons).

It sort of does, in the sense that rfkill (not the rfkill class!) defines
how the input layer should be used for these events.

> I'd like the rfkill system to eventually cover cases A - D, and also
> handle radio block state notifications and queries.  I'm willing to help
> code that.  Actual power levels of the radio is probably best left up to
> the device-specific subsystem, but at least the state (and events!) of
> "radio now blocked" or "radio now unblocked" are useful to have.

Unless I missed something, I have provided you with that for cases
A to D already.  What I didn't provide you with was "radio now blocked and
you cannot unblock it", *yet*.  You have convinced me it is something 
needed, and if left to my own devices, I will implement it as a third
state.

HOWEVER, rfkill can't provide you with "radio is enabled, configured, 
operational and transmitting" status.  It really can't say much of what
is happening in the unblocked state.

> > Currently we can't differentiate "block changes by the user" from "the
> > kernel can change the state if you ask it to".  I agree this is a
> > desireable feature, and I'd rather add a third rfkill_state to propagate
> > that information.
> 
> Well... I still think this is best as a _radio_ property, not as a
> killswitch property.  Physical switches are physical, you can't change
> the state and thus the third state here isn't useful.  If we separate
> switch state from radio power state that makes it clear (at least to
> me).

But then you have more than one "switch" per radio, which needs changes
to rfkill (currently, you are NOT to do it).

Currently, one is to think of a rfkill class as the representation of
the "radio property".  Which means you *lose the information* of which
underlying hardware/firmware reason the device has to be blocked.

I think we are actually better off by losing that information, it is
not useful for UIs (you need to know the device is force-blocked, not
WHY it is blocked or force-blocked -- that is highly platform-specific).

> Since the current rfkillX device is the _switch_, and since I'm not
> aware of any machines where the BIOS synthesizes a toggle state from a
> non-toggle button, maybe we should punt this until such a device
> actually turns up?

The current rfkillX device represents the radio state, which means it might
need to synthesize it from various hardware bits.

E.g.  Let's look at a possible conversion of IPW2200 to the rfkill class.

The IPW2200 driver has TWO rfkill "registers":
   R1 - Read/Write, controlled by the driver
   R2 - Read-Only, reflects an input pin in the hardware and cannot be
        overriden.

The IPW2000 driver would register just *one* instance of the rfkill class,
and it would return the status as this.

Assume R1 active high, and R2 active high.  Active means BLOCK RADIO.

  rfkill_status = (R1 | R2) ? RFKILL_STATUS_OFF : RFKILL_STATUS_ON.

I.e. if either one (or both) of the registers are blocking the radio, it
reports the status as RFKILL_STATUS_OFF.  Otherwise, it reports the status
as RFKILL_STATUS_ON (unblocked).

Now, for the toggle_radio function in pseudo-code:

  switch (new_state) {
   case RFKILL_STATUS_ON:
       if (R2) {
           R1 = 1; /* fail safe, least surprise */
           return -EPERM;  /* cannot override! */
       }
       R1 = 0;
       break;
   case RFKILL_STATUS_OFF:
       R1 = 1;
       break;
   }

There are possible variations, the most pressing one that comes to mind
is whether we should force the R1 switch to 1 or 0 when R2 is 1 on the
RFKILL_STATUS_ON branch.  I used the "won't EVER cause the radio to be
unblocked by surprise" alternative.

However, now userspace really gets to know if the ipw2200 radio is blocked or not,
it doesn't have to hunt down two different rfkill class instances for it.  And it
just needs to listen to uevents (which HAL should be taught to export to DBUS) for
ipw2200 to know when the status changes, no pooling or even reading of sysfs
attributes would be required.

If you wanted to also handle txpower off through rfkill, you'd take the state of
txpower into consideration on the code above, and still have only ONE rfkillX
instance for the ipw2200 device.

> > > The only thing I personally care about is separating radio state from
> > > switch state so that I can distinguish a softkill (via ex. iwconfig
> > > wlan0 txpower off) from a hardkill via a real killswitch.
> > 
> > Ok, so what you care about is to know if you COULD CHANGE THE STATE,
> > correct?
> 
> Could change the radio _block_ state, yes.  rfkill switch state no,

I mean the radio _block_ state.  See above.  One rfkill class per device,
synthesizing the state of n, n>=1 real switches.  So, you get the radio
block state from it.

> because I don't know of any examples of those and frankly I think it's
> easier to just make the user flip the switch again.  Keeping it simpler
> is better.

I'd agree with this view, least surprise is good, and the way the whole
rfkill idea was engineered to leave the transmitter BLOCKED in cause of
doubt.

> > The third state would tell you that.
> > 
> > > Why should a "device rfkill state" be in a separate module?  Radio state
> > > _is_ rfkill state.  rfkill switches turn the radio on or off but
> > 
> > device-wide rfkill state is rfkill state.  radio state could be
> > anything.
> 
> I started using "radio block state" in this mail instead.

Ok, radio block state is also good.  As long as we both know exactly
what we mean by it.

> > But yes, I understand what you want.  The two states you talk about are
> > the same if you have only ONE rfkill class attached to a device, and
> > they are different (but related) things when you have MORE than one
> > rfkill class attached to a device.
> 
> What situations would have more than one rfkill class attached to the
> device?

If you try to model IPW2200 or other hardware with many rfkill input signals
as one signal per rfkill class.  That's something that is probably NOT a good
idea at all.

> > IMO, we should attach just one rfkill class per transmitter device, and
> > handle the "you cannot change the state" possibility by adding a third
> > state to rfkill_state.
> 
> Right about the one rfkill class per device than drives a killswitch.
> But that's not necessarily the transmitter device.  It might be a child
> of the laptop module if it's a BIOS switch that also kills the radio
> automatically.  In the case of hp-wmi, it provides 3 different rfkill
> class devices.

Which is why I want to do it in a way we don't have to know what is a
child of what, slaved to what, master of what...

> > > devices should have _one_ method of turning themselves off through
> > > either hardware or software, and the system that provides that method
> > > should be the rfkill system.
> > 
> > We don't agree there.  If you use "devices should have _one_ method of
> > *forcing themselves off* outside of the normal control path of interface
> > up/down", THEN we agree.
> 
> Right, all devices with transmitters should have _one_ method of
> blocking and unblocking their transmitters.

OK.

> > The reason is extremely simple: rfkill CANNOT TURN SOMETHING ON.  If it
> > *was* ON, and you used rfkill to turn it OFF, than yes, when you "stop
> > turning it OFF through rfkill", it will go back to ON.
> > 
> > But if it was not ON in the first place, it won't go to ON when you stop
> > turning it OFF through rfkill.  It will just remain OFF, unless
> > something else that is NOT rfkill hooks into the event and takes the
> > oportunity to do whatever is needed (such as configure the interface and
> > bring it up) to bring the device to ON state.
> 
> Good point.

It is a very central point to rfkill, if you lose track of it, things get
very confusing, very very quickly.

> > > > Anyway, if we are to use various *related* rfkill switches per device,
> > > > rfkill needs further changes, including an extra callback into the
> > > > driver, so as to be able to export the device rfkill state also in all
> > > > switch rfkill state events (otherwise these events become quite useless
> > > > for many uses).
> > > 
> > > But yes, there would need to be a "device rfkill state" changed event
> > > and another call to get the device rfkill state.
> > 
> > Indeed.  It is a possiblity.  I still feel a third addition to
> > rfkill_state and the use of only ONE rfkill class per transmitter device
> > is a better way to do it.
> 
> As I said above, I think I disagree about the third state.  I think the
> best thing to do is keep the general rfkill switch operation as it is
> now (only 2 states, blocked and unblocked), and eventually add a
> standard "radio block state" sysfs entry on the _transmitter_ device
> with 3 values: hw-blocked, sw-blocked, and unblocked.

If we mandate the one-rfkill-class-per-transmitter rule, you now have two
attributes that say the very same thing, except that the old one (the one
we currently have) lacks the force-blocked state.  So basically, you just
avoided a minor ABI change by not adding the third state to rfkill_state.

If we mandate the one-rfkill-class-per-kill-line rule, you will add 
complexity, now a driver like IPW2200 would need at least two rfkill
class instances.   In THIS case, the new attribute conveys interesting
information, but OTOH, NM and any user application will have to deal
with more than one rfkill sysfs instance per device, and we will have
weird issues to deal with, like how to deal with user_claim...

The reason I insist on the third state so much is that rfkill *really*
was not designed to cope with two or more per transmitter.  You now
have to mess with various rfkill switches to get something to happen
(and most of the time, all but one will EPERM you, because they are
read-only, and my subconsious mind is severely screaming up this is
a BAD IDEA, we currently forbid read-only switches and I recall there
were some subtle issues with the input layer events for read-only
stuff).

> Does that sound OK?  I feel like I have a better understanding of what

It WOULD work, I think.  But for the reasons above, I am more inclined
to add a third state.  It is much simpler on the code, and it has no
drawbacks I can see, while the multiple rfkill per device approach does
have some (and it gives me a bad feeling every time I consider it).

What whould be the technical advantages of a separate attribute
from your UI (NM) point of view?  That is not yet clear to me, at
all.  Assume you will only get ONE rfkillX interface per device,
which means it DOES reflect the block/unblock state of the device.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux