2 * Broadcom Dongle Host Driver (DHD), common DHD core.
4 * Copyright (C) 1999-2011, Broadcom Corporation
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
24 * $Id: dhd_common.c,v 1.57.2.21.4.1 2011-02-01 19:36:23 $
32 #include <bcmendian.h>
33 #include <dngl_stats.h>
37 #include <proto/bcmevent.h>
40 #include <dhd_proto.h>
44 /*filters related headers*/
45 #include <proto/ethernet.h>
46 #include <proto/802.1d.h>
47 #include <proto/802.11.h>
48 #include <proto/bcmip.h>
49 /*filters related headers end*/
54 extern void htsf_update(struct dhd_info *dhd, void *data);
60 char fw_path[MOD_PARAM_PATHLEN];
61 char nv_path[MOD_PARAM_PATHLEN];
63 /* Last connection success/failure status */
64 uint32 dhd_conn_event;
65 uint32 dhd_conn_status;
66 uint32 dhd_conn_reason;
73 typedef struct wl_filter_tag {
76 uint8 filterdata[100];
80 #ifdef BCM_PKTFILTER_BASE_PORT
81 /* status table for wl_filter_pref_t */
87 } wl_filter_pref_status_t;
89 typedef struct wl_filter_pref {
90 uint8 set; /* 1 is configuration set, 0 is unset*/
91 uint8 type; /* 0x6 is TCP, 0x11 is UDP*/
92 wl_filter_pref_status_t status; /* 0 REMOVED, 1 REMOVE, 2 ADD , 3 ADDED */
93 uint port; /* Port Num*/
94 wl_filter_tag_t *filter_tag_p;
96 int set_unicast_add_filter(dhd_pub_t *dhd,wl_filter_tag_t *, wl_filter_pref_t *,int );
97 int set_unicast_remove_filter(dhd_pub_t *dhd,wl_filter_tag_t *, wl_filter_pref_t *);
99 int set_bcast_filter(dhd_pub_t *dhd, wl_filter_tag_t *);
100 int set_mcast_filter(dhd_pub_t *dhd, wl_filter_tag_t *);
102 int dhd_set_pktfilter_mode(dhd_pub_t *dhd, int flag);
103 int dhd_config_pktfilter(dhd_pub_t *dhd, uint32 id ,uint32 flag);
105 #define PKTFILTER_BCAST_ID 100
106 #define PKTFILTER_MCAST_ID 101
107 #define PKTFILTER_UCAST_ID 102
109 #define MAX_PKT_FILTERS 3
110 #ifdef BCM_PKTFILTER_BASE_PORT
111 #define MAX_PKT_PREFS MAX_PKT_FILTERS
113 wl_filter_tag_t filters[MAX_PKT_FILTERS];
114 #ifdef BCM_PKTFILTER_BASE_PORT
115 wl_filter_pref_t filters_pref[MAX_PKT_PREFS];
118 extern void dhd_ind_scan_confirm(void *h, bool status);
119 extern int dhd_iscan_in_progress(void *h);
120 void dhd_iscan_lock(void);
121 void dhd_iscan_unlock(void);
122 extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx);
124 /* Packet alignment for most efficient SDIO (can change based on platform) */
126 #define DHD_SDALIGN 32
128 #if !ISPOWEROF2(DHD_SDALIGN)
129 #error DHD_SDALIGN is not a power of 2!
133 const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on "
134 __DATE__ " at " __TIME__;
136 const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
139 void dhd_set_timer(void *bus, uint wdtick);
157 #if defined(DHD_DEBUG)
160 #endif /* defined(DHD_DEBUG) */
169 const bcm_iovar_t dhd_iovars[] = {
170 {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) },
172 {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
173 #endif /* DHD_DEBUG */
174 {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN },
175 {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0 },
176 {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0 },
177 {"dump", IOV_DUMP, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN },
179 {"cons", IOV_CONS, 0, IOVT_BUFFER, 0 },
180 {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0 },
182 {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0 },
183 {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0 },
184 {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0 },
185 {"bustype", IOV_BUS_TYPE, 0, IOVT_UINT32, 0},
187 {"pktdlystatsz", IOV_WLPKTDLYSTAT_SZ, 0, IOVT_UINT8, 0 },
189 {"changemtu", IOV_CHANGEMTU, 0, IOVT_UINT32, 0 },
194 dhd_common_init(osl_t *osh)
198 /* Init global variables at run-time, not as part of the declaration.
199 * This is required to support init/de-init of the driver. Initialization
200 * of globals as part of the declaration results in non-deterministic
201 * behavior since the value of the globals may be different on the
202 * first time that the driver is initialized vs subsequent initializations.
204 dhd_msg_level = DHD_ERROR_VAL;
205 /* Allocate private bus interface state */
206 if (!(cmn = MALLOC(osh, sizeof(dhd_cmn_t)))) {
207 DHD_ERROR(("%s: MALLOC failed\n", __FUNCTION__));
210 memset(cmn, 0, sizeof(dhd_cmn_t));
213 #ifdef CONFIG_BCM4329_FW_PATH
214 strncpy(fw_path, CONFIG_BCM4329_FW_PATH, MOD_PARAM_PATHLEN-1);
215 #else /* CONFIG_BCM4329_FW_PATH */
217 #endif /* CONFIG_BCM4329_FW_PATH */
218 #ifdef CONFIG_BCM4329_NVRAM_PATH
219 strncpy(nv_path, CONFIG_BCM4329_NVRAM_PATH, MOD_PARAM_PATHLEN-1);
220 #else /* CONFIG_BCM4329_NVRAM_PATH */
222 #endif /* CONFIG_BCM4329_NVRAM_PATH */
227 dhd_common_deinit(dhd_pub_t *dhd_pub)
230 dhd_cmn_t *cmn = dhd_pub->cmn;
237 MFREE(osh, cmn, sizeof(dhd_cmn_t));
241 dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen)
243 char eabuf[ETHER_ADDR_STR_LEN];
246 struct bcmstrbuf *strbuf = &b;
248 bcm_binit(strbuf, buf, buflen);
251 bcm_bprintf(strbuf, "%s\n", dhd_version);
252 bcm_bprintf(strbuf, "\n");
253 bcm_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
254 dhdp->up, dhdp->txoff, dhdp->busstate);
255 bcm_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n",
256 dhdp->hdrlen, dhdp->maxctl, dhdp->rxsz);
257 bcm_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %s\n",
258 dhdp->iswl, dhdp->drv_version, bcm_ether_ntoa(&dhdp->mac, eabuf));
259 bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", dhdp->bcmerror, dhdp->tickcnt);
261 bcm_bprintf(strbuf, "dongle stats:\n");
262 bcm_bprintf(strbuf, "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n",
263 dhdp->dstats.tx_packets, dhdp->dstats.tx_bytes,
264 dhdp->dstats.tx_errors, dhdp->dstats.tx_dropped);
265 bcm_bprintf(strbuf, "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n",
266 dhdp->dstats.rx_packets, dhdp->dstats.rx_bytes,
267 dhdp->dstats.rx_errors, dhdp->dstats.rx_dropped);
268 bcm_bprintf(strbuf, "multicast %ld\n", dhdp->dstats.multicast);
270 bcm_bprintf(strbuf, "bus stats:\n");
271 bcm_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n",
272 dhdp->tx_packets, dhdp->tx_multicast, dhdp->tx_errors);
273 bcm_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n",
274 dhdp->tx_ctlpkts, dhdp->tx_ctlerrs);
275 bcm_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld \n",
276 dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors);
277 bcm_bprintf(strbuf, "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld\n",
278 dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped);
279 bcm_bprintf(strbuf, "rx_readahead_cnt %ld tx_realloc %ld\n",
280 dhdp->rx_readahead_cnt, dhdp->tx_realloc);
281 bcm_bprintf(strbuf, "\n");
283 /* Add any prot info */
284 dhd_prot_dump(dhdp, strbuf);
285 bcm_bprintf(strbuf, "\n");
287 /* Add any bus info */
288 dhd_bus_dump(dhdp, strbuf);
290 return (!strbuf->size ? BCME_BUFTOOSHORT : 0);
294 dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, int ifindex)
303 return dhd_wl_ioctl(dhd_pub, ifindex, &ioc, arg, len);
308 dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len)
312 dhd_os_proto_block(dhd_pub);
313 ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len);
314 dhd_os_proto_unblock(dhd_pub);
320 dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const char *name,
321 void *params, int plen, void *arg, int len, int val_size)
326 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
327 DHD_TRACE(("%s: actionid = %d; name %s\n", __FUNCTION__, actionid, name));
329 if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
332 if (plen >= (int)sizeof(int_val))
333 bcopy(params, &int_val, sizeof(int_val));
336 case IOV_GVAL(IOV_VERSION):
337 /* Need to have checked buffer length */
338 strncpy((char*)arg, dhd_version, len);
341 case IOV_GVAL(IOV_MSGLEVEL):
342 int_val = (int32)dhd_msg_level;
343 bcopy(&int_val, arg, val_size);
346 case IOV_SVAL(IOV_MSGLEVEL):
347 dhd_msg_level = int_val;
349 case IOV_GVAL(IOV_BCMERRORSTR):
350 strncpy((char *)arg, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN);
351 ((char *)arg)[BCME_STRLEN - 1] = 0x00;
354 case IOV_GVAL(IOV_BCMERROR):
355 int_val = (int32)dhd_pub->bcmerror;
356 bcopy(&int_val, arg, val_size);
359 case IOV_GVAL(IOV_WDTICK):
360 int_val = (int32)dhd_watchdog_ms;
361 bcopy(&int_val, arg, val_size);
364 case IOV_SVAL(IOV_WDTICK):
366 bcmerror = BCME_NOTUP;
369 dhd_os_wd_timer(dhd_pub, (uint)int_val);
372 case IOV_GVAL(IOV_DUMP):
373 bcmerror = dhd_dump(dhd_pub, arg, len);
377 case IOV_GVAL(IOV_DCONSOLE_POLL):
378 int_val = (int32)dhd_console_ms;
379 bcopy(&int_val, arg, val_size);
382 case IOV_SVAL(IOV_DCONSOLE_POLL):
383 dhd_console_ms = (uint)int_val;
386 case IOV_SVAL(IOV_CONS):
388 bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
390 #endif /* DHD_DEBUG */
392 case IOV_SVAL(IOV_CLEARCOUNTS):
393 dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
394 dhd_pub->tx_errors = dhd_pub->rx_errors = 0;
395 dhd_pub->tx_ctlpkts = dhd_pub->rx_ctlpkts = 0;
396 dhd_pub->tx_ctlerrs = dhd_pub->rx_ctlerrs = 0;
397 dhd_pub->rx_dropped = 0;
398 dhd_pub->rx_readahead_cnt = 0;
399 dhd_pub->tx_realloc = 0;
400 dhd_pub->wd_dpc_sched = 0;
401 memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats));
402 dhd_bus_clearcounts(dhd_pub);
406 case IOV_GVAL(IOV_IOCTLTIMEOUT): {
407 int_val = (int32)dhd_os_get_ioctl_resp_timeout();
408 bcopy(&int_val, arg, sizeof(int_val));
412 case IOV_SVAL(IOV_IOCTLTIMEOUT): {
414 bcmerror = BCME_BADARG;
416 dhd_os_set_ioctl_resp_timeout((unsigned int)int_val);
422 case IOV_GVAL(IOV_BUS_TYPE):
423 /* The dhd application query the driver to check if its usb or sdio. */
425 int_val = BUS_TYPE_USB;
427 int_val = BUS_TYPE_SDIO;
428 bcopy(&int_val, arg, val_size);
433 case IOV_GVAL(IOV_WLPKTDLYSTAT_SZ):
434 int_val = dhd_pub->htsfdlystat_sz;
435 bcopy(&int_val, arg, val_size);
438 case IOV_SVAL(IOV_WLPKTDLYSTAT_SZ):
439 dhd_pub->htsfdlystat_sz = int_val & 0xff;
440 printf("Setting tsfdlystat_sz:%d\n", dhd_pub->htsfdlystat_sz);
443 case IOV_SVAL(IOV_CHANGEMTU):
445 bcmerror = dhd_change_mtu(dhd_pub, int_val, 0);
449 bcmerror = BCME_UNSUPPORTED;
454 DHD_TRACE(("%s: actionid %d, bcmerror %d\n", __FUNCTION__, actionid, bcmerror));
458 /* Store the status of a connection attempt for later retrieval by an iovar */
460 dhd_store_conn_status(uint32 event, uint32 status, uint32 reason)
462 /* Do not overwrite a WLC_E_PRUNE with a WLC_E_SET_SSID
463 * because an encryption/rsn mismatch results in both events, and
464 * the important information is in the WLC_E_PRUNE.
466 if (!(event == WLC_E_SET_SSID && status == WLC_E_STATUS_FAIL &&
467 dhd_conn_event == WLC_E_PRUNE)) {
468 dhd_conn_event = event;
469 dhd_conn_status = status;
470 dhd_conn_reason = reason;
475 dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec)
478 int eprec = -1; /* precedence to evict from */
481 /* Fast case, precedence queue is not full and we are also not
482 * exceeding total queue length
484 if (!pktq_pfull(q, prec) && !pktq_full(q)) {
485 pktq_penq(q, prec, pkt);
489 /* Determine precedence from which to evict packet, if any */
490 if (pktq_pfull(q, prec))
492 else if (pktq_full(q)) {
493 p = pktq_peek_tail(q, &eprec);
499 /* Evict if needed */
501 /* Detect queueing to unconfigured precedence */
502 ASSERT(!pktq_pempty(q, eprec));
503 discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec);
504 if (eprec == prec && !discard_oldest)
505 return FALSE; /* refuse newer (incoming) packet */
506 /* Evict packet according to discard policy */
507 p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q, eprec);
510 PKTFREE(dhdp->osh, p, TRUE);
514 p = pktq_penq(q, prec, pkt);
521 dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name,
522 void *params, int plen, void *arg, int len, bool set)
526 const bcm_iovar_t *vi = NULL;
529 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
534 /* Get MUST have return space */
535 ASSERT(set || (arg && len));
537 /* Set does NOT take qualifiers */
538 ASSERT(!set || (!params && !plen));
540 if ((vi = bcm_iovar_lookup(dhd_iovars, name)) == NULL) {
541 bcmerror = BCME_UNSUPPORTED;
545 DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
546 name, (set ? "set" : "get"), len, plen));
548 /* set up 'params' pointer in case this is a set command so that
549 * the convenience int and bool code can be common to set and get
551 if (params == NULL) {
556 if (vi->type == IOVT_VOID)
558 else if (vi->type == IOVT_BUFFER)
561 /* all other types are integer sized */
562 val_size = sizeof(int);
564 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
566 bcmerror = dhd_doiovar(dhd_pub, vi, actionid, name, params, plen, arg, len, val_size);
573 dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen)
577 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
585 if (buflen < sizeof(int))
586 bcmerror = BCME_BUFTOOSHORT;
588 *(int*)buf = DHD_IOCTL_MAGIC;
591 case DHD_GET_VERSION:
592 if (buflen < sizeof(int))
593 bcmerror = -BCME_BUFTOOSHORT;
595 *(int*)buf = DHD_IOCTL_VERSION;
603 /* scan past the name to any arguments */
604 for (arg = buf, arglen = buflen; *arg && arglen; arg++, arglen--)
608 bcmerror = BCME_BUFTOOSHORT;
612 /* account for the NUL terminator */
615 /* call with the appropriate arguments */
616 if (ioc->cmd == DHD_GET_VAR)
617 bcmerror = dhd_iovar_op(dhd_pub, buf, arg, arglen,
618 buf, buflen, IOV_GET);
620 bcmerror = dhd_iovar_op(dhd_pub, buf, NULL, 0, arg, arglen, IOV_SET);
621 if (bcmerror != BCME_UNSUPPORTED)
624 /* not in generic table, try protocol module */
625 if (ioc->cmd == DHD_GET_VAR)
626 bcmerror = dhd_prot_iovar_op(dhd_pub, buf, arg,
627 arglen, buf, buflen, IOV_GET);
629 bcmerror = dhd_prot_iovar_op(dhd_pub, buf,
630 NULL, 0, arg, arglen, IOV_SET);
631 if (bcmerror != BCME_UNSUPPORTED)
634 /* if still not found, try bus module */
635 if (ioc->cmd == DHD_GET_VAR) {
636 bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
637 arg, arglen, buf, buflen, IOV_GET);
639 bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
640 NULL, 0, arg, arglen, IOV_SET);
647 bcmerror = BCME_UNSUPPORTED;
655 wl_show_host_event(wl_event_msg_t *event, void *event_data)
657 uint i, status, reason;
658 bool group = FALSE, flush_txq = FALSE, link = FALSE;
659 const char *auth_str;
660 const char *event_name;
662 char err_msg[256], eabuf[ETHER_ADDR_STR_LEN];
663 uint event_type, flags, auth_type, datalen;
665 event_type = ntoh32(event->event_type);
666 flags = ntoh16(event->flags);
667 status = ntoh32(event->status);
668 reason = ntoh32(event->reason);
669 auth_type = ntoh32(event->auth_type);
670 datalen = ntoh32(event->datalen);
672 /* debug dump of event messages */
673 sprintf(eabuf, "%02x:%02x:%02x:%02x:%02x:%02x",
674 (uchar)event->addr.octet[0]&0xff,
675 (uchar)event->addr.octet[1]&0xff,
676 (uchar)event->addr.octet[2]&0xff,
677 (uchar)event->addr.octet[3]&0xff,
678 (uchar)event->addr.octet[4]&0xff,
679 (uchar)event->addr.octet[5]&0xff);
681 event_name = "UNKNOWN";
682 for (i = 0; i < (uint)bcmevent_names_size; i++)
683 if (bcmevent_names[i].event == event_type)
684 event_name = bcmevent_names[i].name;
686 if (flags & WLC_EVENT_MSG_LINK)
688 if (flags & WLC_EVENT_MSG_GROUP)
690 if (flags & WLC_EVENT_MSG_FLUSHTXQ)
693 switch (event_type) {
697 DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
700 case WLC_E_ASSOC_IND:
701 case WLC_E_REASSOC_IND:
703 DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
708 if (status == WLC_E_STATUS_SUCCESS) {
709 DHD_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n", event_name, eabuf));
710 } else if (status == WLC_E_STATUS_TIMEOUT) {
711 DHD_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n", event_name, eabuf));
712 } else if (status == WLC_E_STATUS_FAIL) {
713 DHD_EVENT(("MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
714 event_name, eabuf, (int)reason));
716 DHD_EVENT(("MACEVENT: %s, MAC %s, unexpected status %d\n",
717 event_name, eabuf, (int)status));
721 case WLC_E_DEAUTH_IND:
722 case WLC_E_DISASSOC_IND:
723 DHD_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name, eabuf, (int)reason));
728 if (auth_type == DOT11_OPEN_SYSTEM)
729 auth_str = "Open System";
730 else if (auth_type == DOT11_SHARED_KEY)
731 auth_str = "Shared Key";
733 sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
736 if (event_type == WLC_E_AUTH_IND) {
737 DHD_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name, eabuf, auth_str));
738 } else if (status == WLC_E_STATUS_SUCCESS) {
739 DHD_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
740 event_name, eabuf, auth_str));
741 } else if (status == WLC_E_STATUS_TIMEOUT) {
742 DHD_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
743 event_name, eabuf, auth_str));
744 } else if (status == WLC_E_STATUS_FAIL) {
745 DHD_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n",
746 event_name, eabuf, auth_str, (int)reason));
754 if (status == WLC_E_STATUS_SUCCESS) {
755 DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
756 } else if (status == WLC_E_STATUS_FAIL) {
757 DHD_EVENT(("MACEVENT: %s, failed\n", event_name));
758 } else if (status == WLC_E_STATUS_NO_NETWORKS) {
759 DHD_EVENT(("MACEVENT: %s, no networks found\n", event_name));
761 DHD_EVENT(("MACEVENT: %s, unexpected status %d\n",
762 event_name, (int)status));
766 case WLC_E_BEACON_RX:
767 if (status == WLC_E_STATUS_SUCCESS) {
768 DHD_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
769 } else if (status == WLC_E_STATUS_FAIL) {
770 DHD_EVENT(("MACEVENT: %s, FAIL\n", event_name));
772 DHD_EVENT(("MACEVENT: %s, status %d\n", event_name, status));
777 DHD_EVENT(("MACEVENT: %s %s\n", event_name, link?"UP":"DOWN"));
780 case WLC_E_MIC_ERROR:
781 DHD_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
782 event_name, eabuf, group, flush_txq));
785 case WLC_E_ICV_ERROR:
786 case WLC_E_UNICAST_DECODE_ERROR:
787 case WLC_E_MULTICAST_DECODE_ERROR:
788 DHD_EVENT(("MACEVENT: %s, MAC %s\n",
793 DHD_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
796 case WLC_E_SCAN_COMPLETE:
797 case WLC_E_PMKID_CACHE:
798 DHD_EVENT(("MACEVENT: %s\n", event_name));
801 case WLC_E_PFN_NET_FOUND:
802 case WLC_E_PFN_NET_LOST:
803 case WLC_E_PFN_SCAN_COMPLETE:
804 DHD_EVENT(("PNOEVENT: %s\n", event_name));
809 DHD_EVENT(("MACEVENT: %s, status %d, reason %d\n",
810 event_name, (int)status, (int)reason));
813 #ifdef WIFI_ACT_FRAME
814 case WLC_E_ACTION_FRAME:
815 DHD_TRACE(("MACEVENT: %s Bssid %s\n", event_name, eabuf));
817 #endif /* WIFI_ACT_FRAME */
820 static uint32 seqnum_prev = 0;
825 buf = (uchar *) event_data;
826 memcpy(&hdr, buf, MSGTRACE_HDRLEN);
828 if (hdr.version != MSGTRACE_VERSION) {
829 printf("\nMACEVENT: %s [unsupported version --> "
830 "dhd version:%d dongle version:%d]\n",
831 event_name, MSGTRACE_VERSION, hdr.version);
832 /* Reset datalen to avoid display below */
837 /* There are 2 bytes available at the end of data */
838 buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0';
840 if (ntoh32(hdr.discarded_bytes) || ntoh32(hdr.discarded_printf)) {
841 printf("\nWLC_E_TRACE: [Discarded traces in dongle -->"
842 "discarded_bytes %d discarded_printf %d]\n",
843 ntoh32(hdr.discarded_bytes), ntoh32(hdr.discarded_printf));
846 nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1;
848 printf("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n",
849 ntoh32(hdr.seqnum), nblost);
851 seqnum_prev = ntoh32(hdr.seqnum);
853 /* Display the trace buffer. Advance from \n to \n to avoid display big
854 * printf (issue with Linux printk )
856 p = (char *)&buf[MSGTRACE_HDRLEN];
857 while ((s = strstr(p, "\n")) != NULL) {
864 /* Reset datalen to avoid display below */
871 DHD_EVENT(("MACEVENT: %s %d\n", event_name, ntoh32(*((int *)event_data))));
875 DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
876 event_name, event_type, eabuf, (int)status, (int)reason,
881 /* show any appended data */
883 buf = (uchar *) event_data;
884 DHD_EVENT((" data (%d) : ", datalen));
885 for (i = 0; i < datalen; i++)
886 DHD_EVENT((" 0x%02x ", *buf++));
890 #endif /* SHOW_EVENTS */
893 wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
894 wl_event_msg_t *event, void **data_ptr)
896 /* check whether packet is a BRCM event pkt */
897 bcm_event_t *pvt_data = (bcm_event_t *)pktdata;
899 uint32 type, status, reason, datalen;
903 if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) {
904 DHD_ERROR(("%s: mismatched OUI, bailing\n", __FUNCTION__));
908 /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
909 if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT) {
910 DHD_ERROR(("%s: mismatched subtype, bailing\n", __FUNCTION__));
914 *data_ptr = &pvt_data[1];
915 event_data = *data_ptr;
917 /* memcpy since BRCM event pkt may be unaligned. */
918 memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
920 type = ntoh32_ua((void *)&event->event_type);
921 flags = ntoh16_ua((void *)&event->flags);
922 status = ntoh32_ua((void *)&event->status);
923 reason = ntoh32_ua((void *)&event->reason);
924 datalen = ntoh32_ua((void *)&event->datalen);
925 evlen = datalen + sizeof(bcm_event_t);
931 dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data;
933 if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) {
934 if (ifevent->action == WLC_E_IF_ADD)
935 dhd_add_if(dhd_pub->info, ifevent->ifidx,
938 ifevent->flags, ifevent->bssidx);
940 dhd_del_if(dhd_pub->info, ifevent->ifidx);
942 DHD_ERROR(("%s: Invalid ifidx %d for %s\n",
943 __FUNCTION__, ifevent->ifidx, event->ifname));
946 /* send up the if event: btamp user needs it */
947 *ifidx = dhd_ifname2idx(dhd_pub->info, event->ifname);
948 /* push up to external supp/auth */
949 dhd_event(dhd_pub->info, (char *)pvt_data, evlen, *ifidx);
955 htsf_update(dhd_pub->info, event_data);
957 #endif /* WLMEDIA_HTSF */
958 case WLC_E_NDIS_LINK: {
959 uint32 temp = hton32(WLC_E_LINK);
961 memcpy((void *)(&pvt_data->event.event_type), &temp,
962 sizeof(pvt_data->event.event_type));
964 /* These are what external supplicant/authenticator wants */
968 case WLC_E_DEAUTH_IND:
970 case WLC_E_DISASSOC_IND:
971 DHD_EVENT(("%s: Link event %d, flags %x, status %x\n",
972 __FUNCTION__, type, flags, status));
975 *ifidx = dhd_ifname2idx(dhd_pub->info, event->ifname);
976 /* push up to external supp/auth */
977 dhd_event(dhd_pub->info, (char *)pvt_data, evlen, *ifidx);
978 DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n",
979 __FUNCTION__, type, flags, status));
981 /* put it back to WLC_E_NDIS_LINK */
982 if (type == WLC_E_NDIS_LINK) {
985 temp = ntoh32_ua((void *)&event->event_type);
986 DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp));
988 temp = ntoh32(WLC_E_NDIS_LINK);
989 memcpy((void *)(&pvt_data->event.event_type), &temp,
990 sizeof(pvt_data->event.event_type));
996 wl_show_host_event(event, (void *)event_data);
997 #endif /* SHOW_EVENTS */
1003 wl_event_to_host_order(wl_event_msg_t * evt)
1005 /* Event struct members passed from dongle to host are stored in network
1006 * byte order. Convert all members to host-order.
1008 evt->event_type = ntoh32(evt->event_type);
1009 evt->flags = ntoh16(evt->flags);
1010 evt->status = ntoh32(evt->status);
1011 evt->reason = ntoh32(evt->reason);
1012 evt->auth_type = ntoh32(evt->auth_type);
1013 evt->datalen = ntoh32(evt->datalen);
1014 evt->version = ntoh16(evt->version);
1018 dhd_print_buf(void *pbuf, int len, int bytes_per_line)
1021 unsigned char *buf = pbuf;
1023 if (bytes_per_line == 0) {
1024 bytes_per_line = len;
1027 for (i = 0; i < len; i++) {
1028 printf("%2.2x", *buf++);
1030 if (j == bytes_per_line) {
1040 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
1042 /* Convert user's input in hex pattern to byte-size mask */
1044 wl_pattern_atoh(char *src, char *dst)
1047 if (strncmp(src, "0x", 2) != 0 &&
1048 strncmp(src, "0X", 2) != 0) {
1049 DHD_ERROR(("Mask invalid format. Needs to start with 0x\n"));
1052 src = src + 2; /* Skip past 0x */
1053 if (strlen(src) % 2 != 0) {
1054 DHD_ERROR(("Mask invalid format. Needs to be of even length\n"));
1057 for (i = 0; *src != '\0'; i++) {
1059 strncpy(num, src, 2);
1061 dst[i] = (uint8)strtoul(num, NULL, 16);
1067 extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
1070 dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode)
1077 char *arg_save = 0, *arg_org = 0;
1080 wl_pkt_filter_enable_t enable_parm;
1081 wl_pkt_filter_enable_t * pkt_filterp;
1083 if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
1084 DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1088 memcpy(arg_save, arg, strlen(arg) + 1);
1090 argv[i] = bcmstrtok(&arg_save, " ", 0);
1093 if (NULL == argv[i]) {
1094 DHD_ERROR(("No args provided\n"));
1098 str = "pkt_filter_enable";
1099 str_len = strlen(str);
1100 strncpy(buf, str, str_len);
1101 buf[str_len] = '\0';
1102 buf_len = str_len + 1;
1104 pkt_filterp = (wl_pkt_filter_enable_t *)(buf + str_len + 1);
1106 /* Parse packet filter id. */
1107 enable_parm.id = htod32(strtoul(argv[i], NULL, 0));
1109 /* Parse enable/disable value. */
1110 enable_parm.enable = htod32(enable);
1112 buf_len += sizeof(enable_parm);
1113 memcpy((char *)pkt_filterp,
1115 sizeof(enable_parm));
1117 /* Enable/disable the specified filter. */
1118 rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
1119 rc = rc >= 0 ? 0 : rc;
1121 DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
1122 __FUNCTION__, arg, rc));
1124 DHD_TRACE(("%s: successfully added pktfilter %s\n",
1125 __FUNCTION__, arg));
1127 /* Contorl the master mode */
1128 bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf, sizeof(buf));
1129 rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
1130 rc = rc >= 0 ? 0 : rc;
1132 DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
1133 __FUNCTION__, arg, rc));
1137 MFREE(dhd->osh, arg_org, strlen(arg) + 1);
1141 dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
1144 wl_pkt_filter_t pkt_filter;
1145 wl_pkt_filter_t *pkt_filterp;
1150 uint32 pattern_size;
1151 char *argv[8], * buf = 0;
1153 char *arg_save = 0, *arg_org = 0;
1154 #define BUF_SIZE 2048
1156 if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
1157 DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1163 if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) {
1164 DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1168 memcpy(arg_save, arg, strlen(arg) + 1);
1170 if (strlen(arg) > BUF_SIZE) {
1171 DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf)));
1175 argv[i] = bcmstrtok(&arg_save, " ", 0);
1177 argv[i] = bcmstrtok(&arg_save, " ", 0);
1180 if (NULL == argv[i]) {
1181 DHD_ERROR(("No args provided\n"));
1185 str = "pkt_filter_add";
1186 str_len = strlen(str);
1187 strncpy(buf, str, str_len);
1188 buf[ str_len ] = '\0';
1189 buf_len = str_len + 1;
1191 pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
1193 /* Parse packet filter id. */
1194 pkt_filter.id = htod32(strtoul(argv[i], NULL, 0));
1196 if (NULL == argv[++i]) {
1197 DHD_ERROR(("Polarity not provided\n"));
1201 /* Parse filter polarity. */
1202 pkt_filter.negate_match = htod32(strtoul(argv[i], NULL, 0));
1204 if (NULL == argv[++i]) {
1205 DHD_ERROR(("Filter type not provided\n"));
1209 /* Parse filter type. */
1210 pkt_filter.type = htod32(strtoul(argv[i], NULL, 0));
1212 if (NULL == argv[++i]) {
1213 DHD_ERROR(("Offset not provided\n"));
1217 /* Parse pattern filter offset. */
1218 pkt_filter.u.pattern.offset = htod32(strtoul(argv[i], NULL, 0));
1220 if (NULL == argv[++i]) {
1221 DHD_ERROR(("Bitmask not provided\n"));
1225 /* Parse pattern filter mask. */
1227 htod32(wl_pattern_atoh(argv[i], (char *) pkt_filterp->u.pattern.mask_and_pattern));
1229 if (NULL == argv[++i]) {
1230 DHD_ERROR(("Pattern not provided\n"));
1234 /* Parse pattern filter pattern. */
1236 htod32(wl_pattern_atoh(argv[i],
1237 (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
1239 if (mask_size != pattern_size) {
1240 DHD_ERROR(("Mask and pattern not the same size\n"));
1244 pkt_filter.u.pattern.size_bytes = mask_size;
1245 buf_len += WL_PKT_FILTER_FIXED_LEN;
1246 buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
1248 /* Keep-alive attributes are set in local variable (keep_alive_pkt), and
1249 ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
1250 ** guarantee that the buffer is properly aligned.
1252 memcpy((char *)pkt_filterp,
1254 WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
1256 rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
1257 rc = rc >= 0 ? 0 : rc;
1260 DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
1261 __FUNCTION__, arg, rc));
1263 DHD_TRACE(("%s: successfully added pktfilter %s\n",
1264 __FUNCTION__, arg));
1268 MFREE(dhd->osh, arg_org, strlen(arg) + 1);
1271 MFREE(dhd->osh, buf, BUF_SIZE);
1275 dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode)
1280 bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
1281 retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
1282 retcode = retcode >= 0 ? 0 : retcode;
1284 DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, retcode = %d\n",
1285 __FUNCTION__, arp_mode, retcode));
1287 DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
1288 __FUNCTION__, arp_mode));
1292 dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
1297 bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
1298 retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
1299 retcode = retcode >= 0 ? 0 : retcode;
1301 DHD_TRACE(("%s: failed to enabe ARP offload to %d, retcode = %d\n",
1302 __FUNCTION__, arp_enable, retcode));
1304 DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
1305 __FUNCTION__, arp_enable));
1308 /* send up locally generated event */
1310 dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
1312 switch (ntoh32(event->event_type)) {
1317 /* Call per-port handler. */
1318 dhd_sendup_event(dhdp, event, data);
1325 uint iscan_thread_id;
1326 iscan_buf_t * iscan_chain = 0;
1329 dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf)
1331 iscan_buf_t *iscanbuf_alloc = 0;
1332 iscan_buf_t *iscanbuf_head;
1334 DHD_TRACE(("%s: Entered\n", __FUNCTION__));
1337 iscanbuf_alloc = (iscan_buf_t*)MALLOC(dhd->osh, sizeof(iscan_buf_t));
1338 if (iscanbuf_alloc == NULL)
1341 iscanbuf_alloc->next = NULL;
1342 iscanbuf_head = *iscanbuf;
1344 DHD_ISCAN(("%s: addr of allocated node = 0x%X"
1345 "addr of iscanbuf_head = 0x%X dhd = 0x%X\n",
1346 __FUNCTION__, iscanbuf_alloc, iscanbuf_head, dhd));
1348 if (iscanbuf_head == NULL) {
1349 *iscanbuf = iscanbuf_alloc;
1350 DHD_ISCAN(("%s: Head is allocated\n", __FUNCTION__));
1354 while (iscanbuf_head->next)
1355 iscanbuf_head = iscanbuf_head->next;
1357 iscanbuf_head->next = iscanbuf_alloc;
1361 return iscanbuf_alloc;
1365 dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete)
1367 iscan_buf_t *iscanbuf_free = 0;
1368 iscan_buf_t *iscanbuf_prv = 0;
1369 iscan_buf_t *iscanbuf_cur;
1370 dhd_pub_t *dhd = dhd_bus_pub(dhdp);
1371 DHD_TRACE(("%s: Entered\n", __FUNCTION__));
1375 iscanbuf_cur = iscan_chain;
1377 /* If iscan_delete is null then delete the entire
1378 * chain or else delete specific one provided
1380 if (!iscan_delete) {
1381 while (iscanbuf_cur) {
1382 iscanbuf_free = iscanbuf_cur;
1383 iscanbuf_cur = iscanbuf_cur->next;
1384 iscanbuf_free->next = 0;
1385 MFREE(dhd->osh, iscanbuf_free, sizeof(iscan_buf_t));
1389 while (iscanbuf_cur) {
1390 if (iscanbuf_cur == iscan_delete)
1392 iscanbuf_prv = iscanbuf_cur;
1393 iscanbuf_cur = iscanbuf_cur->next;
1396 iscanbuf_prv->next = iscan_delete->next;
1398 iscan_delete->next = 0;
1399 MFREE(dhd->osh, iscan_delete, sizeof(iscan_buf_t));
1408 dhd_iscan_result_buf(void)
1414 * delete disappeared AP from specific scan cache
1417 dhd_iscan_delete_bss(/* TBD void *dhdp, */ void *addr)
1419 int i = 0, j = 0, l = 0;
1420 iscan_buf_t *iscan_cur;
1421 wl_iscan_results_t *list;
1422 wl_scan_results_t *results;
1423 wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
1425 uchar *s_addr = addr;
1426 DHD_TRACE(("%s: Entered\n", __FUNCTION__));
1429 DHD_TRACE(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n",
1430 __FUNCTION__, s_addr[0], s_addr[1], s_addr[2],
1431 s_addr[3], s_addr[4], s_addr[5]));
1433 DHD_TRACE(("%s: Scan cache before delete\n",
1436 iscan_cur = dhd_iscan_result_buf();
1439 list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
1443 results = (wl_scan_results_t *)&list->results;
1447 if (results->version != WL_BSS_INFO_VERSION) {
1448 DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
1449 __FUNCTION__, results->version));
1453 bi = results->bss_info;
1454 for (i = 0; i < results->count; i++) {
1458 if (!memcmp(bi->BSSID.octet, addr, ETHER_ADDR_LEN)) {
1459 DHD_TRACE(("%s: Del BSS[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n",
1460 __FUNCTION__, l, i, bi->BSSID.octet[0], bi->BSSID.octet[1],
1461 bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4],
1462 bi->BSSID.octet[5]));
1465 bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
1468 for (j = i; j < results->count; j++) {
1469 DHD_TRACE(("%s: Moved up BSS[%2.2d:%2.2d]"
1470 " %X:%X:%X:%X:%X:%X\n",
1471 __FUNCTION__, l, j, bi->BSSID.octet[0], bi->BSSID.octet[1],
1472 bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4],
1473 bi->BSSID.octet[5]));
1475 bi_next = (wl_bss_info_t *)((uintptr)bi +
1476 dtoh32(bi->length));
1477 bcopy(bi, bi_new, dtoh32(bi->length));
1478 bi_new = (wl_bss_info_t *)((uintptr)bi_new +
1479 dtoh32(bi_new->length));
1483 if (results->count == 0) {
1484 /* Prune now empty partial scan list */
1490 bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
1492 iscan_cur = iscan_cur->next;
1497 DHD_TRACE(("%s: Scan cache after delete\n",
1504 dhd_iscan_request(void * dhdp, uint16 action)
1507 wl_iscan_params_t params;
1508 dhd_pub_t *dhd = dhd_bus_pub(dhdp);
1509 char buf[WLC_IOCTL_SMLEN];
1511 DHD_TRACE(("%s: Entered\n", __FUNCTION__));
1513 memset(¶ms, 0, sizeof(wl_iscan_params_t));
1514 memcpy(¶ms.params.bssid, ðer_bcast, ETHER_ADDR_LEN);
1516 params.params.bss_type = DOT11_BSSTYPE_ANY;
1517 params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
1519 params.params.nprobes = htod32(-1);
1520 params.params.active_time = htod32(-1);
1521 params.params.passive_time = htod32(-1);
1522 params.params.home_time = htod32(-1);
1523 params.params.channel_num = htod32(0);
1525 params.version = htod32(ISCAN_REQ_VERSION);
1526 params.action = htod16(action);
1527 params.scan_duration = htod16(0);
1529 bcm_mkiovar("iscan", (char *)¶ms, sizeof(wl_iscan_params_t), buf, WLC_IOCTL_SMLEN);
1530 rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, WLC_IOCTL_SMLEN, TRUE, 0);
1536 dhd_iscan_get_partial_result(void *dhdp, uint *scan_count)
1538 wl_iscan_results_t *list_buf;
1539 wl_iscan_results_t list;
1540 wl_scan_results_t *results;
1541 iscan_buf_t *iscan_cur;
1543 dhd_pub_t *dhd = dhd_bus_pub(dhdp);
1546 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1548 iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain);
1550 DHD_ERROR(("%s: Failed to allocate node\n", __FUNCTION__));
1551 dhd_iscan_free_buf(dhdp, 0);
1552 dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT);
1553 dhd_ind_scan_confirm(dhdp, FALSE);
1559 memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
1560 list_buf = (wl_iscan_results_t*)iscan_cur->iscan_buf;
1561 results = &list_buf->results;
1562 results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
1563 results->version = 0;
1566 memset(&list, 0, sizeof(list));
1567 list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
1568 bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
1569 iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
1570 rc = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iscan_cur->iscan_buf,
1571 WLC_IW_ISCAN_MAXLEN, FALSE, 0);
1573 results->buflen = dtoh32(results->buflen);
1574 results->version = dtoh32(results->version);
1575 *scan_count = results->count = dtoh32(results->count);
1576 status = dtoh32(list_buf->status);
1577 DHD_TRACE(("%s: Got %d resuls\n", __FUNCTION__, results->count));
1581 if (!(*scan_count)) {
1582 dhd_iscan_free_buf(dhdp, iscan_cur);
1591 int dhd_pno_clean(dhd_pub_t *dhd)
1594 int pfn_enabled = 0;
1599 iov_len = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf));
1600 if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) >= 0) {
1602 iov_len = bcm_mkiovar("pfnclear", 0, 0, iovbuf, sizeof(iovbuf));
1604 if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
1605 iov_len, TRUE, 0)) < 0) {
1606 DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
1611 DHD_ERROR(("%s failed code %d\n", __FUNCTION__, iov_len));
1615 DHD_ERROR(("%s pfn enable/disable failed: code %d\n", __FUNCTION__, ret));
1620 int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
1626 if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) {
1627 DHD_ERROR(("%s error exit\n", __FUNCTION__));
1630 memset(iovbuf, 0, sizeof(iovbuf));
1631 /* Check if disassoc to enable pno */
1632 if ((pfn_enabled) &&
1633 ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID,
1634 (char *)&bssid, ETHER_ADDR_LEN, TRUE, 0)) == BCME_NOTASSOCIATED)) {
1635 DHD_TRACE(("%s pno enable called in disassoc mode\n", __FUNCTION__));
1637 else if (pfn_enabled) {
1638 DHD_ERROR(("%s pno enable called in assoc mode ret=%d\n",
1639 __FUNCTION__, ret));
1642 /* Enable/disable PNO */
1643 if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) {
1644 if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
1645 sizeof(iovbuf), TRUE, 0)) < 0) {
1646 DHD_ERROR(("%s failed for error=%d\n", __FUNCTION__, ret));
1650 dhd->pno_enable = pfn_enabled;
1651 DHD_TRACE(("%s set pno as %d\n", __FUNCTION__, dhd->pno_enable));
1654 else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, ret));
1659 /* Function to execute combined scan */
1661 dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
1662 int pno_repeat, int pno_freq_expo_max)
1667 wl_pfn_param_t pfn_param;
1668 wl_pfn_t pfn_element;
1671 DHD_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, scan_fr));
1673 if ((!dhd) && (!ssids_local)) {
1674 DHD_ERROR(("%s error exit\n", __FUNCTION__));
1678 /* Check for broadcast ssid */
1679 for (k = 0; k < nssid; k++) {
1680 if (!ssids_local[k].SSID_len) {
1681 DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", k));
1685 /* #define PNO_DUMP 1 */
1689 for (j = 0; j < nssid; j++) {
1690 DHD_ERROR(("%d: scan for %s size =%d\n", j,
1691 ssids_local[j].SSID, ssids_local[j].SSID_len));
1694 #endif /* PNO_DUMP */
1696 /* clean up everything */
1697 if ((err = dhd_pno_clean(dhd)) < 0) {
1698 DHD_ERROR(("%s failed error=%d\n", __FUNCTION__, err));
1701 memset(&pfn_param, 0, sizeof(pfn_param));
1702 memset(&pfn_element, 0, sizeof(pfn_element));
1704 /* set pfn parameters */
1705 pfn_param.version = htod32(PFN_VERSION);
1706 pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT));
1707 /* check and set extra pno params */
1708 if ((pno_repeat != 0) || (pno_freq_expo_max != 0)) {
1709 pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT);
1710 pfn_param.repeat = htod32(pno_repeat);
1711 pfn_param.exp = htod32(pno_freq_expo_max);
1713 /* set up pno scan fr */
1715 pfn_param.scan_freq = htod32(scan_fr);
1717 if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) {
1718 DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC));
1721 if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) {
1722 DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC));
1725 len = bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf));
1726 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0);
1728 /* set all pfn ssid */
1729 for (i = 0; i < nssid; i++) {
1731 pfn_element.infra = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
1732 pfn_element.auth = (DOT11_OPEN_SYSTEM);
1733 pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
1734 pfn_element.wsec = htod32(0);
1735 pfn_element.infra = htod32(1);
1737 memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID, ssids_local[i].SSID_len);
1738 pfn_element.ssid.SSID_len = ssids_local[i].SSID_len;
1741 bcm_mkiovar("pfn_add", (char *)&pfn_element,
1742 sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) {
1744 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) {
1745 DHD_ERROR(("%s failed for i=%d error=%d\n",
1746 __FUNCTION__, i, err));
1750 DHD_ERROR(("%s set OK with PNO time=%d repeat=%d max_adjust=%d\n",
1751 __FUNCTION__, pfn_param.scan_freq,
1752 pfn_param.repeat, pfn_param.exp));
1754 else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, err));
1758 /* dhd_pno_enable(dhd, 1); */
1762 int dhd_pno_get_status(dhd_pub_t *dhd)
1769 return (dhd->pno_enable);
1772 #endif /* PNO_SUPPORT */
1774 int dhd_enable_filters(dhd_pub_t *dhd)
1780 DHD_TRACE(("%s: Enter.. \n", __FUNCTION__));
1781 #ifdef BCM_PKTFILTER_BASE_PORT
1782 for (i = 0 ; i < MAX_PKT_FILTERS ; i++) {
1783 if(filters[i].filterset == TRUE)
1784 dhd_config_pktfilter(dhd,filters[i].filterid, TRUE);
1787 dhd_config_pktfilter(dhd, PKTFILTER_BCAST_ID, TRUE);
1788 dhd_config_pktfilter(dhd, PKTFILTER_MCAST_ID, TRUE);
1792 int dhd_disable_filters(dhd_pub_t *dhd)
1799 DHD_TRACE(("%s: Enter.. \n", __FUNCTION__));
1800 #ifdef BCM_PKTFILTER_BASE_PORT
1801 for (i = 0 ; i < MAX_PKT_FILTERS ; i++) {
1802 if(filters[i].filterset == TRUE)
1803 dhd_config_pktfilter(dhd,filters[i].filterid, FALSE);
1806 dhd_config_pktfilter(dhd, PKTFILTER_BCAST_ID, FALSE);
1807 dhd_config_pktfilter(dhd, PKTFILTER_MCAST_ID, FALSE);
1813 dhd_set_filter(dhd_pub_t *dhd, wl_filter_tag_t *filter)
1816 //char iovbuf[1024] = {0};
1817 char iovbuf[1000] = {0}; //reduced array size to get rid of compiler warning
1818 wl_ioctl_t ioc = {0};
1823 DHD_ERROR(("%s: dhd pointer NULL\n", __FUNCTION__));
1827 if((ioctl_len = strlen("pkt_filter_add") + 1 + filter->filtersize) > sizeof(iovbuf))
1831 ret = bcm_mkiovar("pkt_filter_add", (char *)filter->filterdata, filter->filtersize, iovbuf, sizeof(iovbuf));
1833 memset(&ioc, 0 , sizeof(ioc));
1834 ioc.cmd = WLC_SET_VAR;
1836 ioc.len = ioctl_len;
1839 if( (ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ioctl_len,TRUE,0) ) < 0)
1841 DHD_ERROR(("%s: Error in add filter ret=%d \n", __FUNCTION__, ret));
1842 filter->filterset = FALSE;
1846 filter->filterset = TRUE;
1850 /* The number of bytes between the start of the 'EtherType' of the ethernet
1851 * header, and the end of the 'Destination port' of the UDP header.
1853 #define PATTERN_SIZE_BYTES 26
1854 #define MASK_SIZE_BYTES PATTERN_SIZE_BYTES
1856 /* The 'EtherType' field is 12 bytes from the start of the ethernet header. */
1857 #define PATTERN_OFFSET 12
1858 #ifdef BCM_PKTFILTER_BASE_PORT
1860 set_unicast_add_filter(dhd_pub_t *dhd,wl_filter_tag_t *filter, wl_filter_pref_t *filter_pref,int index)
1863 wl_pkt_filter_t *pktfilter = NULL;
1864 wl_pkt_filter_pattern_t *filter_pattern;
1868 struct ether_header ether_hdr_mask;
1869 struct bcmudp_hdr udp_hdr_mask;
1870 struct bcmtcp_hdr tcp_hdr_mask;
1871 struct ipv4_hdr ip_hdr_mask;
1872 struct ether_header ether_hdr_pattern;
1873 struct bcmudp_hdr udp_hdr_pattern;
1874 struct bcmtcp_hdr tcp_hdr_pattern;
1875 struct ipv4_hdr ip_hdr_pattern;
1877 /* Check whether the filter is already set */
1878 if (filter->filterset == TRUE)
1881 DHD_ERROR(("%s: Enter.. \n", __FUNCTION__));
1882 pktfilter = (wl_pkt_filter_t *)filter->filterdata;
1884 /* configure pattern to match against received packets*/
1885 memset(ðer_hdr_pattern,0,sizeof(ether_hdr_pattern));
1886 memset(&udp_hdr_pattern,0,sizeof(udp_hdr_pattern));
1887 memset(&tcp_hdr_pattern,0,sizeof(tcp_hdr_pattern));
1888 memset(&ip_hdr_pattern,0,sizeof(ip_hdr_pattern));
1890 /*Ethernet header. Validate that 'EtherType' is IP */
1891 ether_hdr_pattern.ether_type = hton16(ETHER_TYPE_IP);
1892 if (filter_pref->type == IP_PROT_UDP) {
1893 /*IP header. Validate that 'Protocol' is UDP*/
1894 ip_hdr_pattern.prot = IP_PROT_UDP;
1896 /* UDP header. Validate that 'Destination port is ' */
1897 udp_hdr_pattern.dst_port = hton16(filter_pref->port);
1898 } else if (filter_pref->type == IP_PROT_TCP) {
1900 /*IP header. Validate that 'Protocol' is UDP*/
1901 ip_hdr_pattern.prot = IP_PROT_TCP;
1903 /* TCP header. Validate that 'Destination port is ' */
1904 tcp_hdr_pattern.dst_port = hton16(filter_pref->port);
1907 /* configure bitmask that indicates which bits of received packets to match against specified pattern */
1909 memset(ðer_hdr_mask,0,sizeof(ether_hdr_mask));
1910 memset(&udp_hdr_mask,0,sizeof(udp_hdr_mask));
1911 memset(&tcp_hdr_mask,0,sizeof(tcp_hdr_mask));
1912 memset(&ip_hdr_mask,0,sizeof(ip_hdr_mask));
1914 /*Ethernet header. Validate that 'EtherType' is IP */
1915 ether_hdr_mask.ether_type = hton16(0xffff);
1917 /* IP header. Validate that 'Protocol is UDP'*/
1918 ip_hdr_mask.prot = 0xff;
1919 if (filter_pref->type == IP_PROT_UDP) {
1920 udp_hdr_mask.dst_port = hton16(0xffff);
1922 else if (filter_pref->type == IP_PROT_TCP) {
1924 tcp_hdr_mask.dst_port = hton16(0xffff);
1927 pktfilter->id = htol32(index+200);;
1928 pktfilter->type = WL_PKT_FILTER_TYPE_PATTERN_MATCH;
1929 /*1-negate mach. 0 is default*/
1930 pktfilter->negate_match = 0;
1931 pktfilter->u.pattern.offset = PATTERN_OFFSET;
1932 pktfilter->u.pattern.size_bytes = PATTERN_SIZE_BYTES;
1934 filter_pattern = &pktfilter->u.pattern;
1935 mask = filter_pattern->mask_and_pattern;
1936 memcpy(mask,ðer_hdr_mask.ether_type, ETHER_TYPE_LEN);
1937 memcpy(mask+ETHER_TYPE_LEN,&ip_hdr_mask, sizeof(ip_hdr_mask));
1938 if (filter_pref->type == IP_PROT_UDP) {
1939 memcpy(mask+ETHER_TYPE_LEN + sizeof(ip_hdr_mask),&udp_hdr_mask,sizeof(udp_hdr_mask));
1940 } else if (filter_pref->type == IP_PROT_TCP) {
1941 memcpy(mask+ETHER_TYPE_LEN + sizeof(ip_hdr_mask),&tcp_hdr_mask,sizeof(tcp_hdr_mask));
1945 pattern = &filter_pattern->mask_and_pattern[MASK_SIZE_BYTES];
1946 memcpy(pattern,ðer_hdr_pattern.ether_type,ETHER_TYPE_LEN);
1947 memcpy(pattern+ETHER_TYPE_LEN, &ip_hdr_pattern, sizeof(ip_hdr_pattern));
1948 if (filter_pref->type == IP_PROT_UDP) {
1949 memcpy(pattern+ETHER_TYPE_LEN+sizeof(ip_hdr_pattern),&udp_hdr_pattern,sizeof(udp_hdr_pattern));
1950 } else if (filter_pref->type == IP_PROT_TCP) {
1951 memcpy(pattern+ETHER_TYPE_LEN+sizeof(ip_hdr_pattern),&tcp_hdr_pattern,sizeof(tcp_hdr_pattern));
1953 filter->filtersize = WL_PKT_FILTER_FIXED_LEN;
1954 filter->filtersize += (WL_PKT_FILTER_PATTERN_FIXED_LEN + MASK_SIZE_BYTES + PATTERN_SIZE_BYTES);
1955 filter->filterid = 200+index;
1957 filter_pref->status = ADDED;
1958 filter_pref->filter_tag_p = filter;
1960 return dhd_set_filter(dhd, filter);
1964 set_unicast_remove_filter(dhd_pub_t *dhd,wl_filter_tag_t *filter, wl_filter_pref_t *filter_pref)
1968 //char iovbuf[1024] = {0};
1969 char iovbuf[992] = {0}; //reduced array size to get rid of compiler warning
1970 wl_ioctl_t ioc = {0};
1972 int val = htod32(filter->filterid);
1973 DHD_ERROR(("%s: Enter.. \n", __FUNCTION__));
1976 DHD_ERROR(("%s: dhd pointer NULL\n", __FUNCTION__));
1980 if((ioctl_len = strlen("pkt_filter_delete") + 1 + sizeof(int)) > sizeof(iovbuf))
1983 ret = bcm_mkiovar("pkt_filter_delete", (char *)(&val), sizeof(val), iovbuf, sizeof(iovbuf));
1985 memset(&ioc, 0 , sizeof(ioc));
1986 ioc.cmd = WLC_SET_VAR;
1988 ioc.len = ioctl_len;
1991 if( (ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ioctl_len,TRUE,0) ) < 0)
1993 DHD_ERROR(("%s: Error in remove filter ret=%d \n", __FUNCTION__, ret));
1997 filter->filterset = FALSE;
1998 filter->filterid = 0;
1999 filter->filtersize = 0;
2000 filter_pref->status = REMOVED;
2001 filter_pref->filter_tag_p = NULL;
2002 filter_pref->set = FALSE;
2007 dhd_custom_set_pktfilters(dhd_pub_t *dhd,int protocol,int port,int *id)
2010 DHD_ERROR(("%s: Enter\n", __FUNCTION__));
2012 DHD_ERROR(("%s: dhd pointer NULL\n",__FUNCTION__));
2016 for (i = 0 ; i < MAX_PKT_PREFS ; i++)
2019 if (filters_pref[i].set == FALSE) {
2020 filters_pref[i].set = TRUE;
2021 filters_pref[i].port = port;
2022 filters_pref[i].status = ADD;
2023 filters_pref[i].type = (protocol == 1)? IP_PROT_TCP : IP_PROT_UDP;
2027 if((filters_pref[i].filter_tag_p != NULL)
2028 && (filters_pref[i].filter_tag_p->filterid == *id)) {
2029 filters_pref[i].status = REMOVE;
2035 if (i == MAX_PKT_PREFS) return -1;
2037 for (i = 0 ; i < MAX_PKT_PREFS ; i++)
2039 if (filters_pref[i].set) {
2041 if(filters_pref[i].status == ADD) {
2042 for (j = 0 ; j < MAX_PKT_FILTERS ; j++) {
2043 if(!filters[j].filterset) {
2044 error = set_unicast_add_filter(dhd,&filters[j],&filters_pref[i],j);
2045 *id = filters[j].filterid;
2051 } else if(filters_pref[i].status == REMOVE) {
2052 error = set_unicast_remove_filter(dhd,filters_pref[i].filter_tag_p,&filters_pref[i]);
2059 //FALSE-Discard on match. TRUE Forward on Match
2060 error = dhd_set_pktfilter_mode(dhd, TRUE);
2067 dhd_set_pktfilters(dhd_pub_t *dhd)
2070 DHD_TRACE(("%s: Enter\n", __FUNCTION__));
2074 DHD_ERROR(("%s: dhd pointer NULL\n",__FUNCTION__));
2078 #ifndef BCM_PKTFILTER_BASE_PORT
2079 set_bcast_filter(dhd, &filters[0]);
2080 //set_mcast_filter(bus, &filters[1]);
2081 //FALSE-Discard on match. TRUE Forward on Match
2082 dhd_set_pktfilter_mode(dhd, FALSE);
2089 #ifndef BCM_PKTFILTER_BASE_PORT
2090 int set_bcast_filter(dhd_pub_t *dhd, wl_filter_tag_t *filter)
2093 wl_pkt_filter_t *pktfilter = NULL;
2095 /* Check whether the filter is already set */
2096 if(filter->filterset == TRUE)
2099 pktfilter = (wl_pkt_filter_t *)filter->filterdata;
2101 pktfilter->id = htol32(PKTFILTER_BCAST_ID);
2103 /*1-negate mach. 0 is default*/
2104 pktfilter->negate_match = 0;
2106 pktfilter->type = 0;
2108 /* Offset 0 means first byte of ethernet header */
2109 pktfilter->u.pattern.offset = 0;
2111 /* mask is 1 byte */
2112 pktfilter->u.pattern.size_bytes = htol32(6);
2115 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2116 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2117 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2118 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2119 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2120 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2122 /* filter pattern */
2123 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2124 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2125 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2126 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2127 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2128 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0xff;
2130 filter->filterid = PKTFILTER_BCAST_ID;
2132 filter->filtersize = WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN + byteoffset;
2134 dhd_set_filter(dhd, filter);
2139 int set_mcast_filter(dhd_pub_t *dhd, wl_filter_tag_t *filter)
2142 wl_pkt_filter_t *pktfilter = NULL;
2144 /* Check whether the filter is already set */
2145 if(filter->filterset == TRUE)
2148 pktfilter = (wl_pkt_filter_t *)filter->filterdata;
2150 pktfilter->id = htol32(PKTFILTER_MCAST_ID);
2152 /*1-negate mach. 0 is default*/
2153 pktfilter->negate_match = 0;
2155 pktfilter->type = 0;
2157 /* Offset 0 means first byte of ethernet header */
2158 pktfilter->u.pattern.offset = 0;
2160 /* mask is 1 byte */
2161 pktfilter->u.pattern.size_bytes = htol32(1);
2164 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0x01;
2166 /* filter pattern */
2167 pktfilter->u.pattern.mask_and_pattern[byteoffset++] = 0x01;
2169 filter->filterid = PKTFILTER_MCAST_ID;
2171 filter->filtersize = WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN + byteoffset;
2173 dhd_set_filter(dhd, filter);
2179 int dhd_set_pktfilter_mode(dhd_pub_t *dhd, int flag)
2184 int filter_mode = flag;
2185 char iovbuf[50] = {0};
2189 DHD_ERROR(("%s: dhd ptr is NULL \n",__FUNCTION__));
2195 DHD_ERROR(("%s: dhd ptr is NULL \n", __FUNCTION__));
2199 /* Set filter mode. 0-Discard on match, 1- Forward on Match */
2200 if( (ret = bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, sizeof(filter_mode), iovbuf, sizeof(iovbuf))) > 0 )
2204 if((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE,0)) < 0)
2206 DHD_ERROR(("%s:Set filter mode failure. ret-> %d \n", __FUNCTION__, ret));
2220 int dhd_config_pktfilter(dhd_pub_t *dhd, uint32 id ,uint32 flag)
2225 wl_pkt_filter_enable_t pktconfig;
2226 char iovbuf[80] = {0};
2229 pktconfig.enable = flag;
2231 DHD_TRACE(("%s: Enter.. Flag->%d \n", __FUNCTION__, flag));
2232 DHD_ERROR(("%s: Enter.. Flag->%d \n", __FUNCTION__, flag));
2235 if( (len = bcm_mkiovar("pkt_filter_enable", (char *)&pktconfig, sizeof(pktconfig), iovbuf, sizeof(iovbuf))) > 0)
2238 if((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE,0)) < 0)
2240 DHD_ERROR(("%s: Config packetfilter failure. ret->%d \n", __FUNCTION__, ret));
2245 DHD_ERROR(("%s: bcm_mkiovar failed. \n", __FUNCTION__));