ioctl.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  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 wlan_set_region(wlan_private * priv, u16 region_code)
  25. {
  26. int i;
  27. int ret = 0;
  28. for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
  29. // use the region code to search for the index
  30. if (region_code == libertas_region_code_to_index[i]) {
  31. priv->adapter->regiontableindex = (u16) i;
  32. priv->adapter->regioncode = region_code;
  33. break;
  34. }
  35. }
  36. // if it's unidentified region code
  37. if (i >= MRVDRV_MAX_REGION_CODE) {
  38. lbs_deb_ioctl("region Code not identified\n");
  39. ret = -1;
  40. goto done;
  41. }
  42. if (libertas_set_regiontable(priv, priv->adapter->regioncode, 0)) {
  43. ret = -EINVAL;
  44. }
  45. done:
  46. lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
  47. return ret;
  48. }
  49. static inline int hex2int(char c)
  50. {
  51. if (c >= '0' && c <= '9')
  52. return (c - '0');
  53. if (c >= 'a' && c <= 'f')
  54. return (c - 'a' + 10);
  55. if (c >= 'A' && c <= 'F')
  56. return (c - 'A' + 10);
  57. return -1;
  58. }
  59. /* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
  60. into binary format (6 bytes).
  61. This function expects that each byte is represented with 2 characters
  62. (e.g., 11:2:11:11:11:11 is invalid)
  63. */
  64. static char *eth_str2addr(char *ethstr, u8 * addr)
  65. {
  66. int i, val, val2;
  67. char *pos = ethstr;
  68. /* get rid of initial blanks */
  69. while (*pos == ' ' || *pos == '\t')
  70. ++pos;
  71. for (i = 0; i < 6; i++) {
  72. val = hex2int(*pos++);
  73. if (val < 0)
  74. return NULL;
  75. val2 = hex2int(*pos++);
  76. if (val2 < 0)
  77. return NULL;
  78. addr[i] = (val * 16 + val2) & 0xff;
  79. if (i < 5 && *pos++ != ':')
  80. return NULL;
  81. }
  82. return pos;
  83. }
  84. /* this writes xx:xx:xx:xx:xx:xx into ethstr
  85. (ethstr must have space for 18 chars) */
  86. static int eth_addr2str(u8 * addr, char *ethstr)
  87. {
  88. int i;
  89. char *pos = ethstr;
  90. for (i = 0; i < 6; i++) {
  91. sprintf(pos, "%02x", addr[i] & 0xff);
  92. pos += 2;
  93. if (i < 5)
  94. *pos++ = ':';
  95. }
  96. return 17;
  97. }
  98. /**
  99. * @brief Add an entry to the BT table
  100. * @param priv A pointer to wlan_private structure
  101. * @param req A pointer to ifreq structure
  102. * @return 0 --success, otherwise fail
  103. */
  104. static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
  105. {
  106. struct iwreq *wrq = (struct iwreq *)req;
  107. char ethaddrs_str[18];
  108. char *pos;
  109. u8 ethaddr[ETH_ALEN];
  110. int ret;
  111. lbs_deb_enter(LBS_DEB_IOCTL);
  112. if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
  113. sizeof(ethaddrs_str)))
  114. return -EFAULT;
  115. if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
  116. lbs_pr_info("BT_ADD: Invalid MAC address\n");
  117. return -EINVAL;
  118. }
  119. lbs_deb_ioctl("BT: adding %s\n", ethaddrs_str);
  120. ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
  121. cmd_act_bt_access_add,
  122. cmd_option_waitforrsp, 0, ethaddr);
  123. lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
  124. return ret;
  125. }
  126. /**
  127. * @brief Delete an entry from the BT table
  128. * @param priv A pointer to wlan_private structure
  129. * @param req A pointer to ifreq structure
  130. * @return 0 --success, otherwise fail
  131. */
  132. static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
  133. {
  134. struct iwreq *wrq = (struct iwreq *)req;
  135. char ethaddrs_str[18];
  136. u8 ethaddr[ETH_ALEN];
  137. char *pos;
  138. lbs_deb_enter(LBS_DEB_IOCTL);
  139. if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
  140. sizeof(ethaddrs_str)))
  141. return -EFAULT;
  142. if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
  143. lbs_pr_info("Invalid MAC address\n");
  144. return -EINVAL;
  145. }
  146. lbs_deb_ioctl("BT: deleting %s\n", ethaddrs_str);
  147. return (libertas_prepare_and_send_command(priv,
  148. cmd_bt_access,
  149. cmd_act_bt_access_del,
  150. cmd_option_waitforrsp, 0, ethaddr));
  151. lbs_deb_leave(LBS_DEB_IOCTL);
  152. return 0;
  153. }
  154. /**
  155. * @brief Reset all entries from the BT table
  156. * @param priv A pointer to wlan_private structure
  157. * @return 0 --success, otherwise fail
  158. */
  159. static int wlan_bt_reset_ioctl(wlan_private * priv)
  160. {
  161. lbs_deb_enter(LBS_DEB_IOCTL);
  162. lbs_pr_alert( "BT: resetting\n");
  163. return (libertas_prepare_and_send_command(priv,
  164. cmd_bt_access,
  165. cmd_act_bt_access_reset,
  166. cmd_option_waitforrsp, 0, NULL));
  167. lbs_deb_leave(LBS_DEB_IOCTL);
  168. return 0;
  169. }
  170. /**
  171. * @brief List an entry from the BT table
  172. * @param priv A pointer to wlan_private structure
  173. * @param req A pointer to ifreq structure
  174. * @return 0 --success, otherwise fail
  175. */
  176. static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
  177. {
  178. int pos;
  179. char *addr1;
  180. struct iwreq *wrq = (struct iwreq *)req;
  181. /* used to pass id and store the bt entry returned by the FW */
  182. union {
  183. int id;
  184. char addr1addr2[2 * ETH_ALEN];
  185. } param;
  186. static char outstr[64];
  187. char *pbuf = outstr;
  188. int ret;
  189. lbs_deb_enter(LBS_DEB_IOCTL);
  190. if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
  191. lbs_deb_ioctl("Copy from user failed\n");
  192. return -1;
  193. }
  194. param.id = simple_strtoul(outstr, NULL, 10);
  195. pos = sprintf(pbuf, "%d: ", param.id);
  196. pbuf += pos;
  197. ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
  198. cmd_act_bt_access_list,
  199. cmd_option_waitforrsp, 0,
  200. (char *)&param);
  201. if (ret == 0) {
  202. addr1 = param.addr1addr2;
  203. pos = sprintf(pbuf, "BT includes node ");
  204. pbuf += pos;
  205. pos = eth_addr2str(addr1, pbuf);
  206. pbuf += pos;
  207. } else {
  208. sprintf(pbuf, "(null)");
  209. pbuf += pos;
  210. }
  211. wrq->u.data.length = strlen(outstr);
  212. if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
  213. wrq->u.data.length)) {
  214. lbs_deb_ioctl("BT_LIST: Copy to user failed!\n");
  215. return -EFAULT;
  216. }
  217. lbs_deb_leave(LBS_DEB_IOCTL);
  218. return 0 ;
  219. }
  220. /**
  221. * @brief Sets inverted state of blacklist (non-zero if inverted)
  222. * @param priv A pointer to wlan_private structure
  223. * @param req A pointer to ifreq structure
  224. * @return 0 --success, otherwise fail
  225. */
  226. static int wlan_bt_set_invert_ioctl(wlan_private * priv, struct ifreq *req)
  227. {
  228. int ret;
  229. struct iwreq *wrq = (struct iwreq *)req;
  230. union {
  231. int id;
  232. char addr1addr2[2 * ETH_ALEN];
  233. } param;
  234. lbs_deb_enter(LBS_DEB_IOCTL);
  235. param.id = SUBCMD_DATA(wrq) ;
  236. ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
  237. cmd_act_bt_access_set_invert,
  238. cmd_option_waitforrsp, 0,
  239. (char *)&param);
  240. if (ret != 0)
  241. return -EFAULT;
  242. lbs_deb_leave(LBS_DEB_IOCTL);
  243. return 0;
  244. }
  245. /**
  246. * @brief Gets inverted state of blacklist (non-zero if inverted)
  247. * @param priv A pointer to wlan_private structure
  248. * @param req A pointer to ifreq structure
  249. * @return 0 --success, otherwise fail
  250. */
  251. static int wlan_bt_get_invert_ioctl(wlan_private * priv, struct ifreq *req)
  252. {
  253. int ret;
  254. union {
  255. int id;
  256. char addr1addr2[2 * ETH_ALEN];
  257. } param;
  258. lbs_deb_enter(LBS_DEB_IOCTL);
  259. ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
  260. cmd_act_bt_access_get_invert,
  261. cmd_option_waitforrsp, 0,
  262. (char *)&param);
  263. if (ret == 0)
  264. req->ifr_data = (char *)(le32_to_cpu(param.id));
  265. else
  266. return -EFAULT;
  267. lbs_deb_leave(LBS_DEB_IOCTL);
  268. return 0;
  269. }
  270. /**
  271. * @brief Find the next parameter in an input string
  272. * @param ptr A pointer to the input parameter string
  273. * @return A pointer to the next parameter, or 0 if no parameters left.
  274. */
  275. static char * next_param(char * ptr)
  276. {
  277. if (!ptr) return NULL;
  278. while (*ptr == ' ' || *ptr == '\t') ++ptr;
  279. return (*ptr == '\0') ? NULL : ptr;
  280. }
  281. /**
  282. * @brief Add an entry to the FWT table
  283. * @param priv A pointer to wlan_private structure
  284. * @param req A pointer to ifreq structure
  285. * @return 0 --success, otherwise fail
  286. */
  287. static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
  288. {
  289. struct iwreq *wrq = (struct iwreq *)req;
  290. char in_str[128];
  291. static struct cmd_ds_fwt_access fwt_access;
  292. char *ptr;
  293. int ret;
  294. lbs_deb_enter(LBS_DEB_IOCTL);
  295. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  296. return -EFAULT;
  297. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  298. lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
  299. return -EINVAL;
  300. }
  301. if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
  302. lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
  303. return -EINVAL;
  304. }
  305. if ((ptr = next_param(ptr)))
  306. fwt_access.metric =
  307. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  308. else
  309. fwt_access.metric = FWT_DEFAULT_METRIC;
  310. if ((ptr = next_param(ptr)))
  311. fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
  312. else
  313. fwt_access.dir = FWT_DEFAULT_DIR;
  314. if ((ptr = next_param(ptr)))
  315. fwt_access.rate = (u8) simple_strtoul(ptr, &ptr, 10);
  316. else
  317. fwt_access.rate = FWT_DEFAULT_RATE;
  318. if ((ptr = next_param(ptr)))
  319. fwt_access.ssn =
  320. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  321. else
  322. fwt_access.ssn = FWT_DEFAULT_SSN;
  323. if ((ptr = next_param(ptr)))
  324. fwt_access.dsn =
  325. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  326. else
  327. fwt_access.dsn = FWT_DEFAULT_DSN;
  328. if ((ptr = next_param(ptr)))
  329. fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
  330. else
  331. fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
  332. if ((ptr = next_param(ptr)))
  333. fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
  334. else
  335. fwt_access.ttl = FWT_DEFAULT_TTL;
  336. if ((ptr = next_param(ptr)))
  337. fwt_access.expiration =
  338. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  339. else
  340. fwt_access.expiration = FWT_DEFAULT_EXPIRATION;
  341. if ((ptr = next_param(ptr)))
  342. fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
  343. else
  344. fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
  345. if ((ptr = next_param(ptr)))
  346. fwt_access.snr =
  347. cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  348. else
  349. fwt_access.snr = FWT_DEFAULT_SNR;
  350. #ifdef DEBUG
  351. {
  352. char ethaddr1_str[18], ethaddr2_str[18];
  353. eth_addr2str(fwt_access.da, ethaddr1_str);
  354. eth_addr2str(fwt_access.ra, ethaddr2_str);
  355. lbs_deb_ioctl("FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
  356. fwt_access.dir, ethaddr2_str);
  357. lbs_deb_ioctl("FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
  358. fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
  359. fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
  360. fwt_access.sleepmode, fwt_access.snr);
  361. }
  362. #endif
  363. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  364. cmd_act_fwt_access_add,
  365. cmd_option_waitforrsp, 0,
  366. (void *)&fwt_access);
  367. lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
  368. return ret;
  369. }
  370. /**
  371. * @brief Delete an entry from the FWT table
  372. * @param priv A pointer to wlan_private structure
  373. * @param req A pointer to ifreq structure
  374. * @return 0 --success, otherwise fail
  375. */
  376. static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
  377. {
  378. struct iwreq *wrq = (struct iwreq *)req;
  379. char in_str[64];
  380. static struct cmd_ds_fwt_access fwt_access;
  381. char *ptr;
  382. int ret;
  383. lbs_deb_enter(LBS_DEB_IOCTL);
  384. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  385. return -EFAULT;
  386. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  387. lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
  388. return -EINVAL;
  389. }
  390. if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
  391. lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
  392. return -EINVAL;
  393. }
  394. if ((ptr = next_param(ptr)))
  395. fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
  396. else
  397. fwt_access.dir = FWT_DEFAULT_DIR;
  398. #ifdef DEBUG
  399. {
  400. char ethaddr1_str[18], ethaddr2_str[18];
  401. lbs_deb_ioctl("FWT_DEL: line is %s\n", in_str);
  402. eth_addr2str(fwt_access.da, ethaddr1_str);
  403. eth_addr2str(fwt_access.ra, ethaddr2_str);
  404. lbs_deb_ioctl("FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
  405. ethaddr2_str, fwt_access.dir);
  406. }
  407. #endif
  408. ret = libertas_prepare_and_send_command(priv,
  409. cmd_fwt_access,
  410. cmd_act_fwt_access_del,
  411. cmd_option_waitforrsp, 0,
  412. (void *)&fwt_access);
  413. lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
  414. return ret;
  415. }
  416. /**
  417. * @brief Print route parameters
  418. * @param fwt_access struct cmd_ds_fwt_access with route info
  419. * @param buf destination buffer for route info
  420. */
  421. static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
  422. {
  423. buf += sprintf(buf, " ");
  424. buf += eth_addr2str(fwt_access.da, buf);
  425. buf += sprintf(buf, " ");
  426. buf += eth_addr2str(fwt_access.ra, buf);
  427. buf += sprintf(buf, " %u", fwt_access.valid);
  428. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
  429. buf += sprintf(buf, " %u", fwt_access.dir);
  430. buf += sprintf(buf, " %u", fwt_access.rate);
  431. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
  432. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
  433. buf += sprintf(buf, " %u", fwt_access.hopcount);
  434. buf += sprintf(buf, " %u", fwt_access.ttl);
  435. buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
  436. buf += sprintf(buf, " %u", fwt_access.sleepmode);
  437. buf += sprintf(buf, " %u ", le32_to_cpu(fwt_access.snr));
  438. buf += eth_addr2str(fwt_access.prec, buf);
  439. }
  440. /**
  441. * @brief Lookup an entry in the FWT table
  442. * @param priv A pointer to wlan_private structure
  443. * @param req A pointer to ifreq structure
  444. * @return 0 --success, otherwise fail
  445. */
  446. static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
  447. {
  448. struct iwreq *wrq = (struct iwreq *)req;
  449. char in_str[64];
  450. char *ptr;
  451. static struct cmd_ds_fwt_access fwt_access;
  452. static char out_str[128];
  453. int ret;
  454. lbs_deb_enter(LBS_DEB_IOCTL);
  455. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  456. return -EFAULT;
  457. if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
  458. lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
  459. return -EINVAL;
  460. }
  461. #ifdef DEBUG
  462. {
  463. char ethaddr1_str[18];
  464. lbs_deb_ioctl("FWT_LOOKUP: line is %s\n", in_str);
  465. eth_addr2str(fwt_access.da, ethaddr1_str);
  466. lbs_deb_ioctl("FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
  467. }
  468. #endif
  469. ret = libertas_prepare_and_send_command(priv,
  470. cmd_fwt_access,
  471. cmd_act_fwt_access_lookup,
  472. cmd_option_waitforrsp, 0,
  473. (void *)&fwt_access);
  474. if (ret == 0)
  475. print_route(fwt_access, out_str);
  476. else
  477. sprintf(out_str, "(null)");
  478. wrq->u.data.length = strlen(out_str);
  479. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  480. wrq->u.data.length)) {
  481. lbs_deb_ioctl("FWT_LOOKUP: Copy to user failed!\n");
  482. return -EFAULT;
  483. }
  484. lbs_deb_leave(LBS_DEB_IOCTL);
  485. return 0;
  486. }
  487. /**
  488. * @brief Reset all entries from the FWT table
  489. * @param priv A pointer to wlan_private structure
  490. * @return 0 --success, otherwise fail
  491. */
  492. static int wlan_fwt_reset_ioctl(wlan_private * priv)
  493. {
  494. lbs_deb_ioctl("FWT: resetting\n");
  495. return (libertas_prepare_and_send_command(priv,
  496. cmd_fwt_access,
  497. cmd_act_fwt_access_reset,
  498. cmd_option_waitforrsp, 0, NULL));
  499. }
  500. /**
  501. * @brief List an entry from the FWT table
  502. * @param priv A pointer to wlan_private structure
  503. * @param req A pointer to ifreq structure
  504. * @return 0 --success, otherwise fail
  505. */
  506. static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
  507. {
  508. struct iwreq *wrq = (struct iwreq *)req;
  509. char in_str[8];
  510. static struct cmd_ds_fwt_access fwt_access;
  511. char *ptr = in_str;
  512. static char out_str[128];
  513. char *pbuf = out_str;
  514. int ret;
  515. lbs_deb_enter(LBS_DEB_IOCTL);
  516. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  517. return -EFAULT;
  518. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  519. #ifdef DEBUG
  520. {
  521. lbs_deb_ioctl("FWT_LIST: line is %s\n", in_str);
  522. lbs_deb_ioctl("FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
  523. }
  524. #endif
  525. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  526. cmd_act_fwt_access_list,
  527. cmd_option_waitforrsp, 0, (void *)&fwt_access);
  528. if (ret == 0)
  529. print_route(fwt_access, pbuf);
  530. else
  531. pbuf += sprintf(pbuf, " (null)");
  532. wrq->u.data.length = strlen(out_str);
  533. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  534. wrq->u.data.length)) {
  535. lbs_deb_ioctl("FWT_LIST: Copy to user failed!\n");
  536. return -EFAULT;
  537. }
  538. lbs_deb_leave(LBS_DEB_IOCTL);
  539. return 0;
  540. }
  541. /**
  542. * @brief List an entry from the FRT table
  543. * @param priv A pointer to wlan_private structure
  544. * @param req A pointer to ifreq structure
  545. * @return 0 --success, otherwise fail
  546. */
  547. static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
  548. {
  549. struct iwreq *wrq = (struct iwreq *)req;
  550. char in_str[64];
  551. static struct cmd_ds_fwt_access fwt_access;
  552. char *ptr = in_str;
  553. static char out_str[128];
  554. char *pbuf = out_str;
  555. int ret;
  556. lbs_deb_enter(LBS_DEB_IOCTL);
  557. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  558. return -EFAULT;
  559. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  560. #ifdef DEBUG
  561. {
  562. lbs_deb_ioctl("FWT_LIST_ROUTE: line is %s\n", in_str);
  563. lbs_deb_ioctl("FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
  564. }
  565. #endif
  566. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  567. cmd_act_fwt_access_list_route,
  568. cmd_option_waitforrsp, 0, (void *)&fwt_access);
  569. if (ret == 0) {
  570. print_route(fwt_access, pbuf);
  571. } else
  572. pbuf += sprintf(pbuf, " (null)");
  573. wrq->u.data.length = strlen(out_str);
  574. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  575. wrq->u.data.length)) {
  576. lbs_deb_ioctl("FWT_LIST_ROUTE: Copy to user failed!\n");
  577. return -EFAULT;
  578. }
  579. lbs_deb_leave(LBS_DEB_IOCTL);
  580. return 0;
  581. }
  582. /**
  583. * @brief List an entry from the FNT table
  584. * @param priv A pointer to wlan_private structure
  585. * @param req A pointer to ifreq structure
  586. * @return 0 --success, otherwise fail
  587. */
  588. static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
  589. {
  590. struct iwreq *wrq = (struct iwreq *)req;
  591. char in_str[8];
  592. static struct cmd_ds_fwt_access fwt_access;
  593. char *ptr = in_str;
  594. static char out_str[128];
  595. char *pbuf = out_str;
  596. int ret;
  597. lbs_deb_enter(LBS_DEB_IOCTL);
  598. if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
  599. return -EFAULT;
  600. memset(&fwt_access, 0, sizeof(fwt_access));
  601. fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
  602. #ifdef DEBUG
  603. {
  604. lbs_deb_ioctl("FWT_LIST_NEIGHBOR: line is %s\n", in_str);
  605. lbs_deb_ioctl("FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
  606. }
  607. #endif
  608. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  609. cmd_act_fwt_access_list_neighbor,
  610. cmd_option_waitforrsp, 0,
  611. (void *)&fwt_access);
  612. if (ret == 0) {
  613. pbuf += sprintf(pbuf, " ra ");
  614. pbuf += eth_addr2str(fwt_access.ra, pbuf);
  615. pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode);
  616. pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr));
  617. pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references));
  618. } else
  619. pbuf += sprintf(pbuf, " (null)");
  620. wrq->u.data.length = strlen(out_str);
  621. if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
  622. wrq->u.data.length)) {
  623. lbs_deb_ioctl("FWT_LIST_NEIGHBOR: Copy to user failed!\n");
  624. return -EFAULT;
  625. }
  626. lbs_deb_leave(LBS_DEB_IOCTL);
  627. return 0;
  628. }
  629. /**
  630. * @brief Cleans up the route (FRT) and neighbor (FNT) tables
  631. * (Garbage Collection)
  632. * @param priv A pointer to wlan_private structure
  633. * @param req A pointer to ifreq structure
  634. * @return 0 --success, otherwise fail
  635. */
  636. static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
  637. {
  638. struct iwreq *wrq = (struct iwreq *)req;
  639. static struct cmd_ds_fwt_access fwt_access;
  640. int ret;
  641. lbs_deb_enter(LBS_DEB_IOCTL);
  642. lbs_deb_ioctl("FWT: cleaning up\n");
  643. memset(&fwt_access, 0, sizeof(fwt_access));
  644. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  645. cmd_act_fwt_access_cleanup,
  646. cmd_option_waitforrsp, 0,
  647. (void *)&fwt_access);
  648. if (ret == 0)
  649. wrq->u.param.value = le32_to_cpu(fwt_access.references);
  650. else
  651. return -EFAULT;
  652. lbs_deb_leave(LBS_DEB_IOCTL);
  653. return 0;
  654. }
  655. /**
  656. * @brief Gets firmware internal time (debug purposes)
  657. * @param priv A pointer to wlan_private structure
  658. * @param req A pointer to ifreq structure
  659. * @return 0 --success, otherwise fail
  660. */
  661. static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
  662. {
  663. struct iwreq *wrq = (struct iwreq *)req;
  664. static struct cmd_ds_fwt_access fwt_access;
  665. int ret;
  666. lbs_deb_enter(LBS_DEB_IOCTL);
  667. lbs_deb_ioctl("FWT: getting time\n");
  668. memset(&fwt_access, 0, sizeof(fwt_access));
  669. ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
  670. cmd_act_fwt_access_time,
  671. cmd_option_waitforrsp, 0,
  672. (void *)&fwt_access);
  673. if (ret == 0)
  674. wrq->u.param.value = le32_to_cpu(fwt_access.references);
  675. else
  676. return -EFAULT;
  677. lbs_deb_leave(LBS_DEB_IOCTL);
  678. return 0;
  679. }
  680. /**
  681. * @brief Gets mesh ttl from firmware
  682. * @param priv A pointer to wlan_private structure
  683. * @param req A pointer to ifreq structure
  684. * @return 0 --success, otherwise fail
  685. */
  686. static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
  687. {
  688. struct iwreq *wrq = (struct iwreq *)req;
  689. struct cmd_ds_mesh_access mesh_access;
  690. int ret;
  691. lbs_deb_enter(LBS_DEB_IOCTL);
  692. memset(&mesh_access, 0, sizeof(mesh_access));
  693. ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
  694. cmd_act_mesh_get_ttl,
  695. cmd_option_waitforrsp, 0,
  696. (void *)&mesh_access);
  697. if (ret == 0)
  698. wrq->u.param.value = le32_to_cpu(mesh_access.data[0]);
  699. else
  700. return -EFAULT;
  701. lbs_deb_leave(LBS_DEB_IOCTL);
  702. return 0;
  703. }
  704. /**
  705. * @brief Gets mesh ttl from firmware
  706. * @param priv A pointer to wlan_private structure
  707. * @param ttl New ttl value
  708. * @return 0 --success, otherwise fail
  709. */
  710. static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
  711. {
  712. struct cmd_ds_mesh_access mesh_access;
  713. int ret;
  714. lbs_deb_enter(LBS_DEB_IOCTL);
  715. if( (ttl > 0xff) || (ttl < 0) )
  716. return -EINVAL;
  717. memset(&mesh_access, 0, sizeof(mesh_access));
  718. mesh_access.data[0] = ttl;
  719. ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
  720. cmd_act_mesh_set_ttl,
  721. cmd_option_waitforrsp, 0,
  722. (void *)&mesh_access);
  723. if (ret != 0)
  724. ret = -EFAULT;
  725. lbs_deb_leave(LBS_DEB_IOCTL);
  726. return ret;
  727. }
  728. /**
  729. * @brief ioctl function - entry point
  730. *
  731. * @param dev A pointer to net_device structure
  732. * @param req A pointer to ifreq structure
  733. * @param cmd command
  734. * @return 0--success, otherwise fail
  735. */
  736. int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
  737. {
  738. int subcmd = 0;
  739. int idata = 0;
  740. int *pdata;
  741. int ret = 0;
  742. wlan_private *priv = dev->priv;
  743. wlan_adapter *adapter = priv->adapter;
  744. struct iwreq *wrq = (struct iwreq *)req;
  745. lbs_deb_enter(LBS_DEB_IOCTL);
  746. lbs_deb_ioctl("libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
  747. switch (cmd) {
  748. case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */
  749. switch (wrq->u.data.flags) {
  750. case WLAN_SUBCMD_BT_RESET: /* bt_reset */
  751. wlan_bt_reset_ioctl(priv);
  752. break;
  753. case WLAN_SUBCMD_FWT_RESET: /* fwt_reset */
  754. wlan_fwt_reset_ioctl(priv);
  755. break;
  756. } /* End of switch */
  757. break;
  758. case WLAN_SETONEINT_GETNONE:
  759. /* The first 4 bytes of req->ifr_data is sub-ioctl number
  760. * after 4 bytes sits the payload.
  761. */
  762. subcmd = wrq->u.data.flags;
  763. if (!subcmd)
  764. subcmd = (int)wrq->u.param.value;
  765. switch (subcmd) {
  766. case WLANSETREGION:
  767. idata = SUBCMD_DATA(wrq);
  768. ret = wlan_set_region(priv, (u16) idata);
  769. break;
  770. case WLAN_SUBCMD_MESH_SET_TTL:
  771. idata = SUBCMD_DATA(wrq);
  772. ret = wlan_mesh_set_ttl_ioctl(priv, idata);
  773. break;
  774. case WLAN_SUBCMD_BT_SET_INVERT:
  775. ret = wlan_bt_set_invert_ioctl(priv, req);
  776. break ;
  777. default:
  778. ret = -EOPNOTSUPP;
  779. break;
  780. }
  781. break;
  782. case WLAN_SET128CHAR_GET128CHAR:
  783. switch ((int)wrq->u.data.flags) {
  784. case WLAN_SUBCMD_BT_ADD:
  785. ret = wlan_bt_add_ioctl(priv, req);
  786. break;
  787. case WLAN_SUBCMD_BT_DEL:
  788. ret = wlan_bt_del_ioctl(priv, req);
  789. break;
  790. case WLAN_SUBCMD_BT_LIST:
  791. ret = wlan_bt_list_ioctl(priv, req);
  792. break;
  793. case WLAN_SUBCMD_FWT_ADD:
  794. ret = wlan_fwt_add_ioctl(priv, req);
  795. break;
  796. case WLAN_SUBCMD_FWT_DEL:
  797. ret = wlan_fwt_del_ioctl(priv, req);
  798. break;
  799. case WLAN_SUBCMD_FWT_LOOKUP:
  800. ret = wlan_fwt_lookup_ioctl(priv, req);
  801. break;
  802. case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
  803. ret = wlan_fwt_list_neighbor_ioctl(priv, req);
  804. break;
  805. case WLAN_SUBCMD_FWT_LIST:
  806. ret = wlan_fwt_list_ioctl(priv, req);
  807. break;
  808. case WLAN_SUBCMD_FWT_LIST_ROUTE:
  809. ret = wlan_fwt_list_route_ioctl(priv, req);
  810. break;
  811. }
  812. break;
  813. case WLAN_SETNONE_GETONEINT:
  814. switch (wrq->u.param.value) {
  815. case WLANGETREGION:
  816. pdata = (int *)wrq->u.name;
  817. *pdata = (int)adapter->regioncode;
  818. break;
  819. case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */
  820. ret = wlan_fwt_cleanup_ioctl(priv, req);
  821. break;
  822. case WLAN_SUBCMD_FWT_TIME: /* fwt_time */
  823. ret = wlan_fwt_time_ioctl(priv, req);
  824. break;
  825. case WLAN_SUBCMD_MESH_GET_TTL:
  826. ret = wlan_mesh_get_ttl_ioctl(priv, req);
  827. break;
  828. case WLAN_SUBCMD_BT_GET_INVERT:
  829. ret = wlan_bt_get_invert_ioctl(priv, req);
  830. break ;
  831. default:
  832. ret = -EOPNOTSUPP;
  833. }
  834. break;
  835. case WLAN_SET_GET_SIXTEEN_INT:
  836. switch ((int)wrq->u.data.flags) {
  837. case WLAN_LED_GPIO_CTRL:
  838. {
  839. int i;
  840. int data[16];
  841. struct cmd_ds_802_11_led_ctrl ctrl;
  842. struct mrvlietypes_ledgpio *gpio =
  843. (struct mrvlietypes_ledgpio *) ctrl.data;
  844. memset(&ctrl, 0, sizeof(ctrl));
  845. if (wrq->u.data.length > MAX_LEDS * 2)
  846. return -ENOTSUPP;
  847. if ((wrq->u.data.length % 2) != 0)
  848. return -ENOTSUPP;
  849. if (wrq->u.data.length == 0) {
  850. ctrl.action =
  851. cpu_to_le16
  852. (cmd_act_get);
  853. } else {
  854. if (copy_from_user
  855. (data, wrq->u.data.pointer,
  856. sizeof(int) *
  857. wrq->u.data.length)) {
  858. lbs_deb_ioctl(
  859. "Copy from user failed\n");
  860. return -EFAULT;
  861. }
  862. ctrl.action =
  863. cpu_to_le16
  864. (cmd_act_set);
  865. ctrl.numled = cpu_to_le16(0);
  866. gpio->header.type =
  867. cpu_to_le16(TLV_TYPE_LED_GPIO);
  868. gpio->header.len = wrq->u.data.length;
  869. for (i = 0; i < wrq->u.data.length;
  870. i += 2) {
  871. gpio->ledpin[i / 2].led =
  872. data[i];
  873. gpio->ledpin[i / 2].pin =
  874. data[i + 1];
  875. }
  876. }
  877. ret =
  878. libertas_prepare_and_send_command(priv,
  879. cmd_802_11_led_gpio_ctrl,
  880. 0,
  881. cmd_option_waitforrsp,
  882. 0, (void *)&ctrl);
  883. for (i = 0; i < gpio->header.len; i += 2) {
  884. data[i] = gpio->ledpin[i / 2].led;
  885. data[i + 1] = gpio->ledpin[i / 2].pin;
  886. }
  887. if (copy_to_user(wrq->u.data.pointer, data,
  888. sizeof(int) *
  889. gpio->header.len)) {
  890. lbs_deb_ioctl("Copy to user failed\n");
  891. return -EFAULT;
  892. }
  893. wrq->u.data.length = gpio->header.len;
  894. }
  895. break;
  896. }
  897. break;
  898. default:
  899. ret = -EINVAL;
  900. break;
  901. }
  902. lbs_deb_leave_args(LBS_DEB_IOCTL, "ret %d", ret);
  903. return ret;
  904. }