ioctl.c 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470
  1. /**
  2. * This file contains ioctl functions
  3. */
  4. #include <linux/ctype.h>
  5. #include <linux/delay.h>
  6. #include <linux/if.h>
  7. #include <linux/if_arp.h>
  8. #include <linux/wireless.h>
  9. #include <net/iw_handler.h>
  10. #include <net/ieee80211.h>
  11. #include "host.h"
  12. #include "radiotap.h"
  13. #include "decl.h"
  14. #include "defs.h"
  15. #include "dev.h"
  16. #include "join.h"
  17. #include "wext.h"
  18. #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN + \
  19. IW_ESSID_MAX_SIZE + \
  20. IW_EV_UINT_LEN + IW_EV_FREQ_LEN + \
  21. IW_EV_QUAL_LEN + IW_ESSID_MAX_SIZE + \
  22. IW_EV_PARAM_LEN + 40) /* 40 for WPAIE */
  23. #define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ)
  24. static int setrxantenna(wlan_private * priv, int mode)
  25. {
  26. int ret = 0;
  27. wlan_adapter *adapter = priv->adapter;
  28. if (mode != RF_ANTENNA_1 && mode != RF_ANTENNA_2
  29. && mode != RF_ANTENNA_AUTO) {
  30. return -EINVAL;
  31. }
  32. adapter->rxantennamode = mode;
  33. lbs_pr_debug(1, "SET RX Antenna mode to 0x%04x\n", adapter->rxantennamode);
  34. ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna,
  35. cmd_act_set_rx,
  36. cmd_option_waitforrsp, 0,
  37. &adapter->rxantennamode);
  38. return ret;
  39. }
  40. static int settxantenna(wlan_private * priv, int mode)
  41. {
  42. int ret = 0;
  43. wlan_adapter *adapter = priv->adapter;
  44. if ((mode != RF_ANTENNA_1) && (mode != RF_ANTENNA_2)
  45. && (mode != RF_ANTENNA_AUTO)) {
  46. return -EINVAL;
  47. }
  48. adapter->txantennamode = mode;
  49. lbs_pr_debug(1, "SET TX Antenna mode to 0x%04x\n", adapter->txantennamode);
  50. ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna,
  51. cmd_act_set_tx,
  52. cmd_option_waitforrsp, 0,
  53. &adapter->txantennamode);
  54. return ret;
  55. }
  56. static int getrxantenna(wlan_private * priv, char *buf)
  57. {
  58. int ret = 0;
  59. wlan_adapter *adapter = priv->adapter;
  60. // clear it, so we will know if the value
  61. // returned below is correct or not.
  62. adapter->rxantennamode = 0;
  63. ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna,
  64. cmd_act_get_rx,
  65. cmd_option_waitforrsp, 0, NULL);
  66. if (ret) {
  67. LEAVE();
  68. return ret;
  69. }
  70. lbs_pr_debug(1, "Get Rx Antenna mode:0x%04x\n", adapter->rxantennamode);
  71. return sprintf(buf, "0x%04x", adapter->rxantennamode) + 1;
  72. }
  73. static int gettxantenna(wlan_private * priv, char *buf)
  74. {
  75. int ret = 0;
  76. wlan_adapter *adapter = priv->adapter;
  77. // clear it, so we will know if the value
  78. // returned below is correct or not.
  79. adapter->txantennamode = 0;
  80. ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_antenna,
  81. cmd_act_get_tx,
  82. cmd_option_waitforrsp, 0, NULL);
  83. if (ret) {
  84. LEAVE();
  85. return ret;
  86. }
  87. lbs_pr_debug(1, "Get Tx Antenna mode:0x%04x\n", adapter->txantennamode);
  88. return sprintf(buf, "0x%04x", adapter->txantennamode) + 1;
  89. }
  90. static int wlan_set_region(wlan_private * priv, u16 region_code)
  91. {
  92. int i;
  93. for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
  94. // use the region code to search for the index
  95. if (region_code == libertas_region_code_to_index[i]) {
  96. priv->adapter->regiontableindex = (u16) i;
  97. priv->adapter->regioncode = region_code;
  98. break;
  99. }
  100. }
  101. // if it's unidentified region code
  102. if (i >= MRVDRV_MAX_REGION_CODE) {
  103. lbs_pr_debug(1, "region Code not identified\n");
  104. LEAVE();
  105. return -1;
  106. }
  107. if (libertas_set_regiontable(priv, priv->adapter->regioncode, 0)) {
  108. LEAVE();
  109. return -EINVAL;
  110. }
  111. return 0;
  112. }
  113. /**
  114. * @brief Get/Set Firmware wakeup method
  115. *
  116. * @param priv A pointer to wlan_private structure
  117. * @param wrq A pointer to user data
  118. * @return 0--success, otherwise fail
  119. */
  120. static int wlan_txcontrol(wlan_private * priv, struct iwreq *wrq)
  121. {
  122. wlan_adapter *adapter = priv->adapter;
  123. int data;
  124. ENTER();
  125. if ((int)wrq->u.data.length == 0) {
  126. if (copy_to_user
  127. (wrq->u.data.pointer, &adapter->pkttxctrl, sizeof(u32))) {
  128. lbs_pr_alert("copy_to_user failed!\n");
  129. return -EFAULT;
  130. }
  131. } else {
  132. if ((int)wrq->u.data.length > 1) {
  133. lbs_pr_alert("ioctl too many args!\n");
  134. return -EFAULT;
  135. }
  136. if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
  137. lbs_pr_alert("Copy from user failed\n");
  138. return -EFAULT;
  139. }
  140. adapter->pkttxctrl = (u32) data;
  141. }
  142. wrq->u.data.length = 1;
  143. LEAVE();
  144. return 0;
  145. }
  146. /**
  147. * @brief Get/Set NULL Package generation interval
  148. *
  149. * @param priv A pointer to wlan_private structure
  150. * @param wrq A pointer to user data
  151. * @return 0--success, otherwise fail
  152. */
  153. static int wlan_null_pkt_interval(wlan_private * priv, struct iwreq *wrq)
  154. {
  155. wlan_adapter *adapter = priv->adapter;
  156. int data;
  157. ENTER();
  158. if ((int)wrq->u.data.length == 0) {
  159. data = adapter->nullpktinterval;
  160. if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
  161. lbs_pr_alert( "copy_to_user failed!\n");
  162. return -EFAULT;
  163. }
  164. } else {
  165. if ((int)wrq->u.data.length > 1) {
  166. lbs_pr_alert( "ioctl too many args!\n");
  167. return -EFAULT;
  168. }
  169. if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
  170. lbs_pr_debug(1, "Copy from user failed\n");
  171. return -EFAULT;
  172. }
  173. adapter->nullpktinterval = data;
  174. }
  175. wrq->u.data.length = 1;
  176. LEAVE();
  177. return 0;
  178. }
  179. static int wlan_get_rxinfo(wlan_private * priv, struct iwreq *wrq)
  180. {
  181. wlan_adapter *adapter = priv->adapter;
  182. int data[2];
  183. ENTER();
  184. data[0] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
  185. data[1] = adapter->rxpd_rate;
  186. if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
  187. lbs_pr_debug(1, "Copy to user failed\n");
  188. return -EFAULT;
  189. }
  190. wrq->u.data.length = 2;
  191. LEAVE();
  192. return 0;
  193. }
  194. static int wlan_get_snr(wlan_private * priv, struct iwreq *wrq)
  195. {
  196. int ret = 0;
  197. wlan_adapter *adapter = priv->adapter;
  198. int data[4];
  199. ENTER();
  200. memset(data, 0, sizeof(data));
  201. if (wrq->u.data.length) {
  202. if (copy_from_user(data, wrq->u.data.pointer,
  203. min_t(size_t, wrq->u.data.length, 4) * sizeof(int)))
  204. return -EFAULT;
  205. }
  206. if ((wrq->u.data.length == 0) || (data[0] == 0) || (data[0] == 1)) {
  207. if (adapter->connect_status == libertas_connected) {
  208. ret = libertas_prepare_and_send_command(priv,
  209. cmd_802_11_rssi,
  210. 0,
  211. cmd_option_waitforrsp,
  212. 0, NULL);
  213. if (ret) {
  214. LEAVE();
  215. return ret;
  216. }
  217. }
  218. }
  219. if (wrq->u.data.length == 0) {
  220. data[0] = adapter->SNR[TYPE_BEACON][TYPE_NOAVG];
  221. data[1] = adapter->SNR[TYPE_BEACON][TYPE_AVG];
  222. data[2] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
  223. data[3] = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
  224. if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 4))
  225. return -EFAULT;
  226. wrq->u.data.length = 4;
  227. } else if (data[0] == 0) {
  228. data[0] = adapter->SNR[TYPE_BEACON][TYPE_NOAVG];
  229. if (copy_to_user(wrq->u.data.pointer, data, sizeof(int)))
  230. return -EFAULT;
  231. wrq->u.data.length = 1;
  232. } else if (data[0] == 1) {
  233. data[0] = adapter->SNR[TYPE_BEACON][TYPE_AVG];
  234. if (copy_to_user(wrq->u.data.pointer, data, sizeof(int)))
  235. return -EFAULT;
  236. wrq->u.data.length = 1;
  237. } else if (data[0] == 2) {
  238. data[0] = adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
  239. if (copy_to_user(wrq->u.data.pointer, data, sizeof(int)))
  240. return -EFAULT;
  241. wrq->u.data.length = 1;
  242. } else if (data[0] == 3) {
  243. data[0] = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
  244. if (copy_to_user(wrq->u.data.pointer, data, sizeof(int)))
  245. return -EFAULT;
  246. wrq->u.data.length = 1;
  247. } else
  248. return -ENOTSUPP;
  249. LEAVE();
  250. return 0;
  251. }
  252. static int wlan_beacon_interval(wlan_private * priv, struct iwreq *wrq)
  253. {
  254. int data;
  255. wlan_adapter *adapter = priv->adapter;
  256. if (wrq->u.data.length > 0) {
  257. if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int)))
  258. return -EFAULT;
  259. lbs_pr_debug(1, "WLAN SET BEACON INTERVAL: %d\n", data);
  260. if ((data > MRVDRV_MAX_BEACON_INTERVAL)
  261. || (data < MRVDRV_MIN_BEACON_INTERVAL))
  262. return -ENOTSUPP;
  263. adapter->beaconperiod = data;
  264. }
  265. data = adapter->beaconperiod;
  266. if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int)))
  267. return -EFAULT;
  268. wrq->u.data.length = 1;
  269. return 0;
  270. }
  271. static int wlan_get_rssi(wlan_private * priv, struct iwreq *wrq)
  272. {
  273. int ret = 0;
  274. wlan_adapter *adapter = priv->adapter;
  275. int temp;
  276. int data = 0;
  277. int *val;
  278. ENTER();
  279. data = SUBCMD_DATA(wrq);
  280. if ((data == 0) || (data == 1)) {
  281. ret = libertas_prepare_and_send_command(priv,
  282. cmd_802_11_rssi,
  283. 0, cmd_option_waitforrsp,
  284. 0, NULL);
  285. if (ret) {
  286. LEAVE();
  287. return ret;
  288. }
  289. }
  290. switch (data) {
  291. case 0:
  292. temp = CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
  293. adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
  294. break;
  295. case 1:
  296. temp = CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG],
  297. adapter->NF[TYPE_BEACON][TYPE_AVG]);
  298. break;
  299. case 2:
  300. temp = CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_NOAVG],
  301. adapter->NF[TYPE_RXPD][TYPE_NOAVG]);
  302. break;
  303. case 3:
  304. temp = CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
  305. adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
  306. break;
  307. default:
  308. return -ENOTSUPP;
  309. }
  310. val = (int *)wrq->u.name;
  311. *val = temp;
  312. LEAVE();
  313. return 0;
  314. }
  315. static int wlan_get_nf(wlan_private * priv, struct iwreq *wrq)
  316. {
  317. int ret = 0;
  318. wlan_adapter *adapter = priv->adapter;
  319. int temp;
  320. int data = 0;
  321. int *val;
  322. data = SUBCMD_DATA(wrq);
  323. if ((data == 0) || (data == 1)) {
  324. ret = libertas_prepare_and_send_command(priv,
  325. cmd_802_11_rssi,
  326. 0, cmd_option_waitforrsp,
  327. 0, NULL);
  328. if (ret) {
  329. LEAVE();
  330. return ret;
  331. }
  332. }
  333. switch (data) {
  334. case 0:
  335. temp = adapter->NF[TYPE_BEACON][TYPE_NOAVG];
  336. break;
  337. case 1:
  338. temp = adapter->NF[TYPE_BEACON][TYPE_AVG];
  339. break;
  340. case 2:
  341. temp = adapter->NF[TYPE_RXPD][TYPE_NOAVG];
  342. break;
  343. case 3:
  344. temp = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
  345. break;
  346. default:
  347. return -ENOTSUPP;
  348. }
  349. temp = CAL_NF(temp);
  350. lbs_pr_debug(1, "%s: temp = %d\n", __FUNCTION__, temp);
  351. val = (int *)wrq->u.name;
  352. *val = temp;
  353. return 0;
  354. }
  355. static int wlan_get_txrate_ioctl(wlan_private * priv, struct ifreq *req)
  356. {
  357. wlan_adapter *adapter = priv->adapter;
  358. int *pdata;
  359. struct iwreq *wrq = (struct iwreq *)req;
  360. int ret = 0;
  361. adapter->txrate = 0;
  362. lbs_pr_debug(1, "wlan_get_txrate_ioctl\n");
  363. ret = libertas_prepare_and_send_command(priv, cmd_802_11_tx_rate_query,
  364. cmd_act_get, cmd_option_waitforrsp,
  365. 0, NULL);
  366. if (ret)
  367. return ret;
  368. pdata = (int *)wrq->u.name;
  369. *pdata = (int)adapter->txrate;
  370. return 0;
  371. }
  372. static int wlan_get_adhoc_status_ioctl(wlan_private * priv, struct iwreq *wrq)
  373. {
  374. char status[64];
  375. wlan_adapter *adapter = priv->adapter;
  376. memset(status, 0, sizeof(status));
  377. switch (adapter->inframode) {
  378. case wlan802_11ibss:
  379. if (adapter->connect_status == libertas_connected) {
  380. if (adapter->adhoccreate)
  381. memcpy(&status, "AdhocStarted", sizeof(status));
  382. else
  383. memcpy(&status, "AdhocJoined", sizeof(status));
  384. } else {
  385. memcpy(&status, "AdhocIdle", sizeof(status));
  386. }
  387. break;
  388. case wlan802_11infrastructure:
  389. memcpy(&status, "Inframode", sizeof(status));
  390. break;
  391. default:
  392. memcpy(&status, "AutoUnknownmode", sizeof(status));
  393. break;
  394. }
  395. lbs_pr_debug(1, "status = %s\n", status);
  396. wrq->u.data.length = strlen(status) + 1;
  397. if (wrq->u.data.pointer) {
  398. if (copy_to_user(wrq->u.data.pointer,
  399. &status, wrq->u.data.length))
  400. return -EFAULT;
  401. }
  402. LEAVE();
  403. return 0;
  404. }
  405. /**
  406. * @brief Set/Get WPA IE
  407. * @param priv A pointer to wlan_private structure
  408. * @param req A pointer to ifreq structure
  409. * @return 0 --success, otherwise fail
  410. */
  411. static int wlan_setwpaie_ioctl(wlan_private * priv, struct ifreq *req)
  412. {
  413. struct iwreq *wrq = (struct iwreq *)req;
  414. wlan_adapter *adapter = priv->adapter;
  415. int ret = 0;
  416. ENTER();
  417. if (wrq->u.data.length) {
  418. if (wrq->u.data.length > sizeof(adapter->wpa_ie)) {
  419. lbs_pr_debug(1, "failed to copy WPA IE, too big \n");
  420. return -EFAULT;
  421. }
  422. if (copy_from_user(adapter->wpa_ie, wrq->u.data.pointer,
  423. wrq->u.data.length)) {
  424. lbs_pr_debug(1, "failed to copy WPA IE \n");
  425. return -EFAULT;
  426. }
  427. adapter->wpa_ie_len = wrq->u.data.length;
  428. lbs_pr_debug(1, "Set wpa_ie_len=%d IE=%#x\n", adapter->wpa_ie_len,
  429. adapter->wpa_ie[0]);
  430. lbs_dbg_hex("wpa_ie", adapter->wpa_ie, adapter->wpa_ie_len);
  431. if (adapter->wpa_ie[0] == WPA_IE)
  432. adapter->secinfo.WPAenabled = 1;
  433. else if (adapter->wpa_ie[0] == WPA2_IE)
  434. adapter->secinfo.WPA2enabled = 1;
  435. else {
  436. adapter->secinfo.WPAenabled = 0;
  437. adapter->secinfo.WPA2enabled = 0;
  438. }
  439. } else {
  440. memset(adapter->wpa_ie, 0, sizeof(adapter->wpa_ie));
  441. adapter->wpa_ie_len = wrq->u.data.length;
  442. lbs_pr_debug(1, "Reset wpa_ie_len=%d IE=%#x\n",
  443. adapter->wpa_ie_len, adapter->wpa_ie[0]);
  444. adapter->secinfo.WPAenabled = 0;
  445. adapter->secinfo.WPA2enabled = 0;
  446. }
  447. // enable/disable RSN in firmware if WPA is enabled/disabled
  448. // depending on variable adapter->secinfo.WPAenabled is set or not
  449. ret = libertas_prepare_and_send_command(priv, cmd_802_11_enable_rsn,
  450. cmd_act_set, cmd_option_waitforrsp,
  451. 0, NULL);
  452. LEAVE();
  453. return ret;
  454. }
  455. /**
  456. * @brief Set Auto prescan
  457. * @param priv A pointer to wlan_private structure
  458. * @param wrq A pointer to iwreq structure
  459. * @return 0 --success, otherwise fail
  460. */
  461. static int wlan_subcmd_setprescan_ioctl(wlan_private * priv, struct iwreq *wrq)
  462. {
  463. int data;
  464. wlan_adapter *adapter = priv->adapter;
  465. int *val;
  466. data = SUBCMD_DATA(wrq);
  467. lbs_pr_debug(1, "WLAN_SUBCMD_SET_PRESCAN %d\n", data);
  468. adapter->prescan = data;
  469. val = (int *)wrq->u.name;
  470. *val = data;
  471. return 0;
  472. }
  473. static int wlan_set_multiple_dtim_ioctl(wlan_private * priv, struct ifreq *req)
  474. {
  475. struct iwreq *wrq = (struct iwreq *)req;
  476. u32 mdtim;
  477. int idata;
  478. int ret = -EINVAL;
  479. ENTER();
  480. idata = SUBCMD_DATA(wrq);
  481. mdtim = (u32) idata;
  482. if (((mdtim >= MRVDRV_MIN_MULTIPLE_DTIM)
  483. && (mdtim <= MRVDRV_MAX_MULTIPLE_DTIM))
  484. || (mdtim == MRVDRV_IGNORE_MULTIPLE_DTIM)) {
  485. priv->adapter->multipledtim = mdtim;
  486. ret = 0;
  487. }
  488. if (ret)
  489. lbs_pr_debug(1, "Invalid parameter, multipledtim not changed.\n");
  490. LEAVE();
  491. return ret;
  492. }
  493. /**
  494. * @brief Set authentication mode
  495. * @param priv A pointer to wlan_private structure
  496. * @param req A pointer to ifreq structure
  497. * @return 0 --success, otherwise fail
  498. */
  499. static int wlan_setauthalg_ioctl(wlan_private * priv, struct ifreq *req)
  500. {
  501. int alg;
  502. struct iwreq *wrq = (struct iwreq *)req;
  503. wlan_adapter *adapter = priv->adapter;
  504. if (wrq->u.data.flags == 0) {
  505. //from iwpriv subcmd
  506. alg = SUBCMD_DATA(wrq);
  507. } else {
  508. //from wpa_supplicant subcmd
  509. if (copy_from_user(&alg, wrq->u.data.pointer, sizeof(alg))) {
  510. lbs_pr_debug(1, "Copy from user failed\n");
  511. return -EFAULT;
  512. }
  513. }
  514. lbs_pr_debug(1, "auth alg is %#x\n", alg);
  515. switch (alg) {
  516. case AUTH_ALG_SHARED_KEY:
  517. adapter->secinfo.authmode = wlan802_11authmodeshared;
  518. break;
  519. case AUTH_ALG_NETWORK_EAP:
  520. adapter->secinfo.authmode =
  521. wlan802_11authmodenetworkEAP;
  522. break;
  523. case AUTH_ALG_OPEN_SYSTEM:
  524. default:
  525. adapter->secinfo.authmode = wlan802_11authmodeopen;
  526. break;
  527. }
  528. return 0;
  529. }
  530. static int wlan_setencryptionmode_ioctl(wlan_private * priv, struct ifreq *req)
  531. {
  532. int mode;
  533. struct iwreq *wrq = (struct iwreq *)req;
  534. ENTER();
  535. if (wrq->u.data.flags == 0) {
  536. //from iwpriv subcmd
  537. mode = SUBCMD_DATA(wrq);
  538. } else {
  539. //from wpa_supplicant subcmd
  540. if (copy_from_user(&mode, wrq->u.data.pointer, sizeof(int))) {
  541. lbs_pr_debug(1, "Copy from user failed\n");
  542. return -EFAULT;
  543. }
  544. }
  545. lbs_pr_debug(1, "encryption mode is %#x\n", mode);
  546. priv->adapter->secinfo.Encryptionmode = mode;
  547. LEAVE();
  548. return 0;
  549. }
  550. static void adjust_mtu(wlan_private * priv)
  551. {
  552. int mtu_increment = 0;
  553. if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
  554. mtu_increment += sizeof(struct ieee80211_hdr_4addr);
  555. if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP)
  556. mtu_increment += max(sizeof(struct tx_radiotap_hdr),
  557. sizeof(struct rx_radiotap_hdr));
  558. priv->wlan_dev.netdev->mtu = ETH_FRAME_LEN
  559. - sizeof(struct ethhdr)
  560. + mtu_increment;
  561. }
  562. /**
  563. * @brief Set Link-Layer Layer mode
  564. * @param priv A pointer to wlan_private structure
  565. * @param req A pointer to ifreq structure
  566. * @return 0 --success, otherwise fail
  567. */
  568. static int wlan_set_linkmode_ioctl(wlan_private * priv, struct ifreq *req)
  569. {
  570. int mode;
  571. mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
  572. switch (mode) {
  573. case WLAN_LINKMODE_802_3:
  574. priv->adapter->linkmode = mode;
  575. break;
  576. case WLAN_LINKMODE_802_11:
  577. priv->adapter->linkmode = mode;
  578. break;
  579. default:
  580. lbs_pr_info("usb8388-5: invalid link-layer mode (%#x)\n",
  581. mode);
  582. return -EINVAL;
  583. break;
  584. }
  585. lbs_pr_debug(1, "usb8388-5: link-layer mode is %#x\n", mode);
  586. adjust_mtu(priv);
  587. return 0;
  588. }
  589. /**
  590. * @brief Set Radio header mode
  591. * @param priv A pointer to wlan_private structure
  592. * @param req A pointer to ifreq structure
  593. * @return 0 --success, otherwise fail
  594. */
  595. static int wlan_set_radiomode_ioctl(wlan_private * priv, struct ifreq *req)
  596. {
  597. int mode;
  598. mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
  599. switch (mode) {
  600. case WLAN_RADIOMODE_NONE:
  601. priv->adapter->radiomode = mode;
  602. break;
  603. case WLAN_RADIOMODE_RADIOTAP:
  604. priv->adapter->radiomode = mode;
  605. break;
  606. default:
  607. lbs_pr_debug(1, "usb8388-5: invalid radio header mode (%#x)\n",
  608. mode);
  609. return -EINVAL;
  610. }
  611. lbs_pr_debug(1, "usb8388-5: radio-header mode is %#x\n", mode);
  612. adjust_mtu(priv);
  613. return 0;
  614. }
  615. /**
  616. * @brief Set Debug header mode
  617. * @param priv A pointer to wlan_private structure
  618. * @param req A pointer to ifreq structure
  619. * @return 0 --success, otherwise fail
  620. */
  621. static int wlan_set_debugmode_ioctl(wlan_private * priv, struct ifreq *req)
  622. {
  623. priv->adapter->debugmode = (int)((struct ifreq *)
  624. ((u8 *) req + 4))->ifr_data;
  625. return 0;
  626. }
  627. static int wlan_subcmd_getrxantenna_ioctl(wlan_private * priv,
  628. struct ifreq *req)
  629. {
  630. int len;
  631. char buf[8];
  632. struct iwreq *wrq = (struct iwreq *)req;
  633. lbs_pr_debug(1, "WLAN_SUBCMD_GETRXANTENNA\n");
  634. len = getrxantenna(priv, buf);
  635. wrq->u.data.length = len;
  636. if (wrq->u.data.pointer) {
  637. if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
  638. lbs_pr_debug(1, "CopyToUser failed\n");
  639. return -EFAULT;
  640. }
  641. }
  642. return 0;
  643. }
  644. static int wlan_subcmd_gettxantenna_ioctl(wlan_private * priv,
  645. struct ifreq *req)
  646. {
  647. int len;
  648. char buf[8];
  649. struct iwreq *wrq = (struct iwreq *)req;
  650. lbs_pr_debug(1, "WLAN_SUBCMD_GETTXANTENNA\n");
  651. len = gettxantenna(priv, buf);
  652. wrq->u.data.length = len;
  653. if (wrq->u.data.pointer) {
  654. if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
  655. lbs_pr_debug(1, "CopyToUser failed\n");
  656. return -EFAULT;
  657. }
  658. }
  659. return 0;
  660. }
  661. /**
  662. * @brief Get the MAC TSF value from the firmware
  663. *
  664. * @param priv A pointer to wlan_private structure
  665. * @param wrq A pointer to iwreq structure containing buffer
  666. * space to store a TSF value retrieved from the firmware
  667. *
  668. * @return 0 if successful; IOCTL error code otherwise
  669. */
  670. static int wlan_get_tsf_ioctl(wlan_private * priv, struct iwreq *wrq)
  671. {
  672. u64 tsfval;
  673. int ret;
  674. ret = libertas_prepare_and_send_command(priv,
  675. cmd_get_tsf,
  676. 0, cmd_option_waitforrsp, 0, &tsfval);
  677. lbs_pr_debug(1, "IOCTL: Get TSF = 0x%016llx\n", tsfval);
  678. if (ret != 0) {
  679. lbs_pr_debug(1, "IOCTL: Get TSF; command exec failed\n");
  680. ret = -EFAULT;
  681. } else {
  682. if (copy_to_user(wrq->u.data.pointer,
  683. &tsfval,
  684. min_t(size_t, wrq->u.data.length,
  685. sizeof(tsfval))) != 0) {
  686. lbs_pr_debug(1, "IOCTL: Get TSF; Copy to user failed\n");
  687. ret = -EFAULT;
  688. } else {
  689. ret = 0;
  690. }
  691. }
  692. return ret;
  693. }
  694. /**
  695. * @brief Get/Set adapt rate
  696. * @param priv A pointer to wlan_private structure
  697. * @param wrq A pointer to iwreq structure
  698. * @return 0 --success, otherwise fail
  699. */
  700. static int wlan_adapt_rateset(wlan_private * priv, struct iwreq *wrq)
  701. {
  702. int ret;
  703. wlan_adapter *adapter = priv->adapter;
  704. int data[2];
  705. memset(data, 0, sizeof(data));
  706. if (!wrq->u.data.length) {
  707. lbs_pr_debug(1, "Get ADAPT RATE SET\n");
  708. ret = libertas_prepare_and_send_command(priv,
  709. cmd_802_11_rate_adapt_rateset,
  710. cmd_act_get,
  711. cmd_option_waitforrsp, 0, NULL);
  712. data[0] = adapter->enablehwauto;
  713. data[1] = adapter->ratebitmap;
  714. if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
  715. lbs_pr_debug(1, "Copy to user failed\n");
  716. return -EFAULT;
  717. }
  718. #define GET_TWO_INT 2
  719. wrq->u.data.length = GET_TWO_INT;
  720. } else {
  721. lbs_pr_debug(1, "Set ADAPT RATE SET\n");
  722. if (wrq->u.data.length > 2)
  723. return -EINVAL;
  724. if (copy_from_user
  725. (data, wrq->u.data.pointer,
  726. sizeof(int) * wrq->u.data.length)) {
  727. lbs_pr_debug(1, "Copy from user failed\n");
  728. return -EFAULT;
  729. }
  730. adapter->enablehwauto = data[0];
  731. adapter->ratebitmap = data[1];
  732. ret = libertas_prepare_and_send_command(priv,
  733. cmd_802_11_rate_adapt_rateset,
  734. cmd_act_set,
  735. cmd_option_waitforrsp, 0, NULL);
  736. }
  737. return ret;
  738. }
  739. /**
  740. * @brief Get/Set inactivity timeout
  741. * @param priv A pointer to wlan_private structure
  742. * @param wrq A pointer to iwreq structure
  743. * @return 0 --success, otherwise fail
  744. */
  745. static int wlan_inactivity_timeout(wlan_private * priv, struct iwreq *wrq)
  746. {
  747. int ret;
  748. int data = 0;
  749. u16 timeout = 0;
  750. ENTER();
  751. if (wrq->u.data.length > 1)
  752. return -ENOTSUPP;
  753. if (wrq->u.data.length == 0) {
  754. /* Get */
  755. ret = libertas_prepare_and_send_command(priv,
  756. cmd_802_11_inactivity_timeout,
  757. cmd_act_get,
  758. cmd_option_waitforrsp, 0,
  759. &timeout);
  760. data = timeout;
  761. if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
  762. lbs_pr_debug(1, "Copy to user failed\n");
  763. return -EFAULT;
  764. }
  765. } else {
  766. /* Set */
  767. if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
  768. lbs_pr_debug(1, "Copy from user failed\n");
  769. return -EFAULT;
  770. }
  771. timeout = data;
  772. ret = libertas_prepare_and_send_command(priv,
  773. cmd_802_11_inactivity_timeout,
  774. cmd_act_set,
  775. cmd_option_waitforrsp, 0,
  776. &timeout);
  777. }
  778. wrq->u.data.length = 1;
  779. LEAVE();
  780. return ret;
  781. }
  782. static int wlan_do_getlog_ioctl(wlan_private * priv, struct iwreq *wrq)
  783. {
  784. int ret;
  785. char buf[GETLOG_BUFSIZE - 1];
  786. wlan_adapter *adapter = priv->adapter;
  787. lbs_pr_debug(1, " GET STATS\n");
  788. ret = libertas_prepare_and_send_command(priv, cmd_802_11_get_log,
  789. 0, cmd_option_waitforrsp, 0, NULL);
  790. if (ret) {
  791. return ret;
  792. }
  793. if (wrq->u.data.pointer) {
  794. sprintf(buf, "\n mcasttxframe %u failed %u retry %u "
  795. "multiretry %u framedup %u "
  796. "rtssuccess %u rtsfailure %u ackfailure %u\n"
  797. "rxfrag %u mcastrxframe %u fcserror %u "
  798. "txframe %u wepundecryptable %u ",
  799. adapter->logmsg.mcasttxframe,
  800. adapter->logmsg.failed,
  801. adapter->logmsg.retry,
  802. adapter->logmsg.multiretry,
  803. adapter->logmsg.framedup,
  804. adapter->logmsg.rtssuccess,
  805. adapter->logmsg.rtsfailure,
  806. adapter->logmsg.ackfailure,
  807. adapter->logmsg.rxfrag,
  808. adapter->logmsg.mcastrxframe,
  809. adapter->logmsg.fcserror,
  810. adapter->logmsg.txframe,
  811. adapter->logmsg.wepundecryptable);
  812. wrq->u.data.length = strlen(buf) + 1;
  813. if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
  814. lbs_pr_debug(1, "Copy to user failed\n");
  815. return -EFAULT;
  816. }
  817. }
  818. return 0;
  819. }
  820. static int wlan_scan_type_ioctl(wlan_private * priv, struct iwreq *wrq)
  821. {
  822. u8 buf[12];
  823. u8 *option[] = { "active", "passive", "get", };
  824. int i, max_options = (sizeof(option) / sizeof(option[0]));
  825. int ret = 0;
  826. wlan_adapter *adapter = priv->adapter;
  827. if (priv->adapter->enable11d) {
  828. lbs_pr_debug(1, "11D: Cannot set scantype when 11D enabled\n");
  829. return -EFAULT;
  830. }
  831. memset(buf, 0, sizeof(buf));
  832. if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
  833. wrq->u.data.length)))
  834. return -EFAULT;
  835. lbs_pr_debug(1, "Scan type Option = %s\n", buf);
  836. buf[sizeof(buf) - 1] = '\0';
  837. for (i = 0; i < max_options; i++) {
  838. if (!strcmp(buf, option[i]))
  839. break;
  840. }
  841. switch (i) {
  842. case 0:
  843. adapter->scantype = cmd_scan_type_active;
  844. break;
  845. case 1:
  846. adapter->scantype = cmd_scan_type_passive;
  847. break;
  848. case 2:
  849. wrq->u.data.length = strlen(option[adapter->scantype]) + 1;
  850. if (copy_to_user(wrq->u.data.pointer,
  851. option[adapter->scantype],
  852. wrq->u.data.length)) {
  853. lbs_pr_debug(1, "Copy to user failed\n");
  854. ret = -EFAULT;
  855. }
  856. break;
  857. default:
  858. lbs_pr_debug(1, "Invalid Scan type Ioctl Option\n");
  859. ret = -EINVAL;
  860. break;
  861. }
  862. return ret;
  863. }
  864. static int wlan_scan_mode_ioctl(wlan_private * priv, struct iwreq *wrq)
  865. {
  866. wlan_adapter *adapter = priv->adapter;
  867. u8 buf[12];
  868. u8 *option[] = { "bss", "ibss", "any", "get" };
  869. int i, max_options = (sizeof(option) / sizeof(option[0]));
  870. int ret = 0;
  871. ENTER();
  872. memset(buf, 0, sizeof(buf));
  873. if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
  874. wrq->u.data.length))) {
  875. lbs_pr_debug(1, "Copy from user failed\n");
  876. return -EFAULT;
  877. }
  878. lbs_pr_debug(1, "Scan mode Option = %s\n", buf);
  879. buf[sizeof(buf) - 1] = '\0';
  880. for (i = 0; i < max_options; i++) {
  881. if (!strcmp(buf, option[i]))
  882. break;
  883. }
  884. switch (i) {
  885. case 0:
  886. adapter->scanmode = cmd_bss_type_bss;
  887. break;
  888. case 1:
  889. adapter->scanmode = cmd_bss_type_ibss;
  890. break;
  891. case 2:
  892. adapter->scanmode = cmd_bss_type_any;
  893. break;
  894. case 3:
  895. wrq->u.data.length = strlen(option[adapter->scanmode - 1]) + 1;
  896. lbs_pr_debug(1, "Get Scan mode Option = %s\n",
  897. option[adapter->scanmode - 1]);
  898. lbs_pr_debug(1, "Scan mode length %d\n", wrq->u.data.length);
  899. if (copy_to_user(wrq->u.data.pointer,
  900. option[adapter->scanmode - 1],
  901. wrq->u.data.length)) {
  902. lbs_pr_debug(1, "Copy to user failed\n");
  903. ret = -EFAULT;
  904. }
  905. lbs_pr_debug(1, "GET Scan type Option after copy = %s\n",
  906. (char *)wrq->u.data.pointer);
  907. break;
  908. default:
  909. lbs_pr_debug(1, "Invalid Scan mode Ioctl Option\n");
  910. ret = -EINVAL;
  911. break;
  912. }
  913. LEAVE();
  914. return ret;
  915. }
  916. /**
  917. * @brief Get/Set Adhoc G Rate
  918. *
  919. * @param priv A pointer to wlan_private structure
  920. * @param wrq A pointer to user data
  921. * @return 0--success, otherwise fail
  922. */
  923. static int wlan_do_set_grate_ioctl(wlan_private * priv, struct iwreq *wrq)
  924. {
  925. wlan_adapter *adapter = priv->adapter;
  926. int data, data1;
  927. int *val;
  928. ENTER();
  929. data1 = SUBCMD_DATA(wrq);
  930. switch (data1) {
  931. case 0:
  932. adapter->adhoc_grate_enabled = 0;
  933. break;
  934. case 1:
  935. adapter->adhoc_grate_enabled = 1;
  936. break;
  937. case 2:
  938. break;
  939. default:
  940. return -EINVAL;
  941. }
  942. data = adapter->adhoc_grate_enabled;
  943. val = (int *)wrq->u.name;
  944. *val = data;
  945. LEAVE();
  946. return 0;
  947. }
  948. static inline int hex2int(char c)
  949. {
  950. if (c >= '0' && c <= '9')
  951. return (c - '0');
  952. if (c >= 'a' && c <= 'f')
  953. return (c - 'a' + 10);
  954. if (c >= 'A' && c <= 'F')
  955. return (c - 'A' + 10);
  956. return -1;
  957. }
  958. /* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
  959. into binary format (6 bytes).
  960. This function expects that each byte is represented with 2 characters
  961. (e.g., 11:2:11:11:11:11 is invalid)
  962. */
  963. static char *eth_str2addr(char *ethstr, u8 * addr)
  964. {
  965. int i, val, val2;
  966. char *pos = ethstr;
  967. /* get rid of initial blanks */
  968. while (*pos == ' ' || *pos == '\t')
  969. ++pos;
  970. for (i = 0; i < 6; i++) {
  971. val = hex2int(*pos++);
  972. if (val < 0)
  973. return NULL;
  974. val2 = hex2int(*pos++);
  975. if (val2 < 0)
  976. return NULL;
  977. addr[i] = (val * 16 + val2) & 0xff;
  978. if (i < 5 && *pos++ != ':')
  979. return NULL;
  980. }
  981. return pos;
  982. }
  983. /* this writes xx:xx:xx:xx:xx:xx into ethstr
  984. (ethstr must have space for 18 chars) */
  985. static int eth_addr2str(u8 * addr, char *ethstr)
  986. {
  987. int i;
  988. char *pos = ethstr;
  989. for (i = 0; i < 6; i++) {
  990. sprintf(pos, "%02x", addr[i] & 0xff);
  991. pos += 2;
  992. if (i < 5)
  993. *pos++ = ':';
  994. }
  995. return 17;
  996. }
  997. /**
  998. * @brief Add an entry to the BT table
  999. * @param priv A pointer to wlan_private structure
  1000. * @param req A pointer to ifreq structure
  1001. * @return 0 --success, otherwise fail
  1002. */
  1003. static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
  1004. {
  1005. struct iwreq *wrq = (struct iwreq *)req;
  1006. char ethaddrs_str[18];
  1007. char *pos;
  1008. u8 ethaddr[ETH_ALEN];
  1009. ENTER();
  1010. if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
  1011. sizeof(ethaddrs_str)))
  1012. return -EFAULT;
  1013. if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
  1014. lbs_pr_info("BT_ADD: Invalid MAC address\n");
  1015. return -EINVAL;
  1016. }
  1017. lbs_pr_debug(1, "BT: adding %s\n", ethaddrs_str);
  1018. LEAVE();
  1019. return (libertas_prepare_and_send_command(priv, cmd_bt_access,
  1020. cmd_act_bt_access_add,
  1021. cmd_option_waitforrsp, 0, ethaddr));
  1022. }
  1023. /**
  1024. * @brief Delete an entry from the BT table
  1025. * @param priv A pointer to wlan_private structure
  1026. * @param req A pointer to ifreq structure
  1027. * @return 0 --success, otherwise fail
  1028. */
  1029. static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
  1030. {
  1031. struct iwreq *wrq = (struct iwreq *)req;
  1032. char ethaddrs_str[18];
  1033. u8 ethaddr[ETH_ALEN];
  1034. char *pos;
  1035. ENTER();
  1036. if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
  1037. sizeof(ethaddrs_str)))
  1038. return -EFAULT;
  1039. if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
  1040. lbs_pr_info("Invalid MAC address\n");
  1041. return -EINVAL;
  1042. }
  1043. lbs_pr_debug(1, "BT: deleting %s\n", ethaddrs_str);
  1044. return (libertas_prepare_and_send_command(priv,
  1045. cmd_bt_access,
  1046. cmd_act_bt_access_del,
  1047. cmd_option_waitforrsp, 0, ethaddr));
  1048. LEAVE();
  1049. return 0;
  1050. }
  1051. /**
  1052. * @brief Reset all entries from the BT table
  1053. * @param priv A pointer to wlan_private structure
  1054. * @return 0 --success, otherwise fail
  1055. */
  1056. static int wlan_bt_reset_ioctl(wlan_private * priv)
  1057. {
  1058. ENTER();
  1059. lbs_pr_alert( "BT: resetting\n");
  1060. return (libertas_prepare_and_send_command(priv,
  1061. cmd_bt_access,
  1062. cmd_act_bt_access_reset,
  1063. cmd_option_waitforrsp, 0, NULL));
  1064. LEAVE();
  1065. return 0;
  1066. }
  1067. /**
  1068. * @brief List an entry from the BT table
  1069. * @param priv A pointer to wlan_private structure
  1070. * @param req A pointer to ifreq structure
  1071. * @return 0 --success, otherwise fail
  1072. */
  1073. static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
  1074. {
  1075. int pos;
  1076. char *addr1;
  1077. struct iwreq *wrq = (struct iwreq *)req;
  1078. /* used to pass id and store the bt entry returned by the FW */
  1079. union {
  1080. int id;
  1081. char addr1addr2[2 * ETH_ALEN];
  1082. } param;
  1083. static char outstr[64];
  1084. char *pbuf = outstr;
  1085. int ret;
  1086. ENTER();
  1087. if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
  1088. lbs_pr_debug(1, "Copy from user failed\n");
  1089. return -1;
  1090. }
  1091. param.id = simple_strtoul(outstr, NULL, 10);
  1092. pos = sprintf(pbuf, "%d: ", param.id);
  1093. pbuf += pos;
  1094. ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
  1095. cmd_act_bt_access_list,
  1096. cmd_option_waitforrsp, 0,
  1097. (char *)&param);
  1098. if (ret == 0) {
  1099. addr1 = param.addr1addr2;
  1100. pos = sprintf(pbuf, "ignoring traffic from ");
  1101. pbuf += pos;
  1102. pos = eth_addr2str(addr1, pbuf);
  1103. pbuf += pos;
  1104. } else {
  1105. sprintf(pbuf, "(null)");
  1106. pbuf += pos;
  1107. }
  1108. wrq->u.data.length = strlen(outstr);
  1109. if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
  1110. wrq->u.data.length)) {
  1111. lbs_pr_debug(1, "BT_LIST: Copy to user failed!\n");
  1112. return -EFAULT;
  1113. }
  1114. LEAVE();
  1115. return 0;
  1116. }
  1117. /**
  1118. * @brief Find the next parameter in an input string
  1119. * @param ptr A pointer to the input parameter string
  1120. * @return A pointer to the next parameter, or 0 if no parameters left.
  1121. */
  1122. static char * next_param(char * ptr)
  1123. {
  1124. if (!ptr) return NULL;
  1125. while (*ptr == ' ' || *ptr == '\t') ++ptr;
  1126. return (*ptr == '\0') ? NULL : ptr;
  1127. }
  1128. /**
  1129. * @brief Add an entry to the FWT table
  1130. * @param priv A pointer to wlan_private structure
  1131. * @param req A pointer to ifreq structure
  1132. * @return 0 --success, otherwise fail
  1133. */
  1134. static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
  1135. {
  1136. struct iwreq *wrq = (struct iwreq *)req;
  1137. char in_str[128];
  1138. static struct cmd_ds_fwt_access fwt_access;
  1139. char *ptr;
  1140. ENTER();
  1141. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1142. return -EFAULT;
  1143. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  1144. lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
  1145. return -EINVAL;
  1146. }
  1147. if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
  1148. lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
  1149. return -EINVAL;
  1150. }
  1151. if ((ptr = next_param(ptr)))
  1152. fwt_access.metric =
  1153. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1154. else
  1155. fwt_access.metric = FWT_DEFAULT_METRIC;
  1156. if ((ptr = next_param(ptr)))
  1157. fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
  1158. else
  1159. fwt_access.dir = FWT_DEFAULT_DIR;
  1160. if ((ptr = next_param(ptr)))
  1161. fwt_access.ssn =
  1162. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1163. else
  1164. fwt_access.ssn = FWT_DEFAULT_SSN;
  1165. if ((ptr = next_param(ptr)))
  1166. fwt_access.dsn =
  1167. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1168. else
  1169. fwt_access.dsn = FWT_DEFAULT_DSN;
  1170. if ((ptr = next_param(ptr)))
  1171. fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
  1172. else
  1173. fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
  1174. if ((ptr = next_param(ptr)))
  1175. fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
  1176. else
  1177. fwt_access.ttl = FWT_DEFAULT_TTL;
  1178. if ((ptr = next_param(ptr)))
  1179. fwt_access.expiration =
  1180. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1181. else
  1182. fwt_access.expiration = FWT_DEFAULT_EXPIRATION;
  1183. if ((ptr = next_param(ptr)))
  1184. fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
  1185. else
  1186. fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
  1187. if ((ptr = next_param(ptr)))
  1188. fwt_access.snr =
  1189. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1190. else
  1191. fwt_access.snr = FWT_DEFAULT_SNR;
  1192. #ifdef DEBUG
  1193. {
  1194. char ethaddr1_str[18], ethaddr2_str[18];
  1195. eth_addr2str(fwt_access.da, ethaddr1_str);
  1196. eth_addr2str(fwt_access.ra, ethaddr2_str);
  1197. lbs_pr_debug(1, "FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
  1198. fwt_access.dir, ethaddr2_str);
  1199. lbs_pr_debug(1, "FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
  1200. fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
  1201. fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
  1202. fwt_access.sleepmode, fwt_access.snr);
  1203. }
  1204. #endif
  1205. LEAVE();
  1206. return (libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1207. cmd_act_fwt_access_add,
  1208. cmd_option_waitforrsp, 0,
  1209. (void *)&fwt_access));
  1210. }
  1211. /**
  1212. * @brief Delete an entry from the FWT table
  1213. * @param priv A pointer to wlan_private structure
  1214. * @param req A pointer to ifreq structure
  1215. * @return 0 --success, otherwise fail
  1216. */
  1217. static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
  1218. {
  1219. struct iwreq *wrq = (struct iwreq *)req;
  1220. char in_str[64];
  1221. static struct cmd_ds_fwt_access fwt_access;
  1222. char *ptr;
  1223. ENTER();
  1224. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1225. return -EFAULT;
  1226. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  1227. lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
  1228. return -EINVAL;
  1229. }
  1230. if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
  1231. lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
  1232. return -EINVAL;
  1233. }
  1234. if ((ptr = next_param(ptr)))
  1235. fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
  1236. else
  1237. fwt_access.dir = FWT_DEFAULT_DIR;
  1238. #ifdef DEBUG
  1239. {
  1240. char ethaddr1_str[18], ethaddr2_str[18];
  1241. lbs_pr_debug(1, "FWT_DEL: line is %s\n", in_str);
  1242. eth_addr2str(fwt_access.da, ethaddr1_str);
  1243. eth_addr2str(fwt_access.ra, ethaddr2_str);
  1244. lbs_pr_debug(1, "FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
  1245. ethaddr2_str, fwt_access.dir);
  1246. }
  1247. #endif
  1248. LEAVE();
  1249. return (libertas_prepare_and_send_command(priv,
  1250. cmd_fwt_access,
  1251. cmd_act_fwt_access_del,
  1252. cmd_option_waitforrsp, 0,
  1253. (void *)&fwt_access));
  1254. }
  1255. /**
  1256. * @brief Print route parameters
  1257. * @param fwt_access struct cmd_ds_fwt_access with route info
  1258. * @param buf destination buffer for route info
  1259. */
  1260. static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
  1261. {
  1262. buf += sprintf(buf, " ");
  1263. buf += eth_addr2str(fwt_access.da, buf);
  1264. buf += sprintf(buf, " ");
  1265. buf += eth_addr2str(fwt_access.ra, buf);
  1266. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
  1267. buf += sprintf(buf, " %u", fwt_access.dir);
  1268. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
  1269. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
  1270. buf += sprintf(buf, " %u", fwt_access.hopcount);
  1271. buf += sprintf(buf, " %u", fwt_access.ttl);
  1272. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
  1273. buf += sprintf(buf, " %u", fwt_access.sleepmode);
  1274. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.snr));
  1275. }
  1276. /**
  1277. * @brief Lookup an entry in the FWT table
  1278. * @param priv A pointer to wlan_private structure
  1279. * @param req A pointer to ifreq structure
  1280. * @return 0 --success, otherwise fail
  1281. */
  1282. static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
  1283. {
  1284. struct iwreq *wrq = (struct iwreq *)req;
  1285. char in_str[64];
  1286. char *ptr;
  1287. static struct cmd_ds_fwt_access fwt_access;
  1288. static char out_str[128];
  1289. int ret;
  1290. ENTER();
  1291. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1292. return -EFAULT;
  1293. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  1294. lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
  1295. return -EINVAL;
  1296. }
  1297. #ifdef DEBUG
  1298. {
  1299. char ethaddr1_str[18];
  1300. lbs_pr_debug(1, "FWT_LOOKUP: line is %s\n", in_str);
  1301. eth_addr2str(fwt_access.da, ethaddr1_str);
  1302. lbs_pr_debug(1, "FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
  1303. }
  1304. #endif
  1305. ret = libertas_prepare_and_send_command(priv,
  1306. cmd_fwt_access,
  1307. cmd_act_fwt_access_lookup,
  1308. cmd_option_waitforrsp, 0,
  1309. (void *)&fwt_access);
  1310. if (ret == 0)
  1311. print_route(fwt_access, out_str);
  1312. else
  1313. sprintf(out_str, "(null)");
  1314. wrq->u.data.length = strlen(out_str);
  1315. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  1316. wrq->u.data.length)) {
  1317. lbs_pr_debug(1, "FWT_LOOKUP: Copy to user failed!\n");
  1318. return -EFAULT;
  1319. }
  1320. LEAVE();
  1321. return 0;
  1322. }
  1323. /**
  1324. * @brief Reset all entries from the FWT table
  1325. * @param priv A pointer to wlan_private structure
  1326. * @return 0 --success, otherwise fail
  1327. */
  1328. static int wlan_fwt_reset_ioctl(wlan_private * priv)
  1329. {
  1330. lbs_pr_debug(1, "FWT: resetting\n");
  1331. return (libertas_prepare_and_send_command(priv,
  1332. cmd_fwt_access,
  1333. cmd_act_fwt_access_reset,
  1334. cmd_option_waitforrsp, 0, NULL));
  1335. }
  1336. /**
  1337. * @brief List an entry from the FWT table
  1338. * @param priv A pointer to wlan_private structure
  1339. * @param req A pointer to ifreq structure
  1340. * @return 0 --success, otherwise fail
  1341. */
  1342. static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
  1343. {
  1344. struct iwreq *wrq = (struct iwreq *)req;
  1345. char in_str[8];
  1346. static struct cmd_ds_fwt_access fwt_access;
  1347. char *ptr = in_str;
  1348. static char out_str[128];
  1349. char *pbuf = out_str;
  1350. int ret;
  1351. ENTER();
  1352. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1353. return -EFAULT;
  1354. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1355. #ifdef DEBUG
  1356. {
  1357. lbs_pr_debug(1, "FWT_LIST: line is %s\n", in_str);
  1358. lbs_pr_debug(1, "FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
  1359. }
  1360. #endif
  1361. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1362. cmd_act_fwt_access_list,
  1363. cmd_option_waitforrsp, 0, (void *)&fwt_access);
  1364. if (ret == 0)
  1365. print_route(fwt_access, pbuf);
  1366. else
  1367. pbuf += sprintf(pbuf, " (null)");
  1368. wrq->u.data.length = strlen(out_str);
  1369. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  1370. wrq->u.data.length)) {
  1371. lbs_pr_debug(1, "FWT_LIST: Copy to user failed!\n");
  1372. return -EFAULT;
  1373. }
  1374. LEAVE();
  1375. return 0;
  1376. }
  1377. /**
  1378. * @brief List an entry from the FRT table
  1379. * @param priv A pointer to wlan_private structure
  1380. * @param req A pointer to ifreq structure
  1381. * @return 0 --success, otherwise fail
  1382. */
  1383. static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
  1384. {
  1385. struct iwreq *wrq = (struct iwreq *)req;
  1386. char in_str[64];
  1387. static struct cmd_ds_fwt_access fwt_access;
  1388. char *ptr = in_str;
  1389. static char out_str[128];
  1390. char *pbuf = out_str;
  1391. int ret;
  1392. ENTER();
  1393. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1394. return -EFAULT;
  1395. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1396. #ifdef DEBUG
  1397. {
  1398. lbs_pr_debug(1, "FWT_LIST_ROUTE: line is %s\n", in_str);
  1399. lbs_pr_debug(1, "FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
  1400. }
  1401. #endif
  1402. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1403. cmd_act_fwt_access_list_route,
  1404. cmd_option_waitforrsp, 0, (void *)&fwt_access);
  1405. if (ret == 0) {
  1406. pbuf += sprintf(pbuf, " ");
  1407. pbuf += eth_addr2str(fwt_access.da, pbuf);
  1408. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.metric));
  1409. pbuf += sprintf(pbuf, " %u", fwt_access.dir);
  1410. /* note that the firmware returns the nid in the id field */
  1411. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.id));
  1412. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.ssn));
  1413. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.dsn));
  1414. pbuf += sprintf(pbuf, " hop %u", fwt_access.hopcount);
  1415. pbuf += sprintf(pbuf, " ttl %u", fwt_access.ttl);
  1416. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.expiration));
  1417. } else
  1418. pbuf += sprintf(pbuf, " (null)");
  1419. wrq->u.data.length = strlen(out_str);
  1420. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  1421. wrq->u.data.length)) {
  1422. lbs_pr_debug(1, "FWT_LIST_ROUTE: Copy to user failed!\n");
  1423. return -EFAULT;
  1424. }
  1425. LEAVE();
  1426. return 0;
  1427. }
  1428. /**
  1429. * @brief List an entry from the FNT table
  1430. * @param priv A pointer to wlan_private structure
  1431. * @param req A pointer to ifreq structure
  1432. * @return 0 --success, otherwise fail
  1433. */
  1434. static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
  1435. {
  1436. struct iwreq *wrq = (struct iwreq *)req;
  1437. char in_str[8];
  1438. static struct cmd_ds_fwt_access fwt_access;
  1439. char *ptr = in_str;
  1440. static char out_str[128];
  1441. char *pbuf = out_str;
  1442. int ret;
  1443. ENTER();
  1444. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1445. return -EFAULT;
  1446. memset(&fwt_access, 0, sizeof(fwt_access));
  1447. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1448. #ifdef DEBUG
  1449. {
  1450. lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: line is %s\n", in_str);
  1451. lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
  1452. }
  1453. #endif
  1454. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1455. cmd_act_fwt_access_list_neighbor,
  1456. cmd_option_waitforrsp, 0,
  1457. (void *)&fwt_access);
  1458. if (ret == 0) {
  1459. pbuf += sprintf(pbuf, " ra ");
  1460. pbuf += eth_addr2str(fwt_access.ra, pbuf);
  1461. pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode);
  1462. pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr));
  1463. pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references));
  1464. } else
  1465. pbuf += sprintf(pbuf, " (null)");
  1466. wrq->u.data.length = strlen(out_str);
  1467. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  1468. wrq->u.data.length)) {
  1469. lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: Copy to user failed!\n");
  1470. return -EFAULT;
  1471. }
  1472. LEAVE();
  1473. return 0;
  1474. }
  1475. /**
  1476. * @brief Cleans up the route (FRT) and neighbor (FNT) tables
  1477. * (Garbage Collection)
  1478. * @param priv A pointer to wlan_private structure
  1479. * @param req A pointer to ifreq structure
  1480. * @return 0 --success, otherwise fail
  1481. */
  1482. static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
  1483. {
  1484. static struct cmd_ds_fwt_access fwt_access;
  1485. int ret;
  1486. ENTER();
  1487. lbs_pr_debug(1, "FWT: cleaning up\n");
  1488. memset(&fwt_access, 0, sizeof(fwt_access));
  1489. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1490. cmd_act_fwt_access_cleanup,
  1491. cmd_option_waitforrsp, 0,
  1492. (void *)&fwt_access);
  1493. if (ret == 0)
  1494. req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
  1495. else
  1496. return -EFAULT;
  1497. LEAVE();
  1498. return 0;
  1499. }
  1500. /**
  1501. * @brief Gets firmware internal time (debug purposes)
  1502. * @param priv A pointer to wlan_private structure
  1503. * @param req A pointer to ifreq structure
  1504. * @return 0 --success, otherwise fail
  1505. */
  1506. static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
  1507. {
  1508. static struct cmd_ds_fwt_access fwt_access;
  1509. int ret;
  1510. ENTER();
  1511. lbs_pr_debug(1, "FWT: getting time\n");
  1512. memset(&fwt_access, 0, sizeof(fwt_access));
  1513. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1514. cmd_act_fwt_access_time,
  1515. cmd_option_waitforrsp, 0,
  1516. (void *)&fwt_access);
  1517. if (ret == 0)
  1518. req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
  1519. else
  1520. return -EFAULT;
  1521. LEAVE();
  1522. return 0;
  1523. }
  1524. /**
  1525. * @brief Gets mesh ttl from firmware
  1526. * @param priv A pointer to wlan_private structure
  1527. * @param req A pointer to ifreq structure
  1528. * @return 0 --success, otherwise fail
  1529. */
  1530. static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
  1531. {
  1532. struct cmd_ds_mesh_access mesh_access;
  1533. int ret;
  1534. ENTER();
  1535. memset(&mesh_access, 0, sizeof(mesh_access));
  1536. ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
  1537. cmd_act_mesh_get_ttl,
  1538. cmd_option_waitforrsp, 0,
  1539. (void *)&mesh_access);
  1540. if (ret == 0) {
  1541. req->ifr_data = (char *)(le32_to_cpu(mesh_access.data[0]));
  1542. }
  1543. else
  1544. return -EFAULT;
  1545. LEAVE();
  1546. return 0;
  1547. }
  1548. /**
  1549. * @brief Gets mesh ttl from firmware
  1550. * @param priv A pointer to wlan_private structure
  1551. * @param ttl New ttl value
  1552. * @return 0 --success, otherwise fail
  1553. */
  1554. static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
  1555. {
  1556. struct cmd_ds_mesh_access mesh_access;
  1557. int ret;
  1558. ENTER();
  1559. if( (ttl > 0xff) || (ttl < 0) )
  1560. return -EINVAL;
  1561. memset(&mesh_access, 0, sizeof(mesh_access));
  1562. mesh_access.data[0] = ttl;
  1563. ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
  1564. cmd_act_mesh_set_ttl,
  1565. cmd_option_waitforrsp, 0,
  1566. (void *)&mesh_access);
  1567. if (ret != 0)
  1568. ret = -EFAULT;
  1569. LEAVE();
  1570. return ret;
  1571. }
  1572. /**
  1573. * @brief ioctl function - entry point
  1574. *
  1575. * @param dev A pointer to net_device structure
  1576. * @param req A pointer to ifreq structure
  1577. * @param cmd command
  1578. * @return 0--success, otherwise fail
  1579. */
  1580. int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
  1581. {
  1582. int subcmd = 0;
  1583. int idata = 0;
  1584. int *pdata;
  1585. int ret = 0;
  1586. wlan_private *priv = dev->priv;
  1587. wlan_adapter *adapter = priv->adapter;
  1588. struct iwreq *wrq = (struct iwreq *)req;
  1589. ENTER();
  1590. lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
  1591. switch (cmd) {
  1592. case WLANSCAN_TYPE:
  1593. lbs_pr_debug(1, "Scan type Ioctl\n");
  1594. ret = wlan_scan_type_ioctl(priv, wrq);
  1595. break;
  1596. case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */
  1597. switch (wrq->u.data.flags) {
  1598. case WLANDEAUTH:
  1599. lbs_pr_debug(1, "Deauth\n");
  1600. libertas_send_deauth(priv);
  1601. break;
  1602. case WLANADHOCSTOP:
  1603. lbs_pr_debug(1, "Adhoc stop\n");
  1604. ret = libertas_do_adhocstop_ioctl(priv);
  1605. break;
  1606. case WLANRADIOON:
  1607. wlan_radio_ioctl(priv, 1);
  1608. break;
  1609. case WLANRADIOOFF:
  1610. wlan_radio_ioctl(priv, 0);
  1611. break;
  1612. case WLANWLANIDLEON:
  1613. libertas_idle_on(priv);
  1614. break;
  1615. case WLANWLANIDLEOFF:
  1616. libertas_idle_off(priv);
  1617. break;
  1618. case WLAN_SUBCMD_BT_RESET: /* bt_reset */
  1619. wlan_bt_reset_ioctl(priv);
  1620. break;
  1621. case WLAN_SUBCMD_FWT_RESET: /* fwt_reset */
  1622. wlan_fwt_reset_ioctl(priv);
  1623. break;
  1624. } /* End of switch */
  1625. break;
  1626. case WLANSETWPAIE:
  1627. ret = wlan_setwpaie_ioctl(priv, req);
  1628. break;
  1629. case WLAN_SETINT_GETINT:
  1630. /* The first 4 bytes of req->ifr_data is sub-ioctl number
  1631. * after 4 bytes sits the payload.
  1632. */
  1633. subcmd = (int)req->ifr_data; //from iwpriv subcmd
  1634. switch (subcmd) {
  1635. case WLANNF:
  1636. ret = wlan_get_nf(priv, wrq);
  1637. break;
  1638. case WLANRSSI:
  1639. ret = wlan_get_rssi(priv, wrq);
  1640. break;
  1641. case WLANENABLE11D:
  1642. ret = libertas_cmd_enable_11d(priv, wrq);
  1643. break;
  1644. case WLANADHOCGRATE:
  1645. ret = wlan_do_set_grate_ioctl(priv, wrq);
  1646. break;
  1647. case WLAN_SUBCMD_SET_PRESCAN:
  1648. ret = wlan_subcmd_setprescan_ioctl(priv, wrq);
  1649. break;
  1650. }
  1651. break;
  1652. case WLAN_SETONEINT_GETONEINT:
  1653. switch (wrq->u.data.flags) {
  1654. case WLAN_BEACON_INTERVAL:
  1655. ret = wlan_beacon_interval(priv, wrq);
  1656. break;
  1657. case WLAN_LISTENINTRVL:
  1658. if (!wrq->u.data.length) {
  1659. int data;
  1660. lbs_pr_debug(1, "Get locallisteninterval value\n");
  1661. #define GET_ONE_INT 1
  1662. data = adapter->locallisteninterval;
  1663. if (copy_to_user(wrq->u.data.pointer,
  1664. &data, sizeof(int))) {
  1665. lbs_pr_debug(1, "Copy to user failed\n");
  1666. return -EFAULT;
  1667. }
  1668. wrq->u.data.length = GET_ONE_INT;
  1669. } else {
  1670. int data;
  1671. if (copy_from_user
  1672. (&data, wrq->u.data.pointer, sizeof(int))) {
  1673. lbs_pr_debug(1, "Copy from user failed\n");
  1674. return -EFAULT;
  1675. }
  1676. lbs_pr_debug(1, "Set locallisteninterval = %d\n",
  1677. data);
  1678. #define MAX_U16_VAL 65535
  1679. if (data > MAX_U16_VAL) {
  1680. lbs_pr_debug(1, "Exceeds U16 value\n");
  1681. return -EINVAL;
  1682. }
  1683. adapter->locallisteninterval = data;
  1684. }
  1685. break;
  1686. case WLAN_TXCONTROL:
  1687. ret = wlan_txcontrol(priv, wrq); //adds for txcontrol ioctl
  1688. break;
  1689. case WLAN_NULLPKTINTERVAL:
  1690. ret = wlan_null_pkt_interval(priv, wrq);
  1691. break;
  1692. default:
  1693. ret = -EOPNOTSUPP;
  1694. break;
  1695. }
  1696. break;
  1697. case WLAN_SETONEINT_GETNONE:
  1698. /* The first 4 bytes of req->ifr_data is sub-ioctl number
  1699. * after 4 bytes sits the payload.
  1700. */
  1701. subcmd = wrq->u.data.flags; //from wpa_supplicant subcmd
  1702. if (!subcmd)
  1703. subcmd = (int)req->ifr_data; //from iwpriv subcmd
  1704. switch (subcmd) {
  1705. case WLAN_SUBCMD_SETRXANTENNA: /* SETRXANTENNA */
  1706. idata = SUBCMD_DATA(wrq);
  1707. ret = setrxantenna(priv, idata);
  1708. break;
  1709. case WLAN_SUBCMD_SETTXANTENNA: /* SETTXANTENNA */
  1710. idata = SUBCMD_DATA(wrq);
  1711. ret = settxantenna(priv, idata);
  1712. break;
  1713. case WLAN_SET_ATIM_WINDOW:
  1714. adapter->atimwindow = SUBCMD_DATA(wrq);
  1715. adapter->atimwindow = min_t(__u16, adapter->atimwindow, 50);
  1716. break;
  1717. case WLANSETBCNAVG:
  1718. adapter->bcn_avg_factor = SUBCMD_DATA(wrq);
  1719. if (adapter->bcn_avg_factor == 0)
  1720. adapter->bcn_avg_factor =
  1721. DEFAULT_BCN_AVG_FACTOR;
  1722. if (adapter->bcn_avg_factor > DEFAULT_BCN_AVG_FACTOR)
  1723. adapter->bcn_avg_factor =
  1724. DEFAULT_BCN_AVG_FACTOR;
  1725. break;
  1726. case WLANSETDATAAVG:
  1727. adapter->data_avg_factor = SUBCMD_DATA(wrq);
  1728. if (adapter->data_avg_factor == 0)
  1729. adapter->data_avg_factor =
  1730. DEFAULT_DATA_AVG_FACTOR;
  1731. if (adapter->data_avg_factor > DEFAULT_DATA_AVG_FACTOR)
  1732. adapter->data_avg_factor =
  1733. DEFAULT_DATA_AVG_FACTOR;
  1734. break;
  1735. case WLANSETREGION:
  1736. idata = SUBCMD_DATA(wrq);
  1737. ret = wlan_set_region(priv, (u16) idata);
  1738. break;
  1739. case WLAN_SET_LISTEN_INTERVAL:
  1740. idata = SUBCMD_DATA(wrq);
  1741. adapter->listeninterval = (u16) idata;
  1742. break;
  1743. case WLAN_SET_MULTIPLE_DTIM:
  1744. ret = wlan_set_multiple_dtim_ioctl(priv, req);
  1745. break;
  1746. case WLANSETAUTHALG:
  1747. ret = wlan_setauthalg_ioctl(priv, req);
  1748. break;
  1749. case WLANSETENCRYPTIONMODE:
  1750. ret = wlan_setencryptionmode_ioctl(priv, req);
  1751. break;
  1752. case WLAN_SET_LINKMODE:
  1753. ret = wlan_set_linkmode_ioctl(priv, req);
  1754. break;
  1755. case WLAN_SET_RADIOMODE:
  1756. ret = wlan_set_radiomode_ioctl(priv, req);
  1757. break;
  1758. case WLAN_SET_DEBUGMODE:
  1759. ret = wlan_set_debugmode_ioctl(priv, req);
  1760. break;
  1761. case WLAN_SUBCMD_MESH_SET_TTL:
  1762. idata = SUBCMD_DATA(wrq);
  1763. ret = wlan_mesh_set_ttl_ioctl(priv, idata);
  1764. break;
  1765. default:
  1766. ret = -EOPNOTSUPP;
  1767. break;
  1768. }
  1769. break;
  1770. case WLAN_SETNONE_GETTWELVE_CHAR: /* Get Antenna settings */
  1771. /*
  1772. * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is
  1773. * in flags of iwreq structure, otherwise it will be in
  1774. * mode member of iwreq structure.
  1775. */
  1776. switch ((int)wrq->u.data.flags) {
  1777. case WLAN_SUBCMD_GETRXANTENNA: /* Get Rx Antenna */
  1778. ret = wlan_subcmd_getrxantenna_ioctl(priv, req);
  1779. break;
  1780. case WLAN_SUBCMD_GETTXANTENNA: /* Get Tx Antenna */
  1781. ret = wlan_subcmd_gettxantenna_ioctl(priv, req);
  1782. break;
  1783. case WLAN_GET_TSF:
  1784. ret = wlan_get_tsf_ioctl(priv, wrq);
  1785. break;
  1786. }
  1787. break;
  1788. case WLAN_SET128CHAR_GET128CHAR:
  1789. switch ((int)wrq->u.data.flags) {
  1790. case WLANSCAN_MODE:
  1791. lbs_pr_debug(1, "Scan mode Ioctl\n");
  1792. ret = wlan_scan_mode_ioctl(priv, wrq);
  1793. break;
  1794. case WLAN_GET_ADHOC_STATUS:
  1795. ret = wlan_get_adhoc_status_ioctl(priv, wrq);
  1796. break;
  1797. case WLAN_SUBCMD_BT_ADD:
  1798. ret = wlan_bt_add_ioctl(priv, req);
  1799. break;
  1800. case WLAN_SUBCMD_BT_DEL:
  1801. ret = wlan_bt_del_ioctl(priv, req);
  1802. break;
  1803. case WLAN_SUBCMD_BT_LIST:
  1804. ret = wlan_bt_list_ioctl(priv, req);
  1805. break;
  1806. case WLAN_SUBCMD_FWT_ADD:
  1807. ret = wlan_fwt_add_ioctl(priv, req);
  1808. break;
  1809. case WLAN_SUBCMD_FWT_DEL:
  1810. ret = wlan_fwt_del_ioctl(priv, req);
  1811. break;
  1812. case WLAN_SUBCMD_FWT_LOOKUP:
  1813. ret = wlan_fwt_lookup_ioctl(priv, req);
  1814. break;
  1815. case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
  1816. ret = wlan_fwt_list_neighbor_ioctl(priv, req);
  1817. break;
  1818. case WLAN_SUBCMD_FWT_LIST:
  1819. ret = wlan_fwt_list_ioctl(priv, req);
  1820. break;
  1821. case WLAN_SUBCMD_FWT_LIST_ROUTE:
  1822. ret = wlan_fwt_list_route_ioctl(priv, req);
  1823. break;
  1824. }
  1825. break;
  1826. case WLAN_SETNONE_GETONEINT:
  1827. switch ((int)req->ifr_data) {
  1828. case WLANGETBCNAVG:
  1829. pdata = (int *)wrq->u.name;
  1830. *pdata = (int)adapter->bcn_avg_factor;
  1831. break;
  1832. case WLANGETREGION:
  1833. pdata = (int *)wrq->u.name;
  1834. *pdata = (int)adapter->regioncode;
  1835. break;
  1836. case WLAN_GET_LISTEN_INTERVAL:
  1837. pdata = (int *)wrq->u.name;
  1838. *pdata = (int)adapter->listeninterval;
  1839. break;
  1840. case WLAN_GET_LINKMODE:
  1841. req->ifr_data = (char *)((u32) adapter->linkmode);
  1842. break;
  1843. case WLAN_GET_RADIOMODE:
  1844. req->ifr_data = (char *)((u32) adapter->radiomode);
  1845. break;
  1846. case WLAN_GET_DEBUGMODE:
  1847. req->ifr_data = (char *)((u32) adapter->debugmode);
  1848. break;
  1849. case WLAN_GET_MULTIPLE_DTIM:
  1850. pdata = (int *)wrq->u.name;
  1851. *pdata = (int)adapter->multipledtim;
  1852. break;
  1853. case WLAN_GET_TX_RATE:
  1854. ret = wlan_get_txrate_ioctl(priv, req);
  1855. break;
  1856. case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */
  1857. ret = wlan_fwt_cleanup_ioctl(priv, req);
  1858. break;
  1859. case WLAN_SUBCMD_FWT_TIME: /* fwt_time */
  1860. ret = wlan_fwt_time_ioctl(priv, req);
  1861. break;
  1862. case WLAN_SUBCMD_MESH_GET_TTL:
  1863. ret = wlan_mesh_get_ttl_ioctl(priv, req);
  1864. break;
  1865. default:
  1866. ret = -EOPNOTSUPP;
  1867. }
  1868. break;
  1869. case WLANGETLOG:
  1870. ret = wlan_do_getlog_ioctl(priv, wrq);
  1871. break;
  1872. case WLAN_SET_GET_SIXTEEN_INT:
  1873. switch ((int)wrq->u.data.flags) {
  1874. case WLAN_TPCCFG:
  1875. {
  1876. int data[5];
  1877. struct cmd_ds_802_11_tpc_cfg cfg;
  1878. memset(&cfg, 0, sizeof(cfg));
  1879. if ((wrq->u.data.length > 1)
  1880. && (wrq->u.data.length != 5))
  1881. return -1;
  1882. if (wrq->u.data.length == 0) {
  1883. cfg.action =
  1884. cpu_to_le16
  1885. (cmd_act_get);
  1886. } else {
  1887. if (copy_from_user
  1888. (data, wrq->u.data.pointer,
  1889. sizeof(int) * 5)) {
  1890. lbs_pr_debug(1,
  1891. "Copy from user failed\n");
  1892. return -EFAULT;
  1893. }
  1894. cfg.action =
  1895. cpu_to_le16
  1896. (cmd_act_set);
  1897. cfg.enable = data[0];
  1898. cfg.usesnr = data[1];
  1899. cfg.P0 = data[2];
  1900. cfg.P1 = data[3];
  1901. cfg.P2 = data[4];
  1902. }
  1903. ret =
  1904. libertas_prepare_and_send_command(priv,
  1905. cmd_802_11_tpc_cfg,
  1906. 0,
  1907. cmd_option_waitforrsp,
  1908. 0, (void *)&cfg);
  1909. data[0] = cfg.enable;
  1910. data[1] = cfg.usesnr;
  1911. data[2] = cfg.P0;
  1912. data[3] = cfg.P1;
  1913. data[4] = cfg.P2;
  1914. if (copy_to_user
  1915. (wrq->u.data.pointer, data,
  1916. sizeof(int) * 5)) {
  1917. lbs_pr_debug(1, "Copy to user failed\n");
  1918. return -EFAULT;
  1919. }
  1920. wrq->u.data.length = 5;
  1921. }
  1922. break;
  1923. case WLAN_POWERCFG:
  1924. {
  1925. int data[4];
  1926. struct cmd_ds_802_11_pwr_cfg cfg;
  1927. memset(&cfg, 0, sizeof(cfg));
  1928. if ((wrq->u.data.length > 1)
  1929. && (wrq->u.data.length != 4))
  1930. return -1;
  1931. if (wrq->u.data.length == 0) {
  1932. cfg.action =
  1933. cpu_to_le16
  1934. (cmd_act_get);
  1935. } else {
  1936. if (copy_from_user
  1937. (data, wrq->u.data.pointer,
  1938. sizeof(int) * 4)) {
  1939. lbs_pr_debug(1,
  1940. "Copy from user failed\n");
  1941. return -EFAULT;
  1942. }
  1943. cfg.action =
  1944. cpu_to_le16
  1945. (cmd_act_set);
  1946. cfg.enable = data[0];
  1947. cfg.PA_P0 = data[1];
  1948. cfg.PA_P1 = data[2];
  1949. cfg.PA_P2 = data[3];
  1950. }
  1951. ret =
  1952. libertas_prepare_and_send_command(priv,
  1953. cmd_802_11_pwr_cfg,
  1954. 0,
  1955. cmd_option_waitforrsp,
  1956. 0, (void *)&cfg);
  1957. data[0] = cfg.enable;
  1958. data[1] = cfg.PA_P0;
  1959. data[2] = cfg.PA_P1;
  1960. data[3] = cfg.PA_P2;
  1961. if (copy_to_user
  1962. (wrq->u.data.pointer, data,
  1963. sizeof(int) * 4)) {
  1964. lbs_pr_debug(1, "Copy to user failed\n");
  1965. return -EFAULT;
  1966. }
  1967. wrq->u.data.length = 4;
  1968. }
  1969. break;
  1970. case WLAN_AUTO_FREQ_SET:
  1971. {
  1972. int data[3];
  1973. struct cmd_ds_802_11_afc afc;
  1974. memset(&afc, 0, sizeof(afc));
  1975. if (wrq->u.data.length != 3)
  1976. return -1;
  1977. if (copy_from_user
  1978. (data, wrq->u.data.pointer,
  1979. sizeof(int) * 3)) {
  1980. lbs_pr_debug(1, "Copy from user failed\n");
  1981. return -EFAULT;
  1982. }
  1983. afc.afc_auto = data[0];
  1984. if (afc.afc_auto != 0) {
  1985. afc.threshold = data[1];
  1986. afc.period = data[2];
  1987. } else {
  1988. afc.timing_offset = data[1];
  1989. afc.carrier_offset = data[2];
  1990. }
  1991. ret =
  1992. libertas_prepare_and_send_command(priv,
  1993. cmd_802_11_set_afc,
  1994. 0,
  1995. cmd_option_waitforrsp,
  1996. 0, (void *)&afc);
  1997. }
  1998. break;
  1999. case WLAN_AUTO_FREQ_GET:
  2000. {
  2001. int data[3];
  2002. struct cmd_ds_802_11_afc afc;
  2003. memset(&afc, 0, sizeof(afc));
  2004. ret =
  2005. libertas_prepare_and_send_command(priv,
  2006. cmd_802_11_get_afc,
  2007. 0,
  2008. cmd_option_waitforrsp,
  2009. 0, (void *)&afc);
  2010. data[0] = afc.afc_auto;
  2011. data[1] = afc.timing_offset;
  2012. data[2] = afc.carrier_offset;
  2013. if (copy_to_user
  2014. (wrq->u.data.pointer, data,
  2015. sizeof(int) * 3)) {
  2016. lbs_pr_debug(1, "Copy to user failed\n");
  2017. return -EFAULT;
  2018. }
  2019. wrq->u.data.length = 3;
  2020. }
  2021. break;
  2022. case WLAN_SCANPROBES:
  2023. {
  2024. int data;
  2025. if (wrq->u.data.length > 0) {
  2026. if (copy_from_user
  2027. (&data, wrq->u.data.pointer,
  2028. sizeof(int))) {
  2029. lbs_pr_debug(1,
  2030. "Copy from user failed\n");
  2031. return -EFAULT;
  2032. }
  2033. adapter->scanprobes = data;
  2034. } else {
  2035. data = adapter->scanprobes;
  2036. if (copy_to_user
  2037. (wrq->u.data.pointer, &data,
  2038. sizeof(int))) {
  2039. lbs_pr_debug(1,
  2040. "Copy to user failed\n");
  2041. return -EFAULT;
  2042. }
  2043. }
  2044. wrq->u.data.length = 1;
  2045. }
  2046. break;
  2047. case WLAN_LED_GPIO_CTRL:
  2048. {
  2049. int i;
  2050. int data[16];
  2051. struct cmd_ds_802_11_led_ctrl ctrl;
  2052. struct mrvlietypes_ledgpio *gpio =
  2053. (struct mrvlietypes_ledgpio *) ctrl.data;
  2054. memset(&ctrl, 0, sizeof(ctrl));
  2055. if (wrq->u.data.length > MAX_LEDS * 2)
  2056. return -ENOTSUPP;
  2057. if ((wrq->u.data.length % 2) != 0)
  2058. return -ENOTSUPP;
  2059. if (wrq->u.data.length == 0) {
  2060. ctrl.action =
  2061. cpu_to_le16
  2062. (cmd_act_get);
  2063. } else {
  2064. if (copy_from_user
  2065. (data, wrq->u.data.pointer,
  2066. sizeof(int) *
  2067. wrq->u.data.length)) {
  2068. lbs_pr_debug(1,
  2069. "Copy from user failed\n");
  2070. return -EFAULT;
  2071. }
  2072. ctrl.action =
  2073. cpu_to_le16
  2074. (cmd_act_set);
  2075. ctrl.numled = cpu_to_le16(0);
  2076. gpio->header.type =
  2077. cpu_to_le16(TLV_TYPE_LED_GPIO);
  2078. gpio->header.len = wrq->u.data.length;
  2079. for (i = 0; i < wrq->u.data.length;
  2080. i += 2) {
  2081. gpio->ledpin[i / 2].led =
  2082. data[i];
  2083. gpio->ledpin[i / 2].pin =
  2084. data[i + 1];
  2085. }
  2086. }
  2087. ret =
  2088. libertas_prepare_and_send_command(priv,
  2089. cmd_802_11_led_gpio_ctrl,
  2090. 0,
  2091. cmd_option_waitforrsp,
  2092. 0, (void *)&ctrl);
  2093. for (i = 0; i < gpio->header.len; i += 2) {
  2094. data[i] = gpio->ledpin[i / 2].led;
  2095. data[i + 1] = gpio->ledpin[i / 2].pin;
  2096. }
  2097. if (copy_to_user(wrq->u.data.pointer, data,
  2098. sizeof(int) *
  2099. gpio->header.len)) {
  2100. lbs_pr_debug(1, "Copy to user failed\n");
  2101. return -EFAULT;
  2102. }
  2103. wrq->u.data.length = gpio->header.len;
  2104. }
  2105. break;
  2106. case WLAN_ADAPT_RATESET:
  2107. ret = wlan_adapt_rateset(priv, wrq);
  2108. break;
  2109. case WLAN_INACTIVITY_TIMEOUT:
  2110. ret = wlan_inactivity_timeout(priv, wrq);
  2111. break;
  2112. case WLANSNR:
  2113. ret = wlan_get_snr(priv, wrq);
  2114. break;
  2115. case WLAN_GET_RXINFO:
  2116. ret = wlan_get_rxinfo(priv, wrq);
  2117. }
  2118. break;
  2119. default:
  2120. ret = -EINVAL;
  2121. break;
  2122. }
  2123. LEAVE();
  2124. return ret;
  2125. }