zd_netdev.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /* zd_netdev.c
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. #include <linux/netdevice.h>
  18. #include <linux/etherdevice.h>
  19. #include <linux/skbuff.h>
  20. #include <net/ieee80211.h>
  21. #include <net/ieee80211softmac.h>
  22. #include <net/ieee80211softmac_wx.h>
  23. #include <net/iw_handler.h>
  24. #include "zd_def.h"
  25. #include "zd_netdev.h"
  26. #include "zd_mac.h"
  27. #include "zd_ieee80211.h"
  28. /* Region 0 means reset regdomain to default. */
  29. static int zd_set_regdomain(struct net_device *netdev,
  30. struct iw_request_info *info,
  31. union iwreq_data *req, char *extra)
  32. {
  33. const u8 *regdomain = (u8 *)req;
  34. return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain);
  35. }
  36. static int zd_get_regdomain(struct net_device *netdev,
  37. struct iw_request_info *info,
  38. union iwreq_data *req, char *extra)
  39. {
  40. u8 *regdomain = (u8 *)req;
  41. if (!regdomain)
  42. return -EINVAL;
  43. *regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev));
  44. return 0;
  45. }
  46. static const struct iw_priv_args zd_priv_args[] = {
  47. {
  48. .cmd = ZD_PRIV_SET_REGDOMAIN,
  49. .set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
  50. .name = "set_regdomain",
  51. },
  52. {
  53. .cmd = ZD_PRIV_GET_REGDOMAIN,
  54. .get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
  55. .name = "get_regdomain",
  56. },
  57. };
  58. #define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV]
  59. static const iw_handler zd_priv_handler[] = {
  60. PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain,
  61. PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain,
  62. };
  63. static int iw_get_name(struct net_device *netdev,
  64. struct iw_request_info *info,
  65. union iwreq_data *req, char *extra)
  66. {
  67. /* FIXME: check whether 802.11a will also supported, add also
  68. * zd1211B, if we support it.
  69. */
  70. strlcpy(req->name, "802.11g zd1211", IFNAMSIZ);
  71. return 0;
  72. }
  73. static int iw_set_freq(struct net_device *netdev,
  74. struct iw_request_info *info,
  75. union iwreq_data *req, char *extra)
  76. {
  77. int r;
  78. struct zd_mac *mac = zd_netdev_mac(netdev);
  79. struct iw_freq *freq = &req->freq;
  80. u8 channel;
  81. r = zd_find_channel(&channel, freq);
  82. if (r < 0)
  83. return r;
  84. r = zd_mac_request_channel(mac, channel);
  85. return r;
  86. }
  87. static int iw_get_freq(struct net_device *netdev,
  88. struct iw_request_info *info,
  89. union iwreq_data *req, char *extra)
  90. {
  91. int r;
  92. struct zd_mac *mac = zd_netdev_mac(netdev);
  93. struct iw_freq *freq = &req->freq;
  94. u8 channel;
  95. u8 flags;
  96. r = zd_mac_get_channel(mac, &channel, &flags);
  97. if (r)
  98. return r;
  99. freq->flags = (flags & MAC_FIXED_CHANNEL) ?
  100. IW_FREQ_FIXED : IW_FREQ_AUTO;
  101. dev_dbg_f(zd_mac_dev(mac), "channel %s\n",
  102. (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto");
  103. return zd_channel_to_freq(freq, channel);
  104. }
  105. static int iw_set_mode(struct net_device *netdev,
  106. struct iw_request_info *info,
  107. union iwreq_data *req, char *extra)
  108. {
  109. return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode);
  110. }
  111. static int iw_get_mode(struct net_device *netdev,
  112. struct iw_request_info *info,
  113. union iwreq_data *req, char *extra)
  114. {
  115. return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode);
  116. }
  117. static int iw_get_range(struct net_device *netdev,
  118. struct iw_request_info *info,
  119. union iwreq_data *req, char *extra)
  120. {
  121. struct iw_range *range = (struct iw_range *)extra;
  122. dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
  123. req->data.length = sizeof(*range);
  124. return zd_mac_get_range(zd_netdev_mac(netdev), range);
  125. }
  126. static int iw_set_encode(struct net_device *netdev,
  127. struct iw_request_info *info,
  128. union iwreq_data *data,
  129. char *extra)
  130. {
  131. return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info,
  132. data, extra);
  133. }
  134. static int iw_get_encode(struct net_device *netdev,
  135. struct iw_request_info *info,
  136. union iwreq_data *data,
  137. char *extra)
  138. {
  139. return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info,
  140. data, extra);
  141. }
  142. static int iw_set_encodeext(struct net_device *netdev,
  143. struct iw_request_info *info,
  144. union iwreq_data *data,
  145. char *extra)
  146. {
  147. return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info,
  148. data, extra);
  149. }
  150. static int iw_get_encodeext(struct net_device *netdev,
  151. struct iw_request_info *info,
  152. union iwreq_data *data,
  153. char *extra)
  154. {
  155. return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info,
  156. data, extra);
  157. }
  158. #define WX(x) [(x)-SIOCIWFIRST]
  159. static const iw_handler zd_standard_iw_handlers[] = {
  160. WX(SIOCGIWNAME) = iw_get_name,
  161. WX(SIOCSIWFREQ) = iw_set_freq,
  162. WX(SIOCGIWFREQ) = iw_get_freq,
  163. WX(SIOCSIWMODE) = iw_set_mode,
  164. WX(SIOCGIWMODE) = iw_get_mode,
  165. WX(SIOCGIWRANGE) = iw_get_range,
  166. WX(SIOCSIWENCODE) = iw_set_encode,
  167. WX(SIOCGIWENCODE) = iw_get_encode,
  168. WX(SIOCSIWENCODEEXT) = iw_set_encodeext,
  169. WX(SIOCGIWENCODEEXT) = iw_get_encodeext,
  170. WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
  171. WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
  172. WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
  173. WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
  174. WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
  175. WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
  176. WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
  177. WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
  178. WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
  179. WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
  180. WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
  181. WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
  182. WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme,
  183. };
  184. static const struct iw_handler_def iw_handler_def = {
  185. .standard = zd_standard_iw_handlers,
  186. .num_standard = ARRAY_SIZE(zd_standard_iw_handlers),
  187. .private = zd_priv_handler,
  188. .num_private = ARRAY_SIZE(zd_priv_handler),
  189. .private_args = zd_priv_args,
  190. .num_private_args = ARRAY_SIZE(zd_priv_args),
  191. .get_wireless_stats = zd_mac_get_wireless_stats,
  192. };
  193. struct net_device *zd_netdev_alloc(struct usb_interface *intf)
  194. {
  195. int r;
  196. struct net_device *netdev;
  197. struct zd_mac *mac;
  198. netdev = alloc_ieee80211softmac(sizeof(struct zd_mac));
  199. if (!netdev) {
  200. dev_dbg_f(&intf->dev, "out of memory\n");
  201. return NULL;
  202. }
  203. mac = zd_netdev_mac(netdev);
  204. r = zd_mac_init(mac, netdev, intf);
  205. if (r) {
  206. usb_set_intfdata(intf, NULL);
  207. free_ieee80211(netdev);
  208. return NULL;
  209. }
  210. SET_MODULE_OWNER(netdev);
  211. SET_NETDEV_DEV(netdev, &intf->dev);
  212. dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags);
  213. dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features);
  214. netdev->open = zd_mac_open;
  215. netdev->stop = zd_mac_stop;
  216. /* netdev->get_stats = */
  217. /* netdev->set_multicast_list = */
  218. netdev->set_mac_address = zd_mac_set_mac_address;
  219. netdev->wireless_handlers = &iw_handler_def;
  220. /* netdev->ethtool_ops = */
  221. return netdev;
  222. }
  223. void zd_netdev_free(struct net_device *netdev)
  224. {
  225. if (!netdev)
  226. return;
  227. zd_mac_clear(zd_netdev_mac(netdev));
  228. free_ieee80211(netdev);
  229. }
  230. void zd_netdev_disconnect(struct net_device *netdev)
  231. {
  232. unregister_netdev(netdev);
  233. }