* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd.h,v 1.32.4.7.2.4.14.43 2010/05/18 05:48:53 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.44 2010/06/03 21:27:48 Exp $
*/
/****************
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 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);
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.36 2010/04/14 12:09:11 Exp $
+ * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.39 2010/06/04 19:08:09 Exp $
*
* BDC is like CDC, except it includes a header for data packets to convey
* packet priority over the bus, and flags (e.g. to indicate checksum status
}
memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
+ dhd_os_proto_unblock(dhd);
+
#ifdef EMBEDDED_PLATFORM
ret = dhd_preinit_ioctls(dhd);
#endif /* EMBEDDED_PLATFORM */
dhd->iswl = TRUE;
fail:
- dhd_os_proto_unblock(dhd);
return ret;
}
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_common.c,v 1.5.6.8.2.6.6.60 2010/05/26 03:36:55 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.62 2010/06/04 19:08:13 Exp $
*/
#include <typedefs.h>
#include <osl.h>
struct ether_addr ea_addr;
#endif /* GET_CUSTOM_MAC_ENABLE */
+ dhd_os_proto_block(dhd);
+
#ifdef GET_CUSTOM_MAC_ENABLE
/*
** Read MAC address from external customer place
** to bring up firmware but unique per board mac address maybe provided
** by customer code
*/
- ret = wifi_get_mac_addr(ea_addr.octet);
+ ret = dhd_custom_get_mac_address(ea_addr.octet);
if (!ret) {
bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
}
#endif /* PKT_FILTER_SUPPORT */
+ dhd_os_proto_unblock(dhd);
+
return 0;
}
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
-* $Id: dhd_custom_gpio.c,v 1.1.4.6 2010/02/19 22:56:49 Exp $
+* $Id: dhd_custom_gpio.c,v 1.1.4.7 2010/06/03 21:27:48 Exp $
*/
extern void bcm_wlan_power_off(int);
extern void bcm_wlan_power_on(int);
#endif /* CUSTOMER_HW */
-
#ifdef CUSTOMER_HW2
int wifi_set_carddetect(int on);
int wifi_set_power(int on, unsigned long msec);
int wifi_get_irq_number(unsigned long *irq_flags_ptr);
+int wifi_get_mac_addr(unsigned char *buf);
#endif
#if defined(OOB_INTR_ONLY)
extern int sdioh_mmc_irq(int irq);
#endif /* (BCMLXSDMMC) */
+#ifdef CUSTOMER_HW3
+#include <mach/gpio.h>
+#endif
+
/* Customer specific Host GPIO defintion */
static int dhd_oob_gpio_num = -1; /* GG 19 */
int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
{
- int host_oob_irq;
+ int host_oob_irq = 0;
+
#ifdef CUSTOMER_HW2
host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
-#else
+
+#else /* for NOT CUSTOMER_HW2 */
#if defined(CUSTOM_OOB_GPIO_NUM)
if (dhd_oob_gpio_num < 0) {
dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
*irq_flags_ptr = IRQF_TRIGGER_FALLING;
if (dhd_oob_gpio_num < 0) {
WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
- __FUNCTION__));
+ __FUNCTION__));
return (dhd_oob_gpio_num);
}
WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n",
__FUNCTION__, dhd_oob_gpio_num));
- host_oob_irq = sdioh_mmc_irq(dhd_oob_gpio_num);
-#endif
+#if defined CUSTOMER_HW
+ host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
+#elif defined CUSTOMER_HW3
+ gpio_request(dhd_oob_gpio_num, "oob irq");
+ host_oob_irq = gpio_to_irq(dhd_oob_gpio_num);
+ gpio_direction_input(dhd_oob_gpio_num);
+#endif /* CUSTOMER_HW */
+#endif /* CUSTOMER_HW2 */
+
return (host_oob_irq);
}
#endif /* defined(OOB_INTR_ONLY) */
break;
}
}
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+/* Function to get custom MAC address */
+int
+dhd_custom_get_mac_address(unsigned char *buf)
+{
+ int ret = 0;
+
+ WL_TRACE(("%s Enter\n", __FUNCTION__));
+ if (!buf)
+ return -EINVAL;
+
+ /* Customer access to MAC address stored outside of DHD driver */
+#ifdef CUSTOMER_HW2
+ ret = wifi_get_mac_addr(buf);
+#endif
+
+#ifdef EXAMPLE_GET_MAC
+ /* EXAMPLE code */
+ {
+ struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
+ bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
+ }
+#endif /* EXAMPLE_GET_MAC */
+
+ return ret;
+}
+#endif /* GET_CUSTOM_MAC_ENABLE */
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.123 2010/05/18 05:48:53 Exp $
+ * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.125 2010/06/04 02:52:15 Exp $
*/
#include <typedefs.h>
/* Check for existing queue, current flow-control, pending event, or pending clock */
if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
(!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
- (bus->clkstate == CLK_PENDING)) {
+ (bus->clkstate != CLK_AVAIL)) {
DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__,
pktq_len(&bus->txq)));
bus->fcqueued++;
/* Otherwise, send it now */
BUS_WAKE(bus);
/* Make sure back plane ht clk is on, no pending allowed */
- dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
#ifndef SDTEST
DHD_TRACE(("%s: calling txpkt\n", __FUNCTION__));
BUS_WAKE(bus);
- /* Make sure backplane clock is on, no pending,
- * waste of cycle to wait for the next schedule to send
- */
- dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ /* Make sure backplane clock is on */
+ dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
if (bus->clkstate == CLK_PENDING)
goto clkwait;
} else if (bus->clkstate == CLK_PENDING) {
DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting \
I_CHIPACTIVE interrupt", __FUNCTION__));
+ resched = TRUE;
} else if (bus->intstatus || bus->ipend ||
(!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
PKT_AVAILABLE()) { /* Read multiple frames */
#define EPI_MINOR_VERSION 218
-#define EPI_RC_NUMBER 238
+#define EPI_RC_NUMBER 239
#define EPI_INCREMENTAL_NUMBER 0
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 4, 218, 238, 0
+#define EPI_VERSION 4, 218, 239, 0
-#define EPI_VERSION_NUM 0x04daee00
+#define EPI_VERSION_NUM 0x04daef00
-#define EPI_VERSION_STR "4.218.238.0"
-#define EPI_ROUTER_VERSION_STR "4.219.238.0"
+#define EPI_VERSION_STR "4.218.239.0"
+#define EPI_ROUTER_VERSION_STR "4.219.239.0"
#endif
}
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+
+static int
+wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num)
+{
+ int num;
+ int val;
+ char* str;
+ char* endptr = NULL;
+
+ if ((list_str == NULL)||(*list_str == NULL))
+ return -1;
+
+ str = *list_str;
+ num = 0;
+ while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) {
+ val = (int)strtoul(str, &endptr, 0);
+ if (endptr == str) {
+ printf("could not parse channel number starting at"
+ " substring \"%s\" in list:\n%s\n",
+ str, *list_str);
+ return -1;
+ }
+ str = endptr + strspn(endptr, " ,");
+
+ if (num == channel_num) {
+ printf("too many channels (more than %d) in channel list:\n%s\n",
+ channel_num, *list_str);
+ return -1;
+ }
+
+ channel_list[num++] = (uint16)val;
+ }
+ *list_str = str;
+ return num;
+}
+
+
+
+static int
+wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max)
+{
+ char* str, *ptr;
+
+ if ((list_str == NULL) || (*list_str == NULL))
+ return -1;
+
+ for (str = *list_str; str != NULL; str = ptr) {
+
+ if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) {
+ *list_str = str + strlen(GET_CHANNEL);
+ return idx;
+ }
+
+ if ((ptr = strchr(str, ',')) != NULL) {
+ *ptr++ = '\0';
+ }
+
+ if (strlen(str) > DOT11_MAX_SSID_LEN) {
+ printf("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN);
+ return -1;
+ }
+
+ if (strlen(str) == 0)
+ ssid[idx].SSID_len = 0;
+
+ if (idx < max) {
+ strcpy((char*)ssid[idx].SSID, str);
+ ssid[idx].SSID_len = strlen(str);
+ }
+ idx++;
+ }
+ return idx;
+}
+
+
+static int
+wl_iw_combined_scan_set(struct net_device *dev, wl_scan_params_t *params, \
+wlc_ssid_t* ssids_local, int nssid, int nchan)
+{
+ int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+ int err = 0;
+ char *p;
+ int i;
+
+ WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan));
+
+ params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+
+ if (nssid > 0) {
+ i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
+ i = ROUNDUP(i, sizeof(uint32));
+ if (i + nssid * sizeof(wlc_ssid_t) > params_size) {
+ printf("additional ssids exceed params_size\n");
+ err = -1;
+ goto exit;
+ }
+
+ p = (char*)params + i;
+ memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t));
+ p += nssid * sizeof(wlc_ssid_t);
+ } else {
+ p = (char*)params->channel_list + nchan * sizeof(uint16);
+ }
+
+ params->channel_num = htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
+ (nchan & WL_SCAN_PARAMS_COUNT_MASK));
+
+ params_size = (int) (p - (char*)params + nssid * sizeof(wlc_ssid_t));
+
+#define SCAN_DUMP 1
+#ifdef SCAN_DUMP
+ printf("\n### List of SSIDs to scan ###\n");
+ for (i = 0; i < nssid; i++) {
+ if (!ssids_local[i].SSID_len)
+ printf("%d: Broadcast scan\n", i);
+ else
+ printf("%d: scan for %s size =%d\n", i, \
+ ssids_local[i].SSID, ssids_local[i].SSID_len);
+ }
+ printf("### List of channels to scan ###\n");
+ for (i = 0; i < nchan; i++)
+ {
+ printf("%d ", params->channel_list[i]);
+ }
+ printf("\nnprobes=%d\n", params->nprobes);
+ printf("active_time=%d\n", params->active_time);
+ printf("passive_time=%d\n", params->passive_time);
+ printf("home_time=%d\n", params->home_time);
+ printf("\n###################\n");
+#endif
+
+ if ((err = dev_wlc_ioctl(dev, WLC_SCAN, params, params_size))) {
+ WL_TRACE(("Set SCAN for %s failed with %d\n", __FUNCTION__, error));
+ err = -1;
+ }
+
+exit:
+
+ return err;
+}
+
+
+static int iwpriv_set_scan(struct net_device *dev, struct iw_request_info *info, \
+ union iwreq_data *wrqu, char *ext)
+{
+ int res = 0;
+ char *extra = NULL;
+ wl_scan_params_t *params;
+ int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+ wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
+ int nssid = 0;
+ int nchan = 0;
+
+ WL_TRACE(("\%s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
+ __FUNCTION__, info->cmd, info->flags,
+ wrqu->data.pointer, wrqu->data.length));
+
+
+ if (wrqu->data.length != 0) {
+
+ char *str_ptr;
+
+ if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ extra[wrqu->data.length] = 0;
+ WL_ERROR(("Got str param in iw_point:\n %s\n", extra));
+
+ str_ptr = extra;
+
+ if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) {
+ WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__));
+ goto exit_proc;
+ }
+ str_ptr += strlen(GET_SSID);
+ nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid, \
+ WL_SCAN_PARAMS_SSID_MAX);
+ if (nssid == -1) {
+ WL_ERROR(("%s wrong ssid list", __FUNCTION__));
+ return -1;
+ }
+
+ params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+
+ params = (wl_scan_params_t*)kmalloc(params_size, GFP_KERNEL);
+ if (params == NULL) {
+ WL_ERROR(("%s Failed allocate %d bytes \n", __FUNCTION__, params_size));
+ return -ENOMEM;
+ }
+ memset(params, 0, params_size);
+ ASSERT(params_size < WLC_IOCTL_MAXLEN);
+
+ wl_iw_iscan_prep(params, NULL);
+
+ if ((nchan = wl_iw_parse_channel_list(&str_ptr, params->channel_list, \
+ WL_NUMCHANNELS)) == -1) {
+ WL_ERROR(("%s missing channel list\n", __FUNCTION__));
+ return -1;
+ }
+
+ get_parmeter_from_string(&str_ptr, \
+ GET_NPROBE, PTYPE_INTDEC, ¶ms->nprobes, 2);
+
+ get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, \
+ PTYPE_INTDEC, ¶ms->active_time, 3);
+
+ get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, \
+ PTYPE_INTDEC, ¶ms->passive_time, 3);
+
+ get_parmeter_from_string(&str_ptr, \
+ GET_HOME_DWELL, PTYPE_INTDEC, ¶ms->home_time, 3);
+
+ res = wl_iw_combined_scan_set(dev, params, \
+ ssids_local, nssid, nchan);
+ } else {
+ WL_ERROR(("IWPRIV argument len = 0 \n"));
+ return -1;
+ }
+
+exit_proc:
+
+ kfree(extra);
+
+ return res;
+}
+
+
#ifdef SOFTAP
static int thr_wait_for_2nd_eth_dev(void *data)
(iw_handler)iwpriv_softap_stop,
NULL,
- (iw_handler)iwpriv_fw_reload
+ (iw_handler)iwpriv_fw_reload,
#endif
+
+ NULL,
+ (iw_handler)iwpriv_set_scan
};
static const struct iw_priv_args wl_iw_priv_args[] = {
"WL_FW_RELOAD"
},
#endif
+ {
+ WL_COMBO_SCAN,
+ IW_PRIV_TYPE_CHAR | 1024,
+ 0,
+ "CSCAN"
+ },
};
const struct iw_handler_def wl_iw_handler_def =
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_iw.h,v 1.5.34.1.6.16 2010/04/19 21:32:10 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.6.18 2010/06/03 02:27:14 Exp $
*/
#include <proto/ethernet.h>
#include <wlioctl.h>
+#define WL_SCAN_PARAMS_SSID_MAX 10
+#define GET_SSID "SSID="
+#define GET_CHANNEL "CH="
+#define GET_NPROBE "NPROBE="
+#define GET_ACTIVE_ASSOC_DWELL "ACTIVE="
+#define GET_PASSIVE_ASSOC_DWELL "PASSIVE="
+#define GET_HOME_DWELL "HOME="
#define WL_IW_RSSI_MINVAL -200
#define WL_IW_RSSI_NO_SIGNAL -91
#define AP_LPB_CMD (SIOCIWFIRSTPRIV+23)
#define WL_AP_STOP (SIOCIWFIRSTPRIV+25)
#define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27)
-#define WL_AP_SPARE2 (SIOCIWFIRSTPRIV+29)
+#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+29)
#define WL_AP_SPARE3 (SIOCIWFIRSTPRIV+31)
#define G_SCAN_RESULTS (8*1024)
#define WE_ADD_EVENT_FIX 0x80