4
0
forked from Mirror/wfb-ng

Initial commit

This commit is contained in:
Vasily Evseenko 2017-01-23 11:37:26 +03:00
commit 834aa7b5bc
27 changed files with 3523 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.o
*.a
rx
tx

7
.hgignore Normal file
View File

@ -0,0 +1,7 @@
syntax: glob
rx
tx
*.orig
*.swp

51
LICENSE Normal file
View File

@ -0,0 +1,51 @@
wifibroadcast and its FEC code are free software
you can redistribute wifibroadcast core functionality and/or
it them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
the FEC code is covered by the following license:
fec.c -- forward error correction based on Vandermonde matrices
980624
(C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
(C) 2001 Alain Knaff (alain@knaff.lu)
Portions derived from code by Phil Karn (karn@ka9q.ampr.org),
Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari
Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.

23
Makefile Normal file
View File

@ -0,0 +1,23 @@
LDFLAGS=-lrt -lpcap
CPPFLAGS=-Wall
all: rx tx
%.o: %.c *.h
gcc -c -o $@ $< $(CPPFLAGS)
%.o: %.cpp *.hpp *.h
g++ -std=c++11 -c -o $@ $< $(CPPFLAGS)
rx: rx.o radiotap.o fec.o
g++ -o $@ $^ $(LDFLAGS)
tx: tx.o fec.o
g++ -o $@ $^ $(LDFLAGS)
clean:
rm -f rx tx *~ *.o

576
fec.c Normal file
View File

@ -0,0 +1,576 @@
/**
* zfec -- fast forward error correction library with Python interface
*/
#include "fec.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/*
* Primitive polynomials - see Lin & Costello, Appendix A,
* and Lee & Messerschmitt, p. 453.
*/
static const char*const Pp="101110001";
/*
* To speed up computations, we have tables for logarithm, exponent and
* inverse of a number. We use a table for multiplication as well (it takes
* 64K, no big deal even on a PDA, especially because it can be
* pre-initialized an put into a ROM!), otherwhise we use a table of
* logarithms. In any case the macro gf_mul(x,y) takes care of
* multiplications.
*/
static gf gf_exp[510]; /* index->poly form conversion table */
static int gf_log[256]; /* Poly->index form conversion table */
static gf inverse[256]; /* inverse of field elem. */
/* inv[\alpha**i]=\alpha**(GF_SIZE-i-1) */
/*
* modnn(x) computes x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1,
* without a slow divide.
*/
static gf
modnn(int x) {
while (x >= 255) {
x -= 255;
x = (x >> 8) + (x & 255);
}
return x;
}
#define SWAP(a,b,t) {t tmp; tmp=a; a=b; b=tmp;}
/*
* gf_mul(x,y) multiplies two numbers. It is much faster to use a
* multiplication table.
*
* USE_GF_MULC, GF_MULC0(c) and GF_ADDMULC(x) can be used when multiplying
* many numbers by the same constant. In this case the first call sets the
* constant, and others perform the multiplications. A value related to the
* multiplication is held in a local variable declared with USE_GF_MULC . See
* usage in _addmul1().
*/
static gf gf_mul_table[256][256];
#define gf_mul(x,y) gf_mul_table[x][y]
#define USE_GF_MULC register gf * __gf_mulc_
#define GF_MULC0(c) __gf_mulc_ = gf_mul_table[c]
#define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x]
/*
* Generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
* Lookup tables:
* index->polynomial form gf_exp[] contains j= \alpha^i;
* polynomial form -> index form gf_log[ j = \alpha^i ] = i
* \alpha=x is the primitive element of GF(2^m)
*
* For efficiency, gf_exp[] has size 2*GF_SIZE, so that a simple
* multiplication of two numbers can be resolved without calling modnn
*/
static void
_init_mul_table(void) {
int i, j;
for (i = 0; i < 256; i++)
for (j = 0; j < 256; j++)
gf_mul_table[i][j] = gf_exp[modnn (gf_log[i] + gf_log[j])];
for (j = 0; j < 256; j++)
gf_mul_table[0][j] = gf_mul_table[j][0] = 0;
}
#define NEW_GF_MATRIX(rows, cols) \
(gf*)malloc(rows * cols)
/*
* initialize the data structures used for computations in GF.
*/
static void
generate_gf (void) {
int i;
gf mask;
mask = 1; /* x ** 0 = 1 */
gf_exp[8] = 0; /* will be updated at the end of the 1st loop */
/*
* first, generate the (polynomial representation of) powers of \alpha,
* which are stored in gf_exp[i] = \alpha ** i .
* At the same time build gf_log[gf_exp[i]] = i .
* The first 8 powers are simply bits shifted to the left.
*/
for (i = 0; i < 8; i++, mask <<= 1) {
gf_exp[i] = mask;
gf_log[gf_exp[i]] = i;
/*
* If Pp[i] == 1 then \alpha ** i occurs in poly-repr
* gf_exp[8] = \alpha ** 8
*/
if (Pp[i] == '1')
gf_exp[8] ^= mask;
}
/*
* now gf_exp[8] = \alpha ** 8 is complete, so can also
* compute its inverse.
*/
gf_log[gf_exp[8]] = 8;
/*
* Poly-repr of \alpha ** (i+1) is given by poly-repr of
* \alpha ** i shifted left one-bit and accounting for any
* \alpha ** 8 term that may occur when poly-repr of
* \alpha ** i is shifted.
*/
mask = 1 << 7;
for (i = 9; i < 255; i++) {
if (gf_exp[i - 1] >= mask)
gf_exp[i] = gf_exp[8] ^ ((gf_exp[i - 1] ^ mask) << 1);
else
gf_exp[i] = gf_exp[i - 1] << 1;
gf_log[gf_exp[i]] = i;
}
/*
* log(0) is not defined, so use a special value
*/
gf_log[0] = 255;
/* set the extended gf_exp values for fast multiply */
for (i = 0; i < 255; i++)
gf_exp[i + 255] = gf_exp[i];
/*
* again special cases. 0 has no inverse. This used to
* be initialized to 255, but it should make no difference
* since noone is supposed to read from here.
*/
inverse[0] = 0;
inverse[1] = 1;
for (i = 2; i <= 255; i++)
inverse[i] = gf_exp[255 - gf_log[i]];
}
/*
* Various linear algebra operations that i use often.
*/
/*
* addmul() computes dst[] = dst[] + c * src[]
* This is used often, so better optimize it! Currently the loop is
* unrolled 16 times, a good value for 486 and pentium-class machines.
* The case c=0 is also optimized, whereas c=1 is not. These
* calls are unfrequent in my typical apps so I did not bother.
*/
#define addmul(dst, src, c, sz) \
if (c != 0) _addmul1(dst, src, c, sz)
#define UNROLL 16 /* 1, 4, 8, 16 */
static void
_addmul1(register gf*restrict dst, const register gf*restrict src, gf c, size_t sz) {
USE_GF_MULC;
const gf* lim = &dst[sz - UNROLL + 1];
GF_MULC0 (c);
#if (UNROLL > 1) /* unrolling by 8/16 is quite effective on the pentium */
for (; dst < lim; dst += UNROLL, src += UNROLL) {
GF_ADDMULC (dst[0], src[0]);
GF_ADDMULC (dst[1], src[1]);
GF_ADDMULC (dst[2], src[2]);
GF_ADDMULC (dst[3], src[3]);
#if (UNROLL > 4)
GF_ADDMULC (dst[4], src[4]);
GF_ADDMULC (dst[5], src[5]);
GF_ADDMULC (dst[6], src[6]);
GF_ADDMULC (dst[7], src[7]);
#endif
#if (UNROLL > 8)
GF_ADDMULC (dst[8], src[8]);
GF_ADDMULC (dst[9], src[9]);
GF_ADDMULC (dst[10], src[10]);
GF_ADDMULC (dst[11], src[11]);
GF_ADDMULC (dst[12], src[12]);
GF_ADDMULC (dst[13], src[13]);
GF_ADDMULC (dst[14], src[14]);
GF_ADDMULC (dst[15], src[15]);
#endif
}
#endif
lim += UNROLL - 1;
for (; dst < lim; dst++, src++) /* final components */
GF_ADDMULC (*dst, *src);
}
/*
* computes C = AB where A is n*k, B is k*m, C is n*m
*/
static void
_matmul(gf * a, gf * b, gf * c, unsigned n, unsigned k, unsigned m) {
unsigned row, col, i;
for (row = 0; row < n; row++) {
for (col = 0; col < m; col++) {
gf *pa = &a[row * k];
gf *pb = &b[col];
gf acc = 0;
for (i = 0; i < k; i++, pa++, pb += m)
acc ^= gf_mul (*pa, *pb);
c[row * m + col] = acc;
}
}
}
/*
* _invert_mat() takes a matrix and produces its inverse
* k is the size of the matrix.
* (Gauss-Jordan, adapted from Numerical Recipes in C)
* Return non-zero if singular.
*/
static void
_invert_mat(gf* src, size_t k) {
gf c;
size_t irow = 0;
size_t icol = 0;
unsigned* indxc = (unsigned*) malloc (k * sizeof(unsigned));
unsigned* indxr = (unsigned*) malloc (k * sizeof(unsigned));
unsigned* ipiv = (unsigned*) malloc (k * sizeof(unsigned));
gf *id_row = NEW_GF_MATRIX (1, k);
memset (id_row, '\0', k * sizeof (gf));
/*
* ipiv marks elements already used as pivots.
*/
for (size_t i = 0; i < k; i++)
ipiv[i] = 0;
for (size_t col = 0; col < k; col++) {
gf *pivot_row;
/*
* Zeroing column 'col', look for a non-zero element.
* First try on the diagonal, if it fails, look elsewhere.
*/
if (ipiv[col] != 1 && src[col * k + col] != 0) {
irow = col;
icol = col;
goto found_piv;
}
for (size_t row = 0; row < k; row++) {
if (ipiv[row] != 1) {
for (size_t ix = 0; ix < k; ix++) {
if (ipiv[ix] == 0) {
if (src[row * k + ix] != 0) {
irow = row;
icol = ix;
goto found_piv;
}
} else
assert (ipiv[ix] <= 1);
}
}
}
found_piv:
++(ipiv[icol]);
/*
* swap rows irow and icol, so afterwards the diagonal
* element will be correct. Rarely done, not worth
* optimizing.
*/
if (irow != icol)
for (size_t ix = 0; ix < k; ix++)
SWAP (src[irow * k + ix], src[icol * k + ix], gf);
indxr[col] = irow;
indxc[col] = icol;
pivot_row = &src[icol * k];
c = pivot_row[icol];
assert (c != 0);
if (c != 1) { /* otherwhise this is a NOP */
/*
* this is done often , but optimizing is not so
* fruitful, at least in the obvious ways (unrolling)
*/
c = inverse[c];
pivot_row[icol] = 1;
for (size_t ix = 0; ix < k; ix++)
pivot_row[ix] = gf_mul (c, pivot_row[ix]);
}
/*
* from all rows, remove multiples of the selected row
* to zero the relevant entry (in fact, the entry is not zero
* because we know it must be zero).
* (Here, if we know that the pivot_row is the identity,
* we can optimize the addmul).
*/
id_row[icol] = 1;
if (memcmp (pivot_row, id_row, k * sizeof (gf)) != 0) {
gf *p = src;
for (size_t ix = 0; ix < k; ix++, p += k) {
if (ix != icol) {
c = p[icol];
p[icol] = 0;
addmul (p, pivot_row, c, k);
}
}
}
id_row[icol] = 0;
} /* done all columns */
for (size_t col = k; col > 0; col--)
if (indxr[col-1] != indxc[col-1])
for (size_t row = 0; row < k; row++)
SWAP (src[row * k + indxr[col-1]], src[row * k + indxc[col-1]], gf);
}
/*
* fast code for inverting a vandermonde matrix.
*
* NOTE: It assumes that the matrix is not singular and _IS_ a vandermonde
* matrix. Only uses the second column of the matrix, containing the p_i's.
*
* Algorithm borrowed from "Numerical recipes in C" -- sec.2.8, but largely
* revised for my purposes.
* p = coefficients of the matrix (p_i)
* q = values of the polynomial (known)
*/
void
_invert_vdm (gf* src, unsigned k) {
unsigned i, j, row, col;
gf *b, *c, *p;
gf t, xx;
if (k == 1) /* degenerate case, matrix must be p^0 = 1 */
return;
/*
* c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1
* b holds the coefficient for the matrix inversion
*/
c = NEW_GF_MATRIX (1, k);
b = NEW_GF_MATRIX (1, k);
p = NEW_GF_MATRIX (1, k);
for (j = 1, i = 0; i < k; i++, j += k) {
c[i] = 0;
p[i] = src[j]; /* p[i] */
}
/*
* construct coeffs. recursively. We know c[k] = 1 (implicit)
* and start P_0 = x - p_0, then at each stage multiply by
* x - p_i generating P_i = x P_{i-1} - p_i P_{i-1}
* After k steps we are done.
*/
c[k - 1] = p[0]; /* really -p(0), but x = -x in GF(2^m) */
for (i = 1; i < k; i++) {
gf p_i = p[i]; /* see above comment */
for (j = k - 1 - (i - 1); j < k - 1; j++)
c[j] ^= gf_mul (p_i, c[j + 1]);
c[k - 1] ^= p_i;
}
for (row = 0; row < k; row++) {
/*
* synthetic division etc.
*/
xx = p[row];
t = 1;
b[k - 1] = 1; /* this is in fact c[k] */
for (i = k - 1; i > 0; i--) {
b[i-1] = c[i] ^ gf_mul (xx, b[i]);
t = gf_mul (xx, t) ^ b[i-1];
}
for (col = 0; col < k; col++)
src[col * k + row] = gf_mul (inverse[t], b[col]);
}
free (c);
free (b);
free (p);
return;
}
static int fec_initialized = 0;
static void
init_fec (void) {
generate_gf();
_init_mul_table();
fec_initialized = 1;
}
/*
* This section contains the proper FEC encoding/decoding routines.
* The encoding matrix is computed starting with a Vandermonde matrix,
* and then transforming it into a systematic matrix.
*/
#define FEC_MAGIC 0xFECC0DEC
void
fec_free (fec_t *p) {
assert (p != NULL && p->magic == (((FEC_MAGIC ^ p->k) ^ p->n) ^ (unsigned long) (p->enc_matrix)));
free (p->enc_matrix);
free (p);
}
fec_t *
fec_new(unsigned short k, unsigned short n) {
unsigned row, col;
gf *p, *tmp_m;
fec_t *retval;
assert(k >= 1);
assert(n >= 1);
assert(n <= 256);
assert(k <= n);
if (fec_initialized == 0)
init_fec ();
retval = (fec_t *) malloc (sizeof (fec_t));
retval->k = k;
retval->n = n;
retval->enc_matrix = NEW_GF_MATRIX (n, k);
retval->magic = ((FEC_MAGIC ^ k) ^ n) ^ (unsigned long) (retval->enc_matrix);
tmp_m = NEW_GF_MATRIX (n, k);
/*
* fill the matrix with powers of field elements, starting from 0.
* The first row is special, cannot be computed with exp. table.
*/
tmp_m[0] = 1;
for (col = 1; col < k; col++)
tmp_m[col] = 0;
for (p = tmp_m + k, row = 0; row < n - 1; row++, p += k)
for (col = 0; col < k; col++)
p[col] = gf_exp[modnn (row * col)];
/*
* quick code to build systematic matrix: invert the top
* k*k vandermonde matrix, multiply right the bottom n-k rows
* by the inverse, and construct the identity matrix at the top.
*/
_invert_vdm (tmp_m, k); /* much faster than _invert_mat */
_matmul(tmp_m + k * k, tmp_m, retval->enc_matrix + k * k, n - k, k, k);
/*
* the upper matrix is I so do not bother with a slow multiply
*/
memset (retval->enc_matrix, '\0', k * k * sizeof (gf));
for (p = retval->enc_matrix, col = 0; col < k; col++, p += k + 1)
*p = 1;
free (tmp_m);
return retval;
}
/* To make sure that we stay within cache in the inner loops of fec_encode(). (It would
probably help to also do this for fec_decode(). */
#ifndef STRIDE
#define STRIDE 8192
#endif
void
fec_encode(const fec_t* code, const gf** src, gf** fecs, size_t sz) {
unsigned char i, j;
size_t k;
unsigned fecnum;
const gf* p;
for (k = 0; k < sz; k += STRIDE) {
size_t stride = ((sz-k) < STRIDE)?(sz-k):STRIDE;
for (i=0; i < (code->n - code->k); i++) {
fecnum = i + code->k;
memset(fecs[i] + k, 0, stride);
p = &(code->enc_matrix[fecnum * code->k]);
for (j = 0; j < code->k; j++)
addmul(fecs[i]+k, src[j]+k, p[j], stride);
}
}
}
/**
* Build decode matrix into some memory space.
*
* @param matrix a space allocated for a k by k matrix
*/
void
build_decode_matrix_into_space(const fec_t*restrict const code, const unsigned*const restrict index, const unsigned k, gf*restrict const matrix) {
unsigned char i;
gf* p;
for (i=0, p=matrix; i < k; i++, p += k) {
if (index[i] < k) {
memset(p, 0, k);
p[i] = 1;
} else {
memcpy(p, &(code->enc_matrix[index[i] * code->k]), k);
}
}
_invert_mat (matrix, k);
}
void
fec_decode(const fec_t* code, const gf** inpkts, gf** outpkts, const unsigned* index, size_t sz) {
gf* m_dec = (gf*)alloca(code->k * code->k);
unsigned char outix=0;
unsigned char row=0;
unsigned char col=0;
build_decode_matrix_into_space(code, index, code->k, m_dec);
for (row=0; row<code->k; row++) {
assert ((index[row] >= code->k) || (index[row] == row)); /* If the block whose number is i is present, then it is required to be in the i'th element. */
if (index[row] >= code->k) {
memset(outpkts[outix], 0, sz);
for (col=0; col < code->k; col++)
addmul(outpkts[outix], inpkts[col], m_dec[row * code->k + col], sz);
outix++;
}
}
}
/**
* zfec -- fast forward error correction library with Python interface
*
* Copyright (C) 2007-2010 Zooko Wilcox-O'Hearn
* Author: Zooko Wilcox-O'Hearn
*
* This file is part of zfec.
*
* See README.rst for licensing information.
*/
/*
* This work is derived from the "fec" software by Luigi Rizzo, et al., the
* copyright notice and licence terms of which are included below for reference.
* fec.c -- forward error correction based on Vandermonde matrices 980624 (C)
* 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
*
* Portions derived from code by Phil Karn (karn@ka9q.ampr.org),
* Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari
* Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995
*
* Modifications by Dan Rubenstein (see Modifications.txt for
* their description.
* Modifications (C) 1998 Dan Rubenstein (drubenst@cs.umass.edu)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/

111
fec.h Normal file
View File

@ -0,0 +1,111 @@
/**
* zfec -- fast forward error correction library with Python interface
*
* See README.rst for documentation.
*/
#include <stddef.h>
typedef unsigned char gf;
typedef struct {
unsigned long magic;
unsigned short k, n; /* parameters of the code */
gf* enc_matrix;
} fec_t;
#if defined(_MSC_VER)
// actually, some of the flavors (i.e. Enterprise) do support restrict
//#define restrict __restrict
#define restrict
#endif
/**
* param k the number of blocks required to reconstruct
* param m the total number of blocks created
*/
fec_t* fec_new(unsigned short k, unsigned short m);
void fec_free(fec_t* p);
/**
* @param inpkts the "primary blocks" i.e. the chunks of the input data
* @param fecs buffers into which the secondary blocks will be written
* @param block_nums the numbers of the desired check blocks (the id >= k) which fec_encode() will produce and store into the buffers of the fecs parameter
* @param num_block_nums the length of the block_nums array
* @param sz size of a packet in bytes
*/
void fec_encode(const fec_t* code, const gf** src, gf** fecs, size_t sz);
/**
* @param inpkts an array of packets (size k); If a primary block, i, is present then it must be at index i. Secondary blocks can appear anywhere.
* @param outpkts an array of buffers into which the reconstructed output packets will be written (only packets which are not present in the inpkts input will be reconstructed and written to outpkts)
* @param index an array of the blocknums of the packets in inpkts
* @param sz size of a packet in bytes
*/
void fec_decode(const fec_t* code, const gf** inpkts, gf** outpkts, const unsigned* index, size_t sz);
#if defined(_MSC_VER)
#define alloca _alloca
#else
#ifdef __GNUC__
#ifndef alloca
#define alloca(x) __builtin_alloca(x)
#endif
#else
#include <alloca.h>
#endif
#endif
/**
* zfec -- fast forward error correction library with Python interface
*
* Copyright (C) 2007-2008 Allmydata, Inc.
* Author: Zooko Wilcox-O'Hearn
*
* This file is part of zfec.
*
* See README.rst for licensing information.
*/
/*
* Much of this work is derived from the "fec" software by Luigi Rizzo, et
* al., the copyright notice and licence terms of which are included below
* for reference.
*
* fec.h -- forward error correction based on Vandermonde matrices
* 980614
* (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
*
* Portions derived from code by Phil Karn (karn@ka9q.ampr.org),
* Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari
* Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995
*
* Modifications by Dan Rubenstein (see Modifications.txt for
* their description.
* Modifications (C) 1998 Dan Rubenstein (drubenst@cs.umass.edu)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/

434
ieee80211_radiotap.h Normal file
View File

@ -0,0 +1,434 @@
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <errno.h>
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef u16 __le16;
typedef u32 __le32;
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define le16_to_cpu(x) (x)
#define le32_to_cpu(x) (x)
#else
#define le16_to_cpu(x) ((((x)&0xff)<<8)|(((x)&0xff00)>>8))
#define le32_to_cpu(x) \
((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)&0xff0000)>>8)|(((x)&0xff000000)>>24))
#endif
#define unlikely(x) (x)
/* Are two types/vars the same type (ignoring qualifiers)? */
#ifndef __same_type
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#endif
#ifndef BUILD_BUG_ON
/* Force a compilation error if condition is true */
#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))
/* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used
e.g. in a structure initializer (or where-ever else comma expressions
aren't permitted). */
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
#endif
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
static inline u16 __get_unaligned_memmove16(const void *p)
{
u16 tmp;
memmove(&tmp, p, 2);
return tmp;
}
static inline u32 __get_unaligned_memmove32(const void *p)
{
u32 tmp;
memmove(&tmp, p, 4);
return tmp;
}
static inline u16 get_unaligned_le16(const void *p)
{
return __get_unaligned_memmove16((const u8 *)p);
}
static inline u32 get_unaligned_le32(const void *p)
{
return __get_unaligned_memmove32((const u8 *)p);
}
/* Base version of the radiotap packet header data */
#define PKTHDR_RADIOTAP_VERSION 0
/* A generic radio capture format is desirable. There is one for
* Linux, but it is neither rigidly defined (there were not even
* units given for some fields) nor easily extensible.
*
* I suggest the following extensible radio capture format. It is
* based on a bitmap indicating which fields are present.
*
* I am trying to describe precisely what the application programmer
* should expect in the following, and for that reason I tell the
* units and origin of each measurement (where it applies), or else I
* use sufficiently weaselly language ("is a monotonically nondecreasing
* function of...") that I cannot set false expectations for lawyerly
* readers.
*/
/*
* The radio capture header precedes the 802.11 header.
* All data in the header is little endian on all platforms.
*/
struct ieee80211_radiotap_header {
u8 it_version; /* Version 0. Only increases
* for drastic changes,
* introduction of compatible
* new fields does not count.
*/
u8 it_pad;
__le16 it_len; /* length of the whole
* header in bytes, including
* it_version, it_pad,
* it_len, and data fields.
*/
__le32 it_present; /* A bitmap telling which
* fields are present. Set bit 31
* (0x80000000) to extend the
* bitmap by another 32 bits.
* Additional extensions are made
* by setting bit 31.
*/
} __packed;
/* Name Data type Units
* ---- --------- -----
*
* IEEE80211_RADIOTAP_TSFT __le64 microseconds
*
* Value in microseconds of the MAC's 64-bit 802.11 Time
* Synchronization Function timer when the first bit of the
* MPDU arrived at the MAC. For received frames, only.
*
* IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap
*
* Tx/Rx frequency in MHz, followed by flags (see below).
*
* IEEE80211_RADIOTAP_FHSS __le16 see below
*
* For frequency-hopping radios, the hop set (first byte)
* and pattern (second byte).
*
* IEEE80211_RADIOTAP_RATE u8 500kb/s
*
* Tx/Rx data rate
*
* IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
* one milliwatt (dBm)
*
* RF signal power at the antenna, decibel difference from
* one milliwatt.
*
* IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
* one milliwatt (dBm)
*
* RF noise power at the antenna, decibel difference from one
* milliwatt.
*
* IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB)
*
* RF signal power at the antenna, decibel difference from an
* arbitrary, fixed reference.
*
* IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB)
*
* RF noise power at the antenna, decibel difference from an
* arbitrary, fixed reference point.
*
* IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
*
* Quality of Barker code lock. Unitless. Monotonically
* nondecreasing with "better" lock strength. Called "Signal
* Quality" in datasheets. (Is there a standard way to measure
* this?)
*
* IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless
*
* Transmit power expressed as unitless distance from max
* power set at factory calibration. 0 is max power.
* Monotonically nondecreasing with lower power levels.
*
* IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB)
*
* Transmit power expressed as decibel distance from max power
* set at factory calibration. 0 is max power. Monotonically
* nondecreasing with lower power levels.
*
* IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
* one milliwatt (dBm)
*
* Transmit power expressed as dBm (decibels from a 1 milliwatt
* reference). This is the absolute power level measured at
* the antenna port.
*
* IEEE80211_RADIOTAP_FLAGS u8 bitmap
*
* Properties of transmitted and received frames. See flags
* defined below.
*
* IEEE80211_RADIOTAP_ANTENNA u8 antenna index
*
* Unitless indication of the Rx/Tx antenna for this packet.
* The first antenna is antenna 0.
*
* IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
*
* Properties of received frames. See flags defined below.
*
* IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap
*
* Properties of transmitted frames. See flags defined below.
*
* IEEE80211_RADIOTAP_RTS_RETRIES u8 data
*
* Number of rts retries a transmitted frame used.
*
* IEEE80211_RADIOTAP_DATA_RETRIES u8 data
*
* Number of unicast retries a transmitted frame used.
*
* IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless
*
* Contains a bitmap of known fields/flags, the flags, and
* the MCS index.
*
* IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
*
* Contains the AMPDU information for the subframe.
*
* IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
*
* Contains VHT information about this frame.
*/
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TSFT = 0,
IEEE80211_RADIOTAP_FLAGS = 1,
IEEE80211_RADIOTAP_RATE = 2,
IEEE80211_RADIOTAP_CHANNEL = 3,
IEEE80211_RADIOTAP_FHSS = 4,
IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
IEEE80211_RADIOTAP_ANTENNA = 11,
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
IEEE80211_RADIOTAP_RX_FLAGS = 14,
IEEE80211_RADIOTAP_TX_FLAGS = 15,
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
IEEE80211_RADIOTAP_MCS = 19,
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
IEEE80211_RADIOTAP_VHT = 21,
/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
IEEE80211_RADIOTAP_EXT = 31
};
/* Channel flags. */
#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
#define IEEE80211_CHAN_GSM 0x1000 /* GSM (900 MHz) */
#define IEEE80211_CHAN_STURBO 0x2000 /* Static Turbo */
#define IEEE80211_CHAN_HALF 0x4000 /* Half channel (10 MHz wide) */
#define IEEE80211_CHAN_QUARTER 0x8000 /* Quarter channel (5 MHz wide) */
/* For IEEE80211_RADIOTAP_FLAGS */
#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
* during CFP
*/
#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
* with short
* preamble
*/
#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
* with WEP encryption
*/
#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
* with fragmentation
*/
#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
* 802.11 header and payload
* (to 32-bit boundary)
*/
#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */
/* For IEEE80211_RADIOTAP_RX_FLAGS */
#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* frame has bad PLCP */
/* For IEEE80211_RADIOTAP_TX_FLAGS */
#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
* retries */
#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ack */
/* For IEEE80211_RADIOTAP_MCS */
#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20
#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
#define IEEE80211_RADIOTAP_MCS_BW_20 0
#define IEEE80211_RADIOTAP_MCS_BW_40 1
#define IEEE80211_RADIOTAP_MCS_BW_20L 2
#define IEEE80211_RADIOTAP_MCS_BW_20U 3
#define IEEE80211_RADIOTAP_MCS_SGI 0x04
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
#define IEEE80211_RADIOTAP_MCS_STBC_1 1
#define IEEE80211_RADIOTAP_MCS_STBC_2 2
#define IEEE80211_RADIOTAP_MCS_STBC_3 3
#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
/* For IEEE80211_RADIOTAP_AMPDU_STATUS */
#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
/* For IEEE80211_RADIOTAP_VHT */
#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001
#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002
#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004
#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008
#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010
#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020
#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040
#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080
#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100
#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01
#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02
#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04
#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08
#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10
#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20
#define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01
#define IEEE80211_RADIOTAP_CODING_LDPC_USER1 0x02
#define IEEE80211_RADIOTAP_CODING_LDPC_USER2 0x04
#define IEEE80211_RADIOTAP_CODING_LDPC_USER3 0x08
struct radiotap_align_size {
uint8_t align:4, size:4;
};
struct ieee80211_radiotap_namespace {
const struct radiotap_align_size *align_size;
int n_bits;
uint32_t oui;
uint8_t subns;
};
struct ieee80211_radiotap_vendor_namespaces {
const struct ieee80211_radiotap_namespace *ns;
int n_ns;
};
/* helpers */
static inline int ieee80211_get_radiotap_len(unsigned char *data)
{
struct ieee80211_radiotap_header *hdr =
(struct ieee80211_radiotap_header *)data;
return get_unaligned_le16(&hdr->it_len);
}
/**
* struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
* @this_arg_index: index of current arg, valid after each successful call
* to ieee80211_radiotap_iterator_next()
* @this_arg: pointer to current radiotap arg; it is valid after each
* call to ieee80211_radiotap_iterator_next() but also after
* ieee80211_radiotap_iterator_init() where it will point to
* the beginning of the actual data portion
* @this_arg_size: length of the current arg, for convenience
* @current_namespace: pointer to the current namespace definition
* (or internally %NULL if the current namespace is unknown)
* @is_radiotap_ns: indicates whether the current namespace is the default
* radiotap namespace or not
*
* @_rtheader: pointer to the radiotap header we are walking through
* @_max_length: length of radiotap header in cpu byte ordering
* @_arg_index: next argument index
* @_arg: next argument pointer
* @_next_bitmap: internal pointer to next present u32
* @_bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
* @_vns: vendor namespace definitions
* @_next_ns_data: beginning of the next namespace's data
* @_reset_on_ext: internal; reset the arg index to 0 when going to the
* next bitmap word
*
* Describes the radiotap parser state. Fields prefixed with an underscore
* must not be used by users of the parser, only by the parser internally.
*/
struct ieee80211_radiotap_iterator {
struct ieee80211_radiotap_header *_rtheader;
const struct ieee80211_radiotap_vendor_namespaces *_vns;
const struct ieee80211_radiotap_namespace *current_namespace;
unsigned char *_arg, *_next_ns_data;
__le32 *_next_bitmap;
unsigned char *this_arg;
int this_arg_index;
int this_arg_size;
int is_radiotap_ns;
int _max_length;
int _arg_index;
uint32_t _bitmap_shifter;
int _reset_on_ext;
};
int
ieee80211_radiotap_iterator_init(struct ieee80211_radiotap_iterator *iterator,
struct ieee80211_radiotap_header *radiotap_header,
int max_length,
const struct ieee80211_radiotap_vendor_namespaces *vns);
int
ieee80211_radiotap_iterator_next(struct ieee80211_radiotap_iterator *iterator);

View File

@ -0,0 +1,41 @@
Files with a Qualcomm Atheros / Atheros licence fall under the following
licence. Please see NOTICES.TXT for information about other files in this
repository.
----
Copyright (c) 2013 Qualcomm Atheros, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the
disclaimer below) provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
* Neither the name of Qualcomm Atheros nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----

View File

@ -0,0 +1,33 @@
From 24c8ae810bf7e232d55113499c6e04630239362b Mon Sep 17 00:00:00 2001
From: befinitiv <nono@never.com>
Date: Thu, 19 Feb 2015 19:58:15 +0100
Subject: [PATCH] patched firmare to use MCS3 as the base rate
---
target_firmware/wlan/ar5416_phy.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/target_firmware/wlan/ar5416_phy.c b/target_firmware/wlan/ar5416_phy.c
index 4031066..4ad5e03 100755
--- a/target_firmware/wlan/ar5416_phy.c
+++ b/target_firmware/wlan/ar5416_phy.c
@@ -211,6 +211,7 @@ ar5416GetRateTable(struct ath_hal *ah, a_uint32_t mode)
#define TURBO IEEE80211_T_TURBO
#define XR ATHEROS_T_XR
#define HT IEEE80211_T_HT
+ // /*[ 0] 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80| 2), 0 },
HAL_RATE_TABLE ar5416_11ng_table = {
@@ -219,7 +220,7 @@ HAL_RATE_TABLE ar5416_11ng_table = {
{
/* short ctrl */
/* valid rateCode Preamble dot11Rate Rate */
- /*[ 0] 1 Mb */ { AH_TRUE, CCK, 1000, 0x1b, 0x00, (0x80| 2), 0 },
+ /*[15] 26 Mb */ { AH_TRUE, HT, 26000, 0x83, 0x00, 3, 8 },
/*[ 1] 2 Mb */ { AH_TRUE, CCK, 2000, 0x1a, 0x04, (0x80| 4), 1 },
/*[ 2] 5.5 Mb */ { AH_TRUE, CCK, 5500, 0x19, 0x04, (0x80|11), 2 },
/*[ 3] 11 Mb */ { AH_TRUE, CCK, 11000, 0x18, 0x04, (0x80|22), 3 },
--
1.9.1

View File

@ -0,0 +1 @@
htc_9271.fw.mcs3

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,3 @@
apply the patch to this repo: https://github.com/qca/open-ath9k-htc-firmware.git
the provided firmware binary is configured to use MCS3 (26mbit/s) as the injection rate

View File

@ -0,0 +1,27 @@
From 4d02539ecd8b417b7efcc0ebc7617fe11c394085 Mon Sep 17 00:00:00 2001
From: befinitiv <nono@never.com>
Date: Thu, 19 Feb 2015 20:27:36 +0100
Subject: [PATCH] fixed channel power of ath9k driver to 20dbm
---
drivers/net/wireless/ath/ath9k/hw.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2ad6057..45fbec3 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2735,8 +2735,9 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
return;
channel = chan->chan;
+ channel->max_power = 20;
chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
- new_pwr = min_t(int, chan_pwr, reg->power_limit);
+ new_pwr = chan_pwr; //min_t(int, chan_pwr, reg->power_limit);
max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
ant_gain = get_antenna_gain(ah, chan);
--
1.9.1

View File

@ -0,0 +1 @@
apply this patch to: https://github.com/raspberrypi/linux.git

1
patches/Readme Normal file
View File

@ -0,0 +1 @@
you will here find patches necessary to build your own setup of wifibroadcast

View File

@ -0,0 +1,915 @@
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/common-init.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/common-init.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/common-init.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/common-init.c 2016-06-19 18:35:17.000000000 +0200
@@ -16,20 +16,22 @@
/* We use the hw_value as an index into our private channel structure */
+ // CHANGES: Added additional channels, increased .max_power to 30
+
#include "common.h"
#define CHAN2G(_freq, _idx) { \
.band = IEEE80211_BAND_2GHZ, \
.center_freq = (_freq), \
.hw_value = (_idx), \
- .max_power = 20, \
+ .max_power = 30, \
}
#define CHAN5G(_freq, _idx) { \
.band = IEEE80211_BAND_5GHZ, \
.center_freq = (_freq), \
.hw_value = (_idx), \
- .max_power = 20, \
+ .max_power = 30, \
}
/* Some 2 GHz radios are actually tunable on 2312-2732
@@ -37,6 +39,27 @@
* we have calibration data for all cards though to make
* this static */
static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
+ CHAN2G(2312, 34), /* Channel -19 */
+ CHAN2G(2317, 35), /* Channel -18 */
+ CHAN2G(2322, 36), /* Channel -17 */
+ CHAN2G(2327, 37), /* Channel -16 */
+ CHAN2G(2332, 38), /* Channel -15 */
+ CHAN2G(2337, 39), /* Channel -14 */
+ CHAN2G(2342, 40), /* Channel -13 */
+ CHAN2G(2347, 41), /* Channel -12 */
+ CHAN2G(2352, 42), /* Channel -11 */
+ CHAN2G(2357, 43), /* Channel -10 */
+ CHAN2G(2362, 44), /* Channel -9 */
+ CHAN2G(2367, 45), /* Channel -8 */
+ CHAN2G(2372, 46), /* Channel -7 */
+ CHAN2G(2377, 47), /* Channel -6 */
+ CHAN2G(2382, 48), /* Channel -5 */
+ CHAN2G(2387, 49), /* Channel -4 */
+ CHAN2G(2392, 50), /* Channel -3 */
+ CHAN2G(2397, 51), /* Channel -2 */
+ CHAN2G(2402, 52), /* Channel -1 */
+ CHAN2G(2407, 53), /* Channel 0 */
+
CHAN2G(2412, 0), /* Channel 1 */
CHAN2G(2417, 1), /* Channel 2 */
CHAN2G(2422, 2), /* Channel 3 */
@@ -50,7 +73,30 @@
CHAN2G(2462, 10), /* Channel 11 */
CHAN2G(2467, 11), /* Channel 12 */
CHAN2G(2472, 12), /* Channel 13 */
- CHAN2G(2484, 13), /* Channel 14 */
+
+ CHAN2G(2477, 13), /* Channel XX */
+ CHAN2G(2478, 14), /* Channel XX */
+ CHAN2G(2482, 15), /* Channel XX */
+
+ CHAN2G(2484, 16), /* Channel 14 */
+
+ CHAN2G(2487, 17), /* Channel XX */
+ CHAN2G(2489, 18), /* Channel XX */
+ CHAN2G(2492, 19), /* Channel XX */
+ CHAN2G(2494, 20), /* Channel XX */
+ CHAN2G(2497, 21), /* Channel XX */
+ CHAN2G(2499, 22), /* Channel XX */
+ CHAN2G(2512, 23), /* Channel XX */
+ CHAN2G(2532, 24), /* Channel XX */
+ CHAN2G(2572, 25), /* Channel XX */
+ CHAN2G(2592, 26), /* Channel XX */
+ CHAN2G(2612, 27), /* Channel XX */
+ CHAN2G(2632, 28), /* Channel XX */
+ CHAN2G(2652, 29), /* Channel XX */
+ CHAN2G(2672, 30), /* Channel XX */
+ CHAN2G(2692, 31), /* Channel XX */
+ CHAN2G(2712, 32), /* Channel XX */
+ CHAN2G(2732, 33), /* Channel XX */
};
/* Some 5 GHz radios are actually tunable on XXXX-YYYY
@@ -58,34 +104,39 @@
* we have calibration data for all cards though to make
* this static */
static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
+ CHAN5G(4920, 54), /* Channel XX */
+ CHAN5G(4940, 55), /* Channel XX */
+ CHAN5G(4960, 56), /* Channel XX */
+ CHAN5G(4980, 57), /* Channel XX */
+
/* _We_ call this UNII 1 */
- CHAN5G(5180, 14), /* Channel 36 */
- CHAN5G(5200, 15), /* Channel 40 */
- CHAN5G(5220, 16), /* Channel 44 */
- CHAN5G(5240, 17), /* Channel 48 */
+ CHAN5G(5180, 58), /* Channel 36 */
+ CHAN5G(5200, 59), /* Channel 40 */
+ CHAN5G(5220, 60), /* Channel 44 */
+ CHAN5G(5240, 61), /* Channel 48 */
/* _We_ call this UNII 2 */
- CHAN5G(5260, 18), /* Channel 52 */
- CHAN5G(5280, 19), /* Channel 56 */
- CHAN5G(5300, 20), /* Channel 60 */
- CHAN5G(5320, 21), /* Channel 64 */
+ CHAN5G(5260, 62), /* Channel 52 */
+ CHAN5G(5280, 63), /* Channel 56 */
+ CHAN5G(5300, 64), /* Channel 60 */
+ CHAN5G(5320, 65), /* Channel 64 */
/* _We_ call this "Middle band" */
- CHAN5G(5500, 22), /* Channel 100 */
- CHAN5G(5520, 23), /* Channel 104 */
- CHAN5G(5540, 24), /* Channel 108 */
- CHAN5G(5560, 25), /* Channel 112 */
- CHAN5G(5580, 26), /* Channel 116 */
- CHAN5G(5600, 27), /* Channel 120 */
- CHAN5G(5620, 28), /* Channel 124 */
- CHAN5G(5640, 29), /* Channel 128 */
- CHAN5G(5660, 30), /* Channel 132 */
- CHAN5G(5680, 31), /* Channel 136 */
- CHAN5G(5700, 32), /* Channel 140 */
+ CHAN5G(5500, 66), /* Channel 100 */
+ CHAN5G(5520, 67), /* Channel 104 */
+ CHAN5G(5540, 68), /* Channel 108 */
+ CHAN5G(5560, 69), /* Channel 112 */
+ CHAN5G(5580, 70), /* Channel 116 */
+ CHAN5G(5600, 71), /* Channel 120 */
+ CHAN5G(5620, 72), /* Channel 124 */
+ CHAN5G(5640, 73), /* Channel 128 */
+ CHAN5G(5660, 74), /* Channel 132 */
+ CHAN5G(5680, 75), /* Channel 136 */
+ CHAN5G(5700, 76), /* Channel 140 */
/* _We_ call this UNII 3 */
- CHAN5G(5745, 33), /* Channel 149 */
- CHAN5G(5765, 34), /* Channel 153 */
- CHAN5G(5785, 35), /* Channel 157 */
- CHAN5G(5805, 36), /* Channel 161 */
- CHAN5G(5825, 37), /* Channel 165 */
+ CHAN5G(5745, 77), /* Channel 149 */
+ CHAN5G(5765, 78), /* Channel 153 */
+ CHAN5G(5785, 79), /* Channel 157 */
+ CHAN5G(5805, 80), /* Channel 161 */
+ CHAN5G(5825, 81), /* Channel 165 */
};
/* Atheros hardware rate code addition for short premble */
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/eeprom_4k.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/eeprom_4k.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/eeprom_4k.c 2016-11-27 22:29:27.402201916 +0100
@@ -682,8 +682,12 @@
if (test)
return;
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+// CHANGES: set 58 for every data rate
+
+ for (i = 0; i < Ar5416RateSize; i++) {
+// ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+ ratesArray[i] = 58;
+ }
ENABLE_REGWRITE_BUFFER(ah);
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/eeprom_9287.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/eeprom_9287.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/eeprom_9287.c 2016-07-04 21:59:24.000000000 +0200
@@ -799,7 +799,8 @@
return;
for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
+// ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
+ ratesArray[i] = 58;
ENABLE_REGWRITE_BUFFER(ah);
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/hif_usb.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/hif_usb.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/hif_usb.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/hif_usb.c 2016-11-27 22:31:59.746196470 +0100
@@ -1085,10 +1085,29 @@
char index[8], *chip;
int ret;
+
+// CHANGES
+
+/* int randwait;
+ int mstimerandwait;
+
+
+
+ get_random_bytes(&randwait, sizeof(int));
+ randwait = randwait % 10;
+
+ mstimerandwait = randwait * 100;
+
+ msleep(mstimerandwait);
+*/
+ msleep(1000);
+
+
+ // CHANGES: re-use debug firmware parameter for loading firmwares with different bitrates
if (first) {
- if (htc_use_dev_fw) {
+ if (htc_fw_bitrate) {
hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX + 1;
- sprintf(index, "%s", "dev");
+ sprintf(index, "%d", htc_fw_bitrate);
} else {
hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX;
sprintf(index, "%d", hif_dev->fw_minor_index);
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/hif_usb.h linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/hif_usb.h
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/hif_usb.h 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/hif_usb.h 2016-11-27 22:33:05.898194106 +0100
@@ -36,7 +36,8 @@
__stringify(MAJOR_VERSION_REQ) \
"." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw"
-extern int htc_use_dev_fw;
+// CHANGES: variable for firmware parameter
+extern int htc_fw_bitrate;
#define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB))
@@ -61,7 +62,7 @@
#define MAX_PKT_NUM_IN_TRANSFER 10
#define MAX_REG_OUT_URB_NUM 1
-#define MAX_REG_IN_URB_NUM 64
+#define MAX_REG_IN_URB_NUM 8
#define MAX_REG_IN_BUF_SIZE 64
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/htc_drv_init.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/htc_drv_init.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/htc_drv_init.c 2016-11-27 22:42:51.566173171 +0100
@@ -38,9 +38,11 @@
module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
-int htc_use_dev_fw = 0;
-module_param_named(use_dev_fw, htc_use_dev_fw, int, 0444);
-MODULE_PARM_DESC(use_dev_fw, "Use development FW version");
+// CHANGES: re-use dev firmware parameter for different bitrate firmwares
+int htc_fw_bitrate = 0;
+module_param_named(fw_bitrate, htc_fw_bitrate, int, 0444);
+MODULE_PARM_DESC(fw_bitrate, "Set Firmware with bitrate to be loaded");
+
#ifdef CONFIG_MAC80211_LEDS
int ath9k_htc_led_blink = 1;
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/htc_drv_main.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/htc_drv_main.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/htc_drv_main.c 2016-11-27 22:37:15.018185201 +0100
@@ -215,6 +215,12 @@
channel->center_freq, ret);
}
+ // CHANGES: disable physical carrier sense
+// REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+// REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_RX_CLEAR);
+
+// printk("!!! carrier sense disabled !!!\n");
+
ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
&priv->curtxpow);
@@ -286,6 +292,12 @@
goto err;
}
+ // CHANGES: disable physical carrier sense
+// REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+// REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_RX_CLEAR);
+
+// printk("!!! carrier sense disabled !!!\n");
+
ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
&priv->curtxpow);
@@ -941,6 +953,13 @@
return ret;
}
+ // CHANGES: disable physical carrier sense
+// REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+// REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_RX_CLEAR);
+
+// printk("!!! carrier sense disabled !!!\n");
+
+
ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
&priv->curtxpow);
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/hw.h linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/hw.h
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/hw.h 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/hw.h 2016-06-09 11:43:39.000000000 +0200
@@ -13,6 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+ // CHANGES: increase NUM_CHANNELS to 82 for additional channels
#ifndef HW_H
#define HW_H
@@ -73,7 +74,7 @@
#define ATH9K_RSSI_BAD -128
-#define ATH9K_NUM_CHANNELS 38
+#define ATH9K_NUM_CHANNELS 82
/* Register read/write primitives */
#define REG_WRITE(_ah, _reg, _val) \
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/mac.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/mac.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/mac.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/mac.c 2016-06-30 17:01:25.000000000 +0200
@@ -160,7 +160,9 @@
}
REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
- REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+
+// CHANGES: do not clear disable physical carrier sense bit
+// REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
REG_WRITE(ah, AR_Q_TXD, 0);
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/mac.h linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/mac.h
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/ath9k/mac.h 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/ath9k/mac.h 2016-06-04 06:28:30.000000000 +0200
@@ -41,6 +41,9 @@
#define CCK_PREAMBLE_BITS 144
#define CCK_PLCP_BITS 48
+
+// CHANGES
+
#define OFDM_SIFS_TIME 16
#define OFDM_PREAMBLE_TIME 20
#define OFDM_PLCP_BITS 22
@@ -56,18 +59,18 @@
#define OFDM_PLCP_BITS_QUARTER 22
#define OFDM_SYMBOL_TIME_QUARTER 16
-#define INIT_AIFS 2
-#define INIT_CWMIN 15
-#define INIT_CWMIN_11B 31
-#define INIT_CWMAX 1023
-#define INIT_SH_RETRY 10
-#define INIT_LG_RETRY 10
-#define INIT_SSH_RETRY 32
-#define INIT_SLG_RETRY 32
-
-#define ATH9K_SLOT_TIME_6 6
-#define ATH9K_SLOT_TIME_9 9
-#define ATH9K_SLOT_TIME_20 20
+#define INIT_AIFS 0
+#define INIT_CWMIN 0
+#define INIT_CWMIN_11B 0
+#define INIT_CWMAX 0
+#define INIT_SH_RETRY 1
+#define INIT_LG_RETRY 1
+#define INIT_SSH_RETRY 3
+#define INIT_SLG_RETRY 3
+
+#define ATH9K_SLOT_TIME_6 1
+#define ATH9K_SLOT_TIME_9 1
+#define ATH9K_SLOT_TIME_20 1
#define ATH9K_TXERR_XRETRY 0x01
#define ATH9K_TXERR_FILT 0x02
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/regd.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/regd.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/ath/regd.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/ath/regd.c 2016-06-19 18:47:18.000000000 +0200
@@ -14,6 +14,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+// CHANGES: - changed frequency range to 2312-2732
+// - allowed channel 12, 13 and 14 for all
+// - removed 802.11b only restriction for channel 14
+// - increased txpower to 30 in ATH9K_2GHZ_ ... REGRULES
+// - always return 0 for radar detection
+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
@@ -32,34 +38,25 @@
* the flags on our reg_notifier() on a case by case basis.
*/
+
/* Only these channels all allow active scan on all world regulatory domains */
-#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
+#define ATH9K_2GHZ_CH01_11 REG_RULE(2312-10, 2462+10, 40, 0, 30, 0)
/* We enable active scan on these a case by case basis by regulatory domain */
-#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\
- NL80211_RRF_NO_IR)
-#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\
- NL80211_RRF_NO_IR | \
- NL80211_RRF_NO_OFDM)
+#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 30, 0)
+#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2732+10, 40, 0, 30, 0)
/* We allow IBSS on these on a case by case basis by regulatory domain */
-#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\
- NL80211_RRF_NO_IR)
-#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\
- NL80211_RRF_NO_IR)
-#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\
- NL80211_RRF_NO_IR)
-
-#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \
- ATH9K_2GHZ_CH12_13, \
- ATH9K_2GHZ_CH14
+#define ATH9K_5GHZ_5150_5350 REG_RULE(4920-10, 5350+10, 80, 0, 30, 0)
+#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30, 0)
+#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30, 0)
+
+#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, ATH9K_2GHZ_CH12_13, ATH9K_2GHZ_CH14
-#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \
- ATH9K_5GHZ_5470_5850
+#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, ATH9K_5GHZ_5470_5850
/* This one skips what we call "mid band" */
-#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
- ATH9K_5GHZ_5725_5850
+#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, ATH9K_5GHZ_5725_5850
/* Can be used for:
* 0x60, 0x61, 0x62 */
@@ -77,9 +74,8 @@
.n_reg_rules = 4,
.alpha2 = "99",
.reg_rules = {
- ATH9K_2GHZ_CH01_11,
- ATH9K_2GHZ_CH12_13,
- ATH9K_5GHZ_NO_MIDBAND,
+ ATH9K_2GHZ_ALL,
+ ATH9K_5GHZ_ALL,
}
};
@@ -88,8 +84,8 @@
.n_reg_rules = 3,
.alpha2 = "99",
.reg_rules = {
- ATH9K_2GHZ_CH01_11,
- ATH9K_5GHZ_NO_MIDBAND,
+ ATH9K_2GHZ_ALL,
+ ATH9K_5GHZ_ALL,
}
};
@@ -98,7 +94,7 @@
.n_reg_rules = 3,
.alpha2 = "99",
.reg_rules = {
- ATH9K_2GHZ_CH01_11,
+ ATH9K_2GHZ_ALL,
ATH9K_5GHZ_ALL,
}
};
@@ -108,8 +104,7 @@
.n_reg_rules = 4,
.alpha2 = "99",
.reg_rules = {
- ATH9K_2GHZ_CH01_11,
- ATH9K_2GHZ_CH12_13,
+ ATH9K_2GHZ_ALL,
ATH9K_5GHZ_ALL,
}
};
@@ -256,7 +251,8 @@
/* Frequency is one where radar detection is required */
static bool ath_is_radar_freq(u16 center_freq)
{
- return (center_freq >= 5260 && center_freq <= 5700);
+// return (center_freq >= 5260 && center_freq <= 5700);
+ return 0;
}
static void ath_force_clear_no_ir_chan(struct wiphy *wiphy,
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/brcm80211/brcmfmac/core.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/brcm80211/brcmfmac/core.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/brcm80211/brcmfmac/core.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/brcm80211/brcmfmac/core.c 2016-11-27 22:48:43.586160588 +0100
@@ -1034,8 +1034,9 @@
brcmf_dbg(TRACE, "\n");
+ // CHANGES: change default interface name from wlanX to intwifiX
/* add primary networking interface */
- ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
+ ifp = brcmf_add_if(drvr, 0, 0, false, "intwifi%d", NULL);
if (IS_ERR(ifp))
return PTR_ERR(ifp);
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/rt2x00/rt2800lib.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/rt2x00/rt2800lib.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/rt2x00/rt2800lib.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/rt2x00/rt2800lib.c 2016-06-19 18:40:56.000000000 +0200
@@ -1485,12 +1485,13 @@
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
+
rt2800_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
!(filter_flags & FIF_PLCPFAIL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME, 1);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME, 0);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_VER_ERROR, 1);
rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_MULTICAST,
@@ -1538,14 +1539,14 @@
*/
rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
- rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 0);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
} else {
rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
- rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 0);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 16);
rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
@@ -4117,7 +4118,7 @@
*/
delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level,
chan->max_power);
-
+
/*
* BBP_R1 controls TX power for all rates, it allow to set the following
* gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively.
@@ -4135,12 +4136,13 @@
} else {
power_ctrl = 0;
}
+
rt2800_bbp_read(rt2x00dev, 1, &r1);
rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
rt2800_bbp_write(rt2x00dev, 1, r1);
offset = TX_PWR_CFG_0;
-
+
for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) {
/* just to be safe */
if (offset > TX_PWR_CFG_4)
@@ -4153,6 +4155,7 @@
i, &eeprom);
is_rate_b = i ? 0 : 1;
+
/*
* TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,
* TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12,
@@ -4162,8 +4165,10 @@
EEPROM_TXPOWER_BYRATE_RATE0);
txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
power_level, txpower, delta);
+ txpower += rt2800_txpower(rt2x00dev);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE0, txpower);
+
/*
* TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,
* TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13,
@@ -4173,6 +4178,7 @@
EEPROM_TXPOWER_BYRATE_RATE1);
txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
power_level, txpower, delta);
+ txpower += rt2800_txpower(rt2x00dev);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE1, txpower);
/*
@@ -4184,6 +4190,7 @@
EEPROM_TXPOWER_BYRATE_RATE2);
txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
power_level, txpower, delta);
+ txpower += rt2800_txpower(rt2x00dev);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE2, txpower);
/*
@@ -4195,6 +4202,7 @@
EEPROM_TXPOWER_BYRATE_RATE3);
txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
power_level, txpower, delta);
+ txpower += rt2800_txpower(rt2x00dev);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
/* read the next four txpower values */
@@ -4211,6 +4219,7 @@
EEPROM_TXPOWER_BYRATE_RATE0);
txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
power_level, txpower, delta);
+ txpower += rt2800_txpower(rt2x00dev);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE4, txpower);
/*
@@ -4222,6 +4231,7 @@
EEPROM_TXPOWER_BYRATE_RATE1);
txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
power_level, txpower, delta);
+ txpower += rt2800_txpower(rt2x00dev);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE5, txpower);
/*
@@ -4233,6 +4243,7 @@
EEPROM_TXPOWER_BYRATE_RATE2);
txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
power_level, txpower, delta);
+ txpower += rt2800_txpower(rt2x00dev);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE6, txpower);
/*
@@ -4244,8 +4255,11 @@
EEPROM_TXPOWER_BYRATE_RATE3);
txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
power_level, txpower, delta);
+ txpower += rt2800_txpower(rt2x00dev);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE7, txpower);
+
+
rt2800_register_write(rt2x00dev, offset, reg);
/* next TX_PWR_CFG register */
@@ -4871,11 +4885,12 @@
* connection problems with 11g + CTS protection. Hence, use the same
* defaults as the Ralink driver: 16 for both, CCK and OFDM SIFS.
*/
+ // CHANGES: TODO check if those are applied or not
rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 16);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 16);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, 314);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 0);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 0);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 0);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, 0);
rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
@@ -7894,7 +7909,7 @@
field.bit_mask = 0xf << field.bit_offset;
rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
- rt2x00_set_field32(&reg, field, queue->aifs);
+ rt2x00_set_field32(&reg, field, 0);
rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
@@ -7910,7 +7925,7 @@
rt2800_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
+ rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, 0);
rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMAX, queue->cw_max);
rt2800_register_write(rt2x00dev, offset, reg);
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/rt2x00/rt2800lib.h linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/rt2x00/rt2800lib.h
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/rt2x00/rt2800lib.h 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/rt2x00/rt2800lib.h 2016-06-19 18:42:28.000000000 +0200
@@ -17,6 +17,8 @@
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+// CHANGES: Addes txpower module parameter related stuff
+
#ifndef RT2800LIB_H
#define RT2800LIB_H
@@ -43,6 +45,7 @@
int (*read_eeprom)(struct rt2x00_dev *rt2x00dev);
bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev);
+ int (*txpower)(struct rt2x00_dev *rt2x00dev);
int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
@@ -129,6 +132,13 @@
return rt2800ops->hwcrypt_disabled(rt2x00dev);
}
+static inline int rt2800_txpower(struct rt2x00_dev *rt2x00dev)
+{
+ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+ return rt2800ops->txpower(rt2x00dev);
+}
+
static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len)
{
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/rt2x00/rt2800usb.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/rt2x00/rt2800usb.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/rt2x00/rt2800usb.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/rt2x00/rt2800usb.c 2016-06-19 18:43:08.000000000 +0200
@@ -27,6 +27,8 @@
Supported chipsets: RT2800U.
*/
+// CHANGES: Addes txpower module parameter related stuff
+
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/kernel.h>
@@ -51,6 +53,16 @@
return modparam_nohwcrypt;
}
+
+static int modparam_txpower;
+module_param_named(txpower, modparam_txpower, int, S_IRUGO);
+MODULE_PARM_DESC(txpower, "Change TXPower.");
+
+static int rt2800usb_txpower(struct rt2x00_dev *rt2x00dev)
+{
+ return modparam_txpower;
+}
+
/*
* Queue handlers.
*/
@@ -860,6 +872,7 @@
.regbusy_read = rt2x00usb_regbusy_read,
.read_eeprom = rt2800usb_read_eeprom,
.hwcrypt_disabled = rt2800usb_hwcrypt_disabled,
+ .txpower = rt2800usb_txpower,
.drv_write_firmware = rt2800usb_write_firmware,
.drv_init_registers = rt2800usb_init_registers,
.drv_get_txwi = rt2800usb_get_txwi,
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/rt2x00/rt2x00.h linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/rt2x00/rt2x00.h
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/drivers/net/wireless/rt2x00/rt2x00.h 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/drivers/net/wireless/rt2x00/rt2x00.h 2016-06-06 12:37:46.000000000 +0200
@@ -119,23 +119,25 @@
* Standard timing and size defines.
* These values should follow the ieee80211 specifications.
*/
+
+// CHANGES:
+
#define ACK_SIZE 14
#define IEEE80211_HEADER 24
#define PLCP 48
#define BEACON 100
#define PREAMBLE 144
#define SHORT_PREAMBLE 72
-#define SLOT_TIME 20
-#define SHORT_SLOT_TIME 9
+#define SLOT_TIME 1
+#define SHORT_SLOT_TIME 1
#define SIFS 10
#define PIFS ( SIFS + SLOT_TIME )
#define SHORT_PIFS ( SIFS + SHORT_SLOT_TIME )
#define DIFS ( PIFS + SLOT_TIME )
#define SHORT_DIFS ( SHORT_PIFS + SHORT_SLOT_TIME )
-#define EIFS ( SIFS + DIFS + \
- GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
-#define SHORT_EIFS ( SIFS + SHORT_DIFS + \
- GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
+#define EIFS 0
+#define SHORT_EIFS 0
+
enum rt2x00_chip_intf {
RT2X00_CHIP_INTF_PCI,
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/net/wireless/db.txt linux-abe33682e797932abcdc0fd1421f30cddc1f101a/net/wireless/db.txt
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/net/wireless/db.txt 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/net/wireless/db.txt 2016-06-19 18:44:30.000000000 +0200
@@ -1,17 +1,47 @@
-#
-# This file is a placeholder to prevent accidental build breakage if someone
-# enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to
-# enable that build option.
-#
-# You should be using CRDA instead. It is even better if you use the CRDA
-# package provided by your distribution, since they will probably keep it
-# up-to-date on your behalf.
-#
-# If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will
-# need to replace this file with one containing appropriately formatted
-# regulatory rules that cover the regulatory domains you will be using. Your
-# best option is to extract the db.txt file from the wireless-regdb git
-# repository:
-#
-# git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git
-#
+country 00:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country DE:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country AT:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country CH:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country TW:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country AU:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country CA:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country US:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country BO:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country GB:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country CN:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
+
+country NZ:
+ (2302 - 2742 @ 40), (30)
+ (4910 - 5835 @ 160), (30)
diff -ruN linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/net/wireless/reg.c linux-abe33682e797932abcdc0fd1421f30cddc1f101a/net/wireless/reg.c
--- linux-abe33682e797932abcdc0fd1421f30cddc1f101a.ORIG/net/wireless/reg.c 2016-11-15 18:17:42.000000000 +0100
+++ linux-abe33682e797932abcdc0fd1421f30cddc1f101a/net/wireless/reg.c 2016-06-25 15:14:55.000000000 +0200
@@ -229,32 +229,23 @@
.alpha2 = "00",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
- REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
+ REG_RULE(2312-10, 2462+10, 40, 6, 30, 0),
/* IEEE 802.11b/g, channels 12..13. */
- REG_RULE(2467-10, 2472+10, 40, 6, 20,
- NL80211_RRF_NO_IR),
+ REG_RULE(2467-10, 2472+10, 40, 6, 30, 0),
/* IEEE 802.11 channel 14 - Only JP enables
* this and for 802.11b only */
- REG_RULE(2484-10, 2484+10, 20, 6, 20,
- NL80211_RRF_NO_IR |
- NL80211_RRF_NO_OFDM),
+ REG_RULE(2484-10, 2732+10, 40, 6, 30, 0),
/* IEEE 802.11a, channel 36..48 */
- REG_RULE(5180-10, 5240+10, 160, 6, 20,
- NL80211_RRF_NO_IR),
+ REG_RULE(4920-10, 5240+10, 160, 6, 30, 0),
/* IEEE 802.11a, channel 52..64 - DFS required */
- REG_RULE(5260-10, 5320+10, 160, 6, 20,
- NL80211_RRF_NO_IR |
- NL80211_RRF_DFS),
+ REG_RULE(5260-10, 5320+10, 160, 6, 30, 0),
/* IEEE 802.11a, channel 100..144 - DFS required */
- REG_RULE(5500-10, 5720+10, 160, 6, 20,
- NL80211_RRF_NO_IR |
- NL80211_RRF_DFS),
+ REG_RULE(5500-10, 5720+10, 160, 6, 30, 0),
/* IEEE 802.11a, channel 149..165 */
- REG_RULE(5745-10, 5825+10, 80, 6, 20,
- NL80211_RRF_NO_IR),
+ REG_RULE(5745-10, 6100+10, 160, 6, 30, 0),
/* IEEE 802.11ad (60GHz), channels 1..3 */
REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0),
@@ -3173,7 +3164,7 @@
int cfg80211_get_unii(int freq)
{
/* UNII-1 */
- if (freq >= 5150 && freq <= 5250)
+ if (freq >= 4920 && freq <= 5250)
return 0;
/* UNII-2A */
@@ -3189,7 +3180,7 @@
return 3;
/* UNII-3 */
- if (freq > 5725 && freq <= 5825)
+ if (freq > 5725 && freq <= 6100)
return 4;
return -EINVAL;

View File

@ -0,0 +1,154 @@
diff -Naur 1/include/net/mac80211.h 2/include/net/mac80211.h
--- 1/include/net/mac80211.h 2016-02-25 21:01:36.000000000 +0100
+++ 2/include/net/mac80211.h 2016-04-07 09:05:21.474203687 +0200
@@ -867,7 +867,16 @@
/* 2 bytes free */
};
/* only needed before rate control */
- unsigned long jiffies;
+ struct {
+ /* same position as rates[0] */
+ struct ieee80211_tx_rate prerate;
+ u8 use_preset_rate:1;
+ u8 use_legacy_rate:1;
+ /* only used for legacy bitrates */
+ u16 bitrate;
+ /* 2 bytes free */
+ unsigned long jiffies;
+ };
};
/* NB: vif can be NULL for injected frames */
struct ieee80211_vif *vif;
diff -Naur 1/net/mac80211/tx.c 2/net/mac80211/tx.c
--- 1/net/mac80211/tx.c 2016-02-25 21:01:36.000000000 +0100
+++ 2/net/mac80211/tx.c 2016-04-07 09:05:21.478203760 +0200
@@ -786,6 +786,52 @@
}
static ieee80211_tx_result debug_noinline
+ieee80211_tx_h_rate_preset(struct ieee80211_tx_data *tx)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+ struct ieee80211_supported_band *sband;
+ u16 bitrate;
+ u8 use_legacy_rate;
+ s8 idx;
+ int i;
+
+ sband = tx->local->hw.wiphy->bands[info->band];
+
+ bitrate = info->control.bitrate;
+ use_legacy_rate = info->control.use_legacy_rate;
+
+ /*
+ * WARNING: This overwrites some data that may be needed in the
+ * following procedure. So everything that is needed and shares memory
+ * with info->control.rates[] needs to be copied beforehand.
+ */
+ for (i = 1; i < IEEE80211_TX_MAX_RATES; i++)
+ info->control.rates[i].idx = -1;
+
+ if (!use_legacy_rate) {
+ if (info->control.rates[0].idx < 0)
+ return TX_DROP;
+ return TX_CONTINUE;
+ }
+
+ idx = -1;
+ for (i = 0; i < sband->n_bitrates; i++) {
+ if (sband->bitrates[i].bitrate > bitrate)
+ continue;
+ if (idx >= 0 &&
+ sband->bitrates[i].bitrate < sband->bitrates[idx].bitrate)
+ continue;
+ idx = i;
+ }
+ if (unlikely(idx < 0))
+ return TX_DROP;
+
+ info->control.rates[0].idx = idx;
+
+ return TX_CONTINUE;
+}
+
+static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
@@ -1476,8 +1522,12 @@
CALL_TXH(ieee80211_tx_h_ps_buf);
CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
CALL_TXH(ieee80211_tx_h_select_key);
- if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
- CALL_TXH(ieee80211_tx_h_rate_ctrl);
+ if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) {
+ if (unlikely(info->control.use_preset_rate))
+ CALL_TXH(ieee80211_tx_h_rate_preset);
+ else
+ CALL_TXH(ieee80211_tx_h_rate_ctrl);
+ }
if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
__skb_queue_tail(&tx->skbs, tx->skb);
@@ -1674,9 +1724,14 @@
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
NULL);
u16 txflags;
+ u8 known, flags, mcs;
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
IEEE80211_TX_CTL_DONTFRAG;
+ info->control.prerate.count = 1;
+ info->control.prerate.flags = 0;
+ info->control.use_preset_rate = 0;
+ info->control.use_legacy_rate = 0;
/*
* for every radiotap entry that is present
@@ -1722,6 +1777,46 @@
txflags = get_unaligned_le16(iterator.this_arg);
if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK)
info->flags |= IEEE80211_TX_CTL_NO_ACK;
+ if (txflags & IEEE80211_RADIOTAP_F_TX_CTS)
+ info->control.prerate.flags |=
+ IEEE80211_TX_RC_USE_CTS_PROTECT;
+ if (txflags & IEEE80211_RADIOTAP_F_TX_RTS)
+ info->control.prerate.flags |=
+ IEEE80211_TX_RC_USE_RTS_CTS;
+ break;
+
+ case IEEE80211_RADIOTAP_RATE:
+ info->control.bitrate = *iterator.this_arg * 5;
+ info->control.use_legacy_rate = 1;
+ info->control.use_preset_rate = 1;
+ break;
+
+ case IEEE80211_RADIOTAP_MCS:
+ known = *iterator.this_arg;
+ flags = *(iterator.this_arg + 1);
+ mcs = *(iterator.this_arg + 2);
+ if (known & IEEE80211_RADIOTAP_MCS_HAVE_MCS) {
+ info->control.prerate.idx = mcs;
+ info->control.prerate.flags |=
+ IEEE80211_TX_RC_MCS;
+ info->control.use_preset_rate = 1;
+ }
+ if (known & IEEE80211_RADIOTAP_MCS_HAVE_BW) {
+ if ((flags & IEEE80211_RADIOTAP_MCS_BW_MASK)
+ == IEEE80211_RADIOTAP_MCS_BW_40)
+ info->control.prerate.flags |=
+ IEEE80211_TX_RC_40_MHZ_WIDTH;
+ }
+ if (known & IEEE80211_RADIOTAP_MCS_HAVE_GI) {
+ if (flags & IEEE80211_RADIOTAP_MCS_SGI)
+ info->control.prerate.flags |=
+ IEEE80211_TX_RC_SHORT_GI;
+ }
+ if (known & IEEE80211_RADIOTAP_MCS_HAVE_FMT) {
+ if (flags & IEEE80211_RADIOTAP_MCS_FMT_GF)
+ info->control.prerate.flags |=
+ IEEE80211_TX_RC_GREEN_FIELD;
+ }
break;
/*

363
radiotap.c Normal file
View File

@ -0,0 +1,363 @@
/*
* Radiotap parser
*
* Copyright 2007 Andy Green <andy@warmcat.com>
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See COPYING for more details.
*/
#include "ieee80211_radiotap.h"
/* function prototypes and related defs are in include/net/cfg80211.h */
static const struct radiotap_align_size rtap_namespace_sizes[] = {
[IEEE80211_RADIOTAP_TSFT] = { .align = 8, .size = 8, },
[IEEE80211_RADIOTAP_FLAGS] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_RATE] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_CHANNEL] = { .align = 2, .size = 4, },
[IEEE80211_RADIOTAP_FHSS] = { .align = 2, .size = 2, },
[IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_DBM_ANTNOISE] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_LOCK_QUALITY] = { .align = 2, .size = 2, },
[IEEE80211_RADIOTAP_TX_ATTENUATION] = { .align = 2, .size = 2, },
[IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = { .align = 2, .size = 2, },
[IEEE80211_RADIOTAP_DBM_TX_POWER] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_ANTENNA] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_DB_ANTSIGNAL] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_DB_ANTNOISE] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_RX_FLAGS] = { .align = 2, .size = 2, },
[IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, },
[IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, },
[IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, },
/*
* add more here as they are defined in radiotap.h
*/
};
static const struct ieee80211_radiotap_namespace radiotap_ns = {
.n_bits = ARRAY_SIZE(rtap_namespace_sizes),
.align_size = rtap_namespace_sizes,
};
/**
* ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
* @iterator: radiotap_iterator to initialize
* @radiotap_header: radiotap header to parse
* @max_length: total length we can parse into (eg, whole packet length)
*
* Returns: 0 or a negative error code if there is a problem.
*
* This function initializes an opaque iterator struct which can then
* be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
* argument which is present in the header. It knows about extended
* present headers and handles them.
*
* How to use:
* call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
* struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
* checking for a good 0 return code. Then loop calling
* __ieee80211_radiotap_iterator_next()... it returns either 0,
* -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
* The iterator's @this_arg member points to the start of the argument
* associated with the current argument index that is present, which can be
* found in the iterator's @this_arg_index member. This arg index corresponds
* to the IEEE80211_RADIOTAP_... defines.
*
* Radiotap header length:
* You can find the CPU-endian total radiotap header length in
* iterator->max_length after executing ieee80211_radiotap_iterator_init()
* successfully.
*
* Alignment Gotcha:
* You must take care when dereferencing iterator.this_arg
* for multibyte types... the pointer is not aligned. Use
* get_unaligned((type *)iterator.this_arg) to dereference
* iterator.this_arg for type "type" safely on all arches.
*
* Example code:
* See Documentation/networking/radiotap-headers.txt
*/
int ieee80211_radiotap_iterator_init(
struct ieee80211_radiotap_iterator *iterator,
struct ieee80211_radiotap_header *radiotap_header,
int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
{
/* check the radiotap header can actually be present */
if (max_length < sizeof(struct ieee80211_radiotap_header))
return -EINVAL;
/* Linux only supports version 0 radiotap format */
if (radiotap_header->it_version)
return -EINVAL;
/* sanity check for allowed length and radiotap length field */
if (max_length < get_unaligned_le16(&radiotap_header->it_len))
return -EINVAL;
iterator->_rtheader = radiotap_header;
iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
iterator->_arg_index = 0;
iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header);
iterator->_reset_on_ext = 0;
iterator->_next_bitmap = &radiotap_header->it_present;
iterator->_next_bitmap++;
iterator->_vns = vns;
iterator->current_namespace = &radiotap_ns;
iterator->is_radiotap_ns = 1;
/* find payload start allowing for extended bitmap(s) */
if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
if ((unsigned long)iterator->_arg -
(unsigned long)iterator->_rtheader + sizeof(uint32_t) >
(unsigned long)iterator->_max_length)
return -EINVAL;
while (get_unaligned_le32(iterator->_arg) &
(1 << IEEE80211_RADIOTAP_EXT)) {
iterator->_arg += sizeof(uint32_t);
/*
* check for insanity where the present bitmaps
* keep claiming to extend up to or even beyond the
* stated radiotap header length
*/
if ((unsigned long)iterator->_arg -
(unsigned long)iterator->_rtheader +
sizeof(uint32_t) >
(unsigned long)iterator->_max_length)
return -EINVAL;
}
iterator->_arg += sizeof(uint32_t);
/*
* no need to check again for blowing past stated radiotap
* header length, because ieee80211_radiotap_iterator_next
* checks it before it is dereferenced
*/
}
iterator->this_arg = iterator->_arg;
/* we are all initialized happily */
return 0;
}
static void find_ns(struct ieee80211_radiotap_iterator *iterator,
uint32_t oui, uint8_t subns)
{
int i;
iterator->current_namespace = NULL;
if (!iterator->_vns)
return;
for (i = 0; i < iterator->_vns->n_ns; i++) {
if (iterator->_vns->ns[i].oui != oui)
continue;
if (iterator->_vns->ns[i].subns != subns)
continue;
iterator->current_namespace = &iterator->_vns->ns[i];
break;
}
}
/**
* ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
* @iterator: radiotap_iterator to move to next arg (if any)
*
* Returns: 0 if there is an argument to handle,
* -ENOENT if there are no more args or -EINVAL
* if there is something else wrong.
*
* This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
* in @this_arg_index and sets @this_arg to point to the
* payload for the field. It takes care of alignment handling and extended
* present fields. @this_arg can be changed by the caller (eg,
* incremented to move inside a compound argument like
* IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in
* little-endian format whatever the endianess of your CPU.
*
* Alignment Gotcha:
* You must take care when dereferencing iterator.this_arg
* for multibyte types... the pointer is not aligned. Use
* get_unaligned((type *)iterator.this_arg) to dereference
* iterator.this_arg for type "type" safely on all arches.
*/
int ieee80211_radiotap_iterator_next(
struct ieee80211_radiotap_iterator *iterator)
{
while (1) {
int hit = 0;
int pad, align, size, subns;
uint32_t oui;
/* if no more EXT bits, that's it */
if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT &&
!(iterator->_bitmap_shifter & 1))
return -ENOENT;
if (!(iterator->_bitmap_shifter & 1))
goto next_entry; /* arg not present */
/* get alignment/size of data */
switch (iterator->_arg_index % 32) {
case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
case IEEE80211_RADIOTAP_EXT:
align = 1;
size = 0;
break;
case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
align = 2;
size = 6;
break;
default:
if (!iterator->current_namespace ||
iterator->_arg_index >= iterator->current_namespace->n_bits) {
if (iterator->current_namespace == &radiotap_ns)
return -ENOENT;
align = 0;
} else {
align = iterator->current_namespace->align_size[iterator->_arg_index].align;
size = iterator->current_namespace->align_size[iterator->_arg_index].size;
}
if (!align) {
/* skip all subsequent data */
iterator->_arg = iterator->_next_ns_data;
/* give up on this namespace */
iterator->current_namespace = NULL;
goto next_entry;
}
break;
}
/*
* arg is present, account for alignment padding
*
* Note that these alignments are relative to the start
* of the radiotap header. There is no guarantee
* that the radiotap header itself is aligned on any
* kind of boundary.
*
* The above is why get_unaligned() is used to dereference
* multibyte elements from the radiotap area.
*/
pad = ((unsigned long)iterator->_arg -
(unsigned long)iterator->_rtheader) & (align - 1);
if (pad)
iterator->_arg += align - pad;
if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
int vnslen;
if ((unsigned long)iterator->_arg + size -
(unsigned long)iterator->_rtheader >
(unsigned long)iterator->_max_length)
return -EINVAL;
oui = (*iterator->_arg << 16) |
(*(iterator->_arg + 1) << 8) |
*(iterator->_arg + 2);
subns = *(iterator->_arg + 3);
find_ns(iterator, oui, subns);
vnslen = get_unaligned_le16(iterator->_arg + 4);
iterator->_next_ns_data = iterator->_arg + size + vnslen;
if (!iterator->current_namespace)
size += vnslen;
}
/*
* this is what we will return to user, but we need to
* move on first so next call has something fresh to test
*/
iterator->this_arg_index = iterator->_arg_index;
iterator->this_arg = iterator->_arg;
iterator->this_arg_size = size;
/* internally move on the size of this arg */
iterator->_arg += size;
/*
* check for insanity where we are given a bitmap that
* claims to have more arg content than the length of the
* radiotap section. We will normally end up equalling this
* max_length on the last arg, never exceeding it.
*/
if ((unsigned long)iterator->_arg -
(unsigned long)iterator->_rtheader >
(unsigned long)iterator->_max_length)
return -EINVAL;
/* these special ones are valid in each bitmap word */
switch (iterator->_arg_index % 32) {
case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
iterator->_reset_on_ext = 1;
iterator->is_radiotap_ns = 0;
/*
* If parser didn't register this vendor
* namespace with us, allow it to show it
* as 'raw. Do do that, set argument index
* to vendor namespace.
*/
iterator->this_arg_index =
IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
if (!iterator->current_namespace)
hit = 1;
goto next_entry;
case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
iterator->_reset_on_ext = 1;
iterator->current_namespace = &radiotap_ns;
iterator->is_radiotap_ns = 1;
goto next_entry;
case IEEE80211_RADIOTAP_EXT:
/*
* bit 31 was set, there is more
* -- move to next u32 bitmap
*/
iterator->_bitmap_shifter =
get_unaligned_le32(iterator->_next_bitmap);
iterator->_next_bitmap++;
if (iterator->_reset_on_ext)
iterator->_arg_index = 0;
else
iterator->_arg_index++;
iterator->_reset_on_ext = 0;
break;
default:
/* we've got a hit! */
hit = 1;
next_entry:
iterator->_bitmap_shifter >>= 1;
iterator->_arg_index++;
}
/* if we found a valid arg earlier, return it now */
if (hit)
return 0;
}
}

412
rx.cpp Normal file
View File

@ -0,0 +1,412 @@
// -*- C++ -*-
//
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/resource.h>
#include <pcap/pcap.h>
#include <poll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
extern "C"
{
#include "ieee80211_radiotap.h"
#include "fec.h"
}
#include <string>
#include <memory>
#include "wifibroadcast.hpp"
#include "rx.hpp"
Receiver::Receiver(const char *wlan, int radio_port, Aggregator *agg) : agg(agg)
{
char errbuf[PCAP_ERRBUF_SIZE];
ppcap = pcap_create(wlan, errbuf);
if (ppcap == NULL){
throw runtime_error(string_format("Unable to open interface %s in pcap: %s\n", wlan, errbuf));
}
if (pcap_set_snaplen(ppcap, 2048) !=0) throw runtime_error("set_snaplen failed");
if (pcap_set_promisc(ppcap, 1) != 0) throw runtime_error("set_promisc failed");
if (pcap_set_rfmon(ppcap, 1) !=0) throw runtime_error("set_rfmon failed");
if (pcap_set_timeout(ppcap, -1) !=0) throw runtime_error("set_timeout failed");
//if (pcap_set_buffer_size(ppcap, 2048) !=0) throw runtime_error("set_buffer_size failed");
if (pcap_activate(ppcap) !=0) throw runtime_error(string_format("pcap_activate failed: %s", pcap_geterr(ppcap)));
if (pcap_setnonblock(ppcap, 1, errbuf) != 0) throw runtime_error(string_format("set_nonblock failed: %s", errbuf));
int link_encap = pcap_datalink(ppcap);
struct bpf_program bpfprogram;
string program;
switch (link_encap)
{
case DLT_PRISM_HEADER:
fprintf(stderr, "%s has DLT_PRISM_HEADER Encap\n", wlan);
program = string_format("radio[0x4a:4]==0x13223344 && radio[0x4e:2] == 0x55%.2x", radio_port);
break;
case DLT_IEEE802_11_RADIO:
fprintf(stderr, "%s has DLT_IEEE802_11_RADIO Encap\n", wlan);
program = string_format("ether[0x0a:4]==0x13223344 && ether[0x0e:2] == 0x55%.2x", radio_port);
break;
default:
throw runtime_error(string_format("unknown encapsulation on %s", wlan));
}
if (pcap_compile(ppcap, &bpfprogram, program.c_str(), 1, 0) == -1) {
throw runtime_error(string_format("Unable to compile %s: %s", program, pcap_geterr(ppcap)));
}
if (pcap_setfilter(ppcap, &bpfprogram) == -1) {
throw runtime_error(string_format("Unable to set filter %s: %s", program, pcap_geterr(ppcap)));
}
pcap_freecode(&bpfprogram);
fd = pcap_get_selectable_fd(ppcap);
}
Receiver::~Receiver()
{
close(fd);
pcap_close(ppcap);
}
void Receiver::loop_iter(void)
{
struct pcap_pkthdr hdr;
const uint8_t* pkt = pcap_next(ppcap, &hdr);
if (pkt == NULL) {
return;
}
int pktlen = hdr.caplen;
int pkt_rate = 0, antenna = 0, pwr = 0;
uint8_t flags = 0;
struct ieee80211_radiotap_iterator iterator;
int ret = ieee80211_radiotap_iterator_init(&iterator, (ieee80211_radiotap_header*)pkt, pktlen, NULL);
while (ret == 0) {
ret = ieee80211_radiotap_iterator_next(&iterator);
if (ret)
continue;
/* see if this argument is something we can use */
switch (iterator.this_arg_index)
{
/*
* You must take care when dereferencing iterator.this_arg
* for multibyte types... the pointer is not aligned. Use
* get_unaligned((type *)iterator.this_arg) to dereference
* iterator.this_arg for type "type" safely on all arches.
*/
case IEEE80211_RADIOTAP_RATE:
/* radiotap "rate" u8 is in
* 500kbps units, eg, 0x02=1Mbps
*/
pkt_rate = (*(uint8_t*)(iterator.this_arg))/2;
break;
case IEEE80211_RADIOTAP_ANTENNA:
antenna = *(uint8_t*)(iterator.this_arg);
break;
case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
pwr = *(int8_t*)(iterator.this_arg);
break;
case IEEE80211_RADIOTAP_FLAGS:
flags = *(uint8_t*)(iterator.this_arg);
break;
default:
break;
}
} /* while more rt headers */
if (ret != -ENOENT){
fprintf(stderr, "Error parsing radiotap header!\n");
return;
}
if (flags & IEEE80211_RADIOTAP_F_FCS)
{
pktlen -= 4;
}
if (flags & IEEE80211_RADIOTAP_F_BADFCS)
{
fprintf(stderr, "Got packet with bad fsc\n");
return;
}
/* discard the radiotap header part */
pkt += iterator._max_length;
pktlen -= iterator._max_length;
//printf("%d mbit/s ant %d %ddBm size:%d\n", pkt_rate, antenna, pwr, pktlen);
if (pktlen > sizeof_ieee80211_header)
{
agg->process_packet(pkt + sizeof_ieee80211_header, pktlen - sizeof_ieee80211_header);
} else {
fprintf(stderr, "short packet (ieee header)\n");
return;
}
}
Aggregator::Aggregator(const string &client_addr, int client_port, int k, int n) : fec_k(k), fec_n(n), block_idx(0), send_fragment_idx(0), seq(0), has_fragments(0), fragment_lost(false)
{
sockfd = open_udp_socket(client_addr, client_port);
fec_p = fec_new(fec_k, fec_n);
fragments = new uint8_t*[fec_n];
for(int i=0; i < fec_n; i++)
{
fragments[i] = new uint8_t[MAX_FEC_PAYLOAD];
}
fragment_map = new uint8_t[fec_n];
memset(fragment_map, '\0', fec_n * sizeof(uint8_t));
}
Aggregator::~Aggregator()
{
delete fragment_map;
for(int i=0; i < fec_n; i++)
{
delete fragments[i];
}
delete fragments;
close(sockfd);
}
int Aggregator::open_udp_socket(const string &client_addr, int client_port)
{
struct sockaddr_in saddr;
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) throw runtime_error(string_format("Error opening socket: %s", strerror(errno)));
bzero((char *) &saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr(client_addr.c_str());
saddr.sin_port = htons((unsigned short)client_port);
if (connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
{
throw runtime_error(string_format("Connect error: %s", strerror(errno)));
}
return fd;
}
void Aggregator::process_packet(const uint8_t *buf, size_t size)
{
if(size < sizeof(wblock_hdr_t) + sizeof(wpacket_hdr_t))
{
fprintf(stderr, "short packet (fec header)\n");
return;
}
if (size > MAX_FEC_PAYLOAD + sizeof(wblock_hdr_t))
{
fprintf(stderr, "long packet (fec payload)\n");
return;
}
wblock_hdr_t *block_hdr = (wblock_hdr_t*)buf;
if (block_hdr->block_idx != block_idx)
{
if(has_fragments < fec_k)
{
for(int i = send_fragment_idx; i < fec_k; i++)
{
if (fragment_map[i]) send_packet(i);
}
}
block_idx = block_hdr->block_idx;
has_fragments = 0;
send_fragment_idx = 0;
fragment_lost = false;
memset(fragment_map, '\0', fec_n * sizeof(uint8_t));
}
if (has_fragments >= fec_k || fragment_map[block_hdr->fragment_idx]) return;
memset(fragments[block_hdr->fragment_idx], '\0', MAX_FEC_PAYLOAD);
memcpy(fragments[block_hdr->fragment_idx], buf + sizeof(wblock_hdr_t), size - sizeof(wblock_hdr_t));
fragment_map[block_hdr->fragment_idx] = 1;
has_fragments += 1;
if(block_hdr->fragment_idx > 0 && !fragment_map[block_hdr->fragment_idx - 1])
{
fragment_lost = true;
}
if(!fragment_lost)
{
send_packet(send_fragment_idx);
send_fragment_idx += 1;
}
if(has_fragments == fec_k)
{
apply_fec();
for(int i = send_fragment_idx; i < fec_k; i++)
{
send_packet(i);
}
}
}
void Aggregator::send_packet(int idx)
{
wpacket_hdr_t* packet_hdr = (wpacket_hdr_t*)(fragments[idx]);
uint8_t *payload = (fragments[idx]) + sizeof(wpacket_hdr_t);
if (packet_hdr->seq > seq + 1)
{
fprintf(stderr, "%d packets lost\n", packet_hdr->seq - seq - 1);
}
seq = packet_hdr->seq;
if(packet_hdr->packet_size > MAX_PAYLOAD_SIZE)
{
fprintf(stderr, "corrupted packet %d\n", seq);
}else{
send(sockfd, payload, packet_hdr->packet_size, 0);
}
}
void Aggregator::apply_fec(void)
{
unsigned index[fec_k];
uint8_t *in_blocks[fec_k];
uint8_t *out_blocks[fec_n - fec_k];
int j = fec_k;
int ob_idx = 0;
for(int i=0; i < fec_k; i++)
{
if(fragment_map[i])
{
in_blocks[i] = fragments[i];
index[i] = i;
}else
{
for(;j < fec_n; j++)
{
if(fragment_map[j])
{
in_blocks[i] = fragments[j];
out_blocks[ob_idx++] = fragments[i];
index[i] = j;
j++;
break;
}
}
}
}
fec_decode(fec_p, (const uint8_t**)in_blocks, out_blocks, index, MAX_FEC_PAYLOAD);
}
int main(int argc, char* const *argv)
{
int opt;
uint8_t k=8, n=12, radio_port=1;
int client_port=5600;
string client_addr="127.0.0.1";
while ((opt = getopt(argc, argv, "k:n:c:u:p:")) != -1) {
switch (opt) {
case 'k':
k = atoi(optarg);
break;
case 'n':
n = atoi(optarg);
break;
case 'c':
client_addr = string(optarg);
break;
case 'u':
client_port = atoi(optarg);
break;
case 'p':
radio_port = atoi(optarg);
break;
default: /* '?' */
show_usage:
fprintf(stderr, "Usage: %s [-k RS_K] [-n RS_N] [-c client_addr] [-u client_port] [-p radio_port] interface1 [interface2] ...\n",
argv[0]);
fprintf(stderr, "Default: k=%d, n=%d, connect=%s:%d, radio_port=%d\n", k, n, client_addr.c_str(), client_port, radio_port);
exit(1);
}
}
if (optind >= argc) {
goto show_usage;
}
int nfds = min(argc - optind, MAX_RX_INTERFACES);
struct pollfd fds[MAX_RX_INTERFACES];
Receiver* rx[MAX_RX_INTERFACES];
try
{
Aggregator agg(client_addr, client_port, k, n);
memset(fds, '\0', sizeof(fds));
for(int i = 0; i < nfds; i++)
{
rx[i] = new Receiver(argv[optind + i], radio_port, &agg);
fds[i].fd = rx[i]->getfd();
fds[i].events = POLLIN;
}
while(1)
{
int rc = poll(fds, nfds, 1000);
if (rc < 0) throw runtime_error(string_format("Poll error: %s", strerror(errno)));
for(int i = 0; rc > 0 && i < nfds; i++)
{
if (fds[i].revents & POLLERR)
{
throw runtime_error("socket error!");
}
if (fds[i].revents & POLLIN){
rx[i]->loop_iter();
rc -= 1;
}
}
}
}catch(runtime_error e)
{
fprintf(stderr, "Error: %s\n", e.what());
exit(1);
}
return 0;
}

40
rx.hpp Normal file
View File

@ -0,0 +1,40 @@
// -*- C++ -*-
//
#define sizeof_ieee80211_header 24
class Aggregator
{
public:
Aggregator(const string &client_addr, int client_port, int k, int n);
~Aggregator();
void process_packet(const uint8_t *buf, size_t size);
private:
int open_udp_socket(const string &client_addr, int client_port);
void apply_fec(void);
void send_packet(int idx);
int sockfd;
fec_t* fec_p;
int fec_k; // RS number of primary fragments in block
int fec_n; // RS total number of fragments in block
uint8_t block_idx;
uint8_t send_fragment_idx;
uint32_t seq;
uint8_t** fragments;
uint8_t *fragment_map;
uint8_t has_fragments;
bool fragment_lost;
};
class Receiver
{
public:
Receiver(const char* wlan, int port, Aggregator* agg);
~Receiver();
void loop_iter(void);
int getfd(void){ return fd; }
private:
Aggregator *agg;
int fd;
pcap_t *ppcap;
};

18
rx.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
WLANS=$@
CHANNEL5G="6"
#CHANNEL5G="149"
for WLAN in $WLANS
do
echo "Setting $WLAN to channel $CHANNEL5G"
ifconfig $WLAN down
iw dev $WLAN set monitor otherbss fcsfail
iw reg set BO
ifconfig $WLAN up
iwconfig $WLAN channel $CHANNEL5G
done
./rx -u 5601 $WLANS
#tcpdump -i $WLAN 'ether[0x0a:4]==0x13223344'

195
tx.cpp Normal file
View File

@ -0,0 +1,195 @@
// -*- C++ -*-
//
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/resource.h>
#include <pcap/pcap.h>
#include <assert.h>
#include <string>
#include <memory>
extern "C"
{
#include "fec.h"
}
#include "wifibroadcast.hpp"
#include "tx.hpp"
Transmitter::Transmitter(const char *wlan, int k, int n, uint8_t radio_rate, uint8_t radio_port) : wlan(wlan), fec_k(k), fec_n(n), block_idx(0),
fragment_idx(0), seq(0), radio_rate(radio_rate),
radio_port(radio_port), max_packet_size(0)
{
char errbuf[PCAP_ERRBUF_SIZE];
ppcap = pcap_create(wlan, errbuf);
if (ppcap == NULL){
throw runtime_error(string_format("Unable to open interface %s in pcap: %s", wlan, errbuf));
}
if (pcap_set_snaplen(ppcap, 1024) !=0) throw runtime_error("set_snaplen failed");
if (pcap_set_promisc(ppcap, 1) != 0) throw runtime_error("set_promisc failed");
if (pcap_set_rfmon(ppcap, 1) !=0) throw runtime_error("set_rfmon failed");
if (pcap_set_timeout(ppcap, -1) !=0) throw runtime_error("set_timeout failed");
//if (pcap_set_buffer_size(ppcap, 2048) !=0) throw runtime_error("set_buffer_size failed");
if (pcap_activate(ppcap) !=0) throw runtime_error(string_format("pcap_activate failed: %s", pcap_geterr(ppcap)));
//if (pcap_setnonblock(ppcap, 1, errbuf) != 0) throw runtime_error(string_format("set_nonblock failed: %s", errbuf));
fec_p = fec_new(fec_k, fec_n);
block = new uint8_t*[fec_n];
for(int i=0; i < fec_n; i++)
{
block[i] = new uint8_t[MAX_FEC_PAYLOAD];
}
}
Transmitter::~Transmitter()
{
for(int i=0; i < fec_n; i++)
{
delete block[i];
}
delete block;
fec_free(fec_p);
pcap_close(ppcap);
}
void Transmitter::send_block_fragment(size_t packet_size)
{
uint8_t txbuf[MAX_PACKET_SIZE];
uint8_t *p = txbuf;
wblock_hdr_t block_hdr;
block_hdr.block_idx = block_idx;
block_hdr.fragment_idx = fragment_idx;
memcpy(p, radiotap_header, sizeof(radiotap_header));
p[8] = radio_rate * 2;
p += sizeof(radiotap_header);
memcpy(p, ieee80211_header, sizeof(ieee80211_header));
p[SRC_MAC_LASTBYTE] = radio_port;
p[DST_MAC_LASTBYTE] = radio_port;
p += sizeof(ieee80211_header);
memcpy(p, &block_hdr, sizeof(block_hdr));
p += sizeof(block_hdr);
memcpy(p, block[fragment_idx], packet_size);
p += packet_size;
if (pcap_inject(ppcap, txbuf, p - txbuf) != p - txbuf)
{
throw runtime_error(string_format("Unable to inject packet"));
}
}
void Transmitter::send_packet(const uint8_t *buf, size_t size)
{
wpacket_hdr_t packet_hdr;
packet_hdr.seq = seq++;
packet_hdr.packet_size = size;
memset(block[fragment_idx], '\0', MAX_FEC_PAYLOAD);
memcpy(block[fragment_idx], &packet_hdr, sizeof(packet_hdr));
memcpy(block[fragment_idx] + sizeof(packet_hdr), buf, size);
send_block_fragment(sizeof(packet_hdr) + size);
max_packet_size = max(max_packet_size, sizeof(packet_hdr) + size);
fragment_idx += 1;
if (fragment_idx < fec_k) return;
fec_encode(fec_p, (const uint8_t**)block, block + fec_k, max_packet_size);
while (fragment_idx < fec_n)
{
send_block_fragment(max_packet_size);
fragment_idx += 1;
}
block_idx += 1;
fragment_idx = 0;
max_packet_size = 0;
}
int open_udp_socket(int port)
{
struct sockaddr_in saddr;
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) throw runtime_error(string_format("Error opening socket: %s", strerror(errno)));
int optval = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));
bzero((char *) &saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons((unsigned short)port);
if (bind(fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
{
throw runtime_error(string_format("Bind error: %s", strerror(errno)));
}
return fd;
}
int main(int argc, char * const *argv)
{
uint8_t buf[MAX_PAYLOAD_SIZE];
int opt;
uint8_t k=8, n=12, radio_port=1, radio_rate=54;
int udp_port=5600;
while ((opt = getopt(argc, argv, "k:n:u:r:p:")) != -1) {
switch (opt) {
case 'k':
k = atoi(optarg);
break;
case 'n':
n = atoi(optarg);
break;
case 'u':
udp_port = atoi(optarg);
break;
case 'r':
radio_rate = atoi(optarg);
break;
case 'p':
radio_port = atoi(optarg);
break;
default: /* '?' */
show_usage:
fprintf(stderr, "Usage: %s [-k RS_K] [-n RS_N] [-u udp_port] [-r tx_rate] [-p radio_port] interface\n",
argv[0]);
fprintf(stderr, "Default: k=%d, n=%d, udp_port=%d, tx_rate=%d Mbit/s, radio_port=%d\n", k, n, udp_port, radio_rate, radio_port);
fprintf(stderr, "Radio MTU: %ld\n", MAX_PAYLOAD_SIZE);
exit(1);
}
}
if (optind >= argc) {
goto show_usage;
}
try
{
int fd = open_udp_socket(udp_port);
Transmitter t(argv[optind], k, n, radio_rate, radio_port);
for(;;)
{
ssize_t rsize = recv(fd, buf, sizeof(buf), 0);
if (rsize < 0) throw runtime_error(string_format("Error receiving packet: %s", strerror(errno)));
t.send_packet(buf, rsize);
}
return 0;
}catch(runtime_error e)
{
fprintf(stderr, "Error: %s\n", e.what());
exit(1);
}
}

28
tx.hpp Normal file
View File

@ -0,0 +1,28 @@
// -*- C++ -*-
//
using namespace std;
class Transmitter
{
public:
Transmitter(const char* wlan, int k, int m, uint8_t radio_rate, uint8_t radio_port);
~Transmitter();
void send_packet(const uint8_t *buf, size_t size);
private:
void send_block_fragment(size_t packet_size);
string wlan;
pcap_t *ppcap;
fec_t* fec_p;
int fec_k; // RS number of primary fragments in block
int fec_n; // RS total number of fragments in block
uint8_t block_idx;
uint8_t fragment_idx;
uint32_t seq;
uint8_t radio_rate;
uint8_t radio_port;
uint8_t** block;
size_t max_packet_size;
};

15
tx.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
WLAN=$1
CHANNEL5G="6"
#CHANNEL5G="149"
echo "Setting $WLAN to channel $CHANNEL5G"
ifconfig $WLAN down
iw reg set BO
iw dev $WLAN set monitor otherbss fcsfail
ifconfig $WLAN up
iwconfig $WLAN channel $CHANNEL5G
./tx $WLAN
#./tx_test | ./tx -b 1 -r 0 -f 1024 $WLAN

70
wifibroadcast.hpp Normal file
View File

@ -0,0 +1,70 @@
#ifndef __WIFIBROADCAST_HPP__
#define __WIFIBROADCAST_HPP__
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <resolv.h>
#include <string.h>
#include <utime.h>
#include <unistd.h>
#include <getopt.h>
#include <pcap.h>
#include <endian.h>
#include <fcntl.h>
#include <time.h>
#include <sys/mman.h>
#define MAX_PACKET_SIZE 1510
#define MAX_RX_INTERFACES 8
using namespace std;
template<typename ... Args>
string string_format( const std::string& format, Args ... args )
{
size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0'
unique_ptr<char[]> buf(new char[ size ]);
snprintf(buf.get(), size, format.c_str(), args ...);
return string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}
/* this is the template radiotap header we send packets out with */
static const uint8_t radiotap_header[] = {
0x00, 0x00, // <-- radiotap version
0x0c, 0x00, // <- radiotap header lengt
0x04, 0x80, 0x00, 0x00, // <-- radiotap present flags
0x00, // Rate, offset 0x8
0x00,
0x18, 0x00
};
//the last byte of the mac address is recycled as a port number
#define SRC_MAC_LASTBYTE 15
#define DST_MAC_LASTBYTE 21
static uint8_t ieee80211_header[] = {
0x08, 0x01, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
0x10, 0x86,
};
typedef struct {
uint8_t block_idx;
uint8_t fragment_idx;
} __attribute__ ((packed)) wblock_hdr_t;
typedef struct {
uint32_t seq;
uint16_t packet_size;
} __attribute__ ((packed)) wpacket_hdr_t;
#define MAX_PAYLOAD_SIZE (MAX_PACKET_SIZE - sizeof(radiotap_header) - sizeof(ieee80211_header) - sizeof(wblock_hdr_t) - sizeof(wpacket_hdr_t))
#define MAX_FEC_PAYLOAD (MAX_PACKET_SIZE - sizeof(radiotap_header) - sizeof(ieee80211_header) - sizeof(wblock_hdr_t))
#endif