2007-09-25 17:57:13 -07:00
/*
2008-02-03 15:42:53 +01:00
Copyright ( C ) 2004 - 2008 rt2x00 SourceForge Project
2007-09-25 17:57:13 -07:00
< http : //rt2x00.serialmonkey.com>
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 .
*/
/*
Module : rt2x00rfkill
Abstract : rt2x00 rfkill routines .
*/
# include <linux/input-polldev.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/rfkill.h>
# include "rt2x00.h"
# include "rt2x00lib.h"
static int rt2x00rfkill_toggle_radio ( void * data , enum rfkill_state state )
{
struct rt2x00_dev * rt2x00dev = data ;
int retval = 0 ;
if ( unlikely ( ! rt2x00dev ) )
return 0 ;
/*
2007-09-25 20:55:39 +02:00
* Only continue if there are enabled interfaces .
2007-09-25 17:57:13 -07:00
*/
2007-09-25 20:55:39 +02:00
if ( ! test_bit ( DEVICE_STARTED , & rt2x00dev - > flags ) )
2007-09-25 17:57:13 -07:00
return 0 ;
if ( state = = RFKILL_STATE_ON ) {
INFO ( rt2x00dev , " Hardware button pressed, enabling radio. \n " ) ;
2007-10-06 14:14:06 +02:00
__clear_bit ( DEVICE_DISABLED_RADIO_HW , & rt2x00dev - > flags ) ;
2007-09-25 17:57:13 -07:00
retval = rt2x00lib_enable_radio ( rt2x00dev ) ;
} else if ( state = = RFKILL_STATE_OFF ) {
INFO ( rt2x00dev , " Hardware button pressed, disabling radio. \n " ) ;
2007-10-06 14:14:06 +02:00
__set_bit ( DEVICE_DISABLED_RADIO_HW , & rt2x00dev - > flags ) ;
2007-09-25 17:57:13 -07:00
rt2x00lib_disable_radio ( rt2x00dev ) ;
}
return retval ;
}
static void rt2x00rfkill_poll ( struct input_polled_dev * poll_dev )
{
struct rt2x00_dev * rt2x00dev = poll_dev - > private ;
int state = rt2x00dev - > ops - > lib - > rfkill_poll ( rt2x00dev ) ;
2007-10-27 13:40:25 +02:00
if ( rt2x00dev - > rfkill - > state ! = state ) {
2007-09-25 17:57:13 -07:00
input_report_key ( poll_dev - > input , KEY_WLAN , 1 ) ;
2007-10-27 13:40:25 +02:00
input_report_key ( poll_dev - > input , KEY_WLAN , 0 ) ;
}
2007-09-25 17:57:13 -07:00
}
2008-03-13 15:38:03 +01:00
void rt2x00rfkill_register ( struct rt2x00_dev * rt2x00dev )
2007-09-25 17:57:13 -07:00
{
2008-03-13 15:38:03 +01:00
if ( ! test_bit ( CONFIG_SUPPORT_HW_BUTTON , & rt2x00dev - > flags ) | |
! test_bit ( RFKILL_STATE_ALLOCATED , & rt2x00dev - > rfkill_state ) )
return ;
2007-09-25 17:57:13 -07:00
2008-03-13 15:38:03 +01:00
if ( rfkill_register ( rt2x00dev - > rfkill ) ) {
2007-09-25 17:57:13 -07:00
ERROR ( rt2x00dev , " Failed to register rfkill handler. \n " ) ;
2008-03-13 15:38:03 +01:00
return ;
2007-09-25 17:57:13 -07:00
}
2008-03-13 15:38:03 +01:00
if ( input_register_polled_device ( rt2x00dev - > poll_dev ) ) {
2007-09-25 17:57:13 -07:00
ERROR ( rt2x00dev , " Failed to register polled device. \n " ) ;
rfkill_unregister ( rt2x00dev - > rfkill ) ;
2008-03-13 15:38:03 +01:00
return ;
2007-09-25 17:57:13 -07:00
}
2008-03-13 15:38:03 +01:00
__set_bit ( RFKILL_STATE_REGISTERED , & rt2x00dev - > rfkill_state ) ;
2007-10-27 13:40:51 +02:00
/*
* Force initial poll which will detect the initial device state ,
* and correctly sends the signal to the rfkill layer about this
* state .
*/
rt2x00rfkill_poll ( rt2x00dev - > poll_dev ) ;
2007-09-25 17:57:13 -07:00
}
void rt2x00rfkill_unregister ( struct rt2x00_dev * rt2x00dev )
{
2008-03-13 15:38:03 +01:00
if ( ! test_bit ( CONFIG_SUPPORT_HW_BUTTON , & rt2x00dev - > flags ) | |
! test_bit ( RFKILL_STATE_REGISTERED , & rt2x00dev - > rfkill_state ) )
2007-09-25 17:57:13 -07:00
return ;
input_unregister_polled_device ( rt2x00dev - > poll_dev ) ;
rfkill_unregister ( rt2x00dev - > rfkill ) ;
2008-03-13 15:38:03 +01:00
__clear_bit ( RFKILL_STATE_REGISTERED , & rt2x00dev - > rfkill_state ) ;
2007-09-25 17:57:13 -07:00
}
2008-03-13 15:38:03 +01:00
static struct input_polled_dev *
rt2x00rfkill_allocate_polldev ( struct rt2x00_dev * rt2x00dev )
2007-09-25 17:57:13 -07:00
{
2008-03-13 15:38:03 +01:00
struct input_polled_dev * poll_dev ;
poll_dev = input_allocate_polled_device ( ) ;
if ( ! poll_dev )
return NULL ;
poll_dev - > private = rt2x00dev ;
poll_dev - > poll = rt2x00rfkill_poll ;
poll_dev - > poll_interval = RFKILL_POLL_INTERVAL ;
poll_dev - > input - > name = rt2x00dev - > ops - > name ;
poll_dev - > input - > phys = wiphy_name ( rt2x00dev - > hw - > wiphy ) ;
poll_dev - > input - > id . bustype = BUS_HOST ;
poll_dev - > input - > id . vendor = 0x1814 ;
poll_dev - > input - > id . product = rt2x00dev - > chip . rt ;
poll_dev - > input - > id . version = rt2x00dev - > chip . rev ;
poll_dev - > input - > dev . parent = wiphy_dev ( rt2x00dev - > hw - > wiphy ) ;
poll_dev - > input - > evbit [ 0 ] = BIT ( EV_KEY ) ;
set_bit ( KEY_WLAN , poll_dev - > input - > keybit ) ;
return poll_dev ;
}
2007-09-25 17:57:13 -07:00
2008-03-13 15:38:03 +01:00
void rt2x00rfkill_allocate ( struct rt2x00_dev * rt2x00dev )
{
2007-09-25 20:55:39 +02:00
if ( ! test_bit ( CONFIG_SUPPORT_HW_BUTTON , & rt2x00dev - > flags ) )
2008-03-13 15:38:03 +01:00
return ;
2007-09-25 17:57:13 -07:00
2008-03-13 15:38:03 +01:00
rt2x00dev - > rfkill =
rfkill_allocate ( wiphy_dev ( rt2x00dev - > hw - > wiphy ) , RFKILL_TYPE_WLAN ) ;
2007-09-25 17:57:13 -07:00
if ( ! rt2x00dev - > rfkill ) {
ERROR ( rt2x00dev , " Failed to allocate rfkill handler. \n " ) ;
2008-03-13 15:38:03 +01:00
return ;
2007-09-25 17:57:13 -07:00
}
rt2x00dev - > rfkill - > name = rt2x00dev - > ops - > name ;
rt2x00dev - > rfkill - > data = rt2x00dev ;
2007-10-27 13:40:51 +02:00
rt2x00dev - > rfkill - > state = - 1 ;
2007-09-25 17:57:13 -07:00
rt2x00dev - > rfkill - > toggle_radio = rt2x00rfkill_toggle_radio ;
2008-03-13 15:38:03 +01:00
rt2x00dev - > poll_dev = rt2x00rfkill_allocate_polldev ( rt2x00dev ) ;
2007-09-25 17:57:13 -07:00
if ( ! rt2x00dev - > poll_dev ) {
ERROR ( rt2x00dev , " Failed to allocate polled device. \n " ) ;
2008-03-13 15:38:03 +01:00
rfkill_free ( rt2x00dev - > rfkill ) ;
rt2x00dev - > rfkill = NULL ;
return ;
2007-09-25 17:57:13 -07:00
}
2008-03-13 15:38:03 +01:00
return ;
}
2007-09-25 17:57:13 -07:00
2008-03-13 15:38:03 +01:00
void rt2x00rfkill_free ( struct rt2x00_dev * rt2x00dev )
{
if ( ! test_bit ( CONFIG_SUPPORT_HW_BUTTON , & rt2x00dev - > flags ) | |
! test_bit ( RFKILL_STATE_ALLOCATED , & rt2x00dev - > rfkill_state ) )
return ;
2007-10-27 13:40:25 +02:00
2008-03-13 15:38:03 +01:00
input_free_polled_device ( rt2x00dev - > poll_dev ) ;
rt2x00dev - > poll_dev = NULL ;
2007-10-27 13:40:25 +02:00
rfkill_free ( rt2x00dev - > rfkill ) ;
2008-03-13 15:38:03 +01:00
rt2x00dev - > rfkill = NULL ;
2007-09-25 17:57:13 -07:00
}
2008-03-13 15:38:03 +01:00
void rt2x00rfkill_suspend ( struct rt2x00_dev * rt2x00dev )
2007-09-25 17:57:13 -07:00
{
2008-03-13 15:38:03 +01:00
if ( ! test_bit ( CONFIG_SUPPORT_HW_BUTTON , & rt2x00dev - > flags ) | |
! test_bit ( RFKILL_STATE_ALLOCATED , & rt2x00dev - > rfkill_state ) )
2007-09-25 17:57:13 -07:00
return ;
input_free_polled_device ( rt2x00dev - > poll_dev ) ;
2008-03-13 15:38:03 +01:00
rt2x00dev - > poll_dev = NULL ;
}
void rt2x00rfkill_resume ( struct rt2x00_dev * rt2x00dev )
{
if ( ! test_bit ( CONFIG_SUPPORT_HW_BUTTON , & rt2x00dev - > flags ) | |
! test_bit ( RFKILL_STATE_ALLOCATED , & rt2x00dev - > rfkill_state ) )
return ;
rt2x00dev - > poll_dev = rt2x00rfkill_allocate_polldev ( rt2x00dev ) ;
if ( ! rt2x00dev - > poll_dev ) {
ERROR ( rt2x00dev , " Failed to allocate polled device. \n " ) ;
return ;
}
2007-09-25 17:57:13 -07:00
}