join.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  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->mode == IW_MODE_INFRA &&
  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->mode == IW_MODE_ADHOC &&
  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->mode == IW_MODE_ADHOC)) {
  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->mode == IW_MODE_INFRA) {
  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->mode);
  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->mode);
  260. }
  261. if (i < 0) {
  262. /* If the BSSID could not be found, try just the SSID */
  263. i = libertas_find_SSID_in_list(adapter,
  264. &adapter->
  265. previousssid, NULL,
  266. adapter->mode);
  267. }
  268. if (i < 0) {
  269. libertas_send_specific_SSID_scan(priv,
  270. &adapter->
  271. previousssid,
  272. 1);
  273. i = libertas_find_SSID_in_list(adapter,
  274. &adapter->
  275. previousssid, NULL,
  276. adapter->mode);
  277. }
  278. if (i >= 0) {
  279. ret =
  280. wlan_associate(priv,
  281. &adapter->
  282. scantable[i]);
  283. }
  284. }
  285. } else if (adapter->mode == IW_MODE_ADHOC) {
  286. ret = libertas_prepare_and_send_command(priv,
  287. cmd_802_11_ad_hoc_start,
  288. 0,
  289. cmd_option_waitforrsp,
  290. 0, &adapter->previousssid);
  291. }
  292. }
  293. /* else it is connected */
  294. lbs_pr_debug(1, "\nwlanidle is off");
  295. LEAVE();
  296. return ret;
  297. }
  298. /**
  299. * @brief Set Idle On
  300. *
  301. * @param priv A pointer to wlan_private structure
  302. * @return 0 --success, otherwise fail
  303. */
  304. int libertas_idle_on(wlan_private * priv)
  305. {
  306. wlan_adapter *adapter = priv->adapter;
  307. int ret = 0;
  308. if (adapter->connect_status == libertas_connected) {
  309. if (adapter->mode == IW_MODE_INFRA) {
  310. lbs_pr_debug(1, "Previous SSID = %s\n",
  311. adapter->previousssid.ssid);
  312. memmove(&adapter->previousssid,
  313. &adapter->curbssparams.ssid,
  314. sizeof(struct WLAN_802_11_SSID));
  315. libertas_send_deauth(priv);
  316. } else if (adapter->mode == IW_MODE_ADHOC) {
  317. ret = libertas_stop_adhoc_network(priv);
  318. }
  319. }
  320. lbs_pr_debug(1, "\nwlanidle is on");
  321. return ret;
  322. }
  323. /**
  324. * @brief This function prepares command of authenticate.
  325. *
  326. * @param priv A pointer to wlan_private structure
  327. * @param cmd A pointer to cmd_ds_command structure
  328. * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
  329. *
  330. * @return 0 or -1
  331. */
  332. int libertas_cmd_80211_authenticate(wlan_private * priv,
  333. struct cmd_ds_command *cmd,
  334. void *pdata_buf)
  335. {
  336. wlan_adapter *adapter = priv->adapter;
  337. struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
  338. int ret = -1;
  339. u8 *bssid = pdata_buf;
  340. cmd->command = cpu_to_le16(cmd_802_11_authenticate);
  341. cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
  342. + S_DS_GEN);
  343. /* translate auth mode to 802.11 defined wire value */
  344. switch (adapter->secinfo.auth_mode) {
  345. case IW_AUTH_ALG_OPEN_SYSTEM:
  346. pauthenticate->authtype = 0x00;
  347. break;
  348. case IW_AUTH_ALG_SHARED_KEY:
  349. pauthenticate->authtype = 0x01;
  350. break;
  351. case IW_AUTH_ALG_LEAP:
  352. pauthenticate->authtype = 0x80;
  353. break;
  354. default:
  355. lbs_pr_debug(1, "AUTH_CMD: invalid auth alg 0x%X\n",
  356. adapter->secinfo.auth_mode);
  357. goto out;
  358. }
  359. memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
  360. lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n",
  361. bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
  362. ret = 0;
  363. out:
  364. return ret;
  365. }
  366. int libertas_cmd_80211_deauthenticate(wlan_private * priv,
  367. struct cmd_ds_command *cmd)
  368. {
  369. wlan_adapter *adapter = priv->adapter;
  370. struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
  371. ENTER();
  372. cmd->command = cpu_to_le16(cmd_802_11_deauthenticate);
  373. cmd->size =
  374. cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
  375. S_DS_GEN);
  376. /* set AP MAC address */
  377. memmove(dauth->macaddr, adapter->curbssparams.bssid,
  378. ETH_ALEN);
  379. /* Reason code 3 = Station is leaving */
  380. #define REASON_CODE_STA_LEAVING 3
  381. dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
  382. LEAVE();
  383. return 0;
  384. }
  385. int libertas_cmd_80211_associate(wlan_private * priv,
  386. struct cmd_ds_command *cmd, void *pdata_buf)
  387. {
  388. wlan_adapter *adapter = priv->adapter;
  389. struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
  390. int ret = 0;
  391. struct bss_descriptor *pbssdesc;
  392. u8 *card_rates;
  393. u8 *pos;
  394. int card_rates_size;
  395. u16 tmpcap;
  396. struct mrvlietypes_ssidparamset *ssid;
  397. struct mrvlietypes_phyparamset *phy;
  398. struct mrvlietypes_ssparamset *ss;
  399. struct mrvlietypes_ratesparamset *rates;
  400. struct mrvlietypes_rsnparamset *rsn;
  401. ENTER();
  402. pbssdesc = pdata_buf;
  403. pos = (u8 *) passo;
  404. if (!adapter) {
  405. ret = -1;
  406. goto done;
  407. }
  408. cmd->command = cpu_to_le16(cmd_802_11_associate);
  409. /* Save so we know which BSS Desc to use in the response handler */
  410. adapter->pattemptedbssdesc = pbssdesc;
  411. memcpy(passo->peerstaaddr,
  412. pbssdesc->macaddress, sizeof(passo->peerstaaddr));
  413. pos += sizeof(passo->peerstaaddr);
  414. /* set the listen interval */
  415. passo->listeninterval = adapter->listeninterval;
  416. pos += sizeof(passo->capinfo);
  417. pos += sizeof(passo->listeninterval);
  418. pos += sizeof(passo->bcnperiod);
  419. pos += sizeof(passo->dtimperiod);
  420. ssid = (struct mrvlietypes_ssidparamset *) pos;
  421. ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
  422. ssid->header.len = pbssdesc->ssid.ssidlength;
  423. memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len);
  424. pos += sizeof(ssid->header) + ssid->header.len;
  425. ssid->header.len = cpu_to_le16(ssid->header.len);
  426. phy = (struct mrvlietypes_phyparamset *) pos;
  427. phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
  428. phy->header.len = sizeof(phy->fh_ds.dsparamset);
  429. memcpy(&phy->fh_ds.dsparamset,
  430. &pbssdesc->phyparamset.dsparamset.currentchan,
  431. sizeof(phy->fh_ds.dsparamset));
  432. pos += sizeof(phy->header) + phy->header.len;
  433. phy->header.len = cpu_to_le16(phy->header.len);
  434. ss = (struct mrvlietypes_ssparamset *) pos;
  435. ss->header.type = cpu_to_le16(TLV_TYPE_CF);
  436. ss->header.len = sizeof(ss->cf_ibss.cfparamset);
  437. pos += sizeof(ss->header) + ss->header.len;
  438. ss->header.len = cpu_to_le16(ss->header.len);
  439. rates = (struct mrvlietypes_ratesparamset *) pos;
  440. rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
  441. memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
  442. card_rates = libertas_supported_rates;
  443. card_rates_size = sizeof(libertas_supported_rates);
  444. if (get_common_rates(adapter, rates->rates, WLAN_SUPPORTED_RATES,
  445. card_rates, card_rates_size)) {
  446. ret = -1;
  447. goto done;
  448. }
  449. rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
  450. adapter->curbssparams.numofrates = rates->header.len;
  451. pos += sizeof(rates->header) + rates->header.len;
  452. rates->header.len = cpu_to_le16(rates->header.len);
  453. if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
  454. rsn = (struct mrvlietypes_rsnparamset *) pos;
  455. rsn->header.type = (u16) adapter->wpa_ie[0]; /* WPA_IE or WPA2_IE */
  456. rsn->header.type = cpu_to_le16(rsn->header.type);
  457. rsn->header.len = (u16) adapter->wpa_ie[1];
  458. memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len);
  459. lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn,
  460. sizeof(rsn->header) + rsn->header.len);
  461. pos += sizeof(rsn->header) + rsn->header.len;
  462. rsn->header.len = cpu_to_le16(rsn->header.len);
  463. }
  464. /* update curbssparams */
  465. adapter->curbssparams.channel =
  466. (pbssdesc->phyparamset.dsparamset.currentchan);
  467. /* Copy the infra. association rates into Current BSS state structure */
  468. memcpy(&adapter->curbssparams.datarates, &rates->rates,
  469. min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len));
  470. lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len);
  471. /* set IBSS field */
  472. if (pbssdesc->mode == IW_MODE_INFRA) {
  473. #define CAPINFO_ESS_MODE 1
  474. passo->capinfo.ess = CAPINFO_ESS_MODE;
  475. }
  476. if (libertas_parse_dnld_countryinfo_11d(priv)) {
  477. ret = -1;
  478. goto done;
  479. }
  480. cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
  481. /* set the capability info at last */
  482. memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo));
  483. tmpcap &= CAPINFO_MASK;
  484. lbs_pr_debug(1, "ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
  485. tmpcap, CAPINFO_MASK);
  486. tmpcap = cpu_to_le16(tmpcap);
  487. memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo));
  488. done:
  489. LEAVE();
  490. return ret;
  491. }
  492. int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
  493. struct cmd_ds_command *cmd, void *pssid)
  494. {
  495. wlan_adapter *adapter = priv->adapter;
  496. struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
  497. int ret = 0;
  498. int cmdappendsize = 0;
  499. int i;
  500. u16 tmpcap;
  501. struct bss_descriptor *pbssdesc;
  502. struct WLAN_802_11_SSID *ssid = pssid;
  503. ENTER();
  504. if (!adapter) {
  505. ret = -1;
  506. goto done;
  507. }
  508. cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start);
  509. pbssdesc = &adapter->curbssparams.bssdescriptor;
  510. adapter->pattemptedbssdesc = pbssdesc;
  511. /*
  512. * Fill in the parameters for 2 data structures:
  513. * 1. cmd_ds_802_11_ad_hoc_start command
  514. * 2. adapter->scantable[i]
  515. *
  516. * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
  517. * probe delay, and cap info.
  518. *
  519. * Firmware will fill up beacon period, DTIM, Basic rates
  520. * and operational rates.
  521. */
  522. memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE);
  523. memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength);
  524. lbs_pr_debug(1, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
  525. memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE);
  526. memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength);
  527. pbssdesc->ssid.ssidlength = ssid->ssidlength;
  528. /* set the BSS type */
  529. adhs->bsstype = cmd_bss_type_ibss;
  530. pbssdesc->mode = IW_MODE_ADHOC;
  531. adhs->beaconperiod = adapter->beaconperiod;
  532. /* set Physical param set */
  533. #define DS_PARA_IE_ID 3
  534. #define DS_PARA_IE_LEN 1
  535. adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
  536. adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
  537. WARN_ON(!adapter->adhocchannel);
  538. lbs_pr_debug(1, "ADHOC_S_CMD: Creating ADHOC on channel %d\n",
  539. adapter->adhocchannel);
  540. adapter->curbssparams.channel = adapter->adhocchannel;
  541. pbssdesc->channel = adapter->adhocchannel;
  542. adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel;
  543. memcpy(&pbssdesc->phyparamset,
  544. &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
  545. /* set IBSS param set */
  546. #define IBSS_PARA_IE_ID 6
  547. #define IBSS_PARA_IE_LEN 2
  548. adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
  549. adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
  550. adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow;
  551. memcpy(&pbssdesc->ssparamset,
  552. &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset));
  553. /* set capability info */
  554. adhs->cap.ess = 0;
  555. adhs->cap.ibss = 1;
  556. pbssdesc->cap.ibss = 1;
  557. /* probedelay */
  558. adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
  559. /* set up privacy in adapter->scantable[i] */
  560. if (adapter->secinfo.wep_enabled) {
  561. lbs_pr_debug(1, "ADHOC_S_CMD: WEP enabled, setting privacy on\n");
  562. pbssdesc->privacy = wlan802_11privfilter8021xWEP;
  563. adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
  564. } else {
  565. lbs_pr_debug(1, "ADHOC_S_CMD: WEP disabled, setting privacy off\n");
  566. pbssdesc->privacy = wlan802_11privfilteracceptall;
  567. }
  568. memset(adhs->datarate, 0, sizeof(adhs->datarate));
  569. if (adapter->adhoc_grate_enabled) {
  570. memcpy(adhs->datarate, libertas_adhoc_rates_g,
  571. min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_g)));
  572. } else {
  573. memcpy(adhs->datarate, libertas_adhoc_rates_b,
  574. min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_b)));
  575. }
  576. /* Find the last non zero */
  577. for (i = 0; i < sizeof(adhs->datarate) && adhs->datarate[i]; i++) ;
  578. adapter->curbssparams.numofrates = i;
  579. /* Copy the ad-hoc creating rates into Current BSS state structure */
  580. memcpy(&adapter->curbssparams.datarates,
  581. &adhs->datarate, adapter->curbssparams.numofrates);
  582. lbs_pr_debug(1, "ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
  583. adhs->datarate[0], adhs->datarate[1],
  584. adhs->datarate[2], adhs->datarate[3]);
  585. lbs_pr_debug(1, "ADHOC_S_CMD: AD HOC Start command is ready\n");
  586. if (libertas_create_dnld_countryinfo_11d(priv)) {
  587. lbs_pr_debug(1, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
  588. ret = -1;
  589. goto done;
  590. }
  591. cmd->size =
  592. cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start)
  593. + S_DS_GEN + cmdappendsize);
  594. memcpy(&tmpcap, &adhs->cap, sizeof(u16));
  595. tmpcap = cpu_to_le16(tmpcap);
  596. memcpy(&adhs->cap, &tmpcap, sizeof(u16));
  597. ret = 0;
  598. done:
  599. LEAVE();
  600. return ret;
  601. }
  602. int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
  603. struct cmd_ds_command *cmd)
  604. {
  605. cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_stop);
  606. cmd->size = cpu_to_le16(S_DS_GEN);
  607. return 0;
  608. }
  609. int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
  610. struct cmd_ds_command *cmd, void *pdata_buf)
  611. {
  612. wlan_adapter *adapter = priv->adapter;
  613. struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj;
  614. struct bss_descriptor *pbssdesc = pdata_buf;
  615. int cmdappendsize = 0;
  616. int ret = 0;
  617. u8 *card_rates;
  618. int card_rates_size;
  619. u16 tmpcap;
  620. int i;
  621. ENTER();
  622. adapter->pattemptedbssdesc = pbssdesc;
  623. cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join);
  624. padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss;
  625. padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod;
  626. memcpy(&padhocjoin->bssdescriptor.BSSID,
  627. &pbssdesc->macaddress, ETH_ALEN);
  628. memcpy(&padhocjoin->bssdescriptor.SSID,
  629. &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength);
  630. memcpy(&padhocjoin->bssdescriptor.phyparamset,
  631. &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset));
  632. memcpy(&padhocjoin->bssdescriptor.ssparamset,
  633. &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset));
  634. memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo));
  635. tmpcap &= CAPINFO_MASK;
  636. lbs_pr_debug(1, "ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
  637. tmpcap, CAPINFO_MASK);
  638. memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap,
  639. sizeof(struct ieeetypes_capinfo));
  640. /* information on BSSID descriptor passed to FW */
  641. lbs_pr_debug(1,
  642. "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
  643. padhocjoin->bssdescriptor.BSSID[0],
  644. padhocjoin->bssdescriptor.BSSID[1],
  645. padhocjoin->bssdescriptor.BSSID[2],
  646. padhocjoin->bssdescriptor.BSSID[3],
  647. padhocjoin->bssdescriptor.BSSID[4],
  648. padhocjoin->bssdescriptor.BSSID[5],
  649. padhocjoin->bssdescriptor.SSID);
  650. lbs_pr_debug(1, "ADHOC_J_CMD: Data Rate = %x\n",
  651. (u32) padhocjoin->bssdescriptor.datarates);
  652. /* failtimeout */
  653. padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
  654. /* probedelay */
  655. padhocjoin->probedelay =
  656. cpu_to_le16(cmd_scan_probe_delay_time);
  657. /* Copy Data rates from the rates recorded in scan response */
  658. memset(padhocjoin->bssdescriptor.datarates, 0,
  659. sizeof(padhocjoin->bssdescriptor.datarates));
  660. memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates,
  661. min(sizeof(padhocjoin->bssdescriptor.datarates),
  662. sizeof(pbssdesc->datarates)));
  663. card_rates = libertas_supported_rates;
  664. card_rates_size = sizeof(libertas_supported_rates);
  665. adapter->curbssparams.channel = pbssdesc->channel;
  666. if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates,
  667. sizeof(padhocjoin->bssdescriptor.datarates),
  668. card_rates, card_rates_size)) {
  669. lbs_pr_debug(1, "ADHOC_J_CMD: get_common_rates returns error.\n");
  670. ret = -1;
  671. goto done;
  672. }
  673. /* Find the last non zero */
  674. for (i = 0; i < sizeof(padhocjoin->bssdescriptor.datarates)
  675. && padhocjoin->bssdescriptor.datarates[i]; i++) ;
  676. adapter->curbssparams.numofrates = i;
  677. /*
  678. * Copy the adhoc joining rates to Current BSS State structure
  679. */
  680. memcpy(adapter->curbssparams.datarates,
  681. padhocjoin->bssdescriptor.datarates,
  682. adapter->curbssparams.numofrates);
  683. padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow =
  684. cpu_to_le16(pbssdesc->atimwindow);
  685. if (adapter->secinfo.wep_enabled) {
  686. padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
  687. }
  688. if (adapter->psmode == wlan802_11powermodemax_psp) {
  689. /* wake up first */
  690. enum WLAN_802_11_POWER_MODE Localpsmode;
  691. Localpsmode = wlan802_11powermodecam;
  692. ret = libertas_prepare_and_send_command(priv,
  693. cmd_802_11_ps_mode,
  694. cmd_act_set,
  695. 0, 0, &Localpsmode);
  696. if (ret) {
  697. ret = -1;
  698. goto done;
  699. }
  700. }
  701. if (libertas_parse_dnld_countryinfo_11d(priv)) {
  702. ret = -1;
  703. goto done;
  704. }
  705. cmd->size =
  706. cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join)
  707. + S_DS_GEN + cmdappendsize);
  708. memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap,
  709. sizeof(struct ieeetypes_capinfo));
  710. tmpcap = cpu_to_le16(tmpcap);
  711. memcpy(&padhocjoin->bssdescriptor.cap,
  712. &tmpcap, sizeof(struct ieeetypes_capinfo));
  713. done:
  714. LEAVE();
  715. return ret;
  716. }
  717. int libertas_ret_80211_associate(wlan_private * priv,
  718. struct cmd_ds_command *resp)
  719. {
  720. wlan_adapter *adapter = priv->adapter;
  721. int ret = 0;
  722. union iwreq_data wrqu;
  723. struct ieeetypes_assocrsp *passocrsp;
  724. struct bss_descriptor *pbssdesc;
  725. ENTER();
  726. passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
  727. if (passocrsp->statuscode) {
  728. libertas_mac_event_disconnected(priv);
  729. lbs_pr_debug(1,
  730. "ASSOC_RESP: Association failed, status code = %d\n",
  731. passocrsp->statuscode);
  732. ret = -1;
  733. goto done;
  734. }
  735. lbs_dbg_hex("ASSOC_RESP:", (void *)&resp->params,
  736. le16_to_cpu(resp->size) - S_DS_GEN);
  737. /* Send a Media Connected event, according to the Spec */
  738. adapter->connect_status = libertas_connected;
  739. /* Set the attempted BSSID Index to current */
  740. pbssdesc = adapter->pattemptedbssdesc;
  741. lbs_pr_debug(1, "ASSOC_RESP: %s\n", pbssdesc->ssid.ssid);
  742. /* Set the new SSID to current SSID */
  743. memcpy(&adapter->curbssparams.ssid,
  744. &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
  745. /* Set the new BSSID (AP's MAC address) to current BSSID */
  746. memcpy(adapter->curbssparams.bssid,
  747. pbssdesc->macaddress, ETH_ALEN);
  748. /* Make a copy of current BSSID descriptor */
  749. memcpy(&adapter->curbssparams.bssdescriptor,
  750. pbssdesc, sizeof(struct bss_descriptor));
  751. lbs_pr_debug(1, "ASSOC_RESP: currentpacketfilter is %x\n",
  752. adapter->currentpacketfilter);
  753. adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
  754. adapter->NF[TYPE_RXPD][TYPE_AVG] = 0;
  755. memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
  756. memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
  757. adapter->nextSNRNF = 0;
  758. adapter->numSNRNF = 0;
  759. netif_carrier_on(priv->wlan_dev.netdev);
  760. netif_wake_queue(priv->wlan_dev.netdev);
  761. lbs_pr_debug(1, "ASSOC_RESP: Associated \n");
  762. memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
  763. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  764. wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
  765. done:
  766. LEAVE();
  767. return ret;
  768. }
  769. int libertas_ret_80211_disassociate(wlan_private * priv,
  770. struct cmd_ds_command *resp)
  771. {
  772. ENTER();
  773. libertas_mac_event_disconnected(priv);
  774. LEAVE();
  775. return 0;
  776. }
  777. int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
  778. struct cmd_ds_command *resp)
  779. {
  780. wlan_adapter *adapter = priv->adapter;
  781. int ret = 0;
  782. u16 command = le16_to_cpu(resp->command);
  783. u16 result = le16_to_cpu(resp->result);
  784. struct cmd_ds_802_11_ad_hoc_result *padhocresult;
  785. union iwreq_data wrqu;
  786. struct bss_descriptor *pbssdesc;
  787. ENTER();
  788. padhocresult = &resp->params.result;
  789. lbs_pr_debug(1, "ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size));
  790. lbs_pr_debug(1, "ADHOC_S_RESP: command = %x\n", command);
  791. lbs_pr_debug(1, "ADHOC_S_RESP: result = %x\n", result);
  792. pbssdesc = adapter->pattemptedbssdesc;
  793. /*
  794. * Join result code 0 --> SUCCESS
  795. */
  796. if (result) {
  797. lbs_pr_debug(1, "ADHOC_RESP failed\n");
  798. if (adapter->connect_status == libertas_connected) {
  799. libertas_mac_event_disconnected(priv);
  800. }
  801. memset(&adapter->curbssparams.bssdescriptor,
  802. 0x00, sizeof(adapter->curbssparams.bssdescriptor));
  803. LEAVE();
  804. return -1;
  805. }
  806. /*
  807. * Now the join cmd should be successful
  808. * If BSSID has changed use SSID to compare instead of BSSID
  809. */
  810. lbs_pr_debug(1, "ADHOC_J_RESP %s\n", pbssdesc->ssid.ssid);
  811. /* Send a Media Connected event, according to the Spec */
  812. adapter->connect_status = libertas_connected;
  813. if (command == cmd_ret_802_11_ad_hoc_start) {
  814. /* Update the created network descriptor with the new BSSID */
  815. memcpy(pbssdesc->macaddress,
  816. padhocresult->BSSID, ETH_ALEN);
  817. } else {
  818. /* Make a copy of current BSSID descriptor, only needed for join since
  819. * the current descriptor is already being used for adhoc start
  820. */
  821. memmove(&adapter->curbssparams.bssdescriptor,
  822. pbssdesc, sizeof(struct bss_descriptor));
  823. }
  824. /* Set the BSSID from the joined/started descriptor */
  825. memcpy(&adapter->curbssparams.bssid,
  826. pbssdesc->macaddress, ETH_ALEN);
  827. /* Set the new SSID to current SSID */
  828. memcpy(&adapter->curbssparams.ssid,
  829. &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
  830. netif_carrier_on(priv->wlan_dev.netdev);
  831. netif_wake_queue(priv->wlan_dev.netdev);
  832. memset(&wrqu, 0, sizeof(wrqu));
  833. memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
  834. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  835. wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
  836. lbs_pr_debug(1, "ADHOC_RESP: - Joined/Started Ad Hoc\n");
  837. lbs_pr_debug(1, "ADHOC_RESP: channel = %d\n", adapter->adhocchannel);
  838. lbs_pr_debug(1, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
  839. padhocresult->BSSID[0], padhocresult->BSSID[1],
  840. padhocresult->BSSID[2], padhocresult->BSSID[3],
  841. padhocresult->BSSID[4], padhocresult->BSSID[5]);
  842. LEAVE();
  843. return ret;
  844. }
  845. int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
  846. struct cmd_ds_command *resp)
  847. {
  848. ENTER();
  849. libertas_mac_event_disconnected(priv);
  850. LEAVE();
  851. return 0;
  852. }