> > > The first parameter of strcat() must be big enough to contain the whole
> > > string.
> > 
> > Will replace it with
> > sprintf(wrqu->name, "radiobtn/", radiobtn->dev_name);
> 
> Or actually, I don't think the radiobtn/ won't be actually needed as prefix.
> The name passed to the radiobtn driver by the driver should be sufficient.

Updated version,

Signed-off-by Ivo van Doorn <[EMAIL PROTECTED]>

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 4bad588..212caad 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -79,4 +79,14 @@ config HP_SDC_RTC
          Say Y here if you want to support the built-in real time clock
          of the HP SDC controller.
 
+config RADIOBTN
+       tristate "Hardware radio button support"
+       help
+         Say Y here if you have an integrated WiFi or Bluetooth device
+         which contains an hardware button for enabling or disabling the radio.
+         When this driver is used, this driver will make sure the radio will
+         be correctly enabled and disabled when needed. It will then also
+         use the created input device to signal user space of this event
+         which allows userspace to take additional actions.
+
 endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 415c491..9af3d98 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_INPUT_UINPUT)            += uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)       += wistron_btns.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)      += ixp4xx-beeper.o
+obj-$(CONFIG_RADIOBTN)                 += radiobtn.o
\ No newline at end of file
diff --git a/drivers/input/misc/radiobtn.c b/drivers/input/misc/radiobtn.c
new file mode 100644
index 0000000..4379abe
--- /dev/null
+++ b/drivers/input/misc/radiobtn.c
@@ -0,0 +1,163 @@
+/*
+       Copyright (C) 2006 Ivo van Doorn
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the
+       Free Software Foundation, Inc.,
+       59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+       Radio hardware button support
+       Poll frequently all registered hardware for hardware button status,
+       if changed enabled or disable the radio of that hardware device.
+       Send signal to input device to inform userspace about the new status.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/radiobtn.h>
+
+MODULE_AUTHOR("Ivo van Doorn <[EMAIL PROTECTED]>");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("Radio hardware button support");
+MODULE_LICENSE("GPL");
+
+static void radiobtn_poll(unsigned long data)
+{
+       struct radio_button *radiobtn = (struct radio_button*)data;
+       int state;
+
+       /*
+        * Poll for the new state.
+        * Check if the state has changed.
+        */
+       state = !!radiobtn->button_poll(radiobtn->data);
+       if (state != radiobtn->current_state) {
+               radiobtn->current_state = state;
+
+               /*
+                * Enable or disable the radio when this
+                * should be done in software.
+                */
+               if (state && radiobtn->enable_radio)
+                       radiobtn->enable_radio(radiobtn->data);
+               else if (!state && radiobtn->disable_radio)
+                       radiobtn->disable_radio(radiobtn->data);
+
+               /*
+                * Report key event.
+                */
+               input_report_key(radiobtn->input_dev, KEY_RADIO, 1);
+               input_sync(radiobtn->input_dev);
+               input_report_key(radiobtn->input_dev, KEY_RADIO, 0);
+               input_sync(radiobtn->input_dev);
+       }
+
+       /*
+        * Check if polling has been disabled.
+        */
+       if (radiobtn->poll_delay != 0) {
+               radiobtn->poll_timer.expires =
+                       jiffies + msecs_to_jiffies(radiobtn->poll_delay);
+               add_timer(&radiobtn->poll_timer);
+       }
+}
+
+int radiobtn_register_device(struct radio_button *radiobtn)
+{
+       int status;
+
+       /*
+        * Check if all mandatory fields have been set.
+        */
+       if (radiobtn->poll_delay == 0 || radiobtn->button_poll == NULL)
+               return -EINVAL;
+
+       /*
+        * Allocate, initialize and register input device.
+        */
+       radiobtn->input_dev = input_allocate_device();
+       if (!radiobtn->input_dev) {
+               printk(KERN_ERR "Failed to allocate input device %s.\n",
+                       radiobtn->dev_name);
+               return -ENOMEM;
+       }
+
+       radiobtn->input_dev->name = "Radio button";
+       radiobtn->input_dev->phys = radiobtn->dev_name;
+       radiobtn->input_dev->id.bustype = BUS_HOST;
+       set_bit(KEY_RADIO, radiobtn->input_dev->keybit);
+
+       status = input_register_device(radiobtn->input_dev);
+       if (status) {
+               printk(KERN_ERR "Failed to register input device %s.\n",
+                       radiobtn->dev_name);
+               input_free_device(radiobtn->input_dev);
+               return status;
+       }
+
+       /*
+        * Set the initial state of the button.
+        */
+       radiobtn->current_state = radiobtn->button_poll(radiobtn->data);
+
+       /*
+        * Initialize timer.
+        */
+       init_timer(&radiobtn->poll_timer);
+       radiobtn->poll_timer.function = radiobtn_poll;
+       radiobtn->poll_timer.data = (unsigned long)radiobtn;
+       radiobtn->poll_timer.expires =
+               jiffies + msecs_to_jiffies(radiobtn->poll_delay);
+       add_timer(&radiobtn->poll_timer);
+
+       printk(KERN_INFO "Created new %s: %s.\n",
+               radiobtn->input_dev->name, radiobtn->input_dev->phys);
+
+       return 0;
+}
+
+void radiobtn_unregister_device(struct radio_button *radiobtn)
+{
+       /*
+        * Stop timer.
+        */
+       radiobtn->poll_delay = 0;
+       del_timer_sync(&radiobtn->poll_timer);
+
+       /*
+        * Remove input device.
+        */
+       input_unregister_device(radiobtn->input_dev);
+       input_free_device(radiobtn->input_dev);
+}
+
+static int __init radiobtn_init(void)
+{
+       printk(KERN_INFO "Loading radio button driver.\n");
+       return 0;
+}
+
+static void __exit radiobtn_exit(void)
+{
+       printk(KERN_INFO "Unloading radio button driver.\n");
+}
+
+EXPORT_SYMBOL(radiobtn_register_device);
+EXPORT_SYMBOL(radiobtn_unregister_device);
+
+module_init(radiobtn_init);
+module_exit(radiobtn_exit);
diff --git a/include/linux/radiobtn.h b/include/linux/radiobtn.h
new file mode 100644
index 0000000..3467606
--- /dev/null
+++ b/include/linux/radiobtn.h
@@ -0,0 +1,84 @@
+/*
+       Copyright (C) 2006 Ivo van Doorn
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the
+       Free Software Foundation, Inc.,
+       59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+       Radio hardware button support
+       Laptops are quite often equiped with support with a hardware button
+       to enabled and disable the radio of the integrated wireless network
+       or bluetooth interface.
+       Altough some devices will make sure that when pressed the radio
+       is disabled in hardware, other device depend on the software
+       to enabled or disable the radio accordingly.
+       This driver will create an input device and will poll registered
+       hardware frequently to listen if the button has been pressed.
+       When the device requires the software to disable or enable
+       the radio it will do so correctly, but it will also in all cases
+       send a signal to the input device to inform any listening daemon
+       the state has changed and will allow userspace to handle certain
+       tasks as well if required.
+ */
+
+#ifndef RADIOBTN_H
+#define RADIOBTN_H
+
+#include <linux/input.h>
+
+/**
+ * struct radio_button - radio hardware structure.
+ * @dev_name: Name of the interface. This will become the name
+ *     of the input device created in /dev/radio/.
+ * @data: Private data which will be passed along with the radio handlers.
+ * @button_poll(unsigned long data): Handler which will be called
+ *     with the poll_delay interval.
+ * @enable_radio(unsigned long data): Optional handler to enable the radio
+ *     once the button has been pressed when the hardware does not do this
+ *     automaticly.
+ * @disable_radio(unsigned long data): Optional handler to disable the radio
+ *     once the button has been pressed when the hardware does not do this
+ *     automaticly.
+ * @poll_delay: Delay in msecs between each poll.
+ * @current_state: Current state of the button.
+ *     (Should not be touched by driver)
+ * @input_dev: Pointer to input device for this radio button.
+ *     (Should not be touched by driver)
+ * @poll_timer: Timer used to poll for the button status.
+ *     (Should not be touched by driver)
+ */
+struct radio_button {
+       const char *dev_name;
+
+       unsigned long data;
+
+       int (*button_poll)(unsigned long data);
+       void (*enable_radio)(unsigned long data);
+       void (*disable_radio)(unsigned long data);
+
+       unsigned int poll_delay;
+
+       unsigned int current_state;
+
+       struct input_dev *input_dev;
+
+       struct timer_list poll_timer;
+};
+
+int radiobtn_register_device(struct radio_button *);
+void radiobtn_unregister_device(struct radio_button *);
+
+#endif /* RADIOBTN_H */

Attachment: pgpqZEAZXLdtn.pgp
Description: PGP signature

Reply via email to