wl_cfgp2p.c 80 KB

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