2 * Copyright (c) 2009 - 2014 Espressif System.
5 #include "linux/types.h"
6 #include "linux/kernel.h"
7 #include <linux/ieee80211.h>
8 #include <net/mac80211.h>
9 #include <linux/skbuff.h>
13 #include <asm/checksum.h>
16 #include "esp_utils.h"
18 #include "esp_debug.h"
21 * Convert IEEE channel number to MHz frequency.
23 u32 esp_ieee2mhz(u8 chan)
31 return 2512 + ((chan-15)*20);
35 ESP_RATE_1_LONG = 0x0,
36 ESP_RATE_2_LONG = 0x1,
37 ESP_RATE_2_SHORT = 0x5,
38 ESP_RATE_5_SHORT = 0x6,
39 ESP_RATE_5_LONG = 0x2,
40 ESP_RATE_11_SHORT = 0x7,
41 ESP_RATE_11_LONG = 0x3,
50 /* ESP_RATE_MCS0 =0x10,
61 static u8 esp_rate_table[20] = {
85 s8 esp_wmac_rate2idx(u8 rate)
89 if (rate == ESP_RATE_2_LONG)
91 if (rate == ESP_RATE_5_LONG)
93 if (rate == ESP_RATE_11_LONG)
96 for (i = 0; i < 20; i++) {
97 if (rate == esp_rate_table[i])
101 esp_dbg(ESP_DBG_ERROR,"%s unknown rate 0x%02x \n", __func__, rate);
106 bool esp_wmac_rxsec_error(u8 error)
108 return (error >= RX_SECOV_ERR && error <= RX_SECFIFO_TIMEOUT) || (error >= RX_WEPICV_ERR && error <= RX_WAPIMIC_ERR);
111 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
112 int esp_cipher2alg(int cipher)
114 if (cipher == WLAN_CIPHER_SUITE_TKIP)
117 if (cipher == WLAN_CIPHER_SUITE_CCMP)
120 if (cipher == WLAN_CIPHER_SUITE_WEP40 || cipher == WLAN_CIPHER_SUITE_WEP104)
123 if (cipher == WLAN_CIPHER_SUITE_AES_CMAC)
126 //printk("%s wrong cipher 0x%x!\n",__func__,cipher);
130 #endif /* NEW_KERNEL */
132 #ifdef RX_CHECKSUM_TEST
134 void esp_rx_checksum_test(struct sk_buff *skb)
136 static u32 ip_err = 0;
137 static u32 tcp_err = 0;
138 struct ieee80211_hdr *pwh = (struct ieee80211_hdr *)skb->data;
139 int hdrlen = ieee80211_hdrlen(pwh->frame_control);
141 if(ieee80211_has_protected(pwh->frame_control))
142 hdrlen += atomic_read(&g_iv_len);
144 if (ieee80211_is_data(pwh->frame_control)) {
145 struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
146 if (ntohs(llc->eth_type) == ETH_P_IP) {
147 int llclen = sizeof(struct llc_snap_hdr);
148 struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
149 __sum16 csum_bak = iph->check;
152 iph->check = ip_fast_csum(iph, iph->ihl);
153 if (iph->check != csum_bak) {
154 esp_dbg(ESP_DBG_ERROR, "total ip checksum error %d\n", ++ip_err);
156 iph->check = csum_bak;
158 if (iph->protocol == 0x06) {
159 struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
160 int datalen = skb->len - (hdrlen + llclen + iph->ihl * 4);
161 csum_bak = tcph->check;
164 tcph->check = tcp_v4_check(datalen, iph->saddr, iph->daddr, csum_partial((char *)tcph, datalen, 0));
165 if (tcph->check != csum_bak)
167 esp_dbg(ESP_DBG_ERROR, "total tcp checksum error %d\n", ++tcp_err);
169 tcph->check = csum_bak;
177 #ifdef GEN_ERR_CHECKSUM
179 void esp_gen_err_checksum(struct sk_buff *skb)
181 static u32 tx_seq = 0;
182 if ((tx_seq++ % 16) == 0)
184 struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
185 int hdrlen = ieee80211_hdrlen(hdr->frame_control);
187 if(ieee80211_has_protected(pwh->frame_control))
188 hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
190 struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
191 if (ntohs(llc->eth_type) == ETH_P_IP) {
192 int llclen = sizeof(struct llc_snap_hdr);
193 struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
195 iph->check = ~iph->check;
197 if (iph->protocol == 0x06) {
198 struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
199 tcph->check = ~tcph->check;
206 bool esp_is_ip_pkt(struct sk_buff *skb)
208 struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
210 struct llc_snap_hdr * llc;
212 if (!ieee80211_is_data(hdr->frame_control))
215 hdrlen = ieee80211_hdrlen(hdr->frame_control);
216 if(ieee80211_has_protected(hdr->frame_control))
217 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
218 hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
220 hdrlen += IEEE80211_SKB_CB(skb)->control.iv_len;
222 #ifdef RX_CHECKSUM_TEST
223 atomic_set(&g_iv_len, IEEE80211_SKB_CB(skb)->control.hw_key->iv_len);
225 if(skb->len < hdrlen + sizeof(struct llc_snap_hdr))
227 llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
228 if (ntohs(llc->eth_type) != ETH_P_IP)