hc
2024-08-16 62c46c9150c4afde7e5b25436263fddf79d66f0b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/mm.h>
 
#include "sprdwl.h"
#include "wl_core.h"
#define SOFTAP_INI_PATH "/data/misc/wifi/softap.ini"
 
static bool is_valid_channel(struct wiphy *wiphy, int chn)
{
   int i;
   struct ieee80211_supported_band *bands;
 
   if (chn < 15) {
       if (chn < 1)
           return false;
       return true;
   }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
   bands = wiphy->bands[NL80211_BAND_5GHZ];
#else
   bands = wiphy->bands[IEEE80211_BAND_5GHZ];
#endif
   for (i = 0; i < bands->n_channels; i++)
       if (chn == bands->channels[i].hw_value)
           return true;
 
   return false;
}
 
static int sprdwl_get_softap_chan(u8 *path)
{
   int ret;
   int chn;
   struct file *fp = NULL;
#ifdef setfs
   mm_segment_t fs;
#endif
   char buf[64] = {0};
 
   if (path == NULL)
       return -EINVAL;
 
   fp = filp_open(path, O_RDONLY, 0);
   if (IS_ERR(fp)) {
       wl_err("Open file: %s failed(%ld)\n", path, PTR_ERR(fp));
       return -EINVAL;
   }
 
#ifdef setfs
   fs = get_fs();
   set_fs(get_ds());
#endif
 
   ret = kernel_read(fp, buf, sizeof(buf), &fp->f_pos);
 
   filp_close(fp, NULL);
#ifdef setfs
   set_fs(fs);
#endif
 
   if (ret <= 0) {
       wl_err("read file failed, ret = %d\n", ret);
       return -EINVAL;
   }
 
   ret = sscanf(buf, "channel=%d\n", &chn);
   if (ret != 1) {
       wl_err("Keywords channel not found in %s\n", path);
       return -EINVAL;
   }
 
   return chn;
}
 
void sprdwl_hook_reset_channel(struct wiphy *wiphy,
                  struct cfg80211_ap_settings *settings)
{
   u8 *ie, *ds_param_ch;
   int channel = 1;
   struct ieee80211_mgmt *mgmt;
   struct ieee80211_ht_operation *oper;
 
   /* Read channel from file /data/misc/wifi/softap.ini */
   channel = sprdwl_get_softap_chan(SOFTAP_INI_PATH);
   if (channel < 0)
       return;
 
   if (!is_valid_channel(wiphy, channel)) {
       wl_err("%s channel(%d) invalid\n", __func__, channel);
       return;
   }
 
   mgmt = (struct ieee80211_mgmt *)settings->beacon.head;
   ie = (u8 *)cfg80211_find_ie(WLAN_EID_DS_PARAMS,
                   &mgmt->u.beacon.variable[0],
                   settings->beacon.head_len);
   if (ie == NULL) {
       wl_err("IE WLAN_EID_DS_PARAMS not found in beacon\n");
       return;
   }
 
   ds_param_ch = ie + 2;
 
   ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_OPERATION,
                   settings->beacon.tail,
                   settings->beacon.tail_len);
   if (ie == NULL) {
       wl_err("IE WLAN_EID_HT_OPERATION not found in beacon\n");
       return;
   }
 
   ie += 2;
   oper = (struct ieee80211_ht_operation *)ie;
 
   wl_info("%s done, reset channel %d -> %d\n", __func__,
          oper->primary_chan, channel);
 
   *ds_param_ch = oper->primary_chan = channel;
}