zd_netdev.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 */
  68. strlcpy(req->name, "IEEE 802.11b/g", IFNAMSIZ);
  69. return 0;
  70. }
  71. static int iw_get_nick(struct net_device *netdev,
  72. struct iw_request_info *info,
  73. union iwreq_data *req, char *extra)
  74. {
  75. strcpy(extra, "zd1211");
  76. req->data.length = strlen(extra);
  77. req->data.flags = 1;
  78. return 0;
  79. }
  80. static int iw_set_freq(struct net_device *netdev,
  81. struct iw_request_info *info,
  82. union iwreq_data *req, char *extra)
  83. {
  84. int r;
  85. struct zd_mac *mac = zd_netdev_mac(netdev);
  86. struct iw_freq *freq = &req->freq;
  87. u8 channel;
  88. r = zd_find_channel(&channel, freq);
  89. if (r < 0)
  90. return r;
  91. r = zd_mac_request_channel(mac, channel);
  92. return r;
  93. }
  94. static int iw_get_freq(struct net_device *netdev,
  95. struct iw_request_info *info,
  96. union iwreq_data *req, char *extra)
  97. {
  98. int r;
  99. struct zd_mac *mac = zd_netdev_mac(netdev);
  100. struct iw_freq *freq = &req->freq;
  101. u8 channel;
  102. u8 flags;
  103. r = zd_mac_get_channel(mac, &channel, &flags);
  104. if (r)
  105. return r;
  106. freq->flags = (flags & MAC_FIXED_CHANNEL) ?
  107. IW_FREQ_FIXED : IW_FREQ_AUTO;
  108. dev_dbg_f(zd_mac_dev(mac), "channel %s\n",
  109. (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto");
  110. return zd_channel_to_freq(freq, channel);
  111. }
  112. static int iw_set_mode(struct net_device *netdev,
  113. struct iw_request_info *info,
  114. union iwreq_data *req, char *extra)
  115. {
  116. return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode);
  117. }
  118. static int iw_get_mode(struct net_device *netdev,
  119. struct iw_request_info *info,
  120. union iwreq_data *req, char *extra)
  121. {
  122. return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode);
  123. }
  124. static int iw_get_range(struct net_device *netdev,
  125. struct iw_request_info *info,
  126. union iwreq_data *req, char *extra)
  127. {
  128. struct iw_range *range = (struct iw_range *)extra;
  129. dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
  130. req->data.length = sizeof(*range);
  131. return zd_mac_get_range(zd_netdev_mac(netdev), range);
  132. }
  133. static int iw_set_encode(struct net_device *netdev,
  134. struct iw_request_info *info,
  135. union iwreq_data *data,
  136. char *extra)
  137. {
  138. return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info,
  139. data, extra);
  140. }
  141. static int iw_get_encode(struct net_device *netdev,
  142. struct iw_request_info *info,
  143. union iwreq_data *data,
  144. char *extra)
  145. {
  146. return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info,
  147. data, extra);
  148. }
  149. static int iw_set_encodeext(struct net_device *netdev,
  150. struct iw_request_info *info,
  151. union iwreq_data *data,
  152. char *extra)
  153. {
  154. return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info,
  155. data, extra);
  156. }
  157. static int iw_get_encodeext(struct net_device *netdev,
  158. struct iw_request_info *info,
  159. union iwreq_data *data,
  160. char *extra)
  161. {
  162. return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info,
  163. data, extra);
  164. }
  165. #define WX(x) [(x)-SIOCIWFIRST]
  166. static const iw_handler zd_standard_iw_handlers[] = {
  167. WX(SIOCGIWNAME) = iw_get_name,
  168. WX(SIOCGIWNICKN) = iw_get_nick,
  169. WX(SIOCSIWFREQ) = iw_set_freq,
  170. WX(SIOCGIWFREQ) = iw_get_freq,
  171. WX(SIOCSIWMODE) = iw_set_mode,
  172. WX(SIOCGIWMODE) = iw_get_mode,
  173. WX(SIOCGIWRANGE) = iw_get_range,
  174. WX(SIOCSIWENCODE) = iw_set_encode,
  175. WX(SIOCGIWENCODE) = iw_get_encode,
  176. WX(SIOCSIWENCODEEXT) = iw_set_encodeext,
  177. WX(SIOCGIWENCODEEXT) = iw_get_encodeext,
  178. WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
  179. WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
  180. WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
  181. WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
  182. WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
  183. WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
  184. WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
  185. WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
  186. WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
  187. WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
  188. WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
  189. WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
  190. WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme,
  191. };
  192. static const struct iw_handler_def iw_handler_def = {
  193. .standard = zd_standard_iw_handlers,
  194. .num_standard = ARRAY_SIZE(zd_standard_iw_handlers),
  195. .private = zd_priv_handler,
  196. .num_private = ARRAY_SIZE(zd_priv_handler),
  197. .private_args = zd_priv_args,
  198. .num_private_args = ARRAY_SIZE(zd_priv_args),
  199. .get_wireless_stats = zd_mac_get_wireless_stats,
  200. };
  201. struct net_device *zd_netdev_alloc(struct usb_interface *intf)
  202. {
  203. int r;
  204. struct net_device *netdev;
  205. struct zd_mac *mac;
  206. netdev = alloc_ieee80211softmac(sizeof(struct zd_mac));
  207. if (!netdev) {
  208. dev_dbg_f(&intf->dev, "out of memory\n");
  209. return NULL;
  210. }
  211. mac = zd_netdev_mac(netdev);
  212. r = zd_mac_init(mac, netdev, intf);
  213. if (r) {
  214. usb_set_intfdata(intf, NULL);
  215. free_ieee80211(netdev);
  216. return NULL;
  217. }
  218. SET_MODULE_OWNER(netdev);
  219. SET_NETDEV_DEV(netdev, &intf->dev);
  220. dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags);
  221. dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features);
  222. netdev->open = zd_mac_open;
  223. netdev->stop = zd_mac_stop;
  224. /* netdev->get_stats = */
  225. /* netdev->set_multicast_list = */
  226. netdev->set_mac_address = zd_mac_set_mac_address;
  227. netdev->wireless_handlers = &iw_handler_def;
  228. /* netdev->ethtool_ops = */
  229. return netdev;
  230. }
  231. void zd_netdev_free(struct net_device *netdev)
  232. {
  233. if (!netdev)
  234. return;
  235. zd_mac_clear(zd_netdev_mac(netdev));
  236. free_ieee80211(netdev);
  237. }
  238. void zd_netdev_disconnect(struct net_device *netdev)
  239. {
  240. unregister_netdev(netdev);
  241. }