wl_cfgp2p.c 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818
  1. /*
  2. * Linux cfgp2p driver
  3. *
  4. * Copyright (C) 1999-2015, Broadcom Corporation
  5. *
  6. * Unless you and Broadcom execute a separate written software license
  7. * agreement governing use of this software, this software is licensed to you
  8. * under the terms of the GNU General Public License version 2 (the "GPL"),
  9. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  10. * following added to such license:
  11. *
  12. * As a special exception, the copyright holders of this software give you
  13. * permission to link this software with independent modules, and to copy and
  14. * distribute the resulting executable under terms of your choice, provided that
  15. * you also meet, for each linked independent module, the terms and conditions of
  16. * the license of that module. An independent module is a module which is not
  17. * derived from this software. The special exception does not apply to any
  18. * modifications of the software.
  19. *
  20. * Notwithstanding the above, under no circumstances may you combine this
  21. * software in any way with any other Broadcom software provided under a license
  22. * other than the GPL, without Broadcom's express prior written consent.
  23. *
  24. * $Id: wl_cfgp2p.c 584255 2015-09-04 14:41:49Z $
  25. *
  26. */
  27. #include <typedefs.h>
  28. #include <linuxver.h>
  29. #include <osl.h>
  30. #include <linux/kernel.h>
  31. #include <linux/kthread.h>
  32. #include <linux/netdevice.h>
  33. #include <linux/etherdevice.h>
  34. #include <linux/types.h>
  35. #include <linux/string.h>
  36. #include <linux/timer.h>
  37. #include <linux/if_arp.h>
  38. #include <asm/uaccess.h>
  39. #include <bcmutils.h>
  40. #include <bcmendian.h>
  41. #include <proto/ethernet.h>
  42. #include <proto/802.11.h>
  43. #include <net/rtnetlink.h>
  44. #include <wl_cfg80211.h>
  45. #include <wl_cfgp2p.h>
  46. #include <wldev_common.h>
  47. #include <wl_android.h>
  48. static s8 scanparambuf[WLC_IOCTL_SMLEN];
  49. static s8 g_mgmt_ie_buf[2048];
  50. static bool
  51. wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
  52. static u32
  53. wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
  54. s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd);
  55. static s32 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  56. struct wireless_dev *wdev, bool notify);
  57. #if defined(WL_ENABLE_P2P_IF)
  58. static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
  59. static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
  60. static int wl_cfgp2p_if_open(struct net_device *net);
  61. static int wl_cfgp2p_if_stop(struct net_device *net);
  62. static const struct net_device_ops wl_cfgp2p_if_ops = {
  63. .ndo_open = wl_cfgp2p_if_open,
  64. .ndo_stop = wl_cfgp2p_if_stop,
  65. .ndo_do_ioctl = wl_cfgp2p_do_ioctl,
  66. .ndo_start_xmit = wl_cfgp2p_start_xmit,
  67. };
  68. #endif /* WL_ENABLE_P2P_IF */
  69. #if defined(WL_NEWCFG_PRIVCMD_SUPPORT)
  70. static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
  71. static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
  72. static int wl_cfgp2p_if_dummy(struct net_device *net)
  73. {
  74. return 0;
  75. }
  76. static const struct net_device_ops wl_cfgp2p_if_ops = {
  77. .ndo_open = wl_cfgp2p_if_dummy,
  78. .ndo_stop = wl_cfgp2p_if_dummy,
  79. .ndo_do_ioctl = wl_cfgp2p_do_ioctl,
  80. .ndo_start_xmit = wl_cfgp2p_start_xmit,
  81. };
  82. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  83. bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len)
  84. {
  85. wifi_p2p_pub_act_frame_t *pact_frm;
  86. if (frame == NULL)
  87. return false;
  88. pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
  89. if (frame_len < sizeof(wifi_p2p_pub_act_frame_t) -1)
  90. return false;
  91. if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
  92. pact_frm->action == P2P_PUB_AF_ACTION &&
  93. pact_frm->oui_type == P2P_VER &&
  94. memcmp(pact_frm->oui, P2P_OUI, sizeof(pact_frm->oui)) == 0) {
  95. return true;
  96. }
  97. return false;
  98. }
  99. bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len)
  100. {
  101. wifi_p2p_action_frame_t *act_frm;
  102. if (frame == NULL)
  103. return false;
  104. act_frm = (wifi_p2p_action_frame_t *)frame;
  105. if (frame_len < sizeof(wifi_p2p_action_frame_t) -1)
  106. return false;
  107. if (act_frm->category == P2P_AF_CATEGORY &&
  108. act_frm->type == P2P_VER &&
  109. memcmp(act_frm->OUI, P2P_OUI, DOT11_OUI_LEN) == 0) {
  110. return true;
  111. }
  112. return false;
  113. }
  114. #define GAS_RESP_LEN 2
  115. #define DOUBLE_TLV_BODY_OFF 4
  116. #define GAS_RESP_OFFSET 4
  117. #define GAS_CRESP_OFFSET 5
  118. bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len)
  119. {
  120. bcm_tlv_t *ie = (bcm_tlv_t *)data;
  121. u8 *frame = NULL;
  122. u16 id, flen;
  123. /* Skipped first ANQP Element, if frame has anqp elemnt */
  124. ie = bcm_parse_tlvs(ie, (int)len, DOT11_MNG_ADVERTISEMENT_ID);
  125. if (ie == NULL)
  126. return false;
  127. frame = (uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
  128. id = ((u16) (((frame)[1] << 8) | (frame)[0]));
  129. flen = ((u16) (((frame)[3] << 8) | (frame)[2]));
  130. /* If the contents match the OUI and the type */
  131. if (flen >= WFA_OUI_LEN + 1 &&
  132. id == P2PSD_GAS_NQP_INFOID &&
  133. !bcmp(&frame[DOUBLE_TLV_BODY_OFF], (const uint8*)WFA_OUI, WFA_OUI_LEN) &&
  134. subtype == frame[DOUBLE_TLV_BODY_OFF+WFA_OUI_LEN]) {
  135. return true;
  136. }
  137. return false;
  138. }
  139. bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len)
  140. {
  141. wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
  142. if (frame == NULL)
  143. return false;
  144. sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
  145. if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1))
  146. return false;
  147. if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
  148. return false;
  149. if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
  150. sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP ||
  151. sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ ||
  152. sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
  153. return true;
  154. else
  155. return false;
  156. }
  157. bool wl_cfgp2p_is_p2p_gas_action(void *frame, u32 frame_len)
  158. {
  159. wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
  160. if (frame == NULL)
  161. return false;
  162. sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
  163. if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1))
  164. return false;
  165. if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
  166. return false;
  167. if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ)
  168. return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE,
  169. (u8 *)sd_act_frm->query_data,
  170. frame_len);
  171. else
  172. return false;
  173. }
  174. void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel)
  175. {
  176. wifi_p2p_pub_act_frame_t *pact_frm;
  177. wifi_p2p_action_frame_t *act_frm;
  178. wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
  179. if (!frame || frame_len <= 2)
  180. return;
  181. if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
  182. pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
  183. switch (pact_frm->subtype) {
  184. case P2P_PAF_GON_REQ:
  185. CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame,"
  186. " channel=%d\n", (tx)? "TX": "RX", channel));
  187. break;
  188. case P2P_PAF_GON_RSP:
  189. CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame,"
  190. " channel=%d\n", (tx)? "TX": "RX", channel));
  191. break;
  192. case P2P_PAF_GON_CONF:
  193. CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame,"
  194. " channel=%d\n", (tx)? "TX": "RX", channel));
  195. break;
  196. case P2P_PAF_INVITE_REQ:
  197. CFGP2P_ACTION(("%s P2P Invitation Request Frame,"
  198. " channel=%d\n", (tx)? "TX": "RX", channel));
  199. break;
  200. case P2P_PAF_INVITE_RSP:
  201. CFGP2P_ACTION(("%s P2P Invitation Response Frame,"
  202. " channel=%d\n", (tx)? "TX": "RX", channel));
  203. break;
  204. case P2P_PAF_DEVDIS_REQ:
  205. CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame,"
  206. " channel=%d\n", (tx)? "TX": "RX", channel));
  207. break;
  208. case P2P_PAF_DEVDIS_RSP:
  209. CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame,"
  210. " channel=%d\n", (tx)? "TX": "RX", channel));
  211. break;
  212. case P2P_PAF_PROVDIS_REQ:
  213. CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame,"
  214. " channel=%d\n", (tx)? "TX": "RX", channel));
  215. break;
  216. case P2P_PAF_PROVDIS_RSP:
  217. CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame,"
  218. " channel=%d\n", (tx)? "TX": "RX", channel));
  219. break;
  220. default:
  221. CFGP2P_ACTION(("%s Unknown P2P Public Action Frame,"
  222. " channel=%d\n", (tx)? "TX": "RX", channel));
  223. }
  224. } else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) {
  225. act_frm = (wifi_p2p_action_frame_t *)frame;
  226. switch (act_frm->subtype) {
  227. case P2P_AF_NOTICE_OF_ABSENCE:
  228. CFGP2P_ACTION(("%s P2P Notice of Absence Frame,"
  229. " channel=%d\n", (tx)? "TX": "RX", channel));
  230. break;
  231. case P2P_AF_PRESENCE_REQ:
  232. CFGP2P_ACTION(("%s P2P Presence Request Frame,"
  233. " channel=%d\n", (tx)? "TX": "RX", channel));
  234. break;
  235. case P2P_AF_PRESENCE_RSP:
  236. CFGP2P_ACTION(("%s P2P Presence Response Frame,"
  237. " channel=%d\n", (tx)? "TX": "RX", channel));
  238. break;
  239. case P2P_AF_GO_DISC_REQ:
  240. CFGP2P_ACTION(("%s P2P Discoverability Request Frame,"
  241. " channel=%d\n", (tx)? "TX": "RX", channel));
  242. break;
  243. default:
  244. CFGP2P_ACTION(("%s Unknown P2P Action Frame,"
  245. " channel=%d\n", (tx)? "TX": "RX", channel));
  246. }
  247. } else if (wl_cfgp2p_is_gas_action(frame, frame_len)) {
  248. sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
  249. switch (sd_act_frm->action) {
  250. case P2PSD_ACTION_ID_GAS_IREQ:
  251. CFGP2P_ACTION(("%s P2P GAS Initial Request,"
  252. " channel=%d\n", (tx)? "TX" : "RX", channel));
  253. break;
  254. case P2PSD_ACTION_ID_GAS_IRESP:
  255. CFGP2P_ACTION(("%s P2P GAS Initial Response,"
  256. " channel=%d\n", (tx)? "TX" : "RX", channel));
  257. break;
  258. case P2PSD_ACTION_ID_GAS_CREQ:
  259. CFGP2P_ACTION(("%s P2P GAS Comback Request,"
  260. " channel=%d\n", (tx)? "TX" : "RX", channel));
  261. break;
  262. case P2PSD_ACTION_ID_GAS_CRESP:
  263. CFGP2P_ACTION(("%s P2P GAS Comback Response,"
  264. " channel=%d\n", (tx)? "TX" : "RX", channel));
  265. break;
  266. default:
  267. CFGP2P_ACTION(("%s Unknown P2P GAS Frame,"
  268. " channel=%d\n", (tx)? "TX" : "RX", channel));
  269. }
  270. }
  271. }
  272. /*
  273. * Initialize variables related to P2P
  274. *
  275. */
  276. s32
  277. wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg)
  278. {
  279. if (!(cfg->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) {
  280. CFGP2P_ERR(("struct p2p_info allocation failed\n"));
  281. return -ENOMEM;
  282. }
  283. #define INIT_IE(IE_TYPE, BSS_TYPE) \
  284. do { \
  285. memset(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \
  286. sizeof(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \
  287. wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \
  288. } while (0);
  289. INIT_IE(probe_req, P2PAPI_BSSCFG_PRIMARY);
  290. INIT_IE(probe_res, P2PAPI_BSSCFG_PRIMARY);
  291. INIT_IE(assoc_req, P2PAPI_BSSCFG_PRIMARY);
  292. INIT_IE(assoc_res, P2PAPI_BSSCFG_PRIMARY);
  293. INIT_IE(beacon, P2PAPI_BSSCFG_PRIMARY);
  294. INIT_IE(probe_req, P2PAPI_BSSCFG_DEVICE);
  295. INIT_IE(probe_res, P2PAPI_BSSCFG_DEVICE);
  296. INIT_IE(assoc_req, P2PAPI_BSSCFG_DEVICE);
  297. INIT_IE(assoc_res, P2PAPI_BSSCFG_DEVICE);
  298. INIT_IE(beacon, P2PAPI_BSSCFG_DEVICE);
  299. INIT_IE(probe_req, P2PAPI_BSSCFG_CONNECTION);
  300. INIT_IE(probe_res, P2PAPI_BSSCFG_CONNECTION);
  301. INIT_IE(assoc_req, P2PAPI_BSSCFG_CONNECTION);
  302. INIT_IE(assoc_res, P2PAPI_BSSCFG_CONNECTION);
  303. INIT_IE(beacon, P2PAPI_BSSCFG_CONNECTION);
  304. #undef INIT_IE
  305. wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY) = bcmcfg_to_prmry_ndev(cfg);
  306. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY) = 0;
  307. wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
  308. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
  309. wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION) = NULL;
  310. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION) = 0;
  311. return BCME_OK;
  312. }
  313. /*
  314. * Deinitialize variables related to P2P
  315. *
  316. */
  317. void
  318. wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg)
  319. {
  320. CFGP2P_DBG(("In\n"));
  321. if (cfg->p2p) {
  322. kfree(cfg->p2p);
  323. cfg->p2p = NULL;
  324. }
  325. cfg->p2p_supported = 0;
  326. }
  327. /*
  328. * Set P2P functions into firmware
  329. */
  330. s32
  331. wl_cfgp2p_set_firm_p2p(struct bcm_cfg80211 *cfg)
  332. {
  333. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  334. struct ether_addr null_eth_addr = { { 0, 0, 0, 0, 0, 0 } };
  335. s32 ret = BCME_OK;
  336. s32 val = 0;
  337. /* Do we have to check whether APSTA is enabled or not ? */
  338. ret = wldev_iovar_getint(ndev, "apsta", &val);
  339. if (ret < 0) {
  340. CFGP2P_ERR(("get apsta error %d\n", ret));
  341. return ret;
  342. }
  343. if (val == 0) {
  344. val = 1;
  345. ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
  346. if (ret < 0) {
  347. CFGP2P_ERR(("WLC_DOWN error %d\n", ret));
  348. return ret;
  349. }
  350. wldev_iovar_setint(ndev, "apsta", val);
  351. ret = wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
  352. if (ret < 0) {
  353. CFGP2P_ERR(("WLC_UP error %d\n", ret));
  354. return ret;
  355. }
  356. }
  357. /* In case of COB type, firmware has default mac address
  358. * After Initializing firmware, we have to set current mac address to
  359. * firmware for P2P device address
  360. */
  361. ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr,
  362. sizeof(null_eth_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &cfg->ioctl_buf_sync);
  363. if (ret && ret != BCME_UNSUPPORTED) {
  364. CFGP2P_ERR(("failed to update device address ret %d\n", ret));
  365. }
  366. return ret;
  367. }
  368. /* Create a new P2P BSS.
  369. * Parameters:
  370. * @mac : MAC address of the BSS to create
  371. * @if_type : interface type: WL_P2P_IF_GO or WL_P2P_IF_CLIENT
  372. * @chspec : chspec to use if creating a GO BSS.
  373. * Returns 0 if success.
  374. */
  375. s32
  376. wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
  377. chanspec_t chspec)
  378. {
  379. wl_p2p_if_t ifreq;
  380. s32 err;
  381. u32 scb_timeout = WL_SCB_TIMEOUT;
  382. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  383. ifreq.type = if_type;
  384. ifreq.chspec = chspec;
  385. memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
  386. CFGP2P_DBG(("---cfg p2p_ifadd "MACDBG" %s %u\n",
  387. MAC2STRDBG(ifreq.addr.octet),
  388. (if_type == WL_P2P_IF_GO) ? "go" : "client",
  389. (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
  390. err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
  391. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  392. if (unlikely(err < 0))
  393. printk("'cfg p2p_ifadd' error %d\n", err);
  394. else if (if_type == WL_P2P_IF_GO) {
  395. err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
  396. if (unlikely(err < 0))
  397. printk("'cfg scb_timeout' error %d\n", err);
  398. }
  399. return err;
  400. }
  401. /* Disable a P2P BSS.
  402. * Parameters:
  403. * @mac : MAC address of the BSS to disable
  404. * Returns 0 if success.
  405. */
  406. s32
  407. wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
  408. {
  409. s32 ret;
  410. struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
  411. CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdis "MACDBG"\n",
  412. netdev->ifindex, MAC2STRDBG(mac->octet)));
  413. ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
  414. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  415. if (unlikely(ret < 0)) {
  416. printk("'cfg p2p_ifdis' error %d\n", ret);
  417. }
  418. return ret;
  419. }
  420. /* Delete a P2P BSS.
  421. * Parameters:
  422. * @mac : MAC address of the BSS to delete
  423. * Returns 0 if success.
  424. */
  425. s32
  426. wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
  427. {
  428. s32 ret;
  429. struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
  430. CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdel "MACDBG"\n",
  431. netdev->ifindex, MAC2STRDBG(mac->octet)));
  432. ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
  433. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  434. if (unlikely(ret < 0)) {
  435. printk("'cfg p2p_ifdel' error %d\n", ret);
  436. }
  437. return ret;
  438. }
  439. /* Change a P2P Role.
  440. * Parameters:
  441. * @mac : MAC address of the BSS to change a role
  442. * Returns 0 if success.
  443. */
  444. s32
  445. wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
  446. chanspec_t chspec)
  447. {
  448. wl_p2p_if_t ifreq;
  449. s32 err;
  450. u32 scb_timeout = WL_SCB_TIMEOUT;
  451. struct net_device *netdev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION);
  452. ifreq.type = if_type;
  453. ifreq.chspec = chspec;
  454. memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
  455. CFGP2P_INFO(("---cfg p2p_ifchange "MACDBG" %s %u"
  456. " chanspec 0x%04x\n", MAC2STRDBG(ifreq.addr.octet),
  457. (if_type == WL_P2P_IF_GO) ? "go" : "client",
  458. (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT,
  459. ifreq.chspec));
  460. err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
  461. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  462. if (unlikely(err < 0)) {
  463. printk("'cfg p2p_ifupd' error %d\n", err);
  464. } else if (if_type == WL_P2P_IF_GO) {
  465. err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
  466. if (unlikely(err < 0))
  467. printk("'cfg scb_timeout' error %d\n", err);
  468. }
  469. return err;
  470. }
  471. /* Get the index of a created P2P BSS.
  472. * Parameters:
  473. * @mac : MAC address of the created BSS
  474. * @index : output: index of created BSS
  475. * Returns 0 if success.
  476. */
  477. s32
  478. wl_cfgp2p_ifidx(struct bcm_cfg80211 *cfg, struct ether_addr *mac, s32 *index)
  479. {
  480. s32 ret;
  481. u8 getbuf[64];
  482. struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
  483. CFGP2P_INFO(("---cfg p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet)));
  484. ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf,
  485. sizeof(getbuf), wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY), NULL);
  486. if (ret == 0) {
  487. memcpy(index, getbuf, sizeof(s32));
  488. CFGP2P_INFO(("---cfg p2p_if ==> %d\n", *index));
  489. }
  490. return ret;
  491. }
  492. static s32
  493. wl_cfgp2p_set_discovery(struct bcm_cfg80211 *cfg, s32 on)
  494. {
  495. s32 ret = BCME_OK;
  496. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  497. CFGP2P_DBG(("enter\n"));
  498. ret = wldev_iovar_setint(ndev, "p2p_disc", on);
  499. if (unlikely(ret < 0)) {
  500. CFGP2P_ERR(("p2p_disc %d error %d\n", on, ret));
  501. }
  502. return ret;
  503. }
  504. /* Set the WL driver's P2P mode.
  505. * Parameters :
  506. * @mode : is one of WL_P2P_DISC_ST_{SCAN,LISTEN,SEARCH}.
  507. * @channel : the channel to listen
  508. * @listen_ms : the time (milli seconds) to wait
  509. * @bssidx : bss index for BSSCFG
  510. * Returns 0 if success
  511. */
  512. s32
  513. wl_cfgp2p_set_p2p_mode(struct bcm_cfg80211 *cfg, u8 mode, u32 channel, u16 listen_ms, int bssidx)
  514. {
  515. wl_p2p_disc_st_t discovery_mode;
  516. s32 ret;
  517. struct net_device *dev;
  518. CFGP2P_DBG(("enter\n"));
  519. if (unlikely(bssidx == WL_INVALID)) {
  520. CFGP2P_ERR((" %d index out of range\n", bssidx));
  521. return -1;
  522. }
  523. dev = wl_cfgp2p_find_ndev(cfg, bssidx);
  524. if (unlikely(dev == NULL)) {
  525. CFGP2P_ERR(("bssidx %d is not assigned\n", bssidx));
  526. return BCME_NOTFOUND;
  527. }
  528. /* Put the WL driver into P2P Listen Mode to respond to P2P probe reqs */
  529. discovery_mode.state = mode;
  530. discovery_mode.chspec = wl_ch_host_to_driver(channel);
  531. discovery_mode.dwell = listen_ms;
  532. ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
  533. sizeof(discovery_mode), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
  534. bssidx, &cfg->ioctl_buf_sync);
  535. return ret;
  536. }
  537. /* Get the index of the P2P Discovery BSS */
  538. static s32
  539. wl_cfgp2p_get_disc_idx(struct bcm_cfg80211 *cfg, s32 *index)
  540. {
  541. s32 ret;
  542. struct net_device *dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
  543. ret = wldev_iovar_getint(dev, "p2p_dev", index);
  544. CFGP2P_INFO(("p2p_dev bsscfg_idx=%d ret=%d\n", *index, ret));
  545. if (unlikely(ret < 0)) {
  546. CFGP2P_ERR(("'p2p_dev' error %d\n", ret));
  547. return ret;
  548. }
  549. return ret;
  550. }
  551. s32
  552. wl_cfgp2p_init_discovery(struct bcm_cfg80211 *cfg)
  553. {
  554. s32 index = 0;
  555. s32 ret = BCME_OK;
  556. CFGP2P_DBG(("enter\n"));
  557. #if defined(CUSTOMER_HW4) && defined(PLATFORM_SLP)
  558. if ((int)wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0) {
  559. #else
  560. if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) != 0) {
  561. #endif /* CUSTOMER_HW4 && PLATFORM_SLP */
  562. CFGP2P_ERR(("do nothing, already initialized\n"));
  563. return ret;
  564. }
  565. ret = wl_cfgp2p_set_discovery(cfg, 1);
  566. if (ret < 0) {
  567. CFGP2P_ERR(("set discover error\n"));
  568. return ret;
  569. }
  570. /* Enable P2P Discovery in the WL Driver */
  571. ret = wl_cfgp2p_get_disc_idx(cfg, &index);
  572. if (ret < 0) {
  573. return ret;
  574. }
  575. wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) =
  576. wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
  577. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = index;
  578. /* Set the initial discovery state to SCAN */
  579. ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
  580. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  581. if (unlikely(ret != 0)) {
  582. CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
  583. wl_cfgp2p_set_discovery(cfg, 0);
  584. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
  585. wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
  586. return 0;
  587. }
  588. return ret;
  589. }
  590. /* Deinitialize P2P Discovery
  591. * Parameters :
  592. * @cfg : wl_private data
  593. * Returns 0 if succes
  594. */
  595. static s32
  596. wl_cfgp2p_deinit_discovery(struct bcm_cfg80211 *cfg)
  597. {
  598. s32 ret = BCME_OK;
  599. CFGP2P_DBG(("enter\n"));
  600. if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) == 0) {
  601. CFGP2P_ERR(("do nothing, not initialized\n"));
  602. return -1;
  603. }
  604. /* Set the discovery state to SCAN */
  605. ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
  606. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  607. /* Disable P2P discovery in the WL driver (deletes the discovery BSSCFG) */
  608. ret = wl_cfgp2p_set_discovery(cfg, 0);
  609. /* Clear our saved WPS and P2P IEs for the discovery BSS. The driver
  610. * deleted these IEs when wl_cfgp2p_set_discovery() deleted the discovery
  611. * BSS.
  612. */
  613. /* Clear the saved bsscfg index of the discovery BSSCFG to indicate we
  614. * have no discovery BSS.
  615. */
  616. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = WL_INVALID;
  617. wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
  618. return ret;
  619. }
  620. /* Enable P2P Discovery
  621. * Parameters:
  622. * @cfg : wl_private data
  623. * @ie : probe request ie (WPS IE + P2P IE)
  624. * @ie_len : probe request ie length
  625. * Returns 0 if success.
  626. */
  627. s32
  628. wl_cfgp2p_enable_discovery(struct bcm_cfg80211 *cfg, struct net_device *dev,
  629. const u8 *ie, u32 ie_len)
  630. {
  631. s32 ret = BCME_OK;
  632. s32 bssidx;
  633. if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
  634. CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n"));
  635. goto set_ie;
  636. }
  637. wl_set_p2p_status(cfg, DISCOVERY_ON);
  638. CFGP2P_DBG(("enter\n"));
  639. ret = wl_cfgp2p_init_discovery(cfg);
  640. if (unlikely(ret < 0)) {
  641. CFGP2P_ERR((" init discovery error %d\n", ret));
  642. goto exit;
  643. }
  644. /* Set wsec to any non-zero value in the discovery bsscfg to ensure our
  645. * P2P probe responses have the privacy bit set in the 802.11 WPA IE.
  646. * Some peer devices may not initiate WPS with us if this bit is not set.
  647. */
  648. ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE),
  649. "wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  650. if (unlikely(ret < 0)) {
  651. CFGP2P_ERR((" wsec error %d\n", ret));
  652. }
  653. set_ie:
  654. if (ie_len) {
  655. if (bcmcfg_to_prmry_ndev(cfg) == dev) {
  656. bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
  657. } else if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
  658. WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
  659. return BCME_ERROR;
  660. }
  661. ret = wl_cfgp2p_set_management_ie(cfg, dev,
  662. bssidx,
  663. VNDR_IE_PRBREQ_FLAG, ie, ie_len);
  664. if (unlikely(ret < 0)) {
  665. CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
  666. goto exit;
  667. }
  668. }
  669. exit:
  670. return ret;
  671. }
  672. /* Disable P2P Discovery
  673. * Parameters:
  674. * @cfg : wl_private_data
  675. * Returns 0 if success.
  676. */
  677. s32
  678. wl_cfgp2p_disable_discovery(struct bcm_cfg80211 *cfg)
  679. {
  680. s32 ret = BCME_OK;
  681. CFGP2P_DBG((" enter\n"));
  682. wl_clr_p2p_status(cfg, DISCOVERY_ON);
  683. if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) == 0) {
  684. CFGP2P_ERR((" do nothing, not initialized\n"));
  685. goto exit;
  686. }
  687. ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
  688. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  689. if (unlikely(ret < 0)) {
  690. CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
  691. }
  692. /* Do a scan abort to stop the driver's scan engine in case it is still
  693. * waiting out an action frame tx dwell time.
  694. */
  695. #ifdef NOT_YET
  696. if (wl_get_p2p_status(cfg, SCANNING)) {
  697. p2pwlu_scan_abort(hdl, FALSE);
  698. }
  699. #endif
  700. wl_clr_p2p_status(cfg, DISCOVERY_ON);
  701. ret = wl_cfgp2p_deinit_discovery(cfg);
  702. exit:
  703. return ret;
  704. }
  705. s32
  706. wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active,
  707. u32 num_chans, u16 *channels,
  708. s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
  709. p2p_scan_purpose_t p2p_scan_purpose)
  710. {
  711. s32 ret = BCME_OK;
  712. s32 memsize;
  713. s32 eparams_size;
  714. u32 i;
  715. s8 *memblk;
  716. wl_p2p_scan_t *p2p_params;
  717. wl_escan_params_t *eparams;
  718. wlc_ssid_t ssid;
  719. /* Scan parameters */
  720. #define P2PAPI_SCAN_NPROBES 1
  721. #define P2PAPI_SCAN_DWELL_TIME_MS 80
  722. #define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
  723. #define P2PAPI_SCAN_HOME_TIME_MS 60
  724. #define P2PAPI_SCAN_NPROBS_TIME_MS 30
  725. #define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
  726. struct net_device *pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
  727. /* Allocate scan params which need space for 3 channels and 0 ssids */
  728. eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
  729. OFFSETOF(wl_escan_params_t, params)) +
  730. num_chans * sizeof(eparams->params.channel_list[0]);
  731. memsize = sizeof(wl_p2p_scan_t) + eparams_size;
  732. memblk = scanparambuf;
  733. if (memsize > sizeof(scanparambuf)) {
  734. CFGP2P_ERR((" scanpar buf too small (%u > %zu)\n",
  735. memsize, sizeof(scanparambuf)));
  736. return -1;
  737. }
  738. memset(memblk, 0, memsize);
  739. memset(cfg->ioctl_buf, 0, WLC_IOCTL_MAXLEN);
  740. if (search_state == WL_P2P_DISC_ST_SEARCH) {
  741. /*
  742. * If we in SEARCH STATE, we don't need to set SSID explictly
  743. * because dongle use P2P WILDCARD internally by default
  744. */
  745. wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx);
  746. /* use null ssid */
  747. ssid.SSID_len = 0;
  748. memset(&ssid.SSID, 0, sizeof(ssid.SSID));
  749. } else if (search_state == WL_P2P_DISC_ST_SCAN) {
  750. /* SCAN STATE 802.11 SCAN
  751. * WFD Supplicant has p2p_find command with (type=progressive, type= full)
  752. * So if P2P_find command with type=progressive,
  753. * we have to set ssid to P2P WILDCARD because
  754. * we just do broadcast scan unless setting SSID
  755. */
  756. wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
  757. /* use wild card ssid */
  758. ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN;
  759. memset(&ssid.SSID, 0, sizeof(ssid.SSID));
  760. memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN);
  761. } else {
  762. CFGP2P_ERR((" invalid search state %d\n", search_state));
  763. return -1;
  764. }
  765. /* Fill in the P2P scan structure at the start of the iovar param block */
  766. p2p_params = (wl_p2p_scan_t*) memblk;
  767. p2p_params->type = 'E';
  768. /* Fill in the Scan structure that follows the P2P scan structure */
  769. eparams = (wl_escan_params_t*) (p2p_params + 1);
  770. eparams->params.bss_type = DOT11_BSSTYPE_ANY;
  771. if (active)
  772. eparams->params.scan_type = DOT11_SCANTYPE_ACTIVE;
  773. else
  774. eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE;
  775. if (tx_dst_addr == NULL)
  776. memcpy(&eparams->params.bssid, &ether_bcast, ETHER_ADDR_LEN);
  777. else
  778. memcpy(&eparams->params.bssid, tx_dst_addr, ETHER_ADDR_LEN);
  779. if (ssid.SSID_len)
  780. memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t));
  781. eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
  782. switch (p2p_scan_purpose) {
  783. case P2P_SCAN_SOCIAL_CHANNEL:
  784. eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS);
  785. break;
  786. case P2P_SCAN_AFX_PEER_NORMAL:
  787. case P2P_SCAN_AFX_PEER_REDUCED:
  788. eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS);
  789. break;
  790. case P2P_SCAN_CONNECT_TRY:
  791. eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
  792. break;
  793. default :
  794. if (wl_get_drv_status_all(cfg, CONNECTED))
  795. eparams->params.active_time = -1;
  796. else
  797. eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS);
  798. break;
  799. }
  800. if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY)
  801. eparams->params.nprobes = htod32(eparams->params.active_time /
  802. WL_SCAN_JOIN_PROBE_INTERVAL_MS);
  803. else
  804. eparams->params.nprobes = htod32((eparams->params.active_time /
  805. P2PAPI_SCAN_NPROBS_TIME_MS));
  806. if (eparams->params.nprobes <= 0)
  807. eparams->params.nprobes = 1;
  808. CFGP2P_DBG(("nprobes # %d, active_time %d\n",
  809. eparams->params.nprobes, eparams->params.active_time));
  810. eparams->params.passive_time = htod32(-1);
  811. eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
  812. (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
  813. for (i = 0; i < num_chans; i++) {
  814. eparams->params.channel_list[i] = wl_ch_host_to_driver(channels[i]);
  815. }
  816. eparams->version = htod32(ESCAN_REQ_VERSION);
  817. eparams->action = htod16(action);
  818. wl_escan_set_sync_id(eparams->sync_id, cfg);
  819. wl_escan_set_type(cfg, WL_SCANTYPE_P2P);
  820. CFGP2P_INFO(("SCAN CHANNELS : "));
  821. for (i = 0; i < num_chans; i++) {
  822. if (i == 0) CFGP2P_INFO(("%d", channels[i]));
  823. else CFGP2P_INFO((",%d", channels[i]));
  824. }
  825. CFGP2P_INFO(("\n"));
  826. ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan",
  827. memblk, memsize, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  828. if (ret == BCME_OK)
  829. wl_set_p2p_status(cfg, SCANNING);
  830. return ret;
  831. }
  832. /* search function to reach at common channel to send action frame
  833. * Parameters:
  834. * @cfg : wl_private data
  835. * @ndev : net device for bssidx
  836. * @bssidx : bssidx for BSS
  837. * Returns 0 if success.
  838. */
  839. s32
  840. wl_cfgp2p_act_frm_search(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  841. s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr)
  842. {
  843. s32 ret = 0;
  844. u32 chan_cnt = 0;
  845. u16 *default_chan_list = NULL;
  846. p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_AFX_PEER_NORMAL;
  847. if (!p2p_is_on(cfg) || ndev == NULL || bssidx == WL_INVALID)
  848. return -BCME_ERROR;
  849. WL_TRACE_HW4((" Enter\n"));
  850. if (bssidx == wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY))
  851. bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
  852. if (channel)
  853. chan_cnt = AF_PEER_SEARCH_CNT;
  854. else
  855. chan_cnt = SOCIAL_CHAN_CNT;
  856. #ifdef CUSTOMER_HW4
  857. if (cfg->afx_hdl->pending_tx_act_frm && cfg->afx_hdl->is_active) {
  858. wl_action_frame_t *action_frame;
  859. action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
  860. if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
  861. chan_cnt = 1;
  862. p2p_scan_purpose = P2P_SCAN_AFX_PEER_REDUCED;
  863. }
  864. }
  865. #endif /* CUSTOMER_HW4 */
  866. default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL);
  867. if (default_chan_list == NULL) {
  868. CFGP2P_ERR(("channel list allocation failed \n"));
  869. ret = -ENOMEM;
  870. goto exit;
  871. }
  872. if (channel) {
  873. u32 i;
  874. /* insert same channel to the chan_list */
  875. for (i = 0; i < chan_cnt; i++) {
  876. default_chan_list[i] = channel;
  877. }
  878. } else {
  879. default_chan_list[0] = SOCIAL_CHAN_1;
  880. default_chan_list[1] = SOCIAL_CHAN_2;
  881. default_chan_list[2] = SOCIAL_CHAN_3;
  882. }
  883. ret = wl_cfgp2p_escan(cfg, ndev, true, chan_cnt,
  884. default_chan_list, WL_P2P_DISC_ST_SEARCH,
  885. WL_SCAN_ACTION_START, bssidx, NULL, p2p_scan_purpose);
  886. kfree(default_chan_list);
  887. exit:
  888. return ret;
  889. }
  890. /* Check whether pointed-to IE looks like WPA. */
  891. #define wl_cfgp2p_is_wpa_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
  892. (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE)
  893. /* Check whether pointed-to IE looks like WPS. */
  894. #define wl_cfgp2p_is_wps_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
  895. (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE)
  896. /* Check whether the given IE looks like WFA P2P IE. */
  897. #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
  898. (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
  899. /* Check whether the given IE looks like WFA WFDisplay IE. */
  900. #ifndef WFA_OUI_TYPE_WFD
  901. #define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */
  902. #endif
  903. #define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
  904. (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
  905. static s32
  906. wl_cfgp2p_parse_vndr_ies(u8 *parse, u32 len,
  907. struct parsed_vndr_ies *vndr_ies)
  908. {
  909. s32 err = BCME_OK;
  910. vndr_ie_t *vndrie;
  911. bcm_tlv_t *ie;
  912. struct parsed_vndr_ie_info *parsed_info;
  913. u32 count = 0;
  914. s32 remained_len;
  915. remained_len = (s32)len;
  916. memset(vndr_ies, 0, sizeof(*vndr_ies));
  917. WL_INFO(("---> len %d\n", len));
  918. ie = (bcm_tlv_t *) parse;
  919. if (!bcm_valid_tlv(ie, remained_len))
  920. ie = NULL;
  921. while (ie) {
  922. if (count >= MAX_VNDR_IE_NUMBER)
  923. break;
  924. if (ie->id == DOT11_MNG_VS_ID) {
  925. vndrie = (vndr_ie_t *) ie;
  926. /* len should be bigger than OUI length + one data length at least */
  927. if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
  928. CFGP2P_ERR(("%s: invalid vndr ie. length is too small %d\n",
  929. __FUNCTION__, vndrie->len));
  930. goto end;
  931. }
  932. /* if wpa or wme ie, do not add ie */
  933. if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
  934. ((vndrie->data[0] == WPA_OUI_TYPE) ||
  935. (vndrie->data[0] == WME_OUI_TYPE))) {
  936. CFGP2P_DBG(("Found WPA/WME oui. Do not add it\n"));
  937. goto end;
  938. }
  939. parsed_info = &vndr_ies->ie_info[count++];
  940. /* save vndr ie information */
  941. parsed_info->ie_ptr = (char *)vndrie;
  942. parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
  943. memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
  944. vndr_ies->count = count;
  945. CFGP2P_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x \n",
  946. parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
  947. parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0]));
  948. }
  949. end:
  950. ie = bcm_next_tlv(ie, &remained_len);
  951. }
  952. return err;
  953. }
  954. /* Delete and Set a management vndr ie to firmware
  955. * Parameters:
  956. * @cfg : wl_private data
  957. * @ndev : net device for bssidx
  958. * @bssidx : bssidx for BSS
  959. * @pktflag : packet flag for IE (VNDR_IE_PRBREQ_FLAG,VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG,
  960. * VNDR_IE_ASSOCREQ_FLAG)
  961. * @ie : VNDR IE (such as P2P IE , WPS IE)
  962. * @ie_len : VNDR IE Length
  963. * Returns 0 if success.
  964. */
  965. s32
  966. wl_cfgp2p_set_management_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx,
  967. s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
  968. {
  969. s32 ret = BCME_OK;
  970. u8 *curr_ie_buf = NULL;
  971. u8 *mgmt_ie_buf = NULL;
  972. u32 mgmt_ie_buf_len = 0;
  973. u32 *mgmt_ie_len = 0;
  974. u32 del_add_ie_buf_len = 0;
  975. u32 total_ie_buf_len = 0;
  976. u32 parsed_ie_buf_len = 0;
  977. struct parsed_vndr_ies old_vndr_ies;
  978. struct parsed_vndr_ies new_vndr_ies;
  979. s32 i;
  980. u8 *ptr;
  981. s32 type = -1;
  982. s32 remained_buf_len;
  983. #define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(cfg, bsstype).p2p_ ## type ## _ie)
  984. #define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(cfg, bsstype).p2p_ ## type ## _ie_len)
  985. memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
  986. curr_ie_buf = g_mgmt_ie_buf;
  987. CFGP2P_DBG((" bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag));
  988. if (cfg->p2p != NULL) {
  989. if (wl_cfgp2p_find_type(cfg, bssidx, &type)) {
  990. CFGP2P_ERR(("cannot find type from bssidx : %d\n", bssidx));
  991. return BCME_ERROR;
  992. }
  993. switch (pktflag) {
  994. case VNDR_IE_PRBREQ_FLAG :
  995. mgmt_ie_buf = IE_TYPE(probe_req, type);
  996. mgmt_ie_len = &IE_TYPE_LEN(probe_req, type);
  997. mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, type));
  998. break;
  999. case VNDR_IE_PRBRSP_FLAG :
  1000. mgmt_ie_buf = IE_TYPE(probe_res, type);
  1001. mgmt_ie_len = &IE_TYPE_LEN(probe_res, type);
  1002. mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, type));
  1003. break;
  1004. case VNDR_IE_ASSOCREQ_FLAG :
  1005. mgmt_ie_buf = IE_TYPE(assoc_req, type);
  1006. mgmt_ie_len = &IE_TYPE_LEN(assoc_req, type);
  1007. mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, type));
  1008. break;
  1009. case VNDR_IE_ASSOCRSP_FLAG :
  1010. mgmt_ie_buf = IE_TYPE(assoc_res, type);
  1011. mgmt_ie_len = &IE_TYPE_LEN(assoc_res, type);
  1012. mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, type));
  1013. break;
  1014. case VNDR_IE_BEACON_FLAG :
  1015. mgmt_ie_buf = IE_TYPE(beacon, type);
  1016. mgmt_ie_len = &IE_TYPE_LEN(beacon, type);
  1017. mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, type));
  1018. break;
  1019. default:
  1020. mgmt_ie_buf = NULL;
  1021. mgmt_ie_len = NULL;
  1022. CFGP2P_ERR(("not suitable type\n"));
  1023. return BCME_ERROR;
  1024. }
  1025. } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
  1026. switch (pktflag) {
  1027. case VNDR_IE_PRBRSP_FLAG :
  1028. mgmt_ie_buf = cfg->ap_info->probe_res_ie;
  1029. mgmt_ie_len = &cfg->ap_info->probe_res_ie_len;
  1030. mgmt_ie_buf_len = sizeof(cfg->ap_info->probe_res_ie);
  1031. break;
  1032. case VNDR_IE_BEACON_FLAG :
  1033. mgmt_ie_buf = cfg->ap_info->beacon_ie;
  1034. mgmt_ie_len = &cfg->ap_info->beacon_ie_len;
  1035. mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie);
  1036. break;
  1037. case VNDR_IE_ASSOCRSP_FLAG :
  1038. /* WPS-AP WSC2.0 assoc res includes wps_ie */
  1039. mgmt_ie_buf = cfg->ap_info->assoc_res_ie;
  1040. mgmt_ie_len = &cfg->ap_info->assoc_res_ie_len;
  1041. mgmt_ie_buf_len = sizeof(cfg->ap_info->assoc_res_ie);
  1042. break;
  1043. default:
  1044. mgmt_ie_buf = NULL;
  1045. mgmt_ie_len = NULL;
  1046. CFGP2P_ERR(("not suitable type\n"));
  1047. return BCME_ERROR;
  1048. }
  1049. bssidx = 0;
  1050. } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
  1051. switch (pktflag) {
  1052. case VNDR_IE_PRBREQ_FLAG :
  1053. mgmt_ie_buf = cfg->sta_info->probe_req_ie;
  1054. mgmt_ie_len = &cfg->sta_info->probe_req_ie_len;
  1055. mgmt_ie_buf_len = sizeof(cfg->sta_info->probe_req_ie);
  1056. break;
  1057. case VNDR_IE_ASSOCREQ_FLAG :
  1058. mgmt_ie_buf = cfg->sta_info->assoc_req_ie;
  1059. mgmt_ie_len = &cfg->sta_info->assoc_req_ie_len;
  1060. mgmt_ie_buf_len = sizeof(cfg->sta_info->assoc_req_ie);
  1061. break;
  1062. default:
  1063. mgmt_ie_buf = NULL;
  1064. mgmt_ie_len = NULL;
  1065. CFGP2P_ERR(("not suitable type\n"));
  1066. return BCME_ERROR;
  1067. }
  1068. bssidx = 0;
  1069. } else {
  1070. CFGP2P_ERR(("not suitable type\n"));
  1071. return BCME_ERROR;
  1072. }
  1073. if (vndr_ie_len > mgmt_ie_buf_len) {
  1074. CFGP2P_ERR(("extra IE size too big\n"));
  1075. ret = -ENOMEM;
  1076. } else {
  1077. /* parse and save new vndr_ie in curr_ie_buff before comparing it */
  1078. if (vndr_ie && vndr_ie_len && curr_ie_buf) {
  1079. ptr = curr_ie_buf;
  1080. wl_cfgp2p_parse_vndr_ies((u8*)vndr_ie,
  1081. vndr_ie_len, &new_vndr_ies);
  1082. for (i = 0; i < new_vndr_ies.count; i++) {
  1083. struct parsed_vndr_ie_info *vndrie_info =
  1084. &new_vndr_ies.ie_info[i];
  1085. memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
  1086. vndrie_info->ie_len);
  1087. parsed_ie_buf_len += vndrie_info->ie_len;
  1088. }
  1089. }
  1090. if (mgmt_ie_buf != NULL) {
  1091. if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
  1092. (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
  1093. CFGP2P_INFO(("Previous mgmt IE is equals to current IE"));
  1094. goto exit;
  1095. }
  1096. /* parse old vndr_ie */
  1097. wl_cfgp2p_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
  1098. &old_vndr_ies);
  1099. /* make a command to delete old ie */
  1100. for (i = 0; i < old_vndr_ies.count; i++) {
  1101. struct parsed_vndr_ie_info *vndrie_info =
  1102. &old_vndr_ies.ie_info[i];
  1103. CFGP2P_INFO(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
  1104. vndrie_info->vndrie.id, vndrie_info->vndrie.len,
  1105. vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
  1106. vndrie_info->vndrie.oui[2]));
  1107. del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
  1108. pktflag, vndrie_info->vndrie.oui,
  1109. vndrie_info->vndrie.id,
  1110. vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
  1111. vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
  1112. "del");
  1113. curr_ie_buf += del_add_ie_buf_len;
  1114. total_ie_buf_len += del_add_ie_buf_len;
  1115. }
  1116. }
  1117. *mgmt_ie_len = 0;
  1118. /* Add if there is any extra IE */
  1119. if (mgmt_ie_buf && parsed_ie_buf_len) {
  1120. ptr = mgmt_ie_buf;
  1121. remained_buf_len = mgmt_ie_buf_len;
  1122. /* make a command to add new ie */
  1123. for (i = 0; i < new_vndr_ies.count; i++) {
  1124. struct parsed_vndr_ie_info *vndrie_info =
  1125. &new_vndr_ies.ie_info[i];
  1126. CFGP2P_INFO(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
  1127. vndrie_info->vndrie.id, vndrie_info->vndrie.len,
  1128. vndrie_info->ie_len - 2,
  1129. vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
  1130. vndrie_info->vndrie.oui[2]));
  1131. del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
  1132. pktflag, vndrie_info->vndrie.oui,
  1133. vndrie_info->vndrie.id,
  1134. vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
  1135. vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
  1136. "add");
  1137. /* verify remained buf size before copy data */
  1138. if (remained_buf_len >= vndrie_info->ie_len) {
  1139. remained_buf_len -= vndrie_info->ie_len;
  1140. } else {
  1141. CFGP2P_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
  1142. "found vndr ies # = %d(cur %d), remained len %d, "
  1143. "cur mgmt_ie_len %d, new ie len = %d\n",
  1144. pktflag, new_vndr_ies.count, i, remained_buf_len,
  1145. *mgmt_ie_len, vndrie_info->ie_len));
  1146. break;
  1147. }
  1148. /* save the parsed IE in cfg struct */
  1149. memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
  1150. vndrie_info->ie_len);
  1151. *mgmt_ie_len += vndrie_info->ie_len;
  1152. curr_ie_buf += del_add_ie_buf_len;
  1153. total_ie_buf_len += del_add_ie_buf_len;
  1154. }
  1155. }
  1156. if (total_ie_buf_len) {
  1157. ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
  1158. total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
  1159. bssidx, &cfg->ioctl_buf_sync);
  1160. if (ret)
  1161. CFGP2P_ERR(("vndr ie set error : %d\n", ret));
  1162. }
  1163. }
  1164. #undef IE_TYPE
  1165. #undef IE_TYPE_LEN
  1166. exit:
  1167. return ret;
  1168. }
  1169. /* Clear the manament IE buffer of BSSCFG
  1170. * Parameters:
  1171. * @cfg : wl_private data
  1172. * @bssidx : bssidx for BSS
  1173. *
  1174. * Returns 0 if success.
  1175. */
  1176. s32
  1177. wl_cfgp2p_clear_management_ie(struct bcm_cfg80211 *cfg, s32 bssidx)
  1178. {
  1179. s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG,
  1180. VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
  1181. s32 index = -1;
  1182. s32 type = -1;
  1183. struct net_device *ndev = wl_cfgp2p_find_ndev(cfg, bssidx);
  1184. #define INIT_IE(IE_TYPE, BSS_TYPE) \
  1185. do { \
  1186. memset(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \
  1187. sizeof(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \
  1188. wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \
  1189. } while (0);
  1190. if (bssidx < 0 || ndev == NULL) {
  1191. CFGP2P_ERR(("invalid %s\n", (bssidx < 0) ? "bssidx" : "ndev"));
  1192. return BCME_BADARG;
  1193. }
  1194. if (wl_cfgp2p_find_type(cfg, bssidx, &type)) {
  1195. CFGP2P_ERR(("invalid argument\n"));
  1196. return BCME_BADARG;
  1197. }
  1198. for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
  1199. /* clean up vndr ies in dongle */
  1200. wl_cfgp2p_set_management_ie(cfg, ndev, bssidx, vndrie_flag[index], NULL, 0);
  1201. }
  1202. INIT_IE(probe_req, type);
  1203. INIT_IE(probe_res, type);
  1204. INIT_IE(assoc_req, type);
  1205. INIT_IE(assoc_res, type);
  1206. INIT_IE(beacon, type);
  1207. return BCME_OK;
  1208. }
  1209. /* Is any of the tlvs the expected entry? If
  1210. * not update the tlvs buffer pointer/length.
  1211. */
  1212. static bool
  1213. wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type)
  1214. {
  1215. /* If the contents match the OUI and the type */
  1216. if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
  1217. !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
  1218. type == ie[TLV_BODY_OFF + oui_len]) {
  1219. return TRUE;
  1220. }
  1221. if (tlvs == NULL)
  1222. return FALSE;
  1223. /* point to the next ie */
  1224. ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
  1225. /* calculate the length of the rest of the buffer */
  1226. *tlvs_len -= (int)(ie - *tlvs);
  1227. /* update the pointer to the start of the buffer */
  1228. *tlvs = ie;
  1229. return FALSE;
  1230. }
  1231. wpa_ie_fixed_t *
  1232. wl_cfgp2p_find_wpaie(u8 *parse, u32 len)
  1233. {
  1234. bcm_tlv_t *ie;
  1235. while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
  1236. if (wl_cfgp2p_is_wpa_ie((u8*)ie, &parse, &len)) {
  1237. return (wpa_ie_fixed_t *)ie;
  1238. }
  1239. }
  1240. return NULL;
  1241. }
  1242. wpa_ie_fixed_t *
  1243. wl_cfgp2p_find_wpsie(u8 *parse, u32 len)
  1244. {
  1245. bcm_tlv_t *ie;
  1246. while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
  1247. if (wl_cfgp2p_is_wps_ie((u8*)ie, &parse, &len)) {
  1248. return (wpa_ie_fixed_t *)ie;
  1249. }
  1250. }
  1251. return NULL;
  1252. }
  1253. wifi_p2p_ie_t *
  1254. wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
  1255. {
  1256. bcm_tlv_t *ie;
  1257. while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
  1258. if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len)) {
  1259. return (wifi_p2p_ie_t *)ie;
  1260. }
  1261. }
  1262. return NULL;
  1263. }
  1264. wifi_wfd_ie_t *
  1265. wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
  1266. {
  1267. bcm_tlv_t *ie;
  1268. while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
  1269. if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
  1270. return (wifi_wfd_ie_t *)ie;
  1271. }
  1272. }
  1273. return NULL;
  1274. }
  1275. static u32
  1276. wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
  1277. s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd)
  1278. {
  1279. vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */
  1280. s32 iecount;
  1281. u32 data_offset;
  1282. /* Validate the pktflag parameter */
  1283. if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
  1284. VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
  1285. VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG))) {
  1286. CFGP2P_ERR(("p2pwl_vndr_ie: Invalid packet flag 0x%x\n", pktflag));
  1287. return -1;
  1288. }
  1289. /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
  1290. strncpy(hdr.cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
  1291. hdr.cmd[VNDR_IE_CMD_LEN - 1] = '\0';
  1292. /* Set the IE count - the buffer contains only 1 IE */
  1293. iecount = htod32(1);
  1294. memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32));
  1295. /* Copy packet flags that indicate which packets will contain this IE */
  1296. pktflag = htod32(pktflag);
  1297. memcpy((void *)&hdr.vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
  1298. sizeof(u32));
  1299. /* Add the IE ID to the buffer */
  1300. hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = ie_id;
  1301. /* Add the IE length to the buffer */
  1302. hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len =
  1303. (uint8) VNDR_IE_MIN_LEN + datalen;
  1304. /* Add the IE OUI to the buffer */
  1305. hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0] = oui[0];
  1306. hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[1] = oui[1];
  1307. hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[2] = oui[2];
  1308. /* Copy the aligned temporary vndr_ie buffer header to the IE buffer */
  1309. memcpy(iebuf, &hdr, sizeof(hdr) - 1);
  1310. /* Copy the IE data to the IE buffer */
  1311. data_offset =
  1312. (u8*)&hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0] -
  1313. (u8*)&hdr;
  1314. memcpy(iebuf + data_offset, data, datalen);
  1315. return data_offset + datalen;
  1316. }
  1317. /*
  1318. * Search the bssidx based on dev argument
  1319. * Parameters:
  1320. * @cfg : wl_private data
  1321. * @ndev : net device to search bssidx
  1322. * @bssidx : output arg to store bssidx of the bsscfg of firmware.
  1323. * Returns error
  1324. */
  1325. s32
  1326. wl_cfgp2p_find_idx(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 *bssidx)
  1327. {
  1328. u32 i;
  1329. if (ndev == NULL || bssidx == NULL) {
  1330. CFGP2P_ERR((" argument is invalid\n"));
  1331. return BCME_BADARG;
  1332. }
  1333. if (!cfg->p2p_supported) {
  1334. *bssidx = P2PAPI_BSSCFG_PRIMARY;
  1335. return BCME_OK;
  1336. }
  1337. /* we cannot find the bssidx of DISCOVERY BSS
  1338. * because the ndev is same with ndev of PRIMARY BSS.
  1339. */
  1340. for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
  1341. if (ndev == wl_to_p2p_bss_ndev(cfg, i)) {
  1342. *bssidx = wl_to_p2p_bss_bssidx(cfg, i);
  1343. return BCME_OK;
  1344. }
  1345. }
  1346. return BCME_BADARG;
  1347. }
  1348. struct net_device *
  1349. wl_cfgp2p_find_ndev(struct bcm_cfg80211 *cfg, s32 bssidx)
  1350. {
  1351. u32 i;
  1352. struct net_device *ndev = NULL;
  1353. if (bssidx < 0) {
  1354. CFGP2P_ERR((" bsscfg idx is invalid\n"));
  1355. goto exit;
  1356. }
  1357. for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
  1358. if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
  1359. ndev = wl_to_p2p_bss_ndev(cfg, i);
  1360. break;
  1361. }
  1362. }
  1363. exit:
  1364. return ndev;
  1365. }
  1366. /*
  1367. * Search the driver array idx based on bssidx argument
  1368. * Parameters:
  1369. * @cfg : wl_private data
  1370. * @bssidx : bssidx which indicate bsscfg->idx of firmware.
  1371. * @type : output arg to store array idx of p2p->bss.
  1372. * Returns error
  1373. */
  1374. s32
  1375. wl_cfgp2p_find_type(struct bcm_cfg80211 *cfg, s32 bssidx, s32 *type)
  1376. {
  1377. u32 i;
  1378. if (bssidx < 0 || type == NULL) {
  1379. CFGP2P_ERR((" argument is invalid\n"));
  1380. goto exit;
  1381. }
  1382. for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
  1383. if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
  1384. *type = i;
  1385. return BCME_OK;
  1386. }
  1387. }
  1388. exit:
  1389. return BCME_BADARG;
  1390. }
  1391. /*
  1392. * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE
  1393. */
  1394. s32
  1395. wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  1396. const wl_event_msg_t *e, void *data)
  1397. {
  1398. s32 ret = BCME_OK;
  1399. struct net_device *ndev = NULL;
  1400. if (!cfg || !cfg->p2p || !cfgdev)
  1401. return BCME_ERROR;
  1402. CFGP2P_DBG((" Enter\n"));
  1403. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  1404. if (wl_get_p2p_status(cfg, LISTEN_EXPIRED) == 0) {
  1405. wl_set_p2p_status(cfg, LISTEN_EXPIRED);
  1406. if (timer_pending(&cfg->p2p->listen_timer)) {
  1407. del_timer_sync(&cfg->p2p->listen_timer);
  1408. }
  1409. if (cfg->afx_hdl->is_listen == TRUE &&
  1410. wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
  1411. WL_DBG(("Listen DONE for action frame\n"));
  1412. complete(&cfg->act_frm_scan);
  1413. }
  1414. #ifdef WL_CFG80211_SYNC_GON
  1415. else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
  1416. wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, ndev);
  1417. WL_DBG(("Listen DONE and wake up wait_next_af !!(%d)\n",
  1418. jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies)));
  1419. if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM))
  1420. wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
  1421. complete(&cfg->wait_next_af);
  1422. }
  1423. #endif /* WL_CFG80211_SYNC_GON */
  1424. #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  1425. if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL)) {
  1426. #else
  1427. if (wl_get_drv_status_all(cfg, REMAINING_ON_CHANNEL) ||
  1428. wl_get_drv_status_all(cfg, FAKE_REMAINING_ON_CHANNEL)) {
  1429. #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  1430. WL_DBG(("Listen DONE for ramain on channel expired\n"));
  1431. wl_clr_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
  1432. #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  1433. wl_clr_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
  1434. #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  1435. if (ndev && (ndev->ieee80211_ptr != NULL)) {
  1436. #if defined(WL_CFG80211_P2P_DEV_IF)
  1437. cfg80211_remain_on_channel_expired(
  1438. bcmcfg_to_p2p_wdev(cfg), cfg->last_roc_id,
  1439. &cfg->remain_on_chan, GFP_KERNEL);
  1440. #else
  1441. cfg80211_remain_on_channel_expired(cfg->p2p_net, cfg->last_roc_id,
  1442. &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
  1443. #endif /* WL_CFG80211_P2P_DEV_IF */
  1444. }
  1445. }
  1446. if (wl_add_remove_eventmsg(bcmcfg_to_prmry_ndev(cfg),
  1447. WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) {
  1448. CFGP2P_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
  1449. }
  1450. } else
  1451. wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
  1452. return ret;
  1453. }
  1454. /*
  1455. * Timer expire callback function for LISTEN
  1456. * We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
  1457. * so lets do it from thread context.
  1458. */
  1459. void
  1460. wl_cfgp2p_listen_expired(unsigned long data)
  1461. {
  1462. wl_event_msg_t msg;
  1463. struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
  1464. CFGP2P_DBG((" Enter\n"));
  1465. bzero(&msg, sizeof(wl_event_msg_t));
  1466. msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
  1467. #if defined(WL_ENABLE_P2P_IF)
  1468. wl_cfg80211_event(cfg->p2p_net ? cfg->p2p_net :
  1469. wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
  1470. #else
  1471. wl_cfg80211_event(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg,
  1472. NULL);
  1473. #endif /* WL_ENABLE_P2P_IF */
  1474. }
  1475. /*
  1476. * Routine for cancelling the P2P LISTEN
  1477. */
  1478. static s32
  1479. wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  1480. struct wireless_dev *wdev, bool notify)
  1481. {
  1482. WL_DBG(("Enter \n"));
  1483. /* Irrespective of whether timer is running or not, reset
  1484. * the LISTEN state.
  1485. */
  1486. #ifdef NOT_YET
  1487. wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
  1488. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  1489. #endif /* NOT_YET */
  1490. if (timer_pending(&cfg->p2p->listen_timer)) {
  1491. del_timer_sync(&cfg->p2p->listen_timer);
  1492. if (notify) {
  1493. #if defined(WL_CFG80211_P2P_DEV_IF)
  1494. if (wdev)
  1495. cfg80211_remain_on_channel_expired(
  1496. bcmcfg_to_p2p_wdev(cfg), cfg->last_roc_id,
  1497. &cfg->remain_on_chan, GFP_KERNEL);
  1498. #else
  1499. if (ndev && ndev->ieee80211_ptr)
  1500. cfg80211_remain_on_channel_expired(cfg->p2p_net, cfg->last_roc_id,
  1501. &cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
  1502. #endif /* WL_CFG80211_P2P_DEV_IF */
  1503. }
  1504. }
  1505. return 0;
  1506. }
  1507. /*
  1508. * Do a P2P Listen on the given channel for the given duration.
  1509. * A listen consists of sitting idle and responding to P2P probe requests
  1510. * with a P2P probe response.
  1511. *
  1512. * This fn assumes dongle p2p device discovery is already enabled.
  1513. * Parameters :
  1514. * @cfg : wl_private data
  1515. * @channel : channel to listen
  1516. * @duration_ms : the time (milli seconds) to wait
  1517. */
  1518. s32
  1519. wl_cfgp2p_discover_listen(struct bcm_cfg80211 *cfg, s32 channel, u32 duration_ms)
  1520. {
  1521. #define EXTRA_DELAY_TIME 100
  1522. s32 ret = BCME_OK;
  1523. struct timer_list *_timer;
  1524. s32 extra_delay;
  1525. struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
  1526. CFGP2P_DBG((" Enter Listen Channel : %d, Duration : %d\n", channel, duration_ms));
  1527. if (unlikely(wl_get_p2p_status(cfg, DISCOVERY_ON) == 0)) {
  1528. CFGP2P_ERR((" Discovery is not set, so we have noting to do\n"));
  1529. ret = BCME_NOTREADY;
  1530. goto exit;
  1531. }
  1532. if (timer_pending(&cfg->p2p->listen_timer)) {
  1533. CFGP2P_DBG(("previous LISTEN is not completed yet\n"));
  1534. goto exit;
  1535. }
  1536. #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  1537. else
  1538. wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
  1539. #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  1540. if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, true) != BCME_OK) {
  1541. CFGP2P_ERR((" failed to set WLC_E_P2P_PROPREQ_MSG\n"));
  1542. }
  1543. ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms,
  1544. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  1545. _timer = &cfg->p2p->listen_timer;
  1546. /* We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle ,
  1547. * otherwise we will wait up to duration_ms + 100ms + duration / 10
  1548. */
  1549. if (ret == BCME_OK) {
  1550. extra_delay = EXTRA_DELAY_TIME + (duration_ms / 10);
  1551. } else {
  1552. /* if failed to set listen, it doesn't need to wait whole duration. */
  1553. duration_ms = 100 + duration_ms / 20;
  1554. extra_delay = 0;
  1555. }
  1556. INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration_ms, extra_delay);
  1557. #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  1558. wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
  1559. #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  1560. #undef EXTRA_DELAY_TIME
  1561. exit:
  1562. return ret;
  1563. }
  1564. s32
  1565. wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable)
  1566. {
  1567. s32 ret = BCME_OK;
  1568. CFGP2P_DBG((" Enter\n"));
  1569. if (!wl_get_p2p_status(cfg, DISCOVERY_ON)) {
  1570. CFGP2P_DBG((" do nothing, discovery is off\n"));
  1571. return ret;
  1572. }
  1573. if (wl_get_p2p_status(cfg, SEARCH_ENABLED) == enable) {
  1574. CFGP2P_DBG(("already : %d\n", enable));
  1575. return ret;
  1576. }
  1577. wl_chg_p2p_status(cfg, SEARCH_ENABLED);
  1578. /* When disabling Search, reset the WL driver's p2p discovery state to
  1579. * WL_P2P_DISC_ST_SCAN.
  1580. */
  1581. if (!enable) {
  1582. wl_clr_p2p_status(cfg, SCANNING);
  1583. ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
  1584. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  1585. }
  1586. return ret;
  1587. }
  1588. /*
  1589. * Callback function for WLC_E_ACTION_FRAME_COMPLETE, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE
  1590. */
  1591. s32
  1592. wl_cfgp2p_action_tx_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  1593. const wl_event_msg_t *e, void *data)
  1594. {
  1595. s32 ret = BCME_OK;
  1596. u32 event_type = ntoh32(e->event_type);
  1597. u32 status = ntoh32(e->status);
  1598. struct net_device *ndev = NULL;
  1599. CFGP2P_DBG((" Enter\n"));
  1600. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  1601. if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
  1602. if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
  1603. CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
  1604. if (status == WLC_E_STATUS_SUCCESS) {
  1605. wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
  1606. CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n"));
  1607. if (!cfg->need_wait_afrx && cfg->af_sent_channel) {
  1608. CFGP2P_DBG(("no need to wait next AF.\n"));
  1609. wl_stop_wait_next_action_frame(cfg, ndev);
  1610. }
  1611. }
  1612. else if (!wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
  1613. wl_set_p2p_status(cfg, ACTION_TX_NOACK);
  1614. CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
  1615. wl_stop_wait_next_action_frame(cfg, ndev);
  1616. }
  1617. } else {
  1618. CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
  1619. "status : %d\n", status));
  1620. if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
  1621. complete(&cfg->send_af_done);
  1622. }
  1623. }
  1624. return ret;
  1625. }
  1626. /* Send an action frame immediately without doing channel synchronization.
  1627. *
  1628. * This function does not wait for a completion event before returning.
  1629. * The WLC_E_ACTION_FRAME_COMPLETE event will be received when the action
  1630. * frame is transmitted.
  1631. * The WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE event will be received when an
  1632. * 802.11 ack has been received for the sent action frame.
  1633. */
  1634. s32
  1635. wl_cfgp2p_tx_action_frame(struct bcm_cfg80211 *cfg, struct net_device *dev,
  1636. wl_af_params_t *af_params, s32 bssidx)
  1637. {
  1638. s32 ret = BCME_OK;
  1639. s32 evt_ret = BCME_OK;
  1640. s32 timeout = 0;
  1641. wl_eventmsg_buf_t buf;
  1642. CFGP2P_INFO(("\n"));
  1643. CFGP2P_INFO(("channel : %u , dwell time : %u\n",
  1644. af_params->channel, af_params->dwell_time));
  1645. wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
  1646. wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
  1647. bzero(&buf, sizeof(wl_eventmsg_buf_t));
  1648. wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, true);
  1649. wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, true);
  1650. if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0)
  1651. return evt_ret;
  1652. cfg->af_sent_channel = af_params->channel;
  1653. #ifdef WL_CFG80211_SYNC_GON
  1654. cfg->af_tx_sent_jiffies = jiffies;
  1655. #endif /* WL_CFG80211_SYNC_GON */
  1656. ret = wldev_iovar_setbuf_bsscfg(dev, "actframe", af_params, sizeof(*af_params),
  1657. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  1658. if (ret < 0) {
  1659. CFGP2P_ERR((" sending action frame is failed\n"));
  1660. goto exit;
  1661. }
  1662. timeout = wait_for_completion_timeout(&cfg->send_af_done,
  1663. msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX));
  1664. if (timeout >= 0 && wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
  1665. CFGP2P_INFO(("tx action frame operation is completed\n"));
  1666. ret = BCME_OK;
  1667. } else if (ETHER_ISBCAST(&cfg->afx_hdl->tx_dst_addr)) {
  1668. CFGP2P_INFO(("bcast tx action frame operation is completed\n"));
  1669. ret = BCME_OK;
  1670. } else {
  1671. ret = BCME_ERROR;
  1672. CFGP2P_INFO(("tx action frame operation is failed\n"));
  1673. }
  1674. /* clear status bit for action tx */
  1675. wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
  1676. wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
  1677. exit:
  1678. CFGP2P_INFO((" via act frame iovar : status = %d\n", ret));
  1679. bzero(&buf, sizeof(wl_eventmsg_buf_t));
  1680. wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false);
  1681. wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, false);
  1682. if ((evt_ret = wl_cfg80211_apply_eventbuffer(bcmcfg_to_prmry_ndev(cfg), cfg, &buf)) < 0) {
  1683. WL_ERR(("TX frame events revert back failed \n"));
  1684. return evt_ret;
  1685. }
  1686. return ret;
  1687. }
  1688. /* Generate our P2P Device Address and P2P Interface Address from our primary
  1689. * MAC address.
  1690. */
  1691. void
  1692. wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr,
  1693. struct ether_addr *out_dev_addr, struct ether_addr *out_int_addr)
  1694. {
  1695. memset(out_dev_addr, 0, sizeof(*out_dev_addr));
  1696. memset(out_int_addr, 0, sizeof(*out_int_addr));
  1697. /* Generate the P2P Device Address. This consists of the device's
  1698. * primary MAC address with the locally administered bit set.
  1699. */
  1700. memcpy(out_dev_addr, primary_addr, sizeof(*out_dev_addr));
  1701. out_dev_addr->octet[0] |= 0x02;
  1702. /* Generate the P2P Interface Address. If the discovery and connection
  1703. * BSSCFGs need to simultaneously co-exist, then this address must be
  1704. * different from the P2P Device Address.
  1705. */
  1706. memcpy(out_int_addr, out_dev_addr, sizeof(*out_int_addr));
  1707. out_int_addr->octet[4] ^= 0x80;
  1708. }
  1709. /* P2P IF Address change to Virtual Interface MAC Address */
  1710. void
  1711. wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id)
  1712. {
  1713. wifi_p2p_ie_t *ie = (wifi_p2p_ie_t*) buf;
  1714. u16 len = ie->len;
  1715. u8 *subel;
  1716. u8 subelt_id;
  1717. u16 subelt_len;
  1718. CFGP2P_DBG((" Enter\n"));
  1719. /* Point subel to the P2P IE's subelt field.
  1720. * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
  1721. */
  1722. subel = ie->subelts;
  1723. len -= 4; /* exclude OUI + OUI_TYPE */
  1724. while (len >= 3) {
  1725. /* attribute id */
  1726. subelt_id = *subel;
  1727. subel += 1;
  1728. len -= 1;
  1729. /* 2-byte little endian */
  1730. subelt_len = *subel++;
  1731. subelt_len |= *subel++ << 8;
  1732. len -= 2;
  1733. len -= subelt_len; /* for the remaining subelt fields */
  1734. if (subelt_id == element_id) {
  1735. if (subelt_id == P2P_SEID_INTINTADDR) {
  1736. memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
  1737. CFGP2P_INFO(("Intended P2P Interface Address ATTR FOUND\n"));
  1738. } else if (subelt_id == P2P_SEID_DEV_ID) {
  1739. memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
  1740. CFGP2P_INFO(("Device ID ATTR FOUND\n"));
  1741. } else if (subelt_id == P2P_SEID_DEV_INFO) {
  1742. memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
  1743. CFGP2P_INFO(("Device INFO ATTR FOUND\n"));
  1744. } else if (subelt_id == P2P_SEID_GROUP_ID) {
  1745. memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
  1746. CFGP2P_INFO(("GROUP ID ATTR FOUND\n"));
  1747. } return;
  1748. } else {
  1749. CFGP2P_DBG(("OTHER id : %d\n", subelt_id));
  1750. }
  1751. subel += subelt_len;
  1752. }
  1753. }
  1754. /*
  1755. * Check if a BSS is up.
  1756. * This is a common implementation called by most OSL implementations of
  1757. * p2posl_bss_isup(). DO NOT call this function directly from the
  1758. * common code -- call p2posl_bss_isup() instead to allow the OSL to
  1759. * override the common implementation if necessary.
  1760. */
  1761. bool
  1762. wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx)
  1763. {
  1764. s32 result, val;
  1765. bool isup = false;
  1766. s8 getbuf[64];
  1767. /* Check if the BSS is up */
  1768. *(int*)getbuf = -1;
  1769. result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
  1770. sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
  1771. if (result != 0) {
  1772. CFGP2P_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
  1773. CFGP2P_ERR(("NOTE: this ioctl error is normal "
  1774. "when the BSS has not been created yet.\n"));
  1775. } else {
  1776. val = *(int*)getbuf;
  1777. val = dtoh32(val);
  1778. CFGP2P_INFO(("---cfg bss -C %d ==> %d\n", bsscfg_idx, val));
  1779. isup = (val ? TRUE : FALSE);
  1780. }
  1781. return isup;
  1782. }
  1783. /* Bring up or down a BSS */
  1784. s32
  1785. wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 up)
  1786. {
  1787. s32 ret = BCME_OK;
  1788. s32 val = up ? 1 : 0;
  1789. struct {
  1790. s32 cfg;
  1791. s32 val;
  1792. } bss_setbuf;
  1793. bss_setbuf.cfg = htod32(bsscfg_idx);
  1794. bss_setbuf.val = htod32(val);
  1795. CFGP2P_INFO(("---cfg bss -C %d %s\n", bsscfg_idx, up ? "up" : "down"));
  1796. ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
  1797. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  1798. if (ret != 0) {
  1799. CFGP2P_ERR(("'bss %d' failed with %d\n", up, ret));
  1800. }
  1801. return ret;
  1802. }
  1803. /* Check if 'p2p' is supported in the driver */
  1804. s32
  1805. wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev)
  1806. {
  1807. s32 ret = BCME_OK;
  1808. s32 p2p_supported = 0;
  1809. ret = wldev_iovar_getint(ndev, "p2p",
  1810. &p2p_supported);
  1811. if (ret < 0) {
  1812. if (ret == BCME_UNSUPPORTED) {
  1813. CFGP2P_INFO(("p2p is unsupported\n"));
  1814. return 0;
  1815. } else {
  1816. CFGP2P_ERR(("cfg p2p error %d\n", ret));
  1817. return ret;
  1818. }
  1819. }
  1820. if (p2p_supported == 1) {
  1821. CFGP2P_INFO(("p2p is supported\n"));
  1822. } else {
  1823. CFGP2P_INFO(("p2p is unsupported\n"));
  1824. p2p_supported = 0;
  1825. }
  1826. return p2p_supported;
  1827. }
  1828. /* Cleanup P2P resources */
  1829. s32
  1830. wl_cfgp2p_down(struct bcm_cfg80211 *cfg)
  1831. {
  1832. struct net_device *ndev = NULL;
  1833. struct wireless_dev *wdev = NULL;
  1834. s32 i = 0, index = -1;
  1835. #if defined(WL_CFG80211_P2P_DEV_IF)
  1836. ndev = bcmcfg_to_prmry_ndev(cfg);
  1837. wdev = bcmcfg_to_p2p_wdev(cfg);
  1838. #elif defined(WL_ENABLE_P2P_IF)
  1839. ndev = cfg->p2p_net ? cfg->p2p_net : bcmcfg_to_prmry_ndev(cfg);
  1840. wdev = ndev_to_wdev(ndev);
  1841. #endif /* WL_CFG80211_P2P_DEV_IF */
  1842. wl_cfgp2p_cancel_listen(cfg, ndev, wdev, TRUE);
  1843. for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
  1844. index = wl_to_p2p_bss_bssidx(cfg, i);
  1845. if (index != WL_INVALID)
  1846. wl_cfgp2p_clear_management_ie(cfg, index);
  1847. }
  1848. wl_cfgp2p_deinit_priv(cfg);
  1849. return 0;
  1850. }
  1851. s32
  1852. wl_cfgp2p_set_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
  1853. {
  1854. s32 ret = -1;
  1855. int count, start, duration;
  1856. wl_p2p_sched_t dongle_noa;
  1857. CFGP2P_DBG((" Enter\n"));
  1858. memset(&dongle_noa, 0, sizeof(dongle_noa));
  1859. if (cfg->p2p && cfg->p2p->vif_created) {
  1860. cfg->p2p->noa.desc[0].start = 0;
  1861. sscanf(buf, "%10d %10d %10d", &count, &start, &duration);
  1862. CFGP2P_DBG(("set_p2p_noa count %d start %d duration %d\n",
  1863. count, start, duration));
  1864. if (count != -1)
  1865. cfg->p2p->noa.desc[0].count = count;
  1866. /* supplicant gives interval as start */
  1867. if (start != -1)
  1868. cfg->p2p->noa.desc[0].interval = start;
  1869. if (duration != -1)
  1870. cfg->p2p->noa.desc[0].duration = duration;
  1871. if (cfg->p2p->noa.desc[0].count < 255 && cfg->p2p->noa.desc[0].count > 1) {
  1872. cfg->p2p->noa.desc[0].start = 0;
  1873. dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
  1874. dongle_noa.action = WL_P2P_SCHED_ACTION_NONE;
  1875. dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS;
  1876. }
  1877. else if (cfg->p2p->noa.desc[0].count == 1) {
  1878. cfg->p2p->noa.desc[0].start = 200;
  1879. dongle_noa.type = WL_P2P_SCHED_TYPE_REQ_ABS;
  1880. dongle_noa.action = WL_P2P_SCHED_ACTION_GOOFF;
  1881. dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS;
  1882. }
  1883. else if (cfg->p2p->noa.desc[0].count == 0) {
  1884. cfg->p2p->noa.desc[0].start = 0;
  1885. dongle_noa.action = WL_P2P_SCHED_ACTION_RESET;
  1886. }
  1887. else {
  1888. /* Continuous NoA interval. */
  1889. dongle_noa.action = WL_P2P_SCHED_ACTION_DOZE;
  1890. dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
  1891. if ((cfg->p2p->noa.desc[0].interval == 102) ||
  1892. (cfg->p2p->noa.desc[0].interval == 100)) {
  1893. cfg->p2p->noa.desc[0].start = 100 -
  1894. cfg->p2p->noa.desc[0].duration;
  1895. dongle_noa.option = WL_P2P_SCHED_OPTION_BCNPCT;
  1896. }
  1897. else {
  1898. dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL;
  1899. }
  1900. }
  1901. /* Put the noa descriptor in dongle format for dongle */
  1902. dongle_noa.desc[0].count = htod32(cfg->p2p->noa.desc[0].count);
  1903. if (dongle_noa.option == WL_P2P_SCHED_OPTION_BCNPCT) {
  1904. dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start);
  1905. dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration);
  1906. }
  1907. else {
  1908. dongle_noa.desc[0].start = htod32(cfg->p2p->noa.desc[0].start*1000);
  1909. dongle_noa.desc[0].duration = htod32(cfg->p2p->noa.desc[0].duration*1000);
  1910. }
  1911. dongle_noa.desc[0].interval = htod32(cfg->p2p->noa.desc[0].interval*1000);
  1912. ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION),
  1913. "p2p_noa", &dongle_noa, sizeof(dongle_noa), cfg->ioctl_buf,
  1914. WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  1915. if (ret < 0) {
  1916. CFGP2P_ERR(("fw set p2p_noa failed %d\n", ret));
  1917. }
  1918. }
  1919. else {
  1920. CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
  1921. }
  1922. return ret;
  1923. }
  1924. s32
  1925. wl_cfgp2p_get_p2p_noa(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int buf_len)
  1926. {
  1927. wifi_p2p_noa_desc_t *noa_desc;
  1928. int len = 0, i;
  1929. char _buf[200];
  1930. CFGP2P_DBG((" Enter\n"));
  1931. buf[0] = '\0';
  1932. if (cfg->p2p && cfg->p2p->vif_created) {
  1933. if (cfg->p2p->noa.desc[0].count || cfg->p2p->ops.ops) {
  1934. _buf[0] = 1; /* noa index */
  1935. _buf[1] = (cfg->p2p->ops.ops ? 0x80: 0) |
  1936. (cfg->p2p->ops.ctw & 0x7f); /* ops + ctw */
  1937. len += 2;
  1938. if (cfg->p2p->noa.desc[0].count) {
  1939. noa_desc = (wifi_p2p_noa_desc_t*)&_buf[len];
  1940. noa_desc->cnt_type = cfg->p2p->noa.desc[0].count;
  1941. noa_desc->duration = cfg->p2p->noa.desc[0].duration;
  1942. noa_desc->interval = cfg->p2p->noa.desc[0].interval;
  1943. noa_desc->start = cfg->p2p->noa.desc[0].start;
  1944. len += sizeof(wifi_p2p_noa_desc_t);
  1945. }
  1946. if (buf_len <= len * 2) {
  1947. CFGP2P_ERR(("ERROR: buf_len %d in not enough for"
  1948. "returning noa in string format\n", buf_len));
  1949. return -1;
  1950. }
  1951. /* We have to convert the buffer data into ASCII strings */
  1952. for (i = 0; i < len; i++) {
  1953. snprintf(buf, 3, "%02x", _buf[i]);
  1954. buf += 2;
  1955. }
  1956. buf[i*2] = '\0';
  1957. }
  1958. }
  1959. else {
  1960. CFGP2P_ERR(("ERROR: get_noa in non-p2p mode\n"));
  1961. return -1;
  1962. }
  1963. return len * 2;
  1964. }
  1965. s32
  1966. wl_cfgp2p_set_p2p_ps(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
  1967. {
  1968. int ps, ctw;
  1969. int ret = -1;
  1970. s32 legacy_ps;
  1971. struct net_device *dev;
  1972. CFGP2P_DBG((" Enter\n"));
  1973. if (cfg->p2p && cfg->p2p->vif_created) {
  1974. sscanf(buf, "%10d %10d %10d", &legacy_ps, &ps, &ctw);
  1975. CFGP2P_DBG((" Enter legacy_ps %d ps %d ctw %d\n", legacy_ps, ps, ctw));
  1976. dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION);
  1977. if (ctw != -1) {
  1978. cfg->p2p->ops.ctw = ctw;
  1979. ret = 0;
  1980. }
  1981. if (ps != -1) {
  1982. cfg->p2p->ops.ops = ps;
  1983. ret = wldev_iovar_setbuf(dev,
  1984. "p2p_ops", &cfg->p2p->ops, sizeof(cfg->p2p->ops),
  1985. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  1986. if (ret < 0) {
  1987. CFGP2P_ERR(("fw set p2p_ops failed %d\n", ret));
  1988. }
  1989. }
  1990. if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) {
  1991. ret = wldev_ioctl(dev,
  1992. WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true);
  1993. if (unlikely(ret))
  1994. CFGP2P_ERR(("error (%d)\n", ret));
  1995. wl_cfg80211_update_power_mode(dev);
  1996. }
  1997. else
  1998. CFGP2P_ERR(("ilegal setting\n"));
  1999. }
  2000. else {
  2001. CFGP2P_ERR(("ERROR: set_p2p_ps in non-p2p mode\n"));
  2002. ret = -1;
  2003. }
  2004. return ret;
  2005. }
  2006. u8 *
  2007. wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
  2008. {
  2009. wifi_p2p_ie_t *ie = NULL;
  2010. u16 len = 0;
  2011. u8 *subel;
  2012. u8 subelt_id;
  2013. u16 subelt_len;
  2014. if (!buf) {
  2015. WL_ERR(("P2P IE not present"));
  2016. return 0;
  2017. }
  2018. ie = (wifi_p2p_ie_t*) buf;
  2019. len = ie->len;
  2020. /* Point subel to the P2P IE's subelt field.
  2021. * Subtract the preceding fields (id, len, OUI, oui_type) from the length.
  2022. */
  2023. subel = ie->subelts;
  2024. len -= 4; /* exclude OUI + OUI_TYPE */
  2025. while (len >= 3) {
  2026. /* attribute id */
  2027. subelt_id = *subel;
  2028. subel += 1;
  2029. len -= 1;
  2030. /* 2-byte little endian */
  2031. subelt_len = *subel++;
  2032. subelt_len |= *subel++ << 8;
  2033. len -= 2;
  2034. len -= subelt_len; /* for the remaining subelt fields */
  2035. if (subelt_id == element_id) {
  2036. /* This will point to start of subelement attrib after
  2037. * attribute id & len
  2038. */
  2039. return subel;
  2040. }
  2041. /* Go to next subelement */
  2042. subel += subelt_len;
  2043. }
  2044. /* Not Found */
  2045. return NULL;
  2046. }
  2047. #define P2P_GROUP_CAPAB_GO_BIT 0x01
  2048. u8*
  2049. wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib)
  2050. {
  2051. bcm_tlv_t *ie;
  2052. u8* pAttrib;
  2053. CFGP2P_INFO(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
  2054. while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
  2055. if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len) == TRUE) {
  2056. /* Have the P2p ie. Now check for attribute */
  2057. if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(parse, attrib)) != NULL) {
  2058. CFGP2P_INFO(("P2P attribute %d was found at parse %p",
  2059. attrib, parse));
  2060. return pAttrib;
  2061. }
  2062. else {
  2063. parse += (ie->len + TLV_HDR_LEN);
  2064. len -= (ie->len + TLV_HDR_LEN);
  2065. CFGP2P_INFO(("P2P Attribute %d not found Moving parse"
  2066. " to %p len to %d", attrib, parse, len));
  2067. }
  2068. }
  2069. else {
  2070. /* It was not p2p IE. parse will get updated automatically to next TLV */
  2071. CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, len));
  2072. }
  2073. }
  2074. CFGP2P_ERR(("P2P attribute %d was NOT found", attrib));
  2075. return NULL;
  2076. }
  2077. u8 *
  2078. wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length)
  2079. {
  2080. u8 *capability = NULL;
  2081. bool p2p_go = 0;
  2082. u8 *ptr = NULL;
  2083. if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
  2084. bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) {
  2085. WL_ERR(("P2P Capability attribute not found"));
  2086. return NULL;
  2087. }
  2088. /* Check Group capability for Group Owner bit */
  2089. p2p_go = capability[1] & P2P_GROUP_CAPAB_GO_BIT;
  2090. if (!p2p_go) {
  2091. return bi->BSSID.octet;
  2092. }
  2093. /* In probe responses, DEVICE INFO attribute will be present */
  2094. if (!(ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
  2095. bi->ie_length, P2P_SEID_DEV_INFO))) {
  2096. /* If DEVICE_INFO is not found, this might be a beacon frame.
  2097. * check for DEVICE_ID in the beacon frame.
  2098. */
  2099. ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
  2100. bi->ie_length, P2P_SEID_DEV_ID);
  2101. }
  2102. if (!ptr)
  2103. WL_ERR((" Both DEVICE_ID & DEVICE_INFO attribute not present in P2P IE "));
  2104. return ptr;
  2105. }
  2106. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
  2107. static void
  2108. wl_cfgp2p_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
  2109. {
  2110. snprintf(info->driver, sizeof(info->driver), "p2p");
  2111. snprintf(info->version, sizeof(info->version), "%lu", (unsigned long)(0));
  2112. }
  2113. struct ethtool_ops cfgp2p_ethtool_ops = {
  2114. .get_drvinfo = wl_cfgp2p_ethtool_get_drvinfo
  2115. };
  2116. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
  2117. #if defined(WL_ENABLE_P2P_IF) || defined(WL_NEWCFG_PRIVCMD_SUPPORT)
  2118. s32
  2119. wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
  2120. {
  2121. int ret = 0;
  2122. struct net_device* net = NULL;
  2123. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  2124. struct wireless_dev *wdev = NULL;
  2125. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  2126. uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 };
  2127. if (cfg->p2p_net) {
  2128. CFGP2P_ERR(("p2p_net defined already.\n"));
  2129. return -EINVAL;
  2130. }
  2131. /* Allocate etherdev, including space for private structure */
  2132. if (!(net = alloc_etherdev(sizeof(struct bcm_cfg80211 *)))) {
  2133. CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __FUNCTION__));
  2134. return -ENODEV;
  2135. }
  2136. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  2137. wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
  2138. if (unlikely(!wdev)) {
  2139. WL_ERR(("Could not allocate wireless device\n"));
  2140. free_netdev(net);
  2141. return -ENOMEM;
  2142. }
  2143. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  2144. strncpy(net->name, "p2p%d", sizeof(net->name) - 1);
  2145. net->name[IFNAMSIZ - 1] = '\0';
  2146. /* Copy the reference to bcm_cfg80211 */
  2147. memcpy((void *)netdev_priv(net), &cfg, sizeof(struct bcm_cfg80211 *));
  2148. #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
  2149. ASSERT(!net->open);
  2150. net->do_ioctl = wl_cfgp2p_do_ioctl;
  2151. net->hard_start_xmit = wl_cfgp2p_start_xmit;
  2152. net->open = wl_cfgp2p_if_open;
  2153. net->stop = wl_cfgp2p_if_stop;
  2154. #else
  2155. ASSERT(!net->netdev_ops);
  2156. net->netdev_ops = &wl_cfgp2p_if_ops;
  2157. #endif
  2158. /* Register with a dummy MAC addr */
  2159. memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
  2160. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  2161. wdev->wiphy = cfg->wdev->wiphy;
  2162. wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
  2163. net->ieee80211_ptr = wdev;
  2164. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  2165. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
  2166. net->ethtool_ops = &cfgp2p_ethtool_ops;
  2167. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
  2168. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  2169. SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy));
  2170. /* Associate p2p0 network interface with new wdev */
  2171. wdev->netdev = net;
  2172. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  2173. ret = register_netdev(net);
  2174. if (ret) {
  2175. CFGP2P_ERR((" register_netdevice failed (%d)\n", ret));
  2176. free_netdev(net);
  2177. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  2178. kfree(wdev);
  2179. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  2180. return -ENODEV;
  2181. }
  2182. /* store p2p net ptr for further reference. Note that iflist won't have this
  2183. * entry as there corresponding firmware interface is a "Hidden" interface.
  2184. */
  2185. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  2186. cfg->p2p_wdev = wdev;
  2187. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  2188. cfg->p2p_net = net;
  2189. printk("%s: P2P Interface Registered\n", net->name);
  2190. return ret;
  2191. }
  2192. s32
  2193. wl_cfgp2p_unregister_ndev(struct bcm_cfg80211 *cfg)
  2194. {
  2195. if (!cfg || !cfg->p2p_net) {
  2196. CFGP2P_ERR(("Invalid Ptr\n"));
  2197. return -EINVAL;
  2198. }
  2199. unregister_netdev(cfg->p2p_net);
  2200. free_netdev(cfg->p2p_net);
  2201. return 0;
  2202. }
  2203. static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev)
  2204. {
  2205. if (skb)
  2206. {
  2207. CFGP2P_DBG(("(%s) is not used for data operations.Droping the packet.\n",
  2208. ndev->name));
  2209. dev_kfree_skb_any(skb);
  2210. }
  2211. return 0;
  2212. }
  2213. static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd)
  2214. {
  2215. int ret = 0;
  2216. struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
  2217. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  2218. /* There is no ifidx corresponding to p2p0 in our firmware. So we should
  2219. * not Handle any IOCTL cmds on p2p0 other than ANDROID PRIVATE CMDs.
  2220. * For Android PRIV CMD handling map it to primary I/F
  2221. */
  2222. if (cmd == SIOCDEVPRIVATE+1) {
  2223. ret = wl_android_priv_cmd(ndev, ifr, cmd);
  2224. } else {
  2225. CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n",
  2226. __FUNCTION__, cmd));
  2227. return -1;
  2228. }
  2229. return ret;
  2230. }
  2231. #endif /* WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT */
  2232. #if defined(CUSTOMER_HW4) && defined(PLATFORM_SLP)
  2233. char g_if_flag = 0;
  2234. extern void dhd_stop_p2p(void);
  2235. void
  2236. wl_cfgp2p_probe_init_priv(struct bcm_cfg80211 *cfg)
  2237. {
  2238. #define INIT_IE(IE_TYPE, BSS_TYPE) \
  2239. do { \
  2240. memset(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \
  2241. sizeof(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \
  2242. wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \
  2243. } while (0);
  2244. INIT_IE(probe_req, P2PAPI_BSSCFG_PRIMARY);
  2245. INIT_IE(probe_res, P2PAPI_BSSCFG_PRIMARY);
  2246. INIT_IE(assoc_req, P2PAPI_BSSCFG_PRIMARY);
  2247. INIT_IE(assoc_res, P2PAPI_BSSCFG_PRIMARY);
  2248. INIT_IE(beacon, P2PAPI_BSSCFG_PRIMARY);
  2249. INIT_IE(probe_req, P2PAPI_BSSCFG_DEVICE);
  2250. INIT_IE(probe_res, P2PAPI_BSSCFG_DEVICE);
  2251. INIT_IE(assoc_req, P2PAPI_BSSCFG_DEVICE);
  2252. INIT_IE(assoc_res, P2PAPI_BSSCFG_DEVICE);
  2253. INIT_IE(beacon, P2PAPI_BSSCFG_DEVICE);
  2254. INIT_IE(probe_req, P2PAPI_BSSCFG_CONNECTION);
  2255. INIT_IE(probe_res, P2PAPI_BSSCFG_CONNECTION);
  2256. INIT_IE(assoc_req, P2PAPI_BSSCFG_CONNECTION);
  2257. INIT_IE(assoc_res, P2PAPI_BSSCFG_CONNECTION);
  2258. INIT_IE(beacon, P2PAPI_BSSCFG_CONNECTION);
  2259. #undef INIT_IE
  2260. }
  2261. #endif /* CUSTOMER_HW4 && PLATFORM_SLP */
  2262. #if defined(WL_ENABLE_P2P_IF)
  2263. static int wl_cfgp2p_if_open(struct net_device *net)
  2264. {
  2265. struct wireless_dev *wdev = net->ieee80211_ptr;
  2266. if (!wdev || !wl_cfg80211_is_p2p_active())
  2267. return -EINVAL;
  2268. WL_TRACE(("Enter\n"));
  2269. #if !defined(WL_IFACE_COMB_NUM_CHANNELS)
  2270. /* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now,
  2271. * do it here. This will make sure that in concurrent mode, supplicant
  2272. * is not dependent on a particular order of interface initialization.
  2273. * i.e you may give wpa_supp -iwlan0 -N -ip2p0 or wpa_supp -ip2p0 -N
  2274. * -iwlan0.
  2275. */
  2276. wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)
  2277. | BIT(NL80211_IFTYPE_P2P_GO));
  2278. #endif /* !WL_IFACE_COMB_NUM_CHANNELS */
  2279. wl_cfg80211_do_driver_init(net);
  2280. return 0;
  2281. }
  2282. static int wl_cfgp2p_if_stop(struct net_device *net)
  2283. {
  2284. struct wireless_dev *wdev = net->ieee80211_ptr;
  2285. if (!wdev)
  2286. return -EINVAL;
  2287. wl_cfg80211_scan_stop(net);
  2288. #if !defined(WL_IFACE_COMB_NUM_CHANNELS)
  2289. wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes)
  2290. & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)|
  2291. BIT(NL80211_IFTYPE_P2P_GO)));
  2292. #endif /* !WL_IFACE_COMB_NUM_CHANNELS */
  2293. return 0;
  2294. }
  2295. bool wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops)
  2296. {
  2297. return (if_ops == &wl_cfgp2p_if_ops);
  2298. }
  2299. #endif /* WL_ENABLE_P2P_IF */
  2300. #if defined(WL_CFG80211_P2P_DEV_IF)
  2301. struct wireless_dev *
  2302. wl_cfgp2p_add_p2p_disc_if(struct bcm_cfg80211 *cfg)
  2303. {
  2304. struct wireless_dev *wdev = NULL;
  2305. struct ether_addr primary_mac;
  2306. if (!cfg)
  2307. return ERR_PTR(-EINVAL);
  2308. WL_TRACE(("Enter\n"));
  2309. if (cfg->p2p_wdev) {
  2310. CFGP2P_ERR(("p2p_wdev defined already.\n"));
  2311. #if defined(CUSTOMER_HW4)
  2312. wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
  2313. CFGP2P_ERR(("p2p_wdev deleted.\n"));
  2314. #else
  2315. return ERR_PTR(-ENFILE);
  2316. #endif
  2317. }
  2318. wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
  2319. if (unlikely(!wdev)) {
  2320. WL_ERR(("Could not allocate wireless device\n"));
  2321. return ERR_PTR(-ENOMEM);
  2322. }
  2323. memset(&primary_mac, 0, sizeof(primary_mac));
  2324. get_primary_mac(cfg, &primary_mac);
  2325. wl_cfgp2p_generate_bss_mac(&primary_mac,
  2326. &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
  2327. wdev->wiphy = cfg->wdev->wiphy;
  2328. wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
  2329. memcpy(wdev->address, &cfg->p2p->dev_addr, ETHER_ADDR_LEN);
  2330. #if defined(WL_NEWCFG_PRIVCMD_SUPPORT)
  2331. if (cfg->p2p_net)
  2332. memcpy(cfg->p2p_net->dev_addr, &cfg->p2p->dev_addr, ETHER_ADDR_LEN);
  2333. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  2334. /* store p2p wdev ptr for further reference. */
  2335. cfg->p2p_wdev = wdev;
  2336. CFGP2P_ERR(("P2P interface registered\n"));
  2337. #if defined(CUSTOMER_HW4) && defined(PLATFORM_SLP)
  2338. g_if_flag |= 0x4; /* DHD_FLAG_P2P_MODE */
  2339. WL_TRACE(("%s: p2p0 IF up : g_if_flag(%d)\n", __FUNCTION__, g_if_flag));
  2340. #endif /* CUSTOMER_HW4 && PLATFORM_SLP */
  2341. return wdev;
  2342. }
  2343. int
  2344. wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
  2345. {
  2346. int ret = 0;
  2347. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  2348. if (!cfg)
  2349. return -EINVAL;
  2350. WL_TRACE(("Enter\n"));
  2351. ret = wl_cfgp2p_set_firm_p2p(cfg);
  2352. if (unlikely(ret < 0)) {
  2353. CFGP2P_ERR(("Set P2P in firmware failed, ret=%d\n", ret));
  2354. goto exit;
  2355. }
  2356. ret = wl_cfgp2p_enable_discovery(cfg, bcmcfg_to_prmry_ndev(cfg), NULL, 0);
  2357. if (unlikely(ret < 0)) {
  2358. CFGP2P_ERR(("P2P enable discovery failed, ret=%d\n", ret));
  2359. goto exit;
  2360. }
  2361. p2p_on(cfg) = true;
  2362. CFGP2P_DBG(("P2P interface started\n"));
  2363. exit:
  2364. return ret;
  2365. }
  2366. void
  2367. wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
  2368. {
  2369. int ret = 0;
  2370. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  2371. if (!cfg)
  2372. return;
  2373. WL_TRACE(("Enter\n"));
  2374. ret = wl_cfg80211_scan_stop(wdev);
  2375. if (unlikely(ret < 0)) {
  2376. CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
  2377. }
  2378. if (!cfg->p2p)
  2379. return;
  2380. ret = wl_cfgp2p_disable_discovery(cfg);
  2381. if (unlikely(ret < 0)) {
  2382. CFGP2P_ERR(("P2P disable discovery failed, ret=%d\n", ret));
  2383. }
  2384. p2p_on(cfg) = false;
  2385. CFGP2P_DBG(("P2P interface stopped\n"));
  2386. return;
  2387. }
  2388. int
  2389. wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev, struct bcm_cfg80211 *cfg)
  2390. {
  2391. bool rollback_lock = false;
  2392. if (!wdev)
  2393. return -EINVAL;
  2394. WL_TRACE(("Enter\n"));
  2395. if (!rtnl_is_locked()) {
  2396. rtnl_lock();
  2397. rollback_lock = true;
  2398. }
  2399. cfg80211_unregister_wdev(wdev);
  2400. if (rollback_lock)
  2401. rtnl_unlock();
  2402. synchronize_rcu();
  2403. kfree(wdev);
  2404. if (cfg)
  2405. cfg->p2p_wdev = NULL;
  2406. CFGP2P_ERR(("P2P interface unregistered\n"));
  2407. #if defined(CUSTOMER_HW4) && defined(PLATFORM_SLP)
  2408. g_if_flag &= 0x1; /* DHD_FLAG_STA_MODE */
  2409. WL_TRACE(("%s: p2p0 IF down : g_if_flag(%d)\n", __FUNCTION__, g_if_flag));
  2410. wl_cfgp2p_probe_init_priv(cfg);
  2411. if (!g_if_flag) {
  2412. dhd_stop_p2p();
  2413. WL_TRACE(("%s: wlan0 IF down\n", __FUNCTION__));
  2414. }
  2415. #endif /* CUSTOMER_HW4 && PLATFORM_SLP */
  2416. return 0;
  2417. }
  2418. #endif /* WL_CFG80211_P2P_DEV_IF */
  2419. void
  2420. wl_cfgp2p_need_wait_actfrmae(struct bcm_cfg80211 *cfg, void *frame, u32 frame_len, bool tx)
  2421. {
  2422. wifi_p2p_pub_act_frame_t *pact_frm;
  2423. int status = 0;
  2424. if (!frame || (frame_len < (sizeof(*pact_frm) + WL_P2P_AF_STATUS_OFFSET - 1))) {
  2425. return;
  2426. }
  2427. if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
  2428. pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
  2429. if (pact_frm->subtype == P2P_PAF_GON_RSP && tx) {
  2430. CFGP2P_ACTION(("Check TX P2P Group Owner Negotiation Rsp Frame status\n"));
  2431. status = pact_frm->elts[WL_P2P_AF_STATUS_OFFSET];
  2432. if (status) {
  2433. cfg->need_wait_afrx = false;
  2434. return;
  2435. }
  2436. }
  2437. }
  2438. cfg->need_wait_afrx = true;
  2439. return;
  2440. }
  2441. int
  2442. wl_cfgp2p_is_p2p_specific_scan(struct cfg80211_scan_request *request)
  2443. {
  2444. if (request && (request->n_ssids == 1) &&
  2445. (request->n_channels == 1) &&
  2446. IS_P2P_SSID(request->ssids[0].ssid, WL_P2P_WILDCARD_SSID_LEN) &&
  2447. (request->ssids[0].ssid_len > WL_P2P_WILDCARD_SSID_LEN)) {
  2448. return true;
  2449. }
  2450. return false;
  2451. }