123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709 |
- /*
- * WiMedia Logical Link Control Protocol (WLP)
- * sysfs functions
- *
- * Copyright (C) 2007 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: Docs
- *
- */
- #include <linux/wlp.h>
- #include "wlp-internal.h"
- static
- size_t wlp_wss_wssid_e_print(char *buf, size_t bufsize,
- struct wlp_wssid_e *wssid_e)
- {
- size_t used = 0;
- used += scnprintf(buf, bufsize, " WSS: ");
- used += wlp_wss_uuid_print(buf + used, bufsize - used,
- &wssid_e->wssid);
- if (wssid_e->info != NULL) {
- used += scnprintf(buf + used, bufsize - used, " ");
- used += uwb_mac_addr_print(buf + used, bufsize - used,
- &wssid_e->info->bcast);
- used += scnprintf(buf + used, bufsize - used, " %u %u %s\n",
- wssid_e->info->accept_enroll,
- wssid_e->info->sec_status,
- wssid_e->info->name);
- }
- return used;
- }
- /**
- * Print out information learned from neighbor discovery
- *
- * Some fields being printed may not be included in the device discovery
- * information (it is not mandatory). We are thus careful how the
- * information is printed to ensure it is clear to the user what field is
- * being referenced.
- * The information being printed is for one time use - temporary storage is
- * cleaned after it is printed.
- *
- * Ideally sysfs output should be on one line. The information printed here
- * contain a few strings so it will be hard to parse if they are all
- * printed on the same line - without agreeing on a standard field
- * separator.
- */
- static
- ssize_t wlp_wss_neighborhood_print_remove(struct wlp *wlp, char *buf,
- size_t bufsize)
- {
- size_t used = 0;
- struct wlp_neighbor_e *neighb;
- struct wlp_wssid_e *wssid_e;
- mutex_lock(&wlp->nbmutex);
- used = scnprintf(buf, bufsize, "#Neighbor information\n"
- "#uuid dev_addr\n"
- "# Device Name:\n# Model Name:\n# Manufacturer:\n"
- "# Model Nr:\n# Serial:\n"
- "# Pri Dev type: CategoryID OUI OUISubdiv "
- "SubcategoryID\n"
- "# WSS: WSSID WSS_name accept_enroll sec_status "
- "bcast\n"
- "# WSS: WSSID WSS_name accept_enroll sec_status "
- "bcast\n\n");
- list_for_each_entry(neighb, &wlp->neighbors, node) {
- if (bufsize - used <= 0)
- goto out;
- used += wlp_wss_uuid_print(buf + used, bufsize - used,
- &neighb->uuid);
- buf[used++] = ' ';
- used += uwb_dev_addr_print(buf + used, bufsize - used,
- &neighb->uwb_dev->dev_addr);
- if (neighb->info != NULL)
- used += scnprintf(buf + used, bufsize - used,
- "\n Device Name: %s\n"
- " Model Name: %s\n"
- " Manufacturer:%s \n"
- " Model Nr: %s\n"
- " Serial: %s\n"
- " Pri Dev type: "
- "%u %02x:%02x:%02x %u %u\n",
- neighb->info->name,
- neighb->info->model_name,
- neighb->info->manufacturer,
- neighb->info->model_nr,
- neighb->info->serial,
- neighb->info->prim_dev_type.category,
- neighb->info->prim_dev_type.OUI[0],
- neighb->info->prim_dev_type.OUI[1],
- neighb->info->prim_dev_type.OUI[2],
- neighb->info->prim_dev_type.OUIsubdiv,
- neighb->info->prim_dev_type.subID);
- list_for_each_entry(wssid_e, &neighb->wssid, node) {
- used += wlp_wss_wssid_e_print(buf + used,
- bufsize - used,
- wssid_e);
- }
- buf[used++] = '\n';
- wlp_remove_neighbor_tmp_info(neighb);
- }
- out:
- mutex_unlock(&wlp->nbmutex);
- return used;
- }
- /**
- * Show properties of all WSS in neighborhood.
- *
- * Will trigger a complete discovery of WSS activated by this device and
- * its neighbors.
- */
- ssize_t wlp_neighborhood_show(struct wlp *wlp, char *buf)
- {
- wlp_discover(wlp);
- return wlp_wss_neighborhood_print_remove(wlp, buf, PAGE_SIZE);
- }
- EXPORT_SYMBOL_GPL(wlp_neighborhood_show);
- static
- ssize_t __wlp_wss_properties_show(struct wlp_wss *wss, char *buf,
- size_t bufsize)
- {
- ssize_t result;
- result = wlp_wss_uuid_print(buf, bufsize, &wss->wssid);
- result += scnprintf(buf + result, bufsize - result, " ");
- result += uwb_mac_addr_print(buf + result, bufsize - result,
- &wss->bcast);
- result += scnprintf(buf + result, bufsize - result,
- " 0x%02x %u ", wss->hash, wss->secure_status);
- result += wlp_wss_key_print(buf + result, bufsize - result,
- wss->master_key);
- result += scnprintf(buf + result, bufsize - result, " 0x%02x ",
- wss->tag);
- result += uwb_mac_addr_print(buf + result, bufsize - result,
- &wss->virtual_addr);
- result += scnprintf(buf + result, bufsize - result, " %s", wss->name);
- result += scnprintf(buf + result, bufsize - result,
- "\n\n#WSSID\n#WSS broadcast address\n"
- "#WSS hash\n#WSS secure status\n"
- "#WSS master key\n#WSS local tag\n"
- "#WSS local virtual EUI-48\n#WSS name\n");
- return result;
- }
- /**
- * Show which WSS is activated.
- */
- ssize_t wlp_wss_activate_show(struct wlp_wss *wss, char *buf)
- {
- int result = 0;
- if (mutex_lock_interruptible(&wss->mutex))
- goto out;
- if (wss->state >= WLP_WSS_STATE_ACTIVE)
- result = __wlp_wss_properties_show(wss, buf, PAGE_SIZE);
- else
- result = scnprintf(buf, PAGE_SIZE, "No local WSS active.\n");
- result += scnprintf(buf + result, PAGE_SIZE - result,
- "\n\n"
- "# echo WSSID SECURE_STATUS ACCEPT_ENROLLMENT "
- "NAME #create new WSS\n"
- "# echo WSSID [DEV ADDR] #enroll in and activate "
- "existing WSS, can request registrar\n"
- "#\n"
- "# WSSID is a 16 byte hex array. Eg. 12 A3 3B ... \n"
- "# SECURE_STATUS 0 - unsecure, 1 - secure (default)\n"
- "# ACCEPT_ENROLLMENT 0 - no, 1 - yes (default)\n"
- "# NAME is the text string identifying the WSS\n"
- "# DEV ADDR is the device address of neighbor "
- "that should be registrar. Eg. 32:AB\n");
- mutex_unlock(&wss->mutex);
- out:
- return result;
- }
- EXPORT_SYMBOL_GPL(wlp_wss_activate_show);
- /**
- * Create/activate a new WSS or enroll/activate in neighboring WSS
- *
- * The user can provide the WSSID of a WSS in which it wants to enroll.
- * Only the WSSID is necessary if the WSS have been discovered before. If
- * the WSS has not been discovered before, or the user wants to use a
- * particular neighbor as its registrar, then the user can also provide a
- * device address or the neighbor that will be used as registrar.
- *
- * A new WSS is created when the user provides a WSSID, secure status, and
- * WSS name.
- */
- ssize_t wlp_wss_activate_store(struct wlp_wss *wss,
- const char *buf, size_t size)
- {
- ssize_t result = -EINVAL;
- struct wlp_uuid wssid;
- struct uwb_dev_addr dev;
- struct uwb_dev_addr bcast = {.data = {0xff, 0xff} };
- char name[65];
- unsigned sec_status, accept;
- memset(name, 0, sizeof(name));
- result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx:%02hhx",
- &wssid.data[0] , &wssid.data[1],
- &wssid.data[2] , &wssid.data[3],
- &wssid.data[4] , &wssid.data[5],
- &wssid.data[6] , &wssid.data[7],
- &wssid.data[8] , &wssid.data[9],
- &wssid.data[10], &wssid.data[11],
- &wssid.data[12], &wssid.data[13],
- &wssid.data[14], &wssid.data[15],
- &dev.data[1], &dev.data[0]);
- if (result == 16 || result == 17) {
- result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx "
- "%u %u %64c",
- &wssid.data[0] , &wssid.data[1],
- &wssid.data[2] , &wssid.data[3],
- &wssid.data[4] , &wssid.data[5],
- &wssid.data[6] , &wssid.data[7],
- &wssid.data[8] , &wssid.data[9],
- &wssid.data[10], &wssid.data[11],
- &wssid.data[12], &wssid.data[13],
- &wssid.data[14], &wssid.data[15],
- &sec_status, &accept, name);
- if (result == 16)
- result = wlp_wss_enroll_activate(wss, &wssid, &bcast);
- else if (result == 19) {
- sec_status = sec_status == 0 ? 0 : 1;
- accept = accept == 0 ? 0 : 1;
- /* We read name using %c, so the newline needs to be
- * removed */
- if (strlen(name) != sizeof(name) - 1)
- name[strlen(name) - 1] = '\0';
- result = wlp_wss_create_activate(wss, &wssid, name,
- sec_status, accept);
- } else
- result = -EINVAL;
- } else if (result == 18)
- result = wlp_wss_enroll_activate(wss, &wssid, &dev);
- else
- result = -EINVAL;
- return result < 0 ? result : size;
- }
- EXPORT_SYMBOL_GPL(wlp_wss_activate_store);
- /**
- * Show the UUID of this host
- */
- ssize_t wlp_uuid_show(struct wlp *wlp, char *buf)
- {
- ssize_t result = 0;
- mutex_lock(&wlp->mutex);
- result = wlp_wss_uuid_print(buf, PAGE_SIZE, &wlp->uuid);
- buf[result++] = '\n';
- mutex_unlock(&wlp->mutex);
- return result;
- }
- EXPORT_SYMBOL_GPL(wlp_uuid_show);
- /**
- * Store a new UUID for this host
- *
- * According to the spec this should be encoded as an octet string in the
- * order the octets are shown in string representation in RFC 4122 (WLP
- * 0.99 [Table 6])
- *
- * We do not check value provided by user.
- */
- ssize_t wlp_uuid_store(struct wlp *wlp, const char *buf, size_t size)
- {
- ssize_t result;
- struct wlp_uuid uuid;
- mutex_lock(&wlp->mutex);
- result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx "
- "%02hhx %02hhx %02hhx %02hhx ",
- &uuid.data[0] , &uuid.data[1],
- &uuid.data[2] , &uuid.data[3],
- &uuid.data[4] , &uuid.data[5],
- &uuid.data[6] , &uuid.data[7],
- &uuid.data[8] , &uuid.data[9],
- &uuid.data[10], &uuid.data[11],
- &uuid.data[12], &uuid.data[13],
- &uuid.data[14], &uuid.data[15]);
- if (result != 16) {
- result = -EINVAL;
- goto error;
- }
- wlp->uuid = uuid;
- error:
- mutex_unlock(&wlp->mutex);
- return result < 0 ? result : size;
- }
- EXPORT_SYMBOL_GPL(wlp_uuid_store);
- /**
- * Show contents of members of device information structure
- */
- #define wlp_dev_info_show(type) \
- ssize_t wlp_dev_##type##_show(struct wlp *wlp, char *buf) \
- { \
- ssize_t result = 0; \
- mutex_lock(&wlp->mutex); \
- if (wlp->dev_info == NULL) { \
- result = __wlp_setup_device_info(wlp); \
- if (result < 0) \
- goto out; \
- } \
- result = scnprintf(buf, PAGE_SIZE, "%s\n", wlp->dev_info->type);\
- out: \
- mutex_unlock(&wlp->mutex); \
- return result; \
- } \
- EXPORT_SYMBOL_GPL(wlp_dev_##type##_show);
- wlp_dev_info_show(name)
- wlp_dev_info_show(model_name)
- wlp_dev_info_show(model_nr)
- wlp_dev_info_show(manufacturer)
- wlp_dev_info_show(serial)
- /**
- * Store contents of members of device information structure
- */
- #define wlp_dev_info_store(type, len) \
- ssize_t wlp_dev_##type##_store(struct wlp *wlp, const char *buf, size_t size)\
- { \
- ssize_t result; \
- char format[10]; \
- mutex_lock(&wlp->mutex); \
- if (wlp->dev_info == NULL) { \
- result = __wlp_alloc_device_info(wlp); \
- if (result < 0) \
- goto out; \
- } \
- memset(wlp->dev_info->type, 0, sizeof(wlp->dev_info->type)); \
- sprintf(format, "%%%uc", len); \
- result = sscanf(buf, format, wlp->dev_info->type); \
- out: \
- mutex_unlock(&wlp->mutex); \
- return result < 0 ? result : size; \
- } \
- EXPORT_SYMBOL_GPL(wlp_dev_##type##_store);
- wlp_dev_info_store(name, 32)
- wlp_dev_info_store(manufacturer, 64)
- wlp_dev_info_store(model_name, 32)
- wlp_dev_info_store(model_nr, 32)
- wlp_dev_info_store(serial, 32)
- static
- const char *__wlp_dev_category[] = {
- [WLP_DEV_CAT_COMPUTER] = "Computer",
- [WLP_DEV_CAT_INPUT] = "Input device",
- [WLP_DEV_CAT_PRINT_SCAN_FAX_COPIER] = "Printer, scanner, FAX, or "
- "Copier",
- [WLP_DEV_CAT_CAMERA] = "Camera",
- [WLP_DEV_CAT_STORAGE] = "Storage Network",
- [WLP_DEV_CAT_INFRASTRUCTURE] = "Infrastructure",
- [WLP_DEV_CAT_DISPLAY] = "Display",
- [WLP_DEV_CAT_MULTIM] = "Multimedia device",
- [WLP_DEV_CAT_GAMING] = "Gaming device",
- [WLP_DEV_CAT_TELEPHONE] = "Telephone",
- [WLP_DEV_CAT_OTHER] = "Other",
- };
- static
- const char *wlp_dev_category_str(unsigned cat)
- {
- if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE)
- || cat == WLP_DEV_CAT_OTHER)
- return __wlp_dev_category[cat];
- return "unknown category";
- }
- ssize_t wlp_dev_prim_category_show(struct wlp *wlp, char *buf)
- {
- ssize_t result = 0;
- mutex_lock(&wlp->mutex);
- if (wlp->dev_info == NULL) {
- result = __wlp_setup_device_info(wlp);
- if (result < 0)
- goto out;
- }
- result = scnprintf(buf, PAGE_SIZE, "%s\n",
- wlp_dev_category_str(wlp->dev_info->prim_dev_type.category));
- out:
- mutex_unlock(&wlp->mutex);
- return result;
- }
- EXPORT_SYMBOL_GPL(wlp_dev_prim_category_show);
- ssize_t wlp_dev_prim_category_store(struct wlp *wlp, const char *buf,
- size_t size)
- {
- ssize_t result;
- u16 cat;
- mutex_lock(&wlp->mutex);
- if (wlp->dev_info == NULL) {
- result = __wlp_alloc_device_info(wlp);
- if (result < 0)
- goto out;
- }
- result = sscanf(buf, "%hu", &cat);
- if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE)
- || cat == WLP_DEV_CAT_OTHER)
- wlp->dev_info->prim_dev_type.category = cat;
- else
- result = -EINVAL;
- out:
- mutex_unlock(&wlp->mutex);
- return result < 0 ? result : size;
- }
- EXPORT_SYMBOL_GPL(wlp_dev_prim_category_store);
- ssize_t wlp_dev_prim_OUI_show(struct wlp *wlp, char *buf)
- {
- ssize_t result = 0;
- mutex_lock(&wlp->mutex);
- if (wlp->dev_info == NULL) {
- result = __wlp_setup_device_info(wlp);
- if (result < 0)
- goto out;
- }
- result = scnprintf(buf, PAGE_SIZE, "%02x:%02x:%02x\n",
- wlp->dev_info->prim_dev_type.OUI[0],
- wlp->dev_info->prim_dev_type.OUI[1],
- wlp->dev_info->prim_dev_type.OUI[2]);
- out:
- mutex_unlock(&wlp->mutex);
- return result;
- }
- EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_show);
- ssize_t wlp_dev_prim_OUI_store(struct wlp *wlp, const char *buf, size_t size)
- {
- ssize_t result;
- u8 OUI[3];
- mutex_lock(&wlp->mutex);
- if (wlp->dev_info == NULL) {
- result = __wlp_alloc_device_info(wlp);
- if (result < 0)
- goto out;
- }
- result = sscanf(buf, "%hhx:%hhx:%hhx",
- &OUI[0], &OUI[1], &OUI[2]);
- if (result != 3) {
- result = -EINVAL;
- goto out;
- } else
- memcpy(wlp->dev_info->prim_dev_type.OUI, OUI, sizeof(OUI));
- out:
- mutex_unlock(&wlp->mutex);
- return result < 0 ? result : size;
- }
- EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_store);
- ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *wlp, char *buf)
- {
- ssize_t result = 0;
- mutex_lock(&wlp->mutex);
- if (wlp->dev_info == NULL) {
- result = __wlp_setup_device_info(wlp);
- if (result < 0)
- goto out;
- }
- result = scnprintf(buf, PAGE_SIZE, "%u\n",
- wlp->dev_info->prim_dev_type.OUIsubdiv);
- out:
- mutex_unlock(&wlp->mutex);
- return result;
- }
- EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_sub_show);
- ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *wlp, const char *buf,
- size_t size)
- {
- ssize_t result;
- unsigned sub;
- u8 max_sub = ~0;
- mutex_lock(&wlp->mutex);
- if (wlp->dev_info == NULL) {
- result = __wlp_alloc_device_info(wlp);
- if (result < 0)
- goto out;
- }
- result = sscanf(buf, "%u", &sub);
- if (sub <= max_sub)
- wlp->dev_info->prim_dev_type.OUIsubdiv = sub;
- else
- result = -EINVAL;
- out:
- mutex_unlock(&wlp->mutex);
- return result < 0 ? result : size;
- }
- EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_sub_store);
- ssize_t wlp_dev_prim_subcat_show(struct wlp *wlp, char *buf)
- {
- ssize_t result = 0;
- mutex_lock(&wlp->mutex);
- if (wlp->dev_info == NULL) {
- result = __wlp_setup_device_info(wlp);
- if (result < 0)
- goto out;
- }
- result = scnprintf(buf, PAGE_SIZE, "%u\n",
- wlp->dev_info->prim_dev_type.subID);
- out:
- mutex_unlock(&wlp->mutex);
- return result;
- }
- EXPORT_SYMBOL_GPL(wlp_dev_prim_subcat_show);
- ssize_t wlp_dev_prim_subcat_store(struct wlp *wlp, const char *buf,
- size_t size)
- {
- ssize_t result;
- unsigned sub;
- __le16 max_sub = ~0;
- mutex_lock(&wlp->mutex);
- if (wlp->dev_info == NULL) {
- result = __wlp_alloc_device_info(wlp);
- if (result < 0)
- goto out;
- }
- result = sscanf(buf, "%u", &sub);
- if (sub <= max_sub)
- wlp->dev_info->prim_dev_type.subID = sub;
- else
- result = -EINVAL;
- out:
- mutex_unlock(&wlp->mutex);
- return result < 0 ? result : size;
- }
- EXPORT_SYMBOL_GPL(wlp_dev_prim_subcat_store);
- /**
- * Subsystem implementation for interaction with individual WSS via sysfs
- *
- * Followed instructions for subsystem in Documentation/filesystems/sysfs.txt
- */
- #define kobj_to_wlp_wss(obj) container_of(obj, struct wlp_wss, kobj)
- #define attr_to_wlp_wss_attr(_attr) \
- container_of(_attr, struct wlp_wss_attribute, attr)
- /**
- * Sysfs subsystem: forward read calls
- *
- * Sysfs operation for forwarding read call to the show method of the
- * attribute owner
- */
- static
- ssize_t wlp_wss_attr_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
- {
- struct wlp_wss_attribute *wss_attr = attr_to_wlp_wss_attr(attr);
- struct wlp_wss *wss = kobj_to_wlp_wss(kobj);
- ssize_t ret = -EIO;
- if (wss_attr->show)
- ret = wss_attr->show(wss, buf);
- return ret;
- }
- /**
- * Sysfs subsystem: forward write calls
- *
- * Sysfs operation for forwarding write call to the store method of the
- * attribute owner
- */
- static
- ssize_t wlp_wss_attr_store(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t count)
- {
- struct wlp_wss_attribute *wss_attr = attr_to_wlp_wss_attr(attr);
- struct wlp_wss *wss = kobj_to_wlp_wss(kobj);
- ssize_t ret = -EIO;
- if (wss_attr->store)
- ret = wss_attr->store(wss, buf, count);
- return ret;
- }
- static
- struct sysfs_ops wss_sysfs_ops = {
- .show = wlp_wss_attr_show,
- .store = wlp_wss_attr_store,
- };
- struct kobj_type wss_ktype = {
- .release = wlp_wss_release,
- .sysfs_ops = &wss_sysfs_ops,
- };
- /**
- * Sysfs files for individual WSS
- */
- /**
- * Print static properties of this WSS
- *
- * The name of a WSS may not be null teminated. It's max size is 64 bytes
- * so we copy it to a larger array just to make sure we print sane data.
- */
- static ssize_t wlp_wss_properties_show(struct wlp_wss *wss, char *buf)
- {
- int result = 0;
- if (mutex_lock_interruptible(&wss->mutex))
- goto out;
- result = __wlp_wss_properties_show(wss, buf, PAGE_SIZE);
- mutex_unlock(&wss->mutex);
- out:
- return result;
- }
- WSS_ATTR(properties, S_IRUGO, wlp_wss_properties_show, NULL);
- /**
- * Print all connected members of this WSS
- * The EDA cache contains all members of WSS neighborhood.
- */
- static ssize_t wlp_wss_members_show(struct wlp_wss *wss, char *buf)
- {
- struct wlp *wlp = container_of(wss, struct wlp, wss);
- return wlp_eda_show(wlp, buf);
- }
- WSS_ATTR(members, S_IRUGO, wlp_wss_members_show, NULL);
- static
- const char *__wlp_strstate[] = {
- "none",
- "partially enrolled",
- "enrolled",
- "active",
- "connected",
- };
- static const char *wlp_wss_strstate(unsigned state)
- {
- if (state >= ARRAY_SIZE(__wlp_strstate))
- return "unknown state";
- return __wlp_strstate[state];
- }
- /*
- * Print current state of this WSS
- */
- static ssize_t wlp_wss_state_show(struct wlp_wss *wss, char *buf)
- {
- int result = 0;
- if (mutex_lock_interruptible(&wss->mutex))
- goto out;
- result = scnprintf(buf, PAGE_SIZE, "%s\n",
- wlp_wss_strstate(wss->state));
- mutex_unlock(&wss->mutex);
- out:
- return result;
- }
- WSS_ATTR(state, S_IRUGO, wlp_wss_state_show, NULL);
- static
- struct attribute *wss_attrs[] = {
- &wss_attr_properties.attr,
- &wss_attr_members.attr,
- &wss_attr_state.attr,
- NULL,
- };
- struct attribute_group wss_attr_group = {
- .name = NULL, /* we want them in the same directory */
- .attrs = wss_attrs,
- };
|