join.c 29 KB

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