2007-02-10 12:25:27 -02:00
# include <linux/module.h>
# include <linux/dcache.h>
# include <linux/debugfs.h>
# include <linux/delay.h>
# include <linux/mm.h>
2007-10-08 09:43:02 +02:00
# include <linux/string.h>
2007-02-10 12:25:27 -02:00
# include <net/iw_handler.h>
2007-05-25 00:37:28 -04:00
2007-02-10 12:25:27 -02:00
# include "dev.h"
# include "decl.h"
# include "host.h"
2007-05-10 23:08:05 -04:00
# include "debugfs.h"
2007-12-17 23:48:31 -05:00
# include "cmd.h"
2007-02-10 12:25:27 -02:00
2007-11-15 18:05:47 -05:00
static struct dentry * lbs_dir ;
2007-02-10 12:25:27 -02:00
static char * szStates [ ] = {
" Connected " ,
" Disconnected "
} ;
2007-05-25 00:37:28 -04:00
# ifdef PROC_DEBUG
2007-11-23 15:43:44 +01:00
static void lbs_debug_init ( struct lbs_private * priv , struct net_device * dev ) ;
2007-05-25 00:37:28 -04:00
# endif
2007-02-10 12:25:27 -02:00
static int open_file_generic ( struct inode * inode , struct file * file )
{
file - > private_data = inode - > i_private ;
return 0 ;
}
static ssize_t write_file_dummy ( struct file * file , const char __user * buf ,
size_t count , loff_t * ppos )
{
return - EINVAL ;
}
static const size_t len = PAGE_SIZE ;
2007-11-15 18:05:47 -05:00
static ssize_t lbs_dev_info ( struct file * file , char __user * userbuf ,
2007-02-10 12:25:27 -02:00
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
size_t pos = 0 ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
ssize_t res ;
pos + = snprintf ( buf + pos , len - pos , " state = %s \n " ,
2007-12-08 20:04:36 +00:00
szStates [ priv - > connect_status ] ) ;
2007-02-10 12:25:27 -02:00
pos + = snprintf ( buf + pos , len - pos , " region_code = %02x \n " ,
2007-12-08 20:04:36 +00:00
( u32 ) priv - > regioncode ) ;
2007-02-10 12:25:27 -02:00
res = simple_read_from_buffer ( userbuf , count , ppos , buf , pos ) ;
free_page ( addr ) ;
return res ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_getscantable ( struct file * file , char __user * userbuf ,
2007-02-10 12:25:27 -02:00
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
size_t pos = 0 ;
int numscansdone = 0 , res ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
2007-10-03 17:59:30 -07:00
DECLARE_MAC_BUF ( mac ) ;
2007-05-25 16:15:56 -04:00
struct bss_descriptor * iter_bss ;
2007-02-10 12:25:27 -02:00
pos + = snprintf ( buf + pos , len - pos ,
2007-08-02 13:12:45 -04:00
" # | ch | rssi | bssid | cap | Qual | SSID \n " ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 20:04:36 +00:00
mutex_lock ( & priv - > lock ) ;
list_for_each_entry ( iter_bss , & priv - > network_list , list ) {
2007-08-02 10:43:44 -04:00
u16 ibss = ( iter_bss - > capability & WLAN_CAPABILITY_IBSS ) ;
u16 privacy = ( iter_bss - > capability & WLAN_CAPABILITY_PRIVACY ) ;
u16 spectrum_mgmt = ( iter_bss - > capability & WLAN_CAPABILITY_SPECTRUM_MGMT ) ;
2007-02-10 12:25:27 -02:00
pos + = snprintf ( buf + pos , len - pos ,
2007-10-03 17:59:30 -07:00
" %02u| %03d | %04ld | %s | " ,
2007-05-25 16:15:56 -04:00
numscansdone , iter_bss - > channel , iter_bss - > rssi ,
2007-10-03 17:59:30 -07:00
print_mac ( mac , iter_bss - > bssid ) ) ;
2007-08-02 10:43:44 -04:00
pos + = snprintf ( buf + pos , len - pos , " %04x- " , iter_bss - > capability ) ;
2007-02-10 12:25:27 -02:00
pos + = snprintf ( buf + pos , len - pos , " %c%c%c | " ,
2007-08-02 10:43:44 -04:00
ibss ? ' A ' : ' I ' , privacy ? ' P ' : ' ' ,
spectrum_mgmt ? ' S ' : ' ' ) ;
2007-08-02 13:12:45 -04:00
pos + = snprintf ( buf + pos , len - pos , " %04d | " , SCAN_RSSI ( iter_bss - > rssi ) ) ;
2007-05-28 23:54:55 -04:00
pos + = snprintf ( buf + pos , len - pos , " %s \n " ,
escape_essid ( iter_bss - > ssid , iter_bss - > ssid_len ) ) ;
2007-02-10 12:25:27 -02:00
numscansdone + + ;
}
2007-12-08 20:04:36 +00:00
mutex_unlock ( & priv - > lock ) ;
2007-02-10 12:25:27 -02:00
res = simple_read_from_buffer ( userbuf , count , ppos , buf , pos ) ;
free_page ( addr ) ;
return res ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_sleepparams_write ( struct file * file ,
2007-02-10 12:25:27 -02:00
const char __user * user_buf , size_t count ,
loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-12-17 23:48:31 -05:00
ssize_t buf_size , ret ;
struct sleep_params sp ;
2007-02-10 12:25:27 -02:00
int p1 , p2 , p3 , p4 , p5 , p6 ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , user_buf , buf_size ) ) {
2007-12-17 23:48:31 -05:00
ret = - EFAULT ;
2007-02-10 12:25:27 -02:00
goto out_unlock ;
}
2007-12-17 23:48:31 -05:00
ret = sscanf ( buf , " %d %d %d %d %d %d " , & p1 , & p2 , & p3 , & p4 , & p5 , & p6 ) ;
if ( ret ! = 6 ) {
ret = - EINVAL ;
2007-02-10 12:25:27 -02:00
goto out_unlock ;
}
2007-12-17 23:48:31 -05:00
sp . sp_error = p1 ;
sp . sp_offset = p2 ;
sp . sp_stabletime = p3 ;
sp . sp_calcontrol = p4 ;
sp . sp_extsleepclk = p5 ;
sp . sp_reserved = p6 ;
ret = lbs_cmd_802_11_sleep_params ( priv , CMD_ACT_SET , & sp ) ;
if ( ! ret )
ret = count ;
else if ( ret > 0 )
ret = - EINVAL ;
2007-02-10 12:25:27 -02:00
out_unlock :
free_page ( addr ) ;
2007-12-17 23:48:31 -05:00
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_sleepparams_read ( struct file * file , char __user * userbuf ,
2007-02-10 12:25:27 -02:00
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-12-17 23:48:31 -05:00
ssize_t ret ;
2007-02-10 12:25:27 -02:00
size_t pos = 0 ;
2007-12-17 23:48:31 -05:00
struct sleep_params sp ;
2007-02-10 12:25:27 -02:00
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
2007-12-17 23:48:31 -05:00
ret = lbs_cmd_802_11_sleep_params ( priv , CMD_ACT_GET , & sp ) ;
if ( ret )
2007-02-10 12:25:27 -02:00
goto out_unlock ;
2007-12-17 23:48:31 -05:00
pos + = snprintf ( buf , len , " %d %d %d %d %d %d \n " , sp . sp_error ,
sp . sp_offset , sp . sp_stabletime ,
sp . sp_calcontrol , sp . sp_extsleepclk ,
sp . sp_reserved ) ;
2007-02-10 12:25:27 -02:00
2007-12-17 23:48:31 -05:00
ret = simple_read_from_buffer ( userbuf , count , ppos , buf , pos ) ;
2007-02-10 12:25:27 -02:00
out_unlock :
free_page ( addr ) ;
2007-12-17 23:48:31 -05:00
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_extscan ( struct file * file , const char __user * userbuf ,
2007-02-10 12:25:27 -02:00
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
ssize_t res , buf_size ;
union iwreq_data wrqu ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
res = - EFAULT ;
goto out_unlock ;
}
2007-11-15 18:05:47 -05:00
lbs_send_specific_ssid_scan ( priv , buf , strlen ( buf ) - 1 , 0 ) ;
2007-02-10 12:25:27 -02:00
memset ( & wrqu , 0 , sizeof ( union iwreq_data ) ) ;
2007-05-25 13:05:16 -04:00
wireless_send_event ( priv - > dev , SIOCGIWSCAN , & wrqu , NULL ) ;
2007-02-10 12:25:27 -02:00
out_unlock :
free_page ( addr ) ;
return count ;
}
2007-11-15 18:05:47 -05:00
static void lbs_parse_bssid ( char * buf , size_t count ,
struct lbs_ioctl_user_scan_cfg * scan_cfg )
2007-02-10 12:25:27 -02:00
{
char * hold ;
unsigned int mac [ ETH_ALEN ] ;
hold = strstr ( buf , " bssid= " ) ;
if ( ! hold )
return ;
hold + = 6 ;
2007-12-27 16:43:38 -08:00
sscanf ( hold , " %02x:%02x:%02x:%02x:%02x:%02x " ,
mac , mac + 1 , mac + 2 , mac + 3 , mac + 4 , mac + 5 ) ;
2007-05-25 16:25:21 -04:00
memcpy ( scan_cfg - > bssid , mac , ETH_ALEN ) ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static void lbs_parse_ssid ( char * buf , size_t count ,
struct lbs_ioctl_user_scan_cfg * scan_cfg )
2007-02-10 12:25:27 -02:00
{
char * hold , * end ;
ssize_t size ;
hold = strstr ( buf , " ssid= " ) ;
if ( ! hold )
return ;
hold + = 5 ;
2007-10-08 09:43:02 +02:00
end = strchr ( hold , ' ' ) ;
2007-02-10 12:25:27 -02:00
if ( ! end )
end = buf + count - 1 ;
2007-05-10 23:10:18 -04:00
size = min ( ( size_t ) IW_ESSID_MAX_SIZE , ( size_t ) ( end - hold ) ) ;
2007-05-25 16:25:21 -04:00
strncpy ( scan_cfg - > ssid , hold , size ) ;
2007-02-10 12:25:27 -02:00
return ;
}
2007-11-15 18:05:47 -05:00
static int lbs_parse_clear ( char * buf , size_t count , const char * tag )
2007-02-10 12:25:27 -02:00
{
char * hold ;
int val ;
2007-05-25 16:25:21 -04:00
hold = strstr ( buf , tag ) ;
2007-02-10 12:25:27 -02:00
if ( ! hold )
2007-05-25 16:25:21 -04:00
return 0 ;
hold + = strlen ( tag ) ;
2007-02-10 12:25:27 -02:00
sscanf ( hold , " %d " , & val ) ;
if ( val ! = 0 )
val = 1 ;
2007-05-25 16:25:21 -04:00
return val ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static int lbs_parse_dur ( char * buf , size_t count ,
struct lbs_ioctl_user_scan_cfg * scan_cfg )
2007-02-10 12:25:27 -02:00
{
char * hold ;
int val ;
hold = strstr ( buf , " dur= " ) ;
if ( ! hold )
return 0 ;
hold + = 4 ;
sscanf ( hold , " %d " , & val ) ;
return val ;
}
2007-11-15 18:05:47 -05:00
static void lbs_parse_type ( char * buf , size_t count ,
struct lbs_ioctl_user_scan_cfg * scan_cfg )
2007-02-10 12:25:27 -02:00
{
char * hold ;
int val ;
hold = strstr ( buf , " type= " ) ;
if ( ! hold )
return ;
hold + = 5 ;
sscanf ( hold , " %d " , & val ) ;
/* type=1,2 or 3 */
if ( val < 1 | | val > 3 )
return ;
scan_cfg - > bsstype = val ;
return ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_setuserscan ( struct file * file ,
2007-02-10 12:25:27 -02:00
const char __user * userbuf ,
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
ssize_t res , buf_size ;
2007-11-15 18:05:47 -05:00
struct lbs_ioctl_user_scan_cfg * scan_cfg ;
2007-02-10 12:25:27 -02:00
union iwreq_data wrqu ;
int dur ;
2007-12-08 00:23:55 +00:00
char * buf = ( char * ) get_zeroed_page ( GFP_KERNEL ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 00:23:55 +00:00
if ( ! buf )
2007-02-10 12:25:27 -02:00
return - ENOMEM ;
2007-12-14 22:53:41 -05:00
2007-02-10 12:25:27 -02:00
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
res = - EFAULT ;
2007-12-08 00:23:55 +00:00
goto out_buf ;
2007-02-10 12:25:27 -02:00
}
2007-12-08 00:23:55 +00:00
scan_cfg = kzalloc ( sizeof ( struct lbs_ioctl_user_scan_cfg ) , GFP_KERNEL ) ;
if ( ! scan_cfg ) {
res = - ENOMEM ;
goto out_buf ;
}
res = count ;
2007-11-15 18:05:47 -05:00
scan_cfg - > bsstype = LBS_SCAN_BSS_TYPE_ANY ;
2007-02-10 12:25:27 -02:00
2007-11-15 18:05:47 -05:00
dur = lbs_parse_dur ( buf , count , scan_cfg ) ;
lbs_parse_bssid ( buf , count , scan_cfg ) ;
scan_cfg - > clear_bssid = lbs_parse_clear ( buf , count , " clear_bssid= " ) ;
lbs_parse_ssid ( buf , count , scan_cfg ) ;
scan_cfg - > clear_ssid = lbs_parse_clear ( buf , count , " clear_ssid= " ) ;
lbs_parse_type ( buf , count , scan_cfg ) ;
2007-02-10 12:25:27 -02:00
2007-11-15 18:05:47 -05:00
lbs_scan_networks ( priv , scan_cfg , 1 ) ;
2007-12-08 20:04:36 +00:00
wait_event_interruptible ( priv - > cmd_pending ,
2007-12-09 11:08:25 -05:00
priv - > surpriseremoved | | ! priv - > last_scanned_channel ) ;
2007-12-08 00:23:55 +00:00
2007-12-08 20:04:36 +00:00
if ( priv - > surpriseremoved )
2007-12-08 00:23:55 +00:00
goto out_scan_cfg ;
2007-02-10 12:25:27 -02:00
memset ( & wrqu , 0x00 , sizeof ( union iwreq_data ) ) ;
2007-05-25 13:05:16 -04:00
wireless_send_event ( priv - > dev , SIOCGIWSCAN , & wrqu , NULL ) ;
2007-02-10 12:25:27 -02:00
2007-12-08 00:23:55 +00:00
out_scan_cfg :
2007-02-10 12:25:27 -02:00
kfree ( scan_cfg ) ;
2007-12-08 00:23:55 +00:00
out_buf :
free_page ( ( unsigned long ) buf ) ;
return res ;
2007-02-10 12:25:27 -02:00
}
2007-11-26 10:07:14 +01:00
/*
* When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET , me might
* get a bunch of vendor - specific TLVs ( a . k . a . IEs ) back from the
* firmware . Here ' s an example :
* 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
* 00 00 07 01 02 00 3 c 00 00 00 00 00 00 00 03 03
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
* The 04 01 is the TLV type ( here TLV_TYPE_RSSI_LOW ) , 02 00 is the length ,
* 00 00 are the data bytes of this TLV . For this TLV , their meaning is
* defined in mrvlietypes_thresholds
*
* This function searches in this TLV data chunk for a given TLV type
* and returns a pointer to the first data byte of the TLV , or to NULL
* if the TLV hasn ' t been found .
*/
2007-12-18 02:01:37 -05:00
static void * lbs_tlv_find ( uint16_t tlv_type , const uint8_t * tlv , uint16_t size )
2007-02-10 12:25:27 -02:00
{
2007-11-26 10:07:14 +01:00
struct mrvlietypesheader * tlv_h ;
2007-12-18 02:01:37 -05:00
uint16_t length ;
ssize_t pos = 0 ;
2007-11-26 10:07:14 +01:00
while ( pos < size ) {
tlv_h = ( struct mrvlietypesheader * ) tlv ;
2007-12-18 02:01:37 -05:00
if ( ! tlv_h - > len )
2007-11-26 10:07:14 +01:00
return NULL ;
2007-12-18 02:01:37 -05:00
if ( tlv_h - > type = = cpu_to_le16 ( tlv_type ) )
return tlv_h ;
length = le16_to_cpu ( tlv_h - > len ) + sizeof ( * tlv_h ) ;
2007-11-26 10:07:14 +01:00
pos + = length ;
tlv + = length ;
}
return NULL ;
2007-02-10 12:25:27 -02:00
}
2007-11-26 10:07:14 +01:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_threshold_read ( uint16_t tlv_type , uint16_t event_mask ,
struct file * file , char __user * userbuf ,
size_t count , loff_t * ppos )
2007-02-10 12:25:27 -02:00
{
2007-12-18 02:01:37 -05:00
struct cmd_ds_802_11_subscribe_event * subscribed ;
struct mrvlietypes_thresholds * got ;
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-12-18 02:01:37 -05:00
ssize_t ret = 0 ;
2007-11-26 10:07:14 +01:00
size_t pos = 0 ;
2007-12-18 02:01:37 -05:00
char * buf ;
2007-11-26 10:07:14 +01:00
u8 value ;
u8 freq ;
2007-12-10 12:19:55 +01:00
int events = 0 ;
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
buf = ( char * ) get_zeroed_page ( GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
subscribed = kzalloc ( sizeof ( * subscribed ) , GFP_KERNEL ) ;
if ( ! subscribed ) {
ret = - ENOMEM ;
goto out_page ;
2007-02-10 12:25:27 -02:00
}
2007-12-18 02:01:37 -05:00
subscribed - > hdr . size = cpu_to_le16 ( sizeof ( * subscribed ) ) ;
subscribed - > action = cpu_to_le16 ( CMD_ACT_GET ) ;
ret = lbs_cmd_with_response ( priv , CMD_802_11_SUBSCRIBE_EVENT , subscribed ) ;
if ( ret )
goto out_cmd ;
2007-12-10 12:19:55 +01:00
got = lbs_tlv_find ( tlv_type , subscribed - > tlv , sizeof ( subscribed - > tlv ) ) ;
2007-11-26 10:07:14 +01:00
if ( got ) {
value = got - > value ;
freq = got - > freq ;
2007-12-10 12:19:55 +01:00
events = le16_to_cpu ( subscribed - > events ) ;
2007-02-10 12:25:27 -02:00
2007-11-26 10:07:14 +01:00
pos + = snprintf ( buf , len , " %d %d %d \n " , value , freq ,
2007-12-18 02:01:37 -05:00
! ! ( events & event_mask ) ) ;
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
ret = simple_read_from_buffer ( userbuf , count , ppos , buf , pos ) ;
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
out_cmd :
kfree ( subscribed ) ;
out_page :
free_page ( ( unsigned long ) buf ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-12-18 02:01:37 -05:00
static ssize_t lbs_threshold_write ( uint16_t tlv_type , uint16_t event_mask ,
struct file * file ,
const char __user * userbuf , size_t count ,
loff_t * ppos )
2007-02-10 12:25:27 -02:00
{
2007-11-26 10:07:14 +01:00
struct cmd_ds_802_11_subscribe_event * events ;
2007-12-18 02:01:37 -05:00
struct mrvlietypes_thresholds * tlv ;
struct lbs_private * priv = file - > private_data ;
ssize_t buf_size ;
int value , freq , new_mask ;
uint16_t curr_mask ;
char * buf ;
int ret ;
buf = ( char * ) get_zeroed_page ( GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
2007-02-10 12:25:27 -02:00
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
2007-12-18 02:01:37 -05:00
ret = - EFAULT ;
goto out_page ;
2007-02-10 12:25:27 -02:00
}
2007-12-18 02:01:37 -05:00
ret = sscanf ( buf , " %d %d %d " , & value , & freq , & new_mask ) ;
if ( ret ! = 3 ) {
ret = - EINVAL ;
goto out_page ;
}
events = kzalloc ( sizeof ( * events ) , GFP_KERNEL ) ;
if ( ! events ) {
ret = - ENOMEM ;
goto out_page ;
2007-02-10 12:25:27 -02:00
}
2007-12-18 02:01:37 -05:00
events - > hdr . size = cpu_to_le16 ( sizeof ( * events ) ) ;
events - > action = cpu_to_le16 ( CMD_ACT_GET ) ;
ret = lbs_cmd_with_response ( priv , CMD_802_11_SUBSCRIBE_EVENT , events ) ;
if ( ret )
goto out_events ;
curr_mask = le16_to_cpu ( events - > events ) ;
2007-02-10 12:25:27 -02:00
2007-11-26 10:07:14 +01:00
if ( new_mask )
new_mask = curr_mask | event_mask ;
else
new_mask = curr_mask & ~ event_mask ;
/* Now everything is set and we can send stuff down to the firmware */
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
tlv = ( void * ) events - > tlv ;
events - > action = cpu_to_le16 ( CMD_ACT_SET ) ;
events - > events = cpu_to_le16 ( new_mask ) ;
tlv - > header . type = cpu_to_le16 ( tlv_type ) ;
tlv - > header . len = cpu_to_le16 ( sizeof ( * tlv ) - sizeof ( tlv - > header ) ) ;
tlv - > value = value ;
if ( tlv_type ! = TLV_TYPE_BCNMISS )
tlv - > freq = freq ;
/* The command header, the event mask, and the one TLV */
events - > hdr . size = cpu_to_le16 ( sizeof ( events - > hdr ) + 2 + sizeof ( * tlv ) ) ;
ret = lbs_cmd_with_response ( priv , CMD_802_11_SUBSCRIBE_EVENT , events ) ;
if ( ! ret )
ret = count ;
out_events :
kfree ( events ) ;
out_page :
free_page ( ( unsigned long ) buf ) ;
return ret ;
2007-02-10 12:25:27 -02:00
}
2007-12-18 02:01:37 -05:00
static ssize_t lbs_lowrssi_read ( struct file * file , char __user * userbuf ,
size_t count , loff_t * ppos )
2007-02-10 12:25:27 -02:00
{
2007-11-26 10:07:14 +01:00
return lbs_threshold_read ( TLV_TYPE_RSSI_LOW , CMD_SUBSCRIBE_RSSI_LOW ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-18 02:01:37 -05:00
static ssize_t lbs_lowrssi_write ( struct file * file , const char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_write ( TLV_TYPE_RSSI_LOW , CMD_SUBSCRIBE_RSSI_LOW ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-11-26 10:07:14 +01:00
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_lowsnr_read ( struct file * file , char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_read ( TLV_TYPE_SNR_LOW , CMD_SUBSCRIBE_SNR_LOW ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-11-26 10:07:14 +01:00
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_lowsnr_write ( struct file * file , const char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_write ( TLV_TYPE_SNR_LOW , CMD_SUBSCRIBE_SNR_LOW ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-11-26 10:07:14 +01:00
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_failcount_read ( struct file * file , char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_read ( TLV_TYPE_FAILCOUNT , CMD_SUBSCRIBE_FAILCOUNT ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-11-26 10:07:14 +01:00
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_failcount_write ( struct file * file , const char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_write ( TLV_TYPE_FAILCOUNT , CMD_SUBSCRIBE_FAILCOUNT ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-02-10 12:25:27 -02:00
}
2007-11-26 10:07:14 +01:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_highrssi_read ( struct file * file , char __user * userbuf ,
size_t count , loff_t * ppos )
2007-02-10 12:25:27 -02:00
{
2007-11-26 10:07:14 +01:00
return lbs_threshold_read ( TLV_TYPE_RSSI_HIGH , CMD_SUBSCRIBE_RSSI_HIGH ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-11-26 10:07:14 +01:00
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_highrssi_write ( struct file * file , const char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_write ( TLV_TYPE_RSSI_HIGH , CMD_SUBSCRIBE_RSSI_HIGH ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-11-26 10:07:14 +01:00
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_highsnr_read ( struct file * file , char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_read ( TLV_TYPE_SNR_HIGH , CMD_SUBSCRIBE_SNR_HIGH ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-11-26 10:07:14 +01:00
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_highsnr_write ( struct file * file , const char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_write ( TLV_TYPE_SNR_HIGH , CMD_SUBSCRIBE_SNR_HIGH ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-02-10 12:25:27 -02:00
}
2007-12-18 02:01:37 -05:00
static ssize_t lbs_bcnmiss_read ( struct file * file , char __user * userbuf ,
size_t count , loff_t * ppos )
2007-02-10 12:25:27 -02:00
{
2007-11-26 10:07:14 +01:00
return lbs_threshold_read ( TLV_TYPE_BCNMISS , CMD_SUBSCRIBE_BCNMISS ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-11-26 10:07:14 +01:00
}
2007-02-10 12:25:27 -02:00
2007-12-18 02:01:37 -05:00
static ssize_t lbs_bcnmiss_write ( struct file * file , const char __user * userbuf ,
size_t count , loff_t * ppos )
2007-11-26 10:07:14 +01:00
{
return lbs_threshold_write ( TLV_TYPE_BCNMISS , CMD_SUBSCRIBE_BCNMISS ,
2007-12-18 02:01:37 -05:00
file , userbuf , count , ppos ) ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_rdmac_read ( struct file * file , char __user * userbuf ,
2007-02-10 12:25:27 -02:00
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-11-15 18:05:47 -05:00
struct lbs_offset_value offval ;
2007-02-10 12:25:27 -02:00
ssize_t pos = 0 ;
int ret ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
offval . offset = priv - > mac_offset ;
offval . value = 0 ;
2007-11-15 18:05:47 -05:00
ret = lbs_prepare_and_send_command ( priv ,
2007-08-02 11:31:18 -04:00
CMD_MAC_REG_ACCESS , 0 ,
CMD_OPTION_WAITFORRSP , 0 , & offval ) ;
2007-02-10 12:25:27 -02:00
mdelay ( 10 ) ;
pos + = snprintf ( buf + pos , len - pos , " MAC[0x%x] = 0x%08x \n " ,
2007-12-08 20:04:36 +00:00
priv - > mac_offset , priv - > offsetvalue . value ) ;
2007-02-10 12:25:27 -02:00
ret = simple_read_from_buffer ( userbuf , count , ppos , buf , pos ) ;
free_page ( addr ) ;
return ret ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_rdmac_write ( struct file * file ,
2007-02-10 12:25:27 -02:00
const char __user * userbuf ,
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
ssize_t res , buf_size ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
res = - EFAULT ;
goto out_unlock ;
}
priv - > mac_offset = simple_strtoul ( ( char * ) buf , NULL , 16 ) ;
res = count ;
out_unlock :
free_page ( addr ) ;
return res ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_wrmac_write ( struct file * file ,
2007-02-10 12:25:27 -02:00
const char __user * userbuf ,
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
ssize_t res , buf_size ;
u32 offset , value ;
2007-11-15 18:05:47 -05:00
struct lbs_offset_value offval ;
2007-02-10 12:25:27 -02:00
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
res = - EFAULT ;
goto out_unlock ;
}
res = sscanf ( buf , " %x %x " , & offset , & value ) ;
if ( res ! = 2 ) {
res = - EFAULT ;
goto out_unlock ;
}
offval . offset = offset ;
offval . value = value ;
2007-11-15 18:05:47 -05:00
res = lbs_prepare_and_send_command ( priv ,
2007-08-02 11:31:18 -04:00
CMD_MAC_REG_ACCESS , 1 ,
CMD_OPTION_WAITFORRSP , 0 , & offval ) ;
2007-02-10 12:25:27 -02:00
mdelay ( 10 ) ;
res = count ;
out_unlock :
free_page ( addr ) ;
return res ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_rdbbp_read ( struct file * file , char __user * userbuf ,
2007-02-10 12:25:27 -02:00
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-11-15 18:05:47 -05:00
struct lbs_offset_value offval ;
2007-02-10 12:25:27 -02:00
ssize_t pos = 0 ;
int ret ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
offval . offset = priv - > bbp_offset ;
offval . value = 0 ;
2007-11-15 18:05:47 -05:00
ret = lbs_prepare_and_send_command ( priv ,
2007-08-02 11:31:18 -04:00
CMD_BBP_REG_ACCESS , 0 ,
CMD_OPTION_WAITFORRSP , 0 , & offval ) ;
2007-02-10 12:25:27 -02:00
mdelay ( 10 ) ;
pos + = snprintf ( buf + pos , len - pos , " BBP[0x%x] = 0x%08x \n " ,
2007-12-08 20:04:36 +00:00
priv - > bbp_offset , priv - > offsetvalue . value ) ;
2007-02-10 12:25:27 -02:00
ret = simple_read_from_buffer ( userbuf , count , ppos , buf , pos ) ;
free_page ( addr ) ;
return ret ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_rdbbp_write ( struct file * file ,
2007-02-10 12:25:27 -02:00
const char __user * userbuf ,
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
ssize_t res , buf_size ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
res = - EFAULT ;
goto out_unlock ;
}
priv - > bbp_offset = simple_strtoul ( ( char * ) buf , NULL , 16 ) ;
res = count ;
out_unlock :
free_page ( addr ) ;
return res ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_wrbbp_write ( struct file * file ,
2007-02-10 12:25:27 -02:00
const char __user * userbuf ,
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
ssize_t res , buf_size ;
u32 offset , value ;
2007-11-15 18:05:47 -05:00
struct lbs_offset_value offval ;
2007-02-10 12:25:27 -02:00
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
res = - EFAULT ;
goto out_unlock ;
}
res = sscanf ( buf , " %x %x " , & offset , & value ) ;
if ( res ! = 2 ) {
res = - EFAULT ;
goto out_unlock ;
}
offval . offset = offset ;
offval . value = value ;
2007-11-15 18:05:47 -05:00
res = lbs_prepare_and_send_command ( priv ,
2007-08-02 11:31:18 -04:00
CMD_BBP_REG_ACCESS , 1 ,
CMD_OPTION_WAITFORRSP , 0 , & offval ) ;
2007-02-10 12:25:27 -02:00
mdelay ( 10 ) ;
res = count ;
out_unlock :
free_page ( addr ) ;
return res ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_rdrf_read ( struct file * file , char __user * userbuf ,
2007-02-10 12:25:27 -02:00
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-11-15 18:05:47 -05:00
struct lbs_offset_value offval ;
2007-02-10 12:25:27 -02:00
ssize_t pos = 0 ;
int ret ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
offval . offset = priv - > rf_offset ;
offval . value = 0 ;
2007-11-15 18:05:47 -05:00
ret = lbs_prepare_and_send_command ( priv ,
2007-08-02 11:31:18 -04:00
CMD_RF_REG_ACCESS , 0 ,
CMD_OPTION_WAITFORRSP , 0 , & offval ) ;
2007-02-10 12:25:27 -02:00
mdelay ( 10 ) ;
pos + = snprintf ( buf + pos , len - pos , " RF[0x%x] = 0x%08x \n " ,
2007-12-08 20:04:36 +00:00
priv - > rf_offset , priv - > offsetvalue . value ) ;
2007-02-10 12:25:27 -02:00
ret = simple_read_from_buffer ( userbuf , count , ppos , buf , pos ) ;
free_page ( addr ) ;
return ret ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_rdrf_write ( struct file * file ,
2007-02-10 12:25:27 -02:00
const char __user * userbuf ,
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
ssize_t res , buf_size ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
res = - EFAULT ;
goto out_unlock ;
}
priv - > rf_offset = simple_strtoul ( ( char * ) buf , NULL , 16 ) ;
res = count ;
out_unlock :
free_page ( addr ) ;
return res ;
}
2007-11-15 18:05:47 -05:00
static ssize_t lbs_wrrf_write ( struct file * file ,
2007-02-10 12:25:27 -02:00
const char __user * userbuf ,
size_t count , loff_t * ppos )
{
2007-11-23 15:43:44 +01:00
struct lbs_private * priv = file - > private_data ;
2007-02-10 12:25:27 -02:00
ssize_t res , buf_size ;
u32 offset , value ;
2007-11-15 18:05:47 -05:00
struct lbs_offset_value offval ;
2007-02-10 12:25:27 -02:00
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
buf_size = min ( count , len - 1 ) ;
if ( copy_from_user ( buf , userbuf , buf_size ) ) {
res = - EFAULT ;
goto out_unlock ;
}
res = sscanf ( buf , " %x %x " , & offset , & value ) ;
if ( res ! = 2 ) {
res = - EFAULT ;
goto out_unlock ;
}
offval . offset = offset ;
offval . value = value ;
2007-11-15 18:05:47 -05:00
res = lbs_prepare_and_send_command ( priv ,
2007-08-02 11:31:18 -04:00
CMD_RF_REG_ACCESS , 1 ,
CMD_OPTION_WAITFORRSP , 0 , & offval ) ;
2007-02-10 12:25:27 -02:00
mdelay ( 10 ) ;
res = count ;
out_unlock :
free_page ( addr ) ;
return res ;
}
# define FOPS(fread, fwrite) { \
. owner = THIS_MODULE , \
. open = open_file_generic , \
. read = ( fread ) , \
. write = ( fwrite ) , \
}
2007-11-15 18:05:47 -05:00
struct lbs_debugfs_files {
2007-02-10 12:25:27 -02:00
char * name ;
int perm ;
struct file_operations fops ;
} ;
2007-11-15 18:05:47 -05:00
static struct lbs_debugfs_files debugfs_files [ ] = {
{ " info " , 0444 , FOPS ( lbs_dev_info , write_file_dummy ) , } ,
{ " getscantable " , 0444 , FOPS ( lbs_getscantable ,
2007-02-10 12:25:27 -02:00
write_file_dummy ) , } ,
2007-11-15 18:05:47 -05:00
{ " sleepparams " , 0644 , FOPS ( lbs_sleepparams_read ,
lbs_sleepparams_write ) , } ,
{ " extscan " , 0600 , FOPS ( NULL , lbs_extscan ) , } ,
{ " setuserscan " , 0600 , FOPS ( NULL , lbs_setuserscan ) , } ,
2007-02-10 12:25:27 -02:00
} ;
2007-11-15 18:05:47 -05:00
static struct lbs_debugfs_files debugfs_events_files [ ] = {
{ " low_rssi " , 0644 , FOPS ( lbs_lowrssi_read ,
lbs_lowrssi_write ) , } ,
{ " low_snr " , 0644 , FOPS ( lbs_lowsnr_read ,
lbs_lowsnr_write ) , } ,
{ " failure_count " , 0644 , FOPS ( lbs_failcount_read ,
lbs_failcount_write ) , } ,
{ " beacon_missed " , 0644 , FOPS ( lbs_bcnmiss_read ,
lbs_bcnmiss_write ) , } ,
{ " high_rssi " , 0644 , FOPS ( lbs_highrssi_read ,
lbs_highrssi_write ) , } ,
{ " high_snr " , 0644 , FOPS ( lbs_highsnr_read ,
lbs_highsnr_write ) , } ,
2007-02-10 12:25:27 -02:00
} ;
2007-11-15 18:05:47 -05:00
static struct lbs_debugfs_files debugfs_regs_files [ ] = {
{ " rdmac " , 0644 , FOPS ( lbs_rdmac_read , lbs_rdmac_write ) , } ,
{ " wrmac " , 0600 , FOPS ( NULL , lbs_wrmac_write ) , } ,
{ " rdbbp " , 0644 , FOPS ( lbs_rdbbp_read , lbs_rdbbp_write ) , } ,
{ " wrbbp " , 0600 , FOPS ( NULL , lbs_wrbbp_write ) , } ,
{ " rdrf " , 0644 , FOPS ( lbs_rdrf_read , lbs_rdrf_write ) , } ,
{ " wrrf " , 0600 , FOPS ( NULL , lbs_wrrf_write ) , } ,
2007-02-10 12:25:27 -02:00
} ;
2007-11-15 18:05:47 -05:00
void lbs_debugfs_init ( void )
2007-02-10 12:25:27 -02:00
{
2007-11-15 18:05:47 -05:00
if ( ! lbs_dir )
lbs_dir = debugfs_create_dir ( " lbs_wireless " , NULL ) ;
2007-02-10 12:25:27 -02:00
return ;
}
2007-11-15 18:05:47 -05:00
void lbs_debugfs_remove ( void )
2007-02-10 12:25:27 -02:00
{
2007-11-15 18:05:47 -05:00
if ( lbs_dir )
debugfs_remove ( lbs_dir ) ;
2007-02-10 12:25:27 -02:00
return ;
}
2007-11-23 15:43:44 +01:00
void lbs_debugfs_init_one ( struct lbs_private * priv , struct net_device * dev )
2007-02-10 12:25:27 -02:00
{
int i ;
2007-11-15 18:05:47 -05:00
struct lbs_debugfs_files * files ;
if ( ! lbs_dir )
2007-02-10 12:25:27 -02:00
goto exit ;
2007-11-15 18:05:47 -05:00
priv - > debugfs_dir = debugfs_create_dir ( dev - > name , lbs_dir ) ;
2007-02-10 12:25:27 -02:00
if ( ! priv - > debugfs_dir )
goto exit ;
for ( i = 0 ; i < ARRAY_SIZE ( debugfs_files ) ; i + + ) {
files = & debugfs_files [ i ] ;
priv - > debugfs_files [ i ] = debugfs_create_file ( files - > name ,
files - > perm ,
priv - > debugfs_dir ,
priv ,
& files - > fops ) ;
}
priv - > events_dir = debugfs_create_dir ( " subscribed_events " , priv - > debugfs_dir ) ;
if ( ! priv - > events_dir )
goto exit ;
for ( i = 0 ; i < ARRAY_SIZE ( debugfs_events_files ) ; i + + ) {
files = & debugfs_events_files [ i ] ;
priv - > debugfs_events_files [ i ] = debugfs_create_file ( files - > name ,
files - > perm ,
priv - > events_dir ,
priv ,
& files - > fops ) ;
}
priv - > regs_dir = debugfs_create_dir ( " registers " , priv - > debugfs_dir ) ;
if ( ! priv - > regs_dir )
goto exit ;
for ( i = 0 ; i < ARRAY_SIZE ( debugfs_regs_files ) ; i + + ) {
files = & debugfs_regs_files [ i ] ;
priv - > debugfs_regs_files [ i ] = debugfs_create_file ( files - > name ,
files - > perm ,
priv - > regs_dir ,
priv ,
& files - > fops ) ;
}
# ifdef PROC_DEBUG
2007-11-15 18:05:47 -05:00
lbs_debug_init ( priv , dev ) ;
2007-02-10 12:25:27 -02:00
# endif
exit :
return ;
}
2007-11-23 15:43:44 +01:00
void lbs_debugfs_remove_one ( struct lbs_private * priv )
2007-02-10 12:25:27 -02:00
{
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( debugfs_regs_files ) ; i + + )
debugfs_remove ( priv - > debugfs_regs_files [ i ] ) ;
debugfs_remove ( priv - > regs_dir ) ;
2007-05-24 23:47:34 -04:00
for ( i = 0 ; i < ARRAY_SIZE ( debugfs_events_files ) ; i + + )
2007-02-10 12:25:27 -02:00
debugfs_remove ( priv - > debugfs_events_files [ i ] ) ;
debugfs_remove ( priv - > events_dir ) ;
# ifdef PROC_DEBUG
debugfs_remove ( priv - > debugfs_debug ) ;
# endif
for ( i = 0 ; i < ARRAY_SIZE ( debugfs_files ) ; i + + )
debugfs_remove ( priv - > debugfs_files [ i ] ) ;
2007-05-24 23:47:34 -04:00
debugfs_remove ( priv - > debugfs_dir ) ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 00:37:28 -04:00
2007-02-10 12:25:27 -02:00
/* debug entry */
2007-05-25 00:37:28 -04:00
# ifdef PROC_DEBUG
2007-12-08 20:04:36 +00:00
# define item_size(n) (FIELD_SIZEOF(struct lbs_private, n))
# define item_addr(n) (offsetof(struct lbs_private, n))
2007-02-10 12:25:27 -02:00
2007-05-25 00:37:28 -04:00
2007-02-10 12:25:27 -02:00
struct debug_data {
char name [ 32 ] ;
u32 size ;
2007-05-10 23:10:18 -04:00
size_t addr ;
2007-02-10 12:25:27 -02:00
} ;
2007-12-08 20:04:36 +00:00
/* To debug any member of struct lbs_private, simply add one line here.
2007-02-10 12:25:27 -02:00
*/
static struct debug_data items [ ] = {
{ " intcounter " , item_size ( intcounter ) , item_addr ( intcounter ) } ,
{ " psmode " , item_size ( psmode ) , item_addr ( psmode ) } ,
{ " psstate " , item_size ( psstate ) , item_addr ( psstate ) } ,
} ;
2007-03-09 13:11:46 +11:00
static int num_of_items = ARRAY_SIZE ( items ) ;
2007-02-10 12:25:27 -02:00
/**
* @ brief proc read function
*
* @ param page pointer to buffer
* @ param s read data starting position
* @ param off offset
* @ param cnt counter
* @ param eof end of file flag
* @ param data data to output
* @ return number of output data
*/
2007-11-15 18:05:47 -05:00
static ssize_t lbs_debugfs_read ( struct file * file , char __user * userbuf ,
2007-02-10 12:25:27 -02:00
size_t count , loff_t * ppos )
{
int val = 0 ;
size_t pos = 0 ;
ssize_t res ;
char * p ;
int i ;
struct debug_data * d ;
unsigned long addr = get_zeroed_page ( GFP_KERNEL ) ;
char * buf = ( char * ) addr ;
p = buf ;
d = ( struct debug_data * ) file - > private_data ;
for ( i = 0 ; i < num_of_items ; i + + ) {
if ( d [ i ] . size = = 1 )
val = * ( ( u8 * ) d [ i ] . addr ) ;
else if ( d [ i ] . size = = 2 )
val = * ( ( u16 * ) d [ i ] . addr ) ;
else if ( d [ i ] . size = = 4 )
val = * ( ( u32 * ) d [ i ] . addr ) ;
2007-05-10 23:10:18 -04:00
else if ( d [ i ] . size = = 8 )
val = * ( ( u64 * ) d [ i ] . addr ) ;
2007-02-10 12:25:27 -02:00
pos + = sprintf ( p + pos , " %s=%d \n " , d [ i ] . name , val ) ;
}
res = simple_read_from_buffer ( userbuf , count , ppos , p , pos ) ;
free_page ( addr ) ;
return res ;
}
/**
* @ brief proc write function
*
* @ param f file pointer
* @ param buf pointer to data buffer
* @ param cnt data number to write
* @ param data data to write
* @ return number of data
*/
2007-11-15 18:05:47 -05:00
static ssize_t lbs_debugfs_write ( struct file * f , const char __user * buf ,
2007-02-10 12:25:27 -02:00
size_t cnt , loff_t * ppos )
{
int r , i ;
char * pdata ;
char * p ;
char * p0 ;
char * p1 ;
char * p2 ;
struct debug_data * d = ( struct debug_data * ) f - > private_data ;
2007-08-24 11:48:16 -04:00
pdata = kmalloc ( cnt , GFP_KERNEL ) ;
2007-02-10 12:25:27 -02:00
if ( pdata = = NULL )
return 0 ;
if ( copy_from_user ( pdata , buf , cnt ) ) {
2007-05-25 11:27:16 -04:00
lbs_deb_debugfs ( " Copy from user failed \n " ) ;
2007-02-10 12:25:27 -02:00
kfree ( pdata ) ;
return 0 ;
}
p0 = pdata ;
for ( i = 0 ; i < num_of_items ; i + + ) {
do {
p = strstr ( p0 , d [ i ] . name ) ;
if ( p = = NULL )
break ;
p1 = strchr ( p , ' \n ' ) ;
if ( p1 = = NULL )
break ;
p0 = p1 + + ;
p2 = strchr ( p , ' = ' ) ;
if ( ! p2 )
break ;
p2 + + ;
2007-03-09 13:11:46 +11:00
r = simple_strtoul ( p2 , NULL , 0 ) ;
2007-02-10 12:25:27 -02:00
if ( d [ i ] . size = = 1 )
* ( ( u8 * ) d [ i ] . addr ) = ( u8 ) r ;
else if ( d [ i ] . size = = 2 )
* ( ( u16 * ) d [ i ] . addr ) = ( u16 ) r ;
else if ( d [ i ] . size = = 4 )
* ( ( u32 * ) d [ i ] . addr ) = ( u32 ) r ;
2007-05-10 23:10:18 -04:00
else if ( d [ i ] . size = = 8 )
* ( ( u64 * ) d [ i ] . addr ) = ( u64 ) r ;
2007-02-10 12:25:27 -02:00
break ;
} while ( 1 ) ;
}
kfree ( pdata ) ;
2007-05-10 23:10:18 -04:00
return ( ssize_t ) cnt ;
2007-02-10 12:25:27 -02:00
}
2007-11-15 18:05:47 -05:00
static struct file_operations lbs_debug_fops = {
2007-02-10 12:25:27 -02:00
. owner = THIS_MODULE ,
. open = open_file_generic ,
2007-11-15 18:05:47 -05:00
. write = lbs_debugfs_write ,
. read = lbs_debugfs_read ,
2007-02-10 12:25:27 -02:00
} ;
/**
* @ brief create debug proc file
*
2007-11-23 15:43:44 +01:00
* @ param priv pointer struct lbs_private
2007-02-10 12:25:27 -02:00
* @ param dev pointer net_device
* @ return N / A
*/
2007-11-23 15:43:44 +01:00
static void lbs_debug_init ( struct lbs_private * priv , struct net_device * dev )
2007-02-10 12:25:27 -02:00
{
int i ;
if ( ! priv - > debugfs_dir )
return ;
for ( i = 0 ; i < num_of_items ; i + + )
2007-12-08 20:04:36 +00:00
items [ i ] . addr + = ( size_t ) priv ;
2007-02-10 12:25:27 -02:00
priv - > debugfs_debug = debugfs_create_file ( " debug " , 0644 ,
priv - > debugfs_dir , & items [ 0 ] ,
2007-11-15 18:05:47 -05:00
& lbs_debug_fops ) ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 00:37:28 -04:00
# endif