源码_添加wifi电源管理接口供jni调用
===============================================================================
接收来自kernel的netlink,然后派发到所有"ATTACH"到该eth0接口的monitor_conn们
=>wpa_driver_wext_event_receive =>wpa_supplicant_event =>wpa_msg =>wpa_msg_cb
最终调用,将event发往所有"ATTACH"了的monitor_conn程序.
=>wpa_supplicant_ctrl_iface_msg_cb
===============================================================================
接收处理来自ctrl_conn或者monitor_conn发送过来的所有数据
=>wpa_supplicant_ctrl_iface_receive
=>wpa_supplicant_ctrl_iface_process
=>wpa_supplicant_driver_cmd
=>wpa_drv_driver_cmd
=>wpa_s->driver->driver_cmd就是wpa_driver_wext_ops.driver_cmd
=>wpa_driver_wext_driver_cmd
const struct wpa_driver_ops wpa_driver_wext_ops = {
...
.get_bssid = wpa_driver_wext_get_bssid,
.get_ssid = wpa_driver_wext_get_ssid,
.set_wpa = wpa_driver_wext_set_wpa,
.set_channel = wpa_driver_wext_set_channel,
.set_ssid = wpa_driver_wext_set_ssid,
.init = wpa_driver_wext_init,
.driver_cmd = wpa_driver_wext_driver_cmd,//自己添加
...
};
===============================================================================
drivers/net/wireless/mrvl8688/wlan_priv.c
wlan_set_power
wlan_deepsleep_ioctl
wlan_hscfg_ioctl
struct iwreq iwr;
os_memset(&iwr, 0, sizeof(iwr));
iwr.u.power.disabled = 1;
ioctl(drv->ioctl_sock, SIOCSIWPOWER, &iwr);//主要是记住是union
//iwr对应kernel中struct ifreq *req;
sys_ioctl
=>vfs_ioctl
=>filp->f_op->unlocked_ioctl
=>sock_ioctl
=>dev_ioctl
=>wext_handle_ioctl
=>wireless_process_ioctl
=>wlan_do_ioctl
union iwreq_data
{
char name[IFNAMSIZ];
struct iw_point essid;
struct iw_param nwid;
struct iw_freq freq;
struct iw_param sens;
struct iw_param bitrate;
struct iw_param txpower;
struct iw_param rts;
struct iw_param frag;
__u32 mode;
struct iw_param retry;
struct iw_point encoding;
struct iw_param power;
struct iw_quality qual;
struct sockaddr ap_addr;
struct sockaddr addr;
struct iw_param param;
struct iw_point data;
};
struct iwreq
{
union
{
char ifrn_name[IFNAMSIZ];
} ifr_ifrn;
union iwreq_data u;
};
======================================================================================
'-'表示output
'+'表示input
echo -170=0>/d/gpio
echo -96 =0>/d/gpio //必须让'='索引为4,所以需要补齐
以下添加参考iwpriv eth0 hscfg命令
iwpriv eth0 powergpio #gpio value
1.drivers/net/wireless/mrvl8688/wlan_priv.h
>>>
#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
而
#define WLANPOWERGPIO (WLANIOCTL + 32)刚好就等于0x8C00
所以这样会导致错误,iwpriv总是提示错误
{
WLANPOWERGPIO,
IW_PRIV_TYPE_INT | 16,
IW_PRIV_TYPE_INT | 16,
"powergpio"},
2.drivers/net/wireless/mrvl8688/wlan_priv.c
>>>
2.1 static int wlan_powergpio_ioctl(wlan_private * priv, struct iwreq *wrq)
2.2 case WLANPOWERGPIO:
ret = wlan_powergpio_ioctl(priv, wrq);
static int
wlan_powergpio_ioctl(wlan_private * priv, struct iwreq *wrq)
{
wlan_adapter *Adapter = priv->adapter;
int data[2] = { -1, 0xff};
int ret = WLAN_STATUS_SUCCESS;
if (wrq->u.data.length >= 1 && wrq->u.data.length <= 2) {
if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * wrq->u.data.length)) {
PRINTM(INFO, "Copy from user failed\n");
return -EFAULT;
}
PRINTM(INFO,
"wlan_powergpio_ioctl: data[0]=%#08x, data[1]=%#02x\n",
data[0], data[1]);
} else {
PRINTM(MSG, "Sample: iwpriv eth0 powergpio #gpio [value]\n");
return -EINVAL;
}
switch(wrq->u.data.length) {
case 2:
if(data[0] < ARCH_NR_GPIOS) {
//if(!(ret = gpio_request(mfp_to_gpio(data[0]), "powergpio"))) {
//mfp_cfg_t powergpio_mfp_cfg = (mfp_to_gpio(data[0]) << 16) | MFPR_DEFAULT | MFP_AF0;
//pxa3xx_mfp_config(&powergpio_mfp_cfg, 1);
ret = gpio_direction_output(mfp_to_gpio(data[0]), data[1]);
//}
} else {
ret = -EINVAL;
}
break;
}
if(ret >= 0) {
data[0] = data[0];
data[1] = gpio_get_value(mfp_to_gpio(data[0]));//read gpio value;
wrq->u.data.length = 2;
if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) {
PRINTM(INFO, "Copy to user failed\n");
return -EFAULT;
}
}
return ret;
}
======================================================================================
int wpa_driver_wext_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len )
{
...
if (os_strncasecmp(cmd, "POWERMODE", sizeof("POWERMODE") - 1) == 0) {
//wpa_printf(MSG_DEBUG, "POWERMODE command = \"%s\"", cmd);
ret = wpa_driver_wext_powermode(drv, atoi(strchr(cmd, ' ')));
}
...
}
static inline int
iw_get_ext(int skfd, /* Socket to the kernel */
const char * ifname, /* Device name */
int request, /* WE ID */
struct iwreq* piwr) /* Fixed part of the request */
{
os_strncpy(piwr->ifr_name, ifname, IFNAMSIZ);
return(ioctl(skfd, request, piwr));
}
static int
wpa_driver_wext_powermode(struct wpa_driver_wext_data *drv, int mode)
{
#define ANDROID_DRIVER_POWER_MODE_AUTO 0
#define ANDROID_DRIVER_POWER_MODE_ACTIVE 1
#define ANDROID_DRIVER_POWER_MODE_DEEPSLEEP 2
#define ANDROID_DRIVER_POWER_MODE_DEEPSLEEP_EXIT 3
struct iwreq iwr;
int request_cmd;
char buffer[16];
int ret = -1;
const char *ifname = drv->ifname;
int skfd = drv->ioctl_sock;
os_memset(&iwr, 0, sizeof(iwr));
switch (mode) {
case ANDROID_DRIVER_POWER_MODE_AUTO:
request_cmd = SIOCSIWPOWER;
iwr.u.power.disabled = 1;
break;
case ANDROID_DRIVER_POWER_MODE_ACTIVE:
/* get power info */
if ((ret = iw_get_ext(skfd, ifname, SIOCGIWPOWER, &iwr)) < 0) {
fprintf(stderr, "ANDROID_DRIVER_POWER_MODE_AUTO erro\n");
goto __wpa_driver_wext_powermode_out;
}
request_cmd = SIOCSIWPOWER;
iwr.u.power.flags = 0;
iwr.u.power.disabled = 0;
break;
case ANDROID_DRIVER_POWER_MODE_DEEPSLEEP:
request_cmd = WLANDEEPSLEEP;
buffer[0] = '1';
iwr.u.data.pointer = (caddr_t) buffer;
iwr.u.data.length = 1;
break;
case ANDROID_DRIVER_POWER_MODE_DEEPSLEEP_EXIT:
request_cmd = WLANDEEPSLEEP;
buffer[0] = '0';
iwr.u.data.pointer = (caddr_t) buffer;
iwr.u.data.length = 1;
break;
default:
goto __wpa_driver_wext_powermode_out;
break;
}
ret = iw_get_ext(skfd, ifname, request_cmd, &iwr);
__wpa_driver_wext_powermode_out:
return ret;
}
======================================================================================
./wpa_supplicant -c ./wpa_supplicant.conf -i eth0 &
./iwpriv eth0 drvdbg 0x6002007f
./wpa_cli
> driver powermode 0
> driver powermode 1
> driver powermode 2
> driver powermode 3
|