aboutsummaryrefslogtreecommitdiffstats
path: root/package/d80211/src/ieee80211_sysfs_sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/d80211/src/ieee80211_sysfs_sta.c')
-rw-r--r--package/d80211/src/ieee80211_sysfs_sta.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/package/d80211/src/ieee80211_sysfs_sta.c b/package/d80211/src/ieee80211_sysfs_sta.c
new file mode 100644
index 0000000000..738daf5af7
--- /dev/null
+++ b/package/d80211/src/ieee80211_sysfs_sta.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2003-2005, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include "ieee80211_i.h"
+#include "ieee80211_key.h"
+#include "sta_info.h"
+
+static ssize_t sta_sysfs_show(struct kobject *, struct attribute *, char *);
+static ssize_t key_sysfs_show(struct kobject *, struct attribute *, char *);
+
+static struct sysfs_ops sta_ktype_ops = {
+ .show = sta_sysfs_show,
+};
+
+static struct sysfs_ops key_ktype_ops = {
+ .show = key_sysfs_show,
+};
+
+/* sta attributtes */
+
+#define STA_SHOW(name, field, format_string) \
+static ssize_t show_sta_##name(const struct sta_info *sta, char *buf) \
+{ \
+ return sprintf(buf, format_string, sta->field); \
+}
+#define STA_SHOW_D(name, field) STA_SHOW(name, field, "%d\n")
+#define STA_SHOW_U(name, field) STA_SHOW(name, field, "%u\n")
+#define STA_SHOW_LU(name, field) STA_SHOW(name, field, "%lu\n")
+#define STA_SHOW_S(name, field) STA_SHOW(name, field, "%s\n")
+
+#define STA_SHOW_RATE(name, field) \
+static ssize_t show_sta_##name(const struct sta_info *sta, char *buf) \
+{ \
+ struct ieee80211_local *local = sta->dev->ieee80211_ptr; \
+ return sprintf(buf, "%d\n", \
+ (sta->field >= 0 && \
+ sta->field < local->num_curr_rates) ? \
+ local->curr_rates[sta->field].rate : -1); \
+}
+
+#define __STA_ATTR(name) \
+static struct sta_attribute sta_attr_##name = \
+ __ATTR(name, S_IRUGO, show_sta_##name, NULL)
+
+#define STA_ATTR(name, field, format) \
+ STA_SHOW_##format(name, field) \
+ __STA_ATTR(name)
+
+STA_ATTR(aid, aid, D);
+STA_ATTR(key_idx_compression, key_idx_compression, D);
+STA_ATTR(dev, dev->name, S);
+STA_ATTR(vlan_id, vlan_id, D);
+STA_ATTR(rx_packets, rx_packets, LU);
+STA_ATTR(tx_packets, tx_packets, LU);
+STA_ATTR(rx_bytes, rx_bytes, LU);
+STA_ATTR(tx_bytes, tx_bytes, LU);
+STA_ATTR(rx_duplicates, num_duplicates, LU);
+STA_ATTR(rx_fragments, rx_fragments, LU);
+STA_ATTR(rx_dropped, rx_dropped, LU);
+STA_ATTR(tx_fragments, tx_fragments, LU);
+STA_ATTR(tx_filtered, tx_filtered_count, LU);
+STA_ATTR(txrate, txrate, RATE);
+STA_ATTR(last_txrate, last_txrate, RATE);
+STA_ATTR(tx_retry_failed, tx_retry_failed, LU);
+STA_ATTR(tx_retry_count, tx_retry_count, LU);
+STA_ATTR(last_rssi, last_rssi, D);
+STA_ATTR(last_signal, last_signal, D);
+STA_ATTR(last_noise, last_noise, D);
+STA_ATTR(channel_use, channel_use, D);
+STA_ATTR(wep_weak_iv_count, wep_weak_iv_count, D);
+
+static ssize_t show_sta_flags(const struct sta_info *sta, char *buf)
+{
+ return sprintf(buf, "%s%s%s%s%s%s%s%s%s",
+ sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
+ sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+ sta->flags & WLAN_STA_PS ? "PS\n" : "",
+ sta->flags & WLAN_STA_TIM ? "TIM\n" : "",
+ sta->flags & WLAN_STA_PERM ? "PERM\n" : "",
+ sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+ sta->flags & WLAN_STA_SHORT_PREAMBLE ?
+ "SHORT PREAMBLE\n" : "",
+ sta->flags & WLAN_STA_WME ? "WME\n" : "",
+ sta->flags & WLAN_STA_WDS ? "WDS\n" : "");
+}
+__STA_ATTR(flags);
+
+static ssize_t show_sta_num_ps_buf_frames(const struct sta_info *sta, char *buf)
+{
+ return sprintf(buf, "%u\n", skb_queue_len(&sta->ps_tx_buf));
+}
+__STA_ATTR(num_ps_buf_frames);
+
+static ssize_t show_sta_last_ack_rssi(const struct sta_info *sta, char *buf)
+{
+ return sprintf(buf, "%d %d %d\n", sta->last_ack_rssi[0],
+ sta->last_ack_rssi[1], sta->last_ack_rssi[2]);
+}
+__STA_ATTR(last_ack_rssi);
+
+static ssize_t show_sta_last_ack_ms(const struct sta_info *sta, char *buf)
+{
+ return sprintf(buf, "%d\n", sta->last_ack ?
+ jiffies_to_msecs(jiffies - sta->last_ack) : -1);
+}
+__STA_ATTR(last_ack_ms);
+
+static ssize_t show_sta_inactive_ms(const struct sta_info *sta, char *buf)
+{
+ return sprintf(buf, "%d\n", jiffies_to_msecs(jiffies - sta->last_rx));
+}
+__STA_ATTR(inactive_ms);
+
+static ssize_t show_sta_last_seq_ctrl(const struct sta_info *sta, char *buf)
+{
+ int i;
+ char *p = buf;
+
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += sprintf(p, "%x ", sta->last_seq_ctrl[i]);
+ p += sprintf(p, "\n");
+ return (p - buf);
+}
+__STA_ATTR(last_seq_ctrl);
+
+#ifdef CONFIG_D80211_DEBUG_COUNTERS
+static ssize_t show_sta_wme_rx_queue(const struct sta_info *sta, char *buf)
+{
+ int i;
+ char *p = buf;
+
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += sprintf(p, "%u ", sta->wme_rx_queue[i]);
+ p += sprintf(p, "\n");
+ return (p - buf);
+}
+__STA_ATTR(wme_rx_queue);
+
+static ssize_t show_sta_wme_tx_queue(const struct sta_info *sta, char *buf)
+{
+ int i;
+ char *p = buf;
+
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += sprintf(p, "%u ", sta->wme_tx_queue[i]);
+ p += sprintf(p, "\n");
+ return (p - buf);
+}
+__STA_ATTR(wme_tx_queue);
+#endif
+
+static struct attribute *sta_ktype_attrs[] = {
+ &sta_attr_aid.attr,
+ &sta_attr_key_idx_compression.attr,
+ &sta_attr_dev.attr,
+ &sta_attr_vlan_id.attr,
+ &sta_attr_rx_packets.attr,
+ &sta_attr_tx_packets.attr,
+ &sta_attr_rx_bytes.attr,
+ &sta_attr_tx_bytes.attr,
+ &sta_attr_rx_duplicates.attr,
+ &sta_attr_rx_fragments.attr,
+ &sta_attr_rx_dropped.attr,
+ &sta_attr_tx_fragments.attr,
+ &sta_attr_tx_filtered.attr,
+ &sta_attr_txrate.attr,
+ &sta_attr_last_txrate.attr,
+ &sta_attr_tx_retry_failed.attr,
+ &sta_attr_tx_retry_count.attr,
+ &sta_attr_last_rssi.attr,
+ &sta_attr_last_signal.attr,
+ &sta_attr_last_noise.attr,
+ &sta_attr_channel_use.attr,
+ &sta_attr_wep_weak_iv_count.attr,
+
+ &sta_attr_flags.attr,
+ &sta_attr_num_ps_buf_frames.attr,
+ &sta_attr_last_ack_rssi.attr,
+ &sta_attr_last_ack_ms.attr,
+ &sta_attr_inactive_ms.attr,
+ &sta_attr_last_seq_ctrl.attr,
+#ifdef CONFIG_D80211_DEBUG_COUNTERS
+ &sta_attr_wme_rx_queue.attr,
+ &sta_attr_wme_tx_queue.attr,
+#endif
+ NULL
+};
+
+/* keys attributtes */
+
+struct key_attribute {
+ struct attribute attr;
+ ssize_t (*show)(const struct ieee80211_key *, char *buf);
+ ssize_t (*store)(struct ieee80211_key *, const char *buf,
+ size_t count);
+};
+
+#define KEY_SHOW(name, field, format_string) \
+static ssize_t show_key_##name(const struct ieee80211_key *key, char *buf)\
+{ \
+ return sprintf(buf, format_string, key->field); \
+}
+#define KEY_SHOW_D(name, field) KEY_SHOW(name, field, "%d\n")
+
+#define __KEY_ATTR(name) \
+static struct key_attribute key_attr_##name = \
+ __ATTR(name, S_IRUSR, show_key_##name, NULL)
+
+#define KEY_ATTR(name, field, format) \
+ KEY_SHOW_##format(name, field) \
+ __KEY_ATTR(name)
+
+KEY_ATTR(length, keylen, D);
+KEY_ATTR(sw_encrypt, force_sw_encrypt, D);
+KEY_ATTR(index, keyidx, D);
+KEY_ATTR(hw_index, hw_key_idx, D);
+KEY_ATTR(tx_rx_count, tx_rx_count, D);
+
+static ssize_t show_key_algorithm(const struct ieee80211_key *key, char *buf)
+{
+ char *alg;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ alg = "WEP";
+ break;
+ case ALG_TKIP:
+ alg = "TKIP";
+ break;
+ case ALG_CCMP:
+ alg = "CCMP";
+ break;
+ default:
+ return 0;
+ }
+ return sprintf(buf, "%s\n", alg);
+}
+__KEY_ATTR(algorithm);
+
+static ssize_t show_key_tx_spec(const struct ieee80211_key *key, char *buf)
+{
+ const u8 *tpn;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ return sprintf(buf, "\n");
+ case ALG_TKIP:
+ return sprintf(buf, "%08x %04x\n", key->u.tkip.iv32,
+ key->u.tkip.iv16);
+ case ALG_CCMP:
+ tpn = key->u.ccmp.tx_pn;
+ return sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", tpn[0],
+ tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
+ default:
+ return 0;
+ }
+}
+__KEY_ATTR(tx_spec);
+
+static ssize_t show_key_rx_spec(const struct ieee80211_key *key, char *buf)
+{
+ int i;
+ const u8 *rpn;
+ char *p = buf;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ return sprintf(buf, "\n");
+ case ALG_TKIP:
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += sprintf(p, "%08x %04x\n",
+ key->u.tkip.iv32_rx[i],
+ key->u.tkip.iv16_rx[i]);
+ return (p - buf);
+ case ALG_CCMP:
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+ rpn = key->u.ccmp.rx_pn[i];
+ p += sprintf(p, "%02x%02x%02x%02x%02x%02x\n", rpn[0],
+ rpn[1], rpn[2], rpn[3], rpn[4], rpn[5]);
+ }
+ return (p - buf);
+ default:
+ return 0;
+ }
+}
+__KEY_ATTR(rx_spec);
+
+static ssize_t show_key_replays(const struct ieee80211_key *key, char *buf)
+{
+ if (key->alg != ALG_CCMP)
+ return 0;
+ return sprintf(buf, "%u\n", key->u.ccmp.replays);
+}
+__KEY_ATTR(replays);
+
+static ssize_t show_key_key(const struct ieee80211_key *key, char *buf)
+{
+ int i;
+ char *p = buf;
+
+ for (i = 0; i < key->keylen; i++)
+ p += sprintf(p, "%02x", key->key[i]);
+ p += sprintf(p, "\n");
+ return (p - buf);
+}
+__KEY_ATTR(key);
+
+static struct attribute *key_ktype_attrs[] = {
+ &key_attr_length.attr,
+ &key_attr_sw_encrypt.attr,
+ &key_attr_index.attr,
+ &key_attr_hw_index.attr,
+ &key_attr_tx_rx_count.attr,
+ &key_attr_algorithm.attr,
+ &key_attr_tx_spec.attr,
+ &key_attr_rx_spec.attr,
+ &key_attr_replays.attr,
+ &key_attr_key.attr,
+ NULL
+};
+
+/* structures and functions */
+
+static struct kobj_type sta_ktype = {
+ .release = sta_info_release,
+ .sysfs_ops = &sta_ktype_ops,
+ .default_attrs = sta_ktype_attrs,
+};
+
+static struct kobj_type key_ktype = {
+ .release = ieee80211_key_release,
+ .sysfs_ops = &key_ktype_ops,
+ .default_attrs = key_ktype_attrs,
+};
+
+static ssize_t sta_sysfs_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct sta_attribute *sta_attr;
+ struct sta_info *sta;
+
+ sta_attr = container_of(attr, struct sta_attribute, attr);
+ sta = container_of(kobj, struct sta_info, kobj);
+ return sta_attr->show(sta, buf);
+}
+
+static ssize_t key_sysfs_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct key_attribute *key_attr;
+ struct ieee80211_key *key;
+
+ key_attr = container_of(attr, struct key_attribute, attr);
+ key = container_of(kobj, struct ieee80211_key, kobj);
+ return key_attr->show(key, buf);
+}
+
+int ieee80211_sta_kset_sysfs_register(struct ieee80211_local *local)
+{
+ int res;
+
+ res = kobject_set_name(&local->sta_kset.kobj, "sta");
+ if (res)
+ return res;
+ local->sta_kset.kobj.parent = &local->class_dev.kobj;
+ local->sta_kset.ktype = &sta_ktype;
+ return kset_register(&local->sta_kset);
+}
+
+void ieee80211_sta_kset_sysfs_unregister(struct ieee80211_local *local)
+{
+ kset_unregister(&local->sta_kset);
+}
+
+int ieee80211_key_kset_sysfs_register(struct ieee80211_sub_if_data *sdata)
+{
+ int res;
+
+ res = kobject_set_name(&sdata->key_kset.kobj, "keys");
+ if (res)
+ return res;
+ sdata->key_kset.kobj.parent = &sdata->dev->class_dev.kobj;
+ sdata->key_kset.ktype = &key_ktype;
+ return kset_register(&sdata->key_kset);
+}
+
+void ieee80211_key_kset_sysfs_unregister(struct ieee80211_sub_if_data *sdata)
+{
+ kset_unregister(&sdata->key_kset);
+}
+
+int ieee80211_sta_sysfs_add(struct sta_info *sta)
+{
+ return kobject_add(&sta->kobj);
+}
+
+void ieee80211_sta_sysfs_remove(struct sta_info *sta)
+{
+ kobject_del(&sta->kobj);
+}
+
+void ieee80211_key_sysfs_set_kset(struct ieee80211_key *key, struct kset *kset)
+{
+ key->kobj.kset = kset;
+ if (!kset)
+ key->kobj.ktype = &key_ktype;
+}
+
+int ieee80211_key_sysfs_add(struct ieee80211_key *key)
+{
+ return kobject_add(&key->kobj);
+}
+
+void ieee80211_key_sysfs_remove(struct ieee80211_key *key)
+{
+ if (key)
+ kobject_del(&key->kobj);
+}
+
+int ieee80211_key_sysfs_add_default(struct ieee80211_sub_if_data *sdata)
+{
+ return sysfs_create_link(&sdata->key_kset.kobj,
+ &sdata->default_key->kobj, "default");
+}
+
+void ieee80211_key_sysfs_remove_default(struct ieee80211_sub_if_data *sdata)
+{
+ sysfs_remove_link(&sdata->key_kset.kobj, "default");
+}