static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
	struct ifinfomsg  *ifm = NLMSG_DATA(nlh);
	struct rtattr    **ida = arg;
	struct net_device *dev;
	int err, send_addr_notify = 0;

	if (ifm->ifi_index >= 0)
		dev = dev_get_by_index(ifm->ifi_index);
	else if (ida[IFLA_IFNAME - 1]) {
		char ifname[IFNAMSIZ];

		if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
		                   IFNAMSIZ) >= IFNAMSIZ)
			return -EINVAL;
		dev = dev_get_by_name(ifname);
	} else
		return -EINVAL;

	if (!dev)
		return -ENODEV;

	err = -EINVAL;

	if (ifm->ifi_flags)
		dev_change_flags(dev, ifm->ifi_flags);

	if (ida[IFLA_MAP - 1]) {
		struct rtnl_link_ifmap *u_map;
		struct ifmap k_map;

		if (!dev->set_config) {
			err = -EOPNOTSUPP;
			goto out;
		}

		if (!netif_device_present(dev)) {
			err = -ENODEV;
			goto out;
		}
		
		if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map)))
			goto out;

		u_map = RTA_DATA(ida[IFLA_MAP - 1]);

		k_map.mem_start = (unsigned long) u_map->mem_start;
		k_map.mem_end = (unsigned long) u_map->mem_end;
		k_map.base_addr = (unsigned short) u_map->base_addr;
		k_map.irq = (unsigned char) u_map->irq;
		k_map.dma = (unsigned char) u_map->dma;
		k_map.port = (unsigned char) u_map->port;

		err = dev->set_config(dev, &k_map);

		if (err)
			goto out;
	}

	if (ida[IFLA_ADDRESS - 1]) {
		if (!dev->set_mac_address) {
			err = -EOPNOTSUPP;
			goto out;
		}
		if (!netif_device_present(dev)) {
			err = -ENODEV;
			goto out;
		}
		if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
			goto out;

		err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1]));
		if (err)
			goto out;
		send_addr_notify = 1;
	}

	if (ida[IFLA_BROADCAST - 1]) {
		if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len))
			goto out;
		memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]),
		       dev->addr_len);
		send_addr_notify = 1;
	}

	if (ida[IFLA_MTU - 1]) {
		if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
			goto out;
		err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1])));

		if (err)
			goto out;

	}

	if (ida[IFLA_TXQLEN - 1]) {
		if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
			goto out;

		dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1]));
	}

	if (ida[IFLA_WEIGHT - 1]) {
		if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
			goto out;

		dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
	}

	if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) {
		char ifname[IFNAMSIZ];

		if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
		                   IFNAMSIZ) >= IFNAMSIZ)
			goto out;
		err = dev_change_name(dev, ifname);
		if (err)
			goto out;
	}

	err = 0;

out:
	if (send_addr_notify)
		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);

	dev_put(dev);
	return err;
}
Exemplo n.º 2
0
static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
	struct ifinfomsg *ifm;
	struct net_device *dev;
	int err, send_addr_notify = 0, modified = 0;
	struct nlattr *tb[IFLA_MAX+1];
	char ifname[IFNAMSIZ];

	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
	if (err < 0)
		goto errout;

	if (tb[IFLA_IFNAME])
		nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
	else
		ifname[0] = '\0';

	err = -EINVAL;
	ifm = nlmsg_data(nlh);
	if (ifm->ifi_index > 0)
		dev = dev_get_by_index(ifm->ifi_index);
	else if (tb[IFLA_IFNAME])
		dev = dev_get_by_name(ifname);
	else
		goto errout;

	if (dev == NULL) {
		err = -ENODEV;
		goto errout;
	}

	if (tb[IFLA_ADDRESS] &&
	    nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
		goto errout_dev;

	if (tb[IFLA_BROADCAST] &&
	    nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
		goto errout_dev;

	if (tb[IFLA_MAP]) {
		struct rtnl_link_ifmap *u_map;
		struct ifmap k_map;

		if (!dev->set_config) {
			err = -EOPNOTSUPP;
			goto errout_dev;
		}

		if (!netif_device_present(dev)) {
			err = -ENODEV;
			goto errout_dev;
		}

		u_map = nla_data(tb[IFLA_MAP]);
		k_map.mem_start = (unsigned long) u_map->mem_start;
		k_map.mem_end = (unsigned long) u_map->mem_end;
		k_map.base_addr = (unsigned short) u_map->base_addr;
		k_map.irq = (unsigned char) u_map->irq;
		k_map.dma = (unsigned char) u_map->dma;
		k_map.port = (unsigned char) u_map->port;

		err = dev->set_config(dev, &k_map);
		if (err < 0)
			goto errout_dev;

		modified = 1;
	}

	if (tb[IFLA_ADDRESS]) {
		struct sockaddr *sa;
		int len;

		if (!dev->set_mac_address) {
			err = -EOPNOTSUPP;
			goto errout_dev;
		}

		if (!netif_device_present(dev)) {
			err = -ENODEV;
			goto errout_dev;
		}

		len = sizeof(sa_family_t) + dev->addr_len;
		sa = kmalloc(len, GFP_KERNEL);
		if (!sa) {
			err = -ENOMEM;
			goto errout_dev;
		}
		sa->sa_family = dev->type;
		memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
		       dev->addr_len);
		err = dev->set_mac_address(dev, sa);
		kfree(sa);
		if (err)
			goto errout_dev;
		send_addr_notify = 1;
		modified = 1;
	}

	if (tb[IFLA_MTU]) {
		err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
		if (err < 0)
			goto errout_dev;
		modified = 1;
	}

	/*
	 * Interface selected by interface index but interface
	 * name provided implies that a name change has been
	 * requested.
	 */
	if (ifm->ifi_index > 0 && ifname[0]) {
		err = dev_change_name(dev, ifname);
		if (err < 0)
			goto errout_dev;
		modified = 1;
	}

	if (tb[IFLA_BROADCAST]) {
		nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
		send_addr_notify = 1;
	}


	if (ifm->ifi_flags || ifm->ifi_change) {
		unsigned int flags = ifm->ifi_flags;

		/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
		if (ifm->ifi_change)
			flags = (flags & ifm->ifi_change) |
				(dev->flags & ~ifm->ifi_change);
		dev_change_flags(dev, flags);
	}

	if (tb[IFLA_TXQLEN])
		dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);

	if (tb[IFLA_WEIGHT])
		dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);

	if (tb[IFLA_OPERSTATE])
		set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));

	if (tb[IFLA_LINKMODE]) {
		write_lock_bh(&dev_base_lock);
		dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
		write_unlock_bh(&dev_base_lock);
	}

	err = 0;

errout_dev:
	if (err < 0 && modified && net_ratelimit())
		printk(KERN_WARNING "A link change request failed with "
		       "some changes comitted already. Interface %s may "
		       "have been left with an inconsistent configuration, "
		       "please check.\n", dev->name);

	if (send_addr_notify)
		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);

	dev_put(dev);
errout:
	return err;
}
Exemplo n.º 3
0
/*
 *	Perform the SIOCxIFxxx calls, inside rtnl_lock()
 */
static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
{
	int err;
	struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
	const struct net_device_ops *ops;

	if (!dev)
		return -ENODEV;

	ops = dev->netdev_ops;

	switch (cmd) {
	case SIOCSIFFLAGS:	/* Set interface flags */
		return dev_change_flags(dev, ifr->ifr_flags);

	case SIOCSIFMETRIC:	/* Set the metric on the interface
				   (currently unused) */
		return -EOPNOTSUPP;

	case SIOCSIFMTU:	/* Set the MTU of a device */
		return dev_set_mtu(dev, ifr->ifr_mtu);

	case SIOCSIFHWADDR:
		if (dev->addr_len > sizeof(struct sockaddr))
			return -EINVAL;
		return dev_set_mac_address(dev, &ifr->ifr_hwaddr);

	case SIOCSIFHWBROADCAST:
		if (ifr->ifr_hwaddr.sa_family != dev->type)
			return -EINVAL;
		memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
		       min(sizeof(ifr->ifr_hwaddr.sa_data),
			   (size_t)dev->addr_len));
		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
		return 0;

	case SIOCSIFMAP:
		if (ops->ndo_set_config) {
			if (!netif_device_present(dev))
				return -ENODEV;
			return ops->ndo_set_config(dev, &ifr->ifr_map);
		}
		return -EOPNOTSUPP;

	case SIOCADDMULTI:
		if (!ops->ndo_set_rx_mode ||
		    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
			return -EINVAL;
		if (!netif_device_present(dev))
			return -ENODEV;
		return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data);

	case SIOCDELMULTI:
		if (!ops->ndo_set_rx_mode ||
		    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
			return -EINVAL;
		if (!netif_device_present(dev))
			return -ENODEV;
		return dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data);

	case SIOCSIFTXQLEN:
		if (ifr->ifr_qlen < 0)
			return -EINVAL;
		return dev_change_tx_queue_len(dev, ifr->ifr_qlen);

	case SIOCSIFNAME:
		ifr->ifr_newname[IFNAMSIZ-1] = '\0';
		return dev_change_name(dev, ifr->ifr_newname);

	case SIOCSHWTSTAMP:
		err = net_hwtstamp_validate(ifr);
		if (err)
			return err;
		/* fall through */

	/*
	 *	Unknown or private ioctl
	 */
	default:
		if ((cmd >= SIOCDEVPRIVATE &&
		    cmd <= SIOCDEVPRIVATE + 15) ||
		    cmd == SIOCBONDENSLAVE ||
		    cmd == SIOCBONDRELEASE ||
		    cmd == SIOCBONDSETHWADDR ||
		    cmd == SIOCBONDSLAVEINFOQUERY ||
		    cmd == SIOCBONDINFOQUERY ||
		    cmd == SIOCBONDCHANGEACTIVE ||
		    cmd == SIOCGMIIPHY ||
		    cmd == SIOCGMIIREG ||
		    cmd == SIOCSMIIREG ||
		    cmd == SIOCBRADDIF ||
		    cmd == SIOCBRDELIF ||
		    cmd == SIOCSHWTSTAMP ||
		    cmd == SIOCGHWTSTAMP ||
		    cmd == SIOCWANDEV) {
			err = -EOPNOTSUPP;
			if (ops->ndo_do_ioctl) {
				if (netif_device_present(dev))
					err = ops->ndo_do_ioctl(dev, ifr, cmd);
				else
					err = -ENODEV;
			}
		} else
			err = -EINVAL;

	}
	return err;
}
Exemplo n.º 4
0
static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
    struct ifinfomsg  *ifm = NLMSG_DATA(nlh);
    struct rtattr    **ida = arg;
    struct net_device *dev;
    int err, send_addr_notify = 0;

    if (ifm->ifi_index >= 0)
        dev = dev_get_by_index(ifm->ifi_index);
    else if (ida[IFLA_IFNAME - 1]) {
        char ifname[IFNAMSIZ];

        if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
                           IFNAMSIZ) >= IFNAMSIZ)
            return -EINVAL;
        dev = dev_get_by_name(ifname);
    } else
        return -EINVAL;

    if (!dev)
        return -ENODEV;

    err = -EINVAL;

    if (ifm->ifi_flags)
        dev_change_flags(dev, ifm->ifi_flags);

    if (ida[IFLA_MAP - 1]) {
        struct rtnl_link_ifmap *u_map;
        struct ifmap k_map;

        if (!dev->set_config) {
            err = -EOPNOTSUPP;
            goto out;
        }

        if (!netif_device_present(dev)) {
            err = -ENODEV;
            goto out;
        }

        if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map)))
            goto out;

        u_map = RTA_DATA(ida[IFLA_MAP - 1]);

        k_map.mem_start = (unsigned long) u_map->mem_start;
        k_map.mem_end = (unsigned long) u_map->mem_end;
        k_map.base_addr = (unsigned short) u_map->base_addr;
        k_map.irq = (unsigned char) u_map->irq;
        k_map.dma = (unsigned char) u_map->dma;
        k_map.port = (unsigned char) u_map->port;

        err = dev->set_config(dev, &k_map);

        if (err)
            goto out;
    }

    if (ida[IFLA_ADDRESS - 1]) {
        struct sockaddr *sa;
        int len;

        if (!dev->set_mac_address) {
            err = -EOPNOTSUPP;
            goto out;
        }
        if (!netif_device_present(dev)) {
            err = -ENODEV;
            goto out;
        }
        if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
            goto out;

        len = sizeof(sa_family_t) + dev->addr_len;
        sa = kmalloc(len, GFP_KERNEL);
        if (!sa) {
            err = -ENOMEM;
            goto out;
        }
        sa->sa_family = dev->type;
        memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]),
               dev->addr_len);
        err = dev->set_mac_address(dev, sa);
        kfree(sa);
        if (err)
            goto out;
        send_addr_notify = 1;
    }

    if (ida[IFLA_BROADCAST - 1]) {
        if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len))
            goto out;
        memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]),
               dev->addr_len);
        send_addr_notify = 1;
    }

    if (ida[IFLA_MTU - 1]) {
        if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
            goto out;
        err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1])));

        if (err)
            goto out;

    }

    if (ida[IFLA_TXQLEN - 1]) {
        if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
            goto out;

        dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1]));
    }

    if (ida[IFLA_WEIGHT - 1]) {
        if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
            goto out;

        dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
    }

    if (ida[IFLA_OPERSTATE - 1]) {
        if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
            goto out;

        set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1])));
    }

    if (ida[IFLA_LINKMODE - 1]) {
        if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
            goto out;

        write_lock_bh(&dev_base_lock);
        dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1]));
        write_unlock_bh(&dev_base_lock);
    }

    if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) {
        char ifname[IFNAMSIZ];

        if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
                           IFNAMSIZ) >= IFNAMSIZ)
            goto out;
        err = dev_change_name(dev, ifname);
        if (err)
            goto out;
    }

#ifdef CONFIG_NET_WIRELESS_RTNETLINK
    if (ida[IFLA_WIRELESS - 1]) {

        /* Call Wireless Extensions.
         * Various stuff checked in there... */
        err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
        if (err)
            goto out;
    }
#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */

    err = 0;

out:
    if (send_addr_notify)
        call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);

    dev_put(dev);
    return err;
}
Exemplo n.º 5
0
ssize_t WIFI_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    INT32 retval = -EIO;
    INT8 local[12] = {0};
    struct net_device *netdev = NULL;
    PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode;
    INT32 wait_cnt = 0;

    down(&wr_mtx);
    if (count <= 0) {
        WIFI_ERR_FUNC("WIFI_write invalid param\n");
        goto done;
    }

    if (0 == copy_from_user(local, buf, (count > sizeof(local)) ? sizeof(local) : count)) {
        local[11] = 0;
        WIFI_INFO_FUNC("WIFI_write %s\n", local);

        if (local[0] == '0') {
            if (powered == 0) {
                WIFI_INFO_FUNC("WIFI is already power off!\n");
                retval = count;
                wlan_mode = WLAN_MODE_HALT;
                goto done;
            }

            netdev = dev_get_by_name(&init_net, ifname);
            if (netdev == NULL) {
                WIFI_ERR_FUNC("Fail to get %s net device\n", ifname);
            }
            else {
                p2pmode.u4Enable = 0;
                p2pmode.u4Mode = 0;

                if (pf_set_p2p_mode) {
                    if (pf_set_p2p_mode(netdev, p2pmode) != 0){
                        WIFI_ERR_FUNC("Turn off p2p/ap mode fail");
                    } else {
                        WIFI_INFO_FUNC("Turn off p2p/ap mode");
                        wlan_mode = WLAN_MODE_HALT;
                    }
               }
               dev_put(netdev);
               netdev = NULL;
            }

            if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI)) {
                WIFI_ERR_FUNC("WMT turn off WIFI fail!\n");
                powered = 2;
            }
            else {
                WIFI_INFO_FUNC("WMT turn off WIFI OK!\n");
                powered = 0;
                retval = count;
                wlan_mode = WLAN_MODE_HALT;
            #if CFG_TC1_FEATURE
                ifname = WLAN_IFACE_NAME;
                wlan_if_changed = 0;
            #endif
            }
        }
        else if (local[0] == '1') {
            if (powered == 1) {
                WIFI_INFO_FUNC("WIFI is already power on!\n");
                retval = count;
                goto done;
            } 

            if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) {
                WIFI_ERR_FUNC("WMT turn on WIFI fail!\n");
            }
            else {
                powered = 1;
                retval = count;
                WIFI_INFO_FUNC("WMT turn on WIFI success!\n");
                wlan_mode = WLAN_MODE_HALT;
            }
        }
        else if (local[0] == 'D') {
            INT32 k = 0;
            /* 
             * 0: no debug
             * 1: common debug output
             * 2: more detials
             * 3: verbose
             */
            switch (local[1]) {
            case '0':
                for (k = 0; k < DBG_MODULE_NUM; k++) {
                    wlan_dbg_level[k] = 0;
                }
                if (pf_set_dbg_level) {
                    pf_set_dbg_level(wlan_dbg_level);
                }
                break;
            case '1':
                for (k = 0; k < DBG_MODULE_NUM; k++) {
                    wlan_dbg_level[k] = DBG_CLASS_ERROR | \
                        DBG_CLASS_WARN | \
                        DBG_CLASS_STATE | \
                        DBG_CLASS_EVENT | \
                        DBG_CLASS_TRACE | \
                        DBG_CLASS_INFO;
                }
                wlan_dbg_level[DBG_TX_IDX] &= ~(DBG_CLASS_EVENT | \
                    DBG_CLASS_TRACE | \
                    DBG_CLASS_INFO);
                wlan_dbg_level[DBG_RX_IDX] &= ~(DBG_CLASS_EVENT | \
                    DBG_CLASS_TRACE | \
                    DBG_CLASS_INFO);
                wlan_dbg_level[DBG_REQ_IDX] &= ~(DBG_CLASS_EVENT | \
                    DBG_CLASS_TRACE | \
                    DBG_CLASS_INFO);
                wlan_dbg_level[DBG_INTR_IDX] = 0;
                wlan_dbg_level[DBG_MEM_IDX] = 0;
                if (pf_set_dbg_level) {
                    pf_set_dbg_level(wlan_dbg_level);
                }
                break;
            case '2':
                for (k = 0; k < DBG_MODULE_NUM; k++) {
                    wlan_dbg_level[k] = DBG_CLASS_ERROR | \
                        DBG_CLASS_WARN | \
                        DBG_CLASS_STATE | \
                        DBG_CLASS_EVENT | \
                        DBG_CLASS_TRACE | \
                        DBG_CLASS_INFO;
                }	
                wlan_dbg_level[DBG_INTR_IDX] = 0;
                wlan_dbg_level[DBG_MEM_IDX] = 0;
                if (pf_set_dbg_level) {
                    pf_set_dbg_level(wlan_dbg_level);
                }
                break;
            case '3':
                for (k = 0; k < DBG_MODULE_NUM; k++) {
                    wlan_dbg_level[k] = DBG_CLASS_ERROR | \
                        DBG_CLASS_WARN | \
                        DBG_CLASS_STATE | \
                        DBG_CLASS_EVENT | \
                        DBG_CLASS_TRACE | \
                        DBG_CLASS_INFO | \
                        DBG_CLASS_LOUD;
                }	
                if (pf_set_dbg_level) {
                    pf_set_dbg_level(wlan_dbg_level);
                }
                break;
            default:
                break;
            }
        }
        else if (local[0] == 'S' || local[0] == 'P' || local[0] == 'A') {
            if (powered == 0) {
                /* If WIFI is off, turn on WIFI first */
                if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) {
                    WIFI_ERR_FUNC("WMT turn on WIFI fail!\n");
                    goto done;
                }
                else {
                    powered = 1;
                    WIFI_INFO_FUNC("WMT turn on WIFI success!\n");
                    wlan_mode = WLAN_MODE_HALT;
                }
            }

            if (pf_set_p2p_mode == NULL) {
                WIFI_ERR_FUNC("Set p2p mode handler is NULL\n");
                goto done;
            }

            netdev = dev_get_by_name(&init_net, ifname);
            while (netdev == NULL && wait_cnt < 10) {
                WIFI_ERR_FUNC("Fail to get %s net device, sleep 300ms\n", ifname);
                msleep(300);
                wait_cnt ++;
                netdev = dev_get_by_name(&init_net, ifname);
            }
            if (wait_cnt >= 10) {
                WIFI_ERR_FUNC("Get %s net device timeout\n", ifname);
                goto done;
            }

            if ((wlan_mode == WLAN_MODE_STA_P2P && (local[0] == 'S' || local[0] == 'P')) ||
                (wlan_mode == WLAN_MODE_AP && (local[0] == 'A'))){
                WIFI_INFO_FUNC("WIFI is already in mode %d!\n", wlan_mode);
                retval = count;
                goto done;
            }

            if ((wlan_mode == WLAN_MODE_AP && (local[0] == 'S' || local[0] == 'P')) ||
                (wlan_mode == WLAN_MODE_STA_P2P && (local[0] == 'A'))){
                p2pmode.u4Enable = 0;
                p2pmode.u4Mode = 0;
                if (pf_set_p2p_mode(netdev, p2pmode) != 0){
                    WIFI_ERR_FUNC("Turn off p2p/ap mode fail");
                    goto done;
                }
            }

            if (local[0] == 'S' || local[0] == 'P'){
            #if CFG_TC1_FEATURE
                /* Restore NIC name to wlan0 */
                rtnl_lock();
                if (strcmp(ifname, WLAN_IFACE_NAME) != 0){
                    if (dev_change_name(netdev, WLAN_IFACE_NAME) != 0){
                        WIFI_ERR_FUNC("netdev name change to %s fail\n", WLAN_IFACE_NAME);
                        rtnl_unlock();
                        goto done;
                    }
                    else{
                        WIFI_INFO_FUNC("netdev name changed %s --> %s\n", ifname, WLAN_IFACE_NAME);
                        ifname = WLAN_IFACE_NAME;
                        wlan_if_changed = 0;
                    }
                }
                rtnl_unlock();
            #endif
                p2pmode.u4Enable = 1;
                p2pmode.u4Mode = 0;
                if (pf_set_p2p_mode(netdev, p2pmode) != 0){
                    WIFI_ERR_FUNC("Set wlan mode fail\n");
                }
                else{
                    WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_STA_P2P);
                    wlan_mode = WLAN_MODE_STA_P2P;
                    retval = count;
                }
            } else if (local[0] == 'A'){
            #if CFG_TC1_FEATURE
                /* Change NIC name to legacy0, since wlan0 is used for AP */
                rtnl_lock();
                if (strcmp(ifname, LEGACY_IFACE_NAME) != 0){
                    if (dev_change_name(netdev, LEGACY_IFACE_NAME) != 0){
                        WIFI_ERR_FUNC("netdev name change to %s fail\n", LEGACY_IFACE_NAME);
                        rtnl_unlock();
                        goto done;
                    }
                    else{
                        WIFI_INFO_FUNC("netdev name changed %s --> %s\n", ifname, LEGACY_IFACE_NAME);
                        ifname = LEGACY_IFACE_NAME;
                        wlan_if_changed = 1;
                    }
                }
                rtnl_unlock();
            #endif
                p2pmode.u4Enable = 1;
                p2pmode.u4Mode = 1;
                if (pf_set_p2p_mode(netdev, p2pmode) != 0){
                    WIFI_ERR_FUNC("Set wlan mode fail\n");
                }
                else{
                    WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_AP);
                    wlan_mode = WLAN_MODE_AP;
                    retval = count;
                }
            }
            dev_put(netdev);
            netdev = NULL;
        }
    }
done:
    if (netdev != NULL){
        dev_put(netdev);
    }
    up(&wr_mtx);
    return (retval);
}
ssize_t WIFI_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    int retval = -EIO;
    char local[12] = {0};
    static int opened = 0;
	int ret = -1;
	struct net_device *netdev = NULL;
	PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode;
	int wait_cnt = 0;

    down(&wr_mtx);
	if (count <= 0) {
		WIFI_INFO_FUNC("WIFI_write invalid param \n");
		goto done;
	}
	if (0 == copy_from_user(local, buf, (count > sizeof(local)) ? sizeof(local) : count)) {
		/*mtk80707 rollback aosp hal*/
		local[11] = 0;
	    WIFI_INFO_FUNC("WIFI_write %s\n", local);

            if (local[0] == '0' && opened == 1) {
                //TODO
                //Configure the EINT pin to GPIO mode.
			p2pmode.u4Enable = 0;
			p2pmode.u4Mode = 0;

			/*IF power off already*/
			if (power_state == 0) {
				WIFI_INFO_FUNC("WMT turn off WIFI OK!\n");
	            opened = 0;
	            retval = count;
				wlan_mode = WLAN_MODE_HALT;
				goto done;
			}
			if (flagIsIFchanged==1)
				{
			     netdev = dev_get_by_name(&init_net, WLAN_LEG_IFACE_NAME);}
		    else
		    	{netdev = dev_get_by_name(&init_net, WLAN_IFACE_NAME);}
			while (netdev == NULL && wait_cnt < 10) {
				WIFI_WARN_FUNC("WMT fail to get wlan0 net device, sleep 300ms\n");
				msleep(300);
				wait_cnt ++;
				if (flagIsIFchanged==1)
				{ netdev = dev_get_by_name(&init_net, WLAN_LEG_IFACE_NAME);}
		        else
		    	{ netdev = dev_get_by_name(&init_net, WLAN_IFACE_NAME);}
			}
			if (wait_cnt >= 10) {
				WIFI_WARN_FUNC("WMT get wlan0 net device time out\n");
				goto done;
			}
			if (pf_set_p2p_mode) {
				ret = pf_set_p2p_mode(netdev, p2pmode);
				if (ret != 0) {
					WIFI_WARN_FUNC("WMT trun off p2p & ap mode ret = %d", ret);
					goto done;
				}
				//msleep(300);
			}
			dev_put(netdev);
			netdev = NULL;

                if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI)) {
                    WIFI_INFO_FUNC("WMT turn off WIFI fail!\n");
                }
                else {
                    WIFI_INFO_FUNC("WMT turn off WIFI OK!\n");
                    opened = 0;
                    retval = count;
				wlan_mode = WLAN_MODE_HALT;
				power_state = 0;
				flagIsIFchanged=0;
				PowerOnIFname = 0;
                }
            }
            else if (local[0] == '1') {
                //TODO
                //Disable EINT(external interrupt), and set the GPIO to EINT mode.
                if (power_state == 1){
					WIFI_INFO_FUNC("WIFI is already on!\n");
                    retval = count;
                	}
				else {
			    pf_set_p2p_mode = NULL;
                if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) {
                    WIFI_WARN_FUNC("WMT turn on WIFI fail!\n");
                }
                else {
                    opened = 1;
                    retval = count;
                    WIFI_INFO_FUNC("WMT turn on WIFI success!\n");
				    wlan_mode = WLAN_MODE_HALT;
				    power_state = 1;
					//msleep(300);
                }
				    }
            }
		else if (local[0] == 'S' || local[0] == 'P' || local[0] == 'A') {	
			p2pmode.u4Enable = 1;
			p2pmode.u4Mode = 0;
			ret = -1;

            if (power_state ==0) {
				WIFI_INFO_FUNC("Turn on WIFI first if WIFI is off\n");
				if(local[0] == 'A')
					{
					 PowerOnIFname = 1; //legacy_wlan0
					 printk("change PoweronIFname\n");
					}
				pf_set_p2p_mode = NULL;
                if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) {
                    WIFI_WARN_FUNC("WMT turn on WIFI fail!\n");
                }
                else {
                    opened = 1;
                    retval = count;
                    WIFI_INFO_FUNC("WMT turn on WIFI success!\n");
				    wlan_mode = WLAN_MODE_HALT;
				    power_state = 1;
					if (local[0] == 'A'){
					flagIsIFchanged=1;}
                }
				
			}
			if (flagIsIFchanged==1)
				{netdev = dev_get_by_name(&init_net, WLAN_LEG_IFACE_NAME);
			    }
			else {
			    netdev = dev_get_by_name(&init_net, WLAN_IFACE_NAME);
				if (local[0] == 'A'&&netdev!=NULL)
					{
					 rtnl_lock();
		             ret = dev_change_name(netdev,WLAN_LEG_IFACE_NAME);
		             rtnl_unlock();
					 flagIsIFchanged=1;
					 printk("change_leagcy_name, ret = %d",ret);
					}
			     }
			while (netdev == NULL && wait_cnt < 10) {
				WIFI_WARN_FUNC("WMT fail to get wlan0 net device, sleep 300ms\n");
				msleep(300);
				wait_cnt ++;
				if (flagIsIFchanged==1)
				{netdev = dev_get_by_name(&init_net, WLAN_LEG_IFACE_NAME);}
			    else {
			     netdev = dev_get_by_name(&init_net, WLAN_IFACE_NAME);
                 if (local[0] == 'A'&&netdev!=NULL)
					{
					 rtnl_lock();
		             ret = dev_change_name(netdev,WLAN_LEG_IFACE_NAME);
		             rtnl_unlock();
					 flagIsIFchanged=1;
					 printk("change_leagcy_name, ret = %d",ret);
					}
				}
			    }
			if (wait_cnt >= 10) {
				WIFI_WARN_FUNC("WMT get wlan0 net device time out\n");
				goto done;
                }
			if (pf_set_p2p_mode == NULL) {
				WIFI_INFO_FUNC("set p2p handler is NULL\n");
				goto done;
			    }
			if (wlan_mode == WLAN_MODE_AP&&(local[0] == 'S' || local[0] == 'P') )
				{
			     p2pmode.u4Enable = 0;
			     p2pmode.u4Mode = 0;
				 ret = pf_set_p2p_mode(netdev, p2pmode);
				// msleep(300);
				 WIFI_INFO_FUNC("success to turn off p2p/AP mode\n");
				}
			p2pmode.u4Enable = 1;
			p2pmode.u4Mode = 0;
			ret = -1;
			if (local[0] == 'A') {
				p2pmode.u4Mode = 1;
            }
			ret = pf_set_p2p_mode(netdev, p2pmode);
			//msleep(300);
			dev_put(netdev);
			netdev = NULL;
			WIFI_INFO_FUNC("WMT WIFI set p2p mode ret=%d\n", ret);

			if (ret == 0 && (local[0] == 'S' || local[0] == 'P')) {
				WIFI_INFO_FUNC("wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_STA_P2P);
				wlan_mode = WLAN_MODE_STA_P2P;
				retval = count;
			} else if (ret == 0 && local[0] == 'A') {
				WIFI_INFO_FUNC("wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_AP);
				wlan_mode = WLAN_MODE_AP;
				retval = count;
			} else {
				WIFI_INFO_FUNC("fail to set wlan mode\n");
			}
		}
	}
done:
    up(&wr_mtx);
	if (netdev != NULL) {
		dev_put(netdev);
	}
    return (retval);
}