wext.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399
  1. /* Wireless extensions support.
  2. *
  3. * See copyright notice in main.c
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/if_arp.h>
  7. #include <linux/wireless.h>
  8. #include <linux/ieee80211.h>
  9. #include <net/iw_handler.h>
  10. #include <net/cfg80211.h>
  11. #include "hermes.h"
  12. #include "hermes_rid.h"
  13. #include "orinoco.h"
  14. #include "hw.h"
  15. #include "mic.h"
  16. #include "scan.h"
  17. #include "main.h"
  18. #include "wext.h"
  19. #define MAX_RID_LEN 1024
  20. /* Helper routine to record keys
  21. * It is called under orinoco_lock so it may not sleep */
  22. static int orinoco_set_key(struct orinoco_private *priv, int index,
  23. enum orinoco_alg alg, const u8 *key, int key_len,
  24. const u8 *seq, int seq_len)
  25. {
  26. kzfree(priv->keys[index].key);
  27. kzfree(priv->keys[index].seq);
  28. if (key_len) {
  29. priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
  30. if (!priv->keys[index].key)
  31. goto nomem;
  32. } else
  33. priv->keys[index].key = NULL;
  34. if (seq_len) {
  35. priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
  36. if (!priv->keys[index].seq)
  37. goto free_key;
  38. } else
  39. priv->keys[index].seq = NULL;
  40. priv->keys[index].key_len = key_len;
  41. priv->keys[index].seq_len = seq_len;
  42. if (key_len)
  43. memcpy(priv->keys[index].key, key, key_len);
  44. if (seq_len)
  45. memcpy(priv->keys[index].seq, seq, seq_len);
  46. switch (alg) {
  47. case ORINOCO_ALG_TKIP:
  48. priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
  49. break;
  50. case ORINOCO_ALG_WEP:
  51. priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
  52. WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
  53. break;
  54. case ORINOCO_ALG_NONE:
  55. default:
  56. priv->keys[index].cipher = 0;
  57. break;
  58. }
  59. return 0;
  60. free_key:
  61. kfree(priv->keys[index].key);
  62. priv->keys[index].key = NULL;
  63. nomem:
  64. priv->keys[index].key_len = 0;
  65. priv->keys[index].seq_len = 0;
  66. priv->keys[index].cipher = 0;
  67. return -ENOMEM;
  68. }
  69. static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
  70. {
  71. struct orinoco_private *priv = ndev_priv(dev);
  72. hermes_t *hw = &priv->hw;
  73. struct iw_statistics *wstats = &priv->wstats;
  74. int err;
  75. unsigned long flags;
  76. if (!netif_device_present(dev)) {
  77. printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
  78. dev->name);
  79. return NULL; /* FIXME: Can we do better than this? */
  80. }
  81. /* If busy, return the old stats. Returning NULL may cause
  82. * the interface to disappear from /proc/net/wireless */
  83. if (orinoco_lock(priv, &flags) != 0)
  84. return wstats;
  85. /* We can't really wait for the tallies inquiry command to
  86. * complete, so we just use the previous results and trigger
  87. * a new tallies inquiry command for next time - Jean II */
  88. /* FIXME: Really we should wait for the inquiry to come back -
  89. * as it is the stats we give don't make a whole lot of sense.
  90. * Unfortunately, it's not clear how to do that within the
  91. * wireless extensions framework: I think we're in user
  92. * context, but a lock seems to be held by the time we get in
  93. * here so we're not safe to sleep here. */
  94. hermes_inquire(hw, HERMES_INQ_TALLIES);
  95. if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
  96. memset(&wstats->qual, 0, sizeof(wstats->qual));
  97. /* If a spy address is defined, we report stats of the
  98. * first spy address - Jean II */
  99. if (SPY_NUMBER(priv)) {
  100. wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
  101. wstats->qual.level = priv->spy_data.spy_stat[0].level;
  102. wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
  103. wstats->qual.updated =
  104. priv->spy_data.spy_stat[0].updated;
  105. }
  106. } else {
  107. struct {
  108. __le16 qual, signal, noise, unused;
  109. } __attribute__ ((packed)) cq;
  110. err = HERMES_READ_RECORD(hw, USER_BAP,
  111. HERMES_RID_COMMSQUALITY, &cq);
  112. if (!err) {
  113. wstats->qual.qual = (int)le16_to_cpu(cq.qual);
  114. wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
  115. wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
  116. wstats->qual.updated =
  117. IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
  118. }
  119. }
  120. orinoco_unlock(priv, &flags);
  121. return wstats;
  122. }
  123. /********************************************************************/
  124. /* Wireless extensions */
  125. /********************************************************************/
  126. static int orinoco_ioctl_setwap(struct net_device *dev,
  127. struct iw_request_info *info,
  128. struct sockaddr *ap_addr,
  129. char *extra)
  130. {
  131. struct orinoco_private *priv = ndev_priv(dev);
  132. int err = -EINPROGRESS; /* Call commit handler */
  133. unsigned long flags;
  134. static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  135. static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  136. if (orinoco_lock(priv, &flags) != 0)
  137. return -EBUSY;
  138. /* Enable automatic roaming - no sanity checks are needed */
  139. if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
  140. memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
  141. priv->bssid_fixed = 0;
  142. memset(priv->desired_bssid, 0, ETH_ALEN);
  143. /* "off" means keep existing connection */
  144. if (ap_addr->sa_data[0] == 0) {
  145. __orinoco_hw_set_wap(priv);
  146. err = 0;
  147. }
  148. goto out;
  149. }
  150. if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
  151. printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
  152. "support manual roaming\n",
  153. dev->name);
  154. err = -EOPNOTSUPP;
  155. goto out;
  156. }
  157. if (priv->iw_mode != NL80211_IFTYPE_STATION) {
  158. printk(KERN_WARNING "%s: Manual roaming supported only in "
  159. "managed mode\n", dev->name);
  160. err = -EOPNOTSUPP;
  161. goto out;
  162. }
  163. /* Intersil firmware hangs without Desired ESSID */
  164. if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
  165. strlen(priv->desired_essid) == 0) {
  166. printk(KERN_WARNING "%s: Desired ESSID must be set for "
  167. "manual roaming\n", dev->name);
  168. err = -EOPNOTSUPP;
  169. goto out;
  170. }
  171. /* Finally, enable manual roaming */
  172. priv->bssid_fixed = 1;
  173. memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
  174. out:
  175. orinoco_unlock(priv, &flags);
  176. return err;
  177. }
  178. static int orinoco_ioctl_getwap(struct net_device *dev,
  179. struct iw_request_info *info,
  180. struct sockaddr *ap_addr,
  181. char *extra)
  182. {
  183. struct orinoco_private *priv = ndev_priv(dev);
  184. int err = 0;
  185. unsigned long flags;
  186. if (orinoco_lock(priv, &flags) != 0)
  187. return -EBUSY;
  188. ap_addr->sa_family = ARPHRD_ETHER;
  189. err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
  190. orinoco_unlock(priv, &flags);
  191. return err;
  192. }
  193. static int orinoco_ioctl_setiwencode(struct net_device *dev,
  194. struct iw_request_info *info,
  195. struct iw_point *erq,
  196. char *keybuf)
  197. {
  198. struct orinoco_private *priv = ndev_priv(dev);
  199. int index = (erq->flags & IW_ENCODE_INDEX) - 1;
  200. int setindex = priv->tx_key;
  201. enum orinoco_alg encode_alg = priv->encode_alg;
  202. int restricted = priv->wep_restrict;
  203. int err = -EINPROGRESS; /* Call commit handler */
  204. unsigned long flags;
  205. if (!priv->has_wep)
  206. return -EOPNOTSUPP;
  207. if (erq->pointer) {
  208. /* We actually have a key to set - check its length */
  209. if (erq->length > LARGE_KEY_SIZE)
  210. return -E2BIG;
  211. if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep)
  212. return -E2BIG;
  213. }
  214. if (orinoco_lock(priv, &flags) != 0)
  215. return -EBUSY;
  216. /* Clear any TKIP key we have */
  217. if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
  218. (void) orinoco_clear_tkip_key(priv, setindex);
  219. if (erq->length > 0) {
  220. if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
  221. index = priv->tx_key;
  222. /* Switch on WEP if off */
  223. if (encode_alg != ORINOCO_ALG_WEP) {
  224. setindex = index;
  225. encode_alg = ORINOCO_ALG_WEP;
  226. }
  227. } else {
  228. /* Important note : if the user do "iwconfig eth0 enc off",
  229. * we will arrive there with an index of -1. This is valid
  230. * but need to be taken care off... Jean II */
  231. if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
  232. if ((index != -1) || (erq->flags == 0)) {
  233. err = -EINVAL;
  234. goto out;
  235. }
  236. } else {
  237. /* Set the index : Check that the key is valid */
  238. if (priv->keys[index].key_len == 0) {
  239. err = -EINVAL;
  240. goto out;
  241. }
  242. setindex = index;
  243. }
  244. }
  245. if (erq->flags & IW_ENCODE_DISABLED)
  246. encode_alg = ORINOCO_ALG_NONE;
  247. if (erq->flags & IW_ENCODE_OPEN)
  248. restricted = 0;
  249. if (erq->flags & IW_ENCODE_RESTRICTED)
  250. restricted = 1;
  251. if (erq->pointer && erq->length > 0) {
  252. err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
  253. erq->length, NULL, 0);
  254. }
  255. priv->tx_key = setindex;
  256. /* Try fast key change if connected and only keys are changed */
  257. if ((priv->encode_alg == encode_alg) &&
  258. (priv->wep_restrict == restricted) &&
  259. netif_carrier_ok(dev)) {
  260. err = __orinoco_hw_setup_wepkeys(priv);
  261. /* No need to commit if successful */
  262. goto out;
  263. }
  264. priv->encode_alg = encode_alg;
  265. priv->wep_restrict = restricted;
  266. out:
  267. orinoco_unlock(priv, &flags);
  268. return err;
  269. }
  270. static int orinoco_ioctl_getiwencode(struct net_device *dev,
  271. struct iw_request_info *info,
  272. struct iw_point *erq,
  273. char *keybuf)
  274. {
  275. struct orinoco_private *priv = ndev_priv(dev);
  276. int index = (erq->flags & IW_ENCODE_INDEX) - 1;
  277. unsigned long flags;
  278. if (!priv->has_wep)
  279. return -EOPNOTSUPP;
  280. if (orinoco_lock(priv, &flags) != 0)
  281. return -EBUSY;
  282. if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
  283. index = priv->tx_key;
  284. erq->flags = 0;
  285. if (!priv->encode_alg)
  286. erq->flags |= IW_ENCODE_DISABLED;
  287. erq->flags |= index + 1;
  288. if (priv->wep_restrict)
  289. erq->flags |= IW_ENCODE_RESTRICTED;
  290. else
  291. erq->flags |= IW_ENCODE_OPEN;
  292. erq->length = priv->keys[index].key_len;
  293. memcpy(keybuf, priv->keys[index].key, erq->length);
  294. orinoco_unlock(priv, &flags);
  295. return 0;
  296. }
  297. static int orinoco_ioctl_setessid(struct net_device *dev,
  298. struct iw_request_info *info,
  299. struct iw_point *erq,
  300. char *essidbuf)
  301. {
  302. struct orinoco_private *priv = ndev_priv(dev);
  303. unsigned long flags;
  304. /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
  305. * anyway... - Jean II */
  306. /* Hum... Should not use Wireless Extension constant (may change),
  307. * should use our own... - Jean II */
  308. if (erq->length > IW_ESSID_MAX_SIZE)
  309. return -E2BIG;
  310. if (orinoco_lock(priv, &flags) != 0)
  311. return -EBUSY;
  312. /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
  313. memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
  314. /* If not ANY, get the new ESSID */
  315. if (erq->flags)
  316. memcpy(priv->desired_essid, essidbuf, erq->length);
  317. orinoco_unlock(priv, &flags);
  318. return -EINPROGRESS; /* Call commit handler */
  319. }
  320. static int orinoco_ioctl_getessid(struct net_device *dev,
  321. struct iw_request_info *info,
  322. struct iw_point *erq,
  323. char *essidbuf)
  324. {
  325. struct orinoco_private *priv = ndev_priv(dev);
  326. int active;
  327. int err = 0;
  328. unsigned long flags;
  329. if (netif_running(dev)) {
  330. err = orinoco_hw_get_essid(priv, &active, essidbuf);
  331. if (err < 0)
  332. return err;
  333. erq->length = err;
  334. } else {
  335. if (orinoco_lock(priv, &flags) != 0)
  336. return -EBUSY;
  337. memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
  338. erq->length = strlen(priv->desired_essid);
  339. orinoco_unlock(priv, &flags);
  340. }
  341. erq->flags = 1;
  342. return 0;
  343. }
  344. static int orinoco_ioctl_setfreq(struct net_device *dev,
  345. struct iw_request_info *info,
  346. struct iw_freq *frq,
  347. char *extra)
  348. {
  349. struct orinoco_private *priv = ndev_priv(dev);
  350. int chan = -1;
  351. unsigned long flags;
  352. int err = -EINPROGRESS; /* Call commit handler */
  353. /* In infrastructure mode the AP sets the channel */
  354. if (priv->iw_mode == NL80211_IFTYPE_STATION)
  355. return -EBUSY;
  356. if ((frq->e == 0) && (frq->m <= 1000)) {
  357. /* Setting by channel number */
  358. chan = frq->m;
  359. } else {
  360. /* Setting by frequency */
  361. int denom = 1;
  362. int i;
  363. /* Calculate denominator to rescale to MHz */
  364. for (i = 0; i < (6 - frq->e); i++)
  365. denom *= 10;
  366. chan = ieee80211_freq_to_dsss_chan(frq->m / denom);
  367. }
  368. if ((chan < 1) || (chan > NUM_CHANNELS) ||
  369. !(priv->channel_mask & (1 << (chan-1))))
  370. return -EINVAL;
  371. if (orinoco_lock(priv, &flags) != 0)
  372. return -EBUSY;
  373. priv->channel = chan;
  374. if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
  375. /* Fast channel change - no commit if successful */
  376. hermes_t *hw = &priv->hw;
  377. err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
  378. HERMES_TEST_SET_CHANNEL,
  379. chan, NULL);
  380. }
  381. orinoco_unlock(priv, &flags);
  382. return err;
  383. }
  384. static int orinoco_ioctl_getfreq(struct net_device *dev,
  385. struct iw_request_info *info,
  386. struct iw_freq *frq,
  387. char *extra)
  388. {
  389. struct orinoco_private *priv = ndev_priv(dev);
  390. int tmp;
  391. /* Locking done in there */
  392. tmp = orinoco_hw_get_freq(priv);
  393. if (tmp < 0)
  394. return tmp;
  395. frq->m = tmp * 100000;
  396. frq->e = 1;
  397. return 0;
  398. }
  399. static int orinoco_ioctl_getsens(struct net_device *dev,
  400. struct iw_request_info *info,
  401. struct iw_param *srq,
  402. char *extra)
  403. {
  404. struct orinoco_private *priv = ndev_priv(dev);
  405. hermes_t *hw = &priv->hw;
  406. u16 val;
  407. int err;
  408. unsigned long flags;
  409. if (!priv->has_sensitivity)
  410. return -EOPNOTSUPP;
  411. if (orinoco_lock(priv, &flags) != 0)
  412. return -EBUSY;
  413. err = hermes_read_wordrec(hw, USER_BAP,
  414. HERMES_RID_CNFSYSTEMSCALE, &val);
  415. orinoco_unlock(priv, &flags);
  416. if (err)
  417. return err;
  418. srq->value = val;
  419. srq->fixed = 0; /* auto */
  420. return 0;
  421. }
  422. static int orinoco_ioctl_setsens(struct net_device *dev,
  423. struct iw_request_info *info,
  424. struct iw_param *srq,
  425. char *extra)
  426. {
  427. struct orinoco_private *priv = ndev_priv(dev);
  428. int val = srq->value;
  429. unsigned long flags;
  430. if (!priv->has_sensitivity)
  431. return -EOPNOTSUPP;
  432. if ((val < 1) || (val > 3))
  433. return -EINVAL;
  434. if (orinoco_lock(priv, &flags) != 0)
  435. return -EBUSY;
  436. priv->ap_density = val;
  437. orinoco_unlock(priv, &flags);
  438. return -EINPROGRESS; /* Call commit handler */
  439. }
  440. static int orinoco_ioctl_setrate(struct net_device *dev,
  441. struct iw_request_info *info,
  442. struct iw_param *rrq,
  443. char *extra)
  444. {
  445. struct orinoco_private *priv = ndev_priv(dev);
  446. int ratemode;
  447. int bitrate; /* 100s of kilobits */
  448. unsigned long flags;
  449. /* As the user space doesn't know our highest rate, it uses -1
  450. * to ask us to set the highest rate. Test it using "iwconfig
  451. * ethX rate auto" - Jean II */
  452. if (rrq->value == -1)
  453. bitrate = 110;
  454. else {
  455. if (rrq->value % 100000)
  456. return -EINVAL;
  457. bitrate = rrq->value / 100000;
  458. }
  459. ratemode = orinoco_get_bitratemode(bitrate, !rrq->fixed);
  460. if (ratemode == -1)
  461. return -EINVAL;
  462. if (orinoco_lock(priv, &flags) != 0)
  463. return -EBUSY;
  464. priv->bitratemode = ratemode;
  465. orinoco_unlock(priv, &flags);
  466. return -EINPROGRESS;
  467. }
  468. static int orinoco_ioctl_getrate(struct net_device *dev,
  469. struct iw_request_info *info,
  470. struct iw_param *rrq,
  471. char *extra)
  472. {
  473. struct orinoco_private *priv = ndev_priv(dev);
  474. int err = 0;
  475. int bitrate, automatic;
  476. unsigned long flags;
  477. if (orinoco_lock(priv, &flags) != 0)
  478. return -EBUSY;
  479. orinoco_get_ratemode_cfg(priv->bitratemode, &bitrate, &automatic);
  480. /* If the interface is running we try to find more about the
  481. current mode */
  482. if (netif_running(dev))
  483. err = orinoco_hw_get_act_bitrate(priv, &bitrate);
  484. orinoco_unlock(priv, &flags);
  485. rrq->value = bitrate;
  486. rrq->fixed = !automatic;
  487. rrq->disabled = 0;
  488. return err;
  489. }
  490. static int orinoco_ioctl_setpower(struct net_device *dev,
  491. struct iw_request_info *info,
  492. struct iw_param *prq,
  493. char *extra)
  494. {
  495. struct orinoco_private *priv = ndev_priv(dev);
  496. int err = -EINPROGRESS; /* Call commit handler */
  497. unsigned long flags;
  498. if (orinoco_lock(priv, &flags) != 0)
  499. return -EBUSY;
  500. if (prq->disabled) {
  501. priv->pm_on = 0;
  502. } else {
  503. switch (prq->flags & IW_POWER_MODE) {
  504. case IW_POWER_UNICAST_R:
  505. priv->pm_mcast = 0;
  506. priv->pm_on = 1;
  507. break;
  508. case IW_POWER_ALL_R:
  509. priv->pm_mcast = 1;
  510. priv->pm_on = 1;
  511. break;
  512. case IW_POWER_ON:
  513. /* No flags : but we may have a value - Jean II */
  514. break;
  515. default:
  516. err = -EINVAL;
  517. goto out;
  518. }
  519. if (prq->flags & IW_POWER_TIMEOUT) {
  520. priv->pm_on = 1;
  521. priv->pm_timeout = prq->value / 1000;
  522. }
  523. if (prq->flags & IW_POWER_PERIOD) {
  524. priv->pm_on = 1;
  525. priv->pm_period = prq->value / 1000;
  526. }
  527. /* It's valid to not have a value if we are just toggling
  528. * the flags... Jean II */
  529. if (!priv->pm_on) {
  530. err = -EINVAL;
  531. goto out;
  532. }
  533. }
  534. out:
  535. orinoco_unlock(priv, &flags);
  536. return err;
  537. }
  538. static int orinoco_ioctl_getpower(struct net_device *dev,
  539. struct iw_request_info *info,
  540. struct iw_param *prq,
  541. char *extra)
  542. {
  543. struct orinoco_private *priv = ndev_priv(dev);
  544. hermes_t *hw = &priv->hw;
  545. int err = 0;
  546. u16 enable, period, timeout, mcast;
  547. unsigned long flags;
  548. if (orinoco_lock(priv, &flags) != 0)
  549. return -EBUSY;
  550. err = hermes_read_wordrec(hw, USER_BAP,
  551. HERMES_RID_CNFPMENABLED, &enable);
  552. if (err)
  553. goto out;
  554. err = hermes_read_wordrec(hw, USER_BAP,
  555. HERMES_RID_CNFMAXSLEEPDURATION, &period);
  556. if (err)
  557. goto out;
  558. err = hermes_read_wordrec(hw, USER_BAP,
  559. HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
  560. if (err)
  561. goto out;
  562. err = hermes_read_wordrec(hw, USER_BAP,
  563. HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
  564. if (err)
  565. goto out;
  566. prq->disabled = !enable;
  567. /* Note : by default, display the period */
  568. if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
  569. prq->flags = IW_POWER_TIMEOUT;
  570. prq->value = timeout * 1000;
  571. } else {
  572. prq->flags = IW_POWER_PERIOD;
  573. prq->value = period * 1000;
  574. }
  575. if (mcast)
  576. prq->flags |= IW_POWER_ALL_R;
  577. else
  578. prq->flags |= IW_POWER_UNICAST_R;
  579. out:
  580. orinoco_unlock(priv, &flags);
  581. return err;
  582. }
  583. static int orinoco_ioctl_set_encodeext(struct net_device *dev,
  584. struct iw_request_info *info,
  585. union iwreq_data *wrqu,
  586. char *extra)
  587. {
  588. struct orinoco_private *priv = ndev_priv(dev);
  589. struct iw_point *encoding = &wrqu->encoding;
  590. struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
  591. int idx, alg = ext->alg, set_key = 1;
  592. unsigned long flags;
  593. int err = -EINVAL;
  594. if (orinoco_lock(priv, &flags) != 0)
  595. return -EBUSY;
  596. /* Determine and validate the key index */
  597. idx = encoding->flags & IW_ENCODE_INDEX;
  598. if (idx) {
  599. if ((idx < 1) || (idx > 4))
  600. goto out;
  601. idx--;
  602. } else
  603. idx = priv->tx_key;
  604. if (encoding->flags & IW_ENCODE_DISABLED)
  605. alg = IW_ENCODE_ALG_NONE;
  606. if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
  607. /* Clear any TKIP TX key we had */
  608. (void) orinoco_clear_tkip_key(priv, priv->tx_key);
  609. }
  610. if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
  611. priv->tx_key = idx;
  612. set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
  613. (ext->key_len > 0)) ? 1 : 0;
  614. }
  615. if (set_key) {
  616. /* Set the requested key first */
  617. switch (alg) {
  618. case IW_ENCODE_ALG_NONE:
  619. priv->encode_alg = ORINOCO_ALG_NONE;
  620. err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
  621. NULL, 0, NULL, 0);
  622. break;
  623. case IW_ENCODE_ALG_WEP:
  624. if (ext->key_len <= 0)
  625. goto out;
  626. priv->encode_alg = ORINOCO_ALG_WEP;
  627. err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
  628. ext->key, ext->key_len, NULL, 0);
  629. break;
  630. case IW_ENCODE_ALG_TKIP:
  631. {
  632. u8 *tkip_iv = NULL;
  633. if (!priv->has_wpa ||
  634. (ext->key_len > sizeof(struct orinoco_tkip_key)))
  635. goto out;
  636. priv->encode_alg = ORINOCO_ALG_TKIP;
  637. if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
  638. tkip_iv = &ext->rx_seq[0];
  639. err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
  640. ext->key, ext->key_len, tkip_iv,
  641. ORINOCO_SEQ_LEN);
  642. err = __orinoco_hw_set_tkip_key(priv, idx,
  643. ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
  644. priv->keys[idx].key,
  645. tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
  646. if (err)
  647. printk(KERN_ERR "%s: Error %d setting TKIP key"
  648. "\n", dev->name, err);
  649. goto out;
  650. }
  651. default:
  652. goto out;
  653. }
  654. }
  655. err = -EINPROGRESS;
  656. out:
  657. orinoco_unlock(priv, &flags);
  658. return err;
  659. }
  660. static int orinoco_ioctl_get_encodeext(struct net_device *dev,
  661. struct iw_request_info *info,
  662. union iwreq_data *wrqu,
  663. char *extra)
  664. {
  665. struct orinoco_private *priv = ndev_priv(dev);
  666. struct iw_point *encoding = &wrqu->encoding;
  667. struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
  668. int idx, max_key_len;
  669. unsigned long flags;
  670. int err;
  671. if (orinoco_lock(priv, &flags) != 0)
  672. return -EBUSY;
  673. err = -EINVAL;
  674. max_key_len = encoding->length - sizeof(*ext);
  675. if (max_key_len < 0)
  676. goto out;
  677. idx = encoding->flags & IW_ENCODE_INDEX;
  678. if (idx) {
  679. if ((idx < 1) || (idx > 4))
  680. goto out;
  681. idx--;
  682. } else
  683. idx = priv->tx_key;
  684. encoding->flags = idx + 1;
  685. memset(ext, 0, sizeof(*ext));
  686. switch (priv->encode_alg) {
  687. case ORINOCO_ALG_NONE:
  688. ext->alg = IW_ENCODE_ALG_NONE;
  689. ext->key_len = 0;
  690. encoding->flags |= IW_ENCODE_DISABLED;
  691. break;
  692. case ORINOCO_ALG_WEP:
  693. ext->alg = IW_ENCODE_ALG_WEP;
  694. ext->key_len = min(priv->keys[idx].key_len, max_key_len);
  695. memcpy(ext->key, priv->keys[idx].key, ext->key_len);
  696. encoding->flags |= IW_ENCODE_ENABLED;
  697. break;
  698. case ORINOCO_ALG_TKIP:
  699. ext->alg = IW_ENCODE_ALG_TKIP;
  700. ext->key_len = min(priv->keys[idx].key_len, max_key_len);
  701. memcpy(ext->key, priv->keys[idx].key, ext->key_len);
  702. encoding->flags |= IW_ENCODE_ENABLED;
  703. break;
  704. }
  705. err = 0;
  706. out:
  707. orinoco_unlock(priv, &flags);
  708. return err;
  709. }
  710. static int orinoco_ioctl_set_auth(struct net_device *dev,
  711. struct iw_request_info *info,
  712. union iwreq_data *wrqu, char *extra)
  713. {
  714. struct orinoco_private *priv = ndev_priv(dev);
  715. hermes_t *hw = &priv->hw;
  716. struct iw_param *param = &wrqu->param;
  717. unsigned long flags;
  718. int ret = -EINPROGRESS;
  719. if (orinoco_lock(priv, &flags) != 0)
  720. return -EBUSY;
  721. switch (param->flags & IW_AUTH_INDEX) {
  722. case IW_AUTH_WPA_VERSION:
  723. case IW_AUTH_CIPHER_PAIRWISE:
  724. case IW_AUTH_CIPHER_GROUP:
  725. case IW_AUTH_RX_UNENCRYPTED_EAPOL:
  726. case IW_AUTH_PRIVACY_INVOKED:
  727. case IW_AUTH_DROP_UNENCRYPTED:
  728. /*
  729. * orinoco does not use these parameters
  730. */
  731. break;
  732. case IW_AUTH_KEY_MGMT:
  733. /* wl_lkm implies value 2 == PSK for Hermes I
  734. * which ties in with WEXT
  735. * no other hints tho :(
  736. */
  737. priv->key_mgmt = param->value;
  738. break;
  739. case IW_AUTH_TKIP_COUNTERMEASURES:
  740. /* When countermeasures are enabled, shut down the
  741. * card; when disabled, re-enable the card. This must
  742. * take effect immediately.
  743. *
  744. * TODO: Make sure that the EAPOL message is getting
  745. * out before card disabled
  746. */
  747. if (param->value) {
  748. priv->tkip_cm_active = 1;
  749. ret = hermes_enable_port(hw, 0);
  750. } else {
  751. priv->tkip_cm_active = 0;
  752. ret = hermes_disable_port(hw, 0);
  753. }
  754. break;
  755. case IW_AUTH_80211_AUTH_ALG:
  756. if (param->value & IW_AUTH_ALG_SHARED_KEY)
  757. priv->wep_restrict = 1;
  758. else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
  759. priv->wep_restrict = 0;
  760. else
  761. ret = -EINVAL;
  762. break;
  763. case IW_AUTH_WPA_ENABLED:
  764. if (priv->has_wpa) {
  765. priv->wpa_enabled = param->value ? 1 : 0;
  766. } else {
  767. if (param->value)
  768. ret = -EOPNOTSUPP;
  769. /* else silently accept disable of WPA */
  770. priv->wpa_enabled = 0;
  771. }
  772. break;
  773. default:
  774. ret = -EOPNOTSUPP;
  775. }
  776. orinoco_unlock(priv, &flags);
  777. return ret;
  778. }
  779. static int orinoco_ioctl_get_auth(struct net_device *dev,
  780. struct iw_request_info *info,
  781. union iwreq_data *wrqu, char *extra)
  782. {
  783. struct orinoco_private *priv = ndev_priv(dev);
  784. struct iw_param *param = &wrqu->param;
  785. unsigned long flags;
  786. int ret = 0;
  787. if (orinoco_lock(priv, &flags) != 0)
  788. return -EBUSY;
  789. switch (param->flags & IW_AUTH_INDEX) {
  790. case IW_AUTH_KEY_MGMT:
  791. param->value = priv->key_mgmt;
  792. break;
  793. case IW_AUTH_TKIP_COUNTERMEASURES:
  794. param->value = priv->tkip_cm_active;
  795. break;
  796. case IW_AUTH_80211_AUTH_ALG:
  797. if (priv->wep_restrict)
  798. param->value = IW_AUTH_ALG_SHARED_KEY;
  799. else
  800. param->value = IW_AUTH_ALG_OPEN_SYSTEM;
  801. break;
  802. case IW_AUTH_WPA_ENABLED:
  803. param->value = priv->wpa_enabled;
  804. break;
  805. default:
  806. ret = -EOPNOTSUPP;
  807. }
  808. orinoco_unlock(priv, &flags);
  809. return ret;
  810. }
  811. static int orinoco_ioctl_set_genie(struct net_device *dev,
  812. struct iw_request_info *info,
  813. union iwreq_data *wrqu, char *extra)
  814. {
  815. struct orinoco_private *priv = ndev_priv(dev);
  816. u8 *buf;
  817. unsigned long flags;
  818. /* cut off at IEEE80211_MAX_DATA_LEN */
  819. if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
  820. (wrqu->data.length && (extra == NULL)))
  821. return -EINVAL;
  822. if (wrqu->data.length) {
  823. buf = kmalloc(wrqu->data.length, GFP_KERNEL);
  824. if (buf == NULL)
  825. return -ENOMEM;
  826. memcpy(buf, extra, wrqu->data.length);
  827. } else
  828. buf = NULL;
  829. if (orinoco_lock(priv, &flags) != 0) {
  830. kfree(buf);
  831. return -EBUSY;
  832. }
  833. kfree(priv->wpa_ie);
  834. priv->wpa_ie = buf;
  835. priv->wpa_ie_len = wrqu->data.length;
  836. if (priv->wpa_ie) {
  837. /* Looks like wl_lkm wants to check the auth alg, and
  838. * somehow pass it to the firmware.
  839. * Instead it just calls the key mgmt rid
  840. * - we do this in set auth.
  841. */
  842. }
  843. orinoco_unlock(priv, &flags);
  844. return 0;
  845. }
  846. static int orinoco_ioctl_get_genie(struct net_device *dev,
  847. struct iw_request_info *info,
  848. union iwreq_data *wrqu, char *extra)
  849. {
  850. struct orinoco_private *priv = ndev_priv(dev);
  851. unsigned long flags;
  852. int err = 0;
  853. if (orinoco_lock(priv, &flags) != 0)
  854. return -EBUSY;
  855. if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
  856. wrqu->data.length = 0;
  857. goto out;
  858. }
  859. if (wrqu->data.length < priv->wpa_ie_len) {
  860. err = -E2BIG;
  861. goto out;
  862. }
  863. wrqu->data.length = priv->wpa_ie_len;
  864. memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
  865. out:
  866. orinoco_unlock(priv, &flags);
  867. return err;
  868. }
  869. static int orinoco_ioctl_set_mlme(struct net_device *dev,
  870. struct iw_request_info *info,
  871. union iwreq_data *wrqu, char *extra)
  872. {
  873. struct orinoco_private *priv = ndev_priv(dev);
  874. struct iw_mlme *mlme = (struct iw_mlme *)extra;
  875. unsigned long flags;
  876. int ret = 0;
  877. if (orinoco_lock(priv, &flags) != 0)
  878. return -EBUSY;
  879. switch (mlme->cmd) {
  880. case IW_MLME_DEAUTH:
  881. /* silently ignore */
  882. break;
  883. case IW_MLME_DISASSOC:
  884. ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
  885. mlme->reason_code);
  886. break;
  887. default:
  888. ret = -EOPNOTSUPP;
  889. }
  890. orinoco_unlock(priv, &flags);
  891. return ret;
  892. }
  893. static int orinoco_ioctl_reset(struct net_device *dev,
  894. struct iw_request_info *info,
  895. void *wrqu,
  896. char *extra)
  897. {
  898. struct orinoco_private *priv = ndev_priv(dev);
  899. if (!capable(CAP_NET_ADMIN))
  900. return -EPERM;
  901. if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
  902. printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
  903. /* Firmware reset */
  904. orinoco_reset(&priv->reset_work);
  905. } else {
  906. printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
  907. schedule_work(&priv->reset_work);
  908. }
  909. return 0;
  910. }
  911. static int orinoco_ioctl_setibssport(struct net_device *dev,
  912. struct iw_request_info *info,
  913. void *wrqu,
  914. char *extra)
  915. {
  916. struct orinoco_private *priv = ndev_priv(dev);
  917. int val = *((int *) extra);
  918. unsigned long flags;
  919. if (orinoco_lock(priv, &flags) != 0)
  920. return -EBUSY;
  921. priv->ibss_port = val;
  922. /* Actually update the mode we are using */
  923. set_port_type(priv);
  924. orinoco_unlock(priv, &flags);
  925. return -EINPROGRESS; /* Call commit handler */
  926. }
  927. static int orinoco_ioctl_getibssport(struct net_device *dev,
  928. struct iw_request_info *info,
  929. void *wrqu,
  930. char *extra)
  931. {
  932. struct orinoco_private *priv = ndev_priv(dev);
  933. int *val = (int *) extra;
  934. *val = priv->ibss_port;
  935. return 0;
  936. }
  937. static int orinoco_ioctl_setport3(struct net_device *dev,
  938. struct iw_request_info *info,
  939. void *wrqu,
  940. char *extra)
  941. {
  942. struct orinoco_private *priv = ndev_priv(dev);
  943. int val = *((int *) extra);
  944. int err = 0;
  945. unsigned long flags;
  946. if (orinoco_lock(priv, &flags) != 0)
  947. return -EBUSY;
  948. switch (val) {
  949. case 0: /* Try to do IEEE ad-hoc mode */
  950. if (!priv->has_ibss) {
  951. err = -EINVAL;
  952. break;
  953. }
  954. priv->prefer_port3 = 0;
  955. break;
  956. case 1: /* Try to do Lucent proprietary ad-hoc mode */
  957. if (!priv->has_port3) {
  958. err = -EINVAL;
  959. break;
  960. }
  961. priv->prefer_port3 = 1;
  962. break;
  963. default:
  964. err = -EINVAL;
  965. }
  966. if (!err) {
  967. /* Actually update the mode we are using */
  968. set_port_type(priv);
  969. err = -EINPROGRESS;
  970. }
  971. orinoco_unlock(priv, &flags);
  972. return err;
  973. }
  974. static int orinoco_ioctl_getport3(struct net_device *dev,
  975. struct iw_request_info *info,
  976. void *wrqu,
  977. char *extra)
  978. {
  979. struct orinoco_private *priv = ndev_priv(dev);
  980. int *val = (int *) extra;
  981. *val = priv->prefer_port3;
  982. return 0;
  983. }
  984. static int orinoco_ioctl_setpreamble(struct net_device *dev,
  985. struct iw_request_info *info,
  986. void *wrqu,
  987. char *extra)
  988. {
  989. struct orinoco_private *priv = ndev_priv(dev);
  990. unsigned long flags;
  991. int val;
  992. if (!priv->has_preamble)
  993. return -EOPNOTSUPP;
  994. /* 802.11b has recently defined some short preamble.
  995. * Basically, the Phy header has been reduced in size.
  996. * This increase performance, especially at high rates
  997. * (the preamble is transmitted at 1Mb/s), unfortunately
  998. * this give compatibility troubles... - Jean II */
  999. val = *((int *) extra);
  1000. if (orinoco_lock(priv, &flags) != 0)
  1001. return -EBUSY;
  1002. if (val)
  1003. priv->preamble = 1;
  1004. else
  1005. priv->preamble = 0;
  1006. orinoco_unlock(priv, &flags);
  1007. return -EINPROGRESS; /* Call commit handler */
  1008. }
  1009. static int orinoco_ioctl_getpreamble(struct net_device *dev,
  1010. struct iw_request_info *info,
  1011. void *wrqu,
  1012. char *extra)
  1013. {
  1014. struct orinoco_private *priv = ndev_priv(dev);
  1015. int *val = (int *) extra;
  1016. if (!priv->has_preamble)
  1017. return -EOPNOTSUPP;
  1018. *val = priv->preamble;
  1019. return 0;
  1020. }
  1021. /* ioctl interface to hermes_read_ltv()
  1022. * To use with iwpriv, pass the RID as the token argument, e.g.
  1023. * iwpriv get_rid [0xfc00]
  1024. * At least Wireless Tools 25 is required to use iwpriv.
  1025. * For Wireless Tools 25 and 26 append "dummy" are the end. */
  1026. static int orinoco_ioctl_getrid(struct net_device *dev,
  1027. struct iw_request_info *info,
  1028. struct iw_point *data,
  1029. char *extra)
  1030. {
  1031. struct orinoco_private *priv = ndev_priv(dev);
  1032. hermes_t *hw = &priv->hw;
  1033. int rid = data->flags;
  1034. u16 length;
  1035. int err;
  1036. unsigned long flags;
  1037. /* It's a "get" function, but we don't want users to access the
  1038. * WEP key and other raw firmware data */
  1039. if (!capable(CAP_NET_ADMIN))
  1040. return -EPERM;
  1041. if (rid < 0xfc00 || rid > 0xffff)
  1042. return -EINVAL;
  1043. if (orinoco_lock(priv, &flags) != 0)
  1044. return -EBUSY;
  1045. err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
  1046. extra);
  1047. if (err)
  1048. goto out;
  1049. data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
  1050. MAX_RID_LEN);
  1051. out:
  1052. orinoco_unlock(priv, &flags);
  1053. return err;
  1054. }
  1055. /* Commit handler, called after set operations */
  1056. static int orinoco_ioctl_commit(struct net_device *dev,
  1057. struct iw_request_info *info,
  1058. void *wrqu,
  1059. char *extra)
  1060. {
  1061. struct orinoco_private *priv = ndev_priv(dev);
  1062. unsigned long flags;
  1063. int err = 0;
  1064. if (!priv->open)
  1065. return 0;
  1066. if (orinoco_lock(priv, &flags) != 0)
  1067. return err;
  1068. err = orinoco_commit(priv);
  1069. orinoco_unlock(priv, &flags);
  1070. return err;
  1071. }
  1072. static const struct iw_priv_args orinoco_privtab[] = {
  1073. { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
  1074. { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
  1075. { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  1076. 0, "set_port3" },
  1077. { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  1078. "get_port3" },
  1079. { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  1080. 0, "set_preamble" },
  1081. { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  1082. "get_preamble" },
  1083. { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  1084. 0, "set_ibssport" },
  1085. { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  1086. "get_ibssport" },
  1087. { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
  1088. "get_rid" },
  1089. };
  1090. /*
  1091. * Structures to export the Wireless Handlers
  1092. */
  1093. static const iw_handler orinoco_handler[] = {
  1094. IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)orinoco_ioctl_commit),
  1095. IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname),
  1096. IW_HANDLER(SIOCSIWFREQ, (iw_handler)orinoco_ioctl_setfreq),
  1097. IW_HANDLER(SIOCGIWFREQ, (iw_handler)orinoco_ioctl_getfreq),
  1098. IW_HANDLER(SIOCSIWMODE, (iw_handler)cfg80211_wext_siwmode),
  1099. IW_HANDLER(SIOCGIWMODE, (iw_handler)cfg80211_wext_giwmode),
  1100. IW_HANDLER(SIOCSIWSENS, (iw_handler)orinoco_ioctl_setsens),
  1101. IW_HANDLER(SIOCGIWSENS, (iw_handler)orinoco_ioctl_getsens),
  1102. IW_HANDLER(SIOCGIWRANGE, (iw_handler)cfg80211_wext_giwrange),
  1103. IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
  1104. IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
  1105. IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
  1106. IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
  1107. IW_HANDLER(SIOCSIWAP, (iw_handler)orinoco_ioctl_setwap),
  1108. IW_HANDLER(SIOCGIWAP, (iw_handler)orinoco_ioctl_getwap),
  1109. IW_HANDLER(SIOCSIWSCAN, (iw_handler)cfg80211_wext_siwscan),
  1110. IW_HANDLER(SIOCGIWSCAN, (iw_handler)cfg80211_wext_giwscan),
  1111. IW_HANDLER(SIOCSIWESSID, (iw_handler)orinoco_ioctl_setessid),
  1112. IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid),
  1113. IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate),
  1114. IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate),
  1115. IW_HANDLER(SIOCSIWRTS, (iw_handler)cfg80211_wext_siwrts),
  1116. IW_HANDLER(SIOCGIWRTS, (iw_handler)cfg80211_wext_giwrts),
  1117. IW_HANDLER(SIOCSIWFRAG, (iw_handler)cfg80211_wext_siwfrag),
  1118. IW_HANDLER(SIOCGIWFRAG, (iw_handler)cfg80211_wext_giwfrag),
  1119. IW_HANDLER(SIOCGIWRETRY, (iw_handler)cfg80211_wext_giwretry),
  1120. IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode),
  1121. IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode),
  1122. IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower),
  1123. IW_HANDLER(SIOCGIWPOWER, (iw_handler)orinoco_ioctl_getpower),
  1124. IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
  1125. IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
  1126. IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
  1127. IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
  1128. IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
  1129. IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
  1130. IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
  1131. };
  1132. /*
  1133. Added typecasting since we no longer use iwreq_data -- Moustafa
  1134. */
  1135. static const iw_handler orinoco_private_handler[] = {
  1136. [0] = (iw_handler)orinoco_ioctl_reset,
  1137. [1] = (iw_handler)orinoco_ioctl_reset,
  1138. [2] = (iw_handler)orinoco_ioctl_setport3,
  1139. [3] = (iw_handler)orinoco_ioctl_getport3,
  1140. [4] = (iw_handler)orinoco_ioctl_setpreamble,
  1141. [5] = (iw_handler)orinoco_ioctl_getpreamble,
  1142. [6] = (iw_handler)orinoco_ioctl_setibssport,
  1143. [7] = (iw_handler)orinoco_ioctl_getibssport,
  1144. [9] = (iw_handler)orinoco_ioctl_getrid,
  1145. };
  1146. const struct iw_handler_def orinoco_handler_def = {
  1147. .num_standard = ARRAY_SIZE(orinoco_handler),
  1148. .num_private = ARRAY_SIZE(orinoco_private_handler),
  1149. .num_private_args = ARRAY_SIZE(orinoco_privtab),
  1150. .standard = orinoco_handler,
  1151. .private = orinoco_private_handler,
  1152. .private_args = orinoco_privtab,
  1153. .get_wireless_stats = orinoco_get_wireless_stats,
  1154. };