00001
00002
00003 #define PROC_LIMIT (PAGE_SIZE - 80)
00004
00005
00006 #ifndef PRISM2_NO_PROCFS_DEBUG
00007 static int prism2_debug_proc_read(char *page, char **start, off_t off,
00008 int count, int *eof, void *data)
00009 {
00010 char *p = page;
00011 local_info_t *local = (local_info_t *) data;
00012 int i;
00013
00014 if (off != 0) {
00015 *eof = 1;
00016 return 0;
00017 }
00018
00019 p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
00020 local->next_txfid, local->next_alloc);
00021 for (i = 0; i < PRISM2_TXFID_COUNT; i++)
00022 p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
00023 local->txfid[i], local->intransmitfid[i]);
00024 p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
00025 p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
00026 p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
00027 p += sprintf(p, "wds_max_connections=%d\n",
00028 local->wds_max_connections);
00029 p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
00030 p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
00031 if (local->crypt && local->crypt->ops)
00032 p += sprintf(p, "crypt=%s\n", local->crypt->ops->name);
00033 p += sprintf(p, "pri_only=%d\n", local->pri_only);
00034
00035 return (p - page);
00036 }
00037 #endif
00038
00039
00040 static int prism2_stats_proc_read(char *page, char **start, off_t off,
00041 int count, int *eof, void *data)
00042 {
00043 char *p = page;
00044 local_info_t *local = (local_info_t *) data;
00045 struct comm_tallies_sums *sums = (struct comm_tallies_sums *)
00046 &local->comm_tallies;
00047
00048 if (off != 0) {
00049 *eof = 1;
00050 return 0;
00051 }
00052
00053 p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
00054 p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
00055 p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments);
00056 p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
00057 p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
00058 p += sprintf(p, "TxDeferredTransmissions=%u\n",
00059 sums->tx_deferred_transmissions);
00060 p += sprintf(p, "TxSingleRetryFrames=%u\n",
00061 sums->tx_single_retry_frames);
00062 p += sprintf(p, "TxMultipleRetryFrames=%u\n",
00063 sums->tx_multiple_retry_frames);
00064 p += sprintf(p, "TxRetryLimitExceeded=%u\n",
00065 sums->tx_retry_limit_exceeded);
00066 p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards);
00067 p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
00068 p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
00069 p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments);
00070 p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
00071 p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
00072 p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
00073 p += sprintf(p, "RxDiscardsNoBuffer=%u\n",
00074 sums->rx_discards_no_buffer);
00075 p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
00076 p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n",
00077 sums->rx_discards_wep_undecryptable);
00078 p += sprintf(p, "RxMessageInMsgFragments=%u\n",
00079 sums->rx_message_in_msg_fragments);
00080 p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
00081 sums->rx_message_in_bad_msg_fragments);
00082
00083
00084 return (p - page);
00085 }
00086
00087
00088 static int prism2_wds_proc_read(char *page, char **start, off_t off,
00089 int count, int *eof, void *data)
00090 {
00091 char *p = page;
00092 local_info_t *local = (local_info_t *) data;
00093 struct list_head *ptr;
00094 struct hostap_interface *iface;
00095 unsigned long flags;
00096
00097 if (off > PROC_LIMIT) {
00098 *eof = 1;
00099 return 0;
00100 }
00101
00102 read_lock_irqsave(&local->iface_lock, flags);
00103 list_for_each(ptr, &local->hostap_interfaces) {
00104 iface = list_entry(ptr, struct hostap_interface, list);
00105 if (iface->type != HOSTAP_INTERFACE_WDS)
00106 continue;
00107 p += sprintf(p, "%s\t" MACSTR "\n",
00108 iface->dev->name,
00109 MAC2STR(iface->u.wds.remote_addr));
00110 if ((p - page) > PROC_LIMIT) {
00111 printk(KERN_DEBUG "%s: wds proc did not fit\n",
00112 local->dev->name);
00113 break;
00114 }
00115 }
00116 read_unlock_irqrestore(&local->iface_lock, flags);
00117
00118 if ((p - page) <= off) {
00119 *eof = 1;
00120 return 0;
00121 }
00122
00123 *start = page + off;
00124
00125 return (p - page - off);
00126 }
00127
00128
00129 static int prism2_pda_proc_read(char *page, char **start, off_t off,
00130 int count, int *eof, void *data)
00131 {
00132 local_info_t *local = (local_info_t *) data;
00133
00134 if (local->pda == NULL || off >= PRISM2_PDA_SIZE) {
00135 *eof = 1;
00136 return 0;
00137 }
00138
00139 if (off + count > PRISM2_PDA_SIZE)
00140 count = PRISM2_PDA_SIZE - off;
00141
00142 memcpy(page, local->pda + off, count);
00143 return count;
00144 }
00145
00146
00147 #ifdef PRISM2_IO_DEBUG
00148 static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
00149 int count, int *eof, void *data)
00150 {
00151 local_info_t *local = (local_info_t *) data;
00152 int head = local->io_debug_head;
00153 int start_bytes, left, copy, copied;
00154
00155 if (off + count > PRISM2_IO_DEBUG_SIZE * 4) {
00156 *eof = 1;
00157 if (off >= PRISM2_IO_DEBUG_SIZE * 4)
00158 return 0;
00159 count = PRISM2_IO_DEBUG_SIZE * 4 - off;
00160 }
00161
00162 copied = 0;
00163 start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4;
00164 left = count;
00165
00166 if (off < start_bytes) {
00167 copy = start_bytes - off;
00168 if (copy > count)
00169 copy = count;
00170 memcpy(page, ((u8 *) &local->io_debug[head]) + off, copy);
00171 left -= copy;
00172 if (left > 0)
00173 memcpy(&page[copy], local->io_debug, left);
00174 } else {
00175 memcpy(page, ((u8 *) local->io_debug) + (off - start_bytes),
00176 left);
00177 }
00178
00179 *start = page;
00180
00181 return count;
00182 }
00183 #endif
00184
00185
00186 #ifndef PRISM2_NO_STATION_MODES
00187 static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
00188 int count, int *eof, void *data)
00189 {
00190 char *p = page;
00191 local_info_t *local = (local_info_t *) data;
00192 int entries, entry, i, len, total = 0, hostscan;
00193 struct hfa384x_scan_result *scanres;
00194 struct hfa384x_hostscan_result *hscanres;
00195 u8 *pos;
00196
00197 p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
00198 "SSID\n");
00199
00200 spin_lock_bh(&local->lock);
00201 hostscan = local->last_scan_type == PRISM2_HOSTSCAN;
00202 entries = hostscan ? local->last_hostscan_results_count :
00203 local->last_scan_results_count;
00204 for (entry = 0; entry < entries; entry++) {
00205 hscanres = &local->last_hostscan_results[entry];
00206 scanres = &local->last_scan_results[entry];
00207
00208 if (total + (p - page) <= off) {
00209 total += p - page;
00210 p = page;
00211 }
00212 if (total + (p - page) > off + count)
00213 break;
00214 if ((p - page) > (PAGE_SIZE - 200))
00215 break;
00216
00217 if (hostscan) {
00218 p += sprintf(p, "%d %d %d %d 0x%02x %d " MACSTR " %d ",
00219 le16_to_cpu(hscanres->chid),
00220 (s16) le16_to_cpu(hscanres->anl),
00221 (s16) le16_to_cpu(hscanres->sl),
00222 le16_to_cpu(hscanres->beacon_interval),
00223 le16_to_cpu(hscanres->capability),
00224 le16_to_cpu(hscanres->rate),
00225 MAC2STR(hscanres->bssid),
00226 le16_to_cpu(hscanres->atim));
00227 } else {
00228 p += sprintf(p, "%d %d %d %d 0x%02x %d " MACSTR
00229 " N/A ",
00230 le16_to_cpu(scanres->chid),
00231 (s16) le16_to_cpu(scanres->anl),
00232 (s16) le16_to_cpu(scanres->sl),
00233 le16_to_cpu(scanres->beacon_interval),
00234 le16_to_cpu(scanres->capability),
00235 le16_to_cpu(scanres->rate),
00236 MAC2STR(scanres->bssid));
00237 }
00238
00239 pos = hostscan ? hscanres->sup_rates : scanres->sup_rates;
00240 for (i = 0; i < sizeof(hscanres->sup_rates); i++) {
00241 if (pos[i] == 0)
00242 break;
00243 p += sprintf(p, "<%02x>", pos[i]);
00244 }
00245 p += sprintf(p, " ");
00246
00247 pos = hostscan ? hscanres->ssid : scanres->ssid;
00248 len = le16_to_cpu(hostscan ? hscanres->ssid_len :
00249 scanres->ssid_len);
00250 if (len > 32)
00251 len = 32;
00252 for (i = 0; i < len; i++) {
00253 unsigned char c = pos[i];
00254 if (c >= 32 && c < 127)
00255 p += sprintf(p, "%c", c);
00256 else
00257 p += sprintf(p, "<%02x>", c);
00258 }
00259 p += sprintf(p, "\n");
00260 }
00261 spin_unlock_bh(&local->lock);
00262
00263 total += (p - page);
00264 if (total >= off + count)
00265 *eof = 1;
00266
00267 if (total < off) {
00268 *eof = 1;
00269 return 0;
00270 }
00271
00272 len = total - off;
00273 if (len > (p - page))
00274 len = p - page;
00275 *start = p - len;
00276 if (len > count)
00277 len = count;
00278
00279 return len;
00280 }
00281 #endif
00282
00283
00284 void hostap_init_proc(local_info_t *local)
00285 {
00286 local->proc = NULL;
00287
00288 if (hostap_proc == NULL) {
00289 printk(KERN_WARNING "%s: hostap proc directory not created\n",
00290 local->dev->name);
00291 return;
00292 }
00293
00294 local->proc = proc_mkdir(local->dev->name, hostap_proc);
00295 if (local->proc == NULL) {
00296 printk(KERN_INFO "/proc/net/hostap/%s creation failed\n",
00297 local->dev->name);
00298 return;
00299 }
00300
00301 #ifndef PRISM2_NO_PROCFS_DEBUG
00302 create_proc_read_entry("debug", 0, local->proc,
00303 prism2_debug_proc_read, local);
00304 #endif
00305 create_proc_read_entry("stats", 0, local->proc,
00306 prism2_stats_proc_read, local);
00307 create_proc_read_entry("wds", 0, local->proc,
00308 prism2_wds_proc_read, local);
00309 create_proc_read_entry("pda", 0, local->proc,
00310 prism2_pda_proc_read, local);
00311 #ifdef PRISM2_IO_DEBUG
00312 create_proc_read_entry("io_debug", 0, local->proc,
00313 prism2_io_debug_proc_read, local);
00314 #endif
00315 #ifndef PRISM2_NO_STATION_MODES
00316 create_proc_read_entry("scan_results", 0, local->proc,
00317 prism2_scan_results_proc_read, local);
00318 #endif
00319 }
00320
00321
00322 void hostap_remove_proc(local_info_t *local)
00323 {
00324 if (local->proc != NULL) {
00325 #ifndef PRISM2_NO_STATION_MODES
00326 remove_proc_entry("scan_results", local->proc);
00327 #endif
00328 #ifdef PRISM2_IO_DEBUG
00329 remove_proc_entry("io_debug", local->proc);
00330 #endif
00331 remove_proc_entry("pda", local->proc);
00332 remove_proc_entry("wds", local->proc);
00333 remove_proc_entry("stats", local->proc);
00334 #ifndef PRISM2_NO_PROCFS_DEBUG
00335 remove_proc_entry("debug", local->proc);
00336 #endif
00337 if (local->dev != NULL && local->dev->name != NULL &&
00338 hostap_proc != NULL)
00339 remove_proc_entry(local->dev->name, hostap_proc);
00340 }
00341 }
00342
00343
00344 EXPORT_SYMBOL(hostap_init_proc);
00345 EXPORT_SYMBOL(hostap_remove_proc);