From e1008adf059996ad1b9baaaf2a9509af51176022 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 7 Jul 2011 17:04:44 -0700 Subject: [PATCH] net: wireless: bcmdhd: Add packet filtering commands Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd.h | 9 ++++++++- drivers/net/wireless/bcmdhd/dhd_common.c | 6 ++++++ drivers/net/wireless/bcmdhd/dhd_linux.c | 34 +++++++++++++++++++++++++++++++- drivers/net/wireless/bcmdhd/wl_android.c | 14 +++++++++++-- drivers/net/wireless/bcmdhd/wl_iw.h | 1 - 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 2606326..bca7535 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -374,7 +374,7 @@ extern void dhd_os_sdlock_rxq(dhd_pub_t * pub); extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub); extern void dhd_customer_gpio_wlan_ctrl(int onoff); -extern int dhd_custom_get_mac_address(unsigned char *buf); +extern int dhd_custom_get_mac_address(unsigned char *buf); extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); @@ -390,6 +390,13 @@ extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); extern int dhd_dev_get_pno_status(struct net_device *dev); extern int dhd_get_dtim_skip(dhd_pub_t *dhd); +#define DHD_UNICAST_FILTER_NUM 0 +#define DHD_BROADCAST_FILTER_NUM 1 +#define DHD_MULTICAST4_FILTER_NUM 2 +#define DHD_MULTICAST6_FILTER_NUM 3 +extern int net_os_set_packet_filter(struct net_device *dev, int val); +extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); + #ifdef DHD_DEBUG extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); #endif /* DHD_DEBUG */ diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 8beb1b4..1fbc283 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -1208,6 +1208,9 @@ dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_ wl_pkt_filter_enable_t enable_parm; wl_pkt_filter_enable_t * pkt_filterp; + if (!arg) + return; + if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); goto fail; @@ -1281,6 +1284,9 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) char *arg_save = 0, *arg_org = 0; #define BUF_SIZE 2048 + if (!arg) + return; + if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); goto fail; diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index dee662c..e952ee1 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -2674,9 +2674,12 @@ dhd_bus_start(dhd_pub_t *dhdp) setbit(dhdp->eventmask, WLC_E_ROAM); - dhdp->pktfilter_count = 1; + dhdp->pktfilter_count = 4; /* Setup filter to allow only unicast */ dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00"; + dhdp->pktfilter[1] = NULL; + dhdp->pktfilter[2] = NULL; + dhdp->pktfilter[3] = NULL; #endif /* EMBEDDED_PLATFORM */ #ifdef READ_MACADDR @@ -3727,6 +3730,35 @@ int net_os_set_dtim_skip(struct net_device *dev, int val) return 0; } +int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + char *filterp = NULL; + int ret = 0; + + if (!dhd || (num == DHD_UNICAST_FILTER_NUM)) + return ret; + if (num >= dhd->pub.pktfilter_count) + return -EINVAL; + if (add_remove) { + switch (num) { + case DHD_BROADCAST_FILTER_NUM: + filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF"; + break; + case DHD_MULTICAST4_FILTER_NUM: + filterp = "102 0 0 0 0xFFFFFF 0x01005E"; + break; + case DHD_MULTICAST6_FILTER_NUM: + filterp = "103 0 0 0 0xFFFF 0x3333"; + break; + default: + return -EINVAL; + } + } + dhd->pub.pktfilter[num] = filterp; + return ret; +} + int net_os_set_packet_filter(struct net_device *dev, int val) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 2d3ff7f..9246272 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -59,6 +59,8 @@ #define CMD_LINKSPEED "LINKSPEED" #define CMD_RXFILTER_START "RXFILTER-START" #define CMD_RXFILTER_STOP "RXFILTER-STOP" +#define CMD_RXFILTER_ADD "RXFILTER-ADD" +#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" #define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" #define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" #define CMD_BTCOEXMODE "BTCOEXMODE" @@ -287,10 +289,18 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_android_get_link_speed(net, command, priv_cmd->total_len); } else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) { - /* TBD: RXFILTER-START */ + bytes_written = net_os_set_packet_filter(net, 1); } else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) { - /* TBD: RXFILTER-STOP */ + bytes_written = net_os_set_packet_filter(net, 0); + } + else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) { + int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; + bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); + } + else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) { + int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; + bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); } else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) { /* TBD: BTCOEXSCAN-START */ diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h index 4d36b8c..a34472f 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.h +++ b/drivers/net/wireless/bcmdhd/wl_iw.h @@ -207,7 +207,6 @@ extern int net_os_wake_lock_timeout_enable(struct net_device *dev); extern int net_os_set_suspend_disable(struct net_device *dev, int val); extern int net_os_set_suspend(struct net_device *dev, int val); extern int net_os_set_dtim_skip(struct net_device *dev, int val); -extern int net_os_set_packet_filter(struct net_device *dev, int val); extern int net_os_send_hang_message(struct net_device *dev); extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec); -- 2.7.4