Android WiFi Port
Two Wi-Fi modules, vt6656 and rt2070, were transplanted on Android 2.2. First, compile the WiFi Linux driver into a module and put the driver (vntwusb. Ko or rt3070sta. KO in/system/lib/modules. Then, make the following changes:
1. Modify init. RC: Many articles have descriptions, but some of them are unclear. I will first list the added items and then explain them.
Added: mkdir/system/etc/WiFi 0771 WiFi
Chmod 0771/system/etc/WiFi
Chmod 0660/system/etc/WiFi/wpa_supplicant.conf
Chown WiFi/system/etc/WiFi/wpa_supplicant.conf # original wifi configuration file
# Wpa_supplicant socket
Mkdir/data/system/wpa_supplicant 0771 WiFi
Chmod 0771/data/system/wpa_supplicant # Place the Wi-Fi Interface
Mkdir/data/MISC/WiFi 0771 WiFi
Chmod 0771/data/MISC/WiFi
Chmod 0660/data/MISC/WiFi/wpa_supplicant.conf # the configuration file of wifi will be written to this file by wpa_supplicant according to the actual configuration
Mkdir/data/MISC/WiFi/sockets 0777
WiFi # path for communication with the upper layer through socket
# Prepare for WiFi
Setprop wifi. Interface ra0
# Set the intreface name, which is in framework/base/WiFi/Java/Android/NET/WiFi
/Wifistatetracker. Java will be used to process DHCP. Rt2070 uses ra0, while vt6656 uses eth1.
0771 goals
The permission recording process allows all users to search for the next level, and the permission configuration highlighted in red is because the/data/MISC/WiFi/sockets directory is not only
The producer service also needs to contact other users for communication reasons. Otherwise, unable to open connection to supplicant on will appear.
"/Data/system/wpa_supplicant/ra0": Connection refused, or permission
Denied error. Many people simply set all of the above permissions to 0777, of course, but they always feel a bit rough.
Service modification:
Service wpa_supplicant/system/bin/logwrapper/system/bin/wpa_supplicant/
-Dwext-ira0-C/data/MISC/WiFi/wpa_supplicant.conf # You can also use/system/etc/WiFi/wpa_supplicant.conf instead.
User Root
Group system WiFi inet
# Socket wpa_wlan0 dgram 660 WiFi # block this item because it is used for UDP connection
Disable
Oneshot
Service dhcpcd/system/bin/logwrapper/system/bin/dhcpcd-D-B ra0
Group system DHCP WiFi
Disabled
Oneshot
2. Modify system/etc/WiFi/wpa_supplicant.conf (in the source code, modify external/wpa_supplicant/wpa_supplicant.conf)
Change ctrl_interface = wlan0 to ctrl_interface = dir =/data/system/wpa_supplicant group = WiFi # This path is used in wifi. C.
3. Modify system/etc/dhcpcd. conf
Change the interface name to ra0.
4. Modify the configuration boardconfig. mk of the chip vendor.
For example, freeescale is added in device/FSL/imx51_bbg:
Have_custom_wifi_driver_2: = true
Board_wpa_supplicant_driver: = wext
The defined Wi-Fi driver path below is better than blocking. It is not more intuitive to directly modify it in wifi. C.
5. Modify Hardware/libhardware_legacy/WiFi/wifi. c
Ifndef wifi_driver_module_path
# Define wifi_driver_module_path "/system/lib/modules/rt3070sta. Ko"
# Endif
# Ifndef wifi_driver_module_name
# Define wifi_driver_module_name "rt3070sta"
# Endif
In
File, for example, iface_dir [] = "/data/system/wpa_supplicant ",
Is the path of the interface. Module_file [] =
"/Proc/modules", which is the path for insmod to place the module. During debugging, you can check whether the module has been installed and whether the interface has been started.
6. Source code modification
Repair
Change external/wpa_supplicant/wpa_ctrl.c:
Find the CHMOD line and press chmod (CTRL-> Local. sun_path,
S_irusr | s_iwusr | s_irgrp | s_iwgrp); change to chmod (CTRL-> Local. sun_path,
S_irusr | s_iwusr | s_irgrp | s_iwgrp | s_iroth | s_iwoth); # add permissions
This is to prevent the error of message writing by IOCTL.
Modify external/wpa_supplicant/driver_wext.c:
This
It is to avoid the ioctl [siocsiwpriv] error when wpa_supplicant communicates with the lower-layer driver, because most of the Wi-Fi module
The siocsiwpriv command is not processed, and this command is used to detect the Wi-Fi strength of the request. A simple method is to add an empty function to the WiFi driver. For example
Rt2070, there is a sta_ioctl.c, find siocsiwpriv, and corresponding empty Function
Static int handler_siocsiwpriv (struct net_device * Dev, struct iw_request_info * info,
Union iwreq_data * wrqu, char * extra)
{
Return 0;
}
However, in this case, some information, such as HTTP, MAC addresses, cannot be displayed on the upper layer. A better method is as follows:
Add
U8 SSID [32];
Unsigned int ssid_len;
Two variables. Change the original wpa_driver_priv_driver_cmd function to the following function (I copied it from porting WiFi driver to Android for slight modification ):
Static int wpa_driver_priv_driver_cmd (void * priv, char * cmd, char * Buf, size_t buf_len)
{
Struct wpa_driver_wext_data * DRV = priv;
Int ret =-1;
Wpa_printf (msg_debug, "awext: % S % s", _ FUNC __, cmd );
If (OS _strcasecmp (CMD, "Start") = 0 ){
Wpa_printf (msg_debug, "Start command ");
Return (RET );
}
If (OS _strcasecmp (CMD, "stop") = 0 ){
Wpa_printf (msg_debug, "Stop command ");
}
Else if (OS _strcasecmp (CMD, "macaddr") = 0 ){
Struct ifreq IFR;
OS _memset (& IFR, 0, sizeof (IFR ));
OS _strncpy (IFR. ifr_name, DRV-> ifname, ifnamsiz );
If (IOCTL (DRV-> ioctl_sock, siocgifhwaddr, & IFR) <0 ){
Perror ("IOCTL [siocgifhwaddr]");
Ret =-1;
} Else {
U8 * macaddr = (u8 *) IFR. ifr_hwaddr.sa_data;
Ret = snprintf (BUF, buf_len, "macaddr =" macstr "/N ",
Mac2str (macaddr ));
}
}
Else if (OS _strcasecmp (CMD, "Scan-Passive") = 0 ){
Wpa_printf (msg_debug, "Scan passive command ");
}
Else if (OS _strcasecmp (CMD, "Scan-active") = 0 ){
Wpa_printf (msg_debug, "Scan active command ");
}
Else if (OS _strcasecmp (CMD, "linkspeed") = 0 ){
Struct iwreq WRQ;
Unsigned int linkspeed;
OS _strncpy (WRQ. ifr_name, DRV-> ifname, ifnamsiz );
Wpa_printf (msg_debug, "link speed command ");
If (IOCTL (DRV-> ioctl_sock, siocgiwrate, & WRQ) <0 ){
Perror ("IOCTL [siocgiwrate]");
Ret =-1;
} Else {
Linkspeed = WRQ. U. bitrate. Value/1000000;
Ret = snprintf (BUF, buf_len, "linkspeed % d/N", linkspeed );
}
}
Else if (OS _strncasecmp (CMD, "Scan-channels", 13) = 0 ){
}
Else if (OS _strcasecmp (CMD, "reported") = 0) | (OS _strcasecmp (CMD, "reported-approx") = 0 )){
Struct iwreq WRQ;
Struct iw_statistics stats;
Signed int ARG;
Wpa_printf (msg_debug, ">>>. Driver awext RSSI ");
WRQ. U. Data. pointer = (caddr_t) & stats;
WRQ. U. Data. Length = sizeof (Stats );
WRQ. U. Data. Flags = 1;/* clear updated flag */
Strncpy (WRQ. ifr_name, DRV-> ifname, ifnamsiz );
If (IOCTL (DRV-> ioctl_sock, siocgiwstats, & WRQ) <0 ){
Perror ("IOCTL [siocgiwstats]");
Ret =-1;
} Else {
If (stats. Qual. Updated & iw_qual_dbm ){
/* Values in dBm, stored in u8 with range 63:-192 */
(Stats. Qual. level> 63 )?
Stats. Qual. Level-Zero X 100:
Stats. Qual. level;
} Else {
Arg = stats. Qual. level;
}
If (DRV-> ssid_len! = 0 & DRV-> ssid_len <buf_len ){
OS _memcpy (void *) BUF, (void *) (DRV-> SSID ),
DRV-> ssid_len );
Ret = DRV-> ssid_len;
RET + = snprintf (& Buf [RET], buf_len-ret,
"Arg % d/N", ARG );
If (Ret <(INT) buf_len ){
Return (RET );
}
Ret =-1;
}
}
}
Else if (OS _strncasecmp (CMD, "powermode", 9) = 0 ){
}
Else if (OS _strncasecmp (CMD, "getpower", 8) = 0 ){
}
Else if (OS _strncasecmp (CMD, "get-RTS-threshold", 17) = 0 ){
Struct iwreq WRQ;
Unsigned int rtsthreshold;
Strncpy (WRQ. ifr_name, DRV-> ifname, ifnamsiz );
If (IOCTL (DRV-> ioctl_sock, siocgiwrts, & WRQ) <0 ){
Perror ("IOCTL [siocgiwrts]");
Ret =-1;
} Else {
Rtsthreshold = WRQ. U. Rts. value;
Wpa_printf (msg_debug, "Get RTS threshold command = % d ",
Rtsthreshold );
Ret = snprintf (BUF, buf_len, "RTS-Threshold = % u/N ",
Rtsthreshold );
If (Ret <(INT) buf_len ){
Return (RET );
}
}
}
Else if (OS _strncasecmp (CMD, "set-RTS-threshold", 17) = 0 ){
Struct iwreq WRQ;
Unsigned int rtsthreshold;
Char * CP = cmd + 17;
Char * endp;
Strncpy (WRQ. ifr_name, DRV-> ifname, ifnamsiz );
If (* CP! = '/0 '){
Rtsthreshold = (unsigned INT) strtol (CP, & endp, 0 );
If (endp! = CP ){
WRQ. U. Rts. value = rtsthreshold;
WRQ. U. Rts. Fixed = 1;
WRQ. U. Rts. Disabled = 0;
If (IOCTL (DRV-> ioctl_sock, siocsiwrts, & WRQ) <0 ){
Perror ("IOCTL [siocgiwrts]");
Ret =-1;
} Else {
Rtsthreshold = WRQ. U. Rts. value;
Wpa_printf (msg_debug, "set RTS threshold command = % d", rtsthreshold );
Ret = 0;
}
}
}
}
Else if (OS _strcasecmp (CMD, "btcoexscan-start") = 0 ){
}
Else if (OS _strcasecmp (CMD, "btcoexscan-stop") = 0 ){
}
Else if (OS _strcasecmp (CMD, "rxfilter-start") = 0 ){
Wpa_printf (msg_debug, "RX data filter start command ");
}
Else if (OS _strcasecmp (CMD, "rxfilter-stop") = 0 ){
Wpa_printf (msg_debug, "RX data filter Stop command ");
}
Else if (OS _strcasecmp (CMD, "rxfilter-Statistics") = 0 ){
}
Else if (OS _strncasecmp (CMD, "rxfilter-Add", 12) = 0 ){
}
Else if (OS _strncasecmp (CMD, "rxfilter-Remove", 15) = 0 ){
}
Else if (OS _strcasecmp (CMD, "SNR") = 0 ){
Struct iwreq WRQ;
Struct iw_statistics stats;
Int SNR, SNR, noise;
WRQ. U. Data. pointer = (caddr_t) & stats;
WRQ. U. Data. Length = sizeof (Stats );
WRQ. U. Data. Flags = 1;/* clear updated flag */
Strncpy (WRQ. ifr_name, DRV-> ifname, ifnamsiz );
If (IOCTL (DRV-> ioctl_sock, siocgiwstats, & WRQ) <0 ){
Perror ("IOCTL [siocgiwstats]");
Ret =-1;
} Else {
If (stats. Qual. Updated & iw_qual_dbm ){
/* Values in dBm, stored in u8 with range 63:-192 */
(Stats. Qual. level> 63 )?
Stats. Qual. Level-Zero X 100:
Stats. Qual. level;
Noise = (stats. Qual. Noise> 63 )?
Stats. Qual. Noise-0x100:
Stats. Qual. noise;
} Else {
Arg = stats. Qual. level;
Noise = stats. Qual. noise;
}
SNR = SNR-noise;
Ret = snprintf (BUF, buf_len, "SNR = % u/N", (unsigned INT) SNR );
If (Ret <(INT) buf_len ){
Return (RET );
}
}
}
Else if (OS _strncasecmp (CMD, "btcoexmode", 10) = 0 ){
}
Else if (OS _strcasecmp (CMD, "btcoexstat") = 0 ){
}
Else {
Wpa_printf (msg_debug, "unsupported command ");
}
Return (RET );
}
After these changes, the WiFi should be able to go up.
Problem retention:
1. This modification is made to wpa_supplicant of version 5.x. Android has version 6.x, and I have not found driver_wext.c !, How can I implement the above changes? It seems that research is needed.
2. The modified driver_wext.c can display the MAC address, and the signal strength can also be displayed on the upper-layer setting interface, but the intensity is not displayed on the home page. It is estimated that the reason should be found in the Java program.
3. On the settings page, if WiFi is disabled and the connection fails, you must manually set ifconfig ra0 up on the debug terminal to trigger the connection. It is estimated that the WiFi settings are not initialized when the Java program disables wifi. Check the modified database.