sysfs.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. Broadcom B43legacy wireless driver
  3. SYSFS support routines
  4. Copyright (c) 2006 Michael Buesch <m@bues.ch>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; see the file COPYING. If not, write to
  15. the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
  16. Boston, MA 02110-1301, USA.
  17. */
  18. #include "sysfs.h"
  19. #include "b43legacy.h"
  20. #include "main.h"
  21. #include "phy.h"
  22. #include "radio.h"
  23. #include <linux/capability.h>
  24. #define GENERIC_FILESIZE 64
  25. static int get_integer(const char *buf, size_t count)
  26. {
  27. char tmp[10 + 1] = { 0 };
  28. int ret = -EINVAL;
  29. if (count == 0)
  30. goto out;
  31. count = min_t(size_t, count, 10);
  32. memcpy(tmp, buf, count);
  33. ret = simple_strtol(tmp, NULL, 10);
  34. out:
  35. return ret;
  36. }
  37. static int get_boolean(const char *buf, size_t count)
  38. {
  39. if (count != 0) {
  40. if (buf[0] == '1')
  41. return 1;
  42. if (buf[0] == '0')
  43. return 0;
  44. if (count >= 4 && memcmp(buf, "true", 4) == 0)
  45. return 1;
  46. if (count >= 5 && memcmp(buf, "false", 5) == 0)
  47. return 0;
  48. if (count >= 3 && memcmp(buf, "yes", 3) == 0)
  49. return 1;
  50. if (count >= 2 && memcmp(buf, "no", 2) == 0)
  51. return 0;
  52. if (count >= 2 && memcmp(buf, "on", 2) == 0)
  53. return 1;
  54. if (count >= 3 && memcmp(buf, "off", 3) == 0)
  55. return 0;
  56. }
  57. return -EINVAL;
  58. }
  59. static ssize_t b43legacy_attr_interfmode_show(struct device *dev,
  60. struct device_attribute *attr,
  61. char *buf)
  62. {
  63. struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
  64. ssize_t count = 0;
  65. if (!capable(CAP_NET_ADMIN))
  66. return -EPERM;
  67. mutex_lock(&wldev->wl->mutex);
  68. switch (wldev->phy.interfmode) {
  69. case B43legacy_INTERFMODE_NONE:
  70. count = snprintf(buf, PAGE_SIZE, "0 (No Interference"
  71. " Mitigation)\n");
  72. break;
  73. case B43legacy_INTERFMODE_NONWLAN:
  74. count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference"
  75. " Mitigation)\n");
  76. break;
  77. case B43legacy_INTERFMODE_MANUALWLAN:
  78. count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference"
  79. " Mitigation)\n");
  80. break;
  81. default:
  82. B43legacy_WARN_ON(1);
  83. }
  84. mutex_unlock(&wldev->wl->mutex);
  85. return count;
  86. }
  87. static ssize_t b43legacy_attr_interfmode_store(struct device *dev,
  88. struct device_attribute *attr,
  89. const char *buf, size_t count)
  90. {
  91. struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
  92. unsigned long flags;
  93. int err;
  94. int mode;
  95. if (!capable(CAP_NET_ADMIN))
  96. return -EPERM;
  97. mode = get_integer(buf, count);
  98. switch (mode) {
  99. case 0:
  100. mode = B43legacy_INTERFMODE_NONE;
  101. break;
  102. case 1:
  103. mode = B43legacy_INTERFMODE_NONWLAN;
  104. break;
  105. case 2:
  106. mode = B43legacy_INTERFMODE_MANUALWLAN;
  107. break;
  108. case 3:
  109. mode = B43legacy_INTERFMODE_AUTOWLAN;
  110. break;
  111. default:
  112. return -EINVAL;
  113. }
  114. mutex_lock(&wldev->wl->mutex);
  115. spin_lock_irqsave(&wldev->wl->irq_lock, flags);
  116. err = b43legacy_radio_set_interference_mitigation(wldev, mode);
  117. if (err)
  118. b43legacyerr(wldev->wl, "Interference Mitigation not "
  119. "supported by device\n");
  120. mmiowb();
  121. spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
  122. mutex_unlock(&wldev->wl->mutex);
  123. return err ? err : count;
  124. }
  125. static DEVICE_ATTR(interference, 0644,
  126. b43legacy_attr_interfmode_show,
  127. b43legacy_attr_interfmode_store);
  128. static ssize_t b43legacy_attr_preamble_show(struct device *dev,
  129. struct device_attribute *attr,
  130. char *buf)
  131. {
  132. struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
  133. ssize_t count;
  134. if (!capable(CAP_NET_ADMIN))
  135. return -EPERM;
  136. mutex_lock(&wldev->wl->mutex);
  137. if (wldev->short_preamble)
  138. count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble"
  139. " enabled)\n");
  140. else
  141. count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble"
  142. " disabled)\n");
  143. mutex_unlock(&wldev->wl->mutex);
  144. return count;
  145. }
  146. static ssize_t b43legacy_attr_preamble_store(struct device *dev,
  147. struct device_attribute *attr,
  148. const char *buf, size_t count)
  149. {
  150. struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
  151. unsigned long flags;
  152. int value;
  153. if (!capable(CAP_NET_ADMIN))
  154. return -EPERM;
  155. value = get_boolean(buf, count);
  156. if (value < 0)
  157. return value;
  158. mutex_lock(&wldev->wl->mutex);
  159. spin_lock_irqsave(&wldev->wl->irq_lock, flags);
  160. wldev->short_preamble = !!value;
  161. spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
  162. mutex_unlock(&wldev->wl->mutex);
  163. return count;
  164. }
  165. static DEVICE_ATTR(shortpreamble, 0644,
  166. b43legacy_attr_preamble_show,
  167. b43legacy_attr_preamble_store);
  168. int b43legacy_sysfs_register(struct b43legacy_wldev *wldev)
  169. {
  170. struct device *dev = wldev->dev->dev;
  171. int err;
  172. B43legacy_WARN_ON(b43legacy_status(wldev) !=
  173. B43legacy_STAT_INITIALIZED);
  174. err = device_create_file(dev, &dev_attr_interference);
  175. if (err)
  176. goto out;
  177. err = device_create_file(dev, &dev_attr_shortpreamble);
  178. if (err)
  179. goto err_remove_interfmode;
  180. out:
  181. return err;
  182. err_remove_interfmode:
  183. device_remove_file(dev, &dev_attr_interference);
  184. goto out;
  185. }
  186. void b43legacy_sysfs_unregister(struct b43legacy_wldev *wldev)
  187. {
  188. struct device *dev = wldev->dev->dev;
  189. device_remove_file(dev, &dev_attr_shortpreamble);
  190. device_remove_file(dev, &dev_attr_interference);
  191. }