ioctl.c 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425
  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. static int wlan_setencryptionmode_ioctl(wlan_private * priv, struct ifreq *req)
  494. {
  495. int mode;
  496. struct iwreq *wrq = (struct iwreq *)req;
  497. ENTER();
  498. if (wrq->u.data.flags == 0) {
  499. //from iwpriv subcmd
  500. mode = SUBCMD_DATA(wrq);
  501. } else {
  502. //from wpa_supplicant subcmd
  503. if (copy_from_user(&mode, wrq->u.data.pointer, sizeof(int))) {
  504. lbs_pr_debug(1, "Copy from user failed\n");
  505. return -EFAULT;
  506. }
  507. }
  508. lbs_pr_debug(1, "encryption mode is %#x\n", mode);
  509. priv->adapter->secinfo.Encryptionmode = mode;
  510. LEAVE();
  511. return 0;
  512. }
  513. static void adjust_mtu(wlan_private * priv)
  514. {
  515. int mtu_increment = 0;
  516. if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
  517. mtu_increment += sizeof(struct ieee80211_hdr_4addr);
  518. if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP)
  519. mtu_increment += max(sizeof(struct tx_radiotap_hdr),
  520. sizeof(struct rx_radiotap_hdr));
  521. priv->wlan_dev.netdev->mtu = ETH_FRAME_LEN
  522. - sizeof(struct ethhdr)
  523. + mtu_increment;
  524. }
  525. /**
  526. * @brief Set Link-Layer Layer mode
  527. * @param priv A pointer to wlan_private structure
  528. * @param req A pointer to ifreq structure
  529. * @return 0 --success, otherwise fail
  530. */
  531. static int wlan_set_linkmode_ioctl(wlan_private * priv, struct ifreq *req)
  532. {
  533. int mode;
  534. mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
  535. switch (mode) {
  536. case WLAN_LINKMODE_802_3:
  537. priv->adapter->linkmode = mode;
  538. break;
  539. case WLAN_LINKMODE_802_11:
  540. priv->adapter->linkmode = mode;
  541. break;
  542. default:
  543. lbs_pr_info("usb8388-5: invalid link-layer mode (%#x)\n",
  544. mode);
  545. return -EINVAL;
  546. break;
  547. }
  548. lbs_pr_debug(1, "usb8388-5: link-layer mode is %#x\n", mode);
  549. adjust_mtu(priv);
  550. return 0;
  551. }
  552. /**
  553. * @brief Set Radio header mode
  554. * @param priv A pointer to wlan_private structure
  555. * @param req A pointer to ifreq structure
  556. * @return 0 --success, otherwise fail
  557. */
  558. static int wlan_set_radiomode_ioctl(wlan_private * priv, struct ifreq *req)
  559. {
  560. int mode;
  561. mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
  562. switch (mode) {
  563. case WLAN_RADIOMODE_NONE:
  564. priv->adapter->radiomode = mode;
  565. break;
  566. case WLAN_RADIOMODE_RADIOTAP:
  567. priv->adapter->radiomode = mode;
  568. break;
  569. default:
  570. lbs_pr_debug(1, "usb8388-5: invalid radio header mode (%#x)\n",
  571. mode);
  572. return -EINVAL;
  573. }
  574. lbs_pr_debug(1, "usb8388-5: radio-header mode is %#x\n", mode);
  575. adjust_mtu(priv);
  576. return 0;
  577. }
  578. /**
  579. * @brief Set Debug header mode
  580. * @param priv A pointer to wlan_private structure
  581. * @param req A pointer to ifreq structure
  582. * @return 0 --success, otherwise fail
  583. */
  584. static int wlan_set_debugmode_ioctl(wlan_private * priv, struct ifreq *req)
  585. {
  586. priv->adapter->debugmode = (int)((struct ifreq *)
  587. ((u8 *) req + 4))->ifr_data;
  588. return 0;
  589. }
  590. static int wlan_subcmd_getrxantenna_ioctl(wlan_private * priv,
  591. struct ifreq *req)
  592. {
  593. int len;
  594. char buf[8];
  595. struct iwreq *wrq = (struct iwreq *)req;
  596. lbs_pr_debug(1, "WLAN_SUBCMD_GETRXANTENNA\n");
  597. len = getrxantenna(priv, buf);
  598. wrq->u.data.length = len;
  599. if (wrq->u.data.pointer) {
  600. if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
  601. lbs_pr_debug(1, "CopyToUser failed\n");
  602. return -EFAULT;
  603. }
  604. }
  605. return 0;
  606. }
  607. static int wlan_subcmd_gettxantenna_ioctl(wlan_private * priv,
  608. struct ifreq *req)
  609. {
  610. int len;
  611. char buf[8];
  612. struct iwreq *wrq = (struct iwreq *)req;
  613. lbs_pr_debug(1, "WLAN_SUBCMD_GETTXANTENNA\n");
  614. len = gettxantenna(priv, buf);
  615. wrq->u.data.length = len;
  616. if (wrq->u.data.pointer) {
  617. if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
  618. lbs_pr_debug(1, "CopyToUser failed\n");
  619. return -EFAULT;
  620. }
  621. }
  622. return 0;
  623. }
  624. /**
  625. * @brief Get the MAC TSF value from the firmware
  626. *
  627. * @param priv A pointer to wlan_private structure
  628. * @param wrq A pointer to iwreq structure containing buffer
  629. * space to store a TSF value retrieved from the firmware
  630. *
  631. * @return 0 if successful; IOCTL error code otherwise
  632. */
  633. static int wlan_get_tsf_ioctl(wlan_private * priv, struct iwreq *wrq)
  634. {
  635. u64 tsfval;
  636. int ret;
  637. ret = libertas_prepare_and_send_command(priv,
  638. cmd_get_tsf,
  639. 0, cmd_option_waitforrsp, 0, &tsfval);
  640. lbs_pr_debug(1, "IOCTL: Get TSF = 0x%016llx\n", tsfval);
  641. if (ret != 0) {
  642. lbs_pr_debug(1, "IOCTL: Get TSF; command exec failed\n");
  643. ret = -EFAULT;
  644. } else {
  645. if (copy_to_user(wrq->u.data.pointer,
  646. &tsfval,
  647. min_t(size_t, wrq->u.data.length,
  648. sizeof(tsfval))) != 0) {
  649. lbs_pr_debug(1, "IOCTL: Get TSF; Copy to user failed\n");
  650. ret = -EFAULT;
  651. } else {
  652. ret = 0;
  653. }
  654. }
  655. return ret;
  656. }
  657. /**
  658. * @brief Get/Set adapt rate
  659. * @param priv A pointer to wlan_private structure
  660. * @param wrq A pointer to iwreq structure
  661. * @return 0 --success, otherwise fail
  662. */
  663. static int wlan_adapt_rateset(wlan_private * priv, struct iwreq *wrq)
  664. {
  665. int ret;
  666. wlan_adapter *adapter = priv->adapter;
  667. int data[2];
  668. memset(data, 0, sizeof(data));
  669. if (!wrq->u.data.length) {
  670. lbs_pr_debug(1, "Get ADAPT RATE SET\n");
  671. ret = libertas_prepare_and_send_command(priv,
  672. cmd_802_11_rate_adapt_rateset,
  673. cmd_act_get,
  674. cmd_option_waitforrsp, 0, NULL);
  675. data[0] = adapter->enablehwauto;
  676. data[1] = adapter->ratebitmap;
  677. if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
  678. lbs_pr_debug(1, "Copy to user failed\n");
  679. return -EFAULT;
  680. }
  681. #define GET_TWO_INT 2
  682. wrq->u.data.length = GET_TWO_INT;
  683. } else {
  684. lbs_pr_debug(1, "Set ADAPT RATE SET\n");
  685. if (wrq->u.data.length > 2)
  686. return -EINVAL;
  687. if (copy_from_user
  688. (data, wrq->u.data.pointer,
  689. sizeof(int) * wrq->u.data.length)) {
  690. lbs_pr_debug(1, "Copy from user failed\n");
  691. return -EFAULT;
  692. }
  693. adapter->enablehwauto = data[0];
  694. adapter->ratebitmap = data[1];
  695. ret = libertas_prepare_and_send_command(priv,
  696. cmd_802_11_rate_adapt_rateset,
  697. cmd_act_set,
  698. cmd_option_waitforrsp, 0, NULL);
  699. }
  700. return ret;
  701. }
  702. /**
  703. * @brief Get/Set inactivity timeout
  704. * @param priv A pointer to wlan_private structure
  705. * @param wrq A pointer to iwreq structure
  706. * @return 0 --success, otherwise fail
  707. */
  708. static int wlan_inactivity_timeout(wlan_private * priv, struct iwreq *wrq)
  709. {
  710. int ret;
  711. int data = 0;
  712. u16 timeout = 0;
  713. ENTER();
  714. if (wrq->u.data.length > 1)
  715. return -ENOTSUPP;
  716. if (wrq->u.data.length == 0) {
  717. /* Get */
  718. ret = libertas_prepare_and_send_command(priv,
  719. cmd_802_11_inactivity_timeout,
  720. cmd_act_get,
  721. cmd_option_waitforrsp, 0,
  722. &timeout);
  723. data = timeout;
  724. if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
  725. lbs_pr_debug(1, "Copy to user failed\n");
  726. return -EFAULT;
  727. }
  728. } else {
  729. /* Set */
  730. if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
  731. lbs_pr_debug(1, "Copy from user failed\n");
  732. return -EFAULT;
  733. }
  734. timeout = data;
  735. ret = libertas_prepare_and_send_command(priv,
  736. cmd_802_11_inactivity_timeout,
  737. cmd_act_set,
  738. cmd_option_waitforrsp, 0,
  739. &timeout);
  740. }
  741. wrq->u.data.length = 1;
  742. LEAVE();
  743. return ret;
  744. }
  745. static int wlan_do_getlog_ioctl(wlan_private * priv, struct iwreq *wrq)
  746. {
  747. int ret;
  748. char buf[GETLOG_BUFSIZE - 1];
  749. wlan_adapter *adapter = priv->adapter;
  750. lbs_pr_debug(1, " GET STATS\n");
  751. ret = libertas_prepare_and_send_command(priv, cmd_802_11_get_log,
  752. 0, cmd_option_waitforrsp, 0, NULL);
  753. if (ret) {
  754. return ret;
  755. }
  756. if (wrq->u.data.pointer) {
  757. sprintf(buf, "\n mcasttxframe %u failed %u retry %u "
  758. "multiretry %u framedup %u "
  759. "rtssuccess %u rtsfailure %u ackfailure %u\n"
  760. "rxfrag %u mcastrxframe %u fcserror %u "
  761. "txframe %u wepundecryptable %u ",
  762. adapter->logmsg.mcasttxframe,
  763. adapter->logmsg.failed,
  764. adapter->logmsg.retry,
  765. adapter->logmsg.multiretry,
  766. adapter->logmsg.framedup,
  767. adapter->logmsg.rtssuccess,
  768. adapter->logmsg.rtsfailure,
  769. adapter->logmsg.ackfailure,
  770. adapter->logmsg.rxfrag,
  771. adapter->logmsg.mcastrxframe,
  772. adapter->logmsg.fcserror,
  773. adapter->logmsg.txframe,
  774. adapter->logmsg.wepundecryptable);
  775. wrq->u.data.length = strlen(buf) + 1;
  776. if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
  777. lbs_pr_debug(1, "Copy to user failed\n");
  778. return -EFAULT;
  779. }
  780. }
  781. return 0;
  782. }
  783. static int wlan_scan_type_ioctl(wlan_private * priv, struct iwreq *wrq)
  784. {
  785. u8 buf[12];
  786. u8 *option[] = { "active", "passive", "get", };
  787. int i, max_options = (sizeof(option) / sizeof(option[0]));
  788. int ret = 0;
  789. wlan_adapter *adapter = priv->adapter;
  790. if (priv->adapter->enable11d) {
  791. lbs_pr_debug(1, "11D: Cannot set scantype when 11D enabled\n");
  792. return -EFAULT;
  793. }
  794. memset(buf, 0, sizeof(buf));
  795. if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
  796. wrq->u.data.length)))
  797. return -EFAULT;
  798. lbs_pr_debug(1, "Scan type Option = %s\n", buf);
  799. buf[sizeof(buf) - 1] = '\0';
  800. for (i = 0; i < max_options; i++) {
  801. if (!strcmp(buf, option[i]))
  802. break;
  803. }
  804. switch (i) {
  805. case 0:
  806. adapter->scantype = cmd_scan_type_active;
  807. break;
  808. case 1:
  809. adapter->scantype = cmd_scan_type_passive;
  810. break;
  811. case 2:
  812. wrq->u.data.length = strlen(option[adapter->scantype]) + 1;
  813. if (copy_to_user(wrq->u.data.pointer,
  814. option[adapter->scantype],
  815. wrq->u.data.length)) {
  816. lbs_pr_debug(1, "Copy to user failed\n");
  817. ret = -EFAULT;
  818. }
  819. break;
  820. default:
  821. lbs_pr_debug(1, "Invalid Scan type Ioctl Option\n");
  822. ret = -EINVAL;
  823. break;
  824. }
  825. return ret;
  826. }
  827. static int wlan_scan_mode_ioctl(wlan_private * priv, struct iwreq *wrq)
  828. {
  829. wlan_adapter *adapter = priv->adapter;
  830. u8 buf[12];
  831. u8 *option[] = { "bss", "ibss", "any", "get" };
  832. int i, max_options = (sizeof(option) / sizeof(option[0]));
  833. int ret = 0;
  834. ENTER();
  835. memset(buf, 0, sizeof(buf));
  836. if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
  837. wrq->u.data.length))) {
  838. lbs_pr_debug(1, "Copy from user failed\n");
  839. return -EFAULT;
  840. }
  841. lbs_pr_debug(1, "Scan mode Option = %s\n", buf);
  842. buf[sizeof(buf) - 1] = '\0';
  843. for (i = 0; i < max_options; i++) {
  844. if (!strcmp(buf, option[i]))
  845. break;
  846. }
  847. switch (i) {
  848. case 0:
  849. adapter->scanmode = cmd_bss_type_bss;
  850. break;
  851. case 1:
  852. adapter->scanmode = cmd_bss_type_ibss;
  853. break;
  854. case 2:
  855. adapter->scanmode = cmd_bss_type_any;
  856. break;
  857. case 3:
  858. wrq->u.data.length = strlen(option[adapter->scanmode - 1]) + 1;
  859. lbs_pr_debug(1, "Get Scan mode Option = %s\n",
  860. option[adapter->scanmode - 1]);
  861. lbs_pr_debug(1, "Scan mode length %d\n", wrq->u.data.length);
  862. if (copy_to_user(wrq->u.data.pointer,
  863. option[adapter->scanmode - 1],
  864. wrq->u.data.length)) {
  865. lbs_pr_debug(1, "Copy to user failed\n");
  866. ret = -EFAULT;
  867. }
  868. lbs_pr_debug(1, "GET Scan type Option after copy = %s\n",
  869. (char *)wrq->u.data.pointer);
  870. break;
  871. default:
  872. lbs_pr_debug(1, "Invalid Scan mode Ioctl Option\n");
  873. ret = -EINVAL;
  874. break;
  875. }
  876. LEAVE();
  877. return ret;
  878. }
  879. /**
  880. * @brief Get/Set Adhoc G Rate
  881. *
  882. * @param priv A pointer to wlan_private structure
  883. * @param wrq A pointer to user data
  884. * @return 0--success, otherwise fail
  885. */
  886. static int wlan_do_set_grate_ioctl(wlan_private * priv, struct iwreq *wrq)
  887. {
  888. wlan_adapter *adapter = priv->adapter;
  889. int data, data1;
  890. int *val;
  891. ENTER();
  892. data1 = SUBCMD_DATA(wrq);
  893. switch (data1) {
  894. case 0:
  895. adapter->adhoc_grate_enabled = 0;
  896. break;
  897. case 1:
  898. adapter->adhoc_grate_enabled = 1;
  899. break;
  900. case 2:
  901. break;
  902. default:
  903. return -EINVAL;
  904. }
  905. data = adapter->adhoc_grate_enabled;
  906. val = (int *)wrq->u.name;
  907. *val = data;
  908. LEAVE();
  909. return 0;
  910. }
  911. static inline int hex2int(char c)
  912. {
  913. if (c >= '0' && c <= '9')
  914. return (c - '0');
  915. if (c >= 'a' && c <= 'f')
  916. return (c - 'a' + 10);
  917. if (c >= 'A' && c <= 'F')
  918. return (c - 'A' + 10);
  919. return -1;
  920. }
  921. /* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
  922. into binary format (6 bytes).
  923. This function expects that each byte is represented with 2 characters
  924. (e.g., 11:2:11:11:11:11 is invalid)
  925. */
  926. static char *eth_str2addr(char *ethstr, u8 * addr)
  927. {
  928. int i, val, val2;
  929. char *pos = ethstr;
  930. /* get rid of initial blanks */
  931. while (*pos == ' ' || *pos == '\t')
  932. ++pos;
  933. for (i = 0; i < 6; i++) {
  934. val = hex2int(*pos++);
  935. if (val < 0)
  936. return NULL;
  937. val2 = hex2int(*pos++);
  938. if (val2 < 0)
  939. return NULL;
  940. addr[i] = (val * 16 + val2) & 0xff;
  941. if (i < 5 && *pos++ != ':')
  942. return NULL;
  943. }
  944. return pos;
  945. }
  946. /* this writes xx:xx:xx:xx:xx:xx into ethstr
  947. (ethstr must have space for 18 chars) */
  948. static int eth_addr2str(u8 * addr, char *ethstr)
  949. {
  950. int i;
  951. char *pos = ethstr;
  952. for (i = 0; i < 6; i++) {
  953. sprintf(pos, "%02x", addr[i] & 0xff);
  954. pos += 2;
  955. if (i < 5)
  956. *pos++ = ':';
  957. }
  958. return 17;
  959. }
  960. /**
  961. * @brief Add an entry to the BT table
  962. * @param priv A pointer to wlan_private structure
  963. * @param req A pointer to ifreq structure
  964. * @return 0 --success, otherwise fail
  965. */
  966. static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
  967. {
  968. struct iwreq *wrq = (struct iwreq *)req;
  969. char ethaddrs_str[18];
  970. char *pos;
  971. u8 ethaddr[ETH_ALEN];
  972. ENTER();
  973. if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
  974. sizeof(ethaddrs_str)))
  975. return -EFAULT;
  976. if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
  977. lbs_pr_info("BT_ADD: Invalid MAC address\n");
  978. return -EINVAL;
  979. }
  980. lbs_pr_debug(1, "BT: adding %s\n", ethaddrs_str);
  981. LEAVE();
  982. return (libertas_prepare_and_send_command(priv, cmd_bt_access,
  983. cmd_act_bt_access_add,
  984. cmd_option_waitforrsp, 0, ethaddr));
  985. }
  986. /**
  987. * @brief Delete an entry from the BT table
  988. * @param priv A pointer to wlan_private structure
  989. * @param req A pointer to ifreq structure
  990. * @return 0 --success, otherwise fail
  991. */
  992. static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
  993. {
  994. struct iwreq *wrq = (struct iwreq *)req;
  995. char ethaddrs_str[18];
  996. u8 ethaddr[ETH_ALEN];
  997. char *pos;
  998. ENTER();
  999. if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
  1000. sizeof(ethaddrs_str)))
  1001. return -EFAULT;
  1002. if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
  1003. lbs_pr_info("Invalid MAC address\n");
  1004. return -EINVAL;
  1005. }
  1006. lbs_pr_debug(1, "BT: deleting %s\n", ethaddrs_str);
  1007. return (libertas_prepare_and_send_command(priv,
  1008. cmd_bt_access,
  1009. cmd_act_bt_access_del,
  1010. cmd_option_waitforrsp, 0, ethaddr));
  1011. LEAVE();
  1012. return 0;
  1013. }
  1014. /**
  1015. * @brief Reset all entries from the BT table
  1016. * @param priv A pointer to wlan_private structure
  1017. * @return 0 --success, otherwise fail
  1018. */
  1019. static int wlan_bt_reset_ioctl(wlan_private * priv)
  1020. {
  1021. ENTER();
  1022. lbs_pr_alert( "BT: resetting\n");
  1023. return (libertas_prepare_and_send_command(priv,
  1024. cmd_bt_access,
  1025. cmd_act_bt_access_reset,
  1026. cmd_option_waitforrsp, 0, NULL));
  1027. LEAVE();
  1028. return 0;
  1029. }
  1030. /**
  1031. * @brief List an entry from the BT table
  1032. * @param priv A pointer to wlan_private structure
  1033. * @param req A pointer to ifreq structure
  1034. * @return 0 --success, otherwise fail
  1035. */
  1036. static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
  1037. {
  1038. int pos;
  1039. char *addr1;
  1040. struct iwreq *wrq = (struct iwreq *)req;
  1041. /* used to pass id and store the bt entry returned by the FW */
  1042. union {
  1043. int id;
  1044. char addr1addr2[2 * ETH_ALEN];
  1045. } param;
  1046. static char outstr[64];
  1047. char *pbuf = outstr;
  1048. int ret;
  1049. ENTER();
  1050. if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
  1051. lbs_pr_debug(1, "Copy from user failed\n");
  1052. return -1;
  1053. }
  1054. param.id = simple_strtoul(outstr, NULL, 10);
  1055. pos = sprintf(pbuf, "%d: ", param.id);
  1056. pbuf += pos;
  1057. ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
  1058. cmd_act_bt_access_list,
  1059. cmd_option_waitforrsp, 0,
  1060. (char *)&param);
  1061. if (ret == 0) {
  1062. addr1 = param.addr1addr2;
  1063. pos = sprintf(pbuf, "ignoring traffic from ");
  1064. pbuf += pos;
  1065. pos = eth_addr2str(addr1, pbuf);
  1066. pbuf += pos;
  1067. } else {
  1068. sprintf(pbuf, "(null)");
  1069. pbuf += pos;
  1070. }
  1071. wrq->u.data.length = strlen(outstr);
  1072. if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
  1073. wrq->u.data.length)) {
  1074. lbs_pr_debug(1, "BT_LIST: Copy to user failed!\n");
  1075. return -EFAULT;
  1076. }
  1077. LEAVE();
  1078. return 0;
  1079. }
  1080. /**
  1081. * @brief Find the next parameter in an input string
  1082. * @param ptr A pointer to the input parameter string
  1083. * @return A pointer to the next parameter, or 0 if no parameters left.
  1084. */
  1085. static char * next_param(char * ptr)
  1086. {
  1087. if (!ptr) return NULL;
  1088. while (*ptr == ' ' || *ptr == '\t') ++ptr;
  1089. return (*ptr == '\0') ? NULL : ptr;
  1090. }
  1091. /**
  1092. * @brief Add an entry to the FWT table
  1093. * @param priv A pointer to wlan_private structure
  1094. * @param req A pointer to ifreq structure
  1095. * @return 0 --success, otherwise fail
  1096. */
  1097. static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
  1098. {
  1099. struct iwreq *wrq = (struct iwreq *)req;
  1100. char in_str[128];
  1101. static struct cmd_ds_fwt_access fwt_access;
  1102. char *ptr;
  1103. ENTER();
  1104. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1105. return -EFAULT;
  1106. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  1107. lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
  1108. return -EINVAL;
  1109. }
  1110. if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
  1111. lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
  1112. return -EINVAL;
  1113. }
  1114. if ((ptr = next_param(ptr)))
  1115. fwt_access.metric =
  1116. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1117. else
  1118. fwt_access.metric = FWT_DEFAULT_METRIC;
  1119. if ((ptr = next_param(ptr)))
  1120. fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
  1121. else
  1122. fwt_access.dir = FWT_DEFAULT_DIR;
  1123. if ((ptr = next_param(ptr)))
  1124. fwt_access.ssn =
  1125. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1126. else
  1127. fwt_access.ssn = FWT_DEFAULT_SSN;
  1128. if ((ptr = next_param(ptr)))
  1129. fwt_access.dsn =
  1130. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1131. else
  1132. fwt_access.dsn = FWT_DEFAULT_DSN;
  1133. if ((ptr = next_param(ptr)))
  1134. fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
  1135. else
  1136. fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
  1137. if ((ptr = next_param(ptr)))
  1138. fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
  1139. else
  1140. fwt_access.ttl = FWT_DEFAULT_TTL;
  1141. if ((ptr = next_param(ptr)))
  1142. fwt_access.expiration =
  1143. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1144. else
  1145. fwt_access.expiration = FWT_DEFAULT_EXPIRATION;
  1146. if ((ptr = next_param(ptr)))
  1147. fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
  1148. else
  1149. fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
  1150. if ((ptr = next_param(ptr)))
  1151. fwt_access.snr =
  1152. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1153. else
  1154. fwt_access.snr = FWT_DEFAULT_SNR;
  1155. #ifdef DEBUG
  1156. {
  1157. char ethaddr1_str[18], ethaddr2_str[18];
  1158. eth_addr2str(fwt_access.da, ethaddr1_str);
  1159. eth_addr2str(fwt_access.ra, ethaddr2_str);
  1160. lbs_pr_debug(1, "FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
  1161. fwt_access.dir, ethaddr2_str);
  1162. lbs_pr_debug(1, "FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
  1163. fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
  1164. fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
  1165. fwt_access.sleepmode, fwt_access.snr);
  1166. }
  1167. #endif
  1168. LEAVE();
  1169. return (libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1170. cmd_act_fwt_access_add,
  1171. cmd_option_waitforrsp, 0,
  1172. (void *)&fwt_access));
  1173. }
  1174. /**
  1175. * @brief Delete an entry from the FWT table
  1176. * @param priv A pointer to wlan_private structure
  1177. * @param req A pointer to ifreq structure
  1178. * @return 0 --success, otherwise fail
  1179. */
  1180. static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
  1181. {
  1182. struct iwreq *wrq = (struct iwreq *)req;
  1183. char in_str[64];
  1184. static struct cmd_ds_fwt_access fwt_access;
  1185. char *ptr;
  1186. ENTER();
  1187. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1188. return -EFAULT;
  1189. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  1190. lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
  1191. return -EINVAL;
  1192. }
  1193. if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
  1194. lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
  1195. return -EINVAL;
  1196. }
  1197. if ((ptr = next_param(ptr)))
  1198. fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
  1199. else
  1200. fwt_access.dir = FWT_DEFAULT_DIR;
  1201. #ifdef DEBUG
  1202. {
  1203. char ethaddr1_str[18], ethaddr2_str[18];
  1204. lbs_pr_debug(1, "FWT_DEL: line is %s\n", in_str);
  1205. eth_addr2str(fwt_access.da, ethaddr1_str);
  1206. eth_addr2str(fwt_access.ra, ethaddr2_str);
  1207. lbs_pr_debug(1, "FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
  1208. ethaddr2_str, fwt_access.dir);
  1209. }
  1210. #endif
  1211. LEAVE();
  1212. return (libertas_prepare_and_send_command(priv,
  1213. cmd_fwt_access,
  1214. cmd_act_fwt_access_del,
  1215. cmd_option_waitforrsp, 0,
  1216. (void *)&fwt_access));
  1217. }
  1218. /**
  1219. * @brief Print route parameters
  1220. * @param fwt_access struct cmd_ds_fwt_access with route info
  1221. * @param buf destination buffer for route info
  1222. */
  1223. static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
  1224. {
  1225. buf += sprintf(buf, " ");
  1226. buf += eth_addr2str(fwt_access.da, buf);
  1227. buf += sprintf(buf, " ");
  1228. buf += eth_addr2str(fwt_access.ra, buf);
  1229. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
  1230. buf += sprintf(buf, " %u", fwt_access.dir);
  1231. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
  1232. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
  1233. buf += sprintf(buf, " %u", fwt_access.hopcount);
  1234. buf += sprintf(buf, " %u", fwt_access.ttl);
  1235. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
  1236. buf += sprintf(buf, " %u", fwt_access.sleepmode);
  1237. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.snr));
  1238. }
  1239. /**
  1240. * @brief Lookup an entry in the FWT table
  1241. * @param priv A pointer to wlan_private structure
  1242. * @param req A pointer to ifreq structure
  1243. * @return 0 --success, otherwise fail
  1244. */
  1245. static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
  1246. {
  1247. struct iwreq *wrq = (struct iwreq *)req;
  1248. char in_str[64];
  1249. char *ptr;
  1250. static struct cmd_ds_fwt_access fwt_access;
  1251. static char out_str[128];
  1252. int ret;
  1253. ENTER();
  1254. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1255. return -EFAULT;
  1256. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  1257. lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
  1258. return -EINVAL;
  1259. }
  1260. #ifdef DEBUG
  1261. {
  1262. char ethaddr1_str[18];
  1263. lbs_pr_debug(1, "FWT_LOOKUP: line is %s\n", in_str);
  1264. eth_addr2str(fwt_access.da, ethaddr1_str);
  1265. lbs_pr_debug(1, "FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
  1266. }
  1267. #endif
  1268. ret = libertas_prepare_and_send_command(priv,
  1269. cmd_fwt_access,
  1270. cmd_act_fwt_access_lookup,
  1271. cmd_option_waitforrsp, 0,
  1272. (void *)&fwt_access);
  1273. if (ret == 0)
  1274. print_route(fwt_access, out_str);
  1275. else
  1276. sprintf(out_str, "(null)");
  1277. wrq->u.data.length = strlen(out_str);
  1278. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  1279. wrq->u.data.length)) {
  1280. lbs_pr_debug(1, "FWT_LOOKUP: Copy to user failed!\n");
  1281. return -EFAULT;
  1282. }
  1283. LEAVE();
  1284. return 0;
  1285. }
  1286. /**
  1287. * @brief Reset all entries from the FWT table
  1288. * @param priv A pointer to wlan_private structure
  1289. * @return 0 --success, otherwise fail
  1290. */
  1291. static int wlan_fwt_reset_ioctl(wlan_private * priv)
  1292. {
  1293. lbs_pr_debug(1, "FWT: resetting\n");
  1294. return (libertas_prepare_and_send_command(priv,
  1295. cmd_fwt_access,
  1296. cmd_act_fwt_access_reset,
  1297. cmd_option_waitforrsp, 0, NULL));
  1298. }
  1299. /**
  1300. * @brief List an entry from the FWT table
  1301. * @param priv A pointer to wlan_private structure
  1302. * @param req A pointer to ifreq structure
  1303. * @return 0 --success, otherwise fail
  1304. */
  1305. static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
  1306. {
  1307. struct iwreq *wrq = (struct iwreq *)req;
  1308. char in_str[8];
  1309. static struct cmd_ds_fwt_access fwt_access;
  1310. char *ptr = in_str;
  1311. static char out_str[128];
  1312. char *pbuf = out_str;
  1313. int ret;
  1314. ENTER();
  1315. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1316. return -EFAULT;
  1317. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1318. #ifdef DEBUG
  1319. {
  1320. lbs_pr_debug(1, "FWT_LIST: line is %s\n", in_str);
  1321. lbs_pr_debug(1, "FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
  1322. }
  1323. #endif
  1324. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1325. cmd_act_fwt_access_list,
  1326. cmd_option_waitforrsp, 0, (void *)&fwt_access);
  1327. if (ret == 0)
  1328. print_route(fwt_access, pbuf);
  1329. else
  1330. pbuf += sprintf(pbuf, " (null)");
  1331. wrq->u.data.length = strlen(out_str);
  1332. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  1333. wrq->u.data.length)) {
  1334. lbs_pr_debug(1, "FWT_LIST: Copy to user failed!\n");
  1335. return -EFAULT;
  1336. }
  1337. LEAVE();
  1338. return 0;
  1339. }
  1340. /**
  1341. * @brief List an entry from the FRT table
  1342. * @param priv A pointer to wlan_private structure
  1343. * @param req A pointer to ifreq structure
  1344. * @return 0 --success, otherwise fail
  1345. */
  1346. static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
  1347. {
  1348. struct iwreq *wrq = (struct iwreq *)req;
  1349. char in_str[64];
  1350. static struct cmd_ds_fwt_access fwt_access;
  1351. char *ptr = in_str;
  1352. static char out_str[128];
  1353. char *pbuf = out_str;
  1354. int ret;
  1355. ENTER();
  1356. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1357. return -EFAULT;
  1358. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1359. #ifdef DEBUG
  1360. {
  1361. lbs_pr_debug(1, "FWT_LIST_ROUTE: line is %s\n", in_str);
  1362. lbs_pr_debug(1, "FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
  1363. }
  1364. #endif
  1365. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1366. cmd_act_fwt_access_list_route,
  1367. cmd_option_waitforrsp, 0, (void *)&fwt_access);
  1368. if (ret == 0) {
  1369. pbuf += sprintf(pbuf, " ");
  1370. pbuf += eth_addr2str(fwt_access.da, pbuf);
  1371. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.metric));
  1372. pbuf += sprintf(pbuf, " %u", fwt_access.dir);
  1373. /* note that the firmware returns the nid in the id field */
  1374. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.id));
  1375. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.ssn));
  1376. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.dsn));
  1377. pbuf += sprintf(pbuf, " hop %u", fwt_access.hopcount);
  1378. pbuf += sprintf(pbuf, " ttl %u", fwt_access.ttl);
  1379. pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.expiration));
  1380. } else
  1381. pbuf += sprintf(pbuf, " (null)");
  1382. wrq->u.data.length = strlen(out_str);
  1383. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  1384. wrq->u.data.length)) {
  1385. lbs_pr_debug(1, "FWT_LIST_ROUTE: Copy to user failed!\n");
  1386. return -EFAULT;
  1387. }
  1388. LEAVE();
  1389. return 0;
  1390. }
  1391. /**
  1392. * @brief List an entry from the FNT table
  1393. * @param priv A pointer to wlan_private structure
  1394. * @param req A pointer to ifreq structure
  1395. * @return 0 --success, otherwise fail
  1396. */
  1397. static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
  1398. {
  1399. struct iwreq *wrq = (struct iwreq *)req;
  1400. char in_str[8];
  1401. static struct cmd_ds_fwt_access fwt_access;
  1402. char *ptr = in_str;
  1403. static char out_str[128];
  1404. char *pbuf = out_str;
  1405. int ret;
  1406. ENTER();
  1407. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  1408. return -EFAULT;
  1409. memset(&fwt_access, 0, sizeof(fwt_access));
  1410. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  1411. #ifdef DEBUG
  1412. {
  1413. lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: line is %s\n", in_str);
  1414. lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
  1415. }
  1416. #endif
  1417. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1418. cmd_act_fwt_access_list_neighbor,
  1419. cmd_option_waitforrsp, 0,
  1420. (void *)&fwt_access);
  1421. if (ret == 0) {
  1422. pbuf += sprintf(pbuf, " ra ");
  1423. pbuf += eth_addr2str(fwt_access.ra, pbuf);
  1424. pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode);
  1425. pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr));
  1426. pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references));
  1427. } else
  1428. pbuf += sprintf(pbuf, " (null)");
  1429. wrq->u.data.length = strlen(out_str);
  1430. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  1431. wrq->u.data.length)) {
  1432. lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: Copy to user failed!\n");
  1433. return -EFAULT;
  1434. }
  1435. LEAVE();
  1436. return 0;
  1437. }
  1438. /**
  1439. * @brief Cleans up the route (FRT) and neighbor (FNT) tables
  1440. * (Garbage Collection)
  1441. * @param priv A pointer to wlan_private structure
  1442. * @param req A pointer to ifreq structure
  1443. * @return 0 --success, otherwise fail
  1444. */
  1445. static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
  1446. {
  1447. static struct cmd_ds_fwt_access fwt_access;
  1448. int ret;
  1449. ENTER();
  1450. lbs_pr_debug(1, "FWT: cleaning up\n");
  1451. memset(&fwt_access, 0, sizeof(fwt_access));
  1452. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1453. cmd_act_fwt_access_cleanup,
  1454. cmd_option_waitforrsp, 0,
  1455. (void *)&fwt_access);
  1456. if (ret == 0)
  1457. req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
  1458. else
  1459. return -EFAULT;
  1460. LEAVE();
  1461. return 0;
  1462. }
  1463. /**
  1464. * @brief Gets firmware internal time (debug purposes)
  1465. * @param priv A pointer to wlan_private structure
  1466. * @param req A pointer to ifreq structure
  1467. * @return 0 --success, otherwise fail
  1468. */
  1469. static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
  1470. {
  1471. static struct cmd_ds_fwt_access fwt_access;
  1472. int ret;
  1473. ENTER();
  1474. lbs_pr_debug(1, "FWT: getting time\n");
  1475. memset(&fwt_access, 0, sizeof(fwt_access));
  1476. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  1477. cmd_act_fwt_access_time,
  1478. cmd_option_waitforrsp, 0,
  1479. (void *)&fwt_access);
  1480. if (ret == 0)
  1481. req->ifr_data = (char *)(le32_to_cpu(fwt_access.references));
  1482. else
  1483. return -EFAULT;
  1484. LEAVE();
  1485. return 0;
  1486. }
  1487. /**
  1488. * @brief Gets mesh ttl from firmware
  1489. * @param priv A pointer to wlan_private structure
  1490. * @param req A pointer to ifreq structure
  1491. * @return 0 --success, otherwise fail
  1492. */
  1493. static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
  1494. {
  1495. struct cmd_ds_mesh_access mesh_access;
  1496. int ret;
  1497. ENTER();
  1498. memset(&mesh_access, 0, sizeof(mesh_access));
  1499. ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
  1500. cmd_act_mesh_get_ttl,
  1501. cmd_option_waitforrsp, 0,
  1502. (void *)&mesh_access);
  1503. if (ret == 0) {
  1504. req->ifr_data = (char *)(le32_to_cpu(mesh_access.data[0]));
  1505. }
  1506. else
  1507. return -EFAULT;
  1508. LEAVE();
  1509. return 0;
  1510. }
  1511. /**
  1512. * @brief Gets mesh ttl from firmware
  1513. * @param priv A pointer to wlan_private structure
  1514. * @param ttl New ttl value
  1515. * @return 0 --success, otherwise fail
  1516. */
  1517. static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
  1518. {
  1519. struct cmd_ds_mesh_access mesh_access;
  1520. int ret;
  1521. ENTER();
  1522. if( (ttl > 0xff) || (ttl < 0) )
  1523. return -EINVAL;
  1524. memset(&mesh_access, 0, sizeof(mesh_access));
  1525. mesh_access.data[0] = ttl;
  1526. ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
  1527. cmd_act_mesh_set_ttl,
  1528. cmd_option_waitforrsp, 0,
  1529. (void *)&mesh_access);
  1530. if (ret != 0)
  1531. ret = -EFAULT;
  1532. LEAVE();
  1533. return ret;
  1534. }
  1535. /**
  1536. * @brief ioctl function - entry point
  1537. *
  1538. * @param dev A pointer to net_device structure
  1539. * @param req A pointer to ifreq structure
  1540. * @param cmd command
  1541. * @return 0--success, otherwise fail
  1542. */
  1543. int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
  1544. {
  1545. int subcmd = 0;
  1546. int idata = 0;
  1547. int *pdata;
  1548. int ret = 0;
  1549. wlan_private *priv = dev->priv;
  1550. wlan_adapter *adapter = priv->adapter;
  1551. struct iwreq *wrq = (struct iwreq *)req;
  1552. ENTER();
  1553. lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
  1554. switch (cmd) {
  1555. case WLANSCAN_TYPE:
  1556. lbs_pr_debug(1, "Scan type Ioctl\n");
  1557. ret = wlan_scan_type_ioctl(priv, wrq);
  1558. break;
  1559. case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */
  1560. switch (wrq->u.data.flags) {
  1561. case WLANDEAUTH:
  1562. lbs_pr_debug(1, "Deauth\n");
  1563. libertas_send_deauth(priv);
  1564. break;
  1565. case WLANADHOCSTOP:
  1566. lbs_pr_debug(1, "Adhoc stop\n");
  1567. ret = libertas_do_adhocstop_ioctl(priv);
  1568. break;
  1569. case WLANRADIOON:
  1570. wlan_radio_ioctl(priv, 1);
  1571. break;
  1572. case WLANRADIOOFF:
  1573. wlan_radio_ioctl(priv, 0);
  1574. break;
  1575. case WLANWLANIDLEON:
  1576. libertas_idle_on(priv);
  1577. break;
  1578. case WLANWLANIDLEOFF:
  1579. libertas_idle_off(priv);
  1580. break;
  1581. case WLAN_SUBCMD_BT_RESET: /* bt_reset */
  1582. wlan_bt_reset_ioctl(priv);
  1583. break;
  1584. case WLAN_SUBCMD_FWT_RESET: /* fwt_reset */
  1585. wlan_fwt_reset_ioctl(priv);
  1586. break;
  1587. } /* End of switch */
  1588. break;
  1589. case WLANSETWPAIE:
  1590. ret = wlan_setwpaie_ioctl(priv, req);
  1591. break;
  1592. case WLAN_SETINT_GETINT:
  1593. /* The first 4 bytes of req->ifr_data is sub-ioctl number
  1594. * after 4 bytes sits the payload.
  1595. */
  1596. subcmd = (int)req->ifr_data; //from iwpriv subcmd
  1597. switch (subcmd) {
  1598. case WLANNF:
  1599. ret = wlan_get_nf(priv, wrq);
  1600. break;
  1601. case WLANRSSI:
  1602. ret = wlan_get_rssi(priv, wrq);
  1603. break;
  1604. case WLANENABLE11D:
  1605. ret = libertas_cmd_enable_11d(priv, wrq);
  1606. break;
  1607. case WLANADHOCGRATE:
  1608. ret = wlan_do_set_grate_ioctl(priv, wrq);
  1609. break;
  1610. case WLAN_SUBCMD_SET_PRESCAN:
  1611. ret = wlan_subcmd_setprescan_ioctl(priv, wrq);
  1612. break;
  1613. }
  1614. break;
  1615. case WLAN_SETONEINT_GETONEINT:
  1616. switch (wrq->u.data.flags) {
  1617. case WLAN_BEACON_INTERVAL:
  1618. ret = wlan_beacon_interval(priv, wrq);
  1619. break;
  1620. case WLAN_LISTENINTRVL:
  1621. if (!wrq->u.data.length) {
  1622. int data;
  1623. lbs_pr_debug(1, "Get locallisteninterval value\n");
  1624. #define GET_ONE_INT 1
  1625. data = adapter->locallisteninterval;
  1626. if (copy_to_user(wrq->u.data.pointer,
  1627. &data, sizeof(int))) {
  1628. lbs_pr_debug(1, "Copy to user failed\n");
  1629. return -EFAULT;
  1630. }
  1631. wrq->u.data.length = GET_ONE_INT;
  1632. } else {
  1633. int data;
  1634. if (copy_from_user
  1635. (&data, wrq->u.data.pointer, sizeof(int))) {
  1636. lbs_pr_debug(1, "Copy from user failed\n");
  1637. return -EFAULT;
  1638. }
  1639. lbs_pr_debug(1, "Set locallisteninterval = %d\n",
  1640. data);
  1641. #define MAX_U16_VAL 65535
  1642. if (data > MAX_U16_VAL) {
  1643. lbs_pr_debug(1, "Exceeds U16 value\n");
  1644. return -EINVAL;
  1645. }
  1646. adapter->locallisteninterval = data;
  1647. }
  1648. break;
  1649. case WLAN_TXCONTROL:
  1650. ret = wlan_txcontrol(priv, wrq); //adds for txcontrol ioctl
  1651. break;
  1652. case WLAN_NULLPKTINTERVAL:
  1653. ret = wlan_null_pkt_interval(priv, wrq);
  1654. break;
  1655. default:
  1656. ret = -EOPNOTSUPP;
  1657. break;
  1658. }
  1659. break;
  1660. case WLAN_SETONEINT_GETNONE:
  1661. /* The first 4 bytes of req->ifr_data is sub-ioctl number
  1662. * after 4 bytes sits the payload.
  1663. */
  1664. subcmd = wrq->u.data.flags; //from wpa_supplicant subcmd
  1665. if (!subcmd)
  1666. subcmd = (int)req->ifr_data; //from iwpriv subcmd
  1667. switch (subcmd) {
  1668. case WLAN_SUBCMD_SETRXANTENNA: /* SETRXANTENNA */
  1669. idata = SUBCMD_DATA(wrq);
  1670. ret = setrxantenna(priv, idata);
  1671. break;
  1672. case WLAN_SUBCMD_SETTXANTENNA: /* SETTXANTENNA */
  1673. idata = SUBCMD_DATA(wrq);
  1674. ret = settxantenna(priv, idata);
  1675. break;
  1676. case WLAN_SET_ATIM_WINDOW:
  1677. adapter->atimwindow = SUBCMD_DATA(wrq);
  1678. adapter->atimwindow = min_t(__u16, adapter->atimwindow, 50);
  1679. break;
  1680. case WLANSETBCNAVG:
  1681. adapter->bcn_avg_factor = SUBCMD_DATA(wrq);
  1682. if (adapter->bcn_avg_factor == 0)
  1683. adapter->bcn_avg_factor =
  1684. DEFAULT_BCN_AVG_FACTOR;
  1685. if (adapter->bcn_avg_factor > DEFAULT_BCN_AVG_FACTOR)
  1686. adapter->bcn_avg_factor =
  1687. DEFAULT_BCN_AVG_FACTOR;
  1688. break;
  1689. case WLANSETDATAAVG:
  1690. adapter->data_avg_factor = SUBCMD_DATA(wrq);
  1691. if (adapter->data_avg_factor == 0)
  1692. adapter->data_avg_factor =
  1693. DEFAULT_DATA_AVG_FACTOR;
  1694. if (adapter->data_avg_factor > DEFAULT_DATA_AVG_FACTOR)
  1695. adapter->data_avg_factor =
  1696. DEFAULT_DATA_AVG_FACTOR;
  1697. break;
  1698. case WLANSETREGION:
  1699. idata = SUBCMD_DATA(wrq);
  1700. ret = wlan_set_region(priv, (u16) idata);
  1701. break;
  1702. case WLAN_SET_LISTEN_INTERVAL:
  1703. idata = SUBCMD_DATA(wrq);
  1704. adapter->listeninterval = (u16) idata;
  1705. break;
  1706. case WLAN_SET_MULTIPLE_DTIM:
  1707. ret = wlan_set_multiple_dtim_ioctl(priv, req);
  1708. break;
  1709. case WLANSETENCRYPTIONMODE:
  1710. ret = wlan_setencryptionmode_ioctl(priv, req);
  1711. break;
  1712. case WLAN_SET_LINKMODE:
  1713. ret = wlan_set_linkmode_ioctl(priv, req);
  1714. break;
  1715. case WLAN_SET_RADIOMODE:
  1716. ret = wlan_set_radiomode_ioctl(priv, req);
  1717. break;
  1718. case WLAN_SET_DEBUGMODE:
  1719. ret = wlan_set_debugmode_ioctl(priv, req);
  1720. break;
  1721. case WLAN_SUBCMD_MESH_SET_TTL:
  1722. idata = SUBCMD_DATA(wrq);
  1723. ret = wlan_mesh_set_ttl_ioctl(priv, idata);
  1724. break;
  1725. default:
  1726. ret = -EOPNOTSUPP;
  1727. break;
  1728. }
  1729. break;
  1730. case WLAN_SETNONE_GETTWELVE_CHAR: /* Get Antenna settings */
  1731. /*
  1732. * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is
  1733. * in flags of iwreq structure, otherwise it will be in
  1734. * mode member of iwreq structure.
  1735. */
  1736. switch ((int)wrq->u.data.flags) {
  1737. case WLAN_SUBCMD_GETRXANTENNA: /* Get Rx Antenna */
  1738. ret = wlan_subcmd_getrxantenna_ioctl(priv, req);
  1739. break;
  1740. case WLAN_SUBCMD_GETTXANTENNA: /* Get Tx Antenna */
  1741. ret = wlan_subcmd_gettxantenna_ioctl(priv, req);
  1742. break;
  1743. case WLAN_GET_TSF:
  1744. ret = wlan_get_tsf_ioctl(priv, wrq);
  1745. break;
  1746. }
  1747. break;
  1748. case WLAN_SET128CHAR_GET128CHAR:
  1749. switch ((int)wrq->u.data.flags) {
  1750. case WLANSCAN_MODE:
  1751. lbs_pr_debug(1, "Scan mode Ioctl\n");
  1752. ret = wlan_scan_mode_ioctl(priv, wrq);
  1753. break;
  1754. case WLAN_GET_ADHOC_STATUS:
  1755. ret = wlan_get_adhoc_status_ioctl(priv, wrq);
  1756. break;
  1757. case WLAN_SUBCMD_BT_ADD:
  1758. ret = wlan_bt_add_ioctl(priv, req);
  1759. break;
  1760. case WLAN_SUBCMD_BT_DEL:
  1761. ret = wlan_bt_del_ioctl(priv, req);
  1762. break;
  1763. case WLAN_SUBCMD_BT_LIST:
  1764. ret = wlan_bt_list_ioctl(priv, req);
  1765. break;
  1766. case WLAN_SUBCMD_FWT_ADD:
  1767. ret = wlan_fwt_add_ioctl(priv, req);
  1768. break;
  1769. case WLAN_SUBCMD_FWT_DEL:
  1770. ret = wlan_fwt_del_ioctl(priv, req);
  1771. break;
  1772. case WLAN_SUBCMD_FWT_LOOKUP:
  1773. ret = wlan_fwt_lookup_ioctl(priv, req);
  1774. break;
  1775. case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
  1776. ret = wlan_fwt_list_neighbor_ioctl(priv, req);
  1777. break;
  1778. case WLAN_SUBCMD_FWT_LIST:
  1779. ret = wlan_fwt_list_ioctl(priv, req);
  1780. break;
  1781. case WLAN_SUBCMD_FWT_LIST_ROUTE:
  1782. ret = wlan_fwt_list_route_ioctl(priv, req);
  1783. break;
  1784. }
  1785. break;
  1786. case WLAN_SETNONE_GETONEINT:
  1787. switch ((int)req->ifr_data) {
  1788. case WLANGETBCNAVG:
  1789. pdata = (int *)wrq->u.name;
  1790. *pdata = (int)adapter->bcn_avg_factor;
  1791. break;
  1792. case WLANGETREGION:
  1793. pdata = (int *)wrq->u.name;
  1794. *pdata = (int)adapter->regioncode;
  1795. break;
  1796. case WLAN_GET_LISTEN_INTERVAL:
  1797. pdata = (int *)wrq->u.name;
  1798. *pdata = (int)adapter->listeninterval;
  1799. break;
  1800. case WLAN_GET_LINKMODE:
  1801. req->ifr_data = (char *)((u32) adapter->linkmode);
  1802. break;
  1803. case WLAN_GET_RADIOMODE:
  1804. req->ifr_data = (char *)((u32) adapter->radiomode);
  1805. break;
  1806. case WLAN_GET_DEBUGMODE:
  1807. req->ifr_data = (char *)((u32) adapter->debugmode);
  1808. break;
  1809. case WLAN_GET_MULTIPLE_DTIM:
  1810. pdata = (int *)wrq->u.name;
  1811. *pdata = (int)adapter->multipledtim;
  1812. break;
  1813. case WLAN_GET_TX_RATE:
  1814. ret = wlan_get_txrate_ioctl(priv, req);
  1815. break;
  1816. case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */
  1817. ret = wlan_fwt_cleanup_ioctl(priv, req);
  1818. break;
  1819. case WLAN_SUBCMD_FWT_TIME: /* fwt_time */
  1820. ret = wlan_fwt_time_ioctl(priv, req);
  1821. break;
  1822. case WLAN_SUBCMD_MESH_GET_TTL:
  1823. ret = wlan_mesh_get_ttl_ioctl(priv, req);
  1824. break;
  1825. default:
  1826. ret = -EOPNOTSUPP;
  1827. }
  1828. break;
  1829. case WLANGETLOG:
  1830. ret = wlan_do_getlog_ioctl(priv, wrq);
  1831. break;
  1832. case WLAN_SET_GET_SIXTEEN_INT:
  1833. switch ((int)wrq->u.data.flags) {
  1834. case WLAN_TPCCFG:
  1835. {
  1836. int data[5];
  1837. struct cmd_ds_802_11_tpc_cfg cfg;
  1838. memset(&cfg, 0, sizeof(cfg));
  1839. if ((wrq->u.data.length > 1)
  1840. && (wrq->u.data.length != 5))
  1841. return -1;
  1842. if (wrq->u.data.length == 0) {
  1843. cfg.action =
  1844. cpu_to_le16
  1845. (cmd_act_get);
  1846. } else {
  1847. if (copy_from_user
  1848. (data, wrq->u.data.pointer,
  1849. sizeof(int) * 5)) {
  1850. lbs_pr_debug(1,
  1851. "Copy from user failed\n");
  1852. return -EFAULT;
  1853. }
  1854. cfg.action =
  1855. cpu_to_le16
  1856. (cmd_act_set);
  1857. cfg.enable = data[0];
  1858. cfg.usesnr = data[1];
  1859. cfg.P0 = data[2];
  1860. cfg.P1 = data[3];
  1861. cfg.P2 = data[4];
  1862. }
  1863. ret =
  1864. libertas_prepare_and_send_command(priv,
  1865. cmd_802_11_tpc_cfg,
  1866. 0,
  1867. cmd_option_waitforrsp,
  1868. 0, (void *)&cfg);
  1869. data[0] = cfg.enable;
  1870. data[1] = cfg.usesnr;
  1871. data[2] = cfg.P0;
  1872. data[3] = cfg.P1;
  1873. data[4] = cfg.P2;
  1874. if (copy_to_user
  1875. (wrq->u.data.pointer, data,
  1876. sizeof(int) * 5)) {
  1877. lbs_pr_debug(1, "Copy to user failed\n");
  1878. return -EFAULT;
  1879. }
  1880. wrq->u.data.length = 5;
  1881. }
  1882. break;
  1883. case WLAN_POWERCFG:
  1884. {
  1885. int data[4];
  1886. struct cmd_ds_802_11_pwr_cfg cfg;
  1887. memset(&cfg, 0, sizeof(cfg));
  1888. if ((wrq->u.data.length > 1)
  1889. && (wrq->u.data.length != 4))
  1890. return -1;
  1891. if (wrq->u.data.length == 0) {
  1892. cfg.action =
  1893. cpu_to_le16
  1894. (cmd_act_get);
  1895. } else {
  1896. if (copy_from_user
  1897. (data, wrq->u.data.pointer,
  1898. sizeof(int) * 4)) {
  1899. lbs_pr_debug(1,
  1900. "Copy from user failed\n");
  1901. return -EFAULT;
  1902. }
  1903. cfg.action =
  1904. cpu_to_le16
  1905. (cmd_act_set);
  1906. cfg.enable = data[0];
  1907. cfg.PA_P0 = data[1];
  1908. cfg.PA_P1 = data[2];
  1909. cfg.PA_P2 = data[3];
  1910. }
  1911. ret =
  1912. libertas_prepare_and_send_command(priv,
  1913. cmd_802_11_pwr_cfg,
  1914. 0,
  1915. cmd_option_waitforrsp,
  1916. 0, (void *)&cfg);
  1917. data[0] = cfg.enable;
  1918. data[1] = cfg.PA_P0;
  1919. data[2] = cfg.PA_P1;
  1920. data[3] = cfg.PA_P2;
  1921. if (copy_to_user
  1922. (wrq->u.data.pointer, data,
  1923. sizeof(int) * 4)) {
  1924. lbs_pr_debug(1, "Copy to user failed\n");
  1925. return -EFAULT;
  1926. }
  1927. wrq->u.data.length = 4;
  1928. }
  1929. break;
  1930. case WLAN_AUTO_FREQ_SET:
  1931. {
  1932. int data[3];
  1933. struct cmd_ds_802_11_afc afc;
  1934. memset(&afc, 0, sizeof(afc));
  1935. if (wrq->u.data.length != 3)
  1936. return -1;
  1937. if (copy_from_user
  1938. (data, wrq->u.data.pointer,
  1939. sizeof(int) * 3)) {
  1940. lbs_pr_debug(1, "Copy from user failed\n");
  1941. return -EFAULT;
  1942. }
  1943. afc.afc_auto = data[0];
  1944. if (afc.afc_auto != 0) {
  1945. afc.threshold = data[1];
  1946. afc.period = data[2];
  1947. } else {
  1948. afc.timing_offset = data[1];
  1949. afc.carrier_offset = data[2];
  1950. }
  1951. ret =
  1952. libertas_prepare_and_send_command(priv,
  1953. cmd_802_11_set_afc,
  1954. 0,
  1955. cmd_option_waitforrsp,
  1956. 0, (void *)&afc);
  1957. }
  1958. break;
  1959. case WLAN_AUTO_FREQ_GET:
  1960. {
  1961. int data[3];
  1962. struct cmd_ds_802_11_afc afc;
  1963. memset(&afc, 0, sizeof(afc));
  1964. ret =
  1965. libertas_prepare_and_send_command(priv,
  1966. cmd_802_11_get_afc,
  1967. 0,
  1968. cmd_option_waitforrsp,
  1969. 0, (void *)&afc);
  1970. data[0] = afc.afc_auto;
  1971. data[1] = afc.timing_offset;
  1972. data[2] = afc.carrier_offset;
  1973. if (copy_to_user
  1974. (wrq->u.data.pointer, data,
  1975. sizeof(int) * 3)) {
  1976. lbs_pr_debug(1, "Copy to user failed\n");
  1977. return -EFAULT;
  1978. }
  1979. wrq->u.data.length = 3;
  1980. }
  1981. break;
  1982. case WLAN_SCANPROBES:
  1983. {
  1984. int data;
  1985. if (wrq->u.data.length > 0) {
  1986. if (copy_from_user
  1987. (&data, wrq->u.data.pointer,
  1988. sizeof(int))) {
  1989. lbs_pr_debug(1,
  1990. "Copy from user failed\n");
  1991. return -EFAULT;
  1992. }
  1993. adapter->scanprobes = data;
  1994. } else {
  1995. data = adapter->scanprobes;
  1996. if (copy_to_user
  1997. (wrq->u.data.pointer, &data,
  1998. sizeof(int))) {
  1999. lbs_pr_debug(1,
  2000. "Copy to user failed\n");
  2001. return -EFAULT;
  2002. }
  2003. }
  2004. wrq->u.data.length = 1;
  2005. }
  2006. break;
  2007. case WLAN_LED_GPIO_CTRL:
  2008. {
  2009. int i;
  2010. int data[16];
  2011. struct cmd_ds_802_11_led_ctrl ctrl;
  2012. struct mrvlietypes_ledgpio *gpio =
  2013. (struct mrvlietypes_ledgpio *) ctrl.data;
  2014. memset(&ctrl, 0, sizeof(ctrl));
  2015. if (wrq->u.data.length > MAX_LEDS * 2)
  2016. return -ENOTSUPP;
  2017. if ((wrq->u.data.length % 2) != 0)
  2018. return -ENOTSUPP;
  2019. if (wrq->u.data.length == 0) {
  2020. ctrl.action =
  2021. cpu_to_le16
  2022. (cmd_act_get);
  2023. } else {
  2024. if (copy_from_user
  2025. (data, wrq->u.data.pointer,
  2026. sizeof(int) *
  2027. wrq->u.data.length)) {
  2028. lbs_pr_debug(1,
  2029. "Copy from user failed\n");
  2030. return -EFAULT;
  2031. }
  2032. ctrl.action =
  2033. cpu_to_le16
  2034. (cmd_act_set);
  2035. ctrl.numled = cpu_to_le16(0);
  2036. gpio->header.type =
  2037. cpu_to_le16(TLV_TYPE_LED_GPIO);
  2038. gpio->header.len = wrq->u.data.length;
  2039. for (i = 0; i < wrq->u.data.length;
  2040. i += 2) {
  2041. gpio->ledpin[i / 2].led =
  2042. data[i];
  2043. gpio->ledpin[i / 2].pin =
  2044. data[i + 1];
  2045. }
  2046. }
  2047. ret =
  2048. libertas_prepare_and_send_command(priv,
  2049. cmd_802_11_led_gpio_ctrl,
  2050. 0,
  2051. cmd_option_waitforrsp,
  2052. 0, (void *)&ctrl);
  2053. for (i = 0; i < gpio->header.len; i += 2) {
  2054. data[i] = gpio->ledpin[i / 2].led;
  2055. data[i + 1] = gpio->ledpin[i / 2].pin;
  2056. }
  2057. if (copy_to_user(wrq->u.data.pointer, data,
  2058. sizeof(int) *
  2059. gpio->header.len)) {
  2060. lbs_pr_debug(1, "Copy to user failed\n");
  2061. return -EFAULT;
  2062. }
  2063. wrq->u.data.length = gpio->header.len;
  2064. }
  2065. break;
  2066. case WLAN_ADAPT_RATESET:
  2067. ret = wlan_adapt_rateset(priv, wrq);
  2068. break;
  2069. case WLAN_INACTIVITY_TIMEOUT:
  2070. ret = wlan_inactivity_timeout(priv, wrq);
  2071. break;
  2072. case WLANSNR:
  2073. ret = wlan_get_snr(priv, wrq);
  2074. break;
  2075. case WLAN_GET_RXINFO:
  2076. ret = wlan_get_rxinfo(priv, wrq);
  2077. }
  2078. break;
  2079. default:
  2080. ret = -EINVAL;
  2081. break;
  2082. }
  2083. LEAVE();
  2084. return ret;
  2085. }