From: Carlos Corbacho <carlos@strangeworlds.co.uk>
To: Ivo van Doorn <ivdoorn@gmail.com>
Cc: linux-input@vger.kernel.org, Dmitry Torokhov <dmitry.torokhov@gmail.com>
Subject: Re: rfkill-input understanding help
Date: Fri, 11 Jan 2008 03:23:37 +0000 [thread overview]
Message-ID: <200801110323.38279.carlos@strangeworlds.co.uk> (raw)
In-Reply-To: <200801022010.21109.IvDoorn@gmail.com>
Well, the good news is that the code I have appears to work. But, I have
something very strange going on with my kernel (latest ACPI git tree +
acer-wmi on top) and rfkill-input.
Basically, if I either:
1) Build rfkill-input into the kernel
or
2) Build rfkill-input as a module, and use kmod to load it from acer-wmi
Then rfkill-input doesn't work.
If I load rfkill-input manually (or if already loaded by kmod; unload and
then reload), everything works as expected. The (in progress) code to add
rfkill support to acer-wmi is here (in case the problem is something wrong
with the code) - as you can see, it's mostly based on the b43 work.
My kernel config is here, in case I'm missing something obvious:
http://files.strangeworlds.co.uk/config-acpi-git-20080111
For reference, the patch series that this ('acpi-wmi-rfkill') is part of
(of which only 'wmi' and 'acpi-wmi' are relevant) is here:
http://files.strangeworlds.co.uk/wmi/
-Carlos
---
acer-wmi: Add rfkill support
From: Carlos Corbacho <carlos@strangeworlds.co.uk>
Add initial rfkill support for acer-wmi
---
drivers/misc/acer-wmi.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 214 insertions(+), 1 deletions(-)
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index 6150120..5f6adc0 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -34,6 +34,9 @@
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/i8042.h>
+#include <linux/rfkill.h>
+#include <linux/input-polldev.h>
+#include <linux/kmod.h>
#include <acpi/acpi_drivers.h>
@@ -710,6 +713,213 @@ static void __init acer_commandline_init(void)
}
/*
+ * RF Kill devices
+ */
+struct acer_rfkill {
+ struct rfkill *wireless;
+ u32 wcap;
+ struct rfkill *bluetooth;
+ u32 bcap;
+};
+
+static struct acer_rfkill acer_rfk;
+
+struct acer_input {
+ struct input_polled_dev *wireless;
+ struct input_polled_dev *bluetooth;
+};
+
+static struct acer_input acer_poll;
+
+static void acer_rfkill_poll(struct input_polled_dev *poll_dev)
+{
+ struct rfkill *rfk = poll_dev->private;
+ u32 cap = *((u32 *) rfk->data);
+ u32 enabled, keycode, *state;
+
+ get_u32(&enabled, cap);
+
+ switch (cap) {
+ case ACER_CAP_WIRELESS:
+ keycode = KEY_WLAN;
+ state = &interface->data.wireless;
+ break;
+ case ACER_CAP_BLUETOOTH:
+ keycode = KEY_BLUETOOTH;
+ state = &interface->data.bluetooth;
+ break;
+ default:
+ return;
+ }
+
+ if (unlikely(enabled != *state)) {
+ printk(ACER_INFO "Radio state changed\n");
+ *state = enabled;
+ input_report_key(poll_dev->input, keycode, 1);
+ input_report_key(poll_dev->input, keycode, 0);
+ }
+}
+
+static int acer_rfkill_toggle(void *data, enum rfkill_state rfk_state)
+{
+ u32 cap = *((u32 *) data);
+ u32 *state;
+
+ printk(ACER_INFO "Setting cap for %u\n", cap);
+
+ switch (cap) {
+ case ACER_CAP_WIRELESS:
+ state = &interface->data.wireless;
+ break;
+ case ACER_CAP_BLUETOOTH:
+ state = &interface->data.bluetooth;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ switch (rfk_state) {
+ case RFKILL_STATE_ON:
+ printk(ACER_INFO "Turning on\n");
+ set_u32(1, cap);
+ *state = 1;
+ break;
+ case RFKILL_STATE_OFF:
+ printk(ACER_INFO "Turning off\n");
+ set_u32(0, cap);
+ *state = 0;
+ break;
+ }
+
+ return 0;
+}
+
+static int acer_rfkill_init_device(struct device **dev, struct rfkill **rfk_dev,
+struct input_polled_dev **rfk_poll_dev, u32 cap, u32 type, char *name)
+{
+ int err;
+ u32 *data;
+ u32 keycode = 0;
+ struct rfkill *rfk;
+ struct input_polled_dev *rfk_poll;
+
+ printk(ACER_INFO "Allocating rfkill device\n");
+ rfk = rfkill_allocate(*dev, type);
+ if (!rfk_dev)
+ goto error;
+
+ rfk->name = name;
+ rfk->state = RFKILL_STATE_ON;
+ rfk->toggle_radio = acer_rfkill_toggle;
+ data = kzalloc(sizeof(u32), GFP_KERNEL);
+ if (!data)
+ goto error_free_rfk;
+
+ *data = cap;
+ rfk->data = data;
+
+ printk(ACER_INFO "Allocating polled device\n");
+ rfk_poll = input_allocate_polled_device();
+ if (!rfk_poll)
+ goto error_free_rfk;
+
+ rfk_poll->private = rfk;
+ rfk_poll->poll = acer_rfkill_poll;
+ rfk_poll->poll_interval = 1000;
+
+ rfk_poll->input->name = rfk->name;
+ rfk_poll->input->id.bustype = BUS_HOST;
+ rfk_poll->input->evbit[0] = BIT(EV_KEY);
+
+ switch (cap) {
+ case ACER_CAP_WIRELESS:
+ keycode = KEY_WLAN;
+ break;
+ case ACER_CAP_BLUETOOTH:
+ keycode = KEY_BLUETOOTH;
+ break;
+ }
+ set_bit(keycode, rfk_poll->input->keybit);
+
+ printk(ACER_INFO "Registering rfkill device\n");
+ err = rfkill_register(rfk);
+ if (err)
+ goto error_free_polldev;
+
+ err = input_register_polled_device(rfk_poll);
+ if (err)
+ goto error_unreg_rfk;
+
+ *rfk_dev = rfk;
+ *rfk_poll_dev = rfk_poll;
+
+ return 0;
+
+error_unreg_rfk:
+ rfkill_unregister(*rfk_dev);
+error_free_polldev:
+ input_free_polled_device(*rfk_poll_dev);
+error_free_rfk:
+ kfree(data);
+ rfkill_free(*rfk_dev);
+error:
+ return -ENODEV;
+}
+
+static int acer_rfkill_init(struct device *dev)
+{
+ int err;
+
+ printk(ACER_INFO "Initialising RFKILL devices\n");
+
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ err = acer_rfkill_init_device(&dev, &acer_rfk.wireless,
+ &acer_poll.wireless, ACER_CAP_WIRELESS,
+ RFKILL_TYPE_WLAN, "acer-wireless");
+ if (err)
+ return -ENODEV;
+ }
+
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ err = acer_rfkill_init_device(&dev, &acer_rfk.bluetooth,
+ &acer_poll.bluetooth, ACER_CAP_BLUETOOTH,
+ RFKILL_TYPE_BLUETOOTH, "acer-bluetooth");
+ if (err)
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_RFKILL_INPUT_MODULE
+ /* acer-wmi RF-kill isn't useful without the rfkill-input subsystem.
+ * Try to load the module. */
+ err = request_module("rfkill-input");
+ if (err)
+ printk(ACER_INFO "Failed to load the rfkill-input module. "
+ "The built-in radio LED will not work.\n");
+#endif /* CONFIG_RFKILL_INPUT */
+
+ return 0;
+}
+
+static void acer_rfkill_exit_device(struct rfkill *rfk_dev,
+struct input_polled_dev *rfk_poll_dev)
+{
+ input_unregister_polled_device(rfk_poll_dev);
+ rfkill_unregister(rfk_dev);
+ input_free_polled_device(rfk_poll_dev);
+ kfree(rfk_dev->data);
+ rfkill_free(rfk_dev);
+}
+
+static void acer_rfkill_exit(void)
+{
+ if (has_cap(ACER_CAP_WIRELESS))
+ acer_rfkill_exit_device(acer_rfk.wireless, acer_poll.wireless);
+
+ if (has_cap(ACER_CAP_BLUETOOTH))
+ acer_rfkill_exit_device(acer_rfk.bluetooth, acer_poll.bluetooth);
+}
+
+/*
* LED device (Mail LED only, no other LEDs known yet)
*/
static void mail_led_set(struct led_classdev *led_cdev,
@@ -842,7 +1052,8 @@ static int __devinit acer_platform_probe(struct platform_device *device)
acer_led_init(&device->dev);
if (has_cap(ACER_CAP_BRIGHTNESS))
acer_backlight_init(&device->dev);
- return 0;
+
+ return acer_rfkill_init(&device->dev);
}
static int acer_platform_remove(struct platform_device *device)
@@ -851,6 +1062,8 @@ static int acer_platform_remove(struct platform_device *device)
acer_led_exit();
if (has_cap(ACER_CAP_BRIGHTNESS))
acer_backlight_exit();
+
+ acer_rfkill_exit();
return 0;
}
next prev parent reply other threads:[~2008-01-11 3:23 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-12-11 3:33 rfkill-input understanding help Carlos Corbacho
2007-12-30 18:59 ` Ivo van Doorn
2007-12-31 1:00 ` Carlos Corbacho
2008-01-02 19:10 ` Ivo van Doorn
2008-01-11 3:23 ` Carlos Corbacho [this message]
2008-01-11 19:08 ` Ivo van Doorn
2008-01-11 20:34 ` Dmitry Torokhov
2008-01-12 0:32 ` Carlos Corbacho
2008-01-22 0:55 ` Carlos Corbacho
2008-04-12 17:21 ` Carlos Corbacho
2008-04-13 11:23 ` Carlos Corbacho
2008-04-14 18:12 ` Dmitry Torokhov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200801110323.38279.carlos@strangeworlds.co.uk \
--to=carlos@strangeworlds.co.uk \
--cc=dmitry.torokhov@gmail.com \
--cc=ivdoorn@gmail.com \
--cc=linux-input@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).