sysfs.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. Broadcom B43 wireless driver
  3. SYSFS support routines
  4. Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
  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 "b43.h"
  19. #include "sysfs.h"
  20. #include "main.h"
  21. #include "phy.h"
  22. #include <linux/capability.h>
  23. #define GENERIC_FILESIZE 64
  24. static int get_integer(const char *buf, size_t count)
  25. {
  26. char tmp[10 + 1] = { 0 };
  27. int ret = -EINVAL;
  28. if (count == 0)
  29. goto out;
  30. count = min(count, (size_t) 10);
  31. memcpy(tmp, buf, count);
  32. ret = simple_strtol(tmp, NULL, 10);
  33. out:
  34. return ret;
  35. }
  36. static int get_boolean(const char *buf, size_t count)
  37. {
  38. if (count != 0) {
  39. if (buf[0] == '1')
  40. return 1;
  41. if (buf[0] == '0')
  42. return 0;
  43. if (count >= 4 && memcmp(buf, "true", 4) == 0)
  44. return 1;
  45. if (count >= 5 && memcmp(buf, "false", 5) == 0)
  46. return 0;
  47. if (count >= 3 && memcmp(buf, "yes", 3) == 0)
  48. return 1;
  49. if (count >= 2 && memcmp(buf, "no", 2) == 0)
  50. return 0;
  51. if (count >= 2 && memcmp(buf, "on", 2) == 0)
  52. return 1;
  53. if (count >= 3 && memcmp(buf, "off", 3) == 0)
  54. return 0;
  55. }
  56. return -EINVAL;
  57. }
  58. static ssize_t b43_attr_interfmode_show(struct device *dev,
  59. struct device_attribute *attr,
  60. char *buf)
  61. {
  62. struct b43_wldev *wldev = dev_to_b43_wldev(dev);
  63. ssize_t count = 0;
  64. if (!capable(CAP_NET_ADMIN))
  65. return -EPERM;
  66. mutex_lock(&wldev->wl->mutex);
  67. switch (wldev->phy.interfmode) {
  68. case B43_INTERFMODE_NONE:
  69. count =
  70. snprintf(buf, PAGE_SIZE,
  71. "0 (No Interference Mitigation)\n");
  72. break;
  73. case B43_INTERFMODE_NONWLAN:
  74. count =
  75. snprintf(buf, PAGE_SIZE,
  76. "1 (Non-WLAN Interference Mitigation)\n");
  77. break;
  78. case B43_INTERFMODE_MANUALWLAN:
  79. count =
  80. snprintf(buf, PAGE_SIZE,
  81. "2 (WLAN Interference Mitigation)\n");
  82. break;
  83. default:
  84. B43_WARN_ON(1);
  85. }
  86. mutex_unlock(&wldev->wl->mutex);
  87. return count;
  88. }
  89. static ssize_t b43_attr_interfmode_store(struct device *dev,
  90. struct device_attribute *attr,
  91. const char *buf, size_t count)
  92. {
  93. struct b43_wldev *wldev = dev_to_b43_wldev(dev);
  94. unsigned long flags;
  95. int err;
  96. int mode;
  97. if (!capable(CAP_NET_ADMIN))
  98. return -EPERM;
  99. mode = get_integer(buf, count);
  100. switch (mode) {
  101. case 0:
  102. mode = B43_INTERFMODE_NONE;
  103. break;
  104. case 1:
  105. mode = B43_INTERFMODE_NONWLAN;
  106. break;
  107. case 2:
  108. mode = B43_INTERFMODE_MANUALWLAN;
  109. break;
  110. case 3:
  111. mode = B43_INTERFMODE_AUTOWLAN;
  112. break;
  113. default:
  114. return -EINVAL;
  115. }
  116. mutex_lock(&wldev->wl->mutex);
  117. spin_lock_irqsave(&wldev->wl->irq_lock, flags);
  118. err = b43_radio_set_interference_mitigation(wldev, mode);
  119. if (err) {
  120. b43err(wldev->wl, "Interference Mitigation not "
  121. "supported by device\n");
  122. }
  123. mmiowb();
  124. spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
  125. mutex_unlock(&wldev->wl->mutex);
  126. return err ? err : count;
  127. }
  128. static DEVICE_ATTR(interference, 0644,
  129. b43_attr_interfmode_show, b43_attr_interfmode_store);
  130. static ssize_t b43_attr_preamble_show(struct device *dev,
  131. struct device_attribute *attr, char *buf)
  132. {
  133. struct b43_wldev *wldev = dev_to_b43_wldev(dev);
  134. ssize_t count;
  135. if (!capable(CAP_NET_ADMIN))
  136. return -EPERM;
  137. mutex_lock(&wldev->wl->mutex);
  138. if (wldev->short_preamble)
  139. count =
  140. snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
  141. else
  142. count =
  143. snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
  144. mutex_unlock(&wldev->wl->mutex);
  145. return count;
  146. }
  147. static ssize_t b43_attr_preamble_store(struct device *dev,
  148. struct device_attribute *attr,
  149. const char *buf, size_t count)
  150. {
  151. struct b43_wldev *wldev = dev_to_b43_wldev(dev);
  152. unsigned long flags;
  153. int value;
  154. if (!capable(CAP_NET_ADMIN))
  155. return -EPERM;
  156. value = get_boolean(buf, count);
  157. if (value < 0)
  158. return value;
  159. mutex_lock(&wldev->wl->mutex);
  160. spin_lock_irqsave(&wldev->wl->irq_lock, flags);
  161. wldev->short_preamble = !!value;
  162. spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
  163. mutex_unlock(&wldev->wl->mutex);
  164. return count;
  165. }
  166. static DEVICE_ATTR(shortpreamble, 0644,
  167. b43_attr_preamble_show, b43_attr_preamble_store);
  168. int b43_sysfs_register(struct b43_wldev *wldev)
  169. {
  170. struct device *dev = wldev->dev->dev;
  171. int err;
  172. B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
  173. err = device_create_file(dev, &dev_attr_interference);
  174. if (err)
  175. goto out;
  176. err = device_create_file(dev, &dev_attr_shortpreamble);
  177. if (err)
  178. goto err_remove_interfmode;
  179. out:
  180. return err;
  181. err_remove_interfmode:
  182. device_remove_file(dev, &dev_attr_interference);
  183. goto out;
  184. }
  185. void b43_sysfs_unregister(struct b43_wldev *wldev)
  186. {
  187. struct device *dev = wldev->dev->dev;
  188. device_remove_file(dev, &dev_attr_shortpreamble);
  189. device_remove_file(dev, &dev_attr_interference);
  190. }