How to set wlan (wifi) frequency/channel

Hi all,

I use debian 16.06.
I want to fix the wifi frequency/channel, but some error occured.
I send these command as follows:

root@linaro-alip:~# iwconfig wlan0 channel 1
Error for wireless request “Set Frequency” (8B04) :
SET failed on device wlan0 ; Device or resource busy.
root@linaro-alip:~# iwconfig wlan0 freq 2.412G
Error for wireless request “Set Frequency” (8B04) :
SET failed on device wlan0 ; Device or resource busy.

does anyone have the same issue? how could I resolve it?

thanks,

Hi All,

I also cannot use iwconfig and iwpriv to set wlan frequency and channel.
Does anyone know how could we use those command?

Thanks.
Best regards,
Johnny

iwconfig is reporting an error after having called the kernel; the tool uses the following ioctl to set either the channel or frequency:

./include/uapi/linux/wireless.h:#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */

The driver:
https://wireless.wiki.kernel.org/en/users/Drivers/wcn36xx

For the extensions, the ioctl calls into net/wireless/wext-compat.c (function cfg80211_wext_siwfreq(…))

I did some debugging and the error comes from:
cfg80211_mgd_wext_siwfreq → cfg80211_set_monitor_channel-> cfg80211_has_monitors_only (returns EBUSY).

Unfortunately I am out of my depth on this (not sure what this check is doing and the implications of bypassing it). Having said that and just for a quick test, I commented out the error case:

int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
struct cfg80211_chan_def chandef)
{
if (!rdev->ops->set_monitor_channel)
return -EOPNOTSUPP;
if (!cfg80211_has_monitors_only(rdev)) {
printk(“cfg has monitors only\n”);
/
return -EBUSY; */
}

return rdev_set_monitor_channel(rdev, chandef);

}

The frequency can now be changed to any of the valid values defined in drivers/net/wireless/ath/wcn36xx/main.c:

/* The wcn firmware expects channel values to matching
 * their mnemonic values. So use these for .hw_value. */
static struct ieee80211_channel wcn_2ghz_channels[] = {
	CHAN2G(2412, 1), /* Channel 1 */
	CHAN2G(2417, 2), /* Channel 2 */
	CHAN2G(2422, 3), /* Channel 3 */
	CHAN2G(2427, 4), /* Channel 4 */
	CHAN2G(2432, 5), /* Channel 5 */
	CHAN2G(2437, 6), /* Channel 6 */
	CHAN2G(2442, 7), /* Channel 7 */
	CHAN2G(2447, 8), /* Channel 8 */
	CHAN2G(2452, 9), /* Channel 9 */
	CHAN2G(2457, 10), /* Channel 10 */
	CHAN2G(2462, 11), /* Channel 11 */
	CHAN2G(2467, 12), /* Channel 12 */
	CHAN2G(2472, 13), /* Channel 13 */
	CHAN2G(2484, 14)  /* Channel 14 */

};

For a test, I selected 2484GHz

dragonboard-410c:~# iwconfig wlan0 freq 2.484G

dragonboard-410c:~# iwconfig wlan0
wlan0     IEEE 802.11abgn  ESSID:off/any  
          Mode:Managed  Frequency:2.484 GHz  Access Point: Not-Associated   
          Tx-Power=20 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Encryption key:off
          Power Management:off

As I said, I dont know enough about the wireless framework to understand the implications of having hacked the kernel in this way.

This is the hack for discussion:

[jramirez@igloo ~ (debian-qcom-dragonboard410c-16.09-local *$)]$ git diff chan.cdiff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 59cabc9..07b038a 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -857,8 +857,6 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
 {
        if (!rdev->ops->set_monitor_channel)
                return -EOPNOTSUPP;
-   if (!cfg80211_has_monitors_only(rdev))
-           return -EBUSY;
 
        return rdev_set_monitor_channel(rdev, chandef);
 }

I did some more reading and in managed mode (client), the driver will not allow the frequency to be changed unless the following kernel commit http://tinyurl.com/ho4urp8 is reverted.

Note that managed mode is the mode that the dragon410 boots in by default.

However reverting such commit wouldn’t make any sense since in this mode it is the access point the one that provides the frequency/channel information.

To be able to change the frequency you will have to change to a mode where this makes sense (for instance, monitor mode)

So:

change to monitor mode

ifconfig wlan0 down
iwconfig wlan0 mode monitor
ifconfig wlan0 up

change the frequency
iwconfig wlan0 freq 2.484G

I validated the above on the dragon and it works as expected.

Hi Jorge,

Very appreciate for your sharing!!
I had tried ifconfig wlan0 down and change mode to monitor before, but I forgot to up the wlan0…
After I followed your command, the dragon board with Debian can work normally for this command (iwconfig).

Thanks again for your kindly help.

Best regards,
Johnny

Sure, no problem, thanks for raising it in the forum! this post triggered questions for me too :slight_smile:

You may also want to follow up this discussion thread that I started in linux-wireless and netdev mailing list:

http://tinyurl.com/iwconfig

Hi Jorge,

I found out that if I do the command:
ifconfig wlan0 down
ifconfig wlan0 up
Then the internet will be interrupted.

It seems not normal, how should I fix the problem?

Thanks.