📄 airo.c
字号:
* will be called with fill set to zero. */static void airo_fill_inode( struct inode *i, int fill ) { if ( fill ) { MOD_INC_USE_COUNT; } else { MOD_DEC_USE_COUNT; }}#endif#if (LINUX_VERSION_CODE < 0x20311)static struct file_operations airo_file_ops = { NULL, // lseek NULL, // read NULL, // write NULL, // readdir NULL, // select NULL, // ioctl NULL, // mmap NULL, // open NULL, // release};static struct inode_operations airo_inode_ops = { &airo_file_ops, NULL, // create NULL, // lookup};static struct proc_dir_entry airo_entry = { 0, 7, "aironet", S_IFDIR | S_IRUGO | S_IXUGO, 1, 0, 0, 44, &airo_inode_ops, 0, // get_info#if ((LINUX_VERSION_CODE > 0x20155) && (LINUX_VERSION_CODE < 0x20311)) airo_fill_inode#endif};#elsestatic struct proc_dir_entry *airo_entry = 0;#endif#if (LINUX_VERSION_CODE < 0x20311)static struct proc_dir_entry wepkey_entry = { 0, 6, "WepKey", S_IFREG | S_IWUSR, 2, 0, 0, 13, &proc_inode_wepkey_ops, NULL};static struct proc_dir_entry statsdelta_entry = { 0, 10, "StatsDelta", S_IFREG | S_IRUGO | S_IWUSR , 2, 0, 0, 13, &proc_inode_statsdelta_ops, NULL};static struct proc_dir_entry stats_entry = { 0, 5, "Stats", S_IFREG | S_IRUGO , 2, 0, 0, 13, &proc_inode_stats_ops, NULL};static struct proc_dir_entry status_entry = { 0, 6, "Status", S_IFREG | S_IRUGO , 2, 0, 0, 13, &proc_inode_status_ops, NULL};static struct proc_dir_entry SSID_entry = { 0, 4, "SSID", S_IFREG | S_IRUGO | S_IWUSR, 2, 0, 0, 13, &proc_inode_SSID_ops, NULL};static struct proc_dir_entry APList_entry = { 0, 6, "APList", S_IFREG | S_IRUGO | S_IWUSR, 2, 0, 0, 13, &proc_inode_APList_ops, NULL};static struct proc_dir_entry config_entry = { 0, 6, "Config", S_IFREG | S_IRUGO | S_IWUSR, 2, 0, 0, 13, &proc_inode_config_ops, NULL};#endifstruct proc_data { int release_buffer; int readlen; char *rbuffer; int writelen; int maxwritelen; char *wbuffer; void (*on_close) (struct inode *, struct file *);};#if (LINUX_VERSION_CODE < 0x20311)static int setup_proc_entry( struct net_device *dev, struct airo_info *apriv ) { /* First setup the device directory */ memset( &apriv->proc_entry, 0, sizeof( apriv->proc_entry ) ); apriv->proc_entry.namelen = strlen( dev->name ); apriv->proc_entry.name = dev->name; apriv->proc_entry.mode = S_IFDIR | S_IRUGO | S_IXUGO; apriv->proc_entry.nlink = 2; apriv->proc_entry.ops = airo_entry.ops; PROC_REGISTER( &airo_entry, &apriv->proc_entry ); /* Setup the StatsDelta */ memcpy( &apriv->proc_statsdelta_entry, &statsdelta_entry, sizeof( statsdelta_entry ) ); apriv->proc_statsdelta_entry.data = dev; PROC_REGISTER( &apriv->proc_entry, &apriv->proc_statsdelta_entry ); /* Setup the Stats */ memcpy( &apriv->proc_stats_entry, &stats_entry, sizeof( stats_entry ) ); apriv->proc_stats_entry.data = dev; PROC_REGISTER( &apriv->proc_entry, &apriv->proc_stats_entry ); /* Setup the Status */ memcpy( &apriv->proc_status_entry, &status_entry, sizeof( status_entry ) ); apriv->proc_status_entry.data = dev; PROC_REGISTER( &apriv->proc_entry, &apriv->proc_status_entry ); /* Setup the Config */ memcpy( &apriv->proc_config_entry, &config_entry, sizeof( config_entry ) ); apriv->proc_config_entry.data = dev; PROC_REGISTER( &apriv->proc_entry, &apriv->proc_config_entry ); /* Setup the SSID */ memcpy( &apriv->proc_SSID_entry, &SSID_entry, sizeof( SSID_entry ) ); apriv->proc_SSID_entry.data = dev; PROC_REGISTER( &apriv->proc_entry, &apriv->proc_SSID_entry ); /* Setup the APList */ memcpy( &apriv->proc_APList_entry, &APList_entry, sizeof( APList_entry ) ); apriv->proc_APList_entry.data = dev; PROC_REGISTER( &apriv->proc_entry, &apriv->proc_APList_entry ); /* Setup the WepKey */ memcpy( &apriv->proc_wepkey_entry, &wepkey_entry, sizeof( wepkey_entry ) ); apriv->proc_wepkey_entry.data = dev; PROC_REGISTER( &apriv->proc_entry, &apriv->proc_wepkey_entry ); return 0;}static int takedown_proc_entry( struct net_device *dev, struct airo_info *apriv ) { if ( !apriv->proc_entry.namelen ) return 0; PROC_UNREGISTER( &apriv->proc_entry, &apriv->proc_statsdelta_entry ); PROC_UNREGISTER( &apriv->proc_entry, &apriv->proc_stats_entry ); PROC_UNREGISTER( &apriv->proc_entry, &apriv->proc_status_entry ); PROC_UNREGISTER( &apriv->proc_entry, &apriv->proc_config_entry ); PROC_UNREGISTER( &apriv->proc_entry, &apriv->proc_SSID_entry ); PROC_UNREGISTER( &apriv->proc_entry, &apriv->proc_APList_entry ); PROC_UNREGISTER( &apriv->proc_entry, &apriv->proc_wepkey_entry ); PROC_UNREGISTER( &airo_entry, &apriv->proc_entry ); return 0;}#elsestatic int setup_proc_entry( struct net_device *dev, struct airo_info *apriv ) { struct proc_dir_entry *entry; /* First setup the device directory */ apriv->proc_entry = create_proc_entry(dev->name, S_IFDIR|S_IRUGO|S_IXUGO, airo_entry); /* Setup the StatsDelta */ entry = create_proc_entry("StatsDelta", S_IFREG | S_IRUGO | S_IWUSR, apriv->proc_entry); entry->data = dev;/* This is what was needed right up to the last few versions of 2.3: entry->ops = &proc_inode_statsdelta_ops;*/ entry->proc_fops = &proc_statsdelta_ops; /* Setup the Stats */ entry = create_proc_entry("Stats", S_IFREG | S_IRUGO, apriv->proc_entry); entry->data = dev; entry->proc_fops = &proc_stats_ops; /* Setup the Status */ entry = create_proc_entry("Status", S_IFREG | S_IRUGO, apriv->proc_entry); entry->data = dev; entry->proc_fops = &proc_status_ops; /* Setup the Config */ entry = create_proc_entry("Config", S_IFREG | S_IRUGO | S_IWUGO, apriv->proc_entry); entry->data = dev; entry->proc_fops = &proc_config_ops; /* Setup the SSID */ entry = create_proc_entry("SSID", S_IFREG | S_IRUGO | S_IWUGO, apriv->proc_entry); entry->data = dev; entry->proc_fops = &proc_SSID_ops; /* Setup the APList */ entry = create_proc_entry("APList", S_IFREG | S_IRUGO | S_IWUGO, apriv->proc_entry); entry->data = dev; entry->proc_fops = &proc_APList_ops; /* Setup the WepKey */ entry = create_proc_entry("WepKey", S_IFREG | S_IWUSR, apriv->proc_entry); entry->data = dev; entry->proc_fops = &proc_wepkey_ops; return 0;}static int takedown_proc_entry( struct net_device *dev, struct airo_info *apriv ) { if ( !apriv->proc_entry->namelen ) return 0; remove_proc_entry("Stats",apriv->proc_entry); remove_proc_entry("StatsDelta",apriv->proc_entry); remove_proc_entry("Status",apriv->proc_entry); remove_proc_entry("Config",apriv->proc_entry); remove_proc_entry("SSID",apriv->proc_entry); remove_proc_entry("APList",apriv->proc_entry); remove_proc_entry("WepKey",apriv->proc_entry); remove_proc_entry(dev->name,airo_entry); return 0;}#endif/* * What we want from the proc_fs is to be able to efficiently read * and write the configuration. To do this, we want to read the * configuration when the file is opened and write it when the file is * closed. So basically we allocate a read buffer at open and fill it * with data, and allocate a write buffer and read it at close. *//* * The read routine is generic, it relies on the preallocated rbuffer * to supply the data. */#if (LINUX_VERSION_CODE > 0x20155)static ssize_t proc_read( struct file *file, char *buffer, size_t len, loff_t *offset )#elsestatic int proc_read( struct inode *inode, struct file *file, char *buffer, int len ) #endif{ int i; int pos; struct proc_data *priv = (struct proc_data*)file->private_data; if( !priv->rbuffer ) return -EINVAL; #if (LINUX_VERSION_CODE > 0x20155) pos = *offset;#else pos = file->f_pos;#endif for( i = 0; i+pos < priv->readlen && i < len; i++ ) { put_user( priv->rbuffer[i+pos], buffer+i ); }#if (LINUX_VERSION_CODE > 0x20155) *offset += i;#else file->f_pos += i;#endif return i;}/* * The write routine is generic, it fills in a preallocated rbuffer * to supply the data. */#if (LINUX_VERSION_CODE > 0x20155)static ssize_t proc_write( struct file *file, const char *buffer, size_t len, loff_t *offset ) #elsestatic int proc_write( struct inode *inode, struct file *file, const char *buffer, int len ) #endif{ int i; int pos; struct proc_data *priv = (struct proc_data*)file->private_data; if ( !priv->wbuffer ) { return -EINVAL; } #if (LINUX_VERSION_CODE > 0x20155) pos = *offset;#else pos = file->f_pos;#endif for( i = 0; i + pos < priv->maxwritelen && i < len; i++ ) {#if (LINUX_VERSION_CODE > 0x20155) get_user( priv->wbuffer[i+pos], buffer + i );#else priv->wbuffer[i+pos] = get_user( buffer + i );#endif } if ( i+pos > priv->writelen ) priv->writelen = i+file->f_pos;#if (LINUX_VERSION_CODE > 0x20155) *offset += i;#else file->f_pos += i;#endif return i;}static int proc_status_open( struct inode *inode, struct file *file ) { struct proc_data *data; struct proc_dir_entry *dp = inode->u.generic_ip; struct net_device *dev = dp->data; struct airo_info *apriv = (struct airo_info *)dev->priv; CapabilityRid cap_rid; StatusRid status_rid; MOD_INC_USE_COUNT; dp = (struct proc_dir_entry *) inode->u.generic_ip; file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL); memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; data->rbuffer = kmalloc( 2048, GFP_KERNEL ); readStatusRid(apriv, &status_rid); readCapabilityRid(apriv, &cap_rid); sprintf( data->rbuffer, "Mode: %x\n" "Signal Strength: %d\n" "Signal Quality: %d\n" "SSID: %-.*s\n" "AP: %-.16s\n" "Freq: %d\n" "BitRate: %dmbs\n" "Driver Version: %s\n" "Device: %s\nManufacturer: %s\nFirmware Version: %s\n" "Radio type: %x\nCountry: %x\nHardware Version: %x\n" "Software Version: %x\nSoftware Subversion: %x\n" "Boot block version: %x\n", (int)status_rid.mode, (int)status_rid.normalizedSignalStrength, (int)status_rid.signalQuality, (int)status_rid.SSIDlen, status_rid.SSID, status_rid.apName, (int)status_rid.channel, (int)status_rid.currentXmitRate/2, version, cap_rid.prodName, cap_rid.manName, cap_rid.prodVer, cap_rid.radioType, cap_rid.country, cap_rid.hardVer, (int)cap_rid.softVer, (int)cap_rid.softSubVer, (int)cap_rid.bootBlockVer ); data->readlen = strlen( data->rbuffer ); return 0;}static int proc_stats_rid_open(struct inode*, struct file*, u16);static int proc_statsdelta_open( struct inode *inode, struct file *file ) { if (file->f_mode&FMODE_WRITE) { return proc_stats_rid_open(inode, file, RID_STATSDELTACLEAR); } return proc_stats_rid_open(inode, file, RID_STATSDELTA);}static int proc_stats_open( struct inode *inode, struct file *file ) { return proc_stats_rid_open(inode, file, RID_STATS);}static int proc_stats_rid_open( struct inode *inode, struct file *file, u16 rid ) { struct proc_data *data; struct proc_dir_entry *dp = inode->u.generic_ip; struct net_device *dev = dp->data; struct airo_info *apriv = (struct airo_info *)dev->priv; StatsRid stats; int i, j; int *vals = stats.vals; MOD_INC_USE_COUNT; dp = (struct proc_dir_entry *) inode->u.generic_ip; file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL); memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; data->rbuffer = kmalloc( 4096, GFP_KERNEL ); readStatsRid(apriv, &stats, rid); j = 0; for(i=0; (int)statsLabels[i]!=-1 && i*4<stats.len; i++){ if (!statsLabels[i]) continue; if (j+strlen(statsLabels[i])+16>4096) { printk(KERN_WARNING "airo: Potentially disasterous buffer overflow averted!\n"); break; } j+=sprintf(data->rbuffer+j, "%s: %d\n", statsLabels[i], vals[i]); } if (i*4>=stats.len){ printk(KERN_WARNING "airo: Got a short rid\n"); } data->readlen = j; return 0;}static int get_dec_u16( char *buffer, int *start, int limit ) { u16 value; int valid = 0; for( value = 0; buffer[*start] >= '0' && buffer[*start] <= '9' && *start < limit; (*start)++ ) { valid = 1; value *= 10; value += buffer[*start] - '0'; } if ( !valid ) return -1; return value;}static void checkThrottle(ConfigRid *config) { int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -