parent
705f07945d
commit
4c91eaec02
|
@ -1,11 +1,19 @@
|
||||||
CMakeLists.txt.user
|
*.o
|
||||||
CMakeCache.txt
|
*.swp
|
||||||
CMakeFiles
|
*.swo
|
||||||
CMakeScripts
|
*.d
|
||||||
Testing
|
*.log
|
||||||
Makefile
|
*.pcap
|
||||||
cmake_install.cmake
|
*~
|
||||||
install_manifest.txt
|
*.exe
|
||||||
compile_commands.json
|
|
||||||
CTestTestfile.cmake
|
a.out
|
||||||
_deps
|
|
||||||
|
.vs/*
|
||||||
|
|
||||||
|
out/*
|
||||||
|
*/out/*
|
||||||
|
build/*
|
||||||
|
*/build/*
|
||||||
|
|
||||||
|
.cache/*
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Based on the hackrf cmakefiles, in turn based on the libftdi cmake
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
project(userspace-wifi C)
|
||||||
|
set(PACKAGE userspace-wifi)
|
||||||
|
include(${PROJECT_SOURCE_DIR}/cmake/set_release.cmake)
|
||||||
|
add_definitions(-DRELEASE="${RELEASE}")
|
||||||
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules)
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
include_directories(getopt)
|
||||||
|
add_definitions(/D _CRT_SECURE_NO_WARNINGS)
|
||||||
|
if (FIND_DEBUG)
|
||||||
|
add_definitions(/D FIND_DEBUG)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
add_definitions(-Wall)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
|
||||||
|
if (FIND_DEBUG)
|
||||||
|
add_definitions(-DFIND_DEBUG=1)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
find_package(PThread REQUIRED)
|
||||||
|
include_directories(${PTHREAD_INCLUDE_DIR})
|
||||||
|
set(INT_THREAD_LIBS ${PTHREADS_LIBRARY})
|
||||||
|
|
||||||
|
find_package(LibUSB-1.0 REQUIRED)
|
||||||
|
include_directories(${LIBUSB_1_INCLUDE_DIR})
|
||||||
|
link_directories(${LIBUSB_1_LIBRARY_DIR})
|
||||||
|
set(INT_LIBUSB_LIBS ${LIBUSB_1_LIBRARIES})
|
||||||
|
|
||||||
|
set (firmwaredir .)
|
||||||
|
else()
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
set(INT_THREAD_LIBS ${THREADS_LIBRARY})
|
||||||
|
|
||||||
|
find_package(USB1 REQUIRED)
|
||||||
|
include_directories(${LIBUSB_INCLUDE_DIR})
|
||||||
|
set(INT_LIBUSB_LIBS ${LIBUSB_LIBRARIES})
|
||||||
|
|
||||||
|
set (firmwaredir \${prefix}/share/wifiuserspace/firmware)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
add_subdirectory(libwifiuserspace)
|
||||||
|
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/libwifiuserspace)
|
||||||
|
|
||||||
|
SET(TOOLS
|
||||||
|
wifi_coconut_capture
|
||||||
|
wifi_coconut
|
||||||
|
)
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
add_library(libgetopt_static STATIC
|
||||||
|
getopt/getopt.c
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
LIST(APPEND TOOLS_LINK_LIBS wifiuserspace-static)
|
||||||
|
LIST(APPEND TOOLS_LINK_LIBS ${INT_THREAD_LIBS})
|
||||||
|
LIST(APPEND TOOLS_LINK_LIBS ${INT_LIBUSB_LIBS})
|
||||||
|
LIST(APPEND TOOLS_LINK_LIBS ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR})
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
LIST(APPEND TOOLS_LINK_LIBS libgetopt_static)
|
||||||
|
|
||||||
|
add_custom_target(copydlls)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(wifi_coconut_capture
|
||||||
|
wifi_capture.c
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(wifi_coconut
|
||||||
|
wifi_coconut.c
|
||||||
|
wifi_coconut/wifi_coconut.c
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(tool ${TOOLS})
|
||||||
|
target_link_libraries(${tool} ${TOOLS_LINK_LIBS})
|
||||||
|
install(TARGETS ${tool} RUNTIME DESTINATION bin)
|
||||||
|
endforeach(tool)
|
||||||
|
|
||||||
|
INSTALL(
|
||||||
|
DIRECTORY ${PROJECT_SOURCE_DIR}/libwifiuserspace/firmware/
|
||||||
|
DESTINATION ${firmwaredir}
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "x64-Debug",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "Debug",
|
||||||
|
"inheritEnvironments": [ "clang_cl_x64" ],
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"buildCommandArgs": "-v",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"name": "CMAKE_TOOLCHAIN_FILE",
|
||||||
|
"value": "C:\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake",
|
||||||
|
"type": "STRING"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
58
LICENSE
58
LICENSE
|
@ -1,12 +1,31 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
Valid-License-Identifier: GPL-2.0
|
||||||
Version 2, June 1991
|
Valid-License-Identifier: GPL-2.0-only
|
||||||
|
Valid-License-Identifier: GPL-2.0+
|
||||||
|
Valid-License-Identifier: GPL-2.0-or-later
|
||||||
|
SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
|
||||||
|
Usage-Guide:
|
||||||
|
To use this license in source code, put one of the following SPDX
|
||||||
|
tag/value pairs into a comment according to the placement
|
||||||
|
guidelines in the licensing rules documentation.
|
||||||
|
For 'GNU General Public License (GPL) version 2 only' use:
|
||||||
|
SPDX-License-Identifier: GPL-2.0
|
||||||
|
or
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
For 'GNU General Public License (GPL) version 2 or any later version' use:
|
||||||
|
SPDX-License-Identifier: GPL-2.0+
|
||||||
|
or
|
||||||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
License-Text:
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
GNU GENERAL PUBLIC LICENSE
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
The licenses for most software are designed to take away your
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
@ -15,7 +34,7 @@ software--to make sure the software is free for all its users. This
|
||||||
General Public License applies to most of the Free Software
|
General Public License applies to most of the Free Software
|
||||||
Foundation's software and to any other program whose authors commit to
|
Foundation's software and to any other program whose authors commit to
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
your programs, too.
|
your programs, too.
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
@ -55,8 +74,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
0. This License applies to any program or other work which contains
|
||||||
|
@ -110,7 +129,7 @@ above, provided that you also meet all of these conditions:
|
||||||
License. (Exception: if the Program itself is interactive but
|
License. (Exception: if the Program itself is interactive but
|
||||||
does not normally print such an announcement, your work based on
|
does not normally print such an announcement, your work based on
|
||||||
the Program is not required to print an announcement.)
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
These requirements apply to the modified work as a whole. If
|
||||||
identifiable sections of that work are not derived from the Program,
|
identifiable sections of that work are not derived from the Program,
|
||||||
and can be reasonably considered independent and separate works in
|
and can be reasonably considered independent and separate works in
|
||||||
|
@ -168,7 +187,7 @@ access to copy from a designated place, then offering equivalent
|
||||||
access to copy the source code from the same place counts as
|
access to copy the source code from the same place counts as
|
||||||
distribution of the source code, even though third parties are not
|
distribution of the source code, even though third parties are not
|
||||||
compelled to copy the source along with the object code.
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
except as expressly provided under this License. Any attempt
|
except as expressly provided under this License. Any attempt
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
@ -225,7 +244,7 @@ impose that choice.
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
This section is intended to make thoroughly clear what is believed to
|
||||||
be a consequence of the rest of this License.
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
original copyright holder who places the Program under this License
|
original copyright holder who places the Program under this License
|
||||||
|
@ -255,7 +274,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||||
of preserving the free status of all derivatives of our free software and
|
of preserving the free status of all derivatives of our free software and
|
||||||
of promoting the sharing and reuse of software generally.
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
NO WARRANTY
|
NO WARRANTY
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
@ -277,9 +296,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
If you develop a new program, and you want it to be of the greatest
|
||||||
possible use to the public, the best way to achieve this is to make it
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
@ -303,9 +322,10 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
along with this program; if not, write to the Free Software
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
@ -335,5 +355,5 @@ necessary. Here is a sample; alter the names:
|
||||||
This General Public License does not permit incorporating your program into
|
This General Public License does not permit incorporating your program into
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
consider it more useful to permit linking proprietary applications with the
|
consider it more useful to permit linking proprietary applications with the
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
library. If this is what you want to do, use the GNU Library General
|
||||||
Public License instead of this License.
|
Public License instead of this License.
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Firmware binaries are licensed according to their corresponding vendor
|
||||||
|
licenses, found in the firmware/ directory.
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Hak5 Wi-Fi Coconut
|
||||||
|
|
||||||
|
A user-space driver for USB Wi-Fi NICs and the Hak5 Wi-Fi Coconut
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
See the full documentation at [docs.hak5.org](https://docs.hak5.org/wifi-coconut) for info about usage, pre-built binaries, and compiling instructions for different platforms!
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
# Updated FindThreads.cmake that supports pthread-win32
|
||||||
|
# Downloaded from http://www.vtk.org/Bug/bug_view_advanced_page.php?bug_id=6399
|
||||||
|
|
||||||
|
# - This module determines the thread library of the system.
|
||||||
|
#
|
||||||
|
# The following variables are set
|
||||||
|
# CMAKE_THREAD_LIBS_INIT - the thread library
|
||||||
|
# CMAKE_USE_SPROC_INIT - are we using sproc?
|
||||||
|
# CMAKE_USE_WIN32_THREADS_INIT - using WIN32 threads?
|
||||||
|
# CMAKE_USE_PTHREADS_INIT - are we using pthreads
|
||||||
|
# CMAKE_HP_PTHREADS_INIT - are we using hp pthreads
|
||||||
|
#
|
||||||
|
# If use of pthreads-win32 is desired, the following variables
|
||||||
|
# can be set.
|
||||||
|
#
|
||||||
|
# THREADS_USE_PTHREADS_WIN32 -
|
||||||
|
# Setting this to true searches for the pthreads-win32
|
||||||
|
# port (since CMake 2.8.0)
|
||||||
|
#
|
||||||
|
# THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME
|
||||||
|
# C = no exceptions (default)
|
||||||
|
# (NOTE: This is the default scheme on most POSIX thread
|
||||||
|
# implementations and what you should probably be using)
|
||||||
|
# CE = C++ Exception Handling
|
||||||
|
# SE = Structure Exception Handling (MSVC only)
|
||||||
|
# (NOTE: Changing this option from the default may affect
|
||||||
|
# the portability of your application. See pthreads-win32
|
||||||
|
# documentation for more details.)
|
||||||
|
#
|
||||||
|
#======================================================
|
||||||
|
# Example usage where threading library
|
||||||
|
# is provided by the system:
|
||||||
|
#
|
||||||
|
# find_package(Threads REQUIRED)
|
||||||
|
# add_executable(foo foo.cc)
|
||||||
|
# target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
#
|
||||||
|
# Example usage if pthreads-win32 is desired on Windows
|
||||||
|
# or a system provided thread library:
|
||||||
|
#
|
||||||
|
# set(THREADS_USE_PTHREADS_WIN32 true)
|
||||||
|
# find_package(Threads REQUIRED)
|
||||||
|
# include_directories(${THREADS_PTHREADS_INCLUDE_DIR})
|
||||||
|
#
|
||||||
|
# add_executable(foo foo.cc)
|
||||||
|
# target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
#
|
||||||
|
|
||||||
|
INCLUDE (CheckIncludeFiles)
|
||||||
|
INCLUDE (CheckLibraryExists)
|
||||||
|
SET(Threads_FOUND FALSE)
|
||||||
|
|
||||||
|
IF(WIN32 AND NOT CYGWIN AND THREADS_USE_PTHREADS_WIN32)
|
||||||
|
SET(_Threads_ptwin32 true)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Do we have sproc?
|
||||||
|
IF(CMAKE_SYSTEM MATCHES IRIX)
|
||||||
|
CHECK_INCLUDE_FILES("sys/types.h;sys/prctl.h" CMAKE_HAVE_SPROC_H)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_HAVE_SPROC_H)
|
||||||
|
# We have sproc
|
||||||
|
SET(CMAKE_USE_SPROC_INIT 1)
|
||||||
|
|
||||||
|
ELSEIF(_Threads_ptwin32)
|
||||||
|
|
||||||
|
IF(NOT DEFINED THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME)
|
||||||
|
# Assign the default scheme
|
||||||
|
SET(THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME "C")
|
||||||
|
ELSE()
|
||||||
|
# Validate the scheme specified by the user
|
||||||
|
IF(NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "C" AND
|
||||||
|
NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "CE" AND
|
||||||
|
NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE")
|
||||||
|
MESSAGE(FATAL_ERROR "See documentation for FindPthreads.cmake, only C, CE, and SE modes are allowed")
|
||||||
|
ENDIF()
|
||||||
|
IF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE")
|
||||||
|
MESSAGE(FATAL_ERROR "Structured Exception Handling is only allowed for MSVC")
|
||||||
|
ENDIF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
FIND_PATH(THREADS_PTHREADS_INCLUDE_DIR NAMES pthread.h)
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the library filename
|
||||||
|
IF(MSVC)
|
||||||
|
SET(_Threads_pthreads_libname
|
||||||
|
pthreadsV${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2)
|
||||||
|
ELSEIF(MINGW)
|
||||||
|
SET(_Threads_pthreads_libname
|
||||||
|
pthreadsG${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2)
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(FATAL_ERROR "This should never happen")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
FIND_LIBRARY(THREADS_PTHREADS_WIN32_LIBRARY
|
||||||
|
NAMES ${_Threads_pthreads_libname}
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(THREADS_PTHREADS_INCLUDE_DIR AND THREADS_PTHREADS_WIN32_LIBRARY)
|
||||||
|
MARK_AS_ADVANCED(THREADS_PTHREADS_INCLUDE_DIR)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT ${THREADS_PTHREADS_WIN32_LIBRARY})
|
||||||
|
SET(CMAKE_HAVE_THREADS_LIBRARY 1)
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(THREADS_PTHREADS_WIN32_LIBRARY)
|
||||||
|
|
||||||
|
ELSE()
|
||||||
|
# Do we have pthreads?
|
||||||
|
CHECK_INCLUDE_FILES("pthread.h" CMAKE_HAVE_PTHREAD_H)
|
||||||
|
IF(CMAKE_HAVE_PTHREAD_H)
|
||||||
|
#
|
||||||
|
# We have pthread.h
|
||||||
|
# Let's check for the library now.
|
||||||
|
#
|
||||||
|
SET(CMAKE_HAVE_THREADS_LIBRARY)
|
||||||
|
IF(NOT THREADS_HAVE_PTHREAD_ARG)
|
||||||
|
|
||||||
|
# Do we have -lpthreads
|
||||||
|
CHECK_LIBRARY_EXISTS(pthreads pthread_create "" CMAKE_HAVE_PTHREADS_CREATE)
|
||||||
|
IF(CMAKE_HAVE_PTHREADS_CREATE)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT "-lpthreads")
|
||||||
|
SET(CMAKE_HAVE_THREADS_LIBRARY 1)
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Ok, how about -lpthread
|
||||||
|
CHECK_LIBRARY_EXISTS(pthread pthread_create "" CMAKE_HAVE_PTHREAD_CREATE)
|
||||||
|
IF(CMAKE_HAVE_PTHREAD_CREATE)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
SET(CMAKE_HAVE_THREADS_LIBRARY 1)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_SYSTEM MATCHES "SunOS.*")
|
||||||
|
# On sun also check for -lthread
|
||||||
|
CHECK_LIBRARY_EXISTS(thread thr_create "" CMAKE_HAVE_THR_CREATE)
|
||||||
|
IF(CMAKE_HAVE_THR_CREATE)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT "-lthread")
|
||||||
|
SET(CMAKE_HAVE_THREADS_LIBRARY 1)
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*")
|
||||||
|
|
||||||
|
ENDIF(NOT THREADS_HAVE_PTHREAD_ARG)
|
||||||
|
|
||||||
|
IF(NOT CMAKE_HAVE_THREADS_LIBRARY)
|
||||||
|
# If we did not found -lpthread, -lpthread, or -lthread, look for -pthread
|
||||||
|
IF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG")
|
||||||
|
MESSAGE(STATUS "Check if compiler accepts -pthread")
|
||||||
|
TRY_RUN(THREADS_PTHREAD_ARG THREADS_HAVE_PTHREAD_ARG
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
${CMAKE_ROOT}/Modules/CheckForPthreads.c
|
||||||
|
CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread
|
||||||
|
COMPILE_OUTPUT_VARIABLE OUTPUT)
|
||||||
|
|
||||||
|
IF(THREADS_HAVE_PTHREAD_ARG)
|
||||||
|
IF(THREADS_PTHREAD_ARG MATCHES "^2$")
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
MESSAGE(STATUS "Check if compiler accepts -pthread - yes")
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(STATUS "Check if compiler accepts -pthread - no")
|
||||||
|
FILE(APPEND
|
||||||
|
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||||
|
"Determining if compiler accepts -pthread returned ${THREADS_PTHREAD_ARG} instead of 2. The compiler had the following output:\n${OUTPUT}\n\n")
|
||||||
|
ENDIF()
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(STATUS "Check if compiler accepts -pthread - no")
|
||||||
|
FILE(APPEND
|
||||||
|
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||||
|
"Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
ENDIF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG")
|
||||||
|
|
||||||
|
IF(THREADS_HAVE_PTHREAD_ARG)
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT "-pthread")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
ENDIF(NOT CMAKE_HAVE_THREADS_LIBRARY)
|
||||||
|
ENDIF(CMAKE_HAVE_PTHREAD_H)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_THREAD_LIBS_INIT)
|
||||||
|
SET(CMAKE_USE_PTHREADS_INIT 1)
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_SYSTEM MATCHES "Windows"
|
||||||
|
AND NOT THREADS_USE_PTHREADS_WIN32)
|
||||||
|
SET(CMAKE_USE_WIN32_THREADS_INIT 1)
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_USE_PTHREADS_INIT)
|
||||||
|
IF(CMAKE_SYSTEM MATCHES "HP-UX-*")
|
||||||
|
# Use libcma if it exists and can be used. It provides more
|
||||||
|
# symbols than the plain pthread library. CMA threads
|
||||||
|
# have actually been deprecated:
|
||||||
|
# http://docs.hp.com/en/B3920-90091/ch12s03.html#d0e11395
|
||||||
|
# http://docs.hp.com/en/947/d8.html
|
||||||
|
# but we need to maintain compatibility here.
|
||||||
|
# The CMAKE_HP_PTHREADS setting actually indicates whether CMA threads
|
||||||
|
# are available.
|
||||||
|
CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA)
|
||||||
|
IF(CMAKE_HAVE_HP_CMA)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT "-lcma")
|
||||||
|
SET(CMAKE_HP_PTHREADS_INIT 1)
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
ENDIF(CMAKE_HAVE_HP_CMA)
|
||||||
|
SET(CMAKE_USE_PTHREADS_INIT 1)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_SYSTEM MATCHES "OSF1-V*")
|
||||||
|
SET(CMAKE_USE_PTHREADS_INIT 0)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_SYSTEM MATCHES "CYGWIN_NT*")
|
||||||
|
SET(CMAKE_USE_PTHREADS_INIT 1)
|
||||||
|
SET(Threads_FOUND TRUE)
|
||||||
|
SET(CMAKE_THREAD_LIBS_INIT )
|
||||||
|
SET(CMAKE_USE_WIN32_THREADS_INIT 0)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF(CMAKE_USE_PTHREADS_INIT)
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
IF(_Threads_ptwin32)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG
|
||||||
|
THREADS_PTHREADS_WIN32_LIBRARY THREADS_PTHREADS_INCLUDE_DIR)
|
||||||
|
ELSE()
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG Threads_FOUND)
|
||||||
|
ENDIF()
|
|
@ -0,0 +1,43 @@
|
||||||
|
# - Try to find the freetype library
|
||||||
|
# Once done this defines
|
||||||
|
#
|
||||||
|
# LIBUSB_FOUND - system has libusb
|
||||||
|
# LIBUSB_INCLUDE_DIR - the libusb include directory
|
||||||
|
# LIBUSB_LIBRARIES - Link these to use libusb
|
||||||
|
|
||||||
|
# Copyright (c) 2006, 2008 Laurent Montel, <montel@kde.org>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
|
||||||
|
|
||||||
|
if (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
||||||
|
|
||||||
|
# in cache already
|
||||||
|
set(LIBUSB_FOUND TRUE)
|
||||||
|
|
||||||
|
else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
||||||
|
IF (NOT WIN32)
|
||||||
|
# use pkg-config to get the directories and then use these values
|
||||||
|
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_LIBUSB libusb-1.0)
|
||||||
|
ENDIF(NOT WIN32)
|
||||||
|
|
||||||
|
set(LIBUSB_LIBRARY_NAME usb-1.0)
|
||||||
|
IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||||
|
set(LIBUSB_LIBRARY_NAME usb)
|
||||||
|
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||||
|
|
||||||
|
FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h
|
||||||
|
PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES ${LIBUSB_LIBRARY_NAME}
|
||||||
|
PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES)
|
||||||
|
|
||||||
|
endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
|
@ -0,0 +1,96 @@
|
||||||
|
# - Try to find libusb-1.0
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# LIBUSB_1_FOUND - system has libusb
|
||||||
|
# LIBUSB_1_INCLUDE_DIRS - the libusb include directory
|
||||||
|
# LIBUSB_1_LIBRARIES - Link these to use libusb
|
||||||
|
# LIBUSB_1_DEFINITIONS - Compiler switches required for using libusb
|
||||||
|
#
|
||||||
|
# Adapted from cmake-modules Google Code project
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
|
||||||
|
#
|
||||||
|
# (Changes for libusb) Copyright (c) 2008 Kyle Machulis <kyle@nonpolynomial.com>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the New BSD license.
|
||||||
|
#
|
||||||
|
# CMake-Modules Project New BSD License
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted 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 the CMake-Modules Project nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from this
|
||||||
|
# software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
|
||||||
|
# in cache already
|
||||||
|
set(LIBUSB_FOUND TRUE)
|
||||||
|
else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
|
||||||
|
find_path(LIBUSB_1_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
libusb.h
|
||||||
|
PATHS
|
||||||
|
/usr/include
|
||||||
|
/usr/local/include
|
||||||
|
/sw/include
|
||||||
|
PATH_SUFFIXES
|
||||||
|
libusb-1.0
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(LIBUSB_1_LIBRARY
|
||||||
|
NAMES
|
||||||
|
usb-1.0 usb libusb-1.0
|
||||||
|
PATHS
|
||||||
|
/usr/lib
|
||||||
|
/usr/local/lib
|
||||||
|
/sw/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
set(LIBUSB_1_INCLUDE_DIRS
|
||||||
|
${LIBUSB_1_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
set(LIBUSB_1_LIBRARIES
|
||||||
|
${LIBUSB_1_LIBRARY}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
|
||||||
|
set(LIBUSB_1_FOUND TRUE)
|
||||||
|
endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
|
||||||
|
|
||||||
|
if (LIBUSB_1_FOUND)
|
||||||
|
if (NOT libusb_1_FIND_QUIETLY)
|
||||||
|
message(STATUS "Found libusb-1.0:")
|
||||||
|
message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
|
||||||
|
message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
|
||||||
|
endif (NOT libusb_1_FIND_QUIETLY)
|
||||||
|
else (LIBUSB_1_FOUND)
|
||||||
|
if (libusb_1_FIND_REQUIRED)
|
||||||
|
message(FATAL_ERROR "Could not find libusb")
|
||||||
|
endif (libusb_1_FIND_REQUIRED)
|
||||||
|
endif (LIBUSB_1_FOUND)
|
||||||
|
|
||||||
|
# show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
|
||||||
|
mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
|
||||||
|
|
||||||
|
endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Get the current git version to set a release number
|
||||||
|
|
||||||
|
#set(RELEASE "")
|
||||||
|
|
||||||
|
if(NOT DEFINED RELEASE)
|
||||||
|
execute_process(
|
||||||
|
COMMAND git log -n 1 --format=%h
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
|
RESULT_VARIABLE GIT_EXIT_VALUE
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_VARIABLE GIT_VERSION
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
if (GIT_EXIT_VALUE)
|
||||||
|
set(RELEASE "unknown")
|
||||||
|
else (GIT_EXIT_VALUE)
|
||||||
|
execute_process(
|
||||||
|
COMMAND git status -s --untracked-files=no
|
||||||
|
OUTPUT_VARIABLE DIRTY
|
||||||
|
)
|
||||||
|
if ( NOT "${DIRTY}" STREQUAL "" )
|
||||||
|
set(DIRTY_FLAG "*")
|
||||||
|
else()
|
||||||
|
set(DIRTY_FLAG "")
|
||||||
|
endif()
|
||||||
|
set(RELEASE "git-${GIT_VERSION}${DIRTY_FLAG}")
|
||||||
|
endif (GIT_EXIT_VALUE)
|
||||||
|
endif()
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,180 @@
|
||||||
|
/* Declarations for getopt.
|
||||||
|
Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#ifndef _GETOPT_H
|
||||||
|
|
||||||
|
#ifndef __need_getopt
|
||||||
|
# define _GETOPT_H 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If __GNU_LIBRARY__ is not already defined, either we are being used
|
||||||
|
standalone, or this is the first header included in the source file.
|
||||||
|
If we are being used with glibc, we need to include <features.h>, but
|
||||||
|
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
|
||||||
|
not defined, include <ctype.h>, which will pull in <features.h> for us
|
||||||
|
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
|
||||||
|
doesn't flood the namespace with stuff the way some other headers do.) */
|
||||||
|
#if !defined __GNU_LIBRARY__
|
||||||
|
# include <ctype.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* For communication from `getopt' to the caller.
|
||||||
|
When `getopt' finds an option that takes an argument,
|
||||||
|
the argument value is returned here.
|
||||||
|
Also, when `ordering' is RETURN_IN_ORDER,
|
||||||
|
each non-option ARGV-element is returned here. */
|
||||||
|
|
||||||
|
extern char *optarg;
|
||||||
|
|
||||||
|
/* Index in ARGV of the next element to be scanned.
|
||||||
|
This is used for communication to and from the caller
|
||||||
|
and for communication between successive calls to `getopt'.
|
||||||
|
|
||||||
|
On entry to `getopt', zero means this is the first call; initialize.
|
||||||
|
|
||||||
|
When `getopt' returns -1, this is the index of the first of the
|
||||||
|
non-option elements that the caller should itself scan.
|
||||||
|
|
||||||
|
Otherwise, `optind' communicates from one call to the next
|
||||||
|
how much of ARGV has been scanned so far. */
|
||||||
|
|
||||||
|
extern int optind;
|
||||||
|
|
||||||
|
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||||
|
for unrecognized options. */
|
||||||
|
|
||||||
|
extern int opterr;
|
||||||
|
|
||||||
|
/* Set to an option character which was unrecognized. */
|
||||||
|
|
||||||
|
extern int optopt;
|
||||||
|
|
||||||
|
#ifndef __need_getopt
|
||||||
|
/* Describe the long-named options requested by the application.
|
||||||
|
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||||
|
of `struct option' terminated by an element containing a name which is
|
||||||
|
zero.
|
||||||
|
|
||||||
|
The field `has_arg' is:
|
||||||
|
no_argument (or 0) if the option does not take an argument,
|
||||||
|
required_argument (or 1) if the option requires an argument,
|
||||||
|
optional_argument (or 2) if the option takes an optional argument.
|
||||||
|
|
||||||
|
If the field `flag' is not NULL, it points to a variable that is set
|
||||||
|
to the value given in the field `val' when the option is found, but
|
||||||
|
left unchanged if the option is not found.
|
||||||
|
|
||||||
|
To have a long-named option do something other than set an `int' to
|
||||||
|
a compiled-in constant, such as set a value from `optarg', set the
|
||||||
|
option's `flag' field to zero and its `val' field to a nonzero
|
||||||
|
value (the equivalent single-letter option character, if there is
|
||||||
|
one). For long options that have a zero `flag' field, `getopt'
|
||||||
|
returns the contents of the `val' field. */
|
||||||
|
|
||||||
|
struct option
|
||||||
|
{
|
||||||
|
# if (defined __STDC__ && __STDC__) || defined __cplusplus
|
||||||
|
const char *name;
|
||||||
|
# else
|
||||||
|
char *name;
|
||||||
|
# endif
|
||||||
|
/* has_arg can't be an enum because some compilers complain about
|
||||||
|
type mismatches in all the code that assumes it is an int. */
|
||||||
|
int has_arg;
|
||||||
|
int *flag;
|
||||||
|
int val;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||||
|
|
||||||
|
# define no_argument 0
|
||||||
|
# define required_argument 1
|
||||||
|
# define optional_argument 2
|
||||||
|
#endif /* need getopt */
|
||||||
|
|
||||||
|
|
||||||
|
/* Get definitions and prototypes for functions to process the
|
||||||
|
arguments in ARGV (ARGC of them, minus the program name) for
|
||||||
|
options given in OPTS.
|
||||||
|
|
||||||
|
Return the option character from OPTS just read. Return -1 when
|
||||||
|
there are no more options. For unrecognized options, or options
|
||||||
|
missing arguments, `optopt' is set to the option letter, and '?' is
|
||||||
|
returned.
|
||||||
|
|
||||||
|
The OPTS string is a list of characters which are recognized option
|
||||||
|
letters, optionally followed by colons, specifying that that letter
|
||||||
|
takes an argument, to be placed in `optarg'.
|
||||||
|
|
||||||
|
If a letter in OPTS is followed by two colons, its argument is
|
||||||
|
optional. This behavior is specific to the GNU `getopt'.
|
||||||
|
|
||||||
|
The argument `--' causes premature termination of argument
|
||||||
|
scanning, explicitly telling `getopt' that there are no more
|
||||||
|
options.
|
||||||
|
|
||||||
|
If OPTS begins with `--', then non-option arguments are treated as
|
||||||
|
arguments to the option '\0'. This behavior is specific to the GNU
|
||||||
|
`getopt'. */
|
||||||
|
|
||||||
|
#if (defined __STDC__ && __STDC__) || defined __cplusplus
|
||||||
|
# ifdef __GNU_LIBRARY__
|
||||||
|
/* Many other libraries have conflicting prototypes for getopt, with
|
||||||
|
differences in the consts, in stdlib.h. To avoid compilation
|
||||||
|
errors, only prototype getopt for the GNU C library. */
|
||||||
|
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
|
||||||
|
# else /* not __GNU_LIBRARY__ */
|
||||||
|
extern int getopt ();
|
||||||
|
# endif /* __GNU_LIBRARY__ */
|
||||||
|
|
||||||
|
# ifndef __need_getopt
|
||||||
|
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
|
||||||
|
const struct option *__longopts, int *__longind);
|
||||||
|
extern int getopt_long_only (int __argc, char *const *__argv,
|
||||||
|
const char *__shortopts,
|
||||||
|
const struct option *__longopts, int *__longind);
|
||||||
|
|
||||||
|
/* Internal only. Users should not call this directly. */
|
||||||
|
extern int _getopt_internal (int __argc, char *const *__argv,
|
||||||
|
const char *__shortopts,
|
||||||
|
const struct option *__longopts, int *__longind,
|
||||||
|
int __long_only);
|
||||||
|
# endif
|
||||||
|
#else /* not __STDC__ */
|
||||||
|
extern int getopt ();
|
||||||
|
# ifndef __need_getopt
|
||||||
|
extern int getopt_long ();
|
||||||
|
extern int getopt_long_only ();
|
||||||
|
|
||||||
|
extern int _getopt_internal ();
|
||||||
|
# endif
|
||||||
|
#endif /* __STDC__ */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Make sure we later can get all the definitions and declarations. */
|
||||||
|
#undef __need_getopt
|
||||||
|
|
||||||
|
#endif /* getopt.h */
|
|
@ -0,0 +1,109 @@
|
||||||
|
# Based on the hackrf cmakefiles, in turn based on the libftdi cmake
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
project(libwifiuserspace C)
|
||||||
|
set(PACKAGE libwifiuserspace)
|
||||||
|
include(${PROJECT_SOURCE_DIR}/../cmake/set_release.cmake)
|
||||||
|
add_definitions(-DRELEASE="${RELEASE}")
|
||||||
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
find_package(PThread REQUIRED)
|
||||||
|
include_directories(${PTHREAD_INCLUDE_DIR})
|
||||||
|
set(INT_THREAD_LIBS ${PTHREADS_LIBRARY})
|
||||||
|
|
||||||
|
find_package(LibUSB-1.0 REQUIRED)
|
||||||
|
include_directories(${LIBUSB_1_INCLUDE_DIR})
|
||||||
|
link_directories(${LIBUSB_1_LIBRARY_DIR})
|
||||||
|
set(INT_LIBUSB_LIBS ${LIBUSB_1_LIBRARIES})
|
||||||
|
|
||||||
|
set(sharedir "./")
|
||||||
|
set(INSTALL_LIB_DIR "./")
|
||||||
|
set(INSTALL_DEFAULT_BINDIR "./")
|
||||||
|
else()
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
set(INT_THREAD_LIBS ${THREADS_LIBRARY})
|
||||||
|
|
||||||
|
find_package(USB1 REQUIRED)
|
||||||
|
include_directories(${LIBUSB_INCLUDE_DIR})
|
||||||
|
set(INT_LIBUSB_LIBS ${LIBUSB_LIBRARIES})
|
||||||
|
|
||||||
|
set (sharedir \${prefix}/share/wifiuserspace/firmware)
|
||||||
|
|
||||||
|
set(INSTALL_LIB_DIR \${lib}suffix)
|
||||||
|
|
||||||
|
set(INSTALL_DEFAULT_BINDIR "bin")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(-DFIRMWAREDIR="${prefix}/share/wifiuserspace/firmware")
|
||||||
|
|
||||||
|
set(c_sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2800lib.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2800usb.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2x00.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2x00mac.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2x00usb.c
|
||||||
|
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/kernel/cfg80211.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/kernel/crc_ccit.c
|
||||||
|
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/userspace/userspace.c
|
||||||
|
|
||||||
|
CACHE INTERNAL "List of C sources")
|
||||||
|
|
||||||
|
set(c_kernel_headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/kernel/kernel.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/kernel/types.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/kernel/usb.h
|
||||||
|
CACHE INTERNAL "List of userspace-kernel headers")
|
||||||
|
set(c_userspace_headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/userspace/userspace.h
|
||||||
|
CACHE INTERNAL "List of userspace API eaders")
|
||||||
|
|
||||||
|
add_library(wifiuserspace SHARED ${c_sources})
|
||||||
|
set_target_properties(wifiuserspace PROPERTIES VERSION 2019.09.0 SOVERSION 0)
|
||||||
|
|
||||||
|
add_library(wifiuserspace-static STATIC ${c_sources})
|
||||||
|
if (MSVC)
|
||||||
|
set_target_properties(wifiuserspace-static PROPERTIES OUTPUT_NAME "wifiuserspace_static")
|
||||||
|
else()
|
||||||
|
set_target_properties(wifiuserspace-static PROPERTIES OUTPUT_NAME "wifiuserspace")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(wifiuserspace PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||||
|
set_target_properties(wifiuserspace-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||||
|
|
||||||
|
target_link_libraries(wifiuserspace ${INT_THREAD_LIBS} ${INT_LIBUSB_LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(wifiuserspace-static ${INT_THREAD_LIBS} ${INT_LIBUSB_LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
|
|
||||||
|
if(INSTALL_LIBUSERSPACE)
|
||||||
|
if(MSVC)
|
||||||
|
# Static linkage only on win32
|
||||||
|
else()
|
||||||
|
install(TARGETS wifiuserspace
|
||||||
|
LIBRARY DESTINATION ${INSTALL_LIB_DIR}
|
||||||
|
COMPONENT sharedlibs
|
||||||
|
)
|
||||||
|
install(TARGETS wifiuserspace-static
|
||||||
|
ARCHIVE DESTINATION ${INSTALL_LIB_DIR}
|
||||||
|
COMPONENT staticlibs
|
||||||
|
)
|
||||||
|
install(FILES ${c_kernel_headers}
|
||||||
|
DESTINATION include/${PROJECT_NAME}
|
||||||
|
COMPONENT headers
|
||||||
|
)
|
||||||
|
install(FILES ${c_userspace_headers}
|
||||||
|
DESTINATION include/${PROJECT_NAME}
|
||||||
|
COMPONENT headers
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
INSTALL(
|
||||||
|
DIRECTORY ${PROJECT_SOURCE_DIR}/firmware/
|
||||||
|
DESTINATION ${sharedir}
|
||||||
|
)
|
||||||
|
endif(INSTALL_LIBUSERSPACE)
|
||||||
|
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR})
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
Copyright (c) 2013, Ralink, A MediaTek Company
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution. Redistribution and use in binary form, without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions must reproduce the above copyright notice and the
|
||||||
|
following disclaimer in the documentation and/or other materials
|
||||||
|
provided with the distribution.
|
||||||
|
* Neither the name of Ralink Technology Corporation nor the names of its
|
||||||
|
suppliers may be used to endorse or promote products derived from this
|
||||||
|
software without specific prior written permission.
|
||||||
|
* No reverse engineering, decompilation, or disassembly of this software
|
||||||
|
is permitted.
|
||||||
|
|
||||||
|
Limited patent license. Ralink Technology Corporation grants a world-wide,
|
||||||
|
royalty-free, non-exclusive license under patents it now or hereafter
|
||||||
|
owns or controls to make, have made, use, import, offer to sell and
|
||||||
|
sell ("Utilize") this software, but solely to the extent that any
|
||||||
|
such patent is necessary to Utilize the software alone, or in
|
||||||
|
combination with an operating system licensed under an approved Open
|
||||||
|
Source license as listed by the Open Source Initiative at
|
||||||
|
http://opensource.org/licenses. The patent license shall not apply to
|
||||||
|
any other combinations which include this software. No hardware per
|
||||||
|
se is licensed hereunder.
|
||||||
|
|
||||||
|
DISCLAIMER. 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.
|
Binary file not shown.
|
@ -0,0 +1,78 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_AVERAGE_H__
|
||||||
|
#define __USERSPACE_AVERAGE_H__
|
||||||
|
|
||||||
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/log2.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exponentially weighted moving average (EWMA)
|
||||||
|
*
|
||||||
|
* This implements a fixed-precision EWMA algorithm, with both the
|
||||||
|
* precision and fall-off coefficient determined at compile-time
|
||||||
|
* and built into the generated helper funtions.
|
||||||
|
*
|
||||||
|
* The first argument to the macro is the name that will be used
|
||||||
|
* for the struct and helper functions.
|
||||||
|
*
|
||||||
|
* The second argument, the precision, expresses how many bits are
|
||||||
|
* used for the fractional part of the fixed-precision values.
|
||||||
|
*
|
||||||
|
* The third argument, the weight reciprocal, determines how the
|
||||||
|
* new values will be weighed vs. the old state, new values will
|
||||||
|
* get weight 1/weight_rcp and old values 1-1/weight_rcp. Note
|
||||||
|
* that this parameter must be a power of two for efficiency.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DECLARE_EWMA(name, _precision, _weight_rcp) \
|
||||||
|
struct ewma_##name { \
|
||||||
|
unsigned long internal; \
|
||||||
|
}; \
|
||||||
|
static inline void ewma_##name##_init(struct ewma_##name *e) \
|
||||||
|
{ \
|
||||||
|
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
|
||||||
|
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
|
||||||
|
/* \
|
||||||
|
* Even if you want to feed it just 0/1 you should have \
|
||||||
|
* some bits for the non-fractional part... \
|
||||||
|
*/ \
|
||||||
|
BUILD_BUG_ON((_precision) > 30); \
|
||||||
|
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
|
||||||
|
e->internal = 0; \
|
||||||
|
} \
|
||||||
|
static inline unsigned long \
|
||||||
|
ewma_##name##_read(struct ewma_##name *e) \
|
||||||
|
{ \
|
||||||
|
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
|
||||||
|
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
|
||||||
|
BUILD_BUG_ON((_precision) > 30); \
|
||||||
|
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
|
||||||
|
return e->internal >> (_precision); \
|
||||||
|
} \
|
||||||
|
static inline void ewma_##name##_add(struct ewma_##name *e, \
|
||||||
|
unsigned long val) \
|
||||||
|
{ \
|
||||||
|
unsigned long internal = READ_ONCE(e->internal); \
|
||||||
|
unsigned long weight_rcp = ilog2(_weight_rcp); \
|
||||||
|
unsigned long precision = _precision; \
|
||||||
|
\
|
||||||
|
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
|
||||||
|
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
|
||||||
|
BUILD_BUG_ON((_precision) > 30); \
|
||||||
|
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
|
||||||
|
\
|
||||||
|
WRITE_ONCE(e->internal, internal ? \
|
||||||
|
(((internal << weight_rcp) - internal) + \
|
||||||
|
(val << precision)) >> weight_rcp : \
|
||||||
|
(val << precision)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_AVERAGE_H */
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_BITOPS_H__
|
||||||
|
#define __USERSPACE_BITOPS_H__
|
||||||
|
|
||||||
|
#include "kernel/bits.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
|
||||||
|
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __test_and_clear_bit - Clear a bit and return its old value
|
||||||
|
* @nr: Bit to clear
|
||||||
|
* @addr: Address to count from
|
||||||
|
*
|
||||||
|
* This operation is non-atomic and can be reordered.
|
||||||
|
* If two examples of this operation race, one can appear to succeed
|
||||||
|
* but actually fail. You must protect multiple accesses with a lock.
|
||||||
|
*/
|
||||||
|
static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
|
||||||
|
{
|
||||||
|
unsigned long mask = BIT_MASK(nr);
|
||||||
|
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||||
|
unsigned long old = *p;
|
||||||
|
|
||||||
|
*p = old & ~mask;
|
||||||
|
return (old & mask) != 0;
|
||||||
|
}
|
||||||
|
#define test_and_clear_bit(nr, addr) __test_and_clear_bit((nr), (addr))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kluge swab16
|
||||||
|
*/
|
||||||
|
static inline __u16 ___swab16(__u16 x)
|
||||||
|
{
|
||||||
|
return x<<8 | x>>8;
|
||||||
|
}
|
||||||
|
#define swab16(x) ___swab16(x)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kluge FLS from generic
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* fls - find last (most-significant) bit set
|
||||||
|
* @x: the word to search
|
||||||
|
*
|
||||||
|
* This is defined the same way as ffs.
|
||||||
|
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int __fls(unsigned int x)
|
||||||
|
{
|
||||||
|
int r = 32;
|
||||||
|
|
||||||
|
if (!x)
|
||||||
|
return 0;
|
||||||
|
if (!(x & 0xffff0000u)) {
|
||||||
|
x <<= 16;
|
||||||
|
r -= 16;
|
||||||
|
}
|
||||||
|
if (!(x & 0xff000000u)) {
|
||||||
|
x <<= 8;
|
||||||
|
r -= 8;
|
||||||
|
}
|
||||||
|
if (!(x & 0xf0000000u)) {
|
||||||
|
x <<= 4;
|
||||||
|
r -= 4;
|
||||||
|
}
|
||||||
|
if (!(x & 0xc0000000u)) {
|
||||||
|
x <<= 2;
|
||||||
|
r -= 2;
|
||||||
|
}
|
||||||
|
if (!(x & 0x80000000u)) {
|
||||||
|
x <<= 1;
|
||||||
|
r -= 1;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __fls64(__u64 x)
|
||||||
|
{
|
||||||
|
__u32 h = x >> 32;
|
||||||
|
if (h)
|
||||||
|
return __fls(h) + 32;
|
||||||
|
return __fls(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __fls_long(x) __fls64(x)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_BITOPS_H */
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BITS_H__
|
||||||
|
#define __BITS_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define BIT(nr) (1UL << (nr))
|
||||||
|
#define BIT_ULL(nr) (1ULL << (nr))
|
||||||
|
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||||
|
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||||
|
#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG))
|
||||||
|
#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG)
|
||||||
|
#define BITS_PER_BYTE 8
|
||||||
|
#define BITS_PER_LONG (8 * BITS_PER_BYTE)
|
||||||
|
|
||||||
|
static inline void set_bit(int bit, unsigned long *x) {
|
||||||
|
*x |= (1UL << bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear_bit(int bit, unsigned long *x) {
|
||||||
|
*x &= ~(1UL << bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool test_bit(int bit, unsigned long *x) {
|
||||||
|
return (*x & (1UL << bit));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __clear_bit(n, r) clear_bit((n), (r))
|
||||||
|
#define __get_bit(n, r) get_bit((n), (r))
|
||||||
|
#define __set_bit(n, r) set_bit((n), (r))
|
||||||
|
|
||||||
|
#endif /* ifndef BITS_H */
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Wireless utility functions
|
||||||
|
*
|
||||||
|
* Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
|
||||||
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
|
* Copyright 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2018-2019 Intel Corporation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cfg80211.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
|
||||||
|
int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
|
||||||
|
{
|
||||||
|
/* see 802.11 17.3.8.3.2 and Annex J
|
||||||
|
* there are overlapping channel numbers in 5GHz and 2GHz bands */
|
||||||
|
if (chan <= 0)
|
||||||
|
return 0; /* not supported */
|
||||||
|
switch (band) {
|
||||||
|
case NL80211_BAND_2GHZ:
|
||||||
|
if (chan == 14)
|
||||||
|
return 2484;
|
||||||
|
else if (chan < 14)
|
||||||
|
return 2407 + chan * 5;
|
||||||
|
break;
|
||||||
|
case NL80211_BAND_5GHZ:
|
||||||
|
if (chan >= 182 && chan <= 196)
|
||||||
|
return 4000 + chan * 5;
|
||||||
|
else
|
||||||
|
return 5000 + chan * 5;
|
||||||
|
break;
|
||||||
|
case NL80211_BAND_60GHZ:
|
||||||
|
if (chan < 7)
|
||||||
|
return 56160 + chan * 2160;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
return 0; /* not supported */
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ieee80211_channel_to_frequency);
|
||||||
|
|
||||||
|
int ieee80211_frequency_to_channel(int freq)
|
||||||
|
{
|
||||||
|
/* see 802.11 17.3.8.3.2 and Annex J */
|
||||||
|
if (freq == 2484)
|
||||||
|
return 14;
|
||||||
|
else if (freq < 2484)
|
||||||
|
return (freq - 2407) / 5;
|
||||||
|
else if (freq >= 4910 && freq <= 4980)
|
||||||
|
return (freq - 4000) / 5;
|
||||||
|
else if (freq <= 45000) /* DMG band lower limit */
|
||||||
|
return (freq - 5000) / 5;
|
||||||
|
else if (freq >= 58320 && freq <= 70200)
|
||||||
|
return (freq - 56160) / 2160;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ieee80211_frequency_to_channel);
|
|
@ -0,0 +1,309 @@
|
||||||
|
/*
|
||||||
|
* 802.11 device and configuration interface
|
||||||
|
*
|
||||||
|
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||||
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
|
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2018-2019 Intel Corporation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_CFG80211_H__
|
||||||
|
#define __USERSPACE_CFG80211_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "kernel/bits.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/nl80211.h"
|
||||||
|
#include "kernel/ieee80211.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_channel - channel definition
|
||||||
|
*
|
||||||
|
* This structure describes a single channel for use
|
||||||
|
* with cfg80211.
|
||||||
|
*
|
||||||
|
* @center_freq: center frequency in MHz
|
||||||
|
* @hw_value: hardware-specific value for the channel
|
||||||
|
* @flags: channel flags from &enum ieee80211_channel_flags.
|
||||||
|
* @orig_flags: channel flags at registration time, used by regulatory
|
||||||
|
* code to support devices with additional restrictions
|
||||||
|
* @band: band this channel belongs to.
|
||||||
|
* @max_antenna_gain: maximum antenna gain in dBi
|
||||||
|
* @max_power: maximum transmission power (in dBm)
|
||||||
|
* @max_reg_power: maximum regulatory transmission power (in dBm)
|
||||||
|
* @beacon_found: helper to regulatory code to indicate when a beacon
|
||||||
|
* has been found on this channel. Use regulatory_hint_found_beacon()
|
||||||
|
* to enable this, this is useful only on 5 GHz band.
|
||||||
|
* @orig_mag: internal use
|
||||||
|
* @orig_mpwr: internal use
|
||||||
|
* @dfs_state: current state of this channel. Only relevant if radar is required
|
||||||
|
* on this channel.
|
||||||
|
* @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
|
||||||
|
* @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
|
||||||
|
*/
|
||||||
|
struct ieee80211_channel {
|
||||||
|
enum nl80211_band band;
|
||||||
|
u32 center_freq;
|
||||||
|
u16 hw_value;
|
||||||
|
u32 flags;
|
||||||
|
int max_antenna_gain;
|
||||||
|
int max_power;
|
||||||
|
int max_reg_power;
|
||||||
|
bool beacon_found;
|
||||||
|
u32 orig_flags;
|
||||||
|
int orig_mag, orig_mpwr;
|
||||||
|
enum nl80211_dfs_state dfs_state;
|
||||||
|
unsigned long dfs_state_entered;
|
||||||
|
unsigned int dfs_cac_ms;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cfg80211_chan_def - channel definition
|
||||||
|
* @chan: the (control) channel
|
||||||
|
* @width: channel width
|
||||||
|
* @center_freq1: center frequency of first segment
|
||||||
|
* @center_freq2: center frequency of second segment
|
||||||
|
* (only with 80+80 MHz)
|
||||||
|
*/
|
||||||
|
struct cfg80211_chan_def {
|
||||||
|
struct ieee80211_channel *chan;
|
||||||
|
enum nl80211_chan_width width;
|
||||||
|
u32 center_freq1;
|
||||||
|
u32 center_freq2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
/**
|
||||||
|
* struct ieee80211_rate - bitrate definition
|
||||||
|
*
|
||||||
|
* This structure describes a bitrate that an 802.11 PHY can
|
||||||
|
* operate with. The two values @hw_value and @hw_value_short
|
||||||
|
* are only for driver use when pointers to this structure are
|
||||||
|
* passed around.
|
||||||
|
*
|
||||||
|
* @flags: rate-specific flags
|
||||||
|
* @bitrate: bitrate in units of 100 Kbps
|
||||||
|
* @hw_value: driver/hardware value for this rate
|
||||||
|
* @hw_value_short: driver/hardware value for this rate when
|
||||||
|
* short preamble is used
|
||||||
|
*/
|
||||||
|
struct ieee80211_rate {
|
||||||
|
u32 flags;
|
||||||
|
u16 bitrate;
|
||||||
|
u16 hw_value, hw_value_short;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_sta_ht_cap - STA's HT capabilities
|
||||||
|
*
|
||||||
|
* This structure describes most essential parameters needed
|
||||||
|
* to describe 802.11n HT capabilities for an STA.
|
||||||
|
*
|
||||||
|
* @ht_supported: is HT supported by the STA
|
||||||
|
* @cap: HT capabilities map as described in 802.11n spec
|
||||||
|
* @ampdu_factor: Maximum A-MPDU length factor
|
||||||
|
* @ampdu_density: Minimum A-MPDU spacing
|
||||||
|
* @mcs: Supported MCS rates
|
||||||
|
*/
|
||||||
|
struct ieee80211_sta_ht_cap {
|
||||||
|
u16 cap; /* use IEEE80211_HT_CAP_ */
|
||||||
|
bool ht_supported;
|
||||||
|
u8 ampdu_factor;
|
||||||
|
u8 ampdu_density;
|
||||||
|
struct ieee80211_mcs_info mcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_sta_vht_cap - STA's VHT capabilities
|
||||||
|
*
|
||||||
|
* This structure describes most essential parameters needed
|
||||||
|
* to describe 802.11ac VHT capabilities for an STA.
|
||||||
|
*
|
||||||
|
* @vht_supported: is VHT supported by the STA
|
||||||
|
* @cap: VHT capabilities map as described in 802.11ac spec
|
||||||
|
* @vht_mcs: Supported VHT MCS rates
|
||||||
|
*/
|
||||||
|
struct ieee80211_sta_vht_cap {
|
||||||
|
bool vht_supported;
|
||||||
|
u32 cap; /* use IEEE80211_VHT_CAP_ */
|
||||||
|
struct ieee80211_vht_mcs_info vht_mcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IEEE80211_HE_PPE_THRES_MAX_LEN 25
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_sta_he_cap - STA's HE capabilities
|
||||||
|
*
|
||||||
|
* This structure describes most essential parameters needed
|
||||||
|
* to describe 802.11ax HE capabilities for a STA.
|
||||||
|
*
|
||||||
|
* @has_he: true iff HE data is valid.
|
||||||
|
* @he_cap_elem: Fixed portion of the HE capabilities element.
|
||||||
|
* @he_mcs_nss_supp: The supported NSS/MCS combinations.
|
||||||
|
* @ppe_thres: Holds the PPE Thresholds data.
|
||||||
|
*/
|
||||||
|
struct ieee80211_sta_he_cap {
|
||||||
|
bool has_he;
|
||||||
|
struct ieee80211_he_cap_elem he_cap_elem;
|
||||||
|
struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp;
|
||||||
|
u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IEEE80211_MAX_CHAINS 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum station_info_rate_flags - bitrate info flags
|
||||||
|
*
|
||||||
|
* Used by the driver to indicate the specific rate transmission
|
||||||
|
* type for 802.11n transmissions.
|
||||||
|
*
|
||||||
|
* @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
|
||||||
|
* @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
|
||||||
|
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
|
||||||
|
* @RATE_INFO_FLAGS_60G: 60GHz MCS
|
||||||
|
* @RATE_INFO_FLAGS_HE_MCS: HE MCS information
|
||||||
|
*/
|
||||||
|
enum rate_info_flags {
|
||||||
|
RATE_INFO_FLAGS_MCS = BIT(0),
|
||||||
|
RATE_INFO_FLAGS_VHT_MCS = BIT(1),
|
||||||
|
RATE_INFO_FLAGS_SHORT_GI = BIT(2),
|
||||||
|
RATE_INFO_FLAGS_60G = BIT(3),
|
||||||
|
RATE_INFO_FLAGS_HE_MCS = BIT(4),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum rate_info_bw - rate bandwidth information
|
||||||
|
*
|
||||||
|
* Used by the driver to indicate the rate bandwidth.
|
||||||
|
*
|
||||||
|
* @RATE_INFO_BW_5: 5 MHz bandwidth
|
||||||
|
* @RATE_INFO_BW_10: 10 MHz bandwidth
|
||||||
|
* @RATE_INFO_BW_20: 20 MHz bandwidth
|
||||||
|
* @RATE_INFO_BW_40: 40 MHz bandwidth
|
||||||
|
* @RATE_INFO_BW_80: 80 MHz bandwidth
|
||||||
|
* @RATE_INFO_BW_160: 160 MHz bandwidth
|
||||||
|
* @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation
|
||||||
|
*/
|
||||||
|
enum rate_info_bw {
|
||||||
|
RATE_INFO_BW_20 = 0,
|
||||||
|
RATE_INFO_BW_5,
|
||||||
|
RATE_INFO_BW_10,
|
||||||
|
RATE_INFO_BW_40,
|
||||||
|
RATE_INFO_BW_80,
|
||||||
|
RATE_INFO_BW_160,
|
||||||
|
RATE_INFO_BW_HE_RU,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct rate_info - bitrate information
|
||||||
|
*
|
||||||
|
* Information about a receiving or transmitting bitrate
|
||||||
|
*
|
||||||
|
* @flags: bitflag of flags from &enum rate_info_flags
|
||||||
|
* @mcs: mcs index if struct describes an HT/VHT/HE rate
|
||||||
|
* @legacy: bitrate in 100kbit/s for 802.11abg
|
||||||
|
* @nss: number of streams (VHT & HE only)
|
||||||
|
* @bw: bandwidth (from &enum rate_info_bw)
|
||||||
|
* @he_gi: HE guard interval (from &enum nl80211_he_gi)
|
||||||
|
* @he_dcm: HE DCM value
|
||||||
|
* @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc,
|
||||||
|
* only valid if bw is %RATE_INFO_BW_HE_RU)
|
||||||
|
*/
|
||||||
|
struct rate_info {
|
||||||
|
u8 flags;
|
||||||
|
u8 mcs;
|
||||||
|
u16 legacy;
|
||||||
|
u8 nss;
|
||||||
|
u8 bw;
|
||||||
|
u8 he_gi;
|
||||||
|
u8 he_dcm;
|
||||||
|
u8 he_ru_alloc;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_channel_to_frequency - convert channel number to frequency
|
||||||
|
* @chan: channel number
|
||||||
|
* @band: band, necessary due to channel number overlap
|
||||||
|
* Return: The corresponding frequency (in MHz), or 0 if the conversion failed.
|
||||||
|
*/
|
||||||
|
int ieee80211_channel_to_frequency(int chan, enum nl80211_band band);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_frequency_to_channel - convert frequency to channel number
|
||||||
|
* @freq: center frequency
|
||||||
|
* Return: The corresponding channel, or 0 if the conversion failed.
|
||||||
|
*/
|
||||||
|
int ieee80211_frequency_to_channel(int freq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ieee80211_rate_flags - rate flags
|
||||||
|
*
|
||||||
|
* Hardware/specification flags for rates. These are structured
|
||||||
|
* in a way that allows using the same bitrate structure for
|
||||||
|
* different bands/PHY modes.
|
||||||
|
*
|
||||||
|
* @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short
|
||||||
|
* preamble on this bitrate; only relevant in 2.4GHz band and
|
||||||
|
* with CCK rates.
|
||||||
|
* @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate
|
||||||
|
* when used with 802.11a (on the 5 GHz band); filled by the
|
||||||
|
* core code when registering the wiphy.
|
||||||
|
* @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate
|
||||||
|
* when used with 802.11b (on the 2.4 GHz band); filled by the
|
||||||
|
* core code when registering the wiphy.
|
||||||
|
* @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate
|
||||||
|
* when used with 802.11g (on the 2.4 GHz band); filled by the
|
||||||
|
* core code when registering the wiphy.
|
||||||
|
* @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode.
|
||||||
|
* @IEEE80211_RATE_SUPPORTS_5MHZ: Rate can be used in 5 MHz mode
|
||||||
|
* @IEEE80211_RATE_SUPPORTS_10MHZ: Rate can be used in 10 MHz mode
|
||||||
|
*/
|
||||||
|
enum ieee80211_rate_flags {
|
||||||
|
IEEE80211_RATE_SHORT_PREAMBLE = 1<<0,
|
||||||
|
IEEE80211_RATE_MANDATORY_A = 1<<1,
|
||||||
|
IEEE80211_RATE_MANDATORY_B = 1<<2,
|
||||||
|
IEEE80211_RATE_MANDATORY_G = 1<<3,
|
||||||
|
IEEE80211_RATE_ERP_G = 1<<4,
|
||||||
|
IEEE80211_RATE_SUPPORTS_5MHZ = 1<<5,
|
||||||
|
IEEE80211_RATE_SUPPORTS_10MHZ = 1<<6,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_supported_band - frequency band definition
|
||||||
|
*
|
||||||
|
* This structure describes a frequency band a wiphy
|
||||||
|
* is able to operate in.
|
||||||
|
*
|
||||||
|
* @channels: Array of channels the hardware can operate in
|
||||||
|
* in this band.
|
||||||
|
* @band: the band this structure represents
|
||||||
|
* @n_channels: Number of channels in @channels
|
||||||
|
* @bitrates: Array of bitrates the hardware can operate with
|
||||||
|
* in this band. Must be sorted to give a valid "supported
|
||||||
|
* rates" IE, i.e. CCK rates first, then OFDM.
|
||||||
|
* @n_bitrates: Number of bitrates in @bitrates
|
||||||
|
* @ht_cap: HT capabilities in this band
|
||||||
|
* @vht_cap: VHT capabilities in this band
|
||||||
|
* @n_iftype_data: number of iftype data entries
|
||||||
|
* @iftype_data: interface type data entries. Note that the bits in
|
||||||
|
* @types_mask inside this structure cannot overlap (i.e. only
|
||||||
|
* one occurrence of each type is allowed across all instances of
|
||||||
|
* iftype_data).
|
||||||
|
*/
|
||||||
|
struct ieee80211_supported_band {
|
||||||
|
struct ieee80211_channel *channels;
|
||||||
|
struct ieee80211_rate *bitrates;
|
||||||
|
enum nl80211_band band;
|
||||||
|
int n_channels;
|
||||||
|
int n_bitrates;
|
||||||
|
struct ieee80211_sta_ht_cap ht_cap;
|
||||||
|
struct ieee80211_sta_vht_cap vht_cap;
|
||||||
|
u16 n_iftype_data;
|
||||||
|
const struct ieee80211_sband_iftype_data *iftype_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_CFG80211_H */
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* linux/lib/crc-ccitt.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "crc_ccit.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This mysterious table is just the CRC of each possible byte. It can be
|
||||||
|
* computed using the standard bit-at-a-time methods. The polynomial can
|
||||||
|
* be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12.
|
||||||
|
* Add the implicit x^16, and you have the standard CRC-CCITT.
|
||||||
|
*/
|
||||||
|
u16 const crc_ccitt_table[256] = {
|
||||||
|
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
||||||
|
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
||||||
|
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
||||||
|
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
||||||
|
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
||||||
|
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
||||||
|
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
||||||
|
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
||||||
|
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
||||||
|
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
||||||
|
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
||||||
|
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
||||||
|
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
||||||
|
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
||||||
|
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
||||||
|
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
||||||
|
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
||||||
|
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
||||||
|
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
||||||
|
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
||||||
|
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
||||||
|
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
||||||
|
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
||||||
|
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
||||||
|
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
||||||
|
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
||||||
|
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
||||||
|
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
||||||
|
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
||||||
|
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
||||||
|
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
||||||
|
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar table to calculate CRC16 variant known as CRC-CCITT-FALSE
|
||||||
|
* Reflected bits order, does not augment final value.
|
||||||
|
*/
|
||||||
|
u16 const crc_ccitt_false_table[256] = {
|
||||||
|
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||||
|
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||||
|
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||||
|
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||||
|
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
|
||||||
|
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||||
|
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
|
||||||
|
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||||
|
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||||
|
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||||
|
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
|
||||||
|
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||||
|
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
|
||||||
|
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||||
|
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
|
||||||
|
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||||
|
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
|
||||||
|
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||||
|
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
|
||||||
|
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||||
|
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
|
||||||
|
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||||
|
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
|
||||||
|
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||||
|
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
|
||||||
|
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||||
|
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||||
|
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||||
|
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
|
||||||
|
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
|
||||||
|
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
|
||||||
|
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* crc_ccitt - recompute the CRC (CRC-CCITT variant) for the data
|
||||||
|
* buffer
|
||||||
|
* @crc: previous CRC value
|
||||||
|
* @buffer: data pointer
|
||||||
|
* @len: number of bytes in the buffer
|
||||||
|
*/
|
||||||
|
u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)
|
||||||
|
{
|
||||||
|
while (len--)
|
||||||
|
crc = crc_ccitt_byte(crc, *buffer++);
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* crc_ccitt_false - recompute the CRC (CRC-CCITT-FALSE variant)
|
||||||
|
* for the data buffer
|
||||||
|
* @crc: previous CRC value
|
||||||
|
* @buffer: data pointer
|
||||||
|
* @len: number of bytes in the buffer
|
||||||
|
*/
|
||||||
|
u16 crc_ccitt_false(u16 crc, u8 const *buffer, size_t len)
|
||||||
|
{
|
||||||
|
while (len--)
|
||||||
|
crc = crc_ccitt_false_byte(crc, *buffer++);
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_CCIT_H__
|
||||||
|
#define __USERSPACE_CCIT_H__
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
extern u16 const crc_ccitt_table[256];
|
||||||
|
extern u16 const crc_ccitt_false_table[256];
|
||||||
|
|
||||||
|
extern u16 crc_ccitt(u16 crc, const u8 *buffer, size_t len);
|
||||||
|
extern u16 crc_ccitt_false(u16 crc, const u8 *buffer, size_t len);
|
||||||
|
|
||||||
|
static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
|
||||||
|
{
|
||||||
|
return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u16 crc_ccitt_false_byte(u16 crc, const u8 c)
|
||||||
|
{
|
||||||
|
return (crc << 8) ^ crc_ccitt_false_table[(crc >> 8) ^ c];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_CCIT_H */
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_ENDIAN_H__
|
||||||
|
#define __USERSPACE_ENDIAN_H__
|
||||||
|
|
||||||
|
/** compatibility header for endian.h
|
||||||
|
* This is a simple compatibility shim to convert
|
||||||
|
* BSD/Linux endian macros to the Mac OS X equivalents.
|
||||||
|
* It is public domain.
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* Derived from
|
||||||
|
*
|
||||||
|
* https://gist.githubusercontent.com/yinyin/2027912/raw/6b3e394dc6a37817410d66d6ba4d7cd6b8d5d03d/endian.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__)) && !defined(__WINDOWS__)
|
||||||
|
#define __WINDOWS__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <libkern/OSByteOrder.h>
|
||||||
|
|
||||||
|
#define htobe16(x) OSSwapHostToBigInt16(x)
|
||||||
|
#define htole16(x) OSSwapHostToLittleInt16(x)
|
||||||
|
#define be16toh(x) OSSwapBigToHostInt16(x)
|
||||||
|
#define le16toh(x) OSSwapLittleToHostInt16(x)
|
||||||
|
|
||||||
|
#define htobe32(x) OSSwapHostToBigInt32(x)
|
||||||
|
#define htole32(x) OSSwapHostToLittleInt32(x)
|
||||||
|
#define be32toh(x) OSSwapBigToHostInt32(x)
|
||||||
|
#define le32toh(x) OSSwapLittleToHostInt32(x)
|
||||||
|
|
||||||
|
#define htobe64(x) OSSwapHostToBigInt64(x)
|
||||||
|
#define htole64(x) OSSwapHostToLittleInt64(x)
|
||||||
|
#define be64toh(x) OSSwapBigToHostInt64(x)
|
||||||
|
#define le64toh(x) OSSwapLittleToHostInt64(x)
|
||||||
|
|
||||||
|
#elif defined(__WINDOWS__)
|
||||||
|
|
||||||
|
#include <winsock.h>
|
||||||
|
|
||||||
|
#define htobe16(x) htons(x)
|
||||||
|
#define htole16(x) (x)
|
||||||
|
#define be16toh(x) ntohs(x)
|
||||||
|
#define le16toh(x) (x)
|
||||||
|
|
||||||
|
#define htobe32(x) htonl(x)
|
||||||
|
#define htole32(x) (x)
|
||||||
|
#define be32toh(x) ntohl(x)
|
||||||
|
#define le32toh(x) (x)
|
||||||
|
|
||||||
|
#define htobe64(x) htonll(x)
|
||||||
|
#define htole64(x) (x)
|
||||||
|
#define be64toh(x) ntohll(x)
|
||||||
|
#define le64toh(x) (x)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <endian.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define cpu_to_le16(x) \
|
||||||
|
htole16(x)
|
||||||
|
#define le16_to_cpu(x) \
|
||||||
|
le16toh(x)
|
||||||
|
|
||||||
|
#define cpu_to_le32(x) \
|
||||||
|
htole32(x)
|
||||||
|
#define le32_to_cpu(x) \
|
||||||
|
le32toh(x)
|
||||||
|
|
||||||
|
#define cpu_to_be16(x) \
|
||||||
|
htobe16(x)
|
||||||
|
#define be16_to_cpu(x) \
|
||||||
|
be16toh(x)
|
||||||
|
|
||||||
|
#define cpu_to_be32(x) \
|
||||||
|
htobe32(x)
|
||||||
|
#define be32_to_cpu(x) \
|
||||||
|
be32toh(x)
|
||||||
|
|
||||||
|
#endif /* ifndef ENDIAN_H */
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
* INET An implementation of the TCP/IP protocol suite for the LINUX
|
||||||
|
* operating system. NET is implemented using the BSD Socket
|
||||||
|
* interface as the means of communication with the user level.
|
||||||
|
*
|
||||||
|
* Definitions for the Ethernet handlers.
|
||||||
|
*
|
||||||
|
* Version: @(#)eth.h 1.0.4 05/13/93
|
||||||
|
*
|
||||||
|
* Authors: Ross Biro
|
||||||
|
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
|
||||||
|
*
|
||||||
|
* Relocated to include/linux where it belongs by Alan Cox
|
||||||
|
* <gw4pts@gw4pts.ampr.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_ETHERDEVICE_H__
|
||||||
|
#define __USERSPACE_ETHERDEVICE_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "kernel/endian.h"
|
||||||
|
#include "kernel/if_ether.h"
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
/* Reserved Ethernet Addresses per IEEE 802.1Q */
|
||||||
|
static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
|
||||||
|
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
|
||||||
|
#define eth_stp_addr eth_reserved_addr_base
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is_link_local_ether_addr - Determine if given Ethernet address is link-local
|
||||||
|
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||||
|
*
|
||||||
|
* Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
|
||||||
|
* IEEE 802.1Q 8.6.3 Frame filtering.
|
||||||
|
*
|
||||||
|
* Please note: addr must be aligned to u16.
|
||||||
|
*/
|
||||||
|
static inline bool is_link_local_ether_addr(const u8 *addr)
|
||||||
|
{
|
||||||
|
__be16 *a = (__be16 *)addr;
|
||||||
|
static const __be16 *b = (const __be16 *)eth_reserved_addr_base;
|
||||||
|
__be16 m = cpu_to_be16(0xfff0);
|
||||||
|
|
||||||
|
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||||
|
return (((*(const u32 *)addr) ^ (*(const u32 *)b)) |
|
||||||
|
(__force int)((a[2] ^ b[2]) & m)) == 0;
|
||||||
|
#else
|
||||||
|
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is_zero_ether_addr - Determine if give Ethernet address is all zeros.
|
||||||
|
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||||
|
*
|
||||||
|
* Return true if the address is all zeroes.
|
||||||
|
*
|
||||||
|
* Please note: addr must be aligned to u16.
|
||||||
|
*/
|
||||||
|
static inline bool is_zero_ether_addr(const u8 *addr)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||||
|
return ((*(const u32 *)addr) | (*(const u16 *)(addr + 4))) == 0;
|
||||||
|
#else
|
||||||
|
return (*(const u16 *)(addr + 0) |
|
||||||
|
*(const u16 *)(addr + 2) |
|
||||||
|
*(const u16 *)(addr + 4)) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_ETHERDEVICE_H */
|
|
@ -0,0 +1,310 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* IEEE 802.11 defines
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
|
||||||
|
* <jkmaline@cc.hut.fi>
|
||||||
|
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
|
||||||
|
* Copyright (c) 2005, Devicescape Software, Inc.
|
||||||
|
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
|
||||||
|
* Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||||
|
* Copyright (c) 2016 - 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (c) 2018 - 2019 Intel Corporation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_IEEE80211_H__
|
||||||
|
#define __USERSPACE_IEEE80211_H__
|
||||||
|
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/nl80211.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
#define WLAN_SA_QUERY_TR_ID_LEN 2
|
||||||
|
#define WLAN_MEMBERSHIP_LEN 8
|
||||||
|
#define WLAN_USER_POSITION_LEN 16
|
||||||
|
|
||||||
|
/* miscellaneous IEEE 802.11 constants */
|
||||||
|
#define IEEE80211_MAX_FRAG_THRESHOLD 2352
|
||||||
|
#define IEEE80211_MAX_RTS_THRESHOLD 2353
|
||||||
|
#define IEEE80211_MAX_AID 2007
|
||||||
|
#define IEEE80211_MAX_TIM_LEN 251
|
||||||
|
#define IEEE80211_MAX_MESH_PEERINGS 63
|
||||||
|
/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
|
||||||
|
6.2.1.1.2.
|
||||||
|
|
||||||
|
802.11e clarifies the figure in section 7.1.2. The frame body is
|
||||||
|
up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */
|
||||||
|
#define IEEE80211_MAX_DATA_LEN 2304
|
||||||
|
/* 802.11ad extends maximum MSDU size for DMG (freq > 40Ghz) networks
|
||||||
|
* to 7920 bytes, see 8.2.3 General frame format
|
||||||
|
*/
|
||||||
|
#define IEEE80211_MAX_DATA_LEN_DMG 7920
|
||||||
|
/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */
|
||||||
|
#define IEEE80211_MAX_FRAME_LEN 2352
|
||||||
|
|
||||||
|
/* Maximal size of an A-MSDU that can be transported in a HT BA session */
|
||||||
|
#define IEEE80211_MAX_MPDU_LEN_HT_BA 4095
|
||||||
|
|
||||||
|
/* Maximal size of an A-MSDU */
|
||||||
|
#define IEEE80211_MAX_MPDU_LEN_HT_3839 3839
|
||||||
|
#define IEEE80211_MAX_MPDU_LEN_HT_7935 7935
|
||||||
|
|
||||||
|
#define IEEE80211_MAX_MPDU_LEN_VHT_3895 3895
|
||||||
|
#define IEEE80211_MAX_MPDU_LEN_VHT_7991 7991
|
||||||
|
#define IEEE80211_MAX_MPDU_LEN_VHT_11454 11454
|
||||||
|
|
||||||
|
#define IEEE80211_MAX_SSID_LEN 32
|
||||||
|
|
||||||
|
#define IEEE80211_MAX_MESH_ID_LEN 32
|
||||||
|
|
||||||
|
#define IEEE80211_FIRST_TSPEC_TSID 8
|
||||||
|
#define IEEE80211_NUM_TIDS 16
|
||||||
|
|
||||||
|
/* number of user priorities 802.11 uses */
|
||||||
|
#define IEEE80211_NUM_UPS 8
|
||||||
|
/* number of ACs */
|
||||||
|
#define IEEE80211_NUM_ACS 4
|
||||||
|
|
||||||
|
#define IEEE80211_QOS_CTL_LEN 2
|
||||||
|
/* 1d tag mask */
|
||||||
|
#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007
|
||||||
|
/* TID mask */
|
||||||
|
#define IEEE80211_QOS_CTL_TID_MASK 0x000f
|
||||||
|
/* EOSP */
|
||||||
|
#define IEEE80211_QOS_CTL_EOSP 0x0010
|
||||||
|
/* ACK policy */
|
||||||
|
#define IEEE80211_QOS_CTL_ACK_POLICY_NORMAL 0x0000
|
||||||
|
#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK 0x0020
|
||||||
|
#define IEEE80211_QOS_CTL_ACK_POLICY_NO_EXPL 0x0040
|
||||||
|
#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060
|
||||||
|
#define IEEE80211_QOS_CTL_ACK_POLICY_MASK 0x0060
|
||||||
|
/* A-MSDU 802.11n */
|
||||||
|
#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080
|
||||||
|
/* Mesh Control 802.11s */
|
||||||
|
#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100
|
||||||
|
|
||||||
|
/* Mesh Power Save Level */
|
||||||
|
#define IEEE80211_QOS_CTL_MESH_PS_LEVEL 0x0200
|
||||||
|
/* Mesh Receiver Service Period Initiated */
|
||||||
|
#define IEEE80211_QOS_CTL_RSPI 0x0400
|
||||||
|
|
||||||
|
/* U-APSD queue for WMM IEs sent by AP */
|
||||||
|
#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7)
|
||||||
|
#define IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK 0x0f
|
||||||
|
|
||||||
|
/* U-APSD queues for WMM IEs sent by STA */
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0)
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1)
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2)
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3)
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f
|
||||||
|
|
||||||
|
/* U-APSD max SP length for WMM IEs sent by STA */
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03
|
||||||
|
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5
|
||||||
|
|
||||||
|
#define IEEE80211_HT_CTL_LEN 4
|
||||||
|
|
||||||
|
/* 802.11 BAR control masks */
|
||||||
|
#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000
|
||||||
|
#define IEEE80211_BAR_CTRL_MULTI_TID 0x0002
|
||||||
|
#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004
|
||||||
|
#define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000
|
||||||
|
#define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12
|
||||||
|
|
||||||
|
#define IEEE80211_HT_MCS_MASK_LEN 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_mcs_info - MCS information
|
||||||
|
* @rx_mask: RX mask
|
||||||
|
* @rx_highest: highest supported RX rate. If set represents
|
||||||
|
* the highest supported RX data rate in units of 1 Mbps.
|
||||||
|
* If this field is 0 this value should not be used to
|
||||||
|
* consider the highest RX data rate supported.
|
||||||
|
* @tx_params: TX parameters
|
||||||
|
*/
|
||||||
|
struct ieee80211_mcs_info {
|
||||||
|
u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN];
|
||||||
|
__le16 rx_highest;
|
||||||
|
u8 tx_params;
|
||||||
|
u8 reserved[3];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* 802.11n HT capability MSC set */
|
||||||
|
#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff
|
||||||
|
#define IEEE80211_HT_MCS_TX_DEFINED 0x01
|
||||||
|
#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02
|
||||||
|
/* value 0 == 1 stream etc */
|
||||||
|
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C
|
||||||
|
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2
|
||||||
|
#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4
|
||||||
|
#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 802.11n D5.0 20.3.5 / 20.6 says:
|
||||||
|
* - indices 0 to 7 and 32 are single spatial stream
|
||||||
|
* - 8 to 31 are multiple spatial streams using equal modulation
|
||||||
|
* [8..15 for two streams, 16..23 for three and 24..31 for four]
|
||||||
|
* - remainder are multiple spatial streams using unequal modulation
|
||||||
|
*/
|
||||||
|
#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33
|
||||||
|
#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \
|
||||||
|
(IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_ht_cap - HT capabilities
|
||||||
|
*
|
||||||
|
* This structure is the "HT capabilities element" as
|
||||||
|
* described in 802.11n D5.0 7.3.2.57
|
||||||
|
*/
|
||||||
|
struct ieee80211_ht_cap {
|
||||||
|
__le16 cap_info;
|
||||||
|
u8 ampdu_params_info;
|
||||||
|
|
||||||
|
/* 16 bytes MCS information */
|
||||||
|
struct ieee80211_mcs_info mcs;
|
||||||
|
|
||||||
|
__le16 extended_ht_cap_info;
|
||||||
|
__le32 tx_BF_cap_info;
|
||||||
|
u8 antenna_selection_info;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* 802.11n HT capabilities masks (for cap_info) */
|
||||||
|
#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
|
||||||
|
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
|
||||||
|
#define IEEE80211_HT_CAP_SM_PS 0x000C
|
||||||
|
#define IEEE80211_HT_CAP_SM_PS_SHIFT 2
|
||||||
|
#define IEEE80211_HT_CAP_GRN_FLD 0x0010
|
||||||
|
#define IEEE80211_HT_CAP_SGI_20 0x0020
|
||||||
|
#define IEEE80211_HT_CAP_SGI_40 0x0040
|
||||||
|
#define IEEE80211_HT_CAP_TX_STBC 0x0080
|
||||||
|
#define IEEE80211_HT_CAP_RX_STBC 0x0300
|
||||||
|
#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8
|
||||||
|
#define IEEE80211_HT_CAP_DELAY_BA 0x0400
|
||||||
|
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
|
||||||
|
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
|
||||||
|
#define IEEE80211_HT_CAP_RESERVED 0x2000
|
||||||
|
#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000
|
||||||
|
#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000
|
||||||
|
|
||||||
|
/* 802.11n HT extended capabilities masks (for extended_ht_cap_info) */
|
||||||
|
#define IEEE80211_HT_EXT_CAP_PCO 0x0001
|
||||||
|
#define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006
|
||||||
|
#define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1
|
||||||
|
#define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300
|
||||||
|
#define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8
|
||||||
|
#define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400
|
||||||
|
#define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800
|
||||||
|
|
||||||
|
/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */
|
||||||
|
#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03
|
||||||
|
#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C
|
||||||
|
#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_vht_mcs_info - VHT MCS information
|
||||||
|
* @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams
|
||||||
|
* @rx_highest: Indicates highest long GI VHT PPDU data rate
|
||||||
|
* STA can receive. Rate expressed in units of 1 Mbps.
|
||||||
|
* If this field is 0 this value should not be used to
|
||||||
|
* consider the highest RX data rate supported.
|
||||||
|
* The top 3 bits of this field indicate the Maximum NSTS,total
|
||||||
|
* (a beamformee capability.)
|
||||||
|
* @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
|
||||||
|
* @tx_highest: Indicates highest long GI VHT PPDU data rate
|
||||||
|
* STA can transmit. Rate expressed in units of 1 Mbps.
|
||||||
|
* If this field is 0 this value should not be used to
|
||||||
|
* consider the highest TX data rate supported.
|
||||||
|
* The top 2 bits of this field are reserved, the
|
||||||
|
* 3rd bit from the top indiciates VHT Extended NSS BW
|
||||||
|
* Capability.
|
||||||
|
*/
|
||||||
|
struct ieee80211_vht_mcs_info {
|
||||||
|
__le16 rx_mcs_map;
|
||||||
|
__le16 rx_highest;
|
||||||
|
__le16 tx_mcs_map;
|
||||||
|
__le16 tx_highest;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_he_cap_elem - HE capabilities element
|
||||||
|
*
|
||||||
|
* This structure is the "HE capabilities element" fixed fields as
|
||||||
|
* described in P802.11ax_D4.0 section 9.4.2.242.2 and 9.4.2.242.3
|
||||||
|
*/
|
||||||
|
struct ieee80211_he_cap_elem {
|
||||||
|
u8 mac_cap_info[6];
|
||||||
|
u8 phy_cap_info[11];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ieee80211_he_mcs_support - HE MCS support definitions
|
||||||
|
* @IEEE80211_HE_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the
|
||||||
|
* number of streams
|
||||||
|
* @IEEE80211_HE_MCS_SUPPORT_0_9: MCSes 0-9 are supported
|
||||||
|
* @IEEE80211_HE_MCS_SUPPORT_0_11: MCSes 0-11 are supported
|
||||||
|
* @IEEE80211_HE_MCS_NOT_SUPPORTED: This number of streams isn't supported
|
||||||
|
*
|
||||||
|
* These definitions are used in each 2-bit subfield of the rx_mcs_*
|
||||||
|
* and tx_mcs_* fields of &struct ieee80211_he_mcs_nss_supp, which are
|
||||||
|
* both split into 8 subfields by number of streams. These values indicate
|
||||||
|
* which MCSes are supported for the number of streams the value appears
|
||||||
|
* for.
|
||||||
|
*/
|
||||||
|
enum ieee80211_he_mcs_support {
|
||||||
|
IEEE80211_HE_MCS_SUPPORT_0_7 = 0,
|
||||||
|
IEEE80211_HE_MCS_SUPPORT_0_9 = 1,
|
||||||
|
IEEE80211_HE_MCS_SUPPORT_0_11 = 2,
|
||||||
|
IEEE80211_HE_MCS_NOT_SUPPORTED = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_he_mcs_nss_supp - HE Tx/Rx HE MCS NSS Support Field
|
||||||
|
*
|
||||||
|
* This structure holds the data required for the Tx/Rx HE MCS NSS Support Field
|
||||||
|
* described in P802.11ax_D2.0 section 9.4.2.237.4
|
||||||
|
*
|
||||||
|
* @rx_mcs_80: Rx MCS map 2 bits for each stream, total 8 streams, for channel
|
||||||
|
* widths less than 80MHz.
|
||||||
|
* @tx_mcs_80: Tx MCS map 2 bits for each stream, total 8 streams, for channel
|
||||||
|
* widths less than 80MHz.
|
||||||
|
* @rx_mcs_160: Rx MCS map 2 bits for each stream, total 8 streams, for channel
|
||||||
|
* width 160MHz.
|
||||||
|
* @tx_mcs_160: Tx MCS map 2 bits for each stream, total 8 streams, for channel
|
||||||
|
* width 160MHz.
|
||||||
|
* @rx_mcs_80p80: Rx MCS map 2 bits for each stream, total 8 streams, for
|
||||||
|
* channel width 80p80MHz.
|
||||||
|
* @tx_mcs_80p80: Tx MCS map 2 bits for each stream, total 8 streams, for
|
||||||
|
* channel width 80p80MHz.
|
||||||
|
*/
|
||||||
|
struct ieee80211_he_mcs_nss_supp {
|
||||||
|
__le16 rx_mcs_80;
|
||||||
|
__le16 tx_mcs_80;
|
||||||
|
__le16 rx_mcs_160;
|
||||||
|
__le16 tx_mcs_160;
|
||||||
|
__le16 rx_mcs_80p80;
|
||||||
|
__le16 tx_mcs_80p80;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* for operation_mode */
|
||||||
|
#define IEEE80211_HT_OP_MODE_PROTECTION 0x0003
|
||||||
|
#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0
|
||||||
|
#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1
|
||||||
|
#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2
|
||||||
|
#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3
|
||||||
|
#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004
|
||||||
|
#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010
|
||||||
|
#define IEEE80211_HT_OP_MODE_CCFS2_SHIFT 5
|
||||||
|
#define IEEE80211_HT_OP_MODE_CCFS2_MASK 0x1fe0
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_IEEE80211_H */
|
|
@ -0,0 +1,368 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (c) 2018-2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef __RADIOTAP_H
|
||||||
|
#define __RADIOTAP_H
|
||||||
|
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/le_byteshift.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee82011_radiotap_header - base radiotap header
|
||||||
|
*/
|
||||||
|
struct ieee80211_radiotap_header {
|
||||||
|
/**
|
||||||
|
* @it_version: radiotap version, always 0
|
||||||
|
*/
|
||||||
|
uint8_t it_version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it_pad: padding (or alignment)
|
||||||
|
*/
|
||||||
|
uint8_t it_pad;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it_len: overall radiotap header length
|
||||||
|
*/
|
||||||
|
__le16 it_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it_present: (first) present word
|
||||||
|
*/
|
||||||
|
__le32 it_present;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* version is always 0 */
|
||||||
|
#define PKTHDR_RADIOTAP_VERSION 0
|
||||||
|
|
||||||
|
/* see the radiotap website for the descriptions */
|
||||||
|
enum ieee80211_radiotap_presence {
|
||||||
|
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,
|
||||||
|
/* 18 is XChannel, but it's not defined yet */
|
||||||
|
IEEE80211_RADIOTAP_MCS = 19,
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
|
||||||
|
IEEE80211_RADIOTAP_VHT = 21,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP = 22,
|
||||||
|
IEEE80211_RADIOTAP_HE = 23,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU = 24,
|
||||||
|
IEEE80211_RADIOTAP_ZERO_LEN_PSDU = 26,
|
||||||
|
IEEE80211_RADIOTAP_LSIG = 27,
|
||||||
|
|
||||||
|
/* valid in every it_present bitmap, even vendor namespaces */
|
||||||
|
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
|
||||||
|
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
|
||||||
|
IEEE80211_RADIOTAP_EXT = 31
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for IEEE80211_RADIOTAP_FLAGS */
|
||||||
|
enum ieee80211_radiotap_flags {
|
||||||
|
IEEE80211_RADIOTAP_F_CFP = 0x01,
|
||||||
|
IEEE80211_RADIOTAP_F_SHORTPRE = 0x02,
|
||||||
|
IEEE80211_RADIOTAP_F_WEP = 0x04,
|
||||||
|
IEEE80211_RADIOTAP_F_FRAG = 0x08,
|
||||||
|
IEEE80211_RADIOTAP_F_FCS = 0x10,
|
||||||
|
IEEE80211_RADIOTAP_F_DATAPAD = 0x20,
|
||||||
|
IEEE80211_RADIOTAP_F_BADFCS = 0x40,
|
||||||
|
IEEE80211_RADIOTAP_F_SHORTGI = 0x80,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for IEEE80211_RADIOTAP_CHANNEL */
|
||||||
|
enum ieee80211_radiotap_channel_flags {
|
||||||
|
IEEE80211_CHAN_CCK = 0x0020,
|
||||||
|
IEEE80211_CHAN_OFDM = 0x0040,
|
||||||
|
IEEE80211_CHAN_2GHZ = 0x0080,
|
||||||
|
IEEE80211_CHAN_5GHZ = 0x0100,
|
||||||
|
IEEE80211_CHAN_DYN = 0x0400,
|
||||||
|
IEEE80211_CHAN_HALF = 0x4000,
|
||||||
|
IEEE80211_CHAN_QUARTER = 0x8000,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for IEEE80211_RADIOTAP_RX_FLAGS */
|
||||||
|
enum ieee80211_radiotap_rx_flags {
|
||||||
|
IEEE80211_RADIOTAP_F_RX_BADPLCP = 0x0002,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for IEEE80211_RADIOTAP_TX_FLAGS */
|
||||||
|
enum ieee80211_radiotap_tx_flags {
|
||||||
|
IEEE80211_RADIOTAP_F_TX_FAIL = 0x0001,
|
||||||
|
IEEE80211_RADIOTAP_F_TX_CTS = 0x0002,
|
||||||
|
IEEE80211_RADIOTAP_F_TX_RTS = 0x0004,
|
||||||
|
IEEE80211_RADIOTAP_F_TX_NOACK = 0x0008,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for IEEE80211_RADIOTAP_MCS "have" flags */
|
||||||
|
enum ieee80211_radiotap_mcs_have {
|
||||||
|
IEEE80211_RADIOTAP_MCS_HAVE_BW = 0x01,
|
||||||
|
IEEE80211_RADIOTAP_MCS_HAVE_MCS = 0x02,
|
||||||
|
IEEE80211_RADIOTAP_MCS_HAVE_GI = 0x04,
|
||||||
|
IEEE80211_RADIOTAP_MCS_HAVE_FMT = 0x08,
|
||||||
|
IEEE80211_RADIOTAP_MCS_HAVE_FEC = 0x10,
|
||||||
|
IEEE80211_RADIOTAP_MCS_HAVE_STBC = 0x20,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_mcs_flags {
|
||||||
|
IEEE80211_RADIOTAP_MCS_BW_MASK = 0x03,
|
||||||
|
IEEE80211_RADIOTAP_MCS_BW_20 = 0,
|
||||||
|
IEEE80211_RADIOTAP_MCS_BW_40 = 1,
|
||||||
|
IEEE80211_RADIOTAP_MCS_BW_20L = 2,
|
||||||
|
IEEE80211_RADIOTAP_MCS_BW_20U = 3,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_MCS_SGI = 0x04,
|
||||||
|
IEEE80211_RADIOTAP_MCS_FMT_GF = 0x08,
|
||||||
|
IEEE80211_RADIOTAP_MCS_FEC_LDPC = 0x10,
|
||||||
|
IEEE80211_RADIOTAP_MCS_STBC_MASK = 0x60,
|
||||||
|
IEEE80211_RADIOTAP_MCS_STBC_1 = 1,
|
||||||
|
IEEE80211_RADIOTAP_MCS_STBC_2 = 2,
|
||||||
|
IEEE80211_RADIOTAP_MCS_STBC_3 = 3,
|
||||||
|
IEEE80211_RADIOTAP_MCS_STBC_SHIFT = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for IEEE80211_RADIOTAP_AMPDU_STATUS */
|
||||||
|
enum ieee80211_radiotap_ampdu_flags {
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN = 0x0001,
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN = 0x0002,
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN = 0x0004,
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_IS_LAST = 0x0008,
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR = 0x0010,
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN = 0x0020,
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_EOF = 0x0040,
|
||||||
|
IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN = 0x0080,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for IEEE80211_RADIOTAP_VHT */
|
||||||
|
enum ieee80211_radiotap_vht_known {
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_STBC = 0x0001,
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA = 0x0002,
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_GI = 0x0004,
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS = 0x0008,
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM = 0x0010,
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED = 0x0020,
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH = 0x0040,
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID = 0x0080,
|
||||||
|
IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID = 0x0100,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_vht_flags {
|
||||||
|
IEEE80211_RADIOTAP_VHT_FLAG_STBC = 0x01,
|
||||||
|
IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA = 0x02,
|
||||||
|
IEEE80211_RADIOTAP_VHT_FLAG_SGI = 0x04,
|
||||||
|
IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 = 0x08,
|
||||||
|
IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM = 0x10,
|
||||||
|
IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED = 0x20,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_vht_coding {
|
||||||
|
IEEE80211_RADIOTAP_CODING_LDPC_USER0 = 0x01,
|
||||||
|
IEEE80211_RADIOTAP_CODING_LDPC_USER1 = 0x02,
|
||||||
|
IEEE80211_RADIOTAP_CODING_LDPC_USER2 = 0x04,
|
||||||
|
IEEE80211_RADIOTAP_CODING_LDPC_USER3 = 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* for IEEE80211_RADIOTAP_TIMESTAMP */
|
||||||
|
enum ieee80211_radiotap_timestamp_unit_spos {
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK = 0x000F,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS = 0x0000,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US = 0x0001,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS = 0x0003,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK = 0x00F0,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU = 0x0000,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ = 0x0010,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU = 0x0020,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU = 0x0030,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN = 0x00F0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_timestamp_flags {
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT = 0x00,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT = 0x01,
|
||||||
|
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ieee80211_radiotap_he {
|
||||||
|
__le16 data1, data2, data3, data4, data5, data6;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_he_bits {
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN = 0x0020,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW = 0x00c0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_20MHZ = 0,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_40MHZ = 1,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_80MHZ = 2,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_160MHZ = 3,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00,
|
||||||
|
IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ieee80211_radiotap_he_mu {
|
||||||
|
__le16 flags1, flags2;
|
||||||
|
u8 ru_ch1[4];
|
||||||
|
u8 ru_ch2[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_he_mu_bits {
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000,
|
||||||
|
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN= 0x0400,
|
||||||
|
IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_lsig_data1 {
|
||||||
|
IEEE80211_RADIOTAP_LSIG_DATA1_RATE_KNOWN = 0x0001,
|
||||||
|
IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN = 0x0002,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_lsig_data2 {
|
||||||
|
IEEE80211_RADIOTAP_LSIG_DATA2_RATE = 0x000f,
|
||||||
|
IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH = 0xfff0,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ieee80211_radiotap_lsig {
|
||||||
|
__le16 data1, data2;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ieee80211_radiotap_zero_len_psdu_type {
|
||||||
|
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING = 0,
|
||||||
|
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED = 1,
|
||||||
|
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR = 0xff,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ieee80211_get_radiotap_len - get radiotap header length
|
||||||
|
*/
|
||||||
|
static inline u16 ieee80211_get_radiotap_len(const char *data)
|
||||||
|
{
|
||||||
|
struct ieee80211_radiotap_header *hdr = (struct ieee80211_radiotap_header *)data;
|
||||||
|
|
||||||
|
return get_unaligned_le16(&hdr->it_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __RADIOTAP_H */
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
|
||||||
|
/*
|
||||||
|
* INET An implementation of the TCP/IP protocol suite for the LINUX
|
||||||
|
* operating system. INET is implemented using the BSD Socket
|
||||||
|
* interface as the means of communication with the user level.
|
||||||
|
*
|
||||||
|
* Global definitions for the Ethernet IEEE 802.3 interface.
|
||||||
|
*
|
||||||
|
* Version: @(#)if_ether.h 1.0.1a 02/08/94
|
||||||
|
*
|
||||||
|
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
|
||||||
|
* Donald Becker, <becker@super.org>
|
||||||
|
* Alan Cox, <alan@lxorguk.ukuu.org.uk>
|
||||||
|
* Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_IF_ETHER_H__
|
||||||
|
#define __USERSPACE_IF_ETHER_H__
|
||||||
|
|
||||||
|
#define ETH_ALEN 6
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_IF_ETHER_H */
|
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_KERNEL_H__
|
||||||
|
#define __USERSPACE_KERNEL_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define some kernel nomenclature and functions that we just transpose into
|
||||||
|
* normal gcc-isms, along with modified BUG_ON, WARN_ON, etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#define __packed __attribute__((packed))
|
||||||
|
#define __aligned(nr) __attribute__((aligned (nr)))
|
||||||
|
#else
|
||||||
|
#define __packed
|
||||||
|
#define __aligned(nr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __rcu
|
||||||
|
|
||||||
|
#ifndef __attribute_const__
|
||||||
|
#define __attribute_const__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
/* Hack all constant compares to be true for MSC */
|
||||||
|
#define __builtin_constant_p(x) (1)
|
||||||
|
|
||||||
|
/* Use ternary to simulate builtin choose expr */
|
||||||
|
#define __builtin_choose_expr(e, t, f) ((e) ? (t) : (f))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just test
|
||||||
|
*/
|
||||||
|
#define unlikely(x) (x)
|
||||||
|
|
||||||
|
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
|
||||||
|
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
|
||||||
|
|
||||||
|
/* Force a compilation error if a constant expression is not a power of 2 */
|
||||||
|
#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \
|
||||||
|
BUILD_BUG_ON(((n) & ((n) - 1)) != 0)
|
||||||
|
#define BUILD_BUG_ON_NOT_POWER_OF_2(n) \
|
||||||
|
BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
|
||||||
|
|
||||||
|
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
|
||||||
|
#define BUG() do { \
|
||||||
|
fprintf(stderr, "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
||||||
|
exit(-1); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define WARN_ONCE(condition, fmt, ...) \
|
||||||
|
do { if (condition) fprintf(stderr, "%s: WARNING - " fmt, __func__, ##__VA_ARGS__); } while (0)
|
||||||
|
#define WARN_ON_ONCE(condition) (condition)
|
||||||
|
#define WARN_ON(condition) do { if (unlikely(condition)) WARN(); } while (0)
|
||||||
|
#define WARN() do { \
|
||||||
|
fprintf(stderr, "WARNING: warning at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define READ_ONCE(x) (x)
|
||||||
|
#define WRITE_ONCE(t, v) ((t) = (v))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't currently do kernel mutexes; this could be re-def'd to pthread
|
||||||
|
* mutexes if we need to
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
#define mutex_lock(x) pthread_mutex_lock((x))
|
||||||
|
#define mutex_unlock(x) pthread_mutex_unlock((x))
|
||||||
|
#else
|
||||||
|
#define mutex_lock(x)
|
||||||
|
#define mutex_unlock(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just treat sleeps and delays as usleeps
|
||||||
|
*/
|
||||||
|
#define msleep(x) usleep(x * 1000)
|
||||||
|
#define udelay(x) usleep(x)
|
||||||
|
#define usleep_range(x, y) usleep(y)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified and simplified from the kernel macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __cmp(x, y, op) ((x) op (y) ? (x) : (y))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* min_t - return minimum of two values, using the specified type
|
||||||
|
* @type: data type to use
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
*/
|
||||||
|
#define min_t(type, x, y) __cmp((type)(x), (type)(y), <)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* max_t - return maximum of two values, using the specified type
|
||||||
|
* @type: data type to use
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
*/
|
||||||
|
#define max_t(type, x, y) __cmp((type)(x), (type)(y), >)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* max - return maximum of two values of the same or compatible types
|
||||||
|
* @x: first value
|
||||||
|
* @y: second value
|
||||||
|
*/
|
||||||
|
#define max(x, y) __cmp(x, y, >)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This looks more complex than it should be. But we need to
|
||||||
|
* get the type for the ~ right in round_down (it needs to be
|
||||||
|
* as wide as the result!), and we want to evaluate the macro
|
||||||
|
* arguments just once each.
|
||||||
|
*/
|
||||||
|
#define __round_mask(x, y) ((__typeof__(x))((y)-1))
|
||||||
|
/**
|
||||||
|
* round_up - round up to next specified power of 2
|
||||||
|
* @x: the value to round
|
||||||
|
* @y: multiple to round up to (must be a power of 2)
|
||||||
|
*
|
||||||
|
* Rounds @x up to next multiple of @y (which must be a power of 2).
|
||||||
|
* To perform arbitrary rounding up, use roundup() below.
|
||||||
|
*/
|
||||||
|
#ifndef round_up
|
||||||
|
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* round_down - round down to next specified power of 2
|
||||||
|
* @x: the value to round
|
||||||
|
* @y: multiple to round down to (must be a power of 2)
|
||||||
|
*
|
||||||
|
* Rounds @x down to next multiple of @y (which must be a power of 2).
|
||||||
|
* To perform arbitrary rounding down, use rounddown() below.
|
||||||
|
*/
|
||||||
|
#ifndef round_down
|
||||||
|
#define round_down(x, y) ((x) & ~__round_mask(x, y))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FIELD_SIZEOF - get the size of a struct's field
|
||||||
|
* @t: the target struct
|
||||||
|
* @f: the target struct's field
|
||||||
|
* Return: the size of @f in the struct definition without having a
|
||||||
|
* declared instance of @t.
|
||||||
|
*/
|
||||||
|
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
|
||||||
|
|
||||||
|
#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
|
||||||
|
|
||||||
|
#define DIV_ROUND_DOWN_ULL(ll, d) \
|
||||||
|
({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; })
|
||||||
|
|
||||||
|
#define DIV_ROUND_UP_ULL(ll, d) \
|
||||||
|
DIV_ROUND_DOWN_ULL((unsigned long long)(ll) + (d) - 1, (d))
|
||||||
|
|
||||||
|
#if BITS_PER_LONG == 32
|
||||||
|
# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP_ULL(ll, d)
|
||||||
|
#else
|
||||||
|
# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP(ll,d)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* roundup - round up to the next specified multiple
|
||||||
|
* @x: the value to up
|
||||||
|
* @y: multiple to round up to
|
||||||
|
*
|
||||||
|
* Rounds @x up to next multiple of @y. If @y will always be a power
|
||||||
|
* of 2, consider using the faster round_up().
|
||||||
|
*/
|
||||||
|
#define roundup(x, y) ( \
|
||||||
|
{ \
|
||||||
|
typeof(y) __y = y; \
|
||||||
|
(((x) + (__y - 1)) / __y) * __y; \
|
||||||
|
} \
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* rounddown - round down to next specified multiple
|
||||||
|
* @x: the value to round
|
||||||
|
* @y: multiple to round down to
|
||||||
|
*
|
||||||
|
* Rounds @x down to next multiple of @y. If @y will always be a power
|
||||||
|
* of 2, consider using the faster round_down().
|
||||||
|
*/
|
||||||
|
#define rounddown(x, y) ( \
|
||||||
|
{ \
|
||||||
|
typeof(x) __x = (x); \
|
||||||
|
__x - (__x % (y)); \
|
||||||
|
} \
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Divide positive or negative dividend by positive or negative divisor
|
||||||
|
* and round to closest integer. Result is undefined for negative
|
||||||
|
* divisors if the dividend variable type is unsigned and for negative
|
||||||
|
* dividends if the divisor variable type is unsigned.
|
||||||
|
*/
|
||||||
|
#define DIV_ROUND_CLOSEST(x, divisor)( \
|
||||||
|
{ \
|
||||||
|
typeof(x) __x = x; \
|
||||||
|
typeof(divisor) __d = divisor; \
|
||||||
|
(((typeof(x))-1) > 0 || \
|
||||||
|
((typeof(divisor))-1) > 0 || \
|
||||||
|
(((__x) > 0) == ((__d) > 0))) ? \
|
||||||
|
(((__x) + ((__d) / 2)) / (__d)) : \
|
||||||
|
(((__x) - ((__d) / 2)) / (__d)); \
|
||||||
|
} \
|
||||||
|
)
|
||||||
|
/*
|
||||||
|
* Same as above but for u64 dividends. divisor must be a 32-bit
|
||||||
|
* number.
|
||||||
|
*/
|
||||||
|
#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \
|
||||||
|
{ \
|
||||||
|
typeof(divisor) __d = divisor; \
|
||||||
|
unsigned long long _tmp = (x) + (__d) / 2; \
|
||||||
|
do_div(_tmp, __d); \
|
||||||
|
_tmp; \
|
||||||
|
} \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
||||||
|
|
||||||
|
/* Are two types/vars the same type (ignoring qualifiers)? */
|
||||||
|
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
|
||||||
|
|
||||||
|
/* &a[0] degrades to a pointer: a different type from an array */
|
||||||
|
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARRAY_SIZE - get the number of elements in array @arr
|
||||||
|
* @arr: array to be sized
|
||||||
|
*/
|
||||||
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kluge in ENOTSUPP which isn't in userspace
|
||||||
|
*/
|
||||||
|
#define ENOTSUPP 524
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kluge in symbol masking
|
||||||
|
*/
|
||||||
|
#define EXPORT_SYMBOL_GPL(x)
|
||||||
|
#define EXPORT_SYMBOL(x)
|
||||||
|
|
||||||
|
#define GFP_KERNEL
|
||||||
|
/*
|
||||||
|
* Hack kalloc to malloc
|
||||||
|
*/
|
||||||
|
#define kcalloc(nelem, sz, type) malloc(nelem * sz)
|
||||||
|
|
||||||
|
|
||||||
|
#define kfree(n) free(n)
|
||||||
|
|
||||||
|
#endif /* ifndef KERNEL_H */
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5 LLC
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _USERSPACE_LINUX_UNALIGNED_LE_BYTESHIFT_H
|
||||||
|
#define _USERSPACE_LINUX_UNALIGNED_LE_BYTESHIFT_H
|
||||||
|
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
static inline u16 __get_unaligned_le16(const u8 *p)
|
||||||
|
{
|
||||||
|
return p[0] | p[1] << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 __get_unaligned_le32(const u8 *p)
|
||||||
|
{
|
||||||
|
return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64 __get_unaligned_le64(const u8 *p)
|
||||||
|
{
|
||||||
|
return (u64)__get_unaligned_le32(p + 4) << 32 |
|
||||||
|
__get_unaligned_le32(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __put_unaligned_le16(u16 val, u8 *p)
|
||||||
|
{
|
||||||
|
*p++ = val;
|
||||||
|
*p++ = val >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __put_unaligned_le32(u32 val, u8 *p)
|
||||||
|
{
|
||||||
|
__put_unaligned_le16(val >> 16, p + 2);
|
||||||
|
__put_unaligned_le16(val, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __put_unaligned_le64(u64 val, u8 *p)
|
||||||
|
{
|
||||||
|
__put_unaligned_le32(val >> 32, p + 4);
|
||||||
|
__put_unaligned_le32(val, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u16 get_unaligned_le16(const void *p)
|
||||||
|
{
|
||||||
|
return __get_unaligned_le16((const u8 *)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 get_unaligned_le32(const void *p)
|
||||||
|
{
|
||||||
|
return __get_unaligned_le32((const u8 *)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64 get_unaligned_le64(const void *p)
|
||||||
|
{
|
||||||
|
return __get_unaligned_le64((const u8 *)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_unaligned_le16(u16 val, void *p)
|
||||||
|
{
|
||||||
|
__put_unaligned_le16(val, (u8 *) p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_unaligned_le32(u32 val, void *p)
|
||||||
|
{
|
||||||
|
__put_unaligned_le32(val, (u8 *) p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_unaligned_le64(u64 val, void *p)
|
||||||
|
{
|
||||||
|
__put_unaligned_le64(val, (u8 *) p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _USERSPACE_LINUX_UNALIGNED_LE_BYTESHIFT_H */
|
|
@ -0,0 +1,229 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/* Integer base 2 logarithm calculation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
|
||||||
|
* Written by David Howells (dhowells@redhat.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_LOG2_H__
|
||||||
|
#define __USERSPACE_LOG2_H__
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "bitops.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* non-constant log of base 2 calculators
|
||||||
|
* - the arch may override these in asm/bitops.h if they can be implemented
|
||||||
|
* more efficiently than using fls() and fls64()
|
||||||
|
* - the arch is not required to handle n==0 if implementing the fallback
|
||||||
|
*/
|
||||||
|
#ifndef CONFIG_ARCH_HAS_ILOG2_U32
|
||||||
|
static inline const
|
||||||
|
int __ilog2_u32(u32 n)
|
||||||
|
{
|
||||||
|
return __fls(n) - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARCH_HAS_ILOG2_U64
|
||||||
|
static inline const
|
||||||
|
int __ilog2_u64(u64 n)
|
||||||
|
{
|
||||||
|
return __fls64(n) - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is_power_of_2() - check if a value is a power of two
|
||||||
|
* @n: the value to check
|
||||||
|
*
|
||||||
|
* Determine whether some value is a power of two, where zero is
|
||||||
|
* *not* considered a power of two.
|
||||||
|
* Return: true if @n is a power of 2, otherwise false.
|
||||||
|
*/
|
||||||
|
static inline const
|
||||||
|
bool is_power_of_2(unsigned long n)
|
||||||
|
{
|
||||||
|
return (n != 0 && ((n & (n - 1)) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __roundup_pow_of_two() - round up to nearest power of two
|
||||||
|
* @n: value to round up
|
||||||
|
*/
|
||||||
|
static inline const
|
||||||
|
unsigned long __roundup_pow_of_two(unsigned long n)
|
||||||
|
{
|
||||||
|
return 1UL << __fls_long(n - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __rounddown_pow_of_two() - round down to nearest power of two
|
||||||
|
* @n: value to round down
|
||||||
|
*/
|
||||||
|
static inline const
|
||||||
|
unsigned long __rounddown_pow_of_two(unsigned long n)
|
||||||
|
{
|
||||||
|
return 1UL << (__fls_long(n) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* const_ilog2 - log base 2 of 32-bit or a 64-bit constant unsigned value
|
||||||
|
* @n: parameter
|
||||||
|
*
|
||||||
|
* Use this where sparse expects a true constant expression, e.g. for array
|
||||||
|
* indices.
|
||||||
|
*/
|
||||||
|
#define const_ilog2(n) \
|
||||||
|
( \
|
||||||
|
__builtin_constant_p(n) ? ( \
|
||||||
|
(n) < 2 ? 0 : \
|
||||||
|
(n) & (1ULL << 63) ? 63 : \
|
||||||
|
(n) & (1ULL << 62) ? 62 : \
|
||||||
|
(n) & (1ULL << 61) ? 61 : \
|
||||||
|
(n) & (1ULL << 60) ? 60 : \
|
||||||
|
(n) & (1ULL << 59) ? 59 : \
|
||||||
|
(n) & (1ULL << 58) ? 58 : \
|
||||||
|
(n) & (1ULL << 57) ? 57 : \
|
||||||
|
(n) & (1ULL << 56) ? 56 : \
|
||||||
|
(n) & (1ULL << 55) ? 55 : \
|
||||||
|
(n) & (1ULL << 54) ? 54 : \
|
||||||
|
(n) & (1ULL << 53) ? 53 : \
|
||||||
|
(n) & (1ULL << 52) ? 52 : \
|
||||||
|
(n) & (1ULL << 51) ? 51 : \
|
||||||
|
(n) & (1ULL << 50) ? 50 : \
|
||||||
|
(n) & (1ULL << 49) ? 49 : \
|
||||||
|
(n) & (1ULL << 48) ? 48 : \
|
||||||
|
(n) & (1ULL << 47) ? 47 : \
|
||||||
|
(n) & (1ULL << 46) ? 46 : \
|
||||||
|
(n) & (1ULL << 45) ? 45 : \
|
||||||
|
(n) & (1ULL << 44) ? 44 : \
|
||||||
|
(n) & (1ULL << 43) ? 43 : \
|
||||||
|
(n) & (1ULL << 42) ? 42 : \
|
||||||
|
(n) & (1ULL << 41) ? 41 : \
|
||||||
|
(n) & (1ULL << 40) ? 40 : \
|
||||||
|
(n) & (1ULL << 39) ? 39 : \
|
||||||
|
(n) & (1ULL << 38) ? 38 : \
|
||||||
|
(n) & (1ULL << 37) ? 37 : \
|
||||||
|
(n) & (1ULL << 36) ? 36 : \
|
||||||
|
(n) & (1ULL << 35) ? 35 : \
|
||||||
|
(n) & (1ULL << 34) ? 34 : \
|
||||||
|
(n) & (1ULL << 33) ? 33 : \
|
||||||
|
(n) & (1ULL << 32) ? 32 : \
|
||||||
|
(n) & (1ULL << 31) ? 31 : \
|
||||||
|
(n) & (1ULL << 30) ? 30 : \
|
||||||
|
(n) & (1ULL << 29) ? 29 : \
|
||||||
|
(n) & (1ULL << 28) ? 28 : \
|
||||||
|
(n) & (1ULL << 27) ? 27 : \
|
||||||
|
(n) & (1ULL << 26) ? 26 : \
|
||||||
|
(n) & (1ULL << 25) ? 25 : \
|
||||||
|
(n) & (1ULL << 24) ? 24 : \
|
||||||
|
(n) & (1ULL << 23) ? 23 : \
|
||||||
|
(n) & (1ULL << 22) ? 22 : \
|
||||||
|
(n) & (1ULL << 21) ? 21 : \
|
||||||
|
(n) & (1ULL << 20) ? 20 : \
|
||||||
|
(n) & (1ULL << 19) ? 19 : \
|
||||||
|
(n) & (1ULL << 18) ? 18 : \
|
||||||
|
(n) & (1ULL << 17) ? 17 : \
|
||||||
|
(n) & (1ULL << 16) ? 16 : \
|
||||||
|
(n) & (1ULL << 15) ? 15 : \
|
||||||
|
(n) & (1ULL << 14) ? 14 : \
|
||||||
|
(n) & (1ULL << 13) ? 13 : \
|
||||||
|
(n) & (1ULL << 12) ? 12 : \
|
||||||
|
(n) & (1ULL << 11) ? 11 : \
|
||||||
|
(n) & (1ULL << 10) ? 10 : \
|
||||||
|
(n) & (1ULL << 9) ? 9 : \
|
||||||
|
(n) & (1ULL << 8) ? 8 : \
|
||||||
|
(n) & (1ULL << 7) ? 7 : \
|
||||||
|
(n) & (1ULL << 6) ? 6 : \
|
||||||
|
(n) & (1ULL << 5) ? 5 : \
|
||||||
|
(n) & (1ULL << 4) ? 4 : \
|
||||||
|
(n) & (1ULL << 3) ? 3 : \
|
||||||
|
(n) & (1ULL << 2) ? 2 : \
|
||||||
|
1) : \
|
||||||
|
-1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ilog2 - log base 2 of 32-bit or a 64-bit unsigned value
|
||||||
|
* @n: parameter
|
||||||
|
*
|
||||||
|
* constant-capable log of base 2 calculation
|
||||||
|
* - this can be used to initialise global variables from constant data, hence
|
||||||
|
* the massive ternary operator construction
|
||||||
|
*
|
||||||
|
* selects the appropriately-sized optimised version depending on sizeof(n)
|
||||||
|
*/
|
||||||
|
#define ilog2(n) \
|
||||||
|
( \
|
||||||
|
__builtin_constant_p(n) ? \
|
||||||
|
const_ilog2(n) : \
|
||||||
|
(sizeof(n) <= 4) ? \
|
||||||
|
__ilog2_u32(n) : \
|
||||||
|
__ilog2_u64(n) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* roundup_pow_of_two - round the given value up to nearest power of two
|
||||||
|
* @n: parameter
|
||||||
|
*
|
||||||
|
* round the given value up to the nearest power of two
|
||||||
|
* - the result is undefined when n == 0
|
||||||
|
* - this can be used to initialise global variables from constant data
|
||||||
|
*/
|
||||||
|
#define roundup_pow_of_two(n) \
|
||||||
|
( \
|
||||||
|
__builtin_constant_p(n) ? ( \
|
||||||
|
(n == 1) ? 1 : \
|
||||||
|
(1UL << (ilog2((n) - 1) + 1)) \
|
||||||
|
) : \
|
||||||
|
__roundup_pow_of_two(n) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rounddown_pow_of_two - round the given value down to nearest power of two
|
||||||
|
* @n: parameter
|
||||||
|
*
|
||||||
|
* round the given value down to the nearest power of two
|
||||||
|
* - the result is undefined when n == 0
|
||||||
|
* - this can be used to initialise global variables from constant data
|
||||||
|
*/
|
||||||
|
#define rounddown_pow_of_two(n) \
|
||||||
|
( \
|
||||||
|
__builtin_constant_p(n) ? ( \
|
||||||
|
(1UL << ilog2(n))) : \
|
||||||
|
__rounddown_pow_of_two(n) \
|
||||||
|
)
|
||||||
|
|
||||||
|
static inline __attribute_const__
|
||||||
|
int __order_base_2(unsigned long n)
|
||||||
|
{
|
||||||
|
return n > 1 ? ilog2(n - 1) + 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* order_base_2 - calculate the (rounded up) base 2 order of the argument
|
||||||
|
* @n: parameter
|
||||||
|
*
|
||||||
|
* The first few values calculated by this routine:
|
||||||
|
* ob2(0) = 0
|
||||||
|
* ob2(1) = 0
|
||||||
|
* ob2(2) = 1
|
||||||
|
* ob2(3) = 2
|
||||||
|
* ob2(4) = 2
|
||||||
|
* ob2(5) = 3
|
||||||
|
* ... and so on.
|
||||||
|
*/
|
||||||
|
#define order_base_2(n) \
|
||||||
|
( \
|
||||||
|
__builtin_constant_p(n) ? ( \
|
||||||
|
((n) == 0 || (n) == 1) ? 0 : \
|
||||||
|
ilog2((n) - 1) + 1) : \
|
||||||
|
__order_base_2(n) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_LOG2_H */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
* 802.11 netlink interface public header
|
||||||
|
*
|
||||||
|
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||||
|
* Copyright 2008 Michael Wu <flamingice@sourmilk.net>
|
||||||
|
* Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
|
||||||
|
* Copyright 2008 Michael Buesch <m@bues.ch>
|
||||||
|
* Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
|
||||||
|
* Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
|
||||||
|
* Copyright 2008 Colin McCabe <colin@cozybit.com>
|
||||||
|
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||||
|
* Copyright (C) 2018-2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_NL80211_H__
|
||||||
|
#define __USERSPACE_NL80211_H__
|
||||||
|
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nl80211_chan_width - channel width definitions
|
||||||
|
*
|
||||||
|
* These values are used with the %NL80211_ATTR_CHANNEL_WIDTH
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel
|
||||||
|
* @NL80211_CHAN_WIDTH_20: 20 MHz HT channel
|
||||||
|
* @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
|
||||||
|
* attribute must be provided as well
|
||||||
|
* @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
|
||||||
|
* attribute must be provided as well
|
||||||
|
* @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
|
||||||
|
* and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well
|
||||||
|
* @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
|
||||||
|
* attribute must be provided as well
|
||||||
|
* @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel
|
||||||
|
* @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel
|
||||||
|
*/
|
||||||
|
enum nl80211_chan_width {
|
||||||
|
NL80211_CHAN_WIDTH_20_NOHT,
|
||||||
|
NL80211_CHAN_WIDTH_20,
|
||||||
|
NL80211_CHAN_WIDTH_40,
|
||||||
|
NL80211_CHAN_WIDTH_80,
|
||||||
|
NL80211_CHAN_WIDTH_80P80,
|
||||||
|
NL80211_CHAN_WIDTH_160,
|
||||||
|
NL80211_CHAN_WIDTH_5,
|
||||||
|
NL80211_CHAN_WIDTH_10,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nl80211_band - Frequency band
|
||||||
|
* @NL80211_BAND_2GHZ: 2.4 GHz ISM band
|
||||||
|
* @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
|
||||||
|
* @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz)
|
||||||
|
* @NUM_NL80211_BANDS: number of bands, avoid using this in userspace
|
||||||
|
* since newer kernel versions may support more bands
|
||||||
|
*/
|
||||||
|
enum nl80211_band {
|
||||||
|
NL80211_BAND_2GHZ,
|
||||||
|
NL80211_BAND_5GHZ,
|
||||||
|
NL80211_BAND_60GHZ,
|
||||||
|
|
||||||
|
NUM_NL80211_BANDS,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nl80211_dfs_state - DFS states for channels
|
||||||
|
*
|
||||||
|
* Channel states used by the DFS code.
|
||||||
|
*
|
||||||
|
* @NL80211_DFS_USABLE: The channel can be used, but channel availability
|
||||||
|
* check (CAC) must be performed before using it for AP or IBSS.
|
||||||
|
* @NL80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it
|
||||||
|
* is therefore marked as not available.
|
||||||
|
* @NL80211_DFS_AVAILABLE: The channel has been CAC checked and is available.
|
||||||
|
*/
|
||||||
|
enum nl80211_dfs_state {
|
||||||
|
NL80211_DFS_USABLE,
|
||||||
|
NL80211_DFS_UNAVAILABLE,
|
||||||
|
NL80211_DFS_AVAILABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nl80211_tx_power_setting - TX power adjustment
|
||||||
|
* @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
|
||||||
|
* @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter
|
||||||
|
* @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter
|
||||||
|
*/
|
||||||
|
enum nl80211_tx_power_setting {
|
||||||
|
NL80211_TX_POWER_AUTOMATIC,
|
||||||
|
NL80211_TX_POWER_LIMITED,
|
||||||
|
NL80211_TX_POWER_FIXED,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nl80211_iftype - (virtual) interface types
|
||||||
|
*
|
||||||
|
* @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides
|
||||||
|
* @NL80211_IFTYPE_ADHOC: independent BSS member
|
||||||
|
* @NL80211_IFTYPE_STATION: managed BSS member
|
||||||
|
* @NL80211_IFTYPE_AP: access point
|
||||||
|
* @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces
|
||||||
|
* are a bit special in that they must always be tied to a pre-existing
|
||||||
|
* AP type interface.
|
||||||
|
* @NL80211_IFTYPE_WDS: wireless distribution interface
|
||||||
|
* @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
|
||||||
|
* @NL80211_IFTYPE_MESH_POINT: mesh point
|
||||||
|
* @NL80211_IFTYPE_P2P_CLIENT: P2P client
|
||||||
|
* @NL80211_IFTYPE_P2P_GO: P2P group owner
|
||||||
|
* @NL80211_IFTYPE_P2P_DEVICE: P2P device interface type, this is not a netdev
|
||||||
|
* and therefore can't be created in the normal ways, use the
|
||||||
|
* %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
|
||||||
|
* commands to create and destroy one
|
||||||
|
* @NL80211_IF_TYPE_OCB: Outside Context of a BSS
|
||||||
|
* This mode corresponds to the MIB variable dot11OCBActivated=true
|
||||||
|
* @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev)
|
||||||
|
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
|
||||||
|
* @NUM_NL80211_IFTYPES: number of defined interface types
|
||||||
|
*
|
||||||
|
* These values are used with the %NL80211_ATTR_IFTYPE
|
||||||
|
* to set the type of an interface.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum nl80211_iftype {
|
||||||
|
NL80211_IFTYPE_UNSPECIFIED,
|
||||||
|
NL80211_IFTYPE_ADHOC,
|
||||||
|
NL80211_IFTYPE_STATION,
|
||||||
|
NL80211_IFTYPE_AP,
|
||||||
|
NL80211_IFTYPE_AP_VLAN,
|
||||||
|
NL80211_IFTYPE_WDS,
|
||||||
|
NL80211_IFTYPE_MONITOR,
|
||||||
|
NL80211_IFTYPE_MESH_POINT,
|
||||||
|
NL80211_IFTYPE_P2P_CLIENT,
|
||||||
|
NL80211_IFTYPE_P2P_GO,
|
||||||
|
NL80211_IFTYPE_P2P_DEVICE,
|
||||||
|
NL80211_IFTYPE_OCB,
|
||||||
|
NL80211_IFTYPE_NAN,
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
NUM_NL80211_IFTYPES,
|
||||||
|
NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
|
||||||
|
}
|
||||||
|
;
|
||||||
|
/* Notice of Absence attribute - described in P2P spec 4.1.14 */
|
||||||
|
/* Typical max value used here */
|
||||||
|
#define IEEE80211_P2P_NOA_DESC_MAX 4
|
||||||
|
|
||||||
|
struct ieee80211_p2p_noa_desc {
|
||||||
|
u8 count;
|
||||||
|
__le32 duration;
|
||||||
|
__le32 interval;
|
||||||
|
__le32 start_time;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ieee80211_p2p_noa_attr {
|
||||||
|
u8 index;
|
||||||
|
u8 oppps_ctwindow;
|
||||||
|
struct ieee80211_p2p_noa_desc desc[IEEE80211_P2P_NOA_DESC_MAX];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7)
|
||||||
|
#define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7F
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_NL80211_H */
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_TYPES_H__
|
||||||
|
#define __USERSPACE_TYPES_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint8_t u8;
|
||||||
|
typedef uint16_t u16;
|
||||||
|
typedef uint32_t u32;
|
||||||
|
typedef uint64_t u64;
|
||||||
|
|
||||||
|
typedef int8_t s8;
|
||||||
|
typedef int16_t s16;
|
||||||
|
typedef int32_t s32;
|
||||||
|
typedef int64_t s64;
|
||||||
|
|
||||||
|
typedef uint8_t __u8;
|
||||||
|
typedef uint16_t __u16;
|
||||||
|
typedef uint32_t __u32;
|
||||||
|
typedef uint64_t __u64;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We lose the atomic stuff
|
||||||
|
*/
|
||||||
|
typedef int64_t atomic64_t;
|
||||||
|
typedef int64_t atomic_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We lose the automagic endian checking and have to make sure
|
||||||
|
* we do it ourselves properly.
|
||||||
|
*/
|
||||||
|
typedef uint16_t __le16;
|
||||||
|
typedef uint32_t __le32;
|
||||||
|
|
||||||
|
typedef uint16_t __be16;
|
||||||
|
typedef uint32_t __be32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not going to make a whole netdev defs file for one def
|
||||||
|
*/
|
||||||
|
typedef u64 netdev_features_t;
|
||||||
|
|
||||||
|
#endif /* ifndef TYPES_H */
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* Derived from Linux kernel usb.h
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USB_H__
|
||||||
|
#define __USB_H__
|
||||||
|
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEVICE \
|
||||||
|
(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEV_RANGE \
|
||||||
|
(USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
|
||||||
|
(USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEV_INFO \
|
||||||
|
(USB_DEVICE_ID_MATCH_DEV_CLASS | \
|
||||||
|
USB_DEVICE_ID_MATCH_DEV_SUBCLASS | \
|
||||||
|
USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
|
||||||
|
#define USB_DEVICE_ID_MATCH_INT_INFO \
|
||||||
|
(USB_DEVICE_ID_MATCH_INT_CLASS | \
|
||||||
|
USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
|
||||||
|
USB_DEVICE_ID_MATCH_INT_PROTOCOL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* USB_DEVICE - macro used to describe a specific usb device
|
||||||
|
* @vend: the 16 bit USB Vendor ID
|
||||||
|
* @prod: the 16 bit USB Product ID
|
||||||
|
*
|
||||||
|
* This macro is used to create a struct usb_device_id that matches a
|
||||||
|
* specific device.
|
||||||
|
*/
|
||||||
|
#define USB_DEVICE(vend, prod) \
|
||||||
|
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
|
||||||
|
.idVendor = (vend), \
|
||||||
|
.idProduct = (prod)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct usb_device_id - identifies USB devices for probing and hotplugging
|
||||||
|
* @match_flags: Bit mask controlling which of the other fields are used to
|
||||||
|
* match against new devices. Any field except for driver_info may be
|
||||||
|
* used, although some only make sense in conjunction with other fields.
|
||||||
|
* This is usually set by a USB_DEVICE_*() macro, which sets all
|
||||||
|
* other fields in this structure except for driver_info.
|
||||||
|
* @idVendor: USB vendor ID for a device; numbers are assigned
|
||||||
|
* by the USB forum to its members.
|
||||||
|
* @idProduct: Vendor-assigned product ID.
|
||||||
|
* @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
|
||||||
|
* This is also used to identify individual product versions, for
|
||||||
|
* a range consisting of a single device.
|
||||||
|
* @bcdDevice_hi: High end of version number range. The range of product
|
||||||
|
* versions is inclusive.
|
||||||
|
* @bDeviceClass: Class of device; numbers are assigned
|
||||||
|
* by the USB forum. Products may choose to implement classes,
|
||||||
|
* or be vendor-specific. Device classes specify behavior of all
|
||||||
|
* the interfaces on a device.
|
||||||
|
* @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
|
||||||
|
* @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
|
||||||
|
* @bInterfaceClass: Class of interface; numbers are assigned
|
||||||
|
* by the USB forum. Products may choose to implement classes,
|
||||||
|
* or be vendor-specific. Interface classes specify behavior only
|
||||||
|
* of a given interface; other interfaces may support other classes.
|
||||||
|
* @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
|
||||||
|
* @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
|
||||||
|
* @bInterfaceNumber: Number of interface; composite devices may use
|
||||||
|
* fixed interface numbers to differentiate between vendor-specific
|
||||||
|
* interfaces.
|
||||||
|
* @driver_info: Holds information used by the driver. Usually it holds
|
||||||
|
* a pointer to a descriptor understood by the driver, or perhaps
|
||||||
|
* device flags.
|
||||||
|
*
|
||||||
|
* In most cases, drivers will create a table of device IDs by using
|
||||||
|
* USB_DEVICE(), or similar macros designed for that purpose.
|
||||||
|
* They will then export it to userspace using MODULE_DEVICE_TABLE(),
|
||||||
|
* and provide it to the USB core through their usb_driver structure.
|
||||||
|
*
|
||||||
|
* See the usb_match_id() function for information about how matches are
|
||||||
|
* performed. Briefly, you will normally use one of several macros to help
|
||||||
|
* construct these entries. Each entry you provide will either identify
|
||||||
|
* one or more specific products, or will identify a class of products
|
||||||
|
* which have agreed to behave the same. You should put the more specific
|
||||||
|
* matches towards the beginning of your table, so that driver_info can
|
||||||
|
* record quirks of specific products.
|
||||||
|
*/
|
||||||
|
struct usb_device_id {
|
||||||
|
/* which fields to match against? */
|
||||||
|
__u16 match_flags;
|
||||||
|
|
||||||
|
/* Used for product specific matches; range is inclusive */
|
||||||
|
__u16 idVendor;
|
||||||
|
__u16 idProduct;
|
||||||
|
__u16 bcdDevice_lo;
|
||||||
|
__u16 bcdDevice_hi;
|
||||||
|
|
||||||
|
/* Used for device class matches */
|
||||||
|
__u8 bDeviceClass;
|
||||||
|
__u8 bDeviceSubClass;
|
||||||
|
__u8 bDeviceProtocol;
|
||||||
|
|
||||||
|
/* Used for interface class matches */
|
||||||
|
__u8 bInterfaceClass;
|
||||||
|
__u8 bInterfaceSubClass;
|
||||||
|
__u8 bInterfaceProtocol;
|
||||||
|
|
||||||
|
/* Used for vendor-specific interface matches */
|
||||||
|
__u8 bInterfaceNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Some useful macros to use to create struct usb_device_id */
|
||||||
|
#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
|
||||||
|
#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
|
||||||
|
#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
|
||||||
|
#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
|
||||||
|
#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
|
||||||
|
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
|
||||||
|
#define USB_DEVICE_ID_MATCH_INT_NUMBER 0x0400
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB directions
|
||||||
|
*
|
||||||
|
* This bit flag is used in endpoint descriptors' bEndpointAddress field.
|
||||||
|
* It's also one of three fields in control requests bRequestType.
|
||||||
|
*/
|
||||||
|
#define USB_DIR_OUT 0 /* to device */
|
||||||
|
#define USB_DIR_IN 0x80 /* to host */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB types, the second of three bRequestType fields
|
||||||
|
*/
|
||||||
|
#define USB_TYPE_MASK (0x03 << 5)
|
||||||
|
#define USB_TYPE_STANDARD (0x00 << 5)
|
||||||
|
#define USB_TYPE_CLASS (0x01 << 5)
|
||||||
|
#define USB_TYPE_VENDOR (0x02 << 5)
|
||||||
|
#define USB_TYPE_RESERVED (0x03 << 5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB recipients, the third of three bRequestType fields
|
||||||
|
*/
|
||||||
|
#define USB_RECIP_MASK 0x1f
|
||||||
|
#define USB_RECIP_DEVICE 0x00
|
||||||
|
#define USB_RECIP_INTERFACE 0x01
|
||||||
|
#define USB_RECIP_ENDPOINT 0x02
|
||||||
|
#define USB_RECIP_OTHER 0x03
|
||||||
|
/* From Wireless USB 1.0 */
|
||||||
|
#define USB_RECIP_PORT 0x04
|
||||||
|
#define USB_RECIP_RPIPE 0x05
|
||||||
|
|
||||||
|
#endif /* ifndef USB_H */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
|
||||||
|
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
* <http://rt2x00.serialmonkey.com>
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RT2800LIB_H__
|
||||||
|
#define __RT2800LIB_H__
|
||||||
|
|
||||||
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/mac80211.h"
|
||||||
|
#include "kernel/ieee80211.h"
|
||||||
|
|
||||||
|
#include "rt2x00.h"
|
||||||
|
#include "rt2800.h"
|
||||||
|
|
||||||
|
/* RT2800 driver data structure */
|
||||||
|
struct rt2800_drv_data {
|
||||||
|
u8 calibration_bw20;
|
||||||
|
u8 calibration_bw40;
|
||||||
|
char rx_calibration_bw20;
|
||||||
|
char rx_calibration_bw40;
|
||||||
|
char tx_calibration_bw20;
|
||||||
|
char tx_calibration_bw40;
|
||||||
|
u8 bbp25;
|
||||||
|
u8 bbp26;
|
||||||
|
u8 txmixer_gain_24g;
|
||||||
|
u8 txmixer_gain_5g;
|
||||||
|
u8 max_psdu;
|
||||||
|
unsigned int tbtt_tick;
|
||||||
|
unsigned int ampdu_factor_cnt[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rt2800_ops {
|
||||||
|
u32 (*register_read)(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset);
|
||||||
|
u32 (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset);
|
||||||
|
void (*register_write)(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset, u32 value);
|
||||||
|
void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset, u32 value);
|
||||||
|
|
||||||
|
void (*register_multiread)(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
void *value, const u32 length);
|
||||||
|
void (*register_multiwrite)(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
const void *value, const u32 length);
|
||||||
|
|
||||||
|
int (*regbusy_read)(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
const struct rt2x00_field32 field, u32 *reg);
|
||||||
|
|
||||||
|
int (*read_eeprom)(struct rt2x00_dev *rt2x00dev);
|
||||||
|
bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 *data, const size_t len);
|
||||||
|
int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
return rt2800ops->register_read(rt2x00dev, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
return rt2800ops->register_read_lock(rt2x00dev, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
u32 value) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
rt2800ops->register_write(rt2x00dev, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
u32 value) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
rt2800ops->register_write_lock(rt2x00dev, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
void *value, const u32 length) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
rt2800ops->register_multiread(rt2x00dev, offset, value, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
const void *value,
|
||||||
|
const u32 length) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
rt2800ops->register_multiwrite(rt2x00dev, offset, value, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
const struct rt2x00_field32 field,
|
||||||
|
u32 *reg) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
return rt2800ops->read_eeprom(rt2x00dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
return rt2800ops->hwcrypt_disabled(rt2x00dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 *data, const size_t len) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
return rt2800ops->drv_write_firmware(rt2x00dev, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) {
|
||||||
|
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
|
||||||
|
|
||||||
|
return rt2800ops->drv_init_registers(rt2x00dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
|
||||||
|
int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev);
|
||||||
|
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
|
||||||
|
struct rt2x00lib_crypto *crypto,
|
||||||
|
struct ieee80211_key_conf *key);
|
||||||
|
int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
|
||||||
|
struct rt2x00lib_crypto *crypto,
|
||||||
|
struct ieee80211_key_conf *key);
|
||||||
|
int rt2800_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta);
|
||||||
|
int rt2800_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta);
|
||||||
|
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int filter_flags);
|
||||||
|
void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant);
|
||||||
|
void rt2800_config(struct rt2x00_dev *rt2x00dev,
|
||||||
|
struct rt2x00lib_conf *libconf,
|
||||||
|
const unsigned int flags);
|
||||||
|
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
|
||||||
|
struct rt2x00intf_conf *conf, const unsigned int flags);
|
||||||
|
void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
|
||||||
|
u32 changed);
|
||||||
|
void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
|
||||||
|
void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
|
||||||
|
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
|
||||||
|
const u32 count);
|
||||||
|
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
|
||||||
|
void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
|
||||||
|
void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 command, const u8 token,
|
||||||
|
const u8 arg0, const u8 arg1);
|
||||||
|
|
||||||
|
int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev);
|
||||||
|
int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 *data, const size_t len);
|
||||||
|
int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 *data, const size_t len);
|
||||||
|
|
||||||
|
int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev);
|
||||||
|
int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
int rt2800_init_registers(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
static inline bool rt2800_clk_is_20mhz(struct rt2x00_dev *rt2x00dev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* clk is for SOC only, and we don't want to deal with all the kernel
|
||||||
|
* stuff. We never have a SOC chip in USB.
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef RT2800LIB_H */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
|
||||||
|
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
* <http://rt2x00.serialmonkey.com>
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RT2800USB_H__
|
||||||
|
#define __RT2800USB_H__
|
||||||
|
|
||||||
|
#include "rt2x00.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 8051 firmware image.
|
||||||
|
*/
|
||||||
|
#define FIRMWARE_RT2870 "rt2870.bin"
|
||||||
|
#define FIRMWARE_IMAGE_BASE 0x3000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DMA descriptor defines.
|
||||||
|
*/
|
||||||
|
#define TXINFO_DESC_SIZE (1 * sizeof(__le32))
|
||||||
|
#define RXINFO_DESC_SIZE (1 * sizeof(__le32))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TX Info structure
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Word0
|
||||||
|
* WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI
|
||||||
|
* QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
|
||||||
|
* 0:MGMT, 1:HCCA 2:EDCA
|
||||||
|
* USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid
|
||||||
|
* DMA_TX_BURST: used ONLY in USB bulk Aggregation.
|
||||||
|
* Force USB DMA transmit frame from current selected endpoint
|
||||||
|
*/
|
||||||
|
#define TXINFO_W0_USB_DMA_TX_PKT_LEN FIELD32(0x0000ffff)
|
||||||
|
#define TXINFO_W0_WIV FIELD32(0x01000000)
|
||||||
|
#define TXINFO_W0_QSEL FIELD32(0x06000000)
|
||||||
|
#define TXINFO_W0_SW_USE_LAST_ROUND FIELD32(0x08000000)
|
||||||
|
#define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000)
|
||||||
|
#define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RX Info structure
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Word 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RXINFO_W0_USB_DMA_RX_PKT_LEN FIELD32(0x0000ffff)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RX descriptor format for RX Ring.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Word0
|
||||||
|
* UNICAST_TO_ME: This RX frame is unicast to me.
|
||||||
|
* MULTICAST: This is a multicast frame.
|
||||||
|
* BROADCAST: This is a broadcast frame.
|
||||||
|
* MY_BSS: this frame belongs to the same BSSID.
|
||||||
|
* CRC_ERROR: CRC error.
|
||||||
|
* CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid.
|
||||||
|
* AMSDU: rx with 802.3 header, not 802.11 header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RXD_W0_BA FIELD32(0x00000001)
|
||||||
|
#define RXD_W0_DATA FIELD32(0x00000002)
|
||||||
|
#define RXD_W0_NULLDATA FIELD32(0x00000004)
|
||||||
|
#define RXD_W0_FRAG FIELD32(0x00000008)
|
||||||
|
#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010)
|
||||||
|
#define RXD_W0_MULTICAST FIELD32(0x00000020)
|
||||||
|
#define RXD_W0_BROADCAST FIELD32(0x00000040)
|
||||||
|
#define RXD_W0_MY_BSS FIELD32(0x00000080)
|
||||||
|
#define RXD_W0_CRC_ERROR FIELD32(0x00000100)
|
||||||
|
#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600)
|
||||||
|
#define RXD_W0_AMSDU FIELD32(0x00000800)
|
||||||
|
#define RXD_W0_HTC FIELD32(0x00001000)
|
||||||
|
#define RXD_W0_RSSI FIELD32(0x00002000)
|
||||||
|
#define RXD_W0_L2PAD FIELD32(0x00004000)
|
||||||
|
#define RXD_W0_AMPDU FIELD32(0x00008000)
|
||||||
|
#define RXD_W0_DECRYPTED FIELD32(0x00010000)
|
||||||
|
#define RXD_W0_PLCP_RSSI FIELD32(0x00020000)
|
||||||
|
#define RXD_W0_CIPHER_ALG FIELD32(0x00040000)
|
||||||
|
#define RXD_W0_LAST_AMSDU FIELD32(0x00080000)
|
||||||
|
#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Firmware functions
|
||||||
|
*/
|
||||||
|
int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev);
|
||||||
|
/*
|
||||||
|
* Probe a usb device to determine if it's a viable rt2800 device;
|
||||||
|
* returns 1 on success and populates **probe_dev,
|
||||||
|
* returns 0 on no match
|
||||||
|
* returns negative on error
|
||||||
|
*/
|
||||||
|
int rt2800usb_probe_device(struct libusb_device_descriptor *desc,
|
||||||
|
struct userspace_wifi_probe_dev **probe_dev);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef RT2800USB_H */
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
|
||||||
|
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
* <http://rt2x00.serialmonkey.com>
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a user-space port of components of the rt2x00usb library,
|
||||||
|
* implementing generic usb device routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "kernel/bits.h"
|
||||||
|
#include "kernel/endian.h"
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
|
||||||
|
#include "rt2800usb/rt2x00.h"
|
||||||
|
#include "rt2800usb/rt2x00usb.h"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,80 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
|
||||||
|
<http://rt2x00.serialmonkey.com>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module: rt2x00lib
|
||||||
|
Abstract: Data structures and definitions for the rt2x00lib module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RT2x00LIB_H__
|
||||||
|
#define __RT2x00LIB_H__
|
||||||
|
|
||||||
|
#include "kernel/nl80211.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rt2x00_rate: Per rate device information
|
||||||
|
*/
|
||||||
|
struct rt2x00_rate {
|
||||||
|
unsigned short flags;
|
||||||
|
#define DEV_RATE_CCK 0x0001
|
||||||
|
#define DEV_RATE_OFDM 0x0002
|
||||||
|
#define DEV_RATE_SHORT_PREAMBLE 0x0004
|
||||||
|
|
||||||
|
unsigned short bitrate; /* In 100kbit/s */
|
||||||
|
unsigned short ratemask;
|
||||||
|
|
||||||
|
unsigned short plcp;
|
||||||
|
unsigned short mcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct rt2x00_rate rt2x00_supported_rates[12];
|
||||||
|
|
||||||
|
static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
|
||||||
|
{
|
||||||
|
return &rt2x00_supported_rates[hw_value & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RATE_MCS(__mode, __mcs) \
|
||||||
|
((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff))
|
||||||
|
|
||||||
|
static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
|
||||||
|
{
|
||||||
|
return (mcs_value & 0x00ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization handlers.
|
||||||
|
*/
|
||||||
|
int rt2x00lib_start(struct rt2x00_dev *rt2x00dev);
|
||||||
|
void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configuration handlers.
|
||||||
|
*/
|
||||||
|
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif);
|
||||||
|
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
|
||||||
|
struct rt2x00_intf *intf,
|
||||||
|
enum nl80211_iftype type,
|
||||||
|
const u8 *mac, const u8 *bssid);
|
||||||
|
void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
|
||||||
|
struct rt2x00_intf *intf,
|
||||||
|
struct ieee80211_bss_conf *conf,
|
||||||
|
u32 changed);
|
||||||
|
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
|
||||||
|
struct antenna_setup ant);
|
||||||
|
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
|
||||||
|
struct ieee80211_conf *conf,
|
||||||
|
const unsigned int changed_flags);
|
||||||
|
|
||||||
|
#endif /* ifndef RT2x00LIB_H */
|
|
@ -0,0 +1,120 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
<http://rt2x00.serialmonkey.com>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace port (c) 2019 Hak5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module: rt2x00mac
|
||||||
|
Abstract: rt2x00 generic mac80211 routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "kernel/ieee80211.h"
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
|
||||||
|
#include "rt2800usb/rt2x00.h"
|
||||||
|
#include "rt2800usb/rt2x00lib.h"
|
||||||
|
|
||||||
|
int rt2x00mac_start(struct ieee80211_hw *hw)
|
||||||
|
{
|
||||||
|
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *) hw->priv;
|
||||||
|
|
||||||
|
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return rt2x00lib_start(rt2x00dev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rt2x00mac_start);
|
||||||
|
|
||||||
|
void rt2x00mac_stop(struct ieee80211_hw *hw)
|
||||||
|
{
|
||||||
|
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *) hw->priv;
|
||||||
|
|
||||||
|
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
rt2x00lib_stop(rt2x00dev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
|
||||||
|
|
||||||
|
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif)
|
||||||
|
{
|
||||||
|
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *) hw->priv;
|
||||||
|
struct rt2x00_intf *intf = vif_to_intf(vif);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't allow interfaces to be added
|
||||||
|
* the device has disappeared.
|
||||||
|
*/
|
||||||
|
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
|
||||||
|
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
|
||||||
|
rt2x00_err(rt2x00dev, "Device not started before adding vif\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are now absolutely sure the interface can be created,
|
||||||
|
* increase interface count and start initialization.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The MAC address must be configured after the device
|
||||||
|
* has been initialized. Otherwise the device can reset
|
||||||
|
* the MAC registers.
|
||||||
|
* The BSSID address must only be configured in AP mode,
|
||||||
|
* however we should not send an empty BSSID address for
|
||||||
|
* STA interfaces at this time, since this can cause
|
||||||
|
* invalid behavior in the device.
|
||||||
|
*/
|
||||||
|
rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
|
||||||
|
vif->addr, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
|
||||||
|
|
||||||
|
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
|
||||||
|
struct rt2x00_intf *intf,
|
||||||
|
enum nl80211_iftype type,
|
||||||
|
const u8 *mac, const u8 *bssid)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trimmed down for userspace
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct rt2x00intf_conf conf;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
|
||||||
|
conf.type = type;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case NL80211_IFTYPE_ADHOC:
|
||||||
|
conf.sync = TSF_SYNC_ADHOC;
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_AP:
|
||||||
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
|
case NL80211_IFTYPE_WDS:
|
||||||
|
conf.sync = TSF_SYNC_AP_NONE;
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_STATION:
|
||||||
|
conf.sync = TSF_SYNC_INFRA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
conf.sync = TSF_SYNC_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = CONFIG_UPDATE_TYPE | CONFIG_UPDATE_MAC | CONFIG_UPDATE_BSSID;
|
||||||
|
|
||||||
|
rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
|
||||||
|
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
* <http://rt2x00.serialmonkey.com>
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RT2X00QUEUE_H__
|
||||||
|
#define __RT2X00QUEUE_H__
|
||||||
|
|
||||||
|
#include "kernel/bits.h"
|
||||||
|
#include "kernel/mac80211.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOC: Entry frame size
|
||||||
|
*
|
||||||
|
* Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
|
||||||
|
* for USB devices this restriction does not apply, but the value of
|
||||||
|
* 2432 makes sense since it is big enough to contain the maximum fragment
|
||||||
|
* size according to the ieee802.11 specs.
|
||||||
|
* The aggregation size depends on support from the driver, but should
|
||||||
|
* be something around 3840 bytes.
|
||||||
|
*/
|
||||||
|
#define DATA_FRAME_SIZE 2432
|
||||||
|
#define MGMT_FRAME_SIZE 256
|
||||||
|
#define AGGREGATION_SIZE 3840
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
|
||||||
|
*
|
||||||
|
* @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
|
||||||
|
* @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
|
||||||
|
* @RXDONE_SIGNAL_MCS: Signal field contains the mcs value.
|
||||||
|
* @RXDONE_MY_BSS: Does this frame originate from device's BSS.
|
||||||
|
* @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
|
||||||
|
* @RXDONE_CRYPTO_ICV: Driver provided ICV data.
|
||||||
|
* @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary.
|
||||||
|
*/
|
||||||
|
enum rxdone_entry_desc_flags {
|
||||||
|
RXDONE_SIGNAL_PLCP = BIT(0),
|
||||||
|
RXDONE_SIGNAL_BITRATE = BIT(1),
|
||||||
|
RXDONE_SIGNAL_MCS = BIT(2),
|
||||||
|
RXDONE_MY_BSS = BIT(3),
|
||||||
|
RXDONE_CRYPTO_IV = BIT(4),
|
||||||
|
RXDONE_CRYPTO_ICV = BIT(5),
|
||||||
|
RXDONE_L2PAD = BIT(6),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RXDONE_SIGNAL_MASK - Define to mask off all &rxdone_entry_desc_flags flags
|
||||||
|
* except for the RXDONE_SIGNAL_* flags. This is useful to convert the dev_flags
|
||||||
|
* from &rxdone_entry_desc to a signal value type.
|
||||||
|
*/
|
||||||
|
#define RXDONE_SIGNAL_MASK \
|
||||||
|
( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct rxdone_entry_desc: RX Entry descriptor
|
||||||
|
*
|
||||||
|
* Summary of information that has been read from the RX frame descriptor.
|
||||||
|
*
|
||||||
|
* @timestamp: RX Timestamp
|
||||||
|
* @signal: Signal of the received frame.
|
||||||
|
* @rssi: RSSI of the received frame.
|
||||||
|
* @size: Data size of the received frame.
|
||||||
|
* @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
|
||||||
|
* @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
|
||||||
|
* @rate_mode: Rate mode (See @enum rate_modulation).
|
||||||
|
* @cipher: Cipher type used during decryption.
|
||||||
|
* @cipher_status: Decryption status.
|
||||||
|
* @iv: IV/EIV data used during decryption.
|
||||||
|
* @icv: ICV data used during decryption.
|
||||||
|
*/
|
||||||
|
struct rxdone_entry_desc {
|
||||||
|
u64 timestamp;
|
||||||
|
int signal;
|
||||||
|
int rssi;
|
||||||
|
int size;
|
||||||
|
int flags;
|
||||||
|
int dev_flags;
|
||||||
|
u16 rate_mode;
|
||||||
|
u16 enc_flags;
|
||||||
|
enum mac80211_rx_encoding encoding;
|
||||||
|
enum rate_info_bw bw;
|
||||||
|
u8 cipher;
|
||||||
|
u8 cipher_status;
|
||||||
|
|
||||||
|
__le32 iv[2];
|
||||||
|
__le32 icv;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ifndef RT2X00QUEUE_H */
|
||||||
|
|
|
@ -0,0 +1,255 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
|
||||||
|
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
* <http://rt2x00.serialmonkey.com>
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RT2X00REG_H__
|
||||||
|
#define __RT2X00REG_H__
|
||||||
|
|
||||||
|
#include "kernel/bits.h"
|
||||||
|
#include "kernel/endian.h"
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RX crypto status
|
||||||
|
*/
|
||||||
|
enum rx_crypto {
|
||||||
|
RX_CRYPTO_SUCCESS = 0,
|
||||||
|
RX_CRYPTO_FAIL_ICV = 1,
|
||||||
|
RX_CRYPTO_FAIL_MIC = 2,
|
||||||
|
RX_CRYPTO_FAIL_KEY = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Antenna values
|
||||||
|
*/
|
||||||
|
enum antenna {
|
||||||
|
ANTENNA_SW_DIVERSITY = 0,
|
||||||
|
ANTENNA_A = 1,
|
||||||
|
ANTENNA_B = 2,
|
||||||
|
ANTENNA_HW_DIVERSITY = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Led mode values.
|
||||||
|
*/
|
||||||
|
enum led_mode {
|
||||||
|
LED_MODE_DEFAULT = 0,
|
||||||
|
LED_MODE_TXRX_ACTIVITY = 1,
|
||||||
|
LED_MODE_SIGNAL_STRENGTH = 2,
|
||||||
|
LED_MODE_ASUS = 3,
|
||||||
|
LED_MODE_ALPHA = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TSF sync values
|
||||||
|
*/
|
||||||
|
enum tsf_sync {
|
||||||
|
TSF_SYNC_NONE = 0,
|
||||||
|
TSF_SYNC_INFRA = 1,
|
||||||
|
TSF_SYNC_ADHOC = 2,
|
||||||
|
TSF_SYNC_AP_NONE = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device states
|
||||||
|
*/
|
||||||
|
enum dev_state {
|
||||||
|
STATE_DEEP_SLEEP = 0,
|
||||||
|
STATE_SLEEP = 1,
|
||||||
|
STATE_STANDBY = 2,
|
||||||
|
STATE_AWAKE = 3,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additional device states, these values are
|
||||||
|
* not strict since they are not directly passed
|
||||||
|
* into the device.
|
||||||
|
*/
|
||||||
|
STATE_RADIO_ON,
|
||||||
|
STATE_RADIO_OFF,
|
||||||
|
STATE_RADIO_IRQ_ON,
|
||||||
|
STATE_RADIO_IRQ_OFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IFS backoff values
|
||||||
|
*/
|
||||||
|
enum ifs {
|
||||||
|
IFS_BACKOFF = 0,
|
||||||
|
IFS_SIFS = 1,
|
||||||
|
IFS_NEW_BACKOFF = 2,
|
||||||
|
IFS_NONE = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IFS backoff values for HT devices
|
||||||
|
*/
|
||||||
|
enum txop {
|
||||||
|
TXOP_HTTXOP = 0,
|
||||||
|
TXOP_PIFS = 1,
|
||||||
|
TXOP_SIFS = 2,
|
||||||
|
TXOP_BACKOFF = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cipher types for hardware encryption
|
||||||
|
*/
|
||||||
|
enum cipher {
|
||||||
|
CIPHER_NONE = 0,
|
||||||
|
CIPHER_WEP64 = 1,
|
||||||
|
CIPHER_WEP128 = 2,
|
||||||
|
CIPHER_TKIP = 3,
|
||||||
|
CIPHER_AES = 4,
|
||||||
|
/*
|
||||||
|
* The following fields were added by rt61pci and rt73usb.
|
||||||
|
*/
|
||||||
|
CIPHER_CKIP64 = 5,
|
||||||
|
CIPHER_CKIP128 = 6,
|
||||||
|
CIPHER_TKIP_NO_MIC = 7, /* Don't send to device */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Max cipher type.
|
||||||
|
* Note that CIPHER_NONE isn't counted, and CKIP64 and CKIP128
|
||||||
|
* are excluded due to limitations in mac80211.
|
||||||
|
*/
|
||||||
|
CIPHER_MAX = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rate modulations
|
||||||
|
*/
|
||||||
|
enum rate_modulation {
|
||||||
|
RATE_MODE_CCK = 0,
|
||||||
|
RATE_MODE_OFDM = 1,
|
||||||
|
RATE_MODE_HT_MIX = 2,
|
||||||
|
RATE_MODE_HT_GREENFIELD = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Firmware validation error codes
|
||||||
|
*/
|
||||||
|
enum firmware_errors {
|
||||||
|
FW_OK,
|
||||||
|
FW_BAD_CRC,
|
||||||
|
FW_BAD_LENGTH,
|
||||||
|
FW_BAD_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register handlers.
|
||||||
|
* We store the position of a register field inside a field structure,
|
||||||
|
* This will simplify the process of setting and reading a certain field
|
||||||
|
* inside the register while making sure the process remains byte order safe.
|
||||||
|
*/
|
||||||
|
struct rt2x00_field8 {
|
||||||
|
u8 bit_offset;
|
||||||
|
u8 bit_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rt2x00_field16 {
|
||||||
|
u16 bit_offset;
|
||||||
|
u16 bit_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rt2x00_field32 {
|
||||||
|
u32 bit_offset;
|
||||||
|
u32 bit_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Power of two check, this will check
|
||||||
|
* if the mask that has been given contains and contiguous set of bits.
|
||||||
|
* Note that we cannot use the is_power_of_2() function since this
|
||||||
|
* check must be done at compile-time.
|
||||||
|
*/
|
||||||
|
#define is_power_of_two(x) ( !((x) & ((x)-1)) )
|
||||||
|
#define low_bit_mask(x) ( ((x)-1) & ~(x) )
|
||||||
|
#define is_valid_mask(x) is_power_of_two(1LU + (x) + low_bit_mask(x))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros to find first set bit in a variable.
|
||||||
|
* These macros behave the same as the __ffs() functions but
|
||||||
|
* the most important difference that this is done during
|
||||||
|
* compile-time rather then run-time.
|
||||||
|
*/
|
||||||
|
#define compile_ffs2(__x) \
|
||||||
|
__builtin_choose_expr(((__x) & 0x1), 0, 1)
|
||||||
|
|
||||||
|
#define compile_ffs4(__x) \
|
||||||
|
__builtin_choose_expr(((__x) & 0x3), \
|
||||||
|
(compile_ffs2((__x))), \
|
||||||
|
(compile_ffs2((__x) >> 2) + 2))
|
||||||
|
|
||||||
|
#define compile_ffs8(__x) \
|
||||||
|
__builtin_choose_expr(((__x) & 0xf), \
|
||||||
|
(compile_ffs4((__x))), \
|
||||||
|
(compile_ffs4((__x) >> 4) + 4))
|
||||||
|
|
||||||
|
#define compile_ffs16(__x) \
|
||||||
|
__builtin_choose_expr(((__x) & 0xff), \
|
||||||
|
(compile_ffs8((__x))), \
|
||||||
|
(compile_ffs8((__x) >> 8) + 8))
|
||||||
|
|
||||||
|
#define compile_ffs32(__x) \
|
||||||
|
__builtin_choose_expr(((__x) & 0xffff), \
|
||||||
|
(compile_ffs16((__x))), \
|
||||||
|
(compile_ffs16((__x) >> 16) + 16))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This macro will check the requirements for the FIELD{8,16,32} macros
|
||||||
|
* The mask should be a constant non-zero contiguous set of bits which
|
||||||
|
* does not exceed the given typelimit.
|
||||||
|
*/
|
||||||
|
#define FIELD_CHECK(__mask, __type) \
|
||||||
|
BUILD_BUG_ON(!(__mask) || \
|
||||||
|
!is_valid_mask(__mask) || \
|
||||||
|
(__mask) != (__type)(__mask)) \
|
||||||
|
|
||||||
|
/* Modified for MSVC happiness */
|
||||||
|
#define FIELD8(__mask) \
|
||||||
|
((struct rt2x00_field8){ \
|
||||||
|
compile_ffs8(__mask), (__mask) \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define FIELD16(__mask) \
|
||||||
|
((struct rt2x00_field16) { \
|
||||||
|
compile_ffs16(__mask), (__mask) \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define FIELD32(__mask) \
|
||||||
|
((struct rt2x00_field32) { \
|
||||||
|
compile_ffs32(__mask), (__mask) \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define SET_FIELD(__reg, __type, __field, __value) \
|
||||||
|
*(__reg) = \
|
||||||
|
(*(__reg) & ~((__field).bit_mask)) | \
|
||||||
|
( ((__value) << ((__field).bit_offset)) & ((__field).bit_mask) )
|
||||||
|
|
||||||
|
#define GET_FIELD(__reg, __type, __field) \
|
||||||
|
(((__reg) & ((__field).bit_mask)) >> ((__field).bit_offset))
|
||||||
|
|
||||||
|
#define rt2x00_set_field32(__reg, __field, __value) \
|
||||||
|
SET_FIELD(__reg, struct rt2x00_field32, __field, __value)
|
||||||
|
#define rt2x00_get_field32(__reg, __field) \
|
||||||
|
GET_FIELD(__reg, struct rt2x00_field32, __field)
|
||||||
|
|
||||||
|
#define rt2x00_set_field16(__reg, __field, __value) \
|
||||||
|
SET_FIELD(__reg, struct rt2x00_field16, __field, __value)
|
||||||
|
#define rt2x00_get_field16(__reg, __field) \
|
||||||
|
GET_FIELD(__reg, struct rt2x00_field16, __field)
|
||||||
|
|
||||||
|
#define rt2x00_set_field8(__reg, __field, __value) \
|
||||||
|
SET_FIELD(__reg, struct rt2x00_field8, __field, __value)
|
||||||
|
#define rt2x00_get_field8(__reg, __field) \
|
||||||
|
GET_FIELD(__reg, struct rt2x00_field8, __field)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef RT2X00REG_H */
|
|
@ -0,0 +1,410 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
|
||||||
|
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
* <http://rt2x00.serialmonkey.com>
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <Windows.h>
|
||||||
|
#define usleep(x) Sleep((x) < 1000 ? 1 : (x) / 1000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "kernel/kernel.h"
|
||||||
|
|
||||||
|
#include "rt2800usb/rt2x00usb.h"
|
||||||
|
#include "rt2800usb/rt2x00reg.h"
|
||||||
|
|
||||||
|
#include "userspace/userspace.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interfacing with the HW.
|
||||||
|
*/
|
||||||
|
int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 request, const u8 requesttype,
|
||||||
|
const u16 offset, const u16 value,
|
||||||
|
void *buffer, const u16 buffer_length,
|
||||||
|
const int timeout) {
|
||||||
|
|
||||||
|
struct libusb_device_handle *usb_dev = rt2x00dev->dev;
|
||||||
|
|
||||||
|
int fail_count = 0;
|
||||||
|
|
||||||
|
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) {
|
||||||
|
rt2x00_err(rt2x00dev, "No device present\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we use a simplified failure count instead of measuring time, so that
|
||||||
|
* we don't introduce timeout errors on multi-platform builds; we don't
|
||||||
|
* want to depend on linux (or posix) high-precision timespec
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (rt2x00dev->control_transfer_buffer_sz < LIBUSB_CONTROL_SETUP_SIZE + buffer_length) {
|
||||||
|
if (rt2x00dev->control_transfer_buffer != NULL)
|
||||||
|
free(rt2x00dev->control_transfer_buffer);
|
||||||
|
|
||||||
|
rt2x00dev->control_transfer_buffer =
|
||||||
|
(unsigned char *) malloc(LIBUSB_CONTROL_SETUP_SIZE + buffer_length);
|
||||||
|
|
||||||
|
if (rt2x00dev->control_transfer_buffer == NULL) {
|
||||||
|
rt2x00_err(rt2x00dev, "No memory");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt2x00dev->control_transfer_buffer_sz = LIBUSB_CONTROL_SETUP_SIZE + buffer_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have to tie into the async io system with libusb here, we use a conditional
|
||||||
|
* variable to determine when our command completes
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (rt2x00dev->control_transfer == NULL)
|
||||||
|
rt2x00dev->control_transfer = libusb_alloc_transfer(0);
|
||||||
|
|
||||||
|
libusb_fill_control_setup(rt2x00dev->control_transfer_buffer, requesttype, request, value, offset, buffer_length);
|
||||||
|
memcpy(rt2x00dev->control_transfer_buffer + LIBUSB_CONTROL_SETUP_SIZE, buffer, buffer_length);
|
||||||
|
libusb_fill_control_transfer(rt2x00dev->control_transfer, usb_dev, rt2x00dev->control_transfer_buffer,
|
||||||
|
rt2x00dev_control_cb, rt2x00dev, timeout / 2);
|
||||||
|
|
||||||
|
do {
|
||||||
|
rt2x00dev->usb_command_complete = false;
|
||||||
|
libusb_submit_transfer(rt2x00dev->control_transfer);
|
||||||
|
|
||||||
|
/* Wait for the cond to unlock */
|
||||||
|
while (1) {
|
||||||
|
pthread_mutex_lock(&rt2x00dev->usb_control_mutex);
|
||||||
|
pthread_cond_wait(&rt2x00dev->usb_control_cond, &rt2x00dev->usb_control_mutex);
|
||||||
|
|
||||||
|
if (!rt2x00dev->usb_command_complete)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&rt2x00dev->usb_control_mutex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rt2x00dev->control_transfer->status == LIBUSB_TRANSFER_COMPLETED) {
|
||||||
|
memcpy(buffer, rt2x00dev->control_transfer_buffer + LIBUSB_CONTROL_SETUP_SIZE, buffer_length);
|
||||||
|
pthread_mutex_unlock(&rt2x00dev->usb_control_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rt2x00dev->control_transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
|
||||||
|
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||||
|
pthread_mutex_unlock(&rt2x00dev->usb_control_mutex);
|
||||||
|
rt2x00_err(rt2x00dev, "Device no longer available");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rt2x00dev->control_transfer->status == LIBUSB_TRANSFER_TIMED_OUT)
|
||||||
|
fail_count++;
|
||||||
|
|
||||||
|
} while (fail_count < 3);
|
||||||
|
|
||||||
|
rt2x00_err(rt2x00dev,
|
||||||
|
"Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
|
||||||
|
request, offset, rt2x00dev->control_transfer->status);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 request, const u8 requesttype,
|
||||||
|
const u16 offset, void *buffer,
|
||||||
|
const u16 buffer_length)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
unsigned char *tb;
|
||||||
|
u16 off, len, bsize;
|
||||||
|
|
||||||
|
mutex_lock(&rt2x00dev->csr_mutex);
|
||||||
|
|
||||||
|
tb = (unsigned char *)buffer;
|
||||||
|
off = offset;
|
||||||
|
len = buffer_length;
|
||||||
|
while (len && !status) {
|
||||||
|
bsize = min_t(u16, CSR_CACHE_SIZE, len);
|
||||||
|
status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
|
||||||
|
requesttype, off, tb,
|
||||||
|
bsize, REGISTER_TIMEOUT);
|
||||||
|
|
||||||
|
tb += bsize;
|
||||||
|
len -= bsize;
|
||||||
|
off += bsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&rt2x00dev->csr_mutex);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
rt2x00_err(rt2x00dev, "Radio USB request failed: %s", libusb_error_name(status));
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace buff_lock doesn't do any locking
|
||||||
|
*/
|
||||||
|
int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 request, const u8 requesttype,
|
||||||
|
const u16 offset, void *buffer,
|
||||||
|
const u16 buffer_length, const int timeout)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for Cache availability.
|
||||||
|
*/
|
||||||
|
if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
|
||||||
|
rt2x00_err(rt2x00dev, "CSR cache not available\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requesttype == USB_VENDOR_REQUEST_OUT)
|
||||||
|
memcpy(rt2x00dev->csr.cache, buffer, buffer_length);
|
||||||
|
|
||||||
|
status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
|
||||||
|
offset, 0, rt2x00dev->csr.cache,
|
||||||
|
buffer_length, timeout);
|
||||||
|
|
||||||
|
if (!status && requesttype == USB_VENDOR_REQUEST_IN)
|
||||||
|
memcpy(buffer, rt2x00dev->csr.cache, buffer_length);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
rt2x00_err(rt2x00dev, "Radio CSR USB request failed: %s", libusb_error_name(status));
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
const struct rt2x00_field32 field,
|
||||||
|
u32 *reg) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
|
||||||
|
*reg = rt2x00usb_register_read_lock(rt2x00dev, offset);
|
||||||
|
if (!rt2x00_get_field32(*reg, field))
|
||||||
|
return 1;
|
||||||
|
usleep(REGISTER_BUSY_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
|
||||||
|
offset, *reg);
|
||||||
|
*reg = ~0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rt2x00_async_read_data {
|
||||||
|
__le32 reg;
|
||||||
|
struct rt2x00_dev *rt2x00dev;
|
||||||
|
bool (*callback)(struct rt2x00_dev *, int, u32);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the userspace port, async actually blocks and then calls the
|
||||||
|
* cb; we'll find out if this causes problems
|
||||||
|
*/
|
||||||
|
void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
bool (*callback)(struct rt2x00_dev*, int, u32)) {
|
||||||
|
struct libusb_device_handle *usb_dev = rt2x00dev->dev;
|
||||||
|
struct rt2x00_async_read_data *rd;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
rd = (struct rt2x00_async_read_data *) malloc(sizeof(*rd));
|
||||||
|
if (!rd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rd->rt2x00dev = rt2x00dev;
|
||||||
|
rd->callback = callback;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implement the equivalent to rt2x00usb_register_read_async_cb and call
|
||||||
|
* the provided cb directly; if the callback says to resubmit the request,
|
||||||
|
* do so
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
status = libusb_control_transfer(usb_dev, USB_VENDOR_REQUEST_IN, USB_MULTI_READ,
|
||||||
|
0, cpu_to_le16(offset), (unsigned char *) &rd->reg, cpu_to_le16(sizeof(u32)), REGISTER_TIMEOUT);
|
||||||
|
|
||||||
|
if (rd->callback(rd->rt2x00dev, status, le32_to_cpu(rd->reg)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) {
|
||||||
|
struct libusb_config_descriptor *config = NULL;
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* interface, config, endpoint, and altsetting iterators
|
||||||
|
*/
|
||||||
|
unsigned int i, c, e;
|
||||||
|
int a;
|
||||||
|
|
||||||
|
bool found_in, found_out;
|
||||||
|
|
||||||
|
|
||||||
|
ret = libusb_get_device_descriptor(rt2x00dev->base_dev, &desc);
|
||||||
|
if (ret != LIBUSB_SUCCESS) {
|
||||||
|
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||||
|
return -EPIPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk through all available endpoints to search for "bulk in"
|
||||||
|
* and "bulk out" endpoints. When we find such endpoints collect
|
||||||
|
* the information we need from the descriptor and confirm they
|
||||||
|
* exist.
|
||||||
|
*
|
||||||
|
* We don't get to use kernel queues so for now we just confirm
|
||||||
|
* the device looks like we expect it to.
|
||||||
|
*/
|
||||||
|
for (c = 0; c < desc.bNumConfigurations; c++) {
|
||||||
|
ret = libusb_get_config_descriptor(rt2x00dev->base_dev, c, &config);
|
||||||
|
|
||||||
|
if (ret != LIBUSB_SUCCESS) {
|
||||||
|
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||||
|
rt2x00_err(rt2x00dev, "unable to retrieve device descriptors");
|
||||||
|
return -EPIPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < config->bNumInterfaces; i++) {
|
||||||
|
/*
|
||||||
|
* We expect both out and in to be on the same interface
|
||||||
|
*/
|
||||||
|
found_in = false;
|
||||||
|
found_out = false;
|
||||||
|
|
||||||
|
for (a = 0; a < config->interface[i].num_altsetting; a++) {
|
||||||
|
for (e = 0; e < config->interface[i].altsetting[a].bNumEndpoints; e++) {
|
||||||
|
if ((config->interface[i].altsetting[a].endpoint[e].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) !=
|
||||||
|
LIBUSB_TRANSFER_TYPE_BULK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!found_in &&
|
||||||
|
(config->interface[i].altsetting[a].endpoint[e].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) ==
|
||||||
|
LIBUSB_ENDPOINT_IN) {
|
||||||
|
rt2x00dev->usb_interface_num = i;
|
||||||
|
rt2x00dev->usb_bulk_in_endp = config->interface[i].altsetting[a].endpoint[e].bEndpointAddress;
|
||||||
|
found_in = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_out &&
|
||||||
|
(config->interface[i].altsetting[a].endpoint[e].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) ==
|
||||||
|
LIBUSB_ENDPOINT_OUT) {
|
||||||
|
rt2x00dev->usb_interface_num = i;
|
||||||
|
rt2x00dev->usb_bulk_out_endp = config->interface[i].altsetting[a].endpoint[e].bEndpointAddress;
|
||||||
|
found_out = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_in && found_out)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_in && found_out)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_in && found_out)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_free_config_descriptor(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At least 1 endpoint for RX and 1 endpoint for TX must be available.
|
||||||
|
*/
|
||||||
|
if (!found_in || !found_out) {
|
||||||
|
rt2x00_err(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
|
||||||
|
return -EPIPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) {
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate the driver data memory, if necessary.
|
||||||
|
*/
|
||||||
|
if (rt2x00dev->ops->drv_data_size > 0) {
|
||||||
|
rt2x00dev->drv_data = malloc(rt2x00dev->ops->drv_data_size);
|
||||||
|
if (!rt2x00dev->drv_data) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset(rt2x00dev->drv_data, 0, rt2x00dev->ops->drv_data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find endpoints for each queue
|
||||||
|
*/
|
||||||
|
status = rt2x00usb_find_endpoints(rt2x00dev);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev) {
|
||||||
|
rt2x00dev->csr.cache = malloc(CSR_CACHE_SIZE);
|
||||||
|
if (!rt2x00dev->csr.cache) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt2x00dev->eeprom = (__le16*) malloc(rt2x00dev->ops->eeprom_size);
|
||||||
|
if (!rt2x00dev->eeprom) {
|
||||||
|
free(rt2x00dev->csr.cache);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt2x00dev->rf = (u32 *) malloc(rt2x00dev->ops->rf_size);
|
||||||
|
if (!rt2x00dev->rf) {
|
||||||
|
free(rt2x00dev->csr.cache);
|
||||||
|
free(rt2x00dev->eeprom);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt2x00usb_free(struct rt2x00_dev *rt2x00dev) {
|
||||||
|
if (rt2x00dev == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (rt2x00dev->csr.cache)
|
||||||
|
free(rt2x00dev->csr.cache);
|
||||||
|
|
||||||
|
if (rt2x00dev->eeprom)
|
||||||
|
free(rt2x00dev->eeprom);
|
||||||
|
|
||||||
|
if (rt2x00dev->rf)
|
||||||
|
free(rt2x00dev->rf);
|
||||||
|
|
||||||
|
free(rt2x00dev);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
|
||||||
|
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
|
||||||
|
* <http://rt2x00.serialmonkey.com>
|
||||||
|
*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RT2x00USB_H__
|
||||||
|
#define __RT2x00USB_H__
|
||||||
|
|
||||||
|
#include "kernel/types.h"
|
||||||
|
|
||||||
|
#include "rt2800usb/rt2x00.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum rt2x00usb_vendor_request: USB vendor commands.
|
||||||
|
*/
|
||||||
|
enum rt2x00usb_vendor_request {
|
||||||
|
USB_DEVICE_MODE = 1,
|
||||||
|
USB_SINGLE_WRITE = 2,
|
||||||
|
USB_SINGLE_READ = 3,
|
||||||
|
USB_MULTI_WRITE = 6,
|
||||||
|
USB_MULTI_READ = 7,
|
||||||
|
USB_EEPROM_WRITE = 8,
|
||||||
|
USB_EEPROM_READ = 9,
|
||||||
|
USB_LED_CONTROL = 10, /* RT73USB */
|
||||||
|
USB_RX_CONTROL = 12,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum rt2x00usb_mode_offset: Device modes offset.
|
||||||
|
*/
|
||||||
|
enum rt2x00usb_mode_offset {
|
||||||
|
USB_MODE_RESET = 1,
|
||||||
|
USB_MODE_UNPLUG = 2,
|
||||||
|
USB_MODE_FUNCTION = 3,
|
||||||
|
USB_MODE_TEST = 4,
|
||||||
|
USB_MODE_SLEEP = 7, /* RT73USB */
|
||||||
|
USB_MODE_FIRMWARE = 8, /* RT73USB */
|
||||||
|
USB_MODE_WAKEUP = 9, /* RT73USB */
|
||||||
|
USB_MODE_AUTORUN = 17, /* RT2800USB */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_vendor_request - Send register command to device
|
||||||
|
* @rt2x00dev: Pointer to &struct rt2x00_dev
|
||||||
|
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
|
||||||
|
* @requesttype: Request type &USB_VENDOR_REQUEST_*
|
||||||
|
* @offset: Register offset to perform action on
|
||||||
|
* @value: Value to write to device
|
||||||
|
* @buffer: Buffer where information will be read/written to by device
|
||||||
|
* @buffer_length: Size of &buffer
|
||||||
|
* @timeout: Operation timeout
|
||||||
|
*
|
||||||
|
* This is the main function to communicate with the device,
|
||||||
|
* the &buffer argument _must_ either be NULL or point to
|
||||||
|
* a buffer allocated by malloc. Failure to do so can lead
|
||||||
|
* to unexpected behavior depending on the architecture.
|
||||||
|
*/
|
||||||
|
int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 request, const u8 requesttype,
|
||||||
|
const u16 offset, const u16 value,
|
||||||
|
void *buffer, const u16 buffer_length,
|
||||||
|
const int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_vendor_request_buff - Send register command to device (buffered)
|
||||||
|
* @rt2x00dev: Pointer to &struct rt2x00_dev
|
||||||
|
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
|
||||||
|
* @requesttype: Request type &USB_VENDOR_REQUEST_*
|
||||||
|
* @offset: Register offset to perform action on
|
||||||
|
* @buffer: Buffer where information will be read/written to by device
|
||||||
|
* @buffer_length: Size of &buffer
|
||||||
|
*
|
||||||
|
* This function will use a previously with malloc allocated cache
|
||||||
|
* to communicate with the device. The contents of the buffer pointer
|
||||||
|
* will be copied to this cache when writing, or read from the cache
|
||||||
|
* when reading.
|
||||||
|
* Buffers send to &rt2x00usb_vendor_request _must_ be allocated with
|
||||||
|
* kmalloc. Hence the reason for using a previously allocated cache
|
||||||
|
* which has been allocated properly.
|
||||||
|
*/
|
||||||
|
int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 request, const u8 requesttype,
|
||||||
|
const u16 offset, void *buffer,
|
||||||
|
const u16 buffer_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_vendor_request_buff - Send register command to device (buffered)
|
||||||
|
* @rt2x00dev: Pointer to &struct rt2x00_dev
|
||||||
|
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
|
||||||
|
* @requesttype: Request type &USB_VENDOR_REQUEST_*
|
||||||
|
* @offset: Register offset to perform action on
|
||||||
|
* @buffer: Buffer where information will be read/written to by device
|
||||||
|
* @buffer_length: Size of &buffer
|
||||||
|
* @timeout: Operation timeout
|
||||||
|
*
|
||||||
|
* A version of &rt2x00usb_vendor_request_buff which must be called
|
||||||
|
* if the usb_cache_mutex is already held.
|
||||||
|
*/
|
||||||
|
int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 request, const u8 requesttype,
|
||||||
|
const u16 offset, void *buffer,
|
||||||
|
const u16 buffer_length, const int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_vendor_request_sw - Send single register command to device
|
||||||
|
* @rt2x00dev: Pointer to &struct rt2x00_dev
|
||||||
|
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
|
||||||
|
* @offset: Register offset to perform action on
|
||||||
|
* @value: Value to write to device
|
||||||
|
* @timeout: Operation timeout
|
||||||
|
*
|
||||||
|
* Simple wrapper around rt2x00usb_vendor_request to write a single
|
||||||
|
* command to the device. Since we don't use the buffer argument we
|
||||||
|
* don't have to worry about kmalloc here.
|
||||||
|
*/
|
||||||
|
static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const u8 request,
|
||||||
|
const u16 offset,
|
||||||
|
const u16 value,
|
||||||
|
const int timeout) {
|
||||||
|
return rt2x00usb_vendor_request(rt2x00dev, request,
|
||||||
|
USB_VENDOR_REQUEST_OUT, offset,
|
||||||
|
value, NULL, 0, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_eeprom_read - Read eeprom from device
|
||||||
|
* @rt2x00dev: Pointer to &struct rt2x00_dev
|
||||||
|
* @eeprom: Pointer to eeprom array to store the information in
|
||||||
|
* @length: Number of bytes to read from the eeprom
|
||||||
|
*
|
||||||
|
* Simple wrapper around rt2x00usb_vendor_request to read the eeprom
|
||||||
|
* from the device. Note that the eeprom argument _must_ be allocated using
|
||||||
|
* kmalloc for correct handling inside the kernel USB layer.
|
||||||
|
*/
|
||||||
|
static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
|
||||||
|
__le16 *eeprom, const u16 length) {
|
||||||
|
return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
|
||||||
|
USB_VENDOR_REQUEST_IN, 0, 0,
|
||||||
|
eeprom, length, EEPROM_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_register_read - Read 32bit register word
|
||||||
|
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||||
|
* @offset: Register offset
|
||||||
|
*
|
||||||
|
* This function is a simple wrapper for 32bit register access
|
||||||
|
* through rt2x00usb_vendor_request_buff().
|
||||||
|
*/
|
||||||
|
static inline u32 rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset) {
|
||||||
|
__le32 reg = 0;
|
||||||
|
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
|
||||||
|
USB_VENDOR_REQUEST_IN, offset,
|
||||||
|
®, sizeof(reg));
|
||||||
|
return le32_to_cpu(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_register_read_lock - Read 32bit register word
|
||||||
|
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||||
|
* @offset: Register offset
|
||||||
|
*
|
||||||
|
* This function is a simple wrapper for 32bit register access
|
||||||
|
* through rt2x00usb_vendor_req_buff_lock().
|
||||||
|
*/
|
||||||
|
static inline u32 rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset) {
|
||||||
|
__le32 reg = 0;
|
||||||
|
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
|
||||||
|
USB_VENDOR_REQUEST_IN, offset,
|
||||||
|
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||||
|
return le32_to_cpu(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_register_multiread - Read 32bit register words
|
||||||
|
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||||
|
* @offset: Register offset
|
||||||
|
* @value: Pointer to where register contents should be stored
|
||||||
|
* @length: Length of the data
|
||||||
|
*
|
||||||
|
* This function is a simple wrapper for 32bit register access
|
||||||
|
* through rt2x00usb_vendor_request_buff().
|
||||||
|
*/
|
||||||
|
static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
void *value, const u32 length) {
|
||||||
|
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
|
||||||
|
USB_VENDOR_REQUEST_IN, offset,
|
||||||
|
value, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_register_write - Write 32bit register word
|
||||||
|
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||||
|
* @offset: Register offset
|
||||||
|
* @value: Data which should be written
|
||||||
|
*
|
||||||
|
* This function is a simple wrapper for 32bit register access
|
||||||
|
* through rt2x00usb_vendor_request_buff().
|
||||||
|
*/
|
||||||
|
static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
u32 value) {
|
||||||
|
__le32 reg = cpu_to_le32(value);
|
||||||
|
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
|
||||||
|
USB_VENDOR_REQUEST_OUT, offset,
|
||||||
|
®, sizeof(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_register_write_lock - Write 32bit register word
|
||||||
|
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||||
|
* @offset: Register offset
|
||||||
|
* @value: Data which should be written
|
||||||
|
*
|
||||||
|
* This function is a simple wrapper for 32bit register access
|
||||||
|
* through rt2x00usb_vendor_req_buff_lock().
|
||||||
|
*/
|
||||||
|
static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
u32 value) {
|
||||||
|
__le32 reg = cpu_to_le32(value);
|
||||||
|
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
|
||||||
|
USB_VENDOR_REQUEST_OUT, offset,
|
||||||
|
®, sizeof(reg), REGISTER_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_register_multiwrite - Write 32bit register words
|
||||||
|
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||||
|
* @offset: Register offset
|
||||||
|
* @value: Data which should be written
|
||||||
|
* @length: Length of the data
|
||||||
|
*
|
||||||
|
* This function is a simple wrapper for 32bit register access
|
||||||
|
* through rt2x00usb_vendor_request_buff().
|
||||||
|
*/
|
||||||
|
static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
const void *value,
|
||||||
|
const u32 length) {
|
||||||
|
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
|
||||||
|
USB_VENDOR_REQUEST_OUT, offset,
|
||||||
|
(void *)value, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_regbusy_read - Read from register with busy check
|
||||||
|
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||||
|
* @offset: Register offset
|
||||||
|
* @field: Field to check if register is busy
|
||||||
|
* @reg: Pointer to where register contents should be stored
|
||||||
|
*
|
||||||
|
* This function will read the given register, and checks if the
|
||||||
|
* register is busy. If it is, it will sleep for a couple of
|
||||||
|
* microseconds before reading the register again. If the register
|
||||||
|
* is not read after a certain timeout, this function will return
|
||||||
|
* FALSE.
|
||||||
|
*/
|
||||||
|
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
const struct rt2x00_field32 field,
|
||||||
|
u32 *reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rt2x00usb_register_read_async - Asynchronously read 32bit register word
|
||||||
|
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
|
||||||
|
* @offset: Register offset
|
||||||
|
* @callback: Functon to call when read completes.
|
||||||
|
*
|
||||||
|
* Submit a control URB to read a 32bit register. This safe to
|
||||||
|
* be called from atomic context. The callback will be called
|
||||||
|
* when the URB completes. Otherwise the function is similar
|
||||||
|
* to rt2x00usb_register_read().
|
||||||
|
* When the callback function returns false, the memory will be cleaned up,
|
||||||
|
* when it returns true, the urb will be fired again.
|
||||||
|
*/
|
||||||
|
void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
|
||||||
|
const unsigned int offset,
|
||||||
|
bool (*callback)(struct rt2x00_dev*, int, u32));
|
||||||
|
|
||||||
|
int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev);
|
||||||
|
void rt2x00usb_free(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
|
||||||
|
|
||||||
|
#endif /* ifndef RT2x00USB_H */
|
|
@ -0,0 +1,832 @@
|
||||||
|
/*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 Inc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <Windows.h>
|
||||||
|
#define usleep(x) Sleep((x) < 1000 ? 1 : (x) / 1000)
|
||||||
|
#define sleep(x) Sleep(x * 1000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "userspace.h"
|
||||||
|
#include "rt2800usb/rt2800usb.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/*
|
||||||
|
* Kluge a windows time into a user time
|
||||||
|
*/
|
||||||
|
int gettimeofday(struct timeval* tp, struct timezone* tzp) {
|
||||||
|
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
|
||||||
|
|
||||||
|
SYSTEMTIME system_time;
|
||||||
|
FILETIME file_time;
|
||||||
|
uint64_t time;
|
||||||
|
|
||||||
|
GetSystemTime(&system_time);
|
||||||
|
SystemTimeToFileTime(&system_time, &file_time);
|
||||||
|
time = ((uint64_t)file_time.dwLowDateTime);
|
||||||
|
time += ((uint64_t)file_time.dwHighDateTime) << 32;
|
||||||
|
|
||||||
|
tp->tv_sec = (long)((time - EPOCH) / 10000000L);
|
||||||
|
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define timercmp(a, b, CMP) \
|
||||||
|
(((a)->tv_sec == (b)->tv_sec) ? \
|
||||||
|
((a)->tv_usec CMP (b)->tv_usec) : \
|
||||||
|
((a)->tv_sec CMP (b)->tv_sec))
|
||||||
|
|
||||||
|
#define timeradd(a, b, result) \
|
||||||
|
do { \
|
||||||
|
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
|
||||||
|
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
|
||||||
|
if ((result)->tv_usec >= 1000000) \
|
||||||
|
{ \
|
||||||
|
++(result)->tv_sec; \
|
||||||
|
(result)->tv_usec -= 1000000; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define timersub(a, b, result) \
|
||||||
|
do { \
|
||||||
|
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
|
||||||
|
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
|
||||||
|
if ((result)->tv_usec < 0) { \
|
||||||
|
--(result)->tv_sec; \
|
||||||
|
(result)->tv_usec += 1000000; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *userspace_wifi_service_thread(void *ctx) {
|
||||||
|
struct userspace_wifi_context *context = (struct userspace_wifi_context *) ctx;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
while (context->service_thread_enabled) {
|
||||||
|
r = libusb_handle_events_completed(context->libusb_context, NULL);
|
||||||
|
|
||||||
|
if (r != 0) {
|
||||||
|
userspace_wifi_error(context, NULL, r, "Failed to handle USB events: %s",
|
||||||
|
libusb_error_name(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *userspace_wifi_cmd_service_thread(void *ctx) {
|
||||||
|
struct userspace_wifi_context *context = (struct userspace_wifi_context *) ctx;
|
||||||
|
struct userspace_wifi_command *command;
|
||||||
|
|
||||||
|
while (context->cmd_thread_enabled) {
|
||||||
|
pthread_mutex_lock(&context->cmd_wakeup_mutex);
|
||||||
|
pthread_cond_wait(&context->cmd_wakeup_cond, &context->cmd_wakeup_mutex);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
pthread_mutex_lock(&context->cmd_mutex);
|
||||||
|
command = context->cmd_queue;
|
||||||
|
|
||||||
|
if (command != NULL) {
|
||||||
|
context->cmd_queue = command->next;
|
||||||
|
if (context->cmd_queue == NULL)
|
||||||
|
context->cmd_queue_last = NULL;
|
||||||
|
|
||||||
|
/* We must unlock BEFORE calling the callback */
|
||||||
|
pthread_mutex_unlock(&context->cmd_mutex);
|
||||||
|
|
||||||
|
(command->callback)(context, command->device, command->param);
|
||||||
|
|
||||||
|
free(command);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&context->cmd_mutex);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&context->cmd_wakeup_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
/* Find the last instance of the / in the path and slice everything
|
||||||
|
* after it off by chopping with a \0. Modifies the passed path. */
|
||||||
|
void chop_after_last_slash(char *path) {
|
||||||
|
char *last = path;
|
||||||
|
char *pos = NULL;
|
||||||
|
|
||||||
|
while ((pos = strstr(last + 1, "/")) != NULL) {
|
||||||
|
last = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
last[0] = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard firmware loader which looks in the specified firmware dir (if any), various
|
||||||
|
* system directories, and the libwifiuserspace share directory
|
||||||
|
*/
|
||||||
|
int userspace_load_firmware_file(const struct userspace_wifi_context *context, const char *file_name,
|
||||||
|
const char **file_hints, size_t hints_len,
|
||||||
|
uint8_t **firmware_blob, size_t *blob_len) {
|
||||||
|
FILE *fwfile = NULL;
|
||||||
|
int fwfd = -1;
|
||||||
|
struct stat statbuf;
|
||||||
|
char fw_path[2048];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
char exe_path[2048];
|
||||||
|
uint32_t exe_path_sz = 2048;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Start by looking at the context dir, if any */
|
||||||
|
if (context->firmware_directory != NULL) {
|
||||||
|
snprintf(fw_path, 2048, "%s/%s", context->firmware_directory, file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
|
||||||
|
/* Look at all the hints */
|
||||||
|
for (i = 0; i < hints_len; i++) {
|
||||||
|
snprintf(fw_path, 2048, "%s/%s/%s", context->firmware_directory, file_hints[i], file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look at the current directory */
|
||||||
|
snprintf(fw_path, 2048, "%s", file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
|
||||||
|
/* Look at all the hints */
|
||||||
|
for (i = 0; i < hints_len; i++) {
|
||||||
|
snprintf(fw_path, 2048, "%s/%s", file_hints[i], file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look at the share firmware dir */
|
||||||
|
snprintf(fw_path, 2048, "%s/%s", FIRMWAREDIR, file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
|
||||||
|
/* Look at all the hints */
|
||||||
|
for (i = 0; i < hints_len; i++) {
|
||||||
|
snprintf(fw_path, 2048, "%s/%s/%s", FIRMWAREDIR, file_hints[i], file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look at the stock linux firmware dir */
|
||||||
|
snprintf(fw_path, 2048, "%s/%s", "/lib/firmware/", file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
|
||||||
|
/* Look at all the hints */
|
||||||
|
for (i = 0; i < hints_len; i++) {
|
||||||
|
snprintf(fw_path, 2048, "%s/%s/%s", "/lib/firmware/", file_hints[i], file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look in our path in case we're on OSX and the firmware is in our framework */
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (_NSGetExecutablePath(exe_path, &exe_path_sz) == 0) {
|
||||||
|
chop_after_last_slash(exe_path);
|
||||||
|
snprintf(fw_path, 2048, "%s/%s/%s", exe_path, "../Resources/firmware/", file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
|
||||||
|
/* Look at all the hints */
|
||||||
|
for (i = 0; i < hints_len; i++) {
|
||||||
|
snprintf(fw_path, 2048, "%s/%s/%s/%s", exe_path, "../Resources/firmware/", file_hints[i], file_name);
|
||||||
|
if ((fwfile = fopen(fw_path, "rb")) != NULL)
|
||||||
|
goto got_file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
goto no_file;
|
||||||
|
|
||||||
|
got_file:
|
||||||
|
fwfd = fileno(fwfile);
|
||||||
|
if (fstat(fwfd, &statbuf) != 0) {
|
||||||
|
fclose(fwfile);
|
||||||
|
|
||||||
|
userspace_wifi_error(context, NULL, -ENOENT, "Could not find firmware file '%s'",
|
||||||
|
file_name);
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (!S_ISREG(statbuf.st_mode)) {
|
||||||
|
fclose(fwfile);
|
||||||
|
|
||||||
|
userspace_wifi_error(context, NULL, -ENOENT, "Firmware file '%s' not a normal file",
|
||||||
|
file_name);
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(*firmware_blob) = (uint8_t *) malloc(statbuf.st_size);
|
||||||
|
if ((*firmware_blob) == NULL) {
|
||||||
|
fclose(fwfile);
|
||||||
|
goto no_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
*blob_len = statbuf.st_size;
|
||||||
|
|
||||||
|
fread((*firmware_blob), *blob_len, 1, fwfile);
|
||||||
|
|
||||||
|
fclose(fwfile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
no_file:
|
||||||
|
userspace_wifi_error(context, NULL, -ENOENT, "Could not find firmware file '%s' in "
|
||||||
|
"any of the standard locations. Make sure you've installed the required "
|
||||||
|
"firmware files.", file_name);
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
no_mem:
|
||||||
|
userspace_wifi_error(context, NULL, -ENOENT, "Could not allocate memory to load "
|
||||||
|
"firmware file '%s'", file_name);
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_init(struct userspace_wifi_context **context) {
|
||||||
|
/* int status; */
|
||||||
|
|
||||||
|
*context = (struct userspace_wifi_context *) malloc(sizeof(struct userspace_wifi_context));
|
||||||
|
|
||||||
|
if (*context == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memset(*context, 0, sizeof(struct userspace_wifi_context));
|
||||||
|
|
||||||
|
(*context)->devs = NULL;
|
||||||
|
(*context)->devs_cnt = 0;
|
||||||
|
(*context)->service_device_count = 0;
|
||||||
|
|
||||||
|
(*context)->load_firmware_file = &userspace_load_firmware_file;
|
||||||
|
|
||||||
|
/*
|
||||||
|
status = libusb_init(&(*context)->libusb_context);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
*/
|
||||||
|
|
||||||
|
pthread_mutex_init(&(*context)->libusb_mutex, NULL);
|
||||||
|
|
||||||
|
(*context)->cmd_thread_enabled = true;
|
||||||
|
pthread_mutex_init(&(*context)->cmd_mutex, NULL);
|
||||||
|
pthread_mutex_init(&(*context)->cmd_wakeup_mutex, NULL);
|
||||||
|
pthread_cond_init(&(*context)->cmd_wakeup_cond, NULL);
|
||||||
|
pthread_create(&(*context)->cmd_thread, NULL, userspace_wifi_cmd_service_thread, (*context));
|
||||||
|
|
||||||
|
pthread_mutex_init(&(*context)->led_ts_mutex, NULL);
|
||||||
|
pthread_mutex_init(&(*context)->led_cond_mutex, NULL);
|
||||||
|
pthread_cond_init(&(*context)->led_cond, NULL);
|
||||||
|
(*context)->led_devs = NULL;
|
||||||
|
(*context)->led_thread_enable = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void userspace_wifi_free(struct userspace_wifi_context *context) {
|
||||||
|
if (context != NULL) {
|
||||||
|
context->service_thread_enabled = false;
|
||||||
|
|
||||||
|
if (context->devs != NULL) {
|
||||||
|
libusb_free_device_list(context->devs, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->libusb_context != NULL)
|
||||||
|
libusb_exit(context->libusb_context);
|
||||||
|
|
||||||
|
if (context->service_thread_active) {
|
||||||
|
pthread_join(context->async_service_thread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_probe(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_probe_dev **devices) {
|
||||||
|
struct userspace_wifi_probe_dev *probe_dev;
|
||||||
|
int i, ret;
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
struct libusb_device_handle *handle;
|
||||||
|
int probed_count = 0;
|
||||||
|
|
||||||
|
if (context->devs != NULL)
|
||||||
|
libusb_free_device_list(context->devs, 1);
|
||||||
|
|
||||||
|
if (context->libusb_context != NULL)
|
||||||
|
libusb_exit(context->libusb_context);
|
||||||
|
|
||||||
|
libusb_init(&context->libusb_context);
|
||||||
|
|
||||||
|
context->devs = NULL;
|
||||||
|
|
||||||
|
*devices = NULL;
|
||||||
|
|
||||||
|
context->devs_cnt = libusb_get_device_list(context->libusb_context, &(context->devs));
|
||||||
|
|
||||||
|
if (context->devs_cnt <= 0)
|
||||||
|
return context->devs_cnt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan via each of the userspace drivers
|
||||||
|
*/
|
||||||
|
for (i = 0; context->devs[i]; ++i) {
|
||||||
|
ret = libusb_get_device_descriptor(context->devs[i], &desc);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = libusb_open(context->devs[i], &handle);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For each supported driver, probe until we get a match.
|
||||||
|
* For each match, add it to our count and our linked list
|
||||||
|
*/
|
||||||
|
if (rt2800usb_probe_device(&desc, &probe_dev) > 0) {
|
||||||
|
probe_dev->context = context;
|
||||||
|
|
||||||
|
probe_dev->dev = context->devs[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Collect as much info about the device as we can, we need it to
|
||||||
|
* identify grouped devices for some platforms
|
||||||
|
*/
|
||||||
|
probe_dev->usb_bus = libusb_get_bus_number(context->devs[i]);
|
||||||
|
probe_dev->usb_port = libusb_get_port_number(context->devs[i]);
|
||||||
|
probe_dev->usb_device = libusb_get_device_address(context->devs[i]);
|
||||||
|
|
||||||
|
ret = libusb_get_port_numbers(context->devs[i], probe_dev->usb_bus_path, 8);
|
||||||
|
if (ret > 0) {
|
||||||
|
probe_dev->usb_bus_path_len = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc.iSerialNumber) {
|
||||||
|
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
|
||||||
|
probe_dev->usb_serial, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
probe_dev->next = *devices;
|
||||||
|
*devices = probe_dev;
|
||||||
|
probe_dev = NULL;
|
||||||
|
|
||||||
|
probed_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_close(handle);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return probed_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void userspace_wifi_free_probe(struct userspace_wifi_probe_dev *devices) {
|
||||||
|
struct userspace_wifi_probe_dev *next;
|
||||||
|
|
||||||
|
while (devices != NULL) {
|
||||||
|
next = devices->next;
|
||||||
|
|
||||||
|
if (devices->driver_name)
|
||||||
|
free(devices->driver_name);
|
||||||
|
if (devices->device_type)
|
||||||
|
free(devices->device_type);
|
||||||
|
|
||||||
|
free(devices);
|
||||||
|
devices = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void userspace_wifi_for_each_probe(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_probe_dev *devices,
|
||||||
|
int (*cb)(struct userspace_wifi_context *, struct userspace_wifi_probe_dev *)) {
|
||||||
|
struct userspace_wifi_probe_dev *next = devices;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
while (next != NULL) {
|
||||||
|
r = (*cb)(context, next);
|
||||||
|
|
||||||
|
if (r)
|
||||||
|
return;
|
||||||
|
|
||||||
|
next = next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void userspace_wifi_handle_usbio(struct userspace_wifi_context *context) {
|
||||||
|
context->service_thread_enabled = true;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
while (context->service_thread_enabled) {
|
||||||
|
r = libusb_handle_events_completed(context->libusb_context, NULL);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
userspace_wifi_error(context, NULL, r, "Handling USB IO queue failed: %s",
|
||||||
|
libusb_error_name(r));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_device_open(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_probe_dev *probedevice,
|
||||||
|
struct userspace_wifi_dev **device) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!context->service_thread_enabled) {
|
||||||
|
context->service_thread_enabled = true;
|
||||||
|
context->service_thread_active = true;
|
||||||
|
pthread_create(&context->async_service_thread, NULL, userspace_wifi_service_thread, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = (*(probedevice->open_device))(probedevice, device);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
userspace_wifi_error(context, *device, r, "Opening device failed");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (!context->service_thread_active) {
|
||||||
|
context->service_thread_enabled = true;
|
||||||
|
context->service_thread_active = true;
|
||||||
|
context->service_device_count++;
|
||||||
|
|
||||||
|
pthread_create(&(context->async_service_thread), NULL, userspace_wifi_service_thread, context);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queue work to the end of the worker queue
|
||||||
|
*/
|
||||||
|
void userspace_wifi_queue_work(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void (*callback)(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void *param), void *param) {
|
||||||
|
|
||||||
|
struct userspace_wifi_command *cmd =
|
||||||
|
(struct userspace_wifi_command *) malloc(sizeof(struct userspace_wifi_command));
|
||||||
|
|
||||||
|
cmd->next = NULL;
|
||||||
|
cmd->device = device;
|
||||||
|
cmd->callback = callback;
|
||||||
|
cmd->param = param;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&context->cmd_mutex);
|
||||||
|
|
||||||
|
cmd->id = context->work_id++;
|
||||||
|
|
||||||
|
if (context->cmd_queue == NULL) {
|
||||||
|
context->cmd_queue = cmd;
|
||||||
|
context->cmd_queue_last = cmd;
|
||||||
|
} else {
|
||||||
|
context->cmd_queue_last->next = cmd;
|
||||||
|
context->cmd_queue_last = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signal the worker thread */
|
||||||
|
pthread_cond_signal(&context->cmd_wakeup_cond);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&context->cmd_mutex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _userspace_wifi_start_capture_cb(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void *param) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO handle error and backpropagate
|
||||||
|
*/
|
||||||
|
device->start_capture(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_device_start_capture(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device) {
|
||||||
|
userspace_wifi_queue_work(context, device, &_userspace_wifi_start_capture_cb, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _userspace_wifi_stop_capture_cb(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void *param) {
|
||||||
|
|
||||||
|
device->start_capture(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_device_stop_capture(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device) {
|
||||||
|
userspace_wifi_queue_work(context, device, &_userspace_wifi_stop_capture_cb, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _userspace_wifi_channel_param {
|
||||||
|
int channel;
|
||||||
|
enum nl80211_chan_width width;
|
||||||
|
};
|
||||||
|
|
||||||
|
void _userspace_wifi_channel_cb(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void *param) {
|
||||||
|
struct _userspace_wifi_channel_param *ch = (struct _userspace_wifi_channel_param *) param;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO handle error and backpropagate
|
||||||
|
*/
|
||||||
|
|
||||||
|
r = device->set_channel(device, ch->channel, ch->width);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
userspace_wifi_error(context, device, r, "Setting channel %d:%d failed: %d / %s",
|
||||||
|
ch->channel, ch->width, r, strerror(r));
|
||||||
|
|
||||||
|
free(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_device_set_channel(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
int channel, enum nl80211_chan_width width) {
|
||||||
|
struct _userspace_wifi_channel_param *p =
|
||||||
|
(struct _userspace_wifi_channel_param *) malloc(sizeof(struct _userspace_wifi_channel_param));
|
||||||
|
|
||||||
|
if (p == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
p->channel = channel;
|
||||||
|
p->width = width;
|
||||||
|
|
||||||
|
userspace_wifi_queue_work(context, dev, &_userspace_wifi_channel_cb, p);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _userspace_wifi_led_on(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void *param) {
|
||||||
|
device->set_led(device, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _userspace_wifi_led_off(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void *param) {
|
||||||
|
device->set_led(device, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_device_set_led(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev, bool enable) {
|
||||||
|
if (enable)
|
||||||
|
userspace_wifi_queue_work(context, dev, &_userspace_wifi_led_on, NULL);
|
||||||
|
else
|
||||||
|
userspace_wifi_queue_work(context, dev, &_userspace_wifi_led_off, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *_userspace_wifi_led_thread(void *ctx) {
|
||||||
|
struct userspace_wifi_context *context = (struct userspace_wifi_context *) ctx;
|
||||||
|
|
||||||
|
struct userspace_wifi_dev_led *led;
|
||||||
|
|
||||||
|
struct timeval now;
|
||||||
|
struct timeval diff_ts;
|
||||||
|
struct timeval sleep_ts;
|
||||||
|
|
||||||
|
while (context->led_thread_enable) {
|
||||||
|
sleep_ts.tv_sec = 0;
|
||||||
|
sleep_ts.tv_usec = 0;
|
||||||
|
|
||||||
|
diff_ts.tv_sec = 0;
|
||||||
|
diff_ts.tv_usec = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&context->led_ts_mutex);
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
|
led = context->led_devs;
|
||||||
|
|
||||||
|
while (led) {
|
||||||
|
if (led->trigger_ts.tv_sec == 0) {
|
||||||
|
led = led->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Did we miss the timer?
|
||||||
|
*/
|
||||||
|
if (timercmp(&led->trigger_ts, &now, <=)) {
|
||||||
|
/*
|
||||||
|
* Zero out the trigger
|
||||||
|
*/
|
||||||
|
led->trigger_ts.tv_sec = 0;
|
||||||
|
|
||||||
|
userspace_wifi_device_set_led(context, led->dev, led->restore_state);
|
||||||
|
|
||||||
|
led = led->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Otherwise we're still waiting; Figure out when to wake up. We want to find
|
||||||
|
* the most likely next timer.
|
||||||
|
*/
|
||||||
|
timersub(&led->trigger_ts, &now, &diff_ts);
|
||||||
|
|
||||||
|
if (timercmp(&sleep_ts, &diff_ts, <)) {
|
||||||
|
sleep_ts.tv_sec = diff_ts.tv_sec;
|
||||||
|
sleep_ts.tv_usec = diff_ts.tv_usec;
|
||||||
|
|
||||||
|
if (sleep_ts.tv_sec > 0) {
|
||||||
|
printf("something weird in sleep for device %d: %lu secs\n", led->dev->dev_id, sleep_ts.tv_sec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
led = led->next;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&context->led_ts_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sleep the shortest amount of time and try all the timers again without
|
||||||
|
* waiting for a cond signal
|
||||||
|
*/
|
||||||
|
if (sleep_ts.tv_sec != 0 || sleep_ts.tv_usec != 0) {
|
||||||
|
sleep(sleep_ts.tv_sec);
|
||||||
|
usleep(sleep_ts.tv_usec);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Otherwise we've handled all extant timers, sleep the thread until we get a
|
||||||
|
* conditional kick
|
||||||
|
*/
|
||||||
|
|
||||||
|
pthread_mutex_lock(&context->led_cond_mutex);
|
||||||
|
pthread_cond_wait(&context->led_cond, &context->led_cond_mutex);
|
||||||
|
pthread_mutex_unlock(&context->led_cond_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _userspace_wifi_start_led_thread(struct userspace_wifi_context *context) {
|
||||||
|
context->led_thread_enable = true;
|
||||||
|
pthread_create(&context->led_thread, NULL, _userspace_wifi_led_thread, context);
|
||||||
|
pthread_cond_signal(&context->led_cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _userspace_wifi_kill_led_thread(struct userspace_wifi_context *context) {
|
||||||
|
context->led_thread_enable = false;
|
||||||
|
pthread_cond_signal(&context->led_cond);
|
||||||
|
pthread_join(context->led_thread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_device_enable_led_control(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device) {
|
||||||
|
|
||||||
|
struct userspace_wifi_dev_led *led =
|
||||||
|
(struct userspace_wifi_dev_led *) malloc(sizeof(struct userspace_wifi_dev_led));
|
||||||
|
|
||||||
|
if (led == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memset(led, 0, sizeof(struct userspace_wifi_dev_led));
|
||||||
|
|
||||||
|
device->led_control = led;
|
||||||
|
led->dev = device;
|
||||||
|
led->next = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&context->led_ts_mutex);
|
||||||
|
led->next = context->led_devs;
|
||||||
|
context->led_devs = led;
|
||||||
|
|
||||||
|
if (!context->led_thread_enable)
|
||||||
|
_userspace_wifi_start_led_thread(context);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&context->led_ts_mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void userspace_wifi_device_disable_led_control(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device) {
|
||||||
|
|
||||||
|
struct userspace_wifi_dev_led *led = NULL, *removal = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&context->led_ts_mutex);
|
||||||
|
led = context->led_devs;
|
||||||
|
|
||||||
|
if (led == device->led_control) {
|
||||||
|
context->led_devs = led->next;
|
||||||
|
removal = led;
|
||||||
|
} else {
|
||||||
|
while (led) {
|
||||||
|
if (led->next == device->led_control) {
|
||||||
|
led->next = device->led_control->next;
|
||||||
|
removal = led;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
led = led->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!removal) {
|
||||||
|
pthread_mutex_unlock(&context->led_ts_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(removal);
|
||||||
|
device->led_control = NULL;
|
||||||
|
|
||||||
|
if (context->led_devs == NULL)
|
||||||
|
_userspace_wifi_kill_led_thread(context);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&context->led_ts_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int userspace_wifi_device_blink_led(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
unsigned int duration_us, bool restore_state,
|
||||||
|
bool extend) {
|
||||||
|
|
||||||
|
struct timeval add_ts = {
|
||||||
|
.tv_sec = 0,
|
||||||
|
.tv_usec = duration_us
|
||||||
|
};
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
|
if (device->led_control == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&context->led_ts_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only toggle the LED if we're not in a timer
|
||||||
|
*/
|
||||||
|
if (device->led_control->trigger_ts.tv_sec == 0) {
|
||||||
|
userspace_wifi_device_set_led(context, device, !restore_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're extending the timer or there is no timer
|
||||||
|
*/
|
||||||
|
if (extend || device->led_control->trigger_ts.tv_sec == 0) {
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
timeradd(&now, &add_ts, &device->led_control->trigger_ts);
|
||||||
|
device->led_control->restore_state = restore_state;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wake up the thread if it isn't already in a processing state
|
||||||
|
*/
|
||||||
|
pthread_cond_signal(&context->led_cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&context->led_ts_mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,434 @@
|
||||||
|
/*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 LLC
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USERSPACE_H__
|
||||||
|
#define __USERSPACE_H__
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include "kernel/nl80211.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/usb.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace wifi USB context; this is used to store a bunch of state info
|
||||||
|
* like the USB device list which we need to keep until we shut down
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forward definitions of various stuff we need
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_dev;
|
||||||
|
struct userspace_wifi_command;
|
||||||
|
struct userspace_wifi_dev_led;
|
||||||
|
struct userspace_wifi_rx_signal;
|
||||||
|
|
||||||
|
struct userspace_wifi_context {
|
||||||
|
struct libusb_context *libusb_context;
|
||||||
|
struct libusb_device **devs;
|
||||||
|
ssize_t devs_cnt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Libusb async can't handle scheduling multiple things at once so we have to guard it
|
||||||
|
*/
|
||||||
|
pthread_mutex_t libusb_mutex;
|
||||||
|
|
||||||
|
pthread_t async_service_thread;
|
||||||
|
bool service_thread_enabled;
|
||||||
|
bool service_thread_active;
|
||||||
|
int service_device_count;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't perform operations on the service thread so we have to process them
|
||||||
|
* through a helper thread
|
||||||
|
*/
|
||||||
|
pthread_t cmd_thread;
|
||||||
|
bool cmd_thread_enabled;
|
||||||
|
pthread_mutex_t cmd_mutex;
|
||||||
|
|
||||||
|
pthread_mutex_t cmd_wakeup_mutex;
|
||||||
|
pthread_cond_t cmd_wakeup_cond;
|
||||||
|
struct userspace_wifi_command *cmd_queue;
|
||||||
|
struct userspace_wifi_command *cmd_queue_last;
|
||||||
|
unsigned long long work_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optional, where to find the firmware. Can be set by the consumer
|
||||||
|
* to pass an alternate firmware directory. By default, firmware fetches
|
||||||
|
* look in the default directory set at install time.
|
||||||
|
*/
|
||||||
|
char *firmware_directory;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function called BY the drivers, to load firmware of a given name. Can be
|
||||||
|
* overridden in the future. Can include 'hints' from the driver to help find
|
||||||
|
* nested firmware (for instance in the linux firmware tree).
|
||||||
|
*
|
||||||
|
* Returns 0 and firmware_blob as an allocated chunk and blob_len as length,
|
||||||
|
* or negative error
|
||||||
|
*/
|
||||||
|
int (*load_firmware_file)(const struct userspace_wifi_context *context,
|
||||||
|
const char *file_name, const char **file_hints, size_t hints_len,
|
||||||
|
uint8_t **firmware_blob, size_t *blob_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper functions supplied by the consumer, called by the
|
||||||
|
* driver
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record used by the consumer to store state
|
||||||
|
*/
|
||||||
|
void *local_data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called on error, with a string and numerical error code. This being
|
||||||
|
* called indicates an unrecoverable error condition.
|
||||||
|
*
|
||||||
|
* error_str will be null terminated, but may be a pointer to a stack
|
||||||
|
* variable of the calling function. Any storage of this value must be
|
||||||
|
* copied (via strdup, etc)
|
||||||
|
*/
|
||||||
|
void (*handle_error)(const struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
const char *error_str, int error_code);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle an incoming packet and l1 signal data
|
||||||
|
*/
|
||||||
|
int (*handle_packet_rx)(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
struct userspace_wifi_rx_signal *signal,
|
||||||
|
unsigned char *data, unsigned int len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Blinking LEDs takes a surprising amount of work! We need to run
|
||||||
|
* another thread that knows when to turn them off.
|
||||||
|
*/
|
||||||
|
pthread_t led_thread;
|
||||||
|
bool led_thread_enable;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trigger condition for waking up a sleeping LED control thread
|
||||||
|
*/
|
||||||
|
pthread_mutex_t led_cond_mutex;
|
||||||
|
pthread_cond_t led_cond;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access control mutex for adding/removing devices from the LED control list
|
||||||
|
*/
|
||||||
|
pthread_mutex_t led_ts_mutex;
|
||||||
|
struct userspace_wifi_dev_led *led_devs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to track each device we control for LEDs; we need to know when to turn
|
||||||
|
* the LED on or off, and what state to return it to.
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_dev_led {
|
||||||
|
struct userspace_wifi_dev_led *next;
|
||||||
|
|
||||||
|
struct userspace_wifi_dev *dev;
|
||||||
|
struct timeval trigger_ts;
|
||||||
|
bool restore_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void userspace_wifi_lock(struct userspace_wifi_context *context) {
|
||||||
|
pthread_mutex_lock(&context->libusb_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void userspace_wifi_unlock(struct userspace_wifi_context *context) {
|
||||||
|
pthread_mutex_unlock(&context->libusb_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command thread interactions take place using a generic structure which the command
|
||||||
|
* handlers fill in
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_command {
|
||||||
|
struct userspace_wifi_command *next;
|
||||||
|
|
||||||
|
struct userspace_wifi_dev *device;
|
||||||
|
void (*callback)(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void *param);
|
||||||
|
void *param;
|
||||||
|
|
||||||
|
unsigned long long id;
|
||||||
|
};
|
||||||
|
|
||||||
|
void userspace_wifi_queue_work(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
void (*callback)(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
void *param), void *param);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace USB device list populated by the scanning function, and used
|
||||||
|
* to open a userspace USB Wi-Fi device
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_probe_dev {
|
||||||
|
/*
|
||||||
|
* Context to pass along
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_context *context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device that we matched against from the raw hw list
|
||||||
|
*/
|
||||||
|
const struct usb_device_id *device_id_match;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Libusb device we could open as a device_handle
|
||||||
|
*/
|
||||||
|
libusb_device *dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arbitrary name and type
|
||||||
|
*/
|
||||||
|
char *driver_name;
|
||||||
|
char *device_type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bus and device location
|
||||||
|
*/
|
||||||
|
int usb_bus;
|
||||||
|
int usb_port;
|
||||||
|
int usb_device;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB serial number of device
|
||||||
|
*/
|
||||||
|
unsigned char usb_serial[64];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB bus path
|
||||||
|
*/
|
||||||
|
uint8_t usb_bus_path[8];
|
||||||
|
int usb_bus_path_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opening function supplied by the driver that found us, opens a *dev into a userspace dev
|
||||||
|
*/
|
||||||
|
int (*open_device)(struct userspace_wifi_probe_dev *dev, struct userspace_wifi_dev **udev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linked list of N possible devices to open
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_probe_dev *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace USB wifi device after it's been opened, with helper functions added by the
|
||||||
|
* userspace driver
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_dev {
|
||||||
|
/*
|
||||||
|
* overall context, needed for locks
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_context *context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arbitrary device id
|
||||||
|
*/
|
||||||
|
int dev_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* device hardware/eeprom MAC, if available
|
||||||
|
*/
|
||||||
|
uint8_t dev_mac[6];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB serial number of device
|
||||||
|
*/
|
||||||
|
unsigned char usb_serial[64];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record used by the driver (often to hold the usb device state)
|
||||||
|
*/
|
||||||
|
void *dev_data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Libusb device we could open as a device_handle
|
||||||
|
*/
|
||||||
|
libusb_device *dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do we continue queuing transfers?
|
||||||
|
*/
|
||||||
|
bool usb_transfer_active;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB data buffer allocated by the driver
|
||||||
|
*/
|
||||||
|
unsigned char *usb_transfer_buffer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB async transfer record allocated by the driver
|
||||||
|
*/
|
||||||
|
struct libusb_transfer *usb_transfer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper functions supplied by the driver
|
||||||
|
*/
|
||||||
|
|
||||||
|
int (*start_capture)(struct userspace_wifi_dev *dev);
|
||||||
|
void (*stop_capture)(struct userspace_wifi_dev *dev);
|
||||||
|
|
||||||
|
int (*set_channel)(struct userspace_wifi_dev *dev, int channel, enum nl80211_chan_width width);
|
||||||
|
int (*set_led)(struct userspace_wifi_dev *dev, bool enable);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pointer to the LED control object, if one exists
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_dev_led *led_control;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal data extracted from radio
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_rx_signal {
|
||||||
|
bool crc_valid;
|
||||||
|
unsigned int channel;
|
||||||
|
enum nl80211_band band;
|
||||||
|
int signal;
|
||||||
|
enum nl80211_chan_width chan_width;
|
||||||
|
bool short_gi;
|
||||||
|
unsigned int mcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the userspace usb driver system; this calls libusb init and
|
||||||
|
* allocates a context in **context. This context should be freed and
|
||||||
|
* the system shut down with free_userspace_wifi_system
|
||||||
|
*/
|
||||||
|
int userspace_wifi_init(struct userspace_wifi_context **context);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up the userspace usb driver system
|
||||||
|
*/
|
||||||
|
void userspace_wifi_free(struct userspace_wifi_context *context);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan for any supported wifi devices; returns negative error or total number
|
||||||
|
* of devices found in the probe, and populates **devices with a linked list
|
||||||
|
* of probe results.
|
||||||
|
*/
|
||||||
|
int userspace_wifi_probe(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_probe_dev **devices);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the results of a probe list
|
||||||
|
*/
|
||||||
|
void userspace_wifi_free_probe(struct userspace_wifi_probe_dev *devices);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call a function for each result of a probe list (obscuring the linked list
|
||||||
|
* internals).
|
||||||
|
* Callback should return 0 to continue or non-0 to break
|
||||||
|
*/
|
||||||
|
void userspace_wifi_for_each_probe(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_probe_dev *devices,
|
||||||
|
int (*cb)(struct userspace_wifi_context *, struct userspace_wifi_probe_dev *));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set an error handling callback
|
||||||
|
*/
|
||||||
|
static inline void userspace_wifi_set_error_cb(struct userspace_wifi_context *context,
|
||||||
|
void (*cb)(const struct userspace_wifi_context *, struct userspace_wifi_dev *,
|
||||||
|
const char *, int)) {
|
||||||
|
context->handle_error = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trigger an error
|
||||||
|
*/
|
||||||
|
static inline void userspace_wifi_error(const struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
int errnum, const char *fmt, ...) {
|
||||||
|
char buf[2048];
|
||||||
|
va_list arg_ptr;
|
||||||
|
|
||||||
|
va_start(arg_ptr, fmt);
|
||||||
|
vsnprintf(buf, 2048, fmt, arg_ptr);
|
||||||
|
va_end(arg_ptr);
|
||||||
|
|
||||||
|
if (context->handle_error != NULL) {
|
||||||
|
(*context->handle_error)(context, dev, buf, errnum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "ERROR: %s\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a callback for handling packets
|
||||||
|
*/
|
||||||
|
static inline void userspace_wifi_set_packet_cb(struct userspace_wifi_context *context,
|
||||||
|
int (*cb)(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
struct userspace_wifi_rx_signal *signal,
|
||||||
|
unsigned char *data, unsigned int len)) {
|
||||||
|
context->handle_packet_rx = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open a userspace device via the open function supplied by the driver
|
||||||
|
* Returns 0 on success, non-zero on failure. On success, allocates a usb device in *device.
|
||||||
|
*/
|
||||||
|
int userspace_wifi_device_open(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_probe_dev *probedevice,
|
||||||
|
struct userspace_wifi_dev **device);
|
||||||
|
|
||||||
|
int userspace_wifi_device_start_capture(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev);
|
||||||
|
int userspace_wifi_device_stop_capture(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev);
|
||||||
|
int userspace_wifi_device_set_channel(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
int channel, enum nl80211_chan_width width);
|
||||||
|
int userspace_wifi_device_set_led(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev, bool enable);
|
||||||
|
|
||||||
|
static inline void userspace_wifi_device_set_id(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
int id) {
|
||||||
|
dev->dev_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int userspace_wifi_device_get_id(const struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev) {
|
||||||
|
return dev->dev_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable LED controls for a specific device; this will enable the LED control thread
|
||||||
|
* if it is not already running.
|
||||||
|
*/
|
||||||
|
int userspace_wifi_device_enable_led_control(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device);
|
||||||
|
void userspace_wifi_device_disable_led_control(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device);
|
||||||
|
/*
|
||||||
|
* Blink a LED for duration_ms (setting led to !restore_state), then restore it.
|
||||||
|
* If extending, extend any existing timer by an additional duration_ms
|
||||||
|
*/
|
||||||
|
int userspace_wifi_device_blink_led(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *device,
|
||||||
|
unsigned int duration_ms, bool restore_state, bool extend);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef USERSPACE_H */
|
Binary file not shown.
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>WiFiCoconut.icns</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.hak5.wifi-coconut</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Wi-Fi Coconut</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Wi-Fi Coconut</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/osascript
|
||||||
|
|
||||||
|
|
||||||
|
tell app "Terminal"
|
||||||
|
if not (exists window 1) then reopen
|
||||||
|
activate
|
||||||
|
|
||||||
|
set UnixPath to POSIX path of ((path to me as text) & "::")
|
||||||
|
set Coconut to "exec '" & UnixPath & "wifi_coconut'"
|
||||||
|
|
||||||
|
do script Coconut
|
||||||
|
end tell
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/zsh
|
||||||
|
|
||||||
|
# Ultimately this should be in a cmake target but getting cmake to build an app
|
||||||
|
# with multiple executable components is proving extremely difficult.
|
||||||
|
|
||||||
|
|
||||||
|
# Step one: Make the basic app structure
|
||||||
|
mkdir WiFiCoconut.app
|
||||||
|
mkdir WiFiCoconut.app/Contents
|
||||||
|
mkdir WiFiCoconut.app/Contents/MacOS
|
||||||
|
mkdir WiFiCoconut.app/Contents/Framework
|
||||||
|
mkdir WiFiCoconut.app/Contents/Resources
|
||||||
|
|
||||||
|
# Step two: Copy the pieces of the app together
|
||||||
|
cp wifi_coconut WiFiCoconut.app/Contents/MacOS
|
||||||
|
cp ../macos/WiFiCoconut WiFiCoconut.app/Contents/MacOS
|
||||||
|
cp /usr/local/lib/libusb-1.0.0.dylib WiFiCoconut.app/Contents/Framework
|
||||||
|
cp -r ../libwifiuserspace/firmware WiFiCoconut.app/Contents/Resources
|
||||||
|
cp ../macos/AppIcon.icns WiFiCoconut.app/Contents/Resources/WiFiCoconut.icns
|
||||||
|
cp ../macos/Info.plist WiFiCoconut.app/Contents/
|
||||||
|
cp ../LICENSE WiFiCoconut.app/Contents/Resources
|
||||||
|
cp ../LICENSE.firmware WiFiCoconut.app/Contents/Resources
|
||||||
|
|
||||||
|
# Step three: Rewrite the native code library path
|
||||||
|
install_name_tool \
|
||||||
|
-change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib \
|
||||||
|
WiFiCoconut.app/Contents/MacOS/wifi_coconut
|
||||||
|
|
||||||
|
# At this point, WiFiCoconut.app should be built
|
||||||
|
|
|
@ -0,0 +1,363 @@
|
||||||
|
/*
|
||||||
|
This file is part of Kismet
|
||||||
|
|
||||||
|
Kismet is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Kismet 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 Kismet; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* An extremely basic ring buffer implemented as a complete header in pure C;
|
||||||
|
* for use with datasource implementations in C */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "simple_ringbuf_c.h"
|
||||||
|
|
||||||
|
/* Allocate a ring buffer
|
||||||
|
*
|
||||||
|
* Returns NULL if allocation failed
|
||||||
|
*/
|
||||||
|
kis_simple_ringbuf_t *kis_simple_ringbuf_create(size_t size) {
|
||||||
|
kis_simple_ringbuf_t *rb;
|
||||||
|
rb = (kis_simple_ringbuf_t *) malloc(sizeof(kis_simple_ringbuf_t));
|
||||||
|
|
||||||
|
if (rb == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rb->buffer = (uint8_t *) malloc(size);
|
||||||
|
|
||||||
|
if (rb->buffer == NULL) {
|
||||||
|
free(rb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb->buffer_sz = size;
|
||||||
|
rb->start_pos = 0;
|
||||||
|
rb->length = 0;
|
||||||
|
rb->mid_peek = 0;
|
||||||
|
rb->mid_commit = 0;
|
||||||
|
rb->free_peek = 0;
|
||||||
|
rb->free_commit = 0;
|
||||||
|
|
||||||
|
return rb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy a ring buffer
|
||||||
|
*/
|
||||||
|
void kis_simple_ringbuf_free(kis_simple_ringbuf_t *ringbuf) {
|
||||||
|
free(ringbuf->buffer);
|
||||||
|
free(ringbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear ring buffer
|
||||||
|
*/
|
||||||
|
void kis_simple_ringbuf_clear(kis_simple_ringbuf_t *ringbuf) {
|
||||||
|
ringbuf->start_pos = 0;
|
||||||
|
ringbuf->length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get available space
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_available(kis_simple_ringbuf_t *ringbuf) {
|
||||||
|
return ringbuf->buffer_sz - ringbuf->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get used space
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_used(kis_simple_ringbuf_t *ringbuf) {
|
||||||
|
return ringbuf->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get total space
|
||||||
|
* */
|
||||||
|
size_t kis_simple_ringbuf_size(kis_simple_ringbuf_t *ringbuf) {
|
||||||
|
return ringbuf->buffer_sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append data
|
||||||
|
*
|
||||||
|
* Returns amount written
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_write(kis_simple_ringbuf_t *ringbuf,
|
||||||
|
void *data, size_t length) {
|
||||||
|
size_t copy_start;
|
||||||
|
|
||||||
|
if (kis_simple_ringbuf_available(ringbuf) < length)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
copy_start =
|
||||||
|
(ringbuf->start_pos + ringbuf->length) % ringbuf->buffer_sz;
|
||||||
|
|
||||||
|
/* Does the write op fit w/out looping? */
|
||||||
|
if (copy_start + length < ringbuf->buffer_sz) {
|
||||||
|
memcpy(ringbuf->buffer + copy_start, data, length);
|
||||||
|
ringbuf->length += length;
|
||||||
|
|
||||||
|
return length;
|
||||||
|
} else {
|
||||||
|
/* We have to split up, figure out the length of the two chunks */
|
||||||
|
size_t chunk_a = ringbuf->buffer_sz - copy_start;
|
||||||
|
size_t chunk_b = length - chunk_a;
|
||||||
|
|
||||||
|
memcpy(ringbuf->buffer + ringbuf->start_pos + ringbuf->length, data, chunk_a);
|
||||||
|
memcpy(ringbuf->buffer, (uint8_t *) data + chunk_a, chunk_b);
|
||||||
|
|
||||||
|
/* Increase the length of the buffer */
|
||||||
|
ringbuf->length += length;
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t kis_simple_ringbuf_reserve(kis_simple_ringbuf_t *ringbuf, void **data, size_t size) {
|
||||||
|
size_t copy_start;
|
||||||
|
|
||||||
|
if (kis_simple_ringbuf_available(ringbuf) < size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (ringbuf->mid_commit) {
|
||||||
|
fprintf(stderr, "ERROR: kis_simple_ringbuf_t mid-commit when reserve called\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_start =
|
||||||
|
(ringbuf->start_pos + ringbuf->length) % ringbuf->buffer_sz;
|
||||||
|
|
||||||
|
/* Does the write op fit w/out looping? */
|
||||||
|
if (copy_start + size < ringbuf->buffer_sz) {
|
||||||
|
ringbuf->mid_commit = 1;
|
||||||
|
ringbuf->free_commit = 0;
|
||||||
|
*data = ringbuf->buffer + copy_start;
|
||||||
|
return size;
|
||||||
|
} else {
|
||||||
|
*data = malloc(size);
|
||||||
|
|
||||||
|
if (*data == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: Could not allocate split-op sz write buffer\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ringbuf->mid_commit = 1;
|
||||||
|
ringbuf->free_commit = 1;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t kis_simple_ringbuf_commit(kis_simple_ringbuf_t *ringbuf, void *data, size_t size) {
|
||||||
|
if (!ringbuf->mid_commit) {
|
||||||
|
fprintf(stderr, "ERROR: kis_simple_ringbuf_t not in a commit when commit called\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t copy_start;
|
||||||
|
|
||||||
|
copy_start =
|
||||||
|
(ringbuf->start_pos + ringbuf->length) % ringbuf->buffer_sz;
|
||||||
|
|
||||||
|
if (!ringbuf->free_commit) {
|
||||||
|
ringbuf->mid_commit = 0;
|
||||||
|
ringbuf->length += size;
|
||||||
|
return size;
|
||||||
|
} else {
|
||||||
|
/* Does the write op fit w/out looping? */
|
||||||
|
if (copy_start + size < ringbuf->buffer_sz) {
|
||||||
|
memcpy(ringbuf->buffer + copy_start, data, size);
|
||||||
|
ringbuf->length += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
} else {
|
||||||
|
/* We have to split up, figure out the length of the two chunks */
|
||||||
|
size_t chunk_a = ringbuf->buffer_sz - copy_start;
|
||||||
|
size_t chunk_b = size - chunk_a;
|
||||||
|
|
||||||
|
memcpy(ringbuf->buffer + ringbuf->start_pos + ringbuf->length, data, chunk_a);
|
||||||
|
memcpy(ringbuf->buffer, (uint8_t *) data + chunk_a, chunk_b);
|
||||||
|
|
||||||
|
/* Increase the length of the buffer */
|
||||||
|
ringbuf->length += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free a previously reserved chunk without committing it.
|
||||||
|
*/
|
||||||
|
void kis_simple_ringbuf_reserve_free(kis_simple_ringbuf_t *ringbuf, void *data) {
|
||||||
|
if (!ringbuf->mid_commit) {
|
||||||
|
fprintf(stderr, "ERROR: kis_simple_ringbuf_t not in a commit when commit_reserve_free called\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ringbuf->free_commit)
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
ringbuf->mid_commit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copies data into provided buffer. Advances ringbuf, clearing consumed data.
|
||||||
|
*
|
||||||
|
* If requested amount is not available, reads amount available and returns.
|
||||||
|
*
|
||||||
|
* Returns amount copied
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_read(kis_simple_ringbuf_t *ringbuf, void *ptr,
|
||||||
|
size_t size) {
|
||||||
|
/* Start with how much we have available - no matter what was
|
||||||
|
* requested, we can't read more than this */
|
||||||
|
size_t opsize = kis_simple_ringbuf_used(ringbuf);
|
||||||
|
|
||||||
|
if (opsize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Only read the amount we requested, if more is available */
|
||||||
|
if (opsize > size)
|
||||||
|
opsize = size;
|
||||||
|
|
||||||
|
/* Simple contiguous read */
|
||||||
|
if (ringbuf->start_pos + opsize < ringbuf->buffer_sz) {
|
||||||
|
if (ptr != NULL)
|
||||||
|
memcpy(ptr, ringbuf->buffer + ringbuf->start_pos, opsize);
|
||||||
|
ringbuf->start_pos += opsize;
|
||||||
|
ringbuf->length -= opsize;
|
||||||
|
return opsize;
|
||||||
|
} else {
|
||||||
|
/* First chunk, start to end of buffer */
|
||||||
|
size_t chunk_a = ringbuf->buffer_sz - ringbuf->start_pos;
|
||||||
|
/* Second chunk, 0 to remaining data */
|
||||||
|
size_t chunk_b = opsize - chunk_a;
|
||||||
|
|
||||||
|
if (ptr != NULL) {
|
||||||
|
memcpy(ptr, ringbuf->buffer + ringbuf->start_pos, chunk_a);
|
||||||
|
memcpy((uint8_t *) ptr + chunk_a, ringbuf->buffer, chunk_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fastforward around the ring to where we finished reading */
|
||||||
|
ringbuf->start_pos = chunk_b;
|
||||||
|
ringbuf->length -= opsize;
|
||||||
|
|
||||||
|
return opsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Peeks at data by copying into provided buffer. Does NOT advance ringbuf
|
||||||
|
* or consume data.
|
||||||
|
*
|
||||||
|
* If requested amount of data is not available, peeks amount available and
|
||||||
|
* returns;
|
||||||
|
*
|
||||||
|
* Returns amount copied
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_peek(kis_simple_ringbuf_t *ringbuf, void *ptr,
|
||||||
|
size_t size) {
|
||||||
|
/* Start with how much we have available - no matter what was
|
||||||
|
* requested, we can't read more than this */
|
||||||
|
size_t opsize = kis_simple_ringbuf_used(ringbuf);
|
||||||
|
|
||||||
|
if (opsize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Only read the amount we requested, if more is available */
|
||||||
|
if (opsize > size)
|
||||||
|
opsize = size;
|
||||||
|
|
||||||
|
/* Simple contiguous read */
|
||||||
|
if (ringbuf->start_pos + opsize < ringbuf->buffer_sz) {
|
||||||
|
memcpy(ptr, ringbuf->buffer + ringbuf->start_pos, opsize);
|
||||||
|
return opsize;
|
||||||
|
} else {
|
||||||
|
/* First chunk, start to end of buffer */
|
||||||
|
size_t chunk_a = ringbuf->buffer_sz - ringbuf->start_pos;
|
||||||
|
/* Second chunk, 0 to remaining data */
|
||||||
|
size_t chunk_b = opsize - chunk_a;
|
||||||
|
|
||||||
|
memcpy(ptr, ringbuf->buffer + ringbuf->start_pos, chunk_a);
|
||||||
|
memcpy((uint8_t *) ptr + chunk_a, ringbuf->buffer, chunk_b);
|
||||||
|
|
||||||
|
return opsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t kis_simple_ringbuf_peek_zc(kis_simple_ringbuf_t *ringbuf, void **ptr, size_t size) {
|
||||||
|
/* Start with how much we have available - no matter what was
|
||||||
|
* requested, we can't read more than this */
|
||||||
|
size_t opsize = kis_simple_ringbuf_used(ringbuf);
|
||||||
|
|
||||||
|
if (ringbuf->mid_peek) {
|
||||||
|
fprintf(stderr, "ERROR: simple_ringbuf_peek_zc mid-peek already\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opsize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Only read the amount we requested, if more is available */
|
||||||
|
if (opsize > size)
|
||||||
|
opsize = size;
|
||||||
|
|
||||||
|
/* Simple contiguous read */
|
||||||
|
if (ringbuf->start_pos + opsize < ringbuf->buffer_sz) {
|
||||||
|
ringbuf->mid_peek = 1;
|
||||||
|
ringbuf->free_peek = 0;
|
||||||
|
*ptr = ringbuf->buffer + ringbuf->start_pos;
|
||||||
|
return opsize;
|
||||||
|
} else {
|
||||||
|
/* First chunk, start to end of buffer */
|
||||||
|
size_t chunk_a = ringbuf->buffer_sz - ringbuf->start_pos;
|
||||||
|
/* Second chunk, 0 to remaining data */
|
||||||
|
size_t chunk_b = opsize - chunk_a;
|
||||||
|
|
||||||
|
*ptr = malloc(opsize);
|
||||||
|
|
||||||
|
if (*ptr == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: simple_ringbuf_peek_zc could not allocate buffer for split peek\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ringbuf->mid_peek = 1;
|
||||||
|
ringbuf->free_peek = 1;
|
||||||
|
|
||||||
|
memcpy(*ptr, ringbuf->buffer + ringbuf->start_pos, chunk_a);
|
||||||
|
memcpy((uint8_t *) *ptr + chunk_a, ringbuf->buffer, chunk_b);
|
||||||
|
|
||||||
|
return opsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kis_simple_ringbuf_peek_free(kis_simple_ringbuf_t *ringbuf, void *ptr) {
|
||||||
|
if (!ringbuf->mid_peek) {
|
||||||
|
fprintf(stderr, "ERROR: kis_simple_ringbuf_peek_free called with no peeked data\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ringbuf->free_peek)
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
|
ringbuf->mid_peek = 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
This file is part of Kismet
|
||||||
|
|
||||||
|
Kismet is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Kismet 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 Kismet; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* An extremely basic ring buffer implemented in pure C; for use with datasource
|
||||||
|
* implementations in C */
|
||||||
|
|
||||||
|
#ifndef __RINGBUF_C_H__
|
||||||
|
#define __RINGBUF_C_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct kis_simple_ringbuf {
|
||||||
|
uint8_t *buffer;
|
||||||
|
size_t buffer_sz;
|
||||||
|
size_t start_pos; /* Where reading starts from */
|
||||||
|
size_t length; /* Amount of data in the buffer */
|
||||||
|
|
||||||
|
int mid_peek, mid_commit; /* Are we in a peek or reserve? */
|
||||||
|
int free_peek, free_commit; /* Do we need to free the peek or reserved buffers */
|
||||||
|
};
|
||||||
|
typedef struct kis_simple_ringbuf kis_simple_ringbuf_t;
|
||||||
|
|
||||||
|
/* Allocate a ring buffer
|
||||||
|
*
|
||||||
|
* Returns NULL if allocation failed
|
||||||
|
*/
|
||||||
|
kis_simple_ringbuf_t *kis_simple_ringbuf_create(size_t size);
|
||||||
|
|
||||||
|
/* Destroy a ring buffer
|
||||||
|
*/
|
||||||
|
void kis_simple_ringbuf_free(kis_simple_ringbuf_t *ringbuf);
|
||||||
|
|
||||||
|
/* Clear ring buffer
|
||||||
|
*/
|
||||||
|
void kis_simple_ringbuf_clear(kis_simple_ringbuf_t *ringbuf);
|
||||||
|
|
||||||
|
/* Get available space
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_available(kis_simple_ringbuf_t *ringbuf);
|
||||||
|
|
||||||
|
/* Get used space
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_used(kis_simple_ringbuf_t *ringbuf);
|
||||||
|
|
||||||
|
/* Get total size
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_size(kis_simple_ringbuf_t *ringbuf);
|
||||||
|
|
||||||
|
/* Append data
|
||||||
|
*
|
||||||
|
* Returns amount written
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_write(kis_simple_ringbuf_t *ringbuf,
|
||||||
|
void *data, size_t length);
|
||||||
|
|
||||||
|
/* Reserve a writeable chunk, striving to make it a zero-copy operation. Only
|
||||||
|
* one chunk may be reserved at a time. A reserved chunk must be written
|
||||||
|
* with kis_simple_ringbuf_commit or discard with kis_simple_ringbuf_reserve_free
|
||||||
|
*
|
||||||
|
* Returns amount available. Returns 0 if that amount cannot be reserved because
|
||||||
|
* the buffer is full.
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_reserve(kis_simple_ringbuf_t *ringbuf, void **data, size_t size);
|
||||||
|
|
||||||
|
/* Commit a previously reserved chunk. Commits the specified number of bytes.
|
||||||
|
*
|
||||||
|
* Returns the amount committed.
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_commit(kis_simple_ringbuf_t *ringbuf, void *data, size_t size);
|
||||||
|
|
||||||
|
/* Free a previously reserved chunk without committing it.
|
||||||
|
*/
|
||||||
|
void kis_simple_ringbuf_reserve_free(kis_simple_ringbuf_t *ringbuf, void *data);
|
||||||
|
|
||||||
|
|
||||||
|
/* Copies data into provided buffer. Advances ringbuf, clearing consumed data.
|
||||||
|
*
|
||||||
|
* If requested amount is not available, reads amount available and returns.
|
||||||
|
*
|
||||||
|
* Returns amount copied
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_read(kis_simple_ringbuf_t *ringbuf, void *ptr, size_t size);
|
||||||
|
|
||||||
|
/* Peeks at data by copying into provided buffer. Does NOT advance ringbuf
|
||||||
|
* or consume data.
|
||||||
|
*
|
||||||
|
* If requested amount of data is not available, peeks amount available and
|
||||||
|
* returns;
|
||||||
|
*
|
||||||
|
* Returns amount copied
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_peek(kis_simple_ringbuf_t *ringbuf, void *ptr, size_t size);
|
||||||
|
|
||||||
|
/* Peeks at data, using a zero-copy method if possible. Does NOT advance ringbuf
|
||||||
|
* or consume data.
|
||||||
|
*
|
||||||
|
* Peeked data MUST BE 'returned' via kis_simple_ringbuf_peek_free.
|
||||||
|
*
|
||||||
|
* Returns amount peeked.
|
||||||
|
*/
|
||||||
|
size_t kis_simple_ringbuf_peek_zc(kis_simple_ringbuf_t *ringbuf, void **ptr, size_t size);
|
||||||
|
|
||||||
|
/* Frees peeked zc data. Must be called after peeking.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void kis_simple_ringbuf_peek_free(kis_simple_ringbuf_t *ringbuf, void *ptr);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,500 @@
|
||||||
|
/*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 LLC
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <Windows.h>
|
||||||
|
#define sleep(x) Sleep(x*1000)
|
||||||
|
#define usleep(x) Sleep((x) < 1000 ? 1 : (x) / 1000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "kernel/cfg80211.h"
|
||||||
|
#include "kernel/endian.h"
|
||||||
|
#include "kernel/ieee80211.h"
|
||||||
|
#include "kernel/ieee80211_radiotap.h"
|
||||||
|
|
||||||
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include "userspace/userspace.h"
|
||||||
|
|
||||||
|
struct wifi_test_context {
|
||||||
|
/*
|
||||||
|
* USB context
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_context *context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device we plan to open
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_probe_dev* probedev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The device we're operating on
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_dev *dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runtime options
|
||||||
|
*/
|
||||||
|
bool disable_leds;
|
||||||
|
bool disable_blink;
|
||||||
|
bool invert_leds;
|
||||||
|
bool no_radiotap;
|
||||||
|
bool quiet;
|
||||||
|
bool diagnostics_mode;
|
||||||
|
bool diagnostics_only;
|
||||||
|
int device_number;
|
||||||
|
int channel;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pcap logging
|
||||||
|
*/
|
||||||
|
bool enable_pcap_log;
|
||||||
|
FILE *dump_filep;
|
||||||
|
int num_packets;
|
||||||
|
pthread_mutex_t pcap_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
int open_wifi_device(struct wifi_test_context *test_context) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = userspace_wifi_device_open(test_context->context, test_context->probedev, &test_context->dev);
|
||||||
|
|
||||||
|
if (r != 0) {
|
||||||
|
printf("Failed to open device: %d %s\n", r, strerror(r));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
userspace_wifi_device_set_channel(test_context->context,
|
||||||
|
test_context->dev,
|
||||||
|
test_context->channel,
|
||||||
|
NL80211_CHAN_WIDTH_20_NOHT);
|
||||||
|
|
||||||
|
if (test_context->disable_leds)
|
||||||
|
userspace_wifi_device_set_led(test_context->context, test_context->dev, false);
|
||||||
|
else
|
||||||
|
userspace_wifi_device_set_led(test_context->context, test_context->dev, true);
|
||||||
|
|
||||||
|
if (!test_context->disable_blink)
|
||||||
|
userspace_wifi_device_enable_led_control(test_context->context, test_context->dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start_wifi_capture(struct wifi_test_context* test_context) {
|
||||||
|
/*
|
||||||
|
* If LEDs are inverted, turn off LEDs once we've enumerated all the radios.
|
||||||
|
*/
|
||||||
|
if (test_context->invert_leds)
|
||||||
|
userspace_wifi_device_set_led(test_context->context, test_context->dev, false);
|
||||||
|
|
||||||
|
userspace_wifi_device_start_capture(test_context->context, test_context->dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
|
||||||
|
#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
|
||||||
|
|
||||||
|
int open_pcap(const char *file, struct wifi_test_context *test_context) {
|
||||||
|
struct {
|
||||||
|
uint32_t magic_number; /* magic number */
|
||||||
|
uint16_t version_major; /* major version number */
|
||||||
|
uint16_t version_minor; /* minor version number */
|
||||||
|
int32_t thiszone; /* GMT to local correction */
|
||||||
|
uint32_t sigfigs; /* accuracy of timestamps */
|
||||||
|
uint32_t snaplen; /* max length of captured packets, in octets */
|
||||||
|
uint32_t network; /* data link type */
|
||||||
|
} pcap_hdr_t;
|
||||||
|
|
||||||
|
pcap_hdr_t.magic_number = 0xa1b2c3d4;
|
||||||
|
pcap_hdr_t.version_major = 2;
|
||||||
|
pcap_hdr_t.version_minor = 4;
|
||||||
|
pcap_hdr_t.thiszone = 0;
|
||||||
|
pcap_hdr_t.sigfigs = 0;
|
||||||
|
pcap_hdr_t.snaplen = 8192;
|
||||||
|
|
||||||
|
test_context->enable_pcap_log = true;
|
||||||
|
pthread_mutex_init(&test_context->pcap_mutex, NULL);
|
||||||
|
|
||||||
|
if (test_context->no_radiotap)
|
||||||
|
pcap_hdr_t.network = DLT_IEEE802_11;
|
||||||
|
else
|
||||||
|
pcap_hdr_t.network = DLT_IEEE802_11_RADIO;
|
||||||
|
|
||||||
|
if (strcmp(file, "-") == 0)
|
||||||
|
test_context->dump_filep = stdout;
|
||||||
|
else
|
||||||
|
test_context->dump_filep = fopen(file, "wb");
|
||||||
|
|
||||||
|
if (test_context->dump_filep == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: Could not open dump: %d %s\n", errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(&pcap_hdr_t, sizeof(pcap_hdr_t), 1, test_context->dump_filep);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pcap_rx_packet(struct userspace_wifi_context *context,
|
||||||
|
struct userspace_wifi_dev *dev,
|
||||||
|
struct userspace_wifi_rx_signal *signal,
|
||||||
|
unsigned char *data, unsigned int len) {
|
||||||
|
|
||||||
|
struct wifi_test_context *test_context = (struct wifi_test_context *) context->local_data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t ts_sec; /* timestamp seconds */
|
||||||
|
uint32_t ts_usec; /* timestamp microseconds */
|
||||||
|
uint32_t incl_len; /* number of octets of packet saved in file */
|
||||||
|
uint32_t orig_len; /* actual length of packet */
|
||||||
|
} pcaprec_hdr_t;
|
||||||
|
|
||||||
|
pcaprec_hdr_t pcap_hdr;
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t version;
|
||||||
|
uint16_t length;
|
||||||
|
uint32_t bitmap;
|
||||||
|
uint8_t flags;
|
||||||
|
uint8_t pad0;
|
||||||
|
uint16_t channel_freq;
|
||||||
|
uint16_t channel_flags;
|
||||||
|
uint8_t antsignal;
|
||||||
|
|
||||||
|
} _rtap_hdr;
|
||||||
|
|
||||||
|
_rtap_hdr rtap_hdr = {
|
||||||
|
.version = 0,
|
||||||
|
.length = htole16(sizeof(_rtap_hdr)),
|
||||||
|
.bitmap = htole32((1 << IEEE80211_RADIOTAP_FLAGS) |
|
||||||
|
(1 << IEEE80211_RADIOTAP_CHANNEL) |
|
||||||
|
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)),
|
||||||
|
.flags = 0,
|
||||||
|
.channel_freq = htole16(ieee80211_channel_to_frequency(signal->channel, signal->band)),
|
||||||
|
.channel_flags = 0,
|
||||||
|
.antsignal = (u8) signal->signal,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!signal->crc_valid)
|
||||||
|
rtap_hdr.flags |= IEEE80211_RADIOTAP_F_BADFCS;
|
||||||
|
|
||||||
|
if (signal->short_gi)
|
||||||
|
rtap_hdr.flags |= IEEE80211_RADIOTAP_F_SHORTGI;
|
||||||
|
|
||||||
|
if (signal->band == NL80211_BAND_2GHZ)
|
||||||
|
rtap_hdr.channel_flags |= IEEE80211_CHAN_2GHZ;
|
||||||
|
else if (signal->band == NL80211_BAND_5GHZ)
|
||||||
|
rtap_hdr.channel_flags |= IEEE80211_CHAN_5GHZ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only blink if we're told to blink.
|
||||||
|
* Default LED state is "not inverted" (so on).
|
||||||
|
* If we're inverted, we let the timer override, so active LEDs stay
|
||||||
|
* ON longer as the timer gets extended; this looks better.
|
||||||
|
*/
|
||||||
|
if (!test_context->disable_blink)
|
||||||
|
userspace_wifi_device_blink_led(context, dev, 100000, !test_context->invert_leds, test_context->invert_leds);
|
||||||
|
|
||||||
|
if (test_context->diagnostics_mode) {
|
||||||
|
fprintf(stderr, "PACKET %u %u %d %02x %02x %02x %02x %02x %02x ...\n",
|
||||||
|
len, signal->channel, signal->signal, data[0], data[1], data[2], data[3], data[4], data[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test_context->enable_pcap_log)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
pcap_hdr.ts_sec = tv.tv_sec;
|
||||||
|
pcap_hdr.ts_usec = tv.tv_usec;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&test_context->pcap_mutex);
|
||||||
|
|
||||||
|
if (test_context->no_radiotap) {
|
||||||
|
pcap_hdr.incl_len = pcap_hdr.orig_len = len;
|
||||||
|
fwrite(&pcap_hdr, sizeof(pcaprec_hdr_t), 1, test_context->dump_filep);
|
||||||
|
fwrite(data, len, 1, test_context->dump_filep);
|
||||||
|
} else {
|
||||||
|
pcap_hdr.incl_len = pcap_hdr.orig_len = sizeof(_rtap_hdr) + len;
|
||||||
|
fwrite(&pcap_hdr, sizeof(pcaprec_hdr_t), 1, test_context->dump_filep);
|
||||||
|
fwrite(&rtap_hdr, sizeof(_rtap_hdr), 1, test_context->dump_filep);
|
||||||
|
fwrite(data, len, 1, test_context->dump_filep);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_context->num_packets++;
|
||||||
|
|
||||||
|
if (!test_context->quiet && test_context->num_packets % 100 == 0)
|
||||||
|
fprintf(stderr, "Got %d packets\n", test_context->num_packets);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&test_context->pcap_mutex);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_device_list(struct userspace_wifi_probe_dev* devs) {
|
||||||
|
int dev_num = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while (devs != NULL) {
|
||||||
|
fprintf(stderr, "DEVICE %d: Driver %s USB ID %x %x ",
|
||||||
|
dev_num, devs->driver_name, devs->device_id_match->idVendor, devs->device_id_match->idProduct);
|
||||||
|
|
||||||
|
for (i = 0; i < devs->usb_bus_path_len; i++) {
|
||||||
|
fprintf(stderr, "/%u", devs->usb_bus_path[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
dev_num++;
|
||||||
|
devs = devs->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct userspace_wifi_probe_dev* find_device_by_number(int device_number, struct userspace_wifi_probe_dev* devs) {
|
||||||
|
int dev_num = 0;
|
||||||
|
|
||||||
|
if (devs == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (device_number < 0)
|
||||||
|
return devs;
|
||||||
|
|
||||||
|
while (devs != NULL) {
|
||||||
|
if (dev_num == device_number)
|
||||||
|
return devs;
|
||||||
|
dev_num++;
|
||||||
|
devs = devs->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_usage(char *argv) {
|
||||||
|
printf("Userspace Wifi Test\n");
|
||||||
|
printf("Usage: %s [options] [output file]\n", argv);
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" --list List devices and exit\n"
|
||||||
|
" --device=X If you have multiple supported Wi-Fi devices, specify\n"
|
||||||
|
" which one to use\n"
|
||||||
|
" --channel=X Set Wi-Fi Channel (1-14)\n"
|
||||||
|
" --plain-dot11 Log plain 802.11 packets instead of radiotap\n"
|
||||||
|
" formatted packets with signal and channel\n"
|
||||||
|
" --disable-leds Go fully dark; don't enable any LEDs\n"
|
||||||
|
" --invert-leds Normally we enable all the LEDs\n"
|
||||||
|
" and blink during traffic; Invert only lights\n"
|
||||||
|
" when there is traffic.\n"
|
||||||
|
" --disable-blinking Disable blinking the LEDs on traffic\n"
|
||||||
|
" --quiet Disable most output\n"
|
||||||
|
" --diagnostics Diagnostic statistics mode\n"
|
||||||
|
" --diagnostics-only Enable diagnostics-only mode, disable pcap\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
#define OPT_HELP 'h'
|
||||||
|
#define OPT_LIST 2
|
||||||
|
#define OPT_DEVNO 3
|
||||||
|
#define OPT_PLAINDOT11 5
|
||||||
|
#define OPT_DISABLELED 6
|
||||||
|
#define OPT_INVERTLED 7
|
||||||
|
#define OPT_DISABLEBLNK 8
|
||||||
|
#define OPT_QUIET 9
|
||||||
|
#define OPT_DIAG 10
|
||||||
|
#define OPT_DIAGONLY 11
|
||||||
|
#define OPT_CHANNEL 12
|
||||||
|
static struct option longopt[] = {
|
||||||
|
{ "help", no_argument, 0, OPT_HELP },
|
||||||
|
{ "list", no_argument, 0, OPT_LIST },
|
||||||
|
{ "device", required_argument, 0, OPT_DEVNO },
|
||||||
|
{ "plain-dot11", no_argument, 0, OPT_PLAINDOT11 },
|
||||||
|
{ "disable-leds", no_argument, 0, OPT_DISABLELED },
|
||||||
|
{ "invert-leds", no_argument, 0, OPT_INVERTLED },
|
||||||
|
{ "disable-blinking", no_argument, 0, OPT_DISABLEBLNK },
|
||||||
|
{ "quiet", no_argument, 0, OPT_QUIET },
|
||||||
|
{ "diagnostics", no_argument, 0, OPT_DIAG },
|
||||||
|
{ "diagnostics-only", no_argument, 0, OPT_DIAGONLY },
|
||||||
|
{ "channel", required_argument, 0, OPT_CHANNEL },
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
int option_idx = 0;
|
||||||
|
optind = 0;
|
||||||
|
opterr = 0;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
bool list_only = false;
|
||||||
|
char *pcap_fname = NULL;
|
||||||
|
|
||||||
|
struct userspace_wifi_context *context;
|
||||||
|
struct userspace_wifi_probe_dev *probed;
|
||||||
|
int probed_count;
|
||||||
|
|
||||||
|
struct wifi_test_context test_context;
|
||||||
|
|
||||||
|
memset(&test_context, 0, sizeof(struct wifi_test_context));
|
||||||
|
|
||||||
|
test_context.device_number = -1;
|
||||||
|
test_context.channel = 1;
|
||||||
|
|
||||||
|
while ((r = getopt_long(argc, argv, "h", longopt, &option_idx)) != -1) {
|
||||||
|
switch (r) {
|
||||||
|
case OPT_HELP:
|
||||||
|
/* help */
|
||||||
|
print_usage(argv[0]);
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
case OPT_LIST:
|
||||||
|
list_only = true;
|
||||||
|
break;
|
||||||
|
case OPT_DISABLELED:
|
||||||
|
test_context.disable_leds = true;
|
||||||
|
break;
|
||||||
|
case OPT_INVERTLED:
|
||||||
|
test_context.invert_leds = true;
|
||||||
|
break;
|
||||||
|
case OPT_DISABLEBLNK:
|
||||||
|
test_context.disable_blink = true;
|
||||||
|
break;
|
||||||
|
case OPT_QUIET:
|
||||||
|
test_context.quiet = true;
|
||||||
|
break;
|
||||||
|
case OPT_DEVNO:
|
||||||
|
if (sscanf(optarg, "%u", &test_context.device_number) != 1) {
|
||||||
|
print_usage(argv[0]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "Expected a number for --device, such as --device=5\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPT_PLAINDOT11:
|
||||||
|
test_context.no_radiotap = true;
|
||||||
|
break;
|
||||||
|
case OPT_DIAG:
|
||||||
|
test_context.diagnostics_mode = true;
|
||||||
|
break;
|
||||||
|
case OPT_DIAGONLY:
|
||||||
|
test_context.diagnostics_only = true;
|
||||||
|
test_context.diagnostics_mode = true;
|
||||||
|
break;
|
||||||
|
case OPT_CHANNEL:
|
||||||
|
if (sscanf(optarg, "%u", &test_context.channel) != 1) {
|
||||||
|
print_usage(argv[0]);
|
||||||
|
fprintf(stderr, "\nExpected a number for --channel, such as --channel=6\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_context.channel < 1 || test_context.channel > 14) {
|
||||||
|
print_usage(argv[0]);
|
||||||
|
fprintf(stderr, "\nExpected a channel between 1 and 14\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!list_only && !test_context.diagnostics_only && optind >= argc) {
|
||||||
|
print_usage(argv[0]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "FATAL: Expected pcap file name\n");
|
||||||
|
exit(1);
|
||||||
|
} else if (!test_context.diagnostics_only && !list_only) {
|
||||||
|
pcap_fname = strdup(argv[optind]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If LEDs are disabled, blinking is disabled
|
||||||
|
*/
|
||||||
|
if (test_context.disable_leds)
|
||||||
|
test_context.disable_blink = true;
|
||||||
|
|
||||||
|
r = userspace_wifi_init(&context);
|
||||||
|
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf(stderr, "FATAL: Failed to initialize USB subsystem, %d\n", r);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
context->local_data = &test_context;
|
||||||
|
test_context.context = context;
|
||||||
|
|
||||||
|
probed_count = userspace_wifi_probe(context, &probed);
|
||||||
|
|
||||||
|
if (probed_count == 0) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
fprintf(stderr, "ERROR: No compatible USB Wi-Fi cards found. Make sure you have a supported Wi-Fi device "
|
||||||
|
"and that you have installed the required drivers via Zadig!\n");
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
/*
|
||||||
|
* Whine about root
|
||||||
|
*/
|
||||||
|
if (getuid() != 0) {
|
||||||
|
fprintf(stderr, "ERROR: No compatible USB Wi-Fi devices found. Not running as root. Root is often required for "
|
||||||
|
"raw USB access if you are not the primary user.\n");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "ERROR: No compatible USB Wi-Fi devices found.\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (getuid() != 0) {
|
||||||
|
fprintf(stderr, "ERROR: No compatible USB Wi-Fi devices found. Not running as root. Root is typically required for "
|
||||||
|
"raw USB access; if you see no USB devices, try running as root\n");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "ERROR No compatible USB Wi-Fi devices found.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test_context.quiet)
|
||||||
|
print_device_list(probed);
|
||||||
|
|
||||||
|
if (list_only)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/* Look for the device we were asked for */
|
||||||
|
test_context.probedev = find_device_by_number(test_context.device_number, probed);
|
||||||
|
|
||||||
|
userspace_wifi_set_packet_cb(context, &pcap_rx_packet);
|
||||||
|
|
||||||
|
if (!test_context.diagnostics_only && !list_only) {
|
||||||
|
r = open_pcap(pcap_fname, &test_context);
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf(stderr, "FATAL: Could not open pcap\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open_wifi_device(&test_context);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Activate capture
|
||||||
|
*/
|
||||||
|
if (!test_context.quiet)
|
||||||
|
fprintf(stderr, "Activating capture...\n");
|
||||||
|
start_wifi_capture(&test_context);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
/* This makes win32 sad right now; not sure why
|
||||||
|
userspace_wifi_free_probe(probed);
|
||||||
|
userspace_wifi_free(context);
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,654 @@
|
||||||
|
/*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 LLC
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wifi_coconut/wifi_coconut.h"
|
||||||
|
#include "userspace/userspace.h"
|
||||||
|
|
||||||
|
struct wifi_coconut_context *init_coconut_context() {
|
||||||
|
struct wifi_coconut_context *ctx =
|
||||||
|
(struct wifi_coconut_context *) malloc(sizeof(struct wifi_coconut_context));
|
||||||
|
|
||||||
|
if (ctx == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(ctx, 0, sizeof(struct wifi_coconut_context));
|
||||||
|
|
||||||
|
pthread_mutex_init(&ctx->diagnostics.mutex, NULL);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map the bus positions to device numbers so we can open
|
||||||
|
* them in order.
|
||||||
|
*/
|
||||||
|
const int device_number_map[7][4] = {
|
||||||
|
{ 0, 1, 2, 3 },
|
||||||
|
{ 4, 5, 6, 7 },
|
||||||
|
{ 8, 9, 0, 0 },
|
||||||
|
{ 10, 0, 0, 0 },
|
||||||
|
{ 13, 0, 0, 0 },
|
||||||
|
{ 12, 0, 0, 0 },
|
||||||
|
{ 11, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
int find_coconuts_cluster(struct wifi_coconut_context *coconut_context,
|
||||||
|
struct userspace_wifi_probe_dev *devicelist,
|
||||||
|
struct wifi_coconut **coconut) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Potential coconuts we've found so far
|
||||||
|
*/
|
||||||
|
struct wifi_coconut *potential_coconuts = NULL;
|
||||||
|
struct wifi_coconut *coconut_iter = NULL;
|
||||||
|
struct wifi_coconut *matched_coconuts = NULL;
|
||||||
|
int root_number = 0;
|
||||||
|
int index_offt = 0;
|
||||||
|
struct userspace_wifi_probe_dev *device;
|
||||||
|
bool continue_descent = true;
|
||||||
|
int device_pos_num;
|
||||||
|
bool found_partial = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fallback enumeration of just 14 rt2800 radios without looking at the bus path
|
||||||
|
*/
|
||||||
|
int num_raw_devices = 0;
|
||||||
|
struct userspace_wifi_probe_dev *raw_devices[14];
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (num_raw_devices = 0; num_raw_devices < 14; num_raw_devices++)
|
||||||
|
raw_devices[num_raw_devices] = NULL;
|
||||||
|
num_raw_devices = 0;
|
||||||
|
|
||||||
|
while (continue_descent) {
|
||||||
|
device = devicelist;
|
||||||
|
|
||||||
|
continue_descent = false;
|
||||||
|
|
||||||
|
while (device) {
|
||||||
|
device_pos_num = -1;
|
||||||
|
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("device %x %x bus len %d ", device->device_id_match->idVendor, device->device_id_match->idProduct, device->usb_bus_path_len);
|
||||||
|
for (int x = 0; x < device->usb_bus_path_len; x++)
|
||||||
|
printf("/%d", device->usb_bus_path[x]);
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Immediately exclude anything that isn't homed on a nested hub
|
||||||
|
* or doesn't have the right pid/vid; We don't need to check the
|
||||||
|
* driver string because of the vid/pid matching.
|
||||||
|
*/
|
||||||
|
if (device->usb_bus_path_len + index_offt < 2 ||
|
||||||
|
device->device_id_match->idVendor != 0x148f ||
|
||||||
|
device->device_id_match->idProduct != 0x5370) {
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("invalid device, bus len too short %d offt %d\n", device->usb_bus_path_len, index_offt);
|
||||||
|
#endif
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have any device which has enough of a path to continue
|
||||||
|
* past this cycle, flag to keep going when we're done.
|
||||||
|
*/
|
||||||
|
if (device->usb_bus_path_len - index_offt > 3) {
|
||||||
|
continue_descent = true;
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
root_number = device->usb_bus_path[index_offt];
|
||||||
|
|
||||||
|
/* Look for a potential coconut that already matches root */
|
||||||
|
coconut_iter = potential_coconuts;
|
||||||
|
while (coconut_iter != NULL) {
|
||||||
|
if (coconut_iter->coconut_number == root_number)
|
||||||
|
break;
|
||||||
|
|
||||||
|
coconut_iter = coconut_iter->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make a new potential record to populate if this is the first
|
||||||
|
* device of this root tree
|
||||||
|
*/
|
||||||
|
if (coconut_iter == NULL) {
|
||||||
|
/* Allocate a coconut if it doesn't exist */
|
||||||
|
coconut_iter = (struct wifi_coconut *) malloc(sizeof(*coconut_iter));
|
||||||
|
if (coconut_iter == NULL) {
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
memset(coconut_iter, 0, sizeof(*coconut_iter));
|
||||||
|
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("setting up coconut %d\n", root_number);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the coconut
|
||||||
|
*/
|
||||||
|
coconut_iter->coconut_context = coconut_context;
|
||||||
|
coconut_iter->coconut_number = root_number;
|
||||||
|
coconut_iter->valid = true;
|
||||||
|
coconut_iter->bus_count[0] = 4;
|
||||||
|
coconut_iter->bus_count[1] = 4;
|
||||||
|
coconut_iter->bus_count[2] = 4;
|
||||||
|
coconut_iter->bus_count[3] = 2;
|
||||||
|
|
||||||
|
coconut_iter->next = potential_coconuts;
|
||||||
|
potential_coconuts = coconut_iter;
|
||||||
|
|
||||||
|
found_partial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is the coconut already in error? */
|
||||||
|
if (!coconut_iter->valid) {
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is there room in this coconut? */
|
||||||
|
if (coconut_iter->device_num >= 14) {
|
||||||
|
coconut_iter->valid = false;
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate bus layout */
|
||||||
|
if (device->usb_bus_path_len - index_offt == 3) {
|
||||||
|
if (device->usb_bus_path[index_offt + 1] < 1 ||
|
||||||
|
device->usb_bus_path[index_offt + 1] > 3 ||
|
||||||
|
device->usb_bus_path[index_offt + 2] < 1 ||
|
||||||
|
device->usb_bus_path[index_offt + 2] > 4) {
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--coconut_iter->bus_count[device->usb_bus_path[index_offt + 1]] < 0) {
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("coconut no longer valid bus count [%d] negative\n", index_offt + 1);
|
||||||
|
#endif
|
||||||
|
coconut_iter->valid = false;
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_pos_num = device_number_map[device->usb_bus_path[index_offt + 1] - 1][device->usb_bus_path[index_offt + 2] - 1];
|
||||||
|
|
||||||
|
} else if (device->usb_bus_path_len - index_offt == 2) {
|
||||||
|
if (device->usb_bus_path[index_offt + 1] < 4 ||
|
||||||
|
device->usb_bus_path[index_offt + 1] > 7) {
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("coconut no longer valid, path 2/4-7 violated\n");
|
||||||
|
#endif
|
||||||
|
coconut_iter->valid = false;
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--coconut_iter->bus_count[0] < 0) {
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("coconut no longer valid, bus count [0] negative\n");
|
||||||
|
#endif
|
||||||
|
coconut_iter->valid = false;
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_pos_num = device_number_map[device->usb_bus_path[index_offt + 1] - 1][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device_pos_num < 0 || device_pos_num >= 14) {
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("Got invalid number %d\n", device_pos_num);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
coconut_iter->probed_devices[device_pos_num] = device;
|
||||||
|
coconut_iter->device_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
device = device->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge any coconuts that were valid */
|
||||||
|
coconut_iter = potential_coconuts;
|
||||||
|
while (coconut_iter != NULL) {
|
||||||
|
struct wifi_coconut *tmp;
|
||||||
|
tmp = coconut_iter->next;
|
||||||
|
|
||||||
|
if (coconut_iter->valid && coconut_iter->device_num == 14) {
|
||||||
|
coconut_iter->next = matched_coconuts;
|
||||||
|
matched_coconuts = coconut_iter;
|
||||||
|
|
||||||
|
for (i = 0; i < 14; i++) {
|
||||||
|
if (coconut_iter->probed_devices[i] != NULL) {
|
||||||
|
memcpy(coconut_iter->first_usb_serial, coconut_iter->probed_devices[i]->usb_serial, 64);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("Invalid coconut, valid %u device num %u\n", coconut_iter->valid, coconut_iter->device_num);
|
||||||
|
#endif
|
||||||
|
free(coconut_iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
coconut_iter = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the potential list and increment down the path */
|
||||||
|
potential_coconuts = NULL;
|
||||||
|
index_offt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*coconut = matched_coconuts;
|
||||||
|
|
||||||
|
/* If we didn't find any coconuts on a nested bus, look for just 14 radios. some platforms
|
||||||
|
* like catalina are having real trouble exposing the bus tree through libusb right now.
|
||||||
|
*/
|
||||||
|
if (*coconut == NULL) {
|
||||||
|
device = devicelist;
|
||||||
|
while (device && num_raw_devices < 14) {
|
||||||
|
if (device->device_id_match->idVendor != 0x148f ||
|
||||||
|
device->device_id_match->idProduct != 0x5370) {
|
||||||
|
device = device->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_devices[num_raw_devices] = device;
|
||||||
|
num_raw_devices++;
|
||||||
|
device = device->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we found at least 14 raw compatible devices, just make a coconut out of them
|
||||||
|
* and call it good enough */
|
||||||
|
if (num_raw_devices == 14) {
|
||||||
|
coconut_iter = (struct wifi_coconut *) malloc(sizeof(*coconut_iter));
|
||||||
|
if (coconut_iter == NULL) {
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("Creating catch-all coconut-0 for 14 devices not in the right order\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset(coconut_iter, 0, sizeof(*coconut_iter));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the coconut
|
||||||
|
*/
|
||||||
|
coconut_iter->coconut_context = coconut_context;
|
||||||
|
coconut_iter->coconut_number = 0;
|
||||||
|
coconut_iter->valid = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the raw list of devices
|
||||||
|
*/
|
||||||
|
coconut_iter->device_num = 0;
|
||||||
|
for (coconut_iter->device_num = 0; coconut_iter->device_num < 14; coconut_iter->device_num++)
|
||||||
|
coconut_iter->probed_devices[coconut_iter->device_num] = raw_devices[coconut_iter->device_num];
|
||||||
|
|
||||||
|
coconut_iter->next = NULL;
|
||||||
|
|
||||||
|
*coconut = coconut_iter;
|
||||||
|
|
||||||
|
for (i = 0; i < 14; i++) {
|
||||||
|
if (coconut_iter->probed_devices[i] != NULL) {
|
||||||
|
memcpy(coconut_iter->first_usb_serial, coconut_iter->probed_devices[i]->usb_serial, 64);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*coconut == NULL) {
|
||||||
|
if (found_partial)
|
||||||
|
return WIFI_COCONUT_FIND_CLUSTER_PARTIAL;
|
||||||
|
return WIFI_COCONUT_FIND_CLUSTER_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WIFI_COCONUT_FIND_CLUSTER_OK;
|
||||||
|
|
||||||
|
failure:
|
||||||
|
#ifdef FIND_DEBUG
|
||||||
|
printf("coconut find fell into failure\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
coconut_iter = potential_coconuts;
|
||||||
|
while (coconut_iter != NULL) {
|
||||||
|
struct wifi_coconut *tmp;
|
||||||
|
|
||||||
|
tmp = coconut_iter;
|
||||||
|
coconut_iter = coconut_iter->next;
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
coconut_iter = matched_coconuts;
|
||||||
|
while (coconut_iter != NULL) {
|
||||||
|
struct wifi_coconut *tmp;
|
||||||
|
|
||||||
|
tmp = coconut_iter;
|
||||||
|
coconut_iter = coconut_iter->next;
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_coconuts(struct wifi_coconut *coconuts) {
|
||||||
|
struct wifi_coconut *next;
|
||||||
|
|
||||||
|
while (coconuts) {
|
||||||
|
next = coconuts->next;
|
||||||
|
free(coconuts);
|
||||||
|
coconuts = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_wifi_coconuts(struct wifi_coconut *coconuts) {
|
||||||
|
struct wifi_coconut *iter = coconuts;
|
||||||
|
|
||||||
|
while (iter != NULL) {
|
||||||
|
fprintf(stderr, "I've got a lovely bunch of coconuts! coconut-%d\n", iter->coconut_number);
|
||||||
|
iter = iter->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int coconut_search_and_open(struct wifi_coconut_context *coconut_context,
|
||||||
|
bool wait_for_coconut, int coconut_number,
|
||||||
|
int (*status_callback)(struct wifi_coconut_context *, void *, int, int, struct wifi_coconut *),
|
||||||
|
void *cb_aux) {
|
||||||
|
struct userspace_wifi_probe_dev *probed;
|
||||||
|
int probed_count;
|
||||||
|
struct wifi_coconut *coconuts = NULL, *ci = NULL;
|
||||||
|
int r, d, htch;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
probed_count = userspace_wifi_probe(coconut_context->context, &probed);
|
||||||
|
|
||||||
|
if (probed_count == 0) {
|
||||||
|
if (status_callback != NULL) {
|
||||||
|
r = (*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_NO_RADIOS, -1, NULL);
|
||||||
|
|
||||||
|
/* Override waiting for a coconut if the callback returns a 'do not
|
||||||
|
* continue'; such as running as non-root */
|
||||||
|
if (r < 0)
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_NO_RADIOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wait_for_coconut)
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_NO_RADIOS;
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = find_coconuts_cluster(coconut_context, probed, &coconuts);
|
||||||
|
|
||||||
|
if (coconuts == NULL) {
|
||||||
|
userspace_wifi_free_probe(probed);
|
||||||
|
probed = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We actually ignore the cluster return value here; we'd only
|
||||||
|
* have gotten this far if we found SOME usb radios, just not what
|
||||||
|
* we need.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (status_callback != NULL) {
|
||||||
|
r = (*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_NO_COCONUT, -1, NULL);
|
||||||
|
|
||||||
|
/* Allow the callback to reject a continued wait */
|
||||||
|
if (r < 0)
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_NO_COCONUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wait_for_coconut)
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_NO_COCONUT;
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_callback != NULL) {
|
||||||
|
r = (*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_LIST, -1, coconuts);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coconut_number >= 0) {
|
||||||
|
ci = coconuts;
|
||||||
|
|
||||||
|
while (ci != NULL) {
|
||||||
|
if (ci->coconut_number == coconut_number) {
|
||||||
|
coconut_context->coconut = ci;
|
||||||
|
coconut_context->coconut_number = coconut_number;
|
||||||
|
coconut_context->coconuts = coconuts;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ci = ci->next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
coconut_context->coconut = coconuts;
|
||||||
|
coconut_context->coconuts = coconuts;
|
||||||
|
coconut_context->coconut_number = coconuts->coconut_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coconut_context->coconut == NULL) {
|
||||||
|
free_coconuts(coconuts);
|
||||||
|
userspace_wifi_free_probe(probed);
|
||||||
|
|
||||||
|
if (status_callback != NULL) {
|
||||||
|
r = (*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_MISMATCH, -1, NULL);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_MISMATCH;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wait_for_coconut)
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_MISMATCH;
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise we've got a coconut assigned, drop out of the spinloop
|
||||||
|
* and move to opening */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_callback != NULL)
|
||||||
|
(*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_FOUND, -1, NULL);
|
||||||
|
|
||||||
|
/* We might need to handle partial devices */
|
||||||
|
for (d = 0; d < 14; d++) {
|
||||||
|
if (coconut_context->coconut->probed_devices[d] == NULL) {
|
||||||
|
if (status_callback != NULL)
|
||||||
|
(*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_NO_DEV, d, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO how do we handle channel mapping w partial devices? */
|
||||||
|
|
||||||
|
r = userspace_wifi_device_open(coconut_context->context,
|
||||||
|
coconut_context->coconut->probed_devices[d],
|
||||||
|
&coconut_context->coconut->active_devices[d]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we failed to open, and have a callback, call it and use that to
|
||||||
|
* decide if we abort opening entirely; otherwise, abort opening the
|
||||||
|
* rest of the coconut and fail out
|
||||||
|
*/
|
||||||
|
if (r < 0) {
|
||||||
|
if (status_callback != NULL) {
|
||||||
|
if ((*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_DEV_ERROR, d, NULL) < 0) {
|
||||||
|
coconut_context->coconut = NULL;
|
||||||
|
free_coconuts(coconuts);
|
||||||
|
userspace_wifi_free_probe(probed);
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
coconut_context->coconut = NULL;
|
||||||
|
free_coconuts(coconuts);
|
||||||
|
userspace_wifi_free_probe(probed);
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userspace_wifi_device_set_id(coconut_context->context,
|
||||||
|
coconut_context->coconut->active_devices[d], d);
|
||||||
|
|
||||||
|
if (!coconut_context->ht40 || d < 12) {
|
||||||
|
userspace_wifi_device_set_channel(coconut_context->context,
|
||||||
|
coconut_context->coconut->active_devices[d],
|
||||||
|
d + 1,
|
||||||
|
NL80211_CHAN_WIDTH_20);
|
||||||
|
} else {
|
||||||
|
if (d == 12)
|
||||||
|
htch = 1;
|
||||||
|
if (d == 13)
|
||||||
|
htch = 11;
|
||||||
|
|
||||||
|
userspace_wifi_device_set_channel(coconut_context->context,
|
||||||
|
coconut_context->coconut->active_devices[d],
|
||||||
|
htch,
|
||||||
|
NL80211_CHAN_WIDTH_40);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coconut_context->disable_leds)
|
||||||
|
userspace_wifi_device_set_led(coconut_context->context,
|
||||||
|
coconut_context->coconut->active_devices[d], false);
|
||||||
|
else
|
||||||
|
userspace_wifi_device_set_led(coconut_context->context,
|
||||||
|
coconut_context->coconut->active_devices[d], true);
|
||||||
|
|
||||||
|
if (!coconut_context->disable_blink)
|
||||||
|
userspace_wifi_device_enable_led_control(coconut_context->context,
|
||||||
|
coconut_context->coconut->active_devices[d]);
|
||||||
|
|
||||||
|
if (status_callback != NULL)
|
||||||
|
(*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_DEV_OPENED, d, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_callback != NULL)
|
||||||
|
(*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_DONE, -1, NULL);
|
||||||
|
|
||||||
|
return WIFI_COCONUT_SEARCH_STATE_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open all the devices in a wifi coconut, setting each one to a channel
|
||||||
|
*/
|
||||||
|
int open_wifi_coconut(struct wifi_coconut_context *coconut_context, struct wifi_coconut *coconut) {
|
||||||
|
int d;
|
||||||
|
int r;
|
||||||
|
int htch;
|
||||||
|
|
||||||
|
coconut_context->coconut = coconut;
|
||||||
|
|
||||||
|
if (!coconut_context->quiet)
|
||||||
|
printf("Opening coconut with %d devices\n", coconut->device_num);
|
||||||
|
|
||||||
|
for (d = 0; d < 14; d++) {
|
||||||
|
if (coconut_context->coconut->probed_devices[d] == NULL) {
|
||||||
|
if (!coconut_context->quiet)
|
||||||
|
printf("Device %d null!\n", d);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!coconut_context->quiet) {
|
||||||
|
if (!coconut_context->quiet) {
|
||||||
|
fprintf(stderr, "Opening Coconut-%d #%d... ", coconut->coconut_number, d + 1);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = userspace_wifi_device_open(coconut->coconut_context->context,
|
||||||
|
coconut->probed_devices[d], &coconut->active_devices[d]);
|
||||||
|
|
||||||
|
if (r != 0) {
|
||||||
|
if (!coconut_context->quiet)
|
||||||
|
printf("Failed to open device %d: %d %s\n", d, r, strerror(r));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
userspace_wifi_device_set_id(coconut->coconut_context->context,
|
||||||
|
coconut->active_devices[d], d);
|
||||||
|
|
||||||
|
if (!coconut_context->ht40 || d < 12) {
|
||||||
|
userspace_wifi_device_set_channel(coconut->coconut_context->context,
|
||||||
|
coconut->active_devices[d],
|
||||||
|
d + 1,
|
||||||
|
NL80211_CHAN_WIDTH_20);
|
||||||
|
} else {
|
||||||
|
if (d == 12)
|
||||||
|
htch = 1;
|
||||||
|
if (d == 13)
|
||||||
|
htch = 11;
|
||||||
|
|
||||||
|
userspace_wifi_device_set_channel(coconut->coconut_context->context,
|
||||||
|
coconut->active_devices[d],
|
||||||
|
htch,
|
||||||
|
NL80211_CHAN_WIDTH_40);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coconut_context->disable_leds)
|
||||||
|
userspace_wifi_device_set_led(coconut->coconut_context->context,
|
||||||
|
coconut->active_devices[d], false);
|
||||||
|
else
|
||||||
|
userspace_wifi_device_set_led(coconut->coconut_context->context,
|
||||||
|
coconut->active_devices[d], true);
|
||||||
|
|
||||||
|
if (!coconut_context->disable_blink)
|
||||||
|
userspace_wifi_device_enable_led_control(coconut->coconut_context->context,
|
||||||
|
coconut->active_devices[d]);
|
||||||
|
|
||||||
|
if (!coconut_context->quiet) {
|
||||||
|
fprintf(stderr, "OK!\n");
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Activate all the devices in a wifi coconut
|
||||||
|
*/
|
||||||
|
int start_wifi_coconut_capture(struct wifi_coconut_context *coconut_context) {
|
||||||
|
int d;
|
||||||
|
|
||||||
|
for (d = 0; d < 14; d++) {
|
||||||
|
if (coconut_context->coconut->active_devices[d] == NULL) {
|
||||||
|
fprintf(stderr, "debug - missing active device %d\n", d);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If LEDs are inverted, turn off LEDs once we've enumerated all the radios.
|
||||||
|
*/
|
||||||
|
if (coconut_context->invert_leds)
|
||||||
|
userspace_wifi_device_set_led(coconut_context->context,
|
||||||
|
coconut_context->coconut->active_devices[d], false);
|
||||||
|
|
||||||
|
userspace_wifi_device_start_capture(coconut_context->context,
|
||||||
|
coconut_context->coconut->active_devices[d]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,254 @@
|
||||||
|
/*
|
||||||
|
* GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* Userspace port (C) 2019 Hak5 LLC
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __WIFI_COCONUT_H__
|
||||||
|
#define __WIFI_COCONUT_H__
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <Windows.h>
|
||||||
|
#define sleep(x) Sleep(x*1000)
|
||||||
|
#define usleep(x) Sleep((x) < 1000 ? 1 : (x) / 1000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "kernel/cfg80211.h"
|
||||||
|
#include "kernel/endian.h"
|
||||||
|
#include "kernel/ieee80211.h"
|
||||||
|
#include "kernel/ieee80211_radiotap.h"
|
||||||
|
|
||||||
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include "userspace/userspace.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Diagnostics struct
|
||||||
|
*/
|
||||||
|
struct wifi_coconut_diagnostics {
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
unsigned int total_packets[14];
|
||||||
|
unsigned int total_data[14];
|
||||||
|
int total_min_signal[14];
|
||||||
|
int total_max_signal[14];
|
||||||
|
|
||||||
|
time_t last_sec;
|
||||||
|
int sec_packets[14];
|
||||||
|
int sec_data[14];
|
||||||
|
int sec_min_signal[14];
|
||||||
|
int sec_max_signal[14];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A wifi coconut always has 14 radios; each radio is configured for its
|
||||||
|
* own channel and the device reports packets as an aggregate
|
||||||
|
* A Wi-Fi Coconut device; can be a linked list or a single device
|
||||||
|
*/
|
||||||
|
struct wifi_coconut {
|
||||||
|
struct wifi_coconut *next;
|
||||||
|
|
||||||
|
struct wifi_coconut_context *coconut_context;
|
||||||
|
struct userspace_wifi_probe_dev *probed_devices[14];
|
||||||
|
struct userspace_wifi_dev *active_devices[14];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* How many devices have we found / allocated, either during scan or in case we can't
|
||||||
|
* allocate all devices and decide to continue anyhow
|
||||||
|
*/
|
||||||
|
int device_num;
|
||||||
|
|
||||||
|
/* Per-bus counts */
|
||||||
|
int bus_count[4];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* What number coconut is this (base hub id)
|
||||||
|
*/
|
||||||
|
int coconut_number;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* What is the USB serial number of the first device in the coconut? This should be
|
||||||
|
* predictable on most platforms but macos catalina seems to have some problems with
|
||||||
|
* libusb
|
||||||
|
*/
|
||||||
|
unsigned char first_usb_serial[64];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this coconut valid or did we error out?
|
||||||
|
*/
|
||||||
|
bool valid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wifi coconut global context
|
||||||
|
*/
|
||||||
|
struct wifi_coconut_context {
|
||||||
|
/*
|
||||||
|
* USB context
|
||||||
|
*/
|
||||||
|
struct userspace_wifi_context *context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All coconuts
|
||||||
|
* */
|
||||||
|
struct wifi_coconut *coconuts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The coconut we're operating on
|
||||||
|
*/
|
||||||
|
struct wifi_coconut *coconut;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Diagnostics
|
||||||
|
*/
|
||||||
|
struct wifi_coconut_diagnostics diagnostics;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runtime options
|
||||||
|
*/
|
||||||
|
bool disable_leds;
|
||||||
|
bool disable_blink;
|
||||||
|
bool invert_leds;
|
||||||
|
bool quiet;
|
||||||
|
bool ht40;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Target coconut device if we have multiple ones
|
||||||
|
*/
|
||||||
|
int coconut_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search through a list of radios to try to find what looks like a
|
||||||
|
* wifi coconut.
|
||||||
|
*
|
||||||
|
* - A coconut will have 14 radios
|
||||||
|
* - All radios in a coconut are connected via hubs; they will either be
|
||||||
|
* on hub/subhub/radio or hub/radio
|
||||||
|
* - All radios in a coconut will be on the same base hub
|
||||||
|
* - All radios in a coconut will be rt2800usb
|
||||||
|
* - All radios in a coconut will be vid/pid 148f/5370
|
||||||
|
* - Radios will be organized as:
|
||||||
|
* {/foo}/base/1/[1..4]
|
||||||
|
* {/foo}/base/2/[1..4]
|
||||||
|
* {/foo}/base/3/[1..2]
|
||||||
|
* {/foo}/base/[4..7]
|
||||||
|
*
|
||||||
|
* We do a somewhat inefficient clustering of radios to try to find
|
||||||
|
* coconut groups.
|
||||||
|
*
|
||||||
|
* Coconuts will be numbered by their root hub ID because a user may
|
||||||
|
* plug in additional coconut devices later, which will get a higher
|
||||||
|
* root ID because of the USB topology
|
||||||
|
*
|
||||||
|
* We take control of the devicelist and parse it ourselves instead of
|
||||||
|
* using the for_each API.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct wifi_coconut_context *init_coconut_context();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map the bus positions to device numbers so we can open
|
||||||
|
* them in order.
|
||||||
|
*/
|
||||||
|
const extern int device_number_map[7][4];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a coconut; returns negative on hard failure and one of the following
|
||||||
|
* on success or logical failure
|
||||||
|
*/
|
||||||
|
#define WIFI_COCONUT_FIND_CLUSTER_OK 0
|
||||||
|
#define WIFI_COCONUT_FIND_CLUSTER_NONE 1
|
||||||
|
#define WIFI_COCONUT_FIND_CLUSTER_PARTIAL 2
|
||||||
|
int find_coconuts_cluster(struct wifi_coconut_context *coconut_context,
|
||||||
|
struct userspace_wifi_probe_dev *devicelist,
|
||||||
|
struct wifi_coconut **coconut);
|
||||||
|
|
||||||
|
void free_coconuts(struct wifi_coconut *coconuts);
|
||||||
|
void print_wifi_coconuts(struct wifi_coconut *coconuts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open all the devices in a wifi coconut, setting each one to a channel
|
||||||
|
*/
|
||||||
|
int open_wifi_coconut(struct wifi_coconut_context *coconut_context, struct wifi_coconut *coconut);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan for coconuts. Optionally wait for a coconut to be found, and optionally
|
||||||
|
* call a callback function reporting the status of the search.
|
||||||
|
*
|
||||||
|
* When a coconut has been found, it will be assigned to the coconut context.
|
||||||
|
*
|
||||||
|
* When a proper coconut has been found, it will be opened. Final activation
|
||||||
|
* is deferred to the caller.
|
||||||
|
*
|
||||||
|
* This can be used by a tool to shim the searching methods.
|
||||||
|
*
|
||||||
|
* If a callback function is available it will be called with state updated
|
||||||
|
* during each phase, allowing it to format the user output as appropriate.
|
||||||
|
*
|
||||||
|
* In some situations, the callback function may return a 0 to continue operation
|
||||||
|
* or a negative to abort; these situations are:
|
||||||
|
* WIFI_COCONUT_SEARCH_STATE_NO_RADIOS (No usb devices found); allow the
|
||||||
|
* callback to cancel the normal behavior controlled by wait_for_coconut
|
||||||
|
* WIFI_COCONUT_SEARCH_STATE_NO_COCONUT (No complete coconut found); allow the
|
||||||
|
* callback to cancel the normal behavior controlled by wait_for_coconut
|
||||||
|
* WIFI_COCONUT_SEARCH_STATE_DEV_ERROR (Failure to open a device)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Generic error */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_ERROR -1
|
||||||
|
|
||||||
|
/* Successful find and open of coconut */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_DONE 0
|
||||||
|
|
||||||
|
/* No USB radios of any sort detected */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_NO_RADIOS 1
|
||||||
|
|
||||||
|
/* No complete wifi coconut detected */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_NO_COCONUT 2
|
||||||
|
|
||||||
|
/* No coconut matching the specified coconut_number found */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_MISMATCH 3
|
||||||
|
|
||||||
|
/* Status update - target coconut has been found */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_FOUND 4
|
||||||
|
|
||||||
|
/* Status update - coconut device (in cb devnum) opened */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_DEV_OPENED 5
|
||||||
|
|
||||||
|
/* Status update - coconut device (in cb devnum) failed to open */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_DEV_ERROR 6
|
||||||
|
|
||||||
|
/* Status update - coconut device (in cb devnum) was not found */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_NO_DEV 7
|
||||||
|
|
||||||
|
/* Status update - one or more coconuts found, returned as list in cb coconut_list */
|
||||||
|
#define WIFI_COCONUT_SEARCH_STATE_LIST 8
|
||||||
|
|
||||||
|
int coconut_search_and_open(struct wifi_coconut_context *coconut_context,
|
||||||
|
bool wait_for_coconut, int coconut_number,
|
||||||
|
int (*status_callback)(struct wifi_coconut_context *, void *cb_aux,
|
||||||
|
int state, int devnum, struct wifi_coconut *coconut_list),
|
||||||
|
void *cb_aux);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Activate all the devices in a wifi coconut
|
||||||
|
*/
|
||||||
|
int start_wifi_coconut_capture(struct wifi_coconut_context *coconut_context);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ifndef WIFI_COCONUT_H */
|
|
@ -0,0 +1,504 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
pthreads-win32 License -
|
||||||
|
a POSIX threads library for Microsoft Windows
|
||||||
|
|
||||||
|
This file is Copyrighted
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
This file is covered under the following Copyright:
|
||||||
|
|
||||||
|
Copyright © 2001,2006 Ross P. Johnson
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Pthreads-win32 is covered by the GNU Lesser General Public License
|
||||||
|
------------------------------------------------------------------
|
||||||
|
|
||||||
|
Pthreads-win32 is open software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public License
|
||||||
|
as published by the Free Software Foundation version 2.1 of the
|
||||||
|
License.
|
||||||
|
|
||||||
|
Pthreads-win32 is several binary link libraries, several modules,
|
||||||
|
associated interface definition files and scripts used to control
|
||||||
|
its compilation and installation.
|
||||||
|
|
||||||
|
Pthreads-win32 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU Lesser General Public License is distributed with
|
||||||
|
pthreads-win32 under the filename:
|
||||||
|
|
||||||
|
COPYING.LIB
|
||||||
|
|
||||||
|
You should have received a copy of the version 2.1 GNU Lesser General
|
||||||
|
Public License with pthreads-win32; if not, write to:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place
|
||||||
|
Suite 330
|
||||||
|
Boston, MA 02111-1307
|
||||||
|
USA
|
||||||
|
|
||||||
|
The contact addresses for pthreads-win32 is as follows:
|
||||||
|
|
||||||
|
Web: https://sources.redhat.com/pthreads-win32
|
||||||
|
Email: Ross Johnson
|
||||||
|
Please use: Firstname.Lastname@homemail.com.au
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Pthreads-win32 copyrights and exception files
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
With the exception of the files listed below, Pthreads-win32
|
||||||
|
is covered under the following GNU Lesser General Public License
|
||||||
|
Copyrights:
|
||||||
|
|
||||||
|
Pthreads-win32 - POSIX Threads Library for Win32
|
||||||
|
Copyright © 1998 John E. Bossom
|
||||||
|
Copyright © 1999,2006 Pthreads-win32 contributors
|
||||||
|
|
||||||
|
The current list of contributors is contained
|
||||||
|
in the file CONTRIBUTORS included with the source
|
||||||
|
code distribution. The current list of CONTRIBUTORS
|
||||||
|
can also be seen at the following WWW location:
|
||||||
|
https://sources.redhat.com/pthreads-win32/contributors.html
|
||||||
|
|
||||||
|
Contact Email: Ross Johnson
|
||||||
|
Please use: Firstname.Lastname@homemail.com.au
|
||||||
|
|
||||||
|
These files are not covered under one of the Copyrights listed above:
|
||||||
|
|
||||||
|
COPYING
|
||||||
|
COPYING.LIB
|
||||||
|
tests/rwlock7.c
|
||||||
|
|
||||||
|
This file, COPYING, is distributed under the Copyright found at the
|
||||||
|
top of this file. It is important to note that you may distribute
|
||||||
|
verbatim copies of this file but you may not modify this file.
|
||||||
|
|
||||||
|
The file COPYING.LIB, which contains a copy of the version 2.1
|
||||||
|
GNU Lesser General Public License, is itself copyrighted by the
|
||||||
|
Free Software Foundation, Inc. Please note that the Free Software
|
||||||
|
Foundation, Inc. does NOT have a copyright over Pthreads-win32,
|
||||||
|
only the COPYING.LIB that is supplied with pthreads-win32.
|
||||||
|
|
||||||
|
The file tests/rwlock7.c is derived from code written by
|
||||||
|
Dave Butenhof for his book 'Programming With POSIX(R) Threads'.
|
||||||
|
The original code was obtained by free download from his website
|
||||||
|
https://home.earthlink.net/~anneart/family/Threads/source.html
|
||||||
|
and did not contain a copyright or author notice. It is assumed to
|
||||||
|
be freely distributable.
|
||||||
|
|
||||||
|
In all cases one may use and distribute these exception files freely.
|
||||||
|
And because one may freely distribute the LGPL covered files, the
|
||||||
|
entire pthreads-win32 source may be freely used and distributed.
|
||||||
|
|
||||||
|
General Copyleft and License info
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
For general information on Copylefts, see:
|
||||||
|
|
||||||
|
https://www.gnu.org/copyleft/
|
||||||
|
|
||||||
|
For information on GNU Lesser General Public Licenses, see:
|
||||||
|
|
||||||
|
https://www.gnu.org/copyleft/lesser.html
|
||||||
|
https://www.gnu.org/copyleft/lesser.txt
|
||||||
|
|
||||||
|
|
||||||
|
Why pthreads-win32 did not use the GNU General Public License
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
The goal of the pthreads-win32 project has been to
|
||||||
|
provide a quality and complete implementation of the POSIX
|
||||||
|
threads API for Microsoft Windows within the limits imposed
|
||||||
|
by virtue of it being a stand-alone library and not
|
||||||
|
linked directly to other POSIX compliant libraries. For
|
||||||
|
example, some functions and features, such as those based
|
||||||
|
on POSIX signals, are missing.
|
||||||
|
|
||||||
|
Pthreads-win32 is a library, available in several different
|
||||||
|
versions depending on supported compilers, and may be used
|
||||||
|
as a dynamically linked module or a statically linked set of
|
||||||
|
binary modules. It is not an application on it's own.
|
||||||
|
|
||||||
|
It was fully intended that pthreads-win32 be usable with
|
||||||
|
commercial software not covered by either the GPL or the LGPL
|
||||||
|
licenses. Pthreads-win32 has many contributors to it's
|
||||||
|
code base, many of whom have done so because they have
|
||||||
|
used the library in commercial or proprietry software
|
||||||
|
projects.
|
||||||
|
|
||||||
|
Releasing pthreads-win32 under the LGPL ensures that the
|
||||||
|
library can be used widely, while at the same time ensures
|
||||||
|
that bug fixes and improvements to the pthreads-win32 code
|
||||||
|
itself is returned to benefit all current and future users
|
||||||
|
of the library.
|
||||||
|
|
||||||
|
Although pthreads-win32 makes it possible for applications
|
||||||
|
that use POSIX threads to be ported to Win32 platforms, the
|
||||||
|
broader goal of the project is to encourage the use of open
|
||||||
|
standards, and in particular, to make it just a little easier
|
||||||
|
for developers writing Win32 applications to consider
|
||||||
|
widening the potential market for their products.
|
|
@ -0,0 +1,65 @@
|
||||||
|
Wi-Fi Coconut Win64
|
||||||
|
|
||||||
|
** Requirements **
|
||||||
|
|
||||||
|
You MUST INSTALL THE ZADIG USB DRIVERS BEFORE CONNECTING YOUR WI-FI COCONUT
|
||||||
|
or THERE IS A RISK OF HARDWARE DAMAGE.
|
||||||
|
|
||||||
|
** Installing **
|
||||||
|
|
||||||
|
1. Download Zadig from https://zadig.akeo.ie
|
||||||
|
2. Run the Zadig tool
|
||||||
|
3. From the menus, select Device->Create New Device
|
||||||
|
4. Enter "RT2800" in the name field (the large field next to the
|
||||||
|
checkbox named "Edit")
|
||||||
|
5. Under USB ID enter:
|
||||||
|
148F 5370
|
||||||
|
Leave the third field next to USB ID blank.
|
||||||
|
6. Click "Install Driver". Zadig may appear to hang - just wait!
|
||||||
|
Zadig will then install the USB drivers required for raw
|
||||||
|
access to the radio.
|
||||||
|
|
||||||
|
NOTE: Installing the Zadig drivers for the rt2800 family of Wi-Fi cards
|
||||||
|
will disable any other Wi-Fi cards using this chipset. These Wi-Fi cards
|
||||||
|
are USB ONLY and this will typically not affect the built-in Wi-Fi card
|
||||||
|
on your system, however if your device ONLY HAS USB for Wi-Fi you should
|
||||||
|
MAKE SURE IT DOES NOT USE THE rt2800 CHIPSET.
|
||||||
|
|
||||||
|
IF YOU ARE UNSURE, we recommend TAKING A SYSTEM SNAPSHOT before installing
|
||||||
|
the Zadig drivers!
|
||||||
|
|
||||||
|
|
||||||
|
** Running **
|
||||||
|
|
||||||
|
1. Plug in coconut
|
||||||
|
2. Open a terminal, navigate to coconut download
|
||||||
|
3. Run .\wifi_coconut.exe --help for info
|
||||||
|
|
||||||
|
Useful commands:
|
||||||
|
|
||||||
|
.\wifi_coconut.exe --diagnostics-only
|
||||||
|
.\wifi_coconut.exe foo.pcap
|
||||||
|
.\wifi_coconut.exe --diagnostics foo.pcap
|
||||||
|
|
||||||
|
** Controlling LEDs **
|
||||||
|
|
||||||
|
By default the Wi-Fi Coconut enables all LEDs. LEDs blink when there is traffic on
|
||||||
|
the corresponding channel.
|
||||||
|
|
||||||
|
The Wi-Fi Coconut can be used in "stealth mode" by disabling LEDs entirely:
|
||||||
|
|
||||||
|
.\wifi_coconut.exe --disable-leds foo.pcap
|
||||||
|
|
||||||
|
The LEDs can be inverted, so that they are normally off and blink only when there is
|
||||||
|
traffic:
|
||||||
|
|
||||||
|
.\wifi_coconut.exe --invert-leds foo.pcap
|
||||||
|
|
||||||
|
If blinking LEDs causes a health issue or is annoying, LED blinking can be disabled
|
||||||
|
with:
|
||||||
|
|
||||||
|
.\wifi_coconut.exe --disable-blinking
|
||||||
|
|
||||||
|
The LEDs will still light up as the radio is enabled, but will not strobe.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
xcopy ..\libwifiuserspace\firmware\* Release\
|
||||||
|
copy ..\windows\README.txt Release\.
|
||||||
|
copy ..\windows\LICENSE_LIBUSB.txt Release\.
|
||||||
|
copy ..\windows\LICENSE_PTHREADS.txt Release\.
|
||||||
|
copy ..\LICENSE Release\License.txt
|
Loading…
Reference in New Issue