📄 iwlib.c
字号:
for(i = 0; i < in->e; i++) res *= 10; return(res);#else /* WE_NOLIBM */ /* Version with libm : faster */ return ((double) in->m) * pow(10,in->e);#endif /* WE_NOLIBM */}/*------------------------------------------------------------------*//* * Output a frequency with proper scaling */voidiw_print_freq_value(char * buffer, int buflen, double freq){ if(freq < KILO) snprintf(buffer, buflen, "%g", freq); else { char scale; int divisor; if(freq >= GIGA) { scale = 'G'; divisor = GIGA; } else { if(freq >= MEGA) { scale = 'M'; divisor = MEGA; } else { scale = 'k'; divisor = KILO; } } snprintf(buffer, buflen, "%g %cHz", freq / divisor, scale); }}/*------------------------------------------------------------------*//* * Output a frequency with proper scaling */voidiw_print_freq(char * buffer, int buflen, double freq, int channel, int freq_flags){ char sep = ((freq_flags & IW_FREQ_FIXED) ? '=' : ':'); char vbuf[16]; /* Print the frequency/channel value */ iw_print_freq_value(vbuf, sizeof(vbuf), freq); /* Check if channel only */ if(freq < KILO) snprintf(buffer, buflen, "Channel%c%s", sep, vbuf); else { /* Frequency. Check if we have a channel as well */ if(channel >= 0) snprintf(buffer, buflen, "Frequency%c%s (Channel %d)", sep, vbuf, channel); else snprintf(buffer, buflen, "Frequency%c%s", sep, vbuf); }}/*------------------------------------------------------------------*//* * Convert a frequency to a channel (negative -> error) */intiw_freq_to_channel(double freq, const struct iw_range * range){ double ref_freq; int k; /* Check if it's a frequency or not already a channel */ if(freq < KILO) return(-1); /* We compare the frequencies as double to ignore differences * in encoding. Slower, but safer... */ for(k = 0; k < range->num_frequency; k++) { ref_freq = iw_freq2float(&(range->freq[k])); if(freq == ref_freq) return(range->freq[k].i); } /* Not found */ return(-2);}/*------------------------------------------------------------------*//* * Convert a channel to a frequency (negative -> error) * Return the channel on success */intiw_channel_to_freq(int channel, double * pfreq, const struct iw_range * range){ int has_freq = 0; int k; /* Check if the driver support only channels or if it has frequencies */ for(k = 0; k < range->num_frequency; k++) { if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO)) has_freq = 1; } if(!has_freq) return(-1); /* Find the correct frequency in the list */ for(k = 0; k < range->num_frequency; k++) { if(range->freq[k].i == channel) { *pfreq = iw_freq2float(&(range->freq[k])); return(channel); } } /* Not found */ return(-2);}/*********************** BITRATE SUBROUTINES ***********************//*------------------------------------------------------------------*//* * Output a bitrate with proper scaling */voidiw_print_bitrate(char * buffer, int buflen, int bitrate){ double rate = bitrate; char scale; int divisor; if(rate >= GIGA) { scale = 'G'; divisor = GIGA; } else { if(rate >= MEGA) { scale = 'M'; divisor = MEGA; } else { scale = 'k'; divisor = KILO; } } snprintf(buffer, buflen, "%g %cb/s", rate / divisor, scale);}/************************ POWER SUBROUTINES *************************//*------------------------------------------------------------------*//* * Convert a value in dBm to a value in milliWatt. */intiw_dbm2mwatt(int in){#ifdef WE_NOLIBM /* Version without libm : slower */ int ip = in / 10; int fp = in % 10; int k; double res = 1.0; /* Split integral and floating part to avoid accumulating rounding errors */ for(k = 0; k < ip; k++) res *= 10; for(k = 0; k < fp; k++) res *= LOG10_MAGIC; return((int) res);#else /* WE_NOLIBM */ /* Version with libm : faster */ return((int) (floor(pow(10.0, (((double) in) / 10.0)))));#endif /* WE_NOLIBM */}/*------------------------------------------------------------------*//* * Convert a value in milliWatt to a value in dBm. */intiw_mwatt2dbm(int in){#ifdef WE_NOLIBM /* Version without libm : slower */ double fin = (double) in; int res = 0; /* Split integral and floating part to avoid accumulating rounding errors */ while(fin > 10.0) { res += 10; fin /= 10.0; } while(fin > 1.000001) /* Eliminate rounding errors, take ceil */ { res += 1; fin /= LOG10_MAGIC; } return(res);#else /* WE_NOLIBM */ /* Version with libm : faster */ return((int) (ceil(10.0 * log10((double) in))));#endif /* WE_NOLIBM */}/*------------------------------------------------------------------*//* * Output a txpower with proper conversion */voidiw_print_txpower(char * buffer, int buflen, struct iw_param * txpower){ int dbm; /* Check if disabled */ if(txpower->disabled) { snprintf(buffer, buflen, "off"); } else { /* Check for relative values */ if(txpower->flags & IW_TXPOW_RELATIVE) { snprintf(buffer, buflen, "%d", txpower->value); } else { /* Convert everything to dBm */ if(txpower->flags & IW_TXPOW_MWATT) dbm = iw_mwatt2dbm(txpower->value); else dbm = txpower->value; /* Display */ snprintf(buffer, buflen, "%d dBm", dbm); } }}/********************** STATISTICS SUBROUTINES **********************//*------------------------------------------------------------------*//* * Read /proc/net/wireless to get the latest statistics * Note : strtok not thread safe, not used in WE-12 and later. */intiw_get_stats(int skfd, const char * ifname, iwstats * stats, const iwrange * range, int has_range){ /* Fortunately, we can always detect this condition properly */ if((has_range) && (range->we_version_compiled > 11)) { struct iwreq wrq; wrq.u.data.pointer = (caddr_t) stats; wrq.u.data.length = sizeof(struct iw_statistics); wrq.u.data.flags = 1; /* Clear updated flag */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0) return(-1); /* Format has not changed since WE-12, no conversion */ return(0); } else { FILE * f = fopen(PROC_NET_WIRELESS, "r"); char buf[256]; char * bp; int t; if(f==NULL) return -1; /* Loop on all devices */ while(fgets(buf,255,f)) { bp=buf; while(*bp&&isspace(*bp)) bp++; /* Is it the good device ? */ if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') { /* Skip ethX: */ bp=strchr(bp,':'); bp++; /* -- status -- */ bp = strtok(bp, " "); sscanf(bp, "%X", &t); stats->status = (unsigned short) t; /* -- link quality -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 1; sscanf(bp, "%d", &t); stats->qual.qual = (unsigned char) t; /* -- signal level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 2; sscanf(bp, "%d", &t); stats->qual.level = (unsigned char) t; /* -- noise level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated += 4; sscanf(bp, "%d", &t); stats->qual.noise = (unsigned char) t; /* -- discarded packets -- */ bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.nwid); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.code); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.misc); fclose(f); /* No conversion needed */ return 0; } } fclose(f); return -1; }}/*------------------------------------------------------------------*//* * Output the link statistics, taking care of formating */voidiw_print_stats(char * buffer, int buflen, const iwqual * qual, const iwrange * range, int has_range){ int len; /* People are very often confused by the 8 bit arithmetic happening * here. * All the values here are encoded in a 8 bit integer. 8 bit integers * are either unsigned [0 ; 255], signed [-128 ; +127] or * negative [-255 ; 0]. * Further, on 8 bits, 0x100 == 256 == 0. * * Relative/percent values are always encoded unsigned, between 0 and 255. * Absolute/dBm values are always encoded between -192 and 63. * (Note that up to version 28 of Wireless Tools, dBm used to be * encoded always negative, between -256 and -1). * * How do we separate relative from absolute values ? * The old way is to use the range to do that. As of WE-19, we have * an explicit IW_QUAL_DBM flag in updated... * The range allow to specify the real min/max of the value. As the * range struct only specify one bound of the value, we assume that * the other bound is 0 (zero). * For relative values, range is [0 ; range->max]. * For absolute values, range is [range->max ; 63]. * * Let's take two example : * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100 * 2) value is -54dBm. noise floor of the radio is -104dBm. * qual->value = -54 = 202 ; range->max_qual.value = -104 = 152 * * Jean II */ /* Just do it... * The old way to detect dBm require both the range and a non-null * level (which confuse the test). The new way can deal with level of 0 * because it does an explicit test on the flag. */ if(has_range && ((qual->level != 0) || (qual->updated & (IW_QUAL_DBM | IW_QUAL_RCPI)))) { /* Deal with quality : always a relative value */ if(!(qual->updated & IW_QUAL_QUAL_INVALID)) { len = snprintf(buffer, buflen, "Quality%c%d/%d ", qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':', qual->qual, range->max_qual.qual); buffer += len; buflen -= len; } /* Check if the statistics are in RCPI (IEEE 802.11k) */ if(qual->updated & IW_QUAL_RCPI) { /* Deal with signal level in RCPI */ /* RCPI = int{(Power in dBm +110)*2} for 0dbm > Power > -110dBm */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { double rcpilevel = (qual->level / 2.0) - 110.0; len = snprintf(buffer, buflen, "Signal level%c%g dBm ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', rcpilevel); buffer += len; buflen -= len; } /* Deal with noise level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { double rcpinoise = (qual->noise / 2.0) - 110.0; len = snprintf(buffer, buflen, "Noise level%c%g dBm", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':', rcpinoise); } } else { /* Check if the statistics are in dBm */ if((qual->updated & IW_QUAL_DBM) || (qual->level > range->max_qual.level)) { /* Deal with signal level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { int dblevel = qual->level; /* Implement a range for dBm [-192; 63] */ if(qual->level >= 64) dblevel -= 0x100; len = snprintf(buffer, buflen, "Signal level%c%d dBm ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', dblevel); buffer += len; buflen -= len; } /* Deal with noise level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { int dbnoise = qual->noise; /* Implement a range for dBm [-192; 63] */ if(qual->noise >= 64) dbnoise -= 0x100; len = snprintf(buffer, buflen, "Noise level%c%d dBm", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':', dbnoise); } } else { /* Deal with signal level as relative value (0 -> max) */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { len = snprintf(buffer, buflen, "Signal level%c%d/%d ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', qual->level, range->max_qual.level); buffer += len; buflen -= len; } /* Deal with noise level as relative value (0 -> max) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { len = snprintf(buffer, buflen, "Noise level%c%d/%d", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':',
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -