join.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. /**
  2. * Functions implementing wlan infrastructure and adhoc join routines,
  3. * IOCTL handlers as well as command preperation and response routines
  4. * for sending adhoc start, adhoc join, and association commands
  5. * to the firmware.
  6. */
  7. #include <linux/netdevice.h>
  8. #include <linux/if_arp.h>
  9. #include <linux/wireless.h>
  10. #include <net/iw_handler.h>
  11. #include "host.h"
  12. #include "decl.h"
  13. #include "join.h"
  14. #include "dev.h"
  15. /**
  16. * @brief This function finds out the common rates between rate1 and rate2.
  17. *
  18. * It will fill common rates in rate1 as output if found.
  19. *
  20. * NOTE: Setting the MSB of the basic rates need to be taken
  21. * care, either before or after calling this function
  22. *
  23. * @param adapter A pointer to wlan_adapter structure
  24. * @param rate1 the buffer which keeps input and output
  25. * @param rate1_size the size of rate1 buffer
  26. * @param rate2 the buffer which keeps rate2
  27. * @param rate2_size the size of rate2 buffer.
  28. *
  29. * @return 0 or -1
  30. */
  31. static int get_common_rates(wlan_adapter * adapter, u8 * rate1,
  32. int rate1_size, u8 * rate2, int rate2_size)
  33. {
  34. u8 *ptr = rate1;
  35. int ret = 0;
  36. u8 tmp[30];
  37. int i;
  38. memset(&tmp, 0, sizeof(tmp));
  39. memcpy(&tmp, rate1, min_t(size_t, rate1_size, sizeof(tmp)));
  40. memset(rate1, 0, rate1_size);
  41. /* Mask the top bit of the original values */
  42. for (i = 0; tmp[i] && i < sizeof(tmp); i++)
  43. tmp[i] &= 0x7F;
  44. for (i = 0; rate2[i] && i < rate2_size; i++) {
  45. /* Check for Card Rate in tmp, excluding the top bit */
  46. if (strchr(tmp, rate2[i] & 0x7F)) {
  47. /* values match, so copy the Card Rate to rate1 */
  48. *rate1++ = rate2[i];
  49. }
  50. }
  51. lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp));
  52. lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size);
  53. lbs_dbg_hex("Common rates:", ptr, rate1_size);
  54. lbs_pr_debug(1, "Tx datarate is set to 0x%X\n", adapter->datarate);
  55. if (!adapter->is_datarate_auto) {
  56. while (*ptr) {
  57. if ((*ptr & 0x7f) == adapter->datarate) {
  58. ret = 0;
  59. goto done;
  60. }
  61. ptr++;
  62. }
  63. lbs_pr_alert( "Previously set fixed data rate %#x isn't "
  64. "compatible with the network.\n", adapter->datarate);
  65. ret = -1;
  66. goto done;
  67. }
  68. ret = 0;
  69. done:
  70. return ret;
  71. }
  72. int libertas_send_deauth(wlan_private * priv)
  73. {
  74. wlan_adapter *adapter = priv->adapter;
  75. int ret = 0;
  76. if (adapter->inframode == wlan802_11infrastructure &&
  77. adapter->connect_status == libertas_connected)
  78. ret = libertas_send_deauthentication(priv);
  79. else
  80. ret = -ENOTSUPP;
  81. return ret;
  82. }
  83. int libertas_do_adhocstop_ioctl(wlan_private * priv)
  84. {
  85. wlan_adapter *adapter = priv->adapter;
  86. int ret = 0;
  87. if (adapter->inframode == wlan802_11ibss &&
  88. adapter->connect_status == libertas_connected)
  89. ret = libertas_stop_adhoc_network(priv);
  90. else
  91. ret = -ENOTSUPP;
  92. return ret;
  93. }
  94. /**
  95. * @brief Associate to a specific BSS discovered in a scan
  96. *
  97. * @param priv A pointer to wlan_private structure
  98. * @param pbssdesc Pointer to the BSS descriptor to associate with.
  99. *
  100. * @return 0-success, otherwise fail
  101. */
  102. int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
  103. {
  104. wlan_adapter *adapter = priv->adapter;
  105. int ret;
  106. ENTER();
  107. ret = libertas_prepare_and_send_command(priv, cmd_802_11_authenticate,
  108. 0, cmd_option_waitforrsp,
  109. 0, pbssdesc->macaddress);
  110. if (ret) {
  111. LEAVE();
  112. return ret;
  113. }
  114. /* set preamble to firmware */
  115. if (adapter->capinfo.shortpreamble && pbssdesc->cap.shortpreamble)
  116. adapter->preamble = cmd_type_short_preamble;
  117. else
  118. adapter->preamble = cmd_type_long_preamble;
  119. libertas_set_radio_control(priv);
  120. ret = libertas_prepare_and_send_command(priv, cmd_802_11_associate,
  121. 0, cmd_option_waitforrsp, 0, pbssdesc);
  122. LEAVE();
  123. return ret;
  124. }
  125. /**
  126. * @brief Start an Adhoc Network
  127. *
  128. * @param priv A pointer to wlan_private structure
  129. * @param adhocssid The ssid of the Adhoc Network
  130. * @return 0--success, -1--fail
  131. */
  132. int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *adhocssid)
  133. {
  134. wlan_adapter *adapter = priv->adapter;
  135. int ret = 0;
  136. adapter->adhoccreate = 1;
  137. if (!adapter->capinfo.shortpreamble) {
  138. lbs_pr_debug(1, "AdhocStart: Long preamble\n");
  139. adapter->preamble = cmd_type_long_preamble;
  140. } else {
  141. lbs_pr_debug(1, "AdhocStart: Short preamble\n");
  142. adapter->preamble = cmd_type_short_preamble;
  143. }
  144. libertas_set_radio_control(priv);
  145. lbs_pr_debug(1, "Adhoc channel = %d\n", adapter->adhocchannel);
  146. lbs_pr_debug(1, "curbssparams.channel = %d\n",
  147. adapter->curbssparams.channel);
  148. lbs_pr_debug(1, "curbssparams.band = %d\n", adapter->curbssparams.band);
  149. ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_start,
  150. 0, cmd_option_waitforrsp, 0, adhocssid);
  151. return ret;
  152. }
  153. /**
  154. * @brief Join an adhoc network found in a previous scan
  155. *
  156. * @param priv A pointer to wlan_private structure
  157. * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
  158. * to attempt to join
  159. *
  160. * @return 0--success, -1--fail
  161. */
  162. int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbssdesc)
  163. {
  164. wlan_adapter *adapter = priv->adapter;
  165. int ret = 0;
  166. lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid =%s\n",
  167. adapter->curbssparams.ssid.ssid);
  168. lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid_len =%u\n",
  169. adapter->curbssparams.ssid.ssidlength);
  170. lbs_pr_debug(1, "libertas_join_adhoc_network: ssid =%s\n", pbssdesc->ssid.ssid);
  171. lbs_pr_debug(1, "libertas_join_adhoc_network: ssid len =%u\n",
  172. pbssdesc->ssid.ssidlength);
  173. /* check if the requested SSID is already joined */
  174. if (adapter->curbssparams.ssid.ssidlength
  175. && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid)
  176. && (adapter->curbssparams.bssdescriptor.inframode ==
  177. wlan802_11ibss)) {
  178. lbs_pr_debug(1,
  179. "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
  180. "not attempting to re-join");
  181. return -1;
  182. }
  183. /*Use shortpreamble only when both creator and card supports
  184. short preamble */
  185. if (!pbssdesc->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
  186. lbs_pr_debug(1, "AdhocJoin: Long preamble\n");
  187. adapter->preamble = cmd_type_long_preamble;
  188. } else {
  189. lbs_pr_debug(1, "AdhocJoin: Short preamble\n");
  190. adapter->preamble = cmd_type_short_preamble;
  191. }
  192. libertas_set_radio_control(priv);
  193. lbs_pr_debug(1, "curbssparams.channel = %d\n",
  194. adapter->curbssparams.channel);
  195. lbs_pr_debug(1, "curbssparams.band = %c\n", adapter->curbssparams.band);
  196. adapter->adhoccreate = 0;
  197. ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_join,
  198. 0, cmd_option_waitforrsp,
  199. OID_802_11_SSID, pbssdesc);
  200. return ret;
  201. }
  202. int libertas_stop_adhoc_network(wlan_private * priv)
  203. {
  204. return libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_stop,
  205. 0, cmd_option_waitforrsp, 0, NULL);
  206. }
  207. /**
  208. * @brief Send Deauthentication Request
  209. *
  210. * @param priv A pointer to wlan_private structure
  211. * @return 0--success, -1--fail
  212. */
  213. int libertas_send_deauthentication(wlan_private * priv)
  214. {
  215. return libertas_prepare_and_send_command(priv, cmd_802_11_deauthenticate,
  216. 0, cmd_option_waitforrsp, 0, NULL);
  217. }
  218. /**
  219. * @brief Set Idle Off
  220. *
  221. * @param priv A pointer to wlan_private structure
  222. * @return 0 --success, otherwise fail
  223. */
  224. int libertas_idle_off(wlan_private * priv)
  225. {
  226. wlan_adapter *adapter = priv->adapter;
  227. int ret = 0;
  228. const u8 zeromac[] = { 0, 0, 0, 0, 0, 0 };
  229. int i;
  230. ENTER();
  231. if (adapter->connect_status == libertas_disconnected) {
  232. if (adapter->inframode == wlan802_11infrastructure) {
  233. if (memcmp(adapter->previousbssid, zeromac,
  234. sizeof(zeromac)) != 0) {
  235. lbs_pr_debug(1, "Previous SSID = %s\n",
  236. adapter->previousssid.ssid);
  237. lbs_pr_debug(1, "Previous BSSID = "
  238. "%02x:%02x:%02x:%02x:%02x:%02x:\n",
  239. adapter->previousbssid[0],
  240. adapter->previousbssid[1],
  241. adapter->previousbssid[2],
  242. adapter->previousbssid[3],
  243. adapter->previousbssid[4],
  244. adapter->previousbssid[5]);
  245. i = libertas_find_SSID_in_list(adapter,
  246. &adapter->previousssid,
  247. adapter->previousbssid,
  248. adapter->inframode);
  249. if (i < 0) {
  250. libertas_send_specific_BSSID_scan(priv,
  251. adapter->
  252. previousbssid,
  253. 1);
  254. i = libertas_find_SSID_in_list(adapter,
  255. &adapter->
  256. previousssid,
  257. adapter->
  258. previousbssid,
  259. adapter->
  260. inframode);
  261. }
  262. if (i < 0) {
  263. /* If the BSSID could not be found, try just the SSID */
  264. i = libertas_find_SSID_in_list(adapter,
  265. &adapter->
  266. previousssid, NULL,
  267. adapter->
  268. inframode);
  269. }
  270. if (i < 0) {
  271. libertas_send_specific_SSID_scan(priv,
  272. &adapter->
  273. previousssid,
  274. 1);
  275. i = libertas_find_SSID_in_list(adapter,
  276. &adapter->
  277. previousssid, NULL,
  278. adapter->
  279. inframode);
  280. }
  281. if (i >= 0) {
  282. ret =
  283. wlan_associate(priv,
  284. &adapter->
  285. scantable[i]);
  286. }
  287. }
  288. } else if (adapter->inframode == wlan802_11ibss) {
  289. ret = libertas_prepare_and_send_command(priv,
  290. cmd_802_11_ad_hoc_start,
  291. 0,
  292. cmd_option_waitforrsp,
  293. 0, &adapter->previousssid);
  294. }
  295. }
  296. /* else it is connected */
  297. lbs_pr_debug(1, "\nwlanidle is off");
  298. LEAVE();
  299. return ret;
  300. }
  301. /**
  302. * @brief Set Idle On
  303. *
  304. * @param priv A pointer to wlan_private structure
  305. * @return 0 --success, otherwise fail
  306. */
  307. int libertas_idle_on(wlan_private * priv)
  308. {
  309. wlan_adapter *adapter = priv->adapter;
  310. int ret = 0;
  311. if (adapter->connect_status == libertas_connected) {
  312. if (adapter->inframode == wlan802_11infrastructure) {
  313. lbs_pr_debug(1, "Previous SSID = %s\n",
  314. adapter->previousssid.ssid);
  315. memmove(&adapter->previousssid,
  316. &adapter->curbssparams.ssid,
  317. sizeof(struct WLAN_802_11_SSID));
  318. libertas_send_deauth(priv);
  319. } else if (adapter->inframode == wlan802_11ibss) {
  320. ret = libertas_stop_adhoc_network(priv);
  321. }
  322. }
  323. lbs_pr_debug(1, "\nwlanidle is on");
  324. return ret;
  325. }
  326. /**
  327. * @brief This function prepares command of authenticate.
  328. *
  329. * @param priv A pointer to wlan_private structure
  330. * @param cmd A pointer to cmd_ds_command structure
  331. * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
  332. *
  333. * @return 0 or -1
  334. */
  335. int libertas_cmd_80211_authenticate(wlan_private * priv,
  336. struct cmd_ds_command *cmd,
  337. void *pdata_buf)
  338. {
  339. wlan_adapter *adapter = priv->adapter;
  340. struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
  341. int ret = -1;
  342. u8 *bssid = pdata_buf;
  343. cmd->command = cpu_to_le16(cmd_802_11_authenticate);
  344. cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
  345. + S_DS_GEN);
  346. /* translate auth mode to 802.11 defined wire value */
  347. switch (adapter->secinfo.auth_mode) {
  348. case IW_AUTH_ALG_OPEN_SYSTEM:
  349. pauthenticate->authtype = 0x00;
  350. break;
  351. case IW_AUTH_ALG_SHARED_KEY:
  352. pauthenticate->authtype = 0x01;
  353. break;
  354. case IW_AUTH_ALG_LEAP:
  355. pauthenticate->authtype = 0x80;
  356. break;
  357. default:
  358. lbs_pr_debug(1, "AUTH_CMD: invalid auth alg 0x%X\n",
  359. adapter->secinfo.auth_mode);
  360. goto out;
  361. }
  362. memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
  363. lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n",
  364. bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
  365. ret = 0;
  366. out:
  367. return ret;
  368. }
  369. int libertas_cmd_80211_deauthenticate(wlan_private * priv,
  370. struct cmd_ds_command *cmd)
  371. {
  372. wlan_adapter *adapter = priv->adapter;
  373. struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
  374. ENTER();
  375. cmd->command = cpu_to_le16(cmd_802_11_deauthenticate);
  376. cmd->size =
  377. cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
  378. S_DS_GEN);
  379. /* set AP MAC address */
  380. memmove(dauth->macaddr, adapter->curbssparams.bssid,
  381. ETH_ALEN);
  382. /* Reason code 3 = Station is leaving */
  383. #define REASON_CODE_STA_LEAVING 3
  384. dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
  385. LEAVE();
  386. return 0;
  387. }
  388. int libertas_cmd_80211_associate(wlan_private * priv,
  389. struct cmd_ds_command *cmd, void *pdata_buf)
  390. {
  391. wlan_adapter *adapter = priv->adapter;
  392. struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
  393. int ret = 0;
  394. struct bss_descriptor *pbssdesc;
  395. u8 *card_rates;
  396. u8 *pos;
  397. int card_rates_size;
  398. u16 tmpcap;
  399. struct mrvlietypes_ssidparamset *ssid;
  400. struct mrvlietypes_phyparamset *phy;
  401. struct mrvlietypes_ssparamset *ss;
  402. struct mrvlietypes_ratesparamset *rates;
  403. struct mrvlietypes_rsnparamset *rsn;
  404. ENTER();
  405. pbssdesc = pdata_buf;
  406. pos = (u8 *) passo;
  407. if (!adapter) {
  408. ret = -1;
  409. goto done;
  410. }
  411. cmd->command = cpu_to_le16(cmd_802_11_associate);
  412. /* Save so we know which BSS Desc to use in the response handler */
  413. adapter->pattemptedbssdesc = pbssdesc;
  414. memcpy(passo->peerstaaddr,
  415. pbssdesc->macaddress, sizeof(passo->peerstaaddr));
  416. pos += sizeof(passo->peerstaaddr);
  417. /* set the listen interval */
  418. passo->listeninterval = adapter->listeninterval;
  419. pos += sizeof(passo->capinfo);
  420. pos += sizeof(passo->listeninterval);
  421. pos += sizeof(passo->bcnperiod);
  422. pos += sizeof(passo->dtimperiod);
  423. ssid = (struct mrvlietypes_ssidparamset *) pos;
  424. ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
  425. ssid->header.len = pbssdesc->ssid.ssidlength;
  426. memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len);
  427. pos += sizeof(ssid->header) + ssid->header.len;
  428. ssid->header.len = cpu_to_le16(ssid->header.len);
  429. phy = (struct mrvlietypes_phyparamset *) pos;
  430. phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
  431. phy->header.len = sizeof(phy->fh_ds.dsparamset);
  432. memcpy(&phy->fh_ds.dsparamset,
  433. &pbssdesc->phyparamset.dsparamset.currentchan,
  434. sizeof(phy->fh_ds.dsparamset));
  435. pos += sizeof(phy->header) + phy->header.len;
  436. phy->header.len = cpu_to_le16(phy->header.len);
  437. ss = (struct mrvlietypes_ssparamset *) pos;
  438. ss->header.type = cpu_to_le16(TLV_TYPE_CF);
  439. ss->header.len = sizeof(ss->cf_ibss.cfparamset);
  440. pos += sizeof(ss->header) + ss->header.len;
  441. ss->header.len = cpu_to_le16(ss->header.len);
  442. rates = (struct mrvlietypes_ratesparamset *) pos;
  443. rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
  444. memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
  445. card_rates = libertas_supported_rates;
  446. card_rates_size = sizeof(libertas_supported_rates);
  447. if (get_common_rates(adapter, rates->rates, WLAN_SUPPORTED_RATES,
  448. card_rates, card_rates_size)) {
  449. ret = -1;
  450. goto done;
  451. }
  452. rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
  453. adapter->curbssparams.numofrates = rates->header.len;
  454. pos += sizeof(rates->header) + rates->header.len;
  455. rates->header.len = cpu_to_le16(rates->header.len);
  456. if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
  457. rsn = (struct mrvlietypes_rsnparamset *) pos;
  458. rsn->header.type = (u16) adapter->wpa_ie[0]; /* WPA_IE or WPA2_IE */
  459. rsn->header.type = cpu_to_le16(rsn->header.type);
  460. rsn->header.len = (u16) adapter->wpa_ie[1];
  461. memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len);
  462. lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn,
  463. sizeof(rsn->header) + rsn->header.len);
  464. pos += sizeof(rsn->header) + rsn->header.len;
  465. rsn->header.len = cpu_to_le16(rsn->header.len);
  466. }
  467. /* update curbssparams */
  468. adapter->curbssparams.channel =
  469. (pbssdesc->phyparamset.dsparamset.currentchan);
  470. /* Copy the infra. association rates into Current BSS state structure */
  471. memcpy(&adapter->curbssparams.datarates, &rates->rates,
  472. min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len));
  473. lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len);
  474. /* set IBSS field */
  475. if (pbssdesc->inframode == wlan802_11infrastructure) {
  476. #define CAPINFO_ESS_MODE 1
  477. passo->capinfo.ess = CAPINFO_ESS_MODE;
  478. }
  479. if (libertas_parse_dnld_countryinfo_11d(priv)) {
  480. ret = -1;
  481. goto done;
  482. }
  483. cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
  484. /* set the capability info at last */
  485. memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo));
  486. tmpcap &= CAPINFO_MASK;
  487. lbs_pr_debug(1, "ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
  488. tmpcap, CAPINFO_MASK);
  489. tmpcap = cpu_to_le16(tmpcap);
  490. memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo));
  491. done:
  492. LEAVE();
  493. return ret;
  494. }
  495. int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
  496. struct cmd_ds_command *cmd, void *pssid)
  497. {
  498. wlan_adapter *adapter = priv->adapter;
  499. struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
  500. int ret = 0;
  501. int cmdappendsize = 0;
  502. int i;
  503. u16 tmpcap;
  504. struct bss_descriptor *pbssdesc;
  505. struct WLAN_802_11_SSID *ssid = pssid;
  506. ENTER();
  507. if (!adapter) {
  508. ret = -1;
  509. goto done;
  510. }
  511. cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start);
  512. pbssdesc = &adapter->curbssparams.bssdescriptor;
  513. adapter->pattemptedbssdesc = pbssdesc;
  514. /*
  515. * Fill in the parameters for 2 data structures:
  516. * 1. cmd_ds_802_11_ad_hoc_start command
  517. * 2. adapter->scantable[i]
  518. *
  519. * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
  520. * probe delay, and cap info.
  521. *
  522. * Firmware will fill up beacon period, DTIM, Basic rates
  523. * and operational rates.
  524. */
  525. memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE);
  526. memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength);
  527. lbs_pr_debug(1, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
  528. memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE);
  529. memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength);
  530. pbssdesc->ssid.ssidlength = ssid->ssidlength;
  531. /* set the BSS type */
  532. adhs->bsstype = cmd_bss_type_ibss;
  533. pbssdesc->inframode = wlan802_11ibss;
  534. adhs->beaconperiod = adapter->beaconperiod;
  535. /* set Physical param set */
  536. #define DS_PARA_IE_ID 3
  537. #define DS_PARA_IE_LEN 1
  538. adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
  539. adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
  540. WARN_ON(!adapter->adhocchannel);
  541. lbs_pr_debug(1, "ADHOC_S_CMD: Creating ADHOC on channel %d\n",
  542. adapter->adhocchannel);
  543. adapter->curbssparams.channel = adapter->adhocchannel;
  544. pbssdesc->channel = adapter->adhocchannel;
  545. adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel;
  546. memcpy(&pbssdesc->phyparamset,
  547. &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
  548. /* set IBSS param set */
  549. #define IBSS_PARA_IE_ID 6
  550. #define IBSS_PARA_IE_LEN 2
  551. adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
  552. adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
  553. adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow;
  554. memcpy(&pbssdesc->ssparamset,
  555. &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset));
  556. /* set capability info */
  557. adhs->cap.ess = 0;
  558. adhs->cap.ibss = 1;
  559. pbssdesc->cap.ibss = 1;
  560. /* probedelay */
  561. adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
  562. /* set up privacy in adapter->scantable[i] */
  563. if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) {
  564. #define AD_HOC_CAP_PRIVACY_ON 1
  565. lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus set, privacy to WEP\n");
  566. pbssdesc->privacy = wlan802_11privfilter8021xWEP;
  567. adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
  568. } else {
  569. lbs_pr_debug(1, "ADHOC_S_CMD: WEPstatus NOT set, Setting "
  570. "privacy to ACCEPT ALL\n");
  571. pbssdesc->privacy = wlan802_11privfilteracceptall;
  572. }
  573. memset(adhs->datarate, 0, sizeof(adhs->datarate));
  574. if (adapter->adhoc_grate_enabled) {
  575. memcpy(adhs->datarate, libertas_adhoc_rates_g,
  576. min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_g)));
  577. } else {
  578. memcpy(adhs->datarate, libertas_adhoc_rates_b,
  579. min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_b)));
  580. }
  581. /* Find the last non zero */
  582. for (i = 0; i < sizeof(adhs->datarate) && adhs->datarate[i]; i++) ;
  583. adapter->curbssparams.numofrates = i;
  584. /* Copy the ad-hoc creating rates into Current BSS state structure */
  585. memcpy(&adapter->curbssparams.datarates,
  586. &adhs->datarate, adapter->curbssparams.numofrates);
  587. lbs_pr_debug(1, "ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
  588. adhs->datarate[0], adhs->datarate[1],
  589. adhs->datarate[2], adhs->datarate[3]);
  590. lbs_pr_debug(1, "ADHOC_S_CMD: AD HOC Start command is ready\n");
  591. if (libertas_create_dnld_countryinfo_11d(priv)) {
  592. lbs_pr_debug(1, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
  593. ret = -1;
  594. goto done;
  595. }
  596. cmd->size =
  597. cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start)
  598. + S_DS_GEN + cmdappendsize);
  599. memcpy(&tmpcap, &adhs->cap, sizeof(u16));
  600. tmpcap = cpu_to_le16(tmpcap);
  601. memcpy(&adhs->cap, &tmpcap, sizeof(u16));
  602. ret = 0;
  603. done:
  604. LEAVE();
  605. return ret;
  606. }
  607. int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
  608. struct cmd_ds_command *cmd)
  609. {
  610. cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_stop);
  611. cmd->size = cpu_to_le16(S_DS_GEN);
  612. return 0;
  613. }
  614. int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
  615. struct cmd_ds_command *cmd, void *pdata_buf)
  616. {
  617. wlan_adapter *adapter = priv->adapter;
  618. struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj;
  619. struct bss_descriptor *pbssdesc = pdata_buf;
  620. int cmdappendsize = 0;
  621. int ret = 0;
  622. u8 *card_rates;
  623. int card_rates_size;
  624. u16 tmpcap;
  625. int i;
  626. ENTER();
  627. adapter->pattemptedbssdesc = pbssdesc;
  628. cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join);
  629. padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss;
  630. padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod;
  631. memcpy(&padhocjoin->bssdescriptor.BSSID,
  632. &pbssdesc->macaddress, ETH_ALEN);
  633. memcpy(&padhocjoin->bssdescriptor.SSID,
  634. &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength);
  635. memcpy(&padhocjoin->bssdescriptor.phyparamset,
  636. &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset));
  637. memcpy(&padhocjoin->bssdescriptor.ssparamset,
  638. &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset));
  639. memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo));
  640. tmpcap &= CAPINFO_MASK;
  641. lbs_pr_debug(1, "ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
  642. tmpcap, CAPINFO_MASK);
  643. memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap,
  644. sizeof(struct ieeetypes_capinfo));
  645. /* information on BSSID descriptor passed to FW */
  646. lbs_pr_debug(1,
  647. "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
  648. padhocjoin->bssdescriptor.BSSID[0],
  649. padhocjoin->bssdescriptor.BSSID[1],
  650. padhocjoin->bssdescriptor.BSSID[2],
  651. padhocjoin->bssdescriptor.BSSID[3],
  652. padhocjoin->bssdescriptor.BSSID[4],
  653. padhocjoin->bssdescriptor.BSSID[5],
  654. padhocjoin->bssdescriptor.SSID);
  655. lbs_pr_debug(1, "ADHOC_J_CMD: Data Rate = %x\n",
  656. (u32) padhocjoin->bssdescriptor.datarates);
  657. /* failtimeout */
  658. padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
  659. /* probedelay */
  660. padhocjoin->probedelay =
  661. cpu_to_le16(cmd_scan_probe_delay_time);
  662. /* Copy Data rates from the rates recorded in scan response */
  663. memset(padhocjoin->bssdescriptor.datarates, 0,
  664. sizeof(padhocjoin->bssdescriptor.datarates));
  665. memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates,
  666. min(sizeof(padhocjoin->bssdescriptor.datarates),
  667. sizeof(pbssdesc->datarates)));
  668. card_rates = libertas_supported_rates;
  669. card_rates_size = sizeof(libertas_supported_rates);
  670. adapter->curbssparams.channel = pbssdesc->channel;
  671. if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates,
  672. sizeof(padhocjoin->bssdescriptor.datarates),
  673. card_rates, card_rates_size)) {
  674. lbs_pr_debug(1, "ADHOC_J_CMD: get_common_rates returns error.\n");
  675. ret = -1;
  676. goto done;
  677. }
  678. /* Find the last non zero */
  679. for (i = 0; i < sizeof(padhocjoin->bssdescriptor.datarates)
  680. && padhocjoin->bssdescriptor.datarates[i]; i++) ;
  681. adapter->curbssparams.numofrates = i;
  682. /*
  683. * Copy the adhoc joining rates to Current BSS State structure
  684. */
  685. memcpy(adapter->curbssparams.datarates,
  686. padhocjoin->bssdescriptor.datarates,
  687. adapter->curbssparams.numofrates);
  688. padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow =
  689. cpu_to_le16(pbssdesc->atimwindow);
  690. if (adapter->secinfo.WEPstatus == wlan802_11WEPenabled) {
  691. padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
  692. }
  693. if (adapter->psmode == wlan802_11powermodemax_psp) {
  694. /* wake up first */
  695. enum WLAN_802_11_POWER_MODE Localpsmode;
  696. Localpsmode = wlan802_11powermodecam;
  697. ret = libertas_prepare_and_send_command(priv,
  698. cmd_802_11_ps_mode,
  699. cmd_act_set,
  700. 0, 0, &Localpsmode);
  701. if (ret) {
  702. ret = -1;
  703. goto done;
  704. }
  705. }
  706. if (libertas_parse_dnld_countryinfo_11d(priv)) {
  707. ret = -1;
  708. goto done;
  709. }
  710. cmd->size =
  711. cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join)
  712. + S_DS_GEN + cmdappendsize);
  713. memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap,
  714. sizeof(struct ieeetypes_capinfo));
  715. tmpcap = cpu_to_le16(tmpcap);
  716. memcpy(&padhocjoin->bssdescriptor.cap,
  717. &tmpcap, sizeof(struct ieeetypes_capinfo));
  718. done:
  719. LEAVE();
  720. return ret;
  721. }
  722. int libertas_ret_80211_associate(wlan_private * priv,
  723. struct cmd_ds_command *resp)
  724. {
  725. wlan_adapter *adapter = priv->adapter;
  726. int ret = 0;
  727. union iwreq_data wrqu;
  728. struct ieeetypes_assocrsp *passocrsp;
  729. struct bss_descriptor *pbssdesc;
  730. ENTER();
  731. passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
  732. if (passocrsp->statuscode) {
  733. libertas_mac_event_disconnected(priv);
  734. lbs_pr_debug(1,
  735. "ASSOC_RESP: Association failed, status code = %d\n",
  736. passocrsp->statuscode);
  737. ret = -1;
  738. goto done;
  739. }
  740. lbs_dbg_hex("ASSOC_RESP:", (void *)&resp->params,
  741. le16_to_cpu(resp->size) - S_DS_GEN);
  742. /* Send a Media Connected event, according to the Spec */
  743. adapter->connect_status = libertas_connected;
  744. /* Set the attempted BSSID Index to current */
  745. pbssdesc = adapter->pattemptedbssdesc;
  746. lbs_pr_debug(1, "ASSOC_RESP: %s\n", pbssdesc->ssid.ssid);
  747. /* Set the new SSID to current SSID */
  748. memcpy(&adapter->curbssparams.ssid,
  749. &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
  750. /* Set the new BSSID (AP's MAC address) to current BSSID */
  751. memcpy(adapter->curbssparams.bssid,
  752. pbssdesc->macaddress, ETH_ALEN);
  753. /* Make a copy of current BSSID descriptor */
  754. memcpy(&adapter->curbssparams.bssdescriptor,
  755. pbssdesc, sizeof(struct bss_descriptor));
  756. lbs_pr_debug(1, "ASSOC_RESP: currentpacketfilter is %x\n",
  757. adapter->currentpacketfilter);
  758. adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
  759. adapter->NF[TYPE_RXPD][TYPE_AVG] = 0;
  760. memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
  761. memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
  762. adapter->nextSNRNF = 0;
  763. adapter->numSNRNF = 0;
  764. netif_carrier_on(priv->wlan_dev.netdev);
  765. netif_wake_queue(priv->wlan_dev.netdev);
  766. lbs_pr_debug(1, "ASSOC_RESP: Associated \n");
  767. memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
  768. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  769. wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
  770. done:
  771. LEAVE();
  772. return ret;
  773. }
  774. int libertas_ret_80211_disassociate(wlan_private * priv,
  775. struct cmd_ds_command *resp)
  776. {
  777. ENTER();
  778. libertas_mac_event_disconnected(priv);
  779. LEAVE();
  780. return 0;
  781. }
  782. int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
  783. struct cmd_ds_command *resp)
  784. {
  785. wlan_adapter *adapter = priv->adapter;
  786. int ret = 0;
  787. u16 command = le16_to_cpu(resp->command);
  788. u16 result = le16_to_cpu(resp->result);
  789. struct cmd_ds_802_11_ad_hoc_result *padhocresult;
  790. union iwreq_data wrqu;
  791. struct bss_descriptor *pbssdesc;
  792. ENTER();
  793. padhocresult = &resp->params.result;
  794. lbs_pr_debug(1, "ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size));
  795. lbs_pr_debug(1, "ADHOC_S_RESP: command = %x\n", command);
  796. lbs_pr_debug(1, "ADHOC_S_RESP: result = %x\n", result);
  797. pbssdesc = adapter->pattemptedbssdesc;
  798. /*
  799. * Join result code 0 --> SUCCESS
  800. */
  801. if (result) {
  802. lbs_pr_debug(1, "ADHOC_RESP failed\n");
  803. if (adapter->connect_status == libertas_connected) {
  804. libertas_mac_event_disconnected(priv);
  805. }
  806. memset(&adapter->curbssparams.bssdescriptor,
  807. 0x00, sizeof(adapter->curbssparams.bssdescriptor));
  808. LEAVE();
  809. return -1;
  810. }
  811. /*
  812. * Now the join cmd should be successful
  813. * If BSSID has changed use SSID to compare instead of BSSID
  814. */
  815. lbs_pr_debug(1, "ADHOC_J_RESP %s\n", pbssdesc->ssid.ssid);
  816. /* Send a Media Connected event, according to the Spec */
  817. adapter->connect_status = libertas_connected;
  818. if (command == cmd_ret_802_11_ad_hoc_start) {
  819. /* Update the created network descriptor with the new BSSID */
  820. memcpy(pbssdesc->macaddress,
  821. padhocresult->BSSID, ETH_ALEN);
  822. } else {
  823. /* Make a copy of current BSSID descriptor, only needed for join since
  824. * the current descriptor is already being used for adhoc start
  825. */
  826. memmove(&adapter->curbssparams.bssdescriptor,
  827. pbssdesc, sizeof(struct bss_descriptor));
  828. }
  829. /* Set the BSSID from the joined/started descriptor */
  830. memcpy(&adapter->curbssparams.bssid,
  831. pbssdesc->macaddress, ETH_ALEN);
  832. /* Set the new SSID to current SSID */
  833. memcpy(&adapter->curbssparams.ssid,
  834. &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
  835. netif_carrier_on(priv->wlan_dev.netdev);
  836. netif_wake_queue(priv->wlan_dev.netdev);
  837. memset(&wrqu, 0, sizeof(wrqu));
  838. memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
  839. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  840. wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
  841. lbs_pr_debug(1, "ADHOC_RESP: - Joined/Started Ad Hoc\n");
  842. lbs_pr_debug(1, "ADHOC_RESP: channel = %d\n", adapter->adhocchannel);
  843. lbs_pr_debug(1, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
  844. padhocresult->BSSID[0], padhocresult->BSSID[1],
  845. padhocresult->BSSID[2], padhocresult->BSSID[3],
  846. padhocresult->BSSID[4], padhocresult->BSSID[5]);
  847. LEAVE();
  848. return ret;
  849. }
  850. int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
  851. struct cmd_ds_command *resp)
  852. {
  853. ENTER();
  854. libertas_mac_event_disconnected(priv);
  855. LEAVE();
  856. return 0;
  857. }