zd_netdev.c 7.4 KB

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