wext.c 36 KB

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