commit 317532ebdef5d9b837178b969a9992cc17fca272
Author: Qubot <1445788683@qq.com>
Date: Sun Oct 22 22:05:23 2023 +0800
first commit
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d7f1051
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 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.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, 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 or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+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 give any other recipients of the Program a copy of this License
+along with the Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) 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; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, 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 executable. However, as a
+special exception, the source code 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.
+
+If distribution of executable or 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 counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+ 5. 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 Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program 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 to
+this License.
+
+ 7. 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 Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program 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.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+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 Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+ 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
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), 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 Programs
+
+ 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
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. 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.
+
+ {description}
+ Copyright (C) {year} {fullname}
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; 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.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ {signature of Ty Coon}, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+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
+Public License instead of this License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d6a2917
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+## Supported boards
+
+Soc | Boards |
+|:--|:--|
+| Allwinner H2+ | |
+| Allwinner H3 | |
+| Allwinner H5 | |
+| Allwinner H6 | Orange Pi 3/3 LTS |
+| Allwinner H616 | Orange Pi Zero2 |
+| Rockchip RK3328 | |
+| Rockchip RK3399 | Orange Pi 4/4B/4 LTS/800 |
+| Rockchip RK3588S | Orange Pi 5/5B |
+| Rockchip RK3588 | Orange Pi 5Plus |
+
+## Download links
+
+- 中文链接: http://www.orangepi.cn
+- English link:http://www.orangepi.org
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..671abd1
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,307 @@
+#!/bin/bash
+#
+# Copyright (c) 2013-2021 Igor Pecovnik, igor.pecovnik@gma**.com
+#
+# This file is licensed under the terms of the GNU General Public
+# License version 2. This program is licensed "as is" without any
+# warranty of any kind, whether express or implied.
+
+# DO NOT EDIT THIS FILE
+# use configuration files like config-default.conf to set the build configuration
+# Please check Orange Pi documentation for more info
+# http://www.orangepi.cn/downloadresourcescn
+# http://www.orangepi.org/downloadresources
+
+SRC="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
+
+# check for whitespace in ${SRC} and exit for safety reasons
+grep -q "[[:space:]]" <<<"${SRC}" && { echo "\"${SRC}\" contains whitespace. Not supported. Aborting." >&2 ; exit 1 ; }
+
+cd "${SRC}" || exit
+
+if [[ "${ORANGEPI_ENABLE_CALL_TRACING}" == "yes" ]]; then
+ set -T # inherit return/debug traps
+ mkdir -p "${SRC}"/output/debug
+ echo -n "" > "${SRC}"/output/debug/calls.txt
+ trap 'echo "${BASH_LINENO[@]}|${BASH_SOURCE[@]}|${FUNCNAME[@]}" >> ${SRC}/output/debug/calls.txt ;' RETURN
+fi
+
+if [[ -f "${SRC}"/scripts/general.sh ]]; then
+
+ # shellcheck source=scripts/general.sh
+ source "${SRC}"/scripts/general.sh
+
+else
+
+ echo "Error: missing build directory structure"
+ echo "Please clone the full repository by https://github.com/orangepi-xunlong/orangepi-build"
+ exit 255
+
+fi
+
+# Add the variables needed at the beginning of the path
+check_args ()
+{
+
+for p in "$@"; do
+
+ case "${p%=*}" in
+ LIB_TAG)
+ # Take a variable if the branch exists locally
+ if [ "${p#*=}" == "$(git branch | \
+ gawk -v b="${p#*=}" '{if ( $NF == b ) {print $NF}}')" ]; then
+ echo -e "[\e[0;35m warn \x1B[0m] Setting $p"
+ eval "$p"
+ else
+ echo -e "[\e[0;35m warn \x1B[0m] Skip $p setting as LIB_TAG=\"\""
+ eval LIB_TAG=""
+ fi
+ ;;
+ esac
+
+done
+
+}
+
+
+check_args "$@"
+
+
+update_src() {
+
+ cd "${SRC}" || exit
+ if [[ ! -f "${SRC}"/.ignore_changes ]]; then
+ echo -e "[\e[0;32m o.k. \x1B[0m] This script will try to update"
+
+ CHANGED_FILES=$(git diff --name-only)
+ if [[ -n "${CHANGED_FILES}" ]]; then
+ echo -e "[\e[0;35m warn \x1B[0m] Can't update since you made changes to: \e[0;32m\n${CHANGED_FILES}\x1B[0m"
+ while true; do
+ echo -e "Press \e[0;33m\x1B[0m or \e[0;33mexit\x1B[0m to abort compilation"\
+ ", \e[0;33m\x1B[0m to ignore and continue, \e[0;33mdiff\x1B[0m to display changes"
+ read -r
+ if [[ "${REPLY}" == "diff" ]]; then
+ git diff
+ elif [[ "${REPLY}" == "exit" ]]; then
+ exit 1
+ elif [[ "${REPLY}" == "" ]]; then
+ break
+ else
+ echo "Unknown command!"
+ fi
+ done
+ elif [[ $(git branch | grep "*" | awk '{print $2}') != "${LIB_TAG}" && -n "${LIB_TAG}" ]]; then
+ git checkout "${LIB_TAG:-master}"
+ git pull
+ fi
+ fi
+
+}
+
+
+TMPFILE=$(mktemp)
+chmod 644 "${TMPFILE}"
+{
+
+ echo SRC="$SRC"
+ echo LIB_TAG="$LIB_TAG"
+ declare -f update_src
+ #echo "update_src"
+
+} > "$TMPFILE"
+
+#do not update/checkout git with root privileges to messup files onwership.
+#due to in docker/VM, we can't su to a normal user, so do not update/checkout git.
+if [[ $(systemd-detect-virt) == 'none' ]]; then
+
+ if [[ "${EUID}" == "0" ]]; then
+ su "$(stat --format=%U "${SRC}"/.git)" -c "bash ${TMPFILE}"
+ else
+ bash "${TMPFILE}"
+ fi
+
+fi
+
+
+rm "${TMPFILE}"
+
+
+if [[ "${EUID}" == "0" ]] || [[ "${1}" == "vagrant" ]]; then
+ :
+elif [[ "${1}" == docker || "${1}" == dockerpurge || "${1}" == docker-shell ]] && grep -q "$(whoami)" <(getent group docker); then
+ :
+else
+ display_alert "This script requires root privileges, trying to use sudo" "" "wrn"
+ sudo "${SRC}/build.sh" "$@"
+ exit $?
+fi
+
+if [ "$OFFLINE_WORK" == "yes" ]; then
+
+ echo -e "\n"
+ display_alert "* " "You are working offline."
+ display_alert "* " "Sources, time and host will not be checked"
+ echo -e "\n"
+ sleep 3s
+
+else
+
+ # check and install the basic utilities here
+ prepare_host_basic
+
+fi
+
+# Check for Vagrant
+if [[ "${1}" == vagrant && -z "$(command -v vagrant)" ]]; then
+ display_alert "Vagrant not installed." "Installing"
+ sudo apt-get update
+ sudo apt-get install -y vagrant virtualbox
+fi
+
+# Purge Orange Pi Docker images
+if [[ "${1}" == dockerpurge && -f /etc/debian_version ]]; then
+ display_alert "Purging Orange Pi Docker containers" "" "wrn"
+ docker container ls -a | grep orangepi | awk '{print $1}' | xargs docker container rm &> /dev/null
+ docker image ls | grep orangepi | awk '{print $3}' | xargs docker image rm &> /dev/null
+ shift
+ set -- "docker" "$@"
+fi
+
+# Docker shell
+if [[ "${1}" == docker-shell ]]; then
+ shift
+ #shellcheck disable=SC2034
+ SHELL_ONLY=yes
+ set -- "docker" "$@"
+fi
+
+# Install Docker if not there but wanted. We cover only Debian based distro install. On other distros, manual Docker install is needed
+if [[ "${1}" == docker && -f /etc/debian_version && -z "$(command -v docker)" ]]; then
+
+ DOCKER_BINARY="docker-ce"
+
+ # add exception for Ubuntu Focal until Docker provides dedicated binary
+ codename=$(cat /etc/os-release | grep VERSION_CODENAME | cut -d"=" -f2)
+ codeid=$(cat /etc/os-release | grep ^NAME | cut -d"=" -f2 | awk '{print tolower($0)}' | tr -d '"' | awk '{print $1}')
+ [[ "${codename}" == "debbie" ]] && codename="buster" && codeid="debian"
+ [[ "${codename}" == "ulyana" || "${codename}" == "jammy" ]] && codename="focal" && codeid="ubuntu"
+
+ # different binaries for some. TBD. Need to check for all others
+ [[ "${codename}" =~ focal|hirsute ]] && DOCKER_BINARY="docker containerd docker.io"
+
+ display_alert "Docker not installed." "Installing" "Info"
+ sudo bash -c "echo \"deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/${codeid} ${codename} stable\" > /etc/apt/sources.list.d/docker.list"
+
+ sudo bash -c "curl -fsSL \"https://download.docker.com/linux/${codeid}/gpg\" | apt-key add -qq - > /dev/null 2>&1 "
+ export DEBIAN_FRONTEND=noninteractive
+ sudo apt-get update
+ sudo apt-get install -y -qq --no-install-recommends ${DOCKER_BINARY}
+ display_alert "Add yourself to docker group to avoid root privileges" "" "wrn"
+ "${SRC}/build.sh" "$@"
+ exit $?
+
+fi
+
+EXTER="${SRC}/external"
+
+# Create userpatches directory if not exists
+mkdir -p "${SRC}"/userpatches
+
+
+# Create example configs if none found in userpatches
+if ! ls "${SRC}"/userpatches/{config-example.conf,config-docker.conf,config-vagrant.conf} 1> /dev/null 2>&1; then
+
+ # Migrate old configs
+ if ls "${SRC}"/*.conf 1> /dev/null 2>&1; then
+ display_alert "Migrate config files to userpatches directory" "all *.conf" "info"
+ cp "${SRC}"/*.conf "${SRC}"/userpatches || exit 1
+ rm "${SRC}"/*.conf
+ [[ ! -L "${SRC}"/userpatches/config-example.conf ]] && ln -fs config-example.conf "${SRC}"/userpatches/config-default.conf || exit 1
+ fi
+
+ display_alert "Create example config file using template" "config-default.conf" "info"
+
+ # Create example config
+ if [[ ! -f "${SRC}"/userpatches/config-example.conf ]]; then
+ cp "${EXTER}"/config/templates/config-example.conf "${SRC}"/userpatches/config-example.conf || exit 1
+ ln -fs config-example.conf "${SRC}"/userpatches/config-default.conf || exit 1
+ fi
+
+ # Create Docker config
+ if [[ ! -f "${SRC}"/userpatches/config-docker.conf ]]; then
+ cp "${EXTER}"/config/templates/config-docker.conf "${SRC}"/userpatches/config-docker.conf || exit 1
+ fi
+
+ # Create Docker file
+ if [[ ! -f "${SRC}"/userpatches/Dockerfile ]]; then
+ cp "${EXTER}"/config/templates/Dockerfile "${SRC}"/userpatches/Dockerfile || exit 1
+ fi
+
+ # Create Vagrant config
+ if [[ ! -f "${SRC}"/userpatches/config-vagrant.conf ]]; then
+ cp "${EXTER}"/config/templates/config-vagrant.conf "${SRC}"/userpatches/config-vagrant.conf || exit 1
+ fi
+
+ # Create Vagrant file
+ if [[ ! -f "${SRC}"/userpatches/Vagrantfile ]]; then
+ cp "${EXTER}"/config/templates/Vagrantfile "${SRC}"/userpatches/Vagrantfile || exit 1
+ fi
+
+fi
+
+if [[ -z "${CONFIG}" && -n "$1" && -f "${SRC}/userpatches/config-$1.conf" ]]; then
+ CONFIG="userpatches/config-$1.conf"
+ shift
+fi
+
+# usind default if custom not found
+if [[ -z "${CONFIG}" && -f "${SRC}/userpatches/config-default.conf" ]]; then
+ CONFIG="userpatches/config-default.conf"
+fi
+
+# source build configuration file
+CONFIG_FILE="$(realpath "${CONFIG}")"
+
+if [[ ! -f "${CONFIG_FILE}" ]]; then
+ display_alert "Config file does not exist" "${CONFIG}" "error"
+ exit 254
+fi
+
+CONFIG_PATH=$(dirname "${CONFIG_FILE}")
+
+# Source the extensions manager library at this point, before sourcing the config.
+# This allows early calls to enable_extension(), but initialization proper is done later.
+# shellcheck source=scripts/extensions.sh
+source "${SRC}"/scripts/extensions.sh
+
+display_alert "Using config file" "${CONFIG_FILE}" "info"
+pushd "${CONFIG_PATH}" > /dev/null || exit
+# shellcheck source=/dev/null
+source "${CONFIG_FILE}"
+popd > /dev/null || exit
+
+[[ -z "${USERPATCHES_PATH}" ]] && USERPATCHES_PATH="${CONFIG_PATH}"
+
+# Script parameters handling
+while [[ "${1}" == *=* ]]; do
+
+ parameter=${1%%=*}
+ value=${1##*=}
+ shift
+ display_alert "Command line: setting $parameter to" "${value:-(empty)}" "info"
+ eval "$parameter=\"$value\""
+
+done
+
+
+if [[ "${BUILD_ALL}" == "yes" || "${BUILD_ALL}" == "demo" ]]; then
+
+ # shellcheck source=scripts/build-all-ng.sh
+ source "${SRC}"/scripts/build-all-ng.sh
+
+else
+
+ # shellcheck source=scripts/main.sh
+ source "${SRC}"/scripts/main.sh
+
+fi
diff --git a/external/cache/debs/aptly/aptly_1.4.0+44+g24a0271_amd64.deb b/external/cache/debs/aptly/aptly_1.4.0+44+g24a0271_amd64.deb
new file mode 100644
index 0000000..09d3660
Binary files /dev/null and b/external/cache/debs/aptly/aptly_1.4.0+44+g24a0271_amd64.deb differ
diff --git a/external/cache/debs/arm64/.gitignore b/external/cache/debs/arm64/.gitignore
new file mode 100644
index 0000000..3249e43
--- /dev/null
+++ b/external/cache/debs/arm64/.gitignore
@@ -0,0 +1,3 @@
+chromium-browser*
+chromium-codecs-ffmpeg-extra*
+firefox-esr*
diff --git a/external/cache/debs/arm64/layout_switcher/layoutswitcher_0.2-0_all.deb b/external/cache/debs/arm64/layout_switcher/layoutswitcher_0.2-0_all.deb
new file mode 100644
index 0000000..b56d585
Binary files /dev/null and b/external/cache/debs/arm64/layout_switcher/layoutswitcher_0.2-0_all.deb differ
diff --git a/external/cache/debs/arm64/usbmount_0.0.24_all.deb b/external/cache/debs/arm64/usbmount_0.0.24_all.deb
new file mode 100644
index 0000000..9202f58
Binary files /dev/null and b/external/cache/debs/arm64/usbmount_0.0.24_all.deb differ
diff --git a/external/cache/debs/arm64/wiringpi_2.51.deb b/external/cache/debs/arm64/wiringpi_2.51.deb
new file mode 100644
index 0000000..12c618c
Binary files /dev/null and b/external/cache/debs/arm64/wiringpi_2.51.deb differ
diff --git a/external/cache/debs/extra/bionic-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..a70d139
Binary files /dev/null and b/external/cache/debs/extra/bionic-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..865bc7d
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..1aaeebb
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..8013ea5
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..47dc242
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..612ba7d
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..2a9b5e7
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..7f73e7d
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..220ab25
Binary files /dev/null and b/external/cache/debs/extra/bionic-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/bookworm-desktop/null.txt b/external/cache/debs/extra/bookworm-desktop/null.txt
new file mode 100644
index 0000000..e69de29
diff --git a/external/cache/debs/extra/bookworm-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb b/external/cache/debs/extra/bookworm-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb
new file mode 100644
index 0000000..51cf71b
Binary files /dev/null and b/external/cache/debs/extra/bookworm-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/dockbarx-common_1.0~beta+git20210222-1~ppa1_all.deb b/external/cache/debs/extra/bullseye-desktop/dockbarx-common_1.0~beta+git20210222-1~ppa1_all.deb
new file mode 100755
index 0000000..39c46d1
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/dockbarx-common_1.0~beta+git20210222-1~ppa1_all.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/dockbarx-dockx_1.0~beta+git20210222-1~ppa1_all.deb b/external/cache/debs/extra/bullseye-desktop/dockbarx-dockx_1.0~beta+git20210222-1~ppa1_all.deb
new file mode 100755
index 0000000..1cf2085
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/dockbarx-dockx_1.0~beta+git20210222-1~ppa1_all.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/dockbarx-theme-zorin_1.1.0_all.deb b/external/cache/debs/extra/bullseye-desktop/dockbarx-theme-zorin_1.1.0_all.deb
new file mode 100755
index 0000000..4269807
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/dockbarx-theme-zorin_1.1.0_all.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/dockbarx_1.0~beta+git20210222-1~ppa1_all.deb b/external/cache/debs/extra/bullseye-desktop/dockbarx_1.0~beta+git20210222-1~ppa1_all.deb
new file mode 100755
index 0000000..75f41c1
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/dockbarx_1.0~beta+git20210222-1~ppa1_all.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/xfce4-dockbarx-plugin_0.6+git20210221-1~ppa2~20.10_arm64.deb b/external/cache/debs/extra/bullseye-desktop/xfce4-dockbarx-plugin_0.6+git20210221-1~ppa2~20.10_arm64.deb
new file mode 100755
index 0000000..78e2249
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/xfce4-dockbarx-plugin_0.6+git20210221-1~ppa2~20.10_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-desktop/xfce4-zorinmenulite-plugin_1.1.2_arm64.deb b/external/cache/debs/extra/bullseye-desktop/xfce4-zorinmenulite-plugin_1.1.2_arm64.deb
new file mode 100755
index 0000000..3eb9582
Binary files /dev/null and b/external/cache/debs/extra/bullseye-desktop/xfce4-zorinmenulite-plugin_1.1.2_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-utils/hostapd_2.9-102~orangepi2.1.8+1_arm64.deb b/external/cache/debs/extra/bullseye-utils/hostapd_2.9-102~orangepi2.1.8+1_arm64.deb
new file mode 100644
index 0000000..10394f9
Binary files /dev/null and b/external/cache/debs/extra/bullseye-utils/hostapd_2.9-102~orangepi2.1.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-utils/htop_3.1.0-0~armbian20.08.2+1_arm64.deb b/external/cache/debs/extra/bullseye-utils/htop_3.1.0-0~armbian20.08.2+1_arm64.deb
new file mode 100644
index 0000000..94f0d4f
Binary files /dev/null and b/external/cache/debs/extra/bullseye-utils/htop_3.1.0-0~armbian20.08.2+1_arm64.deb differ
diff --git a/external/cache/debs/extra/bullseye-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb b/external/cache/debs/extra/bullseye-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb
new file mode 100644
index 0000000..78186af
Binary files /dev/null and b/external/cache/debs/extra/bullseye-utils/sunxi-tools_1.4.2-2~orangepi2.1.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..98e76b3
Binary files /dev/null and b/external/cache/debs/extra/buster-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..b78f0b2
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..c887b29
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..1c92f7b
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..94c693b
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..c996ecd
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..11ea2a7
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..5345065
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..ed9e573
Binary files /dev/null and b/external/cache/debs/extra/buster-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..813c3c1
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..388932a
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..09fe136
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..8e1821a
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libump-dev_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/libump-dev_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..cbe8a2b
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libump-dev_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/libump_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/libump_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..cbe1db4
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/libump_3.0-0sunxi1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..2f8d6d7
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..637a6ed
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..ddf1bc1
Binary files /dev/null and b/external/cache/debs/extra/focal-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..887f3bd
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..e22c28a
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..6a30235
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..42fbae9
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/htop_2.2.0-5~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..293a1ec
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..663ee6d
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..377b8cb
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..138b442
Binary files /dev/null and b/external/cache/debs/extra/focal-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/jammy-desktop/null.txt b/external/cache/debs/extra/jammy-desktop/null.txt
new file mode 100644
index 0000000..e69de29
diff --git a/external/cache/debs/extra/jammy-utils/hostapd_2.10-6~armbian22.02.3+1_arm64.deb b/external/cache/debs/extra/jammy-utils/hostapd_2.10-6~armbian22.02.3+1_arm64.deb
new file mode 100644
index 0000000..004c6a0
Binary files /dev/null and b/external/cache/debs/extra/jammy-utils/hostapd_2.10-6~armbian22.02.3+1_arm64.deb differ
diff --git a/external/cache/debs/extra/stretch-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/stretch-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..d3f0467
Binary files /dev/null and b/external/cache/debs/extra/stretch-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..ea387b8
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..fce073a
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..19b4547
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..eab57cc
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..c88912c
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..3331e9a
Binary files /dev/null and b/external/cache/debs/extra/stretch-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/dri2-utils_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/dri2-utils_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..1aca914
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/dri2-utils_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..fbeb178
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..f84c990
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libcedrus1-dev_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..b995891
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..0921e28
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libcedrus1_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libdri2-1_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libdri2-1_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..ca0c9f8
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libdri2-1_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libdri2-dev_1.0.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libdri2-dev_1.0.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..b9f16d5
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libdri2-dev_1.0.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libglshim_0.9.2~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libglshim_0.9.2~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..1a67632
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libglshim_0.9.2~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libmali-sunxi-dev_1.0-1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libmali-sunxi-dev_1.0-1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..2eab8ab
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libmali-sunxi-dev_1.0-1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libmali-sunxi-r3p0_1.0-1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libmali-sunxi-r3p0_1.0-1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..56dab32
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libmali-sunxi-r3p0_1.0-1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libump-dev_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libump-dev_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..2ebb772
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libump-dev_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libump_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libump_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..05ad60b
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libump_3.0-0sunxi1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libvdpau-dev_1.1.1-10~armbian5.73+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libvdpau-dev_1.1.1-10~armbian5.73+1_armhf.deb
new file mode 100755
index 0000000..32e0fcc
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libvdpau-dev_1.1.1-10~armbian5.73+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/libvdpau-sunxi1_0.5.1~armbian5.73+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/libvdpau-sunxi1_0.5.1~armbian5.73+1_armhf.deb
new file mode 100755
index 0000000..4ee681f
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/libvdpau-sunxi1_0.5.1~armbian5.73+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..5dd1f2a
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-armsoc-sun4i_1.4.1~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..b9e08bf
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.1.0+1_armhf.deb b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.1.0+1_armhf.deb
new file mode 100644
index 0000000..4fd80de
Binary files /dev/null and b/external/cache/debs/extra/xenial-desktop/xserver-xorg-video-fbturbo_0.4.4~orangepi2.1.0+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..864f5f6
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..3dad38b
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/hostapd_2.9-102~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..4ed0f67
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..745cfe0
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/mmc-utils_0~gita3d3331-3~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb b/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb
new file mode 100644
index 0000000..5860aaf
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_arm64.deb differ
diff --git a/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb b/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb
new file mode 100644
index 0000000..5c45b3a
Binary files /dev/null and b/external/cache/debs/extra/xenial-utils/sunxi-tools_1.4.2-2~orangepi2.0.8+1_armhf.deb differ
diff --git a/external/cache/debs/h618/linux-u-boot-current-orangepizero2w_1.0.0_arm64.deb b/external/cache/debs/h618/linux-u-boot-current-orangepizero2w_1.0.0_arm64.deb
new file mode 100644
index 0000000..084ba0e
Binary files /dev/null and b/external/cache/debs/h618/linux-u-boot-current-orangepizero2w_1.0.0_arm64.deb differ
diff --git a/external/cache/debs/h618/linux-u-boot-current-orangepizero3_1.0.2_arm64.deb b/external/cache/debs/h618/linux-u-boot-current-orangepizero3_1.0.2_arm64.deb
new file mode 100644
index 0000000..9bfd1e2
Binary files /dev/null and b/external/cache/debs/h618/linux-u-boot-current-orangepizero3_1.0.2_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/gl4es_1.1.5-0armbian1_arm64.deb b/external/cache/debs/rk3399/buster_media/gl4es_1.1.5-0armbian1_arm64.deb
new file mode 100644
index 0000000..2eb1207
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/gl4es_1.1.5-0armbian1_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/gstreamer1.0-rockchip1-extra_3%3a20180115-3armbian1_arm64.deb b/external/cache/debs/rk3399/buster_media/gstreamer1.0-rockchip1-extra_3%3a20180115-3armbian1_arm64.deb
new file mode 100644
index 0000000..9e57bbd
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/gstreamer1.0-rockchip1-extra_3%3a20180115-3armbian1_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/gstreamer1.0-rockchip1_2%3a1.10-0armbian1_arm64.deb b/external/cache/debs/rk3399/buster_media/gstreamer1.0-rockchip1_2%3a1.10-0armbian1_arm64.deb
new file mode 100644
index 0000000..157b3c3
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/gstreamer1.0-rockchip1_2%3a1.10-0armbian1_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/kodi-rk-bin_2%3a18.9-final-18.9buster0armbian3_arm64.deb b/external/cache/debs/rk3399/buster_media/kodi-rk-bin_2%3a18.9-final-18.9buster0armbian3_arm64.deb
new file mode 100644
index 0000000..eeec326
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/kodi-rk-bin_2%3a18.9-final-18.9buster0armbian3_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/kodi-rk_2%3a18.9-final-18.9buster0armbian3_all.deb b/external/cache/debs/rk3399/buster_media/kodi-rk_2%3a18.9-final-18.9buster0armbian3_all.deb
new file mode 100644
index 0000000..89b35b1
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/kodi-rk_2%3a18.9-final-18.9buster0armbian3_all.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/libmali-rk-midgard-t86x-r14p0-r0p0_1.6-1-1armbian3_arm64.deb b/external/cache/debs/rk3399/buster_media/libmali-rk-midgard-t86x-r14p0-r0p0_1.6-1-1armbian3_arm64.deb
new file mode 100644
index 0000000..b143d31
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/libmali-rk-midgard-t86x-r14p0-r0p0_1.6-1-1armbian3_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/librga2_2.0.0-1_arm64.deb b/external/cache/debs/rk3399/buster_media/librga2_2.0.0-1_arm64.deb
new file mode 100644
index 0000000..a3fe0ba
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/librga2_2.0.0-1_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/librockchip-mpp1_1.4.0-3armbian3_arm64.deb b/external/cache/debs/rk3399/buster_media/librockchip-mpp1_1.4.0-3armbian3_arm64.deb
new file mode 100644
index 0000000..fec0979
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/librockchip-mpp1_1.4.0-3armbian3_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/librockchip-vpu0_1.4.0-3armbian3_arm64.deb b/external/cache/debs/rk3399/buster_media/librockchip-vpu0_1.4.0-3armbian3_arm64.deb
new file mode 100644
index 0000000..db6f62d
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/librockchip-vpu0_1.4.0-3armbian3_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/media-buster-legacy-rk3399_20.11.4_arm64.deb b/external/cache/debs/rk3399/buster_media/media-buster-legacy-rk3399_20.11.4_arm64.deb
new file mode 100644
index 0000000..019352b
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/media-buster-legacy-rk3399_20.11.4_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/mpv-legacy_2%3a2020.12.08.df805cfc84_arm64.deb b/external/cache/debs/rk3399/buster_media/mpv-legacy_2%3a2020.12.08.df805cfc84_arm64.deb
new file mode 100644
index 0000000..7599c23
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/mpv-legacy_2%3a2020.12.08.df805cfc84_arm64.deb differ
diff --git a/external/cache/debs/rk3399/buster_media/xserver-xorg-core-rockchip_1.20.3-3armbian1_arm64.deb b/external/cache/debs/rk3399/buster_media/xserver-xorg-core-rockchip_1.20.3-3armbian1_arm64.deb
new file mode 100644
index 0000000..aa20808
Binary files /dev/null and b/external/cache/debs/rk3399/buster_media/xserver-xorg-core-rockchip_1.20.3-3armbian1_arm64.deb differ
diff --git a/external/cache/debs/rk3399/libmali-rk-dev_1.6-2_arm64.deb b/external/cache/debs/rk3399/libmali-rk-dev_1.6-2_arm64.deb
new file mode 100644
index 0000000..2747be8
Binary files /dev/null and b/external/cache/debs/rk3399/libmali-rk-dev_1.6-2_arm64.deb differ
diff --git a/external/cache/debs/rk3399/libmali-rk-midgard-t86x-r14p0-r0p0_1.6-1-1armbian3_arm64.deb b/external/cache/debs/rk3399/libmali-rk-midgard-t86x-r14p0-r0p0_1.6-1-1armbian3_arm64.deb
new file mode 100644
index 0000000..b143d31
Binary files /dev/null and b/external/cache/debs/rk3399/libmali-rk-midgard-t86x-r14p0-r0p0_1.6-1-1armbian3_arm64.deb differ
diff --git a/external/cache/debs/rk3399/libmali-rk-midgard-t86x-r14p0_1.6-2_arm64.deb b/external/cache/debs/rk3399/libmali-rk-midgard-t86x-r14p0_1.6-2_arm64.deb
new file mode 100644
index 0000000..56d128f
Binary files /dev/null and b/external/cache/debs/rk3399/libmali-rk-midgard-t86x-r14p0_1.6-2_arm64.deb differ
diff --git a/external/cache/sources/brcm_patchram_plus/Makefile b/external/cache/sources/brcm_patchram_plus/Makefile
new file mode 100755
index 0000000..4cb8a93
--- /dev/null
+++ b/external/cache/sources/brcm_patchram_plus/Makefile
@@ -0,0 +1,20 @@
+# ----------------------------------------------------------------------------
+# Makefile for building tapp
+#
+#
+
+CFLAGS = -Wall -O2
+CC = gcc
+INSTALL = install
+
+TARGET = brcm_patchram_plus
+
+all: $(TARGET)
+
+$(TARGET): brcm_patchram_plus.c
+ $(CC) $(CFLAGS) $< -o $@
+clean distclean:
+ rm -rf *.o $(TARGET)
+# ----------------------------------------------------------------------------
+
+.PHONY: $(PHONY) install clean distclean
diff --git a/external/cache/sources/brcm_patchram_plus/brcm_patchram_plus.c b/external/cache/sources/brcm_patchram_plus/brcm_patchram_plus.c
new file mode 100755
index 0000000..e5fc6f1
--- /dev/null
+++ b/external/cache/sources/brcm_patchram_plus/brcm_patchram_plus.c
@@ -0,0 +1,890 @@
+/*******************************************************************************
+ *
+ * Copyright (C) 2009-2011 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/*****************************************************************************
+**
+** Name: brcm_patchram_plus.c
+**
+** Description: This program downloads a patchram files in the HCD format
+** to Broadcom Bluetooth based silicon and combo chips and
+** and other utility functions.
+**
+** It can be invoked from the command line in the form
+** <-d> to print a debug log
+** <--patchram patchram_file>
+** <--baudrate baud_rate>
+** <--bd_addr bd_address>
+** <--enable_lpm>
+** <--enable_hci>
+** <--use_baudrate_for_download>
+** <--scopcm=sco_routing,pcm_interface_rate,frame_type,
+** sync_mode,clock_mode,lsb_first,fill_bits,
+** fill_method,fill_num,right_justify>
+**
+** Where
+**
+** sco_routing is 0 for PCM, 1 for Transport,
+** 2 for Codec and 3 for I2S,
+**
+** pcm_interface_rate is 0 for 128KBps, 1 for
+** 256 KBps, 2 for 512KBps, 3 for 1024KBps,
+** and 4 for 2048Kbps,
+**
+** frame_type is 0 for short and 1 for long,
+**
+** sync_mode is 0 for slave and 1 for master,
+**
+** clock_mode is 0 for slabe and 1 for master,
+**
+** lsb_first is 0 for false aand 1 for true,
+**
+** fill_bits is the value in decimal for unused bits,
+**
+** fill_method is 0 for 0's and 1 for 1's, 2 for
+** signed and 3 for programmable,
+**
+** fill_num is the number or bits to fill,
+**
+** right_justify is 0 for false and 1 for true
+**
+** <--i2s=i2s_enable,is_master,sample_rate,clock_rate>
+**
+** Where
+**
+** i2s_enable is 0 for disable and 1 for enable,
+**
+** is_master is 0 for slave and 1 for master,
+**
+** sample_rate is 0 for 8KHz, 1 for 16Khz and
+** 2 for 4 KHz,
+**
+** clock_rate is 0 for 128KHz, 1 for 256KHz, 3 for
+** 1024 KHz and 4 for 2048 KHz.
+**
+** <--no2bytes skips waiting for two byte confirmation
+** before starting patchram download. Newer chips
+** do not generate these two bytes.>
+** <--tosleep=number of microsseconds to sleep before
+** patchram download begins.>
+** uart_device_name
+**
+** For example:
+**
+** brcm_patchram_plus -d --patchram \
+** BCM2045B2_002.002.011.0348.0349.hcd /dev/ttyHS0
+**
+** It will return 0 for success and a number greater than 0
+** for any errors.
+**
+** For Android, this program invoked using a
+** "system(2)" call from the beginning of the bt_enable
+** function inside the file
+** system/bluetooth/bluedroid/bluetooth.c.
+**
+** If the Android system property "ro.bt.bcm_bdaddr_path" is
+** set, then the bd_addr will be read from this path.
+** This is overridden by --bd_addr on the command line.
+**
+******************************************************************************/
+
+// TODO: Integrate BCM support into Bluez hciattach
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#ifdef ANDROID
+#include
+#else
+#include
+#include
+#include
+#endif
+
+#include
+#include
+
+#ifdef ANDROID
+#include
+#define LOG_TAG "brcm_patchram_plus"
+#include
+#undef printf
+#define printf ALOGD
+#undef fprintf
+#define fprintf(x, ...) \
+ { if(x==stderr) ALOGE(__VA_ARGS__); else fprintf(x, __VA_ARGS__); }
+
+#endif //ANDROID
+
+#ifndef N_HCI
+#define N_HCI 15
+#endif
+
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define HCIUARTGETPROTO _IOR('U', 201, int)
+#define HCIUARTGETDEVICE _IOR('U', 202, int)
+
+#define HCI_UART_H4 0
+#define HCI_UART_BCSP 1
+#define HCI_UART_3WIRE 2
+#define HCI_UART_H4DS 3
+#define HCI_UART_LL 4
+
+typedef unsigned char uchar;
+
+int uart_fd = -1;
+int hcdfile_fd = -1;
+int termios_baudrate = 0;
+int bdaddr_flag = 0;
+int enable_lpm = 0;
+int enable_hci = 0;
+int use_baudrate_for_download = 0;
+int debug = 0;
+int scopcm = 0;
+int i2s = 0;
+int no2bytes = 0;
+int tosleep = 0;
+
+struct termios termios;
+uchar buffer[1024];
+
+uchar hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
+
+uchar hci_download_minidriver[] = { 0x01, 0x2e, 0xfc, 0x00 };
+
+uchar hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+
+uchar hci_write_bd_addr[] = { 0x01, 0x01, 0xfc, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+uchar hci_write_sleep_mode[] = { 0x01, 0x27, 0xfc, 0x0c,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00 };
+
+uchar hci_write_sco_pcm_int[] =
+ { 0x01, 0x1C, 0xFC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+uchar hci_write_pcm_data_format[] =
+ { 0x01, 0x1e, 0xFC, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+uchar hci_write_i2spcm_interface_param[] =
+ { 0x01, 0x6d, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00 };
+
+#ifdef SAMSUNG_BLUETOOTH
+char* get_samsung_bluetooth_type()
+{
+ char buf[10];
+ int fd = open("/data/.cid.info", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "couldn't open file /data/.cid.info for reading\n");
+ return NULL;
+ }
+
+ if (read(fd, buf, sizeof(buf)) < 0) {
+ close(fd);
+ return NULL;
+ }
+
+ close(fd);
+
+ if (strncmp(buf, "murata", 6) == 0)
+ return "_murata";
+
+ if (strncmp(buf, "semcove", 7) == 0)
+ return "_semcove";
+
+ if (strncmp(buf, "semcosh", 7) == 0)
+ return "_semcosh";
+
+ return NULL;
+}
+#endif
+
+int
+parse_patchram(char *optarg)
+{
+ char *p;
+
+ if (!(p = strrchr(optarg, '.'))) {
+ fprintf(stderr, "file %s not an HCD file\n", optarg);
+ exit(3);
+ }
+
+ p++;
+
+ if (strcasecmp("hcd", p) != 0) {
+ fprintf(stderr, "file %s not an HCD file\n", optarg);
+ exit(4);
+ }
+
+#ifdef SAMSUNG_BLUETOOTH
+ char optarg2[256];
+ char* type = get_samsung_bluetooth_type();
+ char* fext = ".hcd";
+
+ if (type != NULL) {
+ memset(optarg2, 0, 256);
+ strncpy(optarg2, optarg, strlen(optarg) - 4);
+ strcpy(optarg2 + strlen(optarg2), type);
+ strcpy(optarg2 + strlen(optarg2), fext);
+ optarg = optarg2;
+ fprintf(stderr, "using %s as hcdfile\n", optarg);
+ }
+#endif
+
+ if ((hcdfile_fd = open(optarg, O_RDONLY)) == -1) {
+ fprintf(stderr, "file %s could not be opened, error %d\n", optarg, errno);
+ exit(5);
+ }
+
+ return(0);
+}
+
+void
+BRCM_encode_baud_rate(uint baud_rate, uchar *encoded_baud)
+{
+ if(baud_rate == 0 || encoded_baud == NULL) {
+ fprintf(stderr, "Baudrate not supported!");
+ return;
+ }
+
+ encoded_baud[3] = (uchar)(baud_rate >> 24);
+ encoded_baud[2] = (uchar)(baud_rate >> 16);
+ encoded_baud[1] = (uchar)(baud_rate >> 8);
+ encoded_baud[0] = (uchar)(baud_rate & 0xFF);
+}
+
+typedef struct {
+ int baud_rate;
+ int termios_value;
+} tBaudRates;
+
+tBaudRates baud_rates[] = {
+ { 115200, B115200 },
+ { 230400, B230400 },
+ { 460800, B460800 },
+ { 500000, B500000 },
+ { 576000, B576000 },
+ { 921600, B921600 },
+ { 1000000, B1000000 },
+ { 1152000, B1152000 },
+ { 1500000, B1500000 },
+ { 2000000, B2000000 },
+ { 2500000, B2500000 },
+ { 3000000, B3000000 },
+#ifndef __CYGWIN__
+ { 3500000, B3500000 },
+ { 4000000, B4000000 }
+#endif
+};
+
+int
+validate_baudrate(int baud_rate, int *value)
+{
+ unsigned int i;
+
+ for (i = 0; i < (sizeof(baud_rates) / sizeof(tBaudRates)); i++) {
+ if (baud_rates[i].baud_rate == baud_rate) {
+ *value = baud_rates[i].termios_value;
+ return(1);
+ }
+ }
+
+ return(0);
+}
+
+int
+parse_baudrate(char *optarg)
+{
+ int baudrate = atoi(optarg);
+
+ if (validate_baudrate(baudrate, &termios_baudrate)) {
+ BRCM_encode_baud_rate(baudrate, &hci_update_baud_rate[6]);
+ }
+
+ return(0);
+}
+
+int
+parse_bdaddr(char *optarg)
+{
+ int bd_addr[6];
+ int i;
+
+ sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X",
+ &bd_addr[5], &bd_addr[4], &bd_addr[3],
+ &bd_addr[2], &bd_addr[1], &bd_addr[0]);
+
+ for (i = 0; i < 6; i++) {
+ hci_write_bd_addr[4 + i] = bd_addr[i];
+ }
+
+ bdaddr_flag = 1;
+
+ return(0);
+}
+
+int
+parse_enable_lpm(char *optarg)
+{
+ enable_lpm = 1;
+ return(0);
+}
+
+int
+parse_use_baudrate_for_download(char *optarg)
+{
+ use_baudrate_for_download = 1;
+ return(0);
+}
+
+int
+parse_enable_hci(char *optarg)
+{
+ enable_hci = 1;
+ return(0);
+}
+
+int
+parse_scopcm(char *optarg)
+{
+ int param[10];
+ int ret;
+ int i;
+
+ ret = sscanf(optarg, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ ¶m[0], ¶m[1], ¶m[2], ¶m[3], ¶m[4],
+ ¶m[5], ¶m[6], ¶m[7], ¶m[8], ¶m[9]);
+
+ if (ret != 10) {
+ return(1);
+ }
+
+ scopcm = 1;
+
+ for (i = 0; i < 5; i++) {
+ hci_write_sco_pcm_int[4 + i] = param[i];
+ }
+
+ for (i = 0; i < 5; i++) {
+ hci_write_pcm_data_format[4 + i] = param[5 + i];
+ }
+
+ return(0);
+}
+
+int
+parse_i2s(char *optarg)
+{
+ int param[4];
+ int ret;
+ int i;
+
+ ret = sscanf(optarg, "%d,%d,%d,%d", ¶m[0], ¶m[1], ¶m[2],
+ ¶m[3]);
+
+ if (ret != 4) {
+ return(1);
+ }
+
+ i2s = 1;
+
+ for (i = 0; i < 4; i++) {
+ hci_write_i2spcm_interface_param[4 + i] = param[i];
+ }
+
+ return(0);
+}
+
+int
+parse_no2bytes(char *optarg)
+{
+ no2bytes = 1;
+ return(0);
+}
+
+int
+parse_tosleep(char *optarg)
+{
+ tosleep = atoi(optarg);
+
+ if (tosleep <= 0) {
+ return(1);
+ }
+
+ return(0);
+}
+
+void
+usage(char *argv0)
+{
+ printf("Usage %s:\n", argv0);
+ printf("\t<-d> to print a debug log\n");
+ printf("\t<--patchram patchram_file>\n");
+ printf("\t<--baudrate baud_rate>\n");
+ printf("\t<--bd_addr bd_address>\n");
+ printf("\t<--enable_lpm>\n");
+ printf("\t<--enable_hci>\n");
+ printf("\t<--use_baudrate_for_download> - Uses the\n");
+ printf("\t\tbaudrate for downloading the firmware\n");
+ printf("\t<--scopcm=sco_routing,pcm_interface_rate,frame_type,\n");
+ printf("\t\tsync_mode,clock_mode,lsb_first,fill_bits,\n");
+ printf("\t\tfill_method,fill_num,right_justify>\n");
+ printf("\n\t\tWhere\n");
+ printf("\n\t\tsco_routing is 0 for PCM, 1 for Transport,\n");
+ printf("\t\t2 for Codec and 3 for I2S,\n");
+ printf("\n\t\tpcm_interface_rate is 0 for 128KBps, 1 for\n");
+ printf("\t\t256 KBps, 2 for 512KBps, 3 for 1024KBps,\n");
+ printf("\t\tand 4 for 2048Kbps,\n");
+ printf("\n\t\tframe_type is 0 for short and 1 for long,\n");
+ printf("\t\tsync_mode is 0 for slave and 1 for master,\n");
+ printf("\n\t\tclock_mode is 0 for slabe and 1 for master,\n");
+ printf("\n\t\tlsb_first is 0 for false aand 1 for true,\n");
+ printf("\n\t\tfill_bits is the value in decimal for unused bits,\n");
+ printf("\n\t\tfill_method is 0 for 0's and 1 for 1's, 2 for\n");
+ printf("\t\tsigned and 3 for programmable,\n");
+ printf("\n\t\tfill_num is the number or bits to fill,\n");
+ printf("\n\t\tright_justify is 0 for false and 1 for true\n");
+ printf("\n\t<--i2s=i2s_enable,is_master,sample_rate,clock_rate>\n");
+ printf("\n\t\tWhere\n");
+ printf("\n\t\ti2s_enable is 0 for disable and 1 for enable,\n");
+ printf("\n\t\tis_master is 0 for slave and 1 for master,\n");
+ printf("\n\t\tsample_rate is 0 for 8KHz, 1 for 16Khz and\n");
+ printf("\t\t2 for 4 KHz,\n");
+ printf("\n\t\tclock_rate is 0 for 128KHz, 1 for 256KHz, 3 for\n");
+ printf("\t\t1024 KHz and 4 for 2048 KHz.\n\n");
+ printf("\t<--no2bytes skips waiting for two byte confirmation\n");
+ printf("\t\tbefore starting patchram download. Newer chips\n");
+ printf("\t\tdo not generate these two bytes.>\n");
+ printf("\t<--tosleep=microseconds>\n");
+ printf("\tuart_device_name\n");
+}
+
+int
+parse_cmd_line(int argc, char **argv)
+{
+ int c;
+ int ret = 0;
+
+ typedef int (*PFI)();
+
+ PFI parse[] = { parse_patchram, parse_baudrate,
+ parse_bdaddr, parse_enable_lpm, parse_enable_hci,
+ parse_use_baudrate_for_download,
+ parse_scopcm, parse_i2s, parse_no2bytes, parse_tosleep};
+
+ while (1) {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+
+ static struct option long_options[] = {
+ {"patchram", 1, 0, 0},
+ {"baudrate", 1, 0, 0},
+ {"bd_addr", 1, 0, 0},
+ {"enable_lpm", 0, 0, 0},
+ {"enable_hci", 0, 0, 0},
+ {"use_baudrate_for_download", 0, 0, 0},
+ {"scopcm", 1, 0, 0},
+ {"i2s", 1, 0, 0},
+ {"no2bytes", 0, 0, 0},
+ {"tosleep", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long_only (argc, argv, "d", long_options,
+ &option_index);
+
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 0:
+ if (debug) {
+ printf ("option %s",
+ long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ }
+
+ ret = (*parse[option_index])(optarg);
+
+ break;
+ case 'd':
+ debug = 1;
+ break;
+
+ case '?':
+ //nobreak
+ default:
+ usage(argv[0]);
+ break;
+ }
+
+ if (ret) {
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if (ret) {
+ return(1);
+ }
+
+ if (optind < argc) {
+ if (debug)
+ printf ("%s \n", argv[optind]);
+ if ((uart_fd = open(argv[optind], O_RDWR | O_NOCTTY)) == -1) {
+ fprintf(stderr, "port %s could not be opened, error %d\n",
+ argv[optind], errno);
+ }
+ }
+
+ return(0);
+}
+
+void
+init_uart()
+{
+#ifdef BCM_INIT_DELAY
+ usleep(150*1000);
+#endif
+ tcflush(uart_fd, TCIOFLUSH);
+ tcgetattr(uart_fd, &termios);
+
+#ifndef __CYGWIN__
+ cfmakeraw(&termios);
+#else
+ termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+ | INLCR | IGNCR | ICRNL | IXON);
+ termios.c_oflag &= ~OPOST;
+ termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ termios.c_cflag &= ~(CSIZE | PARENB);
+ termios.c_cflag |= CS8;
+#endif
+
+ termios.c_cflag |= CRTSCTS;
+ tcsetattr(uart_fd, TCSANOW, &termios);
+ tcflush(uart_fd, TCIOFLUSH);
+ tcsetattr(uart_fd, TCSANOW, &termios);
+ tcflush(uart_fd, TCIOFLUSH);
+ tcflush(uart_fd, TCIOFLUSH);
+ cfsetospeed(&termios, B115200);
+ cfsetispeed(&termios, B115200);
+ tcsetattr(uart_fd, TCSANOW, &termios);
+}
+
+void
+dump(uchar *out, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (i && !(i % 16)) {
+ fprintf(stderr, "\n");
+ }
+
+ fprintf(stderr, "%02x ", out[i]);
+ }
+
+ fprintf(stderr, "\n");
+}
+
+void
+read_event(int fd, uchar *buffer)
+{
+ int i = 0;
+ int len = 3;
+ int count;
+
+ while ((count = read(fd, &buffer[i], len)) < len) {
+ i += count;
+ len -= count;
+ }
+
+ i += count;
+ len = buffer[2];
+
+ while ((count = read(fd, &buffer[i], len)) < len) {
+ i += count;
+ len -= count;
+ }
+
+ if (debug) {
+ count += i;
+
+ fprintf(stderr, "received %d\n", count);
+ dump(buffer, count);
+ }
+}
+
+void
+hci_send_cmd(uchar *buf, int len)
+{
+ if (debug) {
+ fprintf(stderr, "writing\n");
+ dump(buf, len);
+ }
+
+ write(uart_fd, buf, len);
+}
+
+void
+expired(int sig)
+{
+ hci_send_cmd(hci_reset, sizeof(hci_reset));
+ alarm(4);
+}
+
+void
+proc_reset()
+{
+ signal(SIGALRM, expired);
+
+
+ hci_send_cmd(hci_reset, sizeof(hci_reset));
+
+ alarm(4);
+
+ read_event(uart_fd, buffer);
+
+ alarm(0);
+}
+
+void
+proc_patchram()
+{
+ int len;
+
+ hci_send_cmd(hci_download_minidriver, sizeof(hci_download_minidriver));
+
+ read_event(uart_fd, buffer);
+
+ if (!no2bytes) {
+ read(uart_fd, &buffer[0], 2);
+ }
+
+ if (tosleep) {
+ usleep(tosleep);
+ }
+
+ while (read(hcdfile_fd, &buffer[1], 3)) {
+ buffer[0] = 0x01;
+
+ len = buffer[3];
+
+ read(hcdfile_fd, &buffer[4], len);
+
+ hci_send_cmd(buffer, len + 4);
+
+ read_event(uart_fd, buffer);
+ }
+
+ if (use_baudrate_for_download) {
+ cfsetospeed(&termios, B115200);
+ cfsetispeed(&termios, B115200);
+ tcsetattr(uart_fd, TCSANOW, &termios);
+ }
+ proc_reset();
+}
+
+void
+proc_baudrate()
+{
+ hci_send_cmd(hci_update_baud_rate, sizeof(hci_update_baud_rate));
+
+ read_event(uart_fd, buffer);
+
+ cfsetospeed(&termios, termios_baudrate);
+ cfsetispeed(&termios, termios_baudrate);
+ tcsetattr(uart_fd, TCSANOW, &termios);
+
+ if (debug) {
+ fprintf(stderr, "Done setting baudrate\n");
+ }
+}
+
+void
+proc_bdaddr()
+{
+ hci_send_cmd(hci_write_bd_addr, sizeof(hci_write_bd_addr));
+
+ read_event(uart_fd, buffer);
+}
+
+void
+proc_enable_lpm()
+{
+ hci_send_cmd(hci_write_sleep_mode, sizeof(hci_write_sleep_mode));
+
+ read_event(uart_fd, buffer);
+}
+
+void
+proc_scopcm()
+{
+ hci_send_cmd(hci_write_sco_pcm_int,
+ sizeof(hci_write_sco_pcm_int));
+
+ read_event(uart_fd, buffer);
+
+ hci_send_cmd(hci_write_pcm_data_format,
+ sizeof(hci_write_pcm_data_format));
+
+ read_event(uart_fd, buffer);
+}
+
+void
+proc_i2s()
+{
+ hci_send_cmd(hci_write_i2spcm_interface_param,
+ sizeof(hci_write_i2spcm_interface_param));
+
+ read_event(uart_fd, buffer);
+}
+
+void
+proc_enable_hci()
+{
+ int i = N_HCI;
+ int proto = HCI_UART_H4;
+ if (ioctl(uart_fd, TIOCSETD, &i) < 0) {
+ fprintf(stderr, "Can't set line discipline\n");
+ return;
+ }
+
+ if (ioctl(uart_fd, HCIUARTSETPROTO, proto) < 0) {
+ fprintf(stderr, "Can't set hci protocol\n");
+ return;
+ }
+ fprintf(stderr, "Done setting line discpline\n");
+ return;
+}
+
+#ifdef ANDROID
+void
+read_default_bdaddr()
+{
+ int sz;
+ int fd;
+
+ char path[PROPERTY_VALUE_MAX];
+
+ char bdaddr[18];
+ int len = 17;
+ memset(bdaddr, 0, (len + 1) * sizeof(char));
+
+ property_get("ro.bt.bdaddr_path", path, "");
+ if (path[0] == 0)
+ return;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "open(%s) failed: %s (%d)", path, strerror(errno),
+ errno);
+ return;
+ }
+
+ sz = read(fd, bdaddr, len);
+ if (sz < 0) {
+ fprintf(stderr, "read(%s) failed: %s (%d)", path, strerror(errno),
+ errno);
+ close(fd);
+ return;
+ } else if (sz != len) {
+ fprintf(stderr, "read(%s) unexpected size %d", path, sz);
+ close(fd);
+ return;
+ }
+
+ if (debug) {
+ printf("Read default bdaddr of %s\n", bdaddr);
+ }
+
+ parse_bdaddr(bdaddr);
+}
+#endif
+
+
+int
+main (int argc, char **argv)
+{
+#ifdef ANDROID
+ read_default_bdaddr();
+#endif
+
+ if (parse_cmd_line(argc, argv)) {
+ exit(1);
+ }
+
+ if (uart_fd < 0) {
+ exit(2);
+ }
+
+ init_uart();
+
+ proc_reset();
+
+ if (use_baudrate_for_download) {
+ if (termios_baudrate) {
+ proc_baudrate();
+ }
+ }
+
+ if (hcdfile_fd > 0) {
+ proc_patchram();
+ }
+
+ if (termios_baudrate) {
+ proc_baudrate();
+ }
+
+ if (bdaddr_flag) {
+ proc_bdaddr();
+ }
+
+ if (enable_lpm) {
+ proc_enable_lpm();
+ }
+
+ if (scopcm) {
+ proc_scopcm();
+ }
+
+ if (i2s) {
+ proc_i2s();
+ }
+
+ if (enable_hci) {
+ proc_enable_hci();
+
+ while (1) {
+ sleep(UINT_MAX);
+ }
+ }
+
+ exit(0);
+}
diff --git a/external/cache/sources/hcitools/Makefile b/external/cache/sources/hcitools/Makefile
new file mode 100644
index 0000000..d902df9
--- /dev/null
+++ b/external/cache/sources/hcitools/Makefile
@@ -0,0 +1,95 @@
+#CFLAGS := $(CFLAGS) -g
+CFLAGS = -I. -Ilib -Wall -DVERSION=\"5.10\" -Wno-strict-aliasing
+CFLAGS += -Ilib/bluetooth
+
+# include rule.mk
+include ./rule.mk
+
+# define objects collection variable
+lib = \
+ lib/bluetooth.o \
+ lib/hci.o \
+ lib/sdp.o
+
+hciattach_objs = \
+ hciattach.o \
+ hciattach_ath3k.o \
+ hciattach_bcm43xx.o \
+ hciattach_intel.o \
+ hciattach_qualcomm.o \
+ hciattach_st.o \
+ hciattach_ti.o \
+ hciattach_tialt.o \
+ hciattach_rtk.o \
+ hciattach_xr.o \
+ hciattach_sprd.o
+
+hciconfig_objs = \
+ hciconfig.o \
+ csr.o
+
+hcitool_objs = \
+ hcitool.o
+
+btmon_objs = \
+ monitor/main.o \
+ monitor/mainloop.o \
+ monitor/display.o \
+ monitor/hcidump.o \
+ monitor/btsnoop.o \
+ monitor/control.o \
+ monitor/packet.o \
+ monitor/vendor.o \
+ monitor/lmp.o \
+ monitor/l2cap.o \
+ monitor/uuid.o \
+ monitor/sdp.o \
+ monitor/crc.o \
+ monitor/ll.o
+
+# add your target(s) to all
+.PHONY: all
+all: hciattach_opi hciconfig hcitool btmon
+
+# directory
+hciattach_opi: $(hciattach_objs) $(lib)
+ $(LINK_MSG)
+ $(LINKX)
+
+hciconfig: $(hciconfig_objs) $(lib)
+ $(LINK_MSG)
+ $(LINKX)
+
+hcitool: $(hcitool_objs) $(lib)
+ $(LINK_MSG)
+ $(LINKX)
+
+btmon: $(btmon_objs) $(lib)
+ $(LINK_MSG)
+ $(LINKX)
+
+# change objs to your objects collection variable
+$(hciattach_objs): %.o: %.c
+ $(COMPILE_MSG)
+ $(COMPILEX)
+
+$(hciconfig_objs): %.o: %.c
+ $(COMPILE_MSG)
+ $(COMPILEX)
+
+$(hcitool_objs): %.o: %.c
+ $(COMPILE_MSG)
+ $(COMPILEX)
+
+$(btmon_objs): %.o: %.c
+ $(COMPILE_MSG)
+ $(COMPILEX)
+
+# clean temp files
+clean:
+ -rm -rf $(hciattach_objs) $(hciattach_objs:.o=.d)
+ -rm -rf $(hciconfig_objs) $(hciconfig_objs:.o=.d)
+ -rm -rf $(hcitool_objs) $(hcitool_objs:.o=.d)
+ -rm -rf $(lib) $(lib:.o=.d)
+ -rm -rf $(btmon_objs) $(btmon_objs:.o=.d)
+ #-rm -rf output
diff --git a/external/cache/sources/hcitools/NOTICE b/external/cache/sources/hcitools/NOTICE
new file mode 100644
index 0000000..52321cc
--- /dev/null
+++ b/external/cache/sources/hcitools/NOTICE
@@ -0,0 +1,343 @@
+All of these programs are made available under version 2 of the GNU General
+Public Licence.
+
+ GNU GENERAL PUBLIC LICENSE
+ 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
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, 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 or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+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 give any other recipients of the Program a copy of this License
+along with the Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) 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; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, 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 executable. However, as a
+special exception, the source code 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.
+
+If distribution of executable or 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 counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+ 5. 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 Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program 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 to
+this License.
+
+ 7. 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 Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program 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.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+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 Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+ 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
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), 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 Programs
+
+ 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
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. 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.
+
+
+ Copyright (C)
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ 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.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/external/cache/sources/hcitools/csr.c b/external/cache/sources/hcitools/csr.c
new file mode 100644
index 0000000..b4ea1fb
--- /dev/null
+++ b/external/cache/sources/hcitools/csr.c
@@ -0,0 +1,2853 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "csr.h"
+
+struct psr_data {
+ uint16_t pskey;
+ uint8_t *value;
+ uint8_t size;
+ struct psr_data *next;
+};
+
+static struct psr_data *head = NULL, *tail = NULL;
+
+static struct {
+ uint16_t id;
+ char *str;
+} csr_map[] = {
+ { 66, "HCI 9.8" },
+ { 97, "HCI 10.3" },
+ { 101, "HCI 10.5" },
+ { 111, "HCI 11.0" },
+ { 112, "HCI 11.1" },
+ { 114, "HCI 11.2" },
+ { 115, "HCI 11.3" },
+ { 117, "HCI 12.0" },
+ { 119, "HCI 12.1" },
+ { 133, "HCI 12.2" },
+ { 134, "HCI 12.3" },
+ { 162, "HCI 12.4" },
+ { 165, "HCI 12.5" },
+ { 169, "HCI 12.6" },
+ { 188, "HCI 12.7" },
+ { 218, "HCI 12.8" },
+ { 283, "HCI 12.9" },
+ { 203, "HCI 13.2" },
+ { 204, "HCI 13.2" },
+ { 210, "HCI 13.3" },
+ { 211, "HCI 13.3" },
+ { 213, "HCI 13.4" },
+ { 214, "HCI 13.4" },
+ { 225, "HCI 13.5" },
+ { 226, "HCI 13.5" },
+ { 237, "HCI 13.6" },
+ { 238, "HCI 13.6" },
+ { 242, "HCI 14.0" },
+ { 243, "HCI 14.0" },
+ { 244, "HCI 14.0" },
+ { 245, "HCI 14.0" },
+ { 254, "HCI 13.7" },
+ { 255, "HCI 13.7" },
+ { 264, "HCI 14.1" },
+ { 265, "HCI 14.1" },
+ { 267, "HCI 14.2" },
+ { 268, "HCI 14.2" },
+ { 272, "HCI 14.3" },
+ { 273, "HCI 14.3" },
+ { 274, "HCI 13.8" },
+ { 275, "HCI 13.8" },
+ { 286, "HCI 13.9" },
+ { 287, "HCI 13.9" },
+ { 309, "HCI 13.10" },
+ { 310, "HCI 13.10" },
+ { 313, "HCI 14.4" },
+ { 314, "HCI 14.4" },
+ { 323, "HCI 14.5" },
+ { 324, "HCI 14.5" },
+ { 336, "HCI 14.6" },
+ { 337, "HCI 14.6" },
+ { 351, "HCI 13.11" },
+ { 352, "HCI 13.11" },
+ { 362, "HCI 15.0" },
+ { 363, "HCI 15.0" },
+ { 364, "HCI 15.0" },
+ { 365, "HCI 15.0" },
+ { 373, "HCI 14.7" },
+ { 374, "HCI 14.7" },
+ { 379, "HCI 15.1" },
+ { 380, "HCI 15.1" },
+ { 381, "HCI 15.1" },
+ { 382, "HCI 15.1" },
+ { 392, "HCI 15.2" },
+ { 393, "HCI 15.2" },
+ { 394, "HCI 15.2" },
+ { 395, "HCI 15.2" },
+ { 436, "HCI 16.0" },
+ { 437, "HCI 16.0" },
+ { 438, "HCI 16.0" },
+ { 439, "HCI 16.0" },
+ { 443, "HCI 15.3" },
+ { 444, "HCI 15.3" },
+ { 465, "HCI 16.1" },
+ { 466, "HCI 16.1" },
+ { 467, "HCI 16.1" },
+ { 468, "HCI 16.1" },
+ { 487, "HCI 14.8" },
+ { 488, "HCI 14.8" },
+ { 492, "HCI 16.2" },
+ { 493, "HCI 16.2" },
+ { 495, "HCI 16.2" },
+ { 496, "HCI 16.2" },
+ { 502, "HCI 16.1.1" },
+ { 503, "HCI 16.1.1" },
+ { 504, "HCI 16.1.1" },
+ { 505, "HCI 16.1.1" },
+ { 506, "HCI 16.1.2" },
+ { 507, "HCI 16.1.2" },
+ { 508, "HCI 16.1.2" },
+ { 509, "HCI 16.1.2" },
+ { 516, "HCI 16.3" },
+ { 517, "HCI 16.3" },
+ { 518, "HCI 16.3" },
+ { 519, "HCI 16.3" },
+ { 523, "HCI 16.4" },
+ { 524, "HCI 16.4" },
+ { 525, "HCI 16.4" },
+ { 526, "HCI 16.4" },
+ { 553, "HCI 15.3" },
+ { 554, "HCI 15.3" },
+ { 562, "HCI 16.5" },
+ { 563, "HCI 16.5" },
+ { 564, "HCI 16.5" },
+ { 565, "HCI 16.5" },
+ { 593, "HCI 17.0" },
+ { 594, "HCI 17.0" },
+ { 595, "HCI 17.0" },
+ { 599, "HCI 17.0" },
+ { 600, "HCI 17.0" },
+ { 608, "HCI 13.10.1" },
+ { 609, "HCI 13.10.1" },
+ { 613, "HCI 17.1" },
+ { 614, "HCI 17.1" },
+ { 615, "HCI 17.1" },
+ { 616, "HCI 17.1" },
+ { 618, "HCI 17.1" },
+ { 624, "HCI 17.2" },
+ { 625, "HCI 17.2" },
+ { 626, "HCI 17.2" },
+ { 627, "HCI 17.2" },
+ { 637, "HCI 16.6" },
+ { 638, "HCI 16.6" },
+ { 639, "HCI 16.6" },
+ { 640, "HCI 16.6" },
+ { 642, "HCI 13.10.2" },
+ { 643, "HCI 13.10.2" },
+ { 644, "HCI 13.10.3" },
+ { 645, "HCI 13.10.3" },
+ { 668, "HCI 13.10.4" },
+ { 669, "HCI 13.10.4" },
+ { 681, "HCI 16.7" },
+ { 682, "HCI 16.7" },
+ { 683, "HCI 16.7" },
+ { 684, "HCI 16.7" },
+ { 704, "HCI 16.8" },
+ { 718, "HCI 16.4.1" },
+ { 719, "HCI 16.4.1" },
+ { 720, "HCI 16.4.1" },
+ { 721, "HCI 16.4.1" },
+ { 722, "HCI 16.7.1" },
+ { 723, "HCI 16.7.1" },
+ { 724, "HCI 16.7.1" },
+ { 725, "HCI 16.7.1" },
+ { 731, "HCI 16.7.2" },
+ { 732, "HCI 16.7.2" },
+ { 733, "HCI 16.7.2" },
+ { 734, "HCI 16.7.2" },
+ { 735, "HCI 16.4.2" },
+ { 736, "HCI 16.4.2" },
+ { 737, "HCI 16.4.2" },
+ { 738, "HCI 16.4.2" },
+ { 750, "HCI 16.7.3" },
+ { 751, "HCI 16.7.3" },
+ { 752, "HCI 16.7.3" },
+ { 753, "HCI 16.7.3" },
+ { 760, "HCI 16.7.4" },
+ { 761, "HCI 16.7.4" },
+ { 762, "HCI 16.7.4" },
+ { 763, "HCI 16.7.4" },
+ { 770, "HCI 16.9" },
+ { 771, "HCI 16.9" },
+ { 772, "HCI 16.9" },
+ { 773, "HCI 16.9" },
+ { 774, "HCI 17.3" },
+ { 775, "HCI 17.3" },
+ { 776, "HCI 17.3" },
+ { 777, "HCI 17.3" },
+ { 781, "HCI 16.7.5" },
+ { 786, "HCI 16.10" },
+ { 787, "HCI 16.10" },
+ { 788, "HCI 16.10" },
+ { 789, "HCI 16.10" },
+ { 791, "HCI 16.4.3" },
+ { 792, "HCI 16.4.3" },
+ { 793, "HCI 16.4.3" },
+ { 794, "HCI 16.4.3" },
+ { 798, "HCI 16.11" },
+ { 799, "HCI 16.11" },
+ { 800, "HCI 16.11" },
+ { 801, "HCI 16.11" },
+ { 806, "HCI 16.7.5" },
+ { 807, "HCI 16.12" },
+ { 808, "HCI 16.12" },
+ { 809, "HCI 16.12" },
+ { 810, "HCI 16.12" },
+ { 817, "HCI 16.13" },
+ { 818, "HCI 16.13" },
+ { 819, "HCI 16.13" },
+ { 820, "HCI 16.13" },
+ { 823, "HCI 13.10.5" },
+ { 824, "HCI 13.10.5" },
+ { 826, "HCI 16.14" },
+ { 827, "HCI 16.14" },
+ { 828, "HCI 16.14" },
+ { 829, "HCI 16.14" },
+ { 843, "HCI 17.3.1" },
+ { 856, "HCI 17.3.2" },
+ { 857, "HCI 17.3.2" },
+ { 858, "HCI 17.3.2" },
+ { 1120, "HCI 17.11" },
+ { 1168, "HCI 18.1" },
+ { 1169, "HCI 18.1" },
+ { 1241, "HCI 18.x" },
+ { 1298, "HCI 18.2" },
+ { 1354, "HCI 18.2" },
+ { 1392, "HCI 18.2" },
+ { 1393, "HCI 18.2" },
+ { 1501, "HCI 18.2" },
+ { 1503, "HCI 18.2" },
+ { 1504, "HCI 18.2" },
+ { 1505, "HCI 18.2" },
+ { 1506, "HCI 18.2" },
+ { 1520, "HCI 18.2" },
+ { 1586, "HCI 18.2" },
+ { 1591, "HCI 18.2" },
+ { 1592, "HCI 18.2" },
+ { 1593, "HCI 18.2.1" },
+ { 1733, "HCI 18.3" },
+ { 1734, "HCI 18.3" },
+ { 1735, "HCI 18.3" },
+ { 1737, "HCI 18.3" },
+ { 1915, "HCI 19.2" },
+ { 1916, "HCI 19.2" },
+ { 1958, "HCI 19.2" },
+ { 1981, "Unified 20a" },
+ { 1982, "Unified 20a" },
+ { 1989, "HCI 18.4" },
+ { 2062, "Unified 20a1" },
+ { 2063, "Unified 20a1" },
+ { 2067, "Unified 18f" },
+ { 2068, "Unified 18f" },
+ { 2243, "Unified 18e" },
+ { 2244, "Unified 18e" },
+ { 2258, "Unified 20d" },
+ { 2259, "Unified 20d" },
+ { 2361, "Unified 20e" },
+ { 2362, "Unified 20e" },
+ { 2386, "Unified 21a" },
+ { 2387, "Unified 21a" },
+ { 2423, "Unified 21a" },
+ { 2424, "Unified 21a" },
+ { 2623, "Unified 21c" },
+ { 2624, "Unified 21c" },
+ { 2625, "Unified 21c" },
+ { 2626, "Unified 21c" },
+ { 2627, "Unified 21c" },
+ { 2628, "Unified 21c" },
+ { 2629, "Unified 21c" },
+ { 2630, "Unified 21c" },
+ { 2631, "Unified 21c" },
+ { 2632, "Unified 21c" },
+ { 2633, "Unified 21c" },
+ { 2634, "Unified 21c" },
+ { 2635, "Unified 21c" },
+ { 2636, "Unified 21c" },
+ { 2649, "Unified 21c" },
+ { 2650, "Unified 21c" },
+ { 2651, "Unified 21c" },
+ { 2652, "Unified 21c" },
+ { 2653, "Unified 21c" },
+ { 2654, "Unified 21c" },
+ { 2655, "Unified 21c" },
+ { 2656, "Unified 21c" },
+ { 2658, "Unified 21c" },
+ { 3057, "Unified 21d" },
+ { 3058, "Unified 21d" },
+ { 3059, "Unified 21d" },
+ { 3060, "Unified 21d" },
+ { 3062, "Unified 21d" },
+ { 3063, "Unified 21d" },
+ { 3064, "Unified 21d" },
+ { 3164, "Unified 21e" },
+ { 3413, "Unified 21f" },
+ { 3414, "Unified 21f" },
+ { 3415, "Unified 21f" },
+ { 3424, "Unified 21f" },
+ { 3454, "Unified 21f" },
+ { 3684, "Unified 21f" },
+ { 3764, "Unified 21f" },
+ { 4276, "Unified 22b" },
+ { 4277, "Unified 22b" },
+ { 4279, "Unified 22b" },
+ { 4281, "Unified 22b" },
+ { 4282, "Unified 22b" },
+ { 4283, "Unified 22b" },
+ { 4284, "Unified 22b" },
+ { 4285, "Unified 22b" },
+ { 4289, "Unified 22b" },
+ { 4290, "Unified 22b" },
+ { 4291, "Unified 22b" },
+ { 4292, "Unified 22b" },
+ { 4293, "Unified 22b" },
+ { 4294, "Unified 22b" },
+ { 4295, "Unified 22b" },
+ { 4363, "Unified 22c" },
+ { 4373, "Unified 22c" },
+ { 4374, "Unified 22c" },
+ { 4532, "Unified 22d" },
+ { 4533, "Unified 22d" },
+ { 4698, "Unified 23c" },
+ { 4839, "Unified 23c" },
+ { 4841, "Unified 23c" },
+ { 4866, "Unified 23c" },
+ { 4867, "Unified 23c" },
+ { 4868, "Unified 23c" },
+ { 4869, "Unified 23c" },
+ { 4870, "Unified 23c" },
+ { 4871, "Unified 23c" },
+ { 4872, "Unified 23c" },
+ { 4874, "Unified 23c" },
+ { 4875, "Unified 23c" },
+ { 4876, "Unified 23c" },
+ { 4877, "Unified 23c" },
+ { 2526, "Marcel 1 (2005-09-26)" },
+ { 2543, "Marcel 2 (2005-09-28)" },
+ { 2622, "Marcel 3 (2005-10-27)" },
+ { 3326, "Marcel 4 (2006-06-16)" },
+ { 3612, "Marcel 5 (2006-10-24)" },
+ { 4509, "Marcel 6 (2007-06-11)" },
+ { 5417, "Marcel 7 (2008-08-26)" },
+ { 195, "Sniff 1 (2001-11-27)" },
+ { 220, "Sniff 2 (2002-01-03)" },
+ { 269, "Sniff 3 (2002-02-22)" },
+ { 270, "Sniff 4 (2002-02-26)" },
+ { 284, "Sniff 5 (2002-03-12)" },
+ { 292, "Sniff 6 (2002-03-20)" },
+ { 305, "Sniff 7 (2002-04-12)" },
+ { 306, "Sniff 8 (2002-04-12)" },
+ { 343, "Sniff 9 (2002-05-02)" },
+ { 346, "Sniff 10 (2002-05-03)" },
+ { 355, "Sniff 11 (2002-05-16)" },
+ { 256, "Sniff 11 (2002-05-16)" },
+ { 390, "Sniff 12 (2002-06-26)" },
+ { 450, "Sniff 13 (2002-08-16)" },
+ { 451, "Sniff 13 (2002-08-16)" },
+ { 533, "Sniff 14 (2002-10-11)" },
+ { 580, "Sniff 15 (2002-11-14)" },
+ { 623, "Sniff 16 (2002-12-12)" },
+ { 678, "Sniff 17 (2003-01-29)" },
+ { 847, "Sniff 18 (2003-04-17)" },
+ { 876, "Sniff 19 (2003-06-10)" },
+ { 997, "Sniff 22 (2003-09-05)" },
+ { 1027, "Sniff 23 (2003-10-03)" },
+ { 1029, "Sniff 24 (2003-10-03)" },
+ { 1112, "Sniff 25 (2003-12-03)" },
+ { 1113, "Sniff 25 (2003-12-03)" },
+ { 1133, "Sniff 26 (2003-12-18)" },
+ { 1134, "Sniff 26 (2003-12-18)" },
+ { 1223, "Sniff 27 (2004-03-08)" },
+ { 1224, "Sniff 27 (2004-03-08)" },
+ { 1319, "Sniff 31 (2004-04-22)" },
+ { 1320, "Sniff 31 (2004-04-22)" },
+ { 1427, "Sniff 34 (2004-06-16)" },
+ { 1508, "Sniff 35 (2004-07-19)" },
+ { 1509, "Sniff 35 (2004-07-19)" },
+ { 1587, "Sniff 36 (2004-08-18)" },
+ { 1588, "Sniff 36 (2004-08-18)" },
+ { 1641, "Sniff 37 (2004-09-16)" },
+ { 1642, "Sniff 37 (2004-09-16)" },
+ { 1699, "Sniff 38 (2004-10-07)" },
+ { 1700, "Sniff 38 (2004-10-07)" },
+ { 1752, "Sniff 39 (2004-11-02)" },
+ { 1753, "Sniff 39 (2004-11-02)" },
+ { 1759, "Sniff 40 (2004-11-03)" },
+ { 1760, "Sniff 40 (2004-11-03)" },
+ { 1761, "Sniff 40 (2004-11-03)" },
+ { 2009, "Sniff 41 (2005-04-06)" },
+ { 2010, "Sniff 41 (2005-04-06)" },
+ { 2011, "Sniff 41 (2005-04-06)" },
+ { 2016, "Sniff 42 (2005-04-11)" },
+ { 2017, "Sniff 42 (2005-04-11)" },
+ { 2018, "Sniff 42 (2005-04-11)" },
+ { 2023, "Sniff 43 (2005-04-14)" },
+ { 2024, "Sniff 43 (2005-04-14)" },
+ { 2025, "Sniff 43 (2005-04-14)" },
+ { 2032, "Sniff 44 (2005-04-18)" },
+ { 2033, "Sniff 44 (2005-04-18)" },
+ { 2034, "Sniff 44 (2005-04-18)" },
+ { 2288, "Sniff 45 (2005-07-08)" },
+ { 2289, "Sniff 45 (2005-07-08)" },
+ { 2290, "Sniff 45 (2005-07-08)" },
+ { 2388, "Sniff 46 (2005-08-17)" },
+ { 2389, "Sniff 46 (2005-08-17)" },
+ { 2390, "Sniff 46 (2005-08-17)" },
+ { 2869, "Sniff 47 (2006-02-15)" },
+ { 2870, "Sniff 47 (2006-02-15)" },
+ { 2871, "Sniff 47 (2006-02-15)" },
+ { 3214, "Sniff 48 (2006-05-16)" },
+ { 3215, "Sniff 48 (2006-05-16)" },
+ { 3216, "Sniff 48 (2006-05-16)" },
+ { 3356, "Sniff 49 (2006-07-17)" },
+ { 3529, "Sniff 50 (2006-09-21)" },
+ { 3546, "Sniff 51 (2006-09-29)" },
+ { 3683, "Sniff 52 (2006-11-03)" },
+ { 0, }
+};
+
+char *csr_builddeftostr(uint16_t def)
+{
+ switch (def) {
+ case 0x0000:
+ return "NONE";
+ case 0x0001:
+ return "CHIP_BASE_BC01";
+ case 0x0002:
+ return "CHIP_BASE_BC02";
+ case 0x0003:
+ return "CHIP_BC01B";
+ case 0x0004:
+ return "CHIP_BC02_EXTERNAL";
+ case 0x0005:
+ return "BUILD_HCI";
+ case 0x0006:
+ return "BUILD_RFCOMM";
+ case 0x0007:
+ return "BT_VER_1_1";
+ case 0x0008:
+ return "TRANSPORT_ALL";
+ case 0x0009:
+ return "TRANSPORT_BCSP";
+ case 0x000a:
+ return "TRANSPORT_H4";
+ case 0x000b:
+ return "TRANSPORT_USB";
+ case 0x000c:
+ return "MAX_CRYPT_KEY_LEN_56";
+ case 0x000d:
+ return "MAX_CRYPT_KEY_LEN_128";
+ case 0x000e:
+ return "TRANSPORT_USER";
+ case 0x000f:
+ return "CHIP_BC02_KATO";
+ case 0x0010:
+ return "TRANSPORT_NONE";
+ case 0x0012:
+ return "REQUIRE_8MBIT";
+ case 0x0013:
+ return "RADIOTEST";
+ case 0x0014:
+ return "RADIOTEST_LITE";
+ case 0x0015:
+ return "INSTALL_FLASH";
+ case 0x0016:
+ return "INSTALL_EEPROM";
+ case 0x0017:
+ return "INSTALL_COMBO_DOT11";
+ case 0x0018:
+ return "LOWPOWER_TX";
+ case 0x0019:
+ return "TRANSPORT_TWUTL";
+ case 0x001a:
+ return "COMPILER_GCC";
+ case 0x001b:
+ return "CHIP_BC02_CLOUSEAU";
+ case 0x001c:
+ return "CHIP_BC02_TOULOUSE";
+ case 0x001d:
+ return "CHIP_BASE_BC3";
+ case 0x001e:
+ return "CHIP_BC3_NICKNACK";
+ case 0x001f:
+ return "CHIP_BC3_KALIMBA";
+ case 0x0020:
+ return "INSTALL_HCI_MODULE";
+ case 0x0021:
+ return "INSTALL_L2CAP_MODULE";
+ case 0x0022:
+ return "INSTALL_DM_MODULE";
+ case 0x0023:
+ return "INSTALL_SDP_MODULE";
+ case 0x0024:
+ return "INSTALL_RFCOMM_MODULE";
+ case 0x0025:
+ return "INSTALL_HIDIO_MODULE";
+ case 0x0026:
+ return "INSTALL_PAN_MODULE";
+ case 0x0027:
+ return "INSTALL_IPV4_MODULE";
+ case 0x0028:
+ return "INSTALL_IPV6_MODULE";
+ case 0x0029:
+ return "INSTALL_TCP_MODULE";
+ case 0x002a:
+ return "BT_VER_1_2";
+ case 0x002b:
+ return "INSTALL_UDP_MODULE";
+ case 0x002c:
+ return "REQUIRE_0_WAIT_STATES";
+ case 0x002d:
+ return "CHIP_BC3_PADDYWACK";
+ case 0x002e:
+ return "CHIP_BC4_COYOTE";
+ case 0x002f:
+ return "CHIP_BC4_ODDJOB";
+ case 0x0030:
+ return "TRANSPORT_H4DS";
+ case 0x0031:
+ return "CHIP_BASE_BC4";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+char *csr_buildidtostr(uint16_t id)
+{
+ static char str[12];
+ int i;
+
+ for (i = 0; csr_map[i].id; i++)
+ if (csr_map[i].id == id)
+ return csr_map[i].str;
+
+ snprintf(str, 11, "Build %d", id);
+ return str;
+}
+
+char *csr_chipvertostr(uint16_t ver, uint16_t rev)
+{
+ switch (ver) {
+ case 0x00:
+ return "BlueCore01a";
+ case 0x01:
+ switch (rev) {
+ case 0x64:
+ return "BlueCore01b (ES)";
+ case 0x65:
+ default:
+ return "BlueCore01b";
+ }
+ case 0x02:
+ switch (rev) {
+ case 0x89:
+ return "BlueCore02-External (ES2)";
+ case 0x8a:
+ return "BlueCore02-External";
+ case 0x28:
+ return "BlueCore02-ROM/Audio/Flash";
+ default:
+ return "BlueCore02";
+ }
+ case 0x03:
+ switch (rev) {
+ case 0x43:
+ return "BlueCore3-MM";
+ case 0x15:
+ return "BlueCore3-ROM";
+ case 0xe2:
+ return "BlueCore3-Flash";
+ case 0x26:
+ return "BlueCore4-External";
+ case 0x30:
+ return "BlueCore4-ROM";
+ default:
+ return "BlueCore3 or BlueCore4";
+ }
+ default:
+ return "Unknown";
+ }
+}
+
+char *csr_pskeytostr(uint16_t pskey)
+{
+ switch (pskey) {
+ case CSR_PSKEY_BDADDR:
+ return "Bluetooth address";
+ case CSR_PSKEY_COUNTRYCODE:
+ return "Country code";
+ case CSR_PSKEY_CLASSOFDEVICE:
+ return "Class of device";
+ case CSR_PSKEY_DEVICE_DRIFT:
+ return "Device drift";
+ case CSR_PSKEY_DEVICE_JITTER:
+ return "Device jitter";
+ case CSR_PSKEY_MAX_ACLS:
+ return "Maximum ACL links";
+ case CSR_PSKEY_MAX_SCOS:
+ return "Maximum SCO links";
+ case CSR_PSKEY_MAX_REMOTE_MASTERS:
+ return "Maximum remote masters";
+ case CSR_PSKEY_ENABLE_MASTERY_WITH_SLAVERY:
+ return "Support master and slave roles simultaneously";
+ case CSR_PSKEY_H_HC_FC_MAX_ACL_PKT_LEN:
+ return "Maximum HCI ACL packet length";
+ case CSR_PSKEY_H_HC_FC_MAX_SCO_PKT_LEN:
+ return "Maximum HCI SCO packet length";
+ case CSR_PSKEY_H_HC_FC_MAX_ACL_PKTS:
+ return "Maximum number of HCI ACL packets";
+ case CSR_PSKEY_H_HC_FC_MAX_SCO_PKTS:
+ return "Maximum number of HCI SCO packets";
+ case CSR_PSKEY_LC_FC_BUFFER_LOW_WATER_MARK:
+ return "Flow control low water mark";
+ case CSR_PSKEY_LC_MAX_TX_POWER:
+ return "Maximum transmit power";
+ case CSR_PSKEY_TX_GAIN_RAMP:
+ return "Transmit gain ramp rate";
+ case CSR_PSKEY_LC_POWER_TABLE:
+ return "Radio power table";
+ case CSR_PSKEY_LC_PEER_POWER_PERIOD:
+ return "Peer transmit power control interval";
+ case CSR_PSKEY_LC_FC_POOLS_LOW_WATER_MARK:
+ return "Flow control pool low water mark";
+ case CSR_PSKEY_LC_DEFAULT_TX_POWER:
+ return "Default transmit power";
+ case CSR_PSKEY_LC_RSSI_GOLDEN_RANGE:
+ return "RSSI at bottom of golden receive range";
+ case CSR_PSKEY_LC_COMBO_DISABLE_PIO_MASK:
+ return "Combo: PIO lines and logic to disable transmit";
+ case CSR_PSKEY_LC_COMBO_PRIORITY_PIO_MASK:
+ return "Combo: priority activity PIO lines and logic";
+ case CSR_PSKEY_LC_COMBO_DOT11_CHANNEL_PIO_BASE:
+ return "Combo: 802.11b channel number base PIO line";
+ case CSR_PSKEY_LC_COMBO_DOT11_BLOCK_CHANNELS:
+ return "Combo: channels to block either side of 802.11b";
+ case CSR_PSKEY_LC_MAX_TX_POWER_NO_RSSI:
+ return "Maximum transmit power when peer has no RSSI";
+ case CSR_PSKEY_LC_CONNECTION_RX_WINDOW:
+ return "Receive window size during connections";
+ case CSR_PSKEY_LC_COMBO_DOT11_TX_PROTECTION_MODE:
+ return "Combo: which TX packets shall we protect";
+ case CSR_PSKEY_LC_ENHANCED_POWER_TABLE:
+ return "Radio power table";
+ case CSR_PSKEY_LC_WIDEBAND_RSSI_CONFIG:
+ return "RSSI configuration for use with wideband RSSI";
+ case CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_LEAD:
+ return "Combo: How much notice will we give the Combo Card";
+ case CSR_PSKEY_BT_CLOCK_INIT:
+ return "Initial value of Bluetooth clock";
+ case CSR_PSKEY_TX_MR_MOD_DELAY:
+ return "TX Mod delay";
+ case CSR_PSKEY_RX_MR_SYNC_TIMING:
+ return "RX MR Sync Timing";
+ case CSR_PSKEY_RX_MR_SYNC_CONFIG:
+ return "RX MR Sync Configuration";
+ case CSR_PSKEY_LC_LOST_SYNC_SLOTS:
+ return "Time in ms for lost sync in low power modes";
+ case CSR_PSKEY_RX_MR_SAMP_CONFIG:
+ return "RX MR Sync Configuration";
+ case CSR_PSKEY_AGC_HYST_LEVELS:
+ return "AGC hysteresis levels";
+ case CSR_PSKEY_RX_LEVEL_LOW_SIGNAL:
+ return "ANA_RX_LVL at low signal strengths";
+ case CSR_PSKEY_AGC_IQ_LVL_VALUES:
+ return "ANA_IQ_LVL values for AGC algorithmn";
+ case CSR_PSKEY_MR_FTRIM_OFFSET_12DB:
+ return "ANA_RX_FTRIM offset when using 12 dB IF atten ";
+ case CSR_PSKEY_MR_FTRIM_OFFSET_6DB:
+ return "ANA_RX_FTRIM offset when using 6 dB IF atten ";
+ case CSR_PSKEY_NO_CAL_ON_BOOT:
+ return "Do not calibrate radio on boot";
+ case CSR_PSKEY_RSSI_HI_TARGET:
+ return "RSSI high target";
+ case CSR_PSKEY_PREFERRED_MIN_ATTENUATION:
+ return "Preferred minimum attenuator setting";
+ case CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_OVERRIDE:
+ return "Combo: Treat all packets as high priority";
+ case CSR_PSKEY_LC_MULTISLOT_HOLDOFF:
+ return "Time till single slot packets are used for resync";
+ case CSR_PSKEY_FREE_KEY_PIGEON_HOLE:
+ return "Link key store bitfield";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR0:
+ return "Bluetooth address + link key 0";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR1:
+ return "Bluetooth address + link key 1";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR2:
+ return "Bluetooth address + link key 2";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR3:
+ return "Bluetooth address + link key 3";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR4:
+ return "Bluetooth address + link key 4";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR5:
+ return "Bluetooth address + link key 5";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR6:
+ return "Bluetooth address + link key 6";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR7:
+ return "Bluetooth address + link key 7";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR8:
+ return "Bluetooth address + link key 8";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR9:
+ return "Bluetooth address + link key 9";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR10:
+ return "Bluetooth address + link key 10";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR11:
+ return "Bluetooth address + link key 11";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR12:
+ return "Bluetooth address + link key 12";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR13:
+ return "Bluetooth address + link key 13";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR14:
+ return "Bluetooth address + link key 14";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR15:
+ return "Bluetooth address + link key 15";
+ case CSR_PSKEY_ENC_KEY_LMIN:
+ return "Minimum encryption key length";
+ case CSR_PSKEY_ENC_KEY_LMAX:
+ return "Maximum encryption key length";
+ case CSR_PSKEY_LOCAL_SUPPORTED_FEATURES:
+ return "Local supported features block";
+ case CSR_PSKEY_LM_USE_UNIT_KEY:
+ return "Allow use of unit key for authentication?";
+ case CSR_PSKEY_HCI_NOP_DISABLE:
+ return "Disable the HCI Command_Status event on boot";
+ case CSR_PSKEY_LM_MAX_EVENT_FILTERS:
+ return "Maximum number of event filters";
+ case CSR_PSKEY_LM_USE_ENC_MODE_BROADCAST:
+ return "Allow LM to use enc_mode=2";
+ case CSR_PSKEY_LM_TEST_SEND_ACCEPTED_TWICE:
+ return "LM sends two LMP_accepted messages in test mode";
+ case CSR_PSKEY_LM_MAX_PAGE_HOLD_TIME:
+ return "Maximum time we hold a device around page";
+ case CSR_PSKEY_AFH_ADAPTATION_RESPONSE_TIME:
+ return "LM period for AFH adaption";
+ case CSR_PSKEY_AFH_OPTIONS:
+ return "Options to configure AFH";
+ case CSR_PSKEY_AFH_RSSI_RUN_PERIOD:
+ return "AFH RSSI reading period";
+ case CSR_PSKEY_AFH_REENABLE_CHANNEL_TIME:
+ return "AFH good channel adding time";
+ case CSR_PSKEY_NO_DROP_ON_ACR_MS_FAIL:
+ return "Complete link if acr barge-in role switch refused";
+ case CSR_PSKEY_MAX_PRIVATE_KEYS:
+ return "Max private link keys stored";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR0:
+ return "Bluetooth address + link key 0";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR1:
+ return "Bluetooth address + link key 1";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR2:
+ return "Bluetooth address + link key 2";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR3:
+ return "Bluetooth address + link key 3";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR4:
+ return "Bluetooth address + link key 4";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR5:
+ return "Bluetooth address + link key 5";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR6:
+ return "Bluetooth address + link key 6";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR7:
+ return "Bluetooth address + link key 7";
+ case CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS:
+ return "Local supported commands";
+ case CSR_PSKEY_LM_MAX_ABSENCE_INDEX:
+ return "Maximum absence index allowed";
+ case CSR_PSKEY_DEVICE_NAME:
+ return "Local device's \"user friendly\" name";
+ case CSR_PSKEY_AFH_RSSI_THRESHOLD:
+ return "AFH RSSI threshold";
+ case CSR_PSKEY_LM_CASUAL_SCAN_INTERVAL:
+ return "Scan interval in slots for casual scanning";
+ case CSR_PSKEY_AFH_MIN_MAP_CHANGE:
+ return "The minimum amount to change an AFH map by";
+ case CSR_PSKEY_AFH_RSSI_LP_RUN_PERIOD:
+ return "AFH RSSI reading period when in low power mode";
+ case CSR_PSKEY_HCI_LMP_LOCAL_VERSION:
+ return "The HCI and LMP version reported locally";
+ case CSR_PSKEY_LMP_REMOTE_VERSION:
+ return "The LMP version reported remotely";
+ case CSR_PSKEY_HOLD_ERROR_MESSAGE_NUMBER:
+ return "Maximum number of queued HCI Hardware Error Events";
+ case CSR_PSKEY_DFU_ATTRIBUTES:
+ return "DFU attributes";
+ case CSR_PSKEY_DFU_DETACH_TO:
+ return "DFU detach timeout";
+ case CSR_PSKEY_DFU_TRANSFER_SIZE:
+ return "DFU transfer size";
+ case CSR_PSKEY_DFU_ENABLE:
+ return "DFU enable";
+ case CSR_PSKEY_DFU_LIN_REG_ENABLE:
+ return "Linear Regulator enabled at boot in DFU mode";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_MSB:
+ return "DFU encryption VM application public key MSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_LSB:
+ return "DFU encryption VM application public key LSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_M_DASH:
+ return "DFU encryption VM application M dash";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_R2N_MSB:
+ return "DFU encryption VM application public key R2N MSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_R2N_LSB:
+ return "DFU encryption VM application public key R2N LSB";
+ case CSR_PSKEY_BCSP_LM_PS_BLOCK:
+ return "BCSP link establishment block";
+ case CSR_PSKEY_HOSTIO_FC_PS_BLOCK:
+ return "HCI flow control block";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO0:
+ return "Host transport channel 0 settings (BCSP ACK)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO1:
+ return "Host transport channel 1 settings (BCSP-LE)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO2:
+ return "Host transport channel 2 settings (BCCMD)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO3:
+ return "Host transport channel 3 settings (HQ)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO4:
+ return "Host transport channel 4 settings (DM)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO5:
+ return "Host transport channel 5 settings (HCI CMD/EVT)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO6:
+ return "Host transport channel 6 settings (HCI ACL)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO7:
+ return "Host transport channel 7 settings (HCI SCO)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO8:
+ return "Host transport channel 8 settings (L2CAP)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO9:
+ return "Host transport channel 9 settings (RFCOMM)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO10:
+ return "Host transport channel 10 settings (SDP)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO11:
+ return "Host transport channel 11 settings (TEST)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO12:
+ return "Host transport channel 12 settings (DFU)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO13:
+ return "Host transport channel 13 settings (VM)";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO14:
+ return "Host transport channel 14 settings";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO15:
+ return "Host transport channel 15 settings";
+ case CSR_PSKEY_HOSTIO_UART_RESET_TIMEOUT:
+ return "UART reset counter timeout";
+ case CSR_PSKEY_HOSTIO_USE_HCI_EXTN:
+ return "Use hci_extn to route non-hci channels";
+ case CSR_PSKEY_HOSTIO_USE_HCI_EXTN_CCFC:
+ return "Use command-complete flow control for hci_extn";
+ case CSR_PSKEY_HOSTIO_HCI_EXTN_PAYLOAD_SIZE:
+ return "Maximum hci_extn payload size";
+ case CSR_PSKEY_BCSP_LM_CNF_CNT_LIMIT:
+ return "BCSP link establishment conf message count";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_PCM:
+ return "Map SCO over PCM";
+ case CSR_PSKEY_HOSTIO_AWKWARD_PCM_SYNC:
+ return "PCM interface synchronisation is difficult";
+ case CSR_PSKEY_HOSTIO_BREAK_POLL_PERIOD:
+ return "Break poll period (microseconds)";
+ case CSR_PSKEY_HOSTIO_MIN_UART_HCI_SCO_SIZE:
+ return "Minimum SCO packet size sent to host over UART HCI";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_CODEC:
+ return "Map SCO over the built-in codec";
+ case CSR_PSKEY_PCM_CVSD_TX_HI_FREQ_BOOST:
+ return "High frequency boost for PCM when transmitting CVSD";
+ case CSR_PSKEY_PCM_CVSD_RX_HI_FREQ_BOOST:
+ return "High frequency boost for PCM when receiving CVSD";
+ case CSR_PSKEY_PCM_CONFIG32:
+ return "PCM interface settings bitfields";
+ case CSR_PSKEY_USE_OLD_BCSP_LE:
+ return "Use the old version of BCSP link establishment";
+ case CSR_PSKEY_PCM_CVSD_USE_NEW_FILTER:
+ return "CVSD uses the new filter if available";
+ case CSR_PSKEY_PCM_FORMAT:
+ return "PCM data format";
+ case CSR_PSKEY_CODEC_OUT_GAIN:
+ return "Audio output gain when using built-in codec";
+ case CSR_PSKEY_CODEC_IN_GAIN:
+ return "Audio input gain when using built-in codec";
+ case CSR_PSKEY_CODEC_PIO:
+ return "PIO to enable when built-in codec is enabled";
+ case CSR_PSKEY_PCM_LOW_JITTER_CONFIG:
+ return "PCM interface settings for low jitter master mode";
+ case CSR_PSKEY_HOSTIO_SCO_PCM_THRESHOLDS:
+ return "Thresholds for SCO PCM buffers";
+ case CSR_PSKEY_HOSTIO_SCO_HCI_THRESHOLDS:
+ return "Thresholds for SCO HCI buffers";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_PCM_SLOT:
+ return "Route SCO data to specified slot in pcm frame";
+ case CSR_PSKEY_UART_BAUDRATE:
+ return "UART Baud rate";
+ case CSR_PSKEY_UART_CONFIG_BCSP:
+ return "UART configuration when using BCSP";
+ case CSR_PSKEY_UART_CONFIG_H4:
+ return "UART configuration when using H4";
+ case CSR_PSKEY_UART_CONFIG_H5:
+ return "UART configuration when using H5";
+ case CSR_PSKEY_UART_CONFIG_USR:
+ return "UART configuration when under VM control";
+ case CSR_PSKEY_UART_TX_CRCS:
+ return "Use CRCs for BCSP or H5";
+ case CSR_PSKEY_UART_ACK_TIMEOUT:
+ return "Acknowledgement timeout for BCSP and H5";
+ case CSR_PSKEY_UART_TX_MAX_ATTEMPTS:
+ return "Max times to send reliable BCSP or H5 message";
+ case CSR_PSKEY_UART_TX_WINDOW_SIZE:
+ return "Transmit window size for BCSP and H5";
+ case CSR_PSKEY_UART_HOST_WAKE:
+ return "UART host wakeup";
+ case CSR_PSKEY_HOSTIO_THROTTLE_TIMEOUT:
+ return "Host interface performance control.";
+ case CSR_PSKEY_PCM_ALWAYS_ENABLE:
+ return "PCM port is always enable when chip is running";
+ case CSR_PSKEY_UART_HOST_WAKE_SIGNAL:
+ return "Signal to use for uart host wakeup protocol";
+ case CSR_PSKEY_UART_CONFIG_H4DS:
+ return "UART configuration when using H4DS";
+ case CSR_PSKEY_H4DS_WAKE_DURATION:
+ return "How long to spend waking the host when using H4DS";
+ case CSR_PSKEY_H4DS_MAXWU:
+ return "Maximum number of H4DS Wake-Up messages to send";
+ case CSR_PSKEY_H4DS_LE_TIMER_PERIOD:
+ return "H4DS Link Establishment Tsync and Tconf period";
+ case CSR_PSKEY_H4DS_TWU_TIMER_PERIOD:
+ return "H4DS Twu timer period";
+ case CSR_PSKEY_H4DS_UART_IDLE_TIMER_PERIOD:
+ return "H4DS Tuart_idle timer period";
+ case CSR_PSKEY_ANA_FTRIM:
+ return "Crystal frequency trim";
+ case CSR_PSKEY_WD_TIMEOUT:
+ return "Watchdog timeout (microseconds)";
+ case CSR_PSKEY_WD_PERIOD:
+ return "Watchdog period (microseconds)";
+ case CSR_PSKEY_HOST_INTERFACE:
+ return "Host interface";
+ case CSR_PSKEY_HQ_HOST_TIMEOUT:
+ return "HQ host command timeout";
+ case CSR_PSKEY_HQ_ACTIVE:
+ return "Enable host query task?";
+ case CSR_PSKEY_BCCMD_SECURITY_ACTIVE:
+ return "Enable configuration security";
+ case CSR_PSKEY_ANA_FREQ:
+ return "Crystal frequency";
+ case CSR_PSKEY_PIO_PROTECT_MASK:
+ return "Access to PIO pins";
+ case CSR_PSKEY_PMALLOC_SIZES:
+ return "pmalloc sizes array";
+ case CSR_PSKEY_UART_BAUD_RATE:
+ return "UART Baud rate (pre 18)";
+ case CSR_PSKEY_UART_CONFIG:
+ return "UART configuration bitfield";
+ case CSR_PSKEY_STUB:
+ return "Stub";
+ case CSR_PSKEY_TXRX_PIO_CONTROL:
+ return "TX and RX PIO control";
+ case CSR_PSKEY_ANA_RX_LEVEL:
+ return "ANA_RX_LVL register initial value";
+ case CSR_PSKEY_ANA_RX_FTRIM:
+ return "ANA_RX_FTRIM register initial value";
+ case CSR_PSKEY_PSBC_DATA_VERSION:
+ return "Persistent store version";
+ case CSR_PSKEY_PCM0_ATTENUATION:
+ return "Volume control on PCM channel 0";
+ case CSR_PSKEY_LO_LVL_MAX:
+ return "Maximum value of LO level control register";
+ case CSR_PSKEY_LO_ADC_AMPL_MIN:
+ return "Minimum value of the LO amplitude measured on the ADC";
+ case CSR_PSKEY_LO_ADC_AMPL_MAX:
+ return "Maximum value of the LO amplitude measured on the ADC";
+ case CSR_PSKEY_IQ_TRIM_CHANNEL:
+ return "IQ calibration channel";
+ case CSR_PSKEY_IQ_TRIM_GAIN:
+ return "IQ calibration gain";
+ case CSR_PSKEY_IQ_TRIM_ENABLE:
+ return "IQ calibration enable";
+ case CSR_PSKEY_TX_OFFSET_HALF_MHZ:
+ return "Transmit offset";
+ case CSR_PSKEY_GBL_MISC_ENABLES:
+ return "Global miscellaneous hardware enables";
+ case CSR_PSKEY_UART_SLEEP_TIMEOUT:
+ return "Time in ms to deep sleep if nothing received";
+ case CSR_PSKEY_DEEP_SLEEP_STATE:
+ return "Deep sleep state usage";
+ case CSR_PSKEY_IQ_ENABLE_PHASE_TRIM:
+ return "IQ phase enable";
+ case CSR_PSKEY_HCI_HANDLE_FREEZE_PERIOD:
+ return "Time for which HCI handle is frozen after link removal";
+ case CSR_PSKEY_MAX_FROZEN_HCI_HANDLES:
+ return "Maximum number of frozen HCI handles";
+ case CSR_PSKEY_PAGETABLE_DESTRUCTION_DELAY:
+ return "Delay from freezing buf handle to deleting page table";
+ case CSR_PSKEY_IQ_TRIM_PIO_SETTINGS:
+ return "IQ PIO settings";
+ case CSR_PSKEY_USE_EXTERNAL_CLOCK:
+ return "Device uses an external clock";
+ case CSR_PSKEY_DEEP_SLEEP_WAKE_CTS:
+ return "Exit deep sleep on CTS line activity";
+ case CSR_PSKEY_FC_HC2H_FLUSH_DELAY:
+ return "Delay from disconnect to flushing HC->H FC tokens";
+ case CSR_PSKEY_RX_HIGHSIDE:
+ return "Disable the HIGHSIDE bit in ANA_CONFIG";
+ case CSR_PSKEY_TX_PRE_LVL:
+ return "TX pre-amplifier level";
+ case CSR_PSKEY_RX_SINGLE_ENDED:
+ return "RX single ended";
+ case CSR_PSKEY_TX_FILTER_CONFIG:
+ return "TX filter configuration";
+ case CSR_PSKEY_CLOCK_REQUEST_ENABLE:
+ return "External clock request enable";
+ case CSR_PSKEY_RX_MIN_ATTEN:
+ return "Minimum attenuation allowed for receiver";
+ case CSR_PSKEY_XTAL_TARGET_AMPLITUDE:
+ return "Crystal target amplitude";
+ case CSR_PSKEY_PCM_MIN_CPU_CLOCK:
+ return "Minimum CPU clock speed with PCM port running";
+ case CSR_PSKEY_HOST_INTERFACE_PIO_USB:
+ return "USB host interface selection PIO line";
+ case CSR_PSKEY_CPU_IDLE_MODE:
+ return "CPU idle mode when radio is active";
+ case CSR_PSKEY_DEEP_SLEEP_CLEAR_RTS:
+ return "Deep sleep clears the UART RTS line";
+ case CSR_PSKEY_RF_RESONANCE_TRIM:
+ return "Frequency trim for IQ and LNA resonant circuits";
+ case CSR_PSKEY_DEEP_SLEEP_PIO_WAKE:
+ return "PIO line to wake the chip from deep sleep";
+ case CSR_PSKEY_DRAIN_BORE_TIMERS:
+ return "Energy consumption measurement settings";
+ case CSR_PSKEY_DRAIN_TX_POWER_BASE:
+ return "Energy consumption measurement settings";
+ case CSR_PSKEY_MODULE_ID:
+ return "Module serial number";
+ case CSR_PSKEY_MODULE_DESIGN:
+ return "Module design ID";
+ case CSR_PSKEY_MODULE_SECURITY_CODE:
+ return "Module security code";
+ case CSR_PSKEY_VM_DISABLE:
+ return "VM disable";
+ case CSR_PSKEY_MOD_MANUF0:
+ return "Module manufactuer data 0";
+ case CSR_PSKEY_MOD_MANUF1:
+ return "Module manufactuer data 1";
+ case CSR_PSKEY_MOD_MANUF2:
+ return "Module manufactuer data 2";
+ case CSR_PSKEY_MOD_MANUF3:
+ return "Module manufactuer data 3";
+ case CSR_PSKEY_MOD_MANUF4:
+ return "Module manufactuer data 4";
+ case CSR_PSKEY_MOD_MANUF5:
+ return "Module manufactuer data 5";
+ case CSR_PSKEY_MOD_MANUF6:
+ return "Module manufactuer data 6";
+ case CSR_PSKEY_MOD_MANUF7:
+ return "Module manufactuer data 7";
+ case CSR_PSKEY_MOD_MANUF8:
+ return "Module manufactuer data 8";
+ case CSR_PSKEY_MOD_MANUF9:
+ return "Module manufactuer data 9";
+ case CSR_PSKEY_DUT_VM_DISABLE:
+ return "VM disable when entering radiotest modes";
+ case CSR_PSKEY_USR0:
+ return "User configuration data 0";
+ case CSR_PSKEY_USR1:
+ return "User configuration data 1";
+ case CSR_PSKEY_USR2:
+ return "User configuration data 2";
+ case CSR_PSKEY_USR3:
+ return "User configuration data 3";
+ case CSR_PSKEY_USR4:
+ return "User configuration data 4";
+ case CSR_PSKEY_USR5:
+ return "User configuration data 5";
+ case CSR_PSKEY_USR6:
+ return "User configuration data 6";
+ case CSR_PSKEY_USR7:
+ return "User configuration data 7";
+ case CSR_PSKEY_USR8:
+ return "User configuration data 8";
+ case CSR_PSKEY_USR9:
+ return "User configuration data 9";
+ case CSR_PSKEY_USR10:
+ return "User configuration data 10";
+ case CSR_PSKEY_USR11:
+ return "User configuration data 11";
+ case CSR_PSKEY_USR12:
+ return "User configuration data 12";
+ case CSR_PSKEY_USR13:
+ return "User configuration data 13";
+ case CSR_PSKEY_USR14:
+ return "User configuration data 14";
+ case CSR_PSKEY_USR15:
+ return "User configuration data 15";
+ case CSR_PSKEY_USR16:
+ return "User configuration data 16";
+ case CSR_PSKEY_USR17:
+ return "User configuration data 17";
+ case CSR_PSKEY_USR18:
+ return "User configuration data 18";
+ case CSR_PSKEY_USR19:
+ return "User configuration data 19";
+ case CSR_PSKEY_USR20:
+ return "User configuration data 20";
+ case CSR_PSKEY_USR21:
+ return "User configuration data 21";
+ case CSR_PSKEY_USR22:
+ return "User configuration data 22";
+ case CSR_PSKEY_USR23:
+ return "User configuration data 23";
+ case CSR_PSKEY_USR24:
+ return "User configuration data 24";
+ case CSR_PSKEY_USR25:
+ return "User configuration data 25";
+ case CSR_PSKEY_USR26:
+ return "User configuration data 26";
+ case CSR_PSKEY_USR27:
+ return "User configuration data 27";
+ case CSR_PSKEY_USR28:
+ return "User configuration data 28";
+ case CSR_PSKEY_USR29:
+ return "User configuration data 29";
+ case CSR_PSKEY_USR30:
+ return "User configuration data 30";
+ case CSR_PSKEY_USR31:
+ return "User configuration data 31";
+ case CSR_PSKEY_USR32:
+ return "User configuration data 32";
+ case CSR_PSKEY_USR33:
+ return "User configuration data 33";
+ case CSR_PSKEY_USR34:
+ return "User configuration data 34";
+ case CSR_PSKEY_USR35:
+ return "User configuration data 35";
+ case CSR_PSKEY_USR36:
+ return "User configuration data 36";
+ case CSR_PSKEY_USR37:
+ return "User configuration data 37";
+ case CSR_PSKEY_USR38:
+ return "User configuration data 38";
+ case CSR_PSKEY_USR39:
+ return "User configuration data 39";
+ case CSR_PSKEY_USR40:
+ return "User configuration data 40";
+ case CSR_PSKEY_USR41:
+ return "User configuration data 41";
+ case CSR_PSKEY_USR42:
+ return "User configuration data 42";
+ case CSR_PSKEY_USR43:
+ return "User configuration data 43";
+ case CSR_PSKEY_USR44:
+ return "User configuration data 44";
+ case CSR_PSKEY_USR45:
+ return "User configuration data 45";
+ case CSR_PSKEY_USR46:
+ return "User configuration data 46";
+ case CSR_PSKEY_USR47:
+ return "User configuration data 47";
+ case CSR_PSKEY_USR48:
+ return "User configuration data 48";
+ case CSR_PSKEY_USR49:
+ return "User configuration data 49";
+ case CSR_PSKEY_USB_VERSION:
+ return "USB specification version number";
+ case CSR_PSKEY_USB_DEVICE_CLASS_CODES:
+ return "USB device class codes";
+ case CSR_PSKEY_USB_VENDOR_ID:
+ return "USB vendor identifier";
+ case CSR_PSKEY_USB_PRODUCT_ID:
+ return "USB product identifier";
+ case CSR_PSKEY_USB_MANUF_STRING:
+ return "USB manufacturer string";
+ case CSR_PSKEY_USB_PRODUCT_STRING:
+ return "USB product string";
+ case CSR_PSKEY_USB_SERIAL_NUMBER_STRING:
+ return "USB serial number string";
+ case CSR_PSKEY_USB_CONFIG_STRING:
+ return "USB configuration string";
+ case CSR_PSKEY_USB_ATTRIBUTES:
+ return "USB attributes bitmap";
+ case CSR_PSKEY_USB_MAX_POWER:
+ return "USB device maximum power consumption";
+ case CSR_PSKEY_USB_BT_IF_CLASS_CODES:
+ return "USB Bluetooth interface class codes";
+ case CSR_PSKEY_USB_LANGID:
+ return "USB language strings supported";
+ case CSR_PSKEY_USB_DFU_CLASS_CODES:
+ return "USB DFU class codes block";
+ case CSR_PSKEY_USB_DFU_PRODUCT_ID:
+ return "USB DFU product ID";
+ case CSR_PSKEY_USB_PIO_DETACH:
+ return "USB detach/attach PIO line";
+ case CSR_PSKEY_USB_PIO_WAKEUP:
+ return "USB wakeup PIO line";
+ case CSR_PSKEY_USB_PIO_PULLUP:
+ return "USB D+ pullup PIO line";
+ case CSR_PSKEY_USB_PIO_VBUS:
+ return "USB VBus detection PIO Line";
+ case CSR_PSKEY_USB_PIO_WAKE_TIMEOUT:
+ return "Timeout for assertion of USB PIO wake signal";
+ case CSR_PSKEY_USB_PIO_RESUME:
+ return "PIO signal used in place of bus resume";
+ case CSR_PSKEY_USB_BT_SCO_IF_CLASS_CODES:
+ return "USB Bluetooth SCO interface class codes";
+ case CSR_PSKEY_USB_SUSPEND_PIO_LEVEL:
+ return "USB PIO levels to set when suspended";
+ case CSR_PSKEY_USB_SUSPEND_PIO_DIR:
+ return "USB PIO I/O directions to set when suspended";
+ case CSR_PSKEY_USB_SUSPEND_PIO_MASK:
+ return "USB PIO lines to be set forcibly in suspend";
+ case CSR_PSKEY_USB_ENDPOINT_0_MAX_PACKET_SIZE:
+ return "The maxmimum packet size for USB endpoint 0";
+ case CSR_PSKEY_USB_CONFIG:
+ return "USB config params for new chips (>bc2)";
+ case CSR_PSKEY_RADIOTEST_ATTEN_INIT:
+ return "Radio test initial attenuator";
+ case CSR_PSKEY_RADIOTEST_FIRST_TRIM_TIME:
+ return "IQ first calibration period in test";
+ case CSR_PSKEY_RADIOTEST_SUBSEQUENT_TRIM_TIME:
+ return "IQ subsequent calibration period in test";
+ case CSR_PSKEY_RADIOTEST_LO_LVL_TRIM_ENABLE:
+ return "LO_LVL calibration enable";
+ case CSR_PSKEY_RADIOTEST_DISABLE_MODULATION:
+ return "Disable modulation during radiotest transmissions";
+ case CSR_PSKEY_RFCOMM_FCON_THRESHOLD:
+ return "RFCOMM aggregate flow control on threshold";
+ case CSR_PSKEY_RFCOMM_FCOFF_THRESHOLD:
+ return "RFCOMM aggregate flow control off threshold";
+ case CSR_PSKEY_IPV6_STATIC_ADDR:
+ return "Static IPv6 address";
+ case CSR_PSKEY_IPV4_STATIC_ADDR:
+ return "Static IPv4 address";
+ case CSR_PSKEY_IPV6_STATIC_PREFIX_LEN:
+ return "Static IPv6 prefix length";
+ case CSR_PSKEY_IPV6_STATIC_ROUTER_ADDR:
+ return "Static IPv6 router address";
+ case CSR_PSKEY_IPV4_STATIC_SUBNET_MASK:
+ return "Static IPv4 subnet mask";
+ case CSR_PSKEY_IPV4_STATIC_ROUTER_ADDR:
+ return "Static IPv4 router address";
+ case CSR_PSKEY_MDNS_NAME:
+ return "Multicast DNS name";
+ case CSR_PSKEY_FIXED_PIN:
+ return "Fixed PIN";
+ case CSR_PSKEY_MDNS_PORT:
+ return "Multicast DNS port";
+ case CSR_PSKEY_MDNS_TTL:
+ return "Multicast DNS TTL";
+ case CSR_PSKEY_MDNS_IPV4_ADDR:
+ return "Multicast DNS IPv4 address";
+ case CSR_PSKEY_ARP_CACHE_TIMEOUT:
+ return "ARP cache timeout";
+ case CSR_PSKEY_HFP_POWER_TABLE:
+ return "HFP power table";
+ case CSR_PSKEY_DRAIN_BORE_TIMER_COUNTERS:
+ return "Energy consumption estimation timer counters";
+ case CSR_PSKEY_DRAIN_BORE_COUNTERS:
+ return "Energy consumption estimation counters";
+ case CSR_PSKEY_LOOP_FILTER_TRIM:
+ return "Trim value to optimise loop filter";
+ case CSR_PSKEY_DRAIN_BORE_CURRENT_PEAK:
+ return "Energy consumption estimation current peak";
+ case CSR_PSKEY_VM_E2_CACHE_LIMIT:
+ return "Maximum RAM for caching EEPROM VM application";
+ case CSR_PSKEY_FORCE_16MHZ_REF_PIO:
+ return "PIO line to force 16 MHz reference to be assumed";
+ case CSR_PSKEY_CDMA_LO_REF_LIMITS:
+ return "Local oscillator frequency reference limits for CDMA";
+ case CSR_PSKEY_CDMA_LO_ERROR_LIMITS:
+ return "Local oscillator frequency error limits for CDMA";
+ case CSR_PSKEY_CLOCK_STARTUP_DELAY:
+ return "Clock startup delay in milliseconds";
+ case CSR_PSKEY_DEEP_SLEEP_CORRECTION_FACTOR:
+ return "Deep sleep clock correction factor";
+ case CSR_PSKEY_TEMPERATURE_CALIBRATION:
+ return "Temperature in deg C for a given internal setting";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA:
+ return "Temperature for given internal PA adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL:
+ return "Temperature for a given TX_PRE_LVL adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB:
+ return "Temperature for a given TX_BB adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_ANA_FTRIM:
+ return "Temperature for given crystal trim adjustment";
+ case CSR_PSKEY_TEST_DELTA_OFFSET:
+ return "Frequency offset applied to synthesiser in test mode";
+ case CSR_PSKEY_RX_DYNAMIC_LVL_OFFSET:
+ return "Receiver dynamic level offset depending on channel";
+ case CSR_PSKEY_TEST_FORCE_OFFSET:
+ return "Force use of exact value in PSKEY_TEST_DELTA_OFFSET";
+ case CSR_PSKEY_RF_TRAP_BAD_DIVISION_RATIOS:
+ return "Trap bad division ratios in radio frequency tables";
+ case CSR_PSKEY_RADIOTEST_CDMA_LO_REF_LIMITS:
+ return "LO frequency reference limits for CDMA in radiotest";
+ case CSR_PSKEY_INITIAL_BOOTMODE:
+ return "Initial device bootmode";
+ case CSR_PSKEY_ONCHIP_HCI_CLIENT:
+ return "HCI traffic routed internally";
+ case CSR_PSKEY_RX_ATTEN_BACKOFF:
+ return "Receiver attenuation back-off";
+ case CSR_PSKEY_RX_ATTEN_UPDATE_RATE:
+ return "Receiver attenuation update rate";
+ case CSR_PSKEY_SYNTH_TXRX_THRESHOLDS:
+ return "Local oscillator tuning voltage limits for tx and rx";
+ case CSR_PSKEY_MIN_WAIT_STATES:
+ return "Flash wait state indicator";
+ case CSR_PSKEY_RSSI_CORRECTION:
+ return "RSSI correction factor.";
+ case CSR_PSKEY_SCHED_THROTTLE_TIMEOUT:
+ return "Scheduler performance control.";
+ case CSR_PSKEY_DEEP_SLEEP_USE_EXTERNAL_CLOCK:
+ return "Deep sleep uses external 32 kHz clock source";
+ case CSR_PSKEY_TRIM_RADIO_FILTERS:
+ return "Trim rx and tx radio filters if true.";
+ case CSR_PSKEY_TRANSMIT_OFFSET:
+ return "Transmit offset in units of 62.5 kHz";
+ case CSR_PSKEY_USB_VM_CONTROL:
+ return "VM application will supply USB descriptors";
+ case CSR_PSKEY_MR_ANA_RX_FTRIM:
+ return "Medium rate value for the ANA_RX_FTRIM register";
+ case CSR_PSKEY_I2C_CONFIG:
+ return "I2C configuration";
+ case CSR_PSKEY_IQ_LVL_RX:
+ return "IQ demand level for reception";
+ case CSR_PSKEY_MR_TX_FILTER_CONFIG:
+ return "TX filter configuration used for enhanced data rate";
+ case CSR_PSKEY_MR_TX_CONFIG2:
+ return "TX filter configuration used for enhanced data rate";
+ case CSR_PSKEY_USB_DONT_RESET_BOOTMODE_ON_HOST_RESET:
+ return "Don't reset bootmode if USB host resets";
+ case CSR_PSKEY_LC_USE_THROTTLING:
+ return "Adjust packet selection on packet error rate";
+ case CSR_PSKEY_CHARGER_TRIM:
+ return "Trim value for the current charger";
+ case CSR_PSKEY_CLOCK_REQUEST_FEATURES:
+ return "Clock request is tristated if enabled";
+ case CSR_PSKEY_TRANSMIT_OFFSET_CLASS1:
+ return "Transmit offset / 62.5 kHz for class 1 radios";
+ case CSR_PSKEY_TX_AVOID_PA_CLASS1_PIO:
+ return "PIO line asserted in class1 operation to avoid PA";
+ case CSR_PSKEY_MR_PIO_CONFIG:
+ return "PIO line asserted in class1 operation to avoid PA";
+ case CSR_PSKEY_UART_CONFIG2:
+ return "The UART Sampling point";
+ case CSR_PSKEY_CLASS1_IQ_LVL:
+ return "IQ demand level for class 1 power level";
+ case CSR_PSKEY_CLASS1_TX_CONFIG2:
+ return "TX filter configuration used for class 1 tx power";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA_CLASS1:
+ return "Temperature for given internal PA adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_EXTERNAL_PA_CLASS1:
+ return "Temperature for given internal PA adjustment";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL_MR:
+ return "Temperature adjustment for TX_PRE_LVL in EDR";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_HEADER:
+ return "Temperature for a given TX_BB in EDR header";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_PAYLOAD:
+ return "Temperature for a given TX_BB in EDR payload";
+ case CSR_PSKEY_RX_MR_EQ_TAPS:
+ return "Adjust receiver configuration for EDR";
+ case CSR_PSKEY_TX_PRE_LVL_CLASS1:
+ return "TX pre-amplifier level in class 1 operation";
+ case CSR_PSKEY_ANALOGUE_ATTENUATOR:
+ return "TX analogue attenuator setting";
+ case CSR_PSKEY_MR_RX_FILTER_TRIM:
+ return "Trim for receiver used in EDR.";
+ case CSR_PSKEY_MR_RX_FILTER_RESPONSE:
+ return "Filter response for receiver used in EDR.";
+ case CSR_PSKEY_PIO_WAKEUP_STATE:
+ return "PIO deep sleep wake up state ";
+ case CSR_PSKEY_MR_TX_IF_ATTEN_OFF_TEMP:
+ return "TX IF atten off temperature when using EDR.";
+ case CSR_PSKEY_LO_DIV_LATCH_BYPASS:
+ return "Bypass latch for LO dividers";
+ case CSR_PSKEY_LO_VCO_STANDBY:
+ return "Use standby mode for the LO VCO";
+ case CSR_PSKEY_SLOW_CLOCK_FILTER_SHIFT:
+ return "Slow clock sampling filter constant";
+ case CSR_PSKEY_SLOW_CLOCK_FILTER_DIVIDER:
+ return "Slow clock filter fractional threshold";
+ case CSR_PSKEY_USB_ATTRIBUTES_POWER:
+ return "USB self powered";
+ case CSR_PSKEY_USB_ATTRIBUTES_WAKEUP:
+ return "USB responds to wake-up";
+ case CSR_PSKEY_DFU_ATTRIBUTES_MANIFESTATION_TOLERANT:
+ return "DFU manifestation tolerant";
+ case CSR_PSKEY_DFU_ATTRIBUTES_CAN_UPLOAD:
+ return "DFU can upload";
+ case CSR_PSKEY_DFU_ATTRIBUTES_CAN_DOWNLOAD:
+ return "DFU can download";
+ case CSR_PSKEY_UART_CONFIG_STOP_BITS:
+ return "UART: stop bits";
+ case CSR_PSKEY_UART_CONFIG_PARITY_BIT:
+ return "UART: parity bit";
+ case CSR_PSKEY_UART_CONFIG_FLOW_CTRL_EN:
+ return "UART: hardware flow control";
+ case CSR_PSKEY_UART_CONFIG_RTS_AUTO_EN:
+ return "UART: RTS auto-enabled";
+ case CSR_PSKEY_UART_CONFIG_RTS:
+ return "UART: RTS asserted";
+ case CSR_PSKEY_UART_CONFIG_TX_ZERO_EN:
+ return "UART: TX zero enable";
+ case CSR_PSKEY_UART_CONFIG_NON_BCSP_EN:
+ return "UART: enable BCSP-specific hardware";
+ case CSR_PSKEY_UART_CONFIG_RX_RATE_DELAY:
+ return "UART: RX rate delay";
+ case CSR_PSKEY_UART_SEQ_TIMEOUT:
+ return "UART: BCSP ack timeout";
+ case CSR_PSKEY_UART_SEQ_RETRIES:
+ return "UART: retry limit in sequencing layer";
+ case CSR_PSKEY_UART_SEQ_WINSIZE:
+ return "UART: BCSP transmit window size";
+ case CSR_PSKEY_UART_USE_CRC_ON_TX:
+ return "UART: use BCSP CRCs";
+ case CSR_PSKEY_UART_HOST_INITIAL_STATE:
+ return "UART: initial host state";
+ case CSR_PSKEY_UART_HOST_ATTENTION_SPAN:
+ return "UART: host attention span";
+ case CSR_PSKEY_UART_HOST_WAKEUP_TIME:
+ return "UART: host wakeup time";
+ case CSR_PSKEY_UART_HOST_WAKEUP_WAIT:
+ return "UART: host wakeup wait";
+ case CSR_PSKEY_BCSP_LM_MODE:
+ return "BCSP link establishment mode";
+ case CSR_PSKEY_BCSP_LM_SYNC_RETRIES:
+ return "BCSP link establishment sync retries";
+ case CSR_PSKEY_BCSP_LM_TSHY:
+ return "BCSP link establishment Tshy";
+ case CSR_PSKEY_UART_DFU_CONFIG_STOP_BITS:
+ return "DFU mode UART: stop bits";
+ case CSR_PSKEY_UART_DFU_CONFIG_PARITY_BIT:
+ return "DFU mode UART: parity bit";
+ case CSR_PSKEY_UART_DFU_CONFIG_FLOW_CTRL_EN:
+ return "DFU mode UART: hardware flow control";
+ case CSR_PSKEY_UART_DFU_CONFIG_RTS_AUTO_EN:
+ return "DFU mode UART: RTS auto-enabled";
+ case CSR_PSKEY_UART_DFU_CONFIG_RTS:
+ return "DFU mode UART: RTS asserted";
+ case CSR_PSKEY_UART_DFU_CONFIG_TX_ZERO_EN:
+ return "DFU mode UART: TX zero enable";
+ case CSR_PSKEY_UART_DFU_CONFIG_NON_BCSP_EN:
+ return "DFU mode UART: enable BCSP-specific hardware";
+ case CSR_PSKEY_UART_DFU_CONFIG_RX_RATE_DELAY:
+ return "DFU mode UART: RX rate delay";
+ case CSR_PSKEY_AMUX_AIO0:
+ return "Multiplexer for AIO 0";
+ case CSR_PSKEY_AMUX_AIO1:
+ return "Multiplexer for AIO 1";
+ case CSR_PSKEY_AMUX_AIO2:
+ return "Multiplexer for AIO 2";
+ case CSR_PSKEY_AMUX_AIO3:
+ return "Multiplexer for AIO 3";
+ case CSR_PSKEY_LOCAL_NAME_SIMPLIFIED:
+ return "Local Name (simplified)";
+ case CSR_PSKEY_EXTENDED_STUB:
+ return "Extended stub";
+ default:
+ return "Unknown";
+ }
+}
+
+char *csr_pskeytoval(uint16_t pskey)
+{
+ switch (pskey) {
+ case CSR_PSKEY_BDADDR:
+ return "BDADDR";
+ case CSR_PSKEY_COUNTRYCODE:
+ return "COUNTRYCODE";
+ case CSR_PSKEY_CLASSOFDEVICE:
+ return "CLASSOFDEVICE";
+ case CSR_PSKEY_DEVICE_DRIFT:
+ return "DEVICE_DRIFT";
+ case CSR_PSKEY_DEVICE_JITTER:
+ return "DEVICE_JITTER";
+ case CSR_PSKEY_MAX_ACLS:
+ return "MAX_ACLS";
+ case CSR_PSKEY_MAX_SCOS:
+ return "MAX_SCOS";
+ case CSR_PSKEY_MAX_REMOTE_MASTERS:
+ return "MAX_REMOTE_MASTERS";
+ case CSR_PSKEY_ENABLE_MASTERY_WITH_SLAVERY:
+ return "ENABLE_MASTERY_WITH_SLAVERY";
+ case CSR_PSKEY_H_HC_FC_MAX_ACL_PKT_LEN:
+ return "H_HC_FC_MAX_ACL_PKT_LEN";
+ case CSR_PSKEY_H_HC_FC_MAX_SCO_PKT_LEN:
+ return "H_HC_FC_MAX_SCO_PKT_LEN";
+ case CSR_PSKEY_H_HC_FC_MAX_ACL_PKTS:
+ return "H_HC_FC_MAX_ACL_PKTS";
+ case CSR_PSKEY_H_HC_FC_MAX_SCO_PKTS:
+ return "H_HC_FC_MAX_SCO_PKTS";
+ case CSR_PSKEY_LC_FC_BUFFER_LOW_WATER_MARK:
+ return "LC_FC_BUFFER_LOW_WATER_MARK";
+ case CSR_PSKEY_LC_MAX_TX_POWER:
+ return "LC_MAX_TX_POWER";
+ case CSR_PSKEY_TX_GAIN_RAMP:
+ return "TX_GAIN_RAMP";
+ case CSR_PSKEY_LC_POWER_TABLE:
+ return "LC_POWER_TABLE";
+ case CSR_PSKEY_LC_PEER_POWER_PERIOD:
+ return "LC_PEER_POWER_PERIOD";
+ case CSR_PSKEY_LC_FC_POOLS_LOW_WATER_MARK:
+ return "LC_FC_POOLS_LOW_WATER_MARK";
+ case CSR_PSKEY_LC_DEFAULT_TX_POWER:
+ return "LC_DEFAULT_TX_POWER";
+ case CSR_PSKEY_LC_RSSI_GOLDEN_RANGE:
+ return "LC_RSSI_GOLDEN_RANGE";
+ case CSR_PSKEY_LC_COMBO_DISABLE_PIO_MASK:
+ return "LC_COMBO_DISABLE_PIO_MASK";
+ case CSR_PSKEY_LC_COMBO_PRIORITY_PIO_MASK:
+ return "LC_COMBO_PRIORITY_PIO_MASK";
+ case CSR_PSKEY_LC_COMBO_DOT11_CHANNEL_PIO_BASE:
+ return "LC_COMBO_DOT11_CHANNEL_PIO_BASE";
+ case CSR_PSKEY_LC_COMBO_DOT11_BLOCK_CHANNELS:
+ return "LC_COMBO_DOT11_BLOCK_CHANNELS";
+ case CSR_PSKEY_LC_MAX_TX_POWER_NO_RSSI:
+ return "LC_MAX_TX_POWER_NO_RSSI";
+ case CSR_PSKEY_LC_CONNECTION_RX_WINDOW:
+ return "LC_CONNECTION_RX_WINDOW";
+ case CSR_PSKEY_LC_COMBO_DOT11_TX_PROTECTION_MODE:
+ return "LC_COMBO_DOT11_TX_PROTECTION_MODE";
+ case CSR_PSKEY_LC_ENHANCED_POWER_TABLE:
+ return "LC_ENHANCED_POWER_TABLE";
+ case CSR_PSKEY_LC_WIDEBAND_RSSI_CONFIG:
+ return "LC_WIDEBAND_RSSI_CONFIG";
+ case CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_LEAD:
+ return "LC_COMBO_DOT11_PRIORITY_LEAD";
+ case CSR_PSKEY_BT_CLOCK_INIT:
+ return "BT_CLOCK_INIT";
+ case CSR_PSKEY_TX_MR_MOD_DELAY:
+ return "TX_MR_MOD_DELAY";
+ case CSR_PSKEY_RX_MR_SYNC_TIMING:
+ return "RX_MR_SYNC_TIMING";
+ case CSR_PSKEY_RX_MR_SYNC_CONFIG:
+ return "RX_MR_SYNC_CONFIG";
+ case CSR_PSKEY_LC_LOST_SYNC_SLOTS:
+ return "LC_LOST_SYNC_SLOTS";
+ case CSR_PSKEY_RX_MR_SAMP_CONFIG:
+ return "RX_MR_SAMP_CONFIG";
+ case CSR_PSKEY_AGC_HYST_LEVELS:
+ return "AGC_HYST_LEVELS";
+ case CSR_PSKEY_RX_LEVEL_LOW_SIGNAL:
+ return "RX_LEVEL_LOW_SIGNAL";
+ case CSR_PSKEY_AGC_IQ_LVL_VALUES:
+ return "AGC_IQ_LVL_VALUES";
+ case CSR_PSKEY_MR_FTRIM_OFFSET_12DB:
+ return "MR_FTRIM_OFFSET_12DB";
+ case CSR_PSKEY_MR_FTRIM_OFFSET_6DB:
+ return "MR_FTRIM_OFFSET_6DB";
+ case CSR_PSKEY_NO_CAL_ON_BOOT:
+ return "NO_CAL_ON_BOOT";
+ case CSR_PSKEY_RSSI_HI_TARGET:
+ return "RSSI_HI_TARGET";
+ case CSR_PSKEY_PREFERRED_MIN_ATTENUATION:
+ return "PREFERRED_MIN_ATTENUATION";
+ case CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_OVERRIDE:
+ return "LC_COMBO_DOT11_PRIORITY_OVERRIDE";
+ case CSR_PSKEY_LC_MULTISLOT_HOLDOFF:
+ return "LC_MULTISLOT_HOLDOFF";
+ case CSR_PSKEY_FREE_KEY_PIGEON_HOLE:
+ return "FREE_KEY_PIGEON_HOLE";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR0:
+ return "LINK_KEY_BD_ADDR0";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR1:
+ return "LINK_KEY_BD_ADDR1";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR2:
+ return "LINK_KEY_BD_ADDR2";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR3:
+ return "LINK_KEY_BD_ADDR3";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR4:
+ return "LINK_KEY_BD_ADDR4";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR5:
+ return "LINK_KEY_BD_ADDR5";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR6:
+ return "LINK_KEY_BD_ADDR6";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR7:
+ return "LINK_KEY_BD_ADDR7";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR8:
+ return "LINK_KEY_BD_ADDR8";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR9:
+ return "LINK_KEY_BD_ADDR9";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR10:
+ return "LINK_KEY_BD_ADDR10";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR11:
+ return "LINK_KEY_BD_ADDR11";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR12:
+ return "LINK_KEY_BD_ADDR12";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR13:
+ return "LINK_KEY_BD_ADDR13";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR14:
+ return "LINK_KEY_BD_ADDR14";
+ case CSR_PSKEY_LINK_KEY_BD_ADDR15:
+ return "LINK_KEY_BD_ADDR15";
+ case CSR_PSKEY_ENC_KEY_LMIN:
+ return "ENC_KEY_LMIN";
+ case CSR_PSKEY_ENC_KEY_LMAX:
+ return "ENC_KEY_LMAX";
+ case CSR_PSKEY_LOCAL_SUPPORTED_FEATURES:
+ return "LOCAL_SUPPORTED_FEATURES";
+ case CSR_PSKEY_LM_USE_UNIT_KEY:
+ return "LM_USE_UNIT_KEY";
+ case CSR_PSKEY_HCI_NOP_DISABLE:
+ return "HCI_NOP_DISABLE";
+ case CSR_PSKEY_LM_MAX_EVENT_FILTERS:
+ return "LM_MAX_EVENT_FILTERS";
+ case CSR_PSKEY_LM_USE_ENC_MODE_BROADCAST:
+ return "LM_USE_ENC_MODE_BROADCAST";
+ case CSR_PSKEY_LM_TEST_SEND_ACCEPTED_TWICE:
+ return "LM_TEST_SEND_ACCEPTED_TWICE";
+ case CSR_PSKEY_LM_MAX_PAGE_HOLD_TIME:
+ return "LM_MAX_PAGE_HOLD_TIME";
+ case CSR_PSKEY_AFH_ADAPTATION_RESPONSE_TIME:
+ return "AFH_ADAPTATION_RESPONSE_TIME";
+ case CSR_PSKEY_AFH_OPTIONS:
+ return "AFH_OPTIONS";
+ case CSR_PSKEY_AFH_RSSI_RUN_PERIOD:
+ return "AFH_RSSI_RUN_PERIOD";
+ case CSR_PSKEY_AFH_REENABLE_CHANNEL_TIME:
+ return "AFH_REENABLE_CHANNEL_TIME";
+ case CSR_PSKEY_NO_DROP_ON_ACR_MS_FAIL:
+ return "NO_DROP_ON_ACR_MS_FAIL";
+ case CSR_PSKEY_MAX_PRIVATE_KEYS:
+ return "MAX_PRIVATE_KEYS";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR0:
+ return "PRIVATE_LINK_KEY_BD_ADDR0";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR1:
+ return "PRIVATE_LINK_KEY_BD_ADDR1";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR2:
+ return "PRIVATE_LINK_KEY_BD_ADDR2";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR3:
+ return "PRIVATE_LINK_KEY_BD_ADDR3";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR4:
+ return "PRIVATE_LINK_KEY_BD_ADDR4";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR5:
+ return "PRIVATE_LINK_KEY_BD_ADDR5";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR6:
+ return "PRIVATE_LINK_KEY_BD_ADDR6";
+ case CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR7:
+ return "PRIVATE_LINK_KEY_BD_ADDR7";
+ case CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS:
+ return "LOCAL_SUPPORTED_COMMANDS";
+ case CSR_PSKEY_LM_MAX_ABSENCE_INDEX:
+ return "LM_MAX_ABSENCE_INDEX";
+ case CSR_PSKEY_DEVICE_NAME:
+ return "DEVICE_NAME";
+ case CSR_PSKEY_AFH_RSSI_THRESHOLD:
+ return "AFH_RSSI_THRESHOLD";
+ case CSR_PSKEY_LM_CASUAL_SCAN_INTERVAL:
+ return "LM_CASUAL_SCAN_INTERVAL";
+ case CSR_PSKEY_AFH_MIN_MAP_CHANGE:
+ return "AFH_MIN_MAP_CHANGE";
+ case CSR_PSKEY_AFH_RSSI_LP_RUN_PERIOD:
+ return "AFH_RSSI_LP_RUN_PERIOD";
+ case CSR_PSKEY_HCI_LMP_LOCAL_VERSION:
+ return "HCI_LMP_LOCAL_VERSION";
+ case CSR_PSKEY_LMP_REMOTE_VERSION:
+ return "LMP_REMOTE_VERSION";
+ case CSR_PSKEY_HOLD_ERROR_MESSAGE_NUMBER:
+ return "HOLD_ERROR_MESSAGE_NUMBER";
+ case CSR_PSKEY_DFU_ATTRIBUTES:
+ return "DFU_ATTRIBUTES";
+ case CSR_PSKEY_DFU_DETACH_TO:
+ return "DFU_DETACH_TO";
+ case CSR_PSKEY_DFU_TRANSFER_SIZE:
+ return "DFU_TRANSFER_SIZE";
+ case CSR_PSKEY_DFU_ENABLE:
+ return "DFU_ENABLE";
+ case CSR_PSKEY_DFU_LIN_REG_ENABLE:
+ return "DFU_LIN_REG_ENABLE";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_MSB:
+ return "DFUENC_VMAPP_PK_MODULUS_MSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_LSB:
+ return "DFUENC_VMAPP_PK_MODULUS_LSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_M_DASH:
+ return "DFUENC_VMAPP_PK_M_DASH";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_R2N_MSB:
+ return "DFUENC_VMAPP_PK_R2N_MSB";
+ case CSR_PSKEY_DFUENC_VMAPP_PK_R2N_LSB:
+ return "DFUENC_VMAPP_PK_R2N_LSB";
+ case CSR_PSKEY_BCSP_LM_PS_BLOCK:
+ return "BCSP_LM_PS_BLOCK";
+ case CSR_PSKEY_HOSTIO_FC_PS_BLOCK:
+ return "HOSTIO_FC_PS_BLOCK";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO0:
+ return "HOSTIO_PROTOCOL_INFO0";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO1:
+ return "HOSTIO_PROTOCOL_INFO1";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO2:
+ return "HOSTIO_PROTOCOL_INFO2";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO3:
+ return "HOSTIO_PROTOCOL_INFO3";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO4:
+ return "HOSTIO_PROTOCOL_INFO4";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO5:
+ return "HOSTIO_PROTOCOL_INFO5";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO6:
+ return "HOSTIO_PROTOCOL_INFO6";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO7:
+ return "HOSTIO_PROTOCOL_INFO7";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO8:
+ return "HOSTIO_PROTOCOL_INFO8";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO9:
+ return "HOSTIO_PROTOCOL_INFO9";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO10:
+ return "HOSTIO_PROTOCOL_INFO10";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO11:
+ return "HOSTIO_PROTOCOL_INFO11";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO12:
+ return "HOSTIO_PROTOCOL_INFO12";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO13:
+ return "HOSTIO_PROTOCOL_INFO13";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO14:
+ return "HOSTIO_PROTOCOL_INFO14";
+ case CSR_PSKEY_HOSTIO_PROTOCOL_INFO15:
+ return "HOSTIO_PROTOCOL_INFO15";
+ case CSR_PSKEY_HOSTIO_UART_RESET_TIMEOUT:
+ return "HOSTIO_UART_RESET_TIMEOUT";
+ case CSR_PSKEY_HOSTIO_USE_HCI_EXTN:
+ return "HOSTIO_USE_HCI_EXTN";
+ case CSR_PSKEY_HOSTIO_USE_HCI_EXTN_CCFC:
+ return "HOSTIO_USE_HCI_EXTN_CCFC";
+ case CSR_PSKEY_HOSTIO_HCI_EXTN_PAYLOAD_SIZE:
+ return "HOSTIO_HCI_EXTN_PAYLOAD_SIZE";
+ case CSR_PSKEY_BCSP_LM_CNF_CNT_LIMIT:
+ return "BCSP_LM_CNF_CNT_LIMIT";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_PCM:
+ return "HOSTIO_MAP_SCO_PCM";
+ case CSR_PSKEY_HOSTIO_AWKWARD_PCM_SYNC:
+ return "HOSTIO_AWKWARD_PCM_SYNC";
+ case CSR_PSKEY_HOSTIO_BREAK_POLL_PERIOD:
+ return "HOSTIO_BREAK_POLL_PERIOD";
+ case CSR_PSKEY_HOSTIO_MIN_UART_HCI_SCO_SIZE:
+ return "HOSTIO_MIN_UART_HCI_SCO_SIZE";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_CODEC:
+ return "HOSTIO_MAP_SCO_CODEC";
+ case CSR_PSKEY_PCM_CVSD_TX_HI_FREQ_BOOST:
+ return "PCM_CVSD_TX_HI_FREQ_BOOST";
+ case CSR_PSKEY_PCM_CVSD_RX_HI_FREQ_BOOST:
+ return "PCM_CVSD_RX_HI_FREQ_BOOST";
+ case CSR_PSKEY_PCM_CONFIG32:
+ return "PCM_CONFIG32";
+ case CSR_PSKEY_USE_OLD_BCSP_LE:
+ return "USE_OLD_BCSP_LE";
+ case CSR_PSKEY_PCM_CVSD_USE_NEW_FILTER:
+ return "PCM_CVSD_USE_NEW_FILTER";
+ case CSR_PSKEY_PCM_FORMAT:
+ return "PCM_FORMAT";
+ case CSR_PSKEY_CODEC_OUT_GAIN:
+ return "CODEC_OUT_GAIN";
+ case CSR_PSKEY_CODEC_IN_GAIN:
+ return "CODEC_IN_GAIN";
+ case CSR_PSKEY_CODEC_PIO:
+ return "CODEC_PIO";
+ case CSR_PSKEY_PCM_LOW_JITTER_CONFIG:
+ return "PCM_LOW_JITTER_CONFIG";
+ case CSR_PSKEY_HOSTIO_SCO_PCM_THRESHOLDS:
+ return "HOSTIO_SCO_PCM_THRESHOLDS";
+ case CSR_PSKEY_HOSTIO_SCO_HCI_THRESHOLDS:
+ return "HOSTIO_SCO_HCI_THRESHOLDS";
+ case CSR_PSKEY_HOSTIO_MAP_SCO_PCM_SLOT:
+ return "HOSTIO_MAP_SCO_PCM_SLOT";
+ case CSR_PSKEY_UART_BAUDRATE:
+ return "UART_BAUDRATE";
+ case CSR_PSKEY_UART_CONFIG_BCSP:
+ return "UART_CONFIG_BCSP";
+ case CSR_PSKEY_UART_CONFIG_H4:
+ return "UART_CONFIG_H4";
+ case CSR_PSKEY_UART_CONFIG_H5:
+ return "UART_CONFIG_H5";
+ case CSR_PSKEY_UART_CONFIG_USR:
+ return "UART_CONFIG_USR";
+ case CSR_PSKEY_UART_TX_CRCS:
+ return "UART_TX_CRCS";
+ case CSR_PSKEY_UART_ACK_TIMEOUT:
+ return "UART_ACK_TIMEOUT";
+ case CSR_PSKEY_UART_TX_MAX_ATTEMPTS:
+ return "UART_TX_MAX_ATTEMPTS";
+ case CSR_PSKEY_UART_TX_WINDOW_SIZE:
+ return "UART_TX_WINDOW_SIZE";
+ case CSR_PSKEY_UART_HOST_WAKE:
+ return "UART_HOST_WAKE";
+ case CSR_PSKEY_HOSTIO_THROTTLE_TIMEOUT:
+ return "HOSTIO_THROTTLE_TIMEOUT";
+ case CSR_PSKEY_PCM_ALWAYS_ENABLE:
+ return "PCM_ALWAYS_ENABLE";
+ case CSR_PSKEY_UART_HOST_WAKE_SIGNAL:
+ return "UART_HOST_WAKE_SIGNAL";
+ case CSR_PSKEY_UART_CONFIG_H4DS:
+ return "UART_CONFIG_H4DS";
+ case CSR_PSKEY_H4DS_WAKE_DURATION:
+ return "H4DS_WAKE_DURATION";
+ case CSR_PSKEY_H4DS_MAXWU:
+ return "H4DS_MAXWU";
+ case CSR_PSKEY_H4DS_LE_TIMER_PERIOD:
+ return "H4DS_LE_TIMER_PERIOD";
+ case CSR_PSKEY_H4DS_TWU_TIMER_PERIOD:
+ return "H4DS_TWU_TIMER_PERIOD";
+ case CSR_PSKEY_H4DS_UART_IDLE_TIMER_PERIOD:
+ return "H4DS_UART_IDLE_TIMER_PERIOD";
+ case CSR_PSKEY_ANA_FTRIM:
+ return "ANA_FTRIM";
+ case CSR_PSKEY_WD_TIMEOUT:
+ return "WD_TIMEOUT";
+ case CSR_PSKEY_WD_PERIOD:
+ return "WD_PERIOD";
+ case CSR_PSKEY_HOST_INTERFACE:
+ return "HOST_INTERFACE";
+ case CSR_PSKEY_HQ_HOST_TIMEOUT:
+ return "HQ_HOST_TIMEOUT";
+ case CSR_PSKEY_HQ_ACTIVE:
+ return "HQ_ACTIVE";
+ case CSR_PSKEY_BCCMD_SECURITY_ACTIVE:
+ return "BCCMD_SECURITY_ACTIVE";
+ case CSR_PSKEY_ANA_FREQ:
+ return "ANA_FREQ";
+ case CSR_PSKEY_PIO_PROTECT_MASK:
+ return "PIO_PROTECT_MASK";
+ case CSR_PSKEY_PMALLOC_SIZES:
+ return "PMALLOC_SIZES";
+ case CSR_PSKEY_UART_BAUD_RATE:
+ return "UART_BAUD_RATE";
+ case CSR_PSKEY_UART_CONFIG:
+ return "UART_CONFIG";
+ case CSR_PSKEY_STUB:
+ return "STUB";
+ case CSR_PSKEY_TXRX_PIO_CONTROL:
+ return "TXRX_PIO_CONTROL";
+ case CSR_PSKEY_ANA_RX_LEVEL:
+ return "ANA_RX_LEVEL";
+ case CSR_PSKEY_ANA_RX_FTRIM:
+ return "ANA_RX_FTRIM";
+ case CSR_PSKEY_PSBC_DATA_VERSION:
+ return "PSBC_DATA_VERSION";
+ case CSR_PSKEY_PCM0_ATTENUATION:
+ return "PCM0_ATTENUATION";
+ case CSR_PSKEY_LO_LVL_MAX:
+ return "LO_LVL_MAX";
+ case CSR_PSKEY_LO_ADC_AMPL_MIN:
+ return "LO_ADC_AMPL_MIN";
+ case CSR_PSKEY_LO_ADC_AMPL_MAX:
+ return "LO_ADC_AMPL_MAX";
+ case CSR_PSKEY_IQ_TRIM_CHANNEL:
+ return "IQ_TRIM_CHANNEL";
+ case CSR_PSKEY_IQ_TRIM_GAIN:
+ return "IQ_TRIM_GAIN";
+ case CSR_PSKEY_IQ_TRIM_ENABLE:
+ return "IQ_TRIM_ENABLE";
+ case CSR_PSKEY_TX_OFFSET_HALF_MHZ:
+ return "TX_OFFSET_HALF_MHZ";
+ case CSR_PSKEY_GBL_MISC_ENABLES:
+ return "GBL_MISC_ENABLES";
+ case CSR_PSKEY_UART_SLEEP_TIMEOUT:
+ return "UART_SLEEP_TIMEOUT";
+ case CSR_PSKEY_DEEP_SLEEP_STATE:
+ return "DEEP_SLEEP_STATE";
+ case CSR_PSKEY_IQ_ENABLE_PHASE_TRIM:
+ return "IQ_ENABLE_PHASE_TRIM";
+ case CSR_PSKEY_HCI_HANDLE_FREEZE_PERIOD:
+ return "HCI_HANDLE_FREEZE_PERIOD";
+ case CSR_PSKEY_MAX_FROZEN_HCI_HANDLES:
+ return "MAX_FROZEN_HCI_HANDLES";
+ case CSR_PSKEY_PAGETABLE_DESTRUCTION_DELAY:
+ return "PAGETABLE_DESTRUCTION_DELAY";
+ case CSR_PSKEY_IQ_TRIM_PIO_SETTINGS:
+ return "IQ_TRIM_PIO_SETTINGS";
+ case CSR_PSKEY_USE_EXTERNAL_CLOCK:
+ return "USE_EXTERNAL_CLOCK";
+ case CSR_PSKEY_DEEP_SLEEP_WAKE_CTS:
+ return "DEEP_SLEEP_WAKE_CTS";
+ case CSR_PSKEY_FC_HC2H_FLUSH_DELAY:
+ return "FC_HC2H_FLUSH_DELAY";
+ case CSR_PSKEY_RX_HIGHSIDE:
+ return "RX_HIGHSIDE";
+ case CSR_PSKEY_TX_PRE_LVL:
+ return "TX_PRE_LVL";
+ case CSR_PSKEY_RX_SINGLE_ENDED:
+ return "RX_SINGLE_ENDED";
+ case CSR_PSKEY_TX_FILTER_CONFIG:
+ return "TX_FILTER_CONFIG";
+ case CSR_PSKEY_CLOCK_REQUEST_ENABLE:
+ return "CLOCK_REQUEST_ENABLE";
+ case CSR_PSKEY_RX_MIN_ATTEN:
+ return "RX_MIN_ATTEN";
+ case CSR_PSKEY_XTAL_TARGET_AMPLITUDE:
+ return "XTAL_TARGET_AMPLITUDE";
+ case CSR_PSKEY_PCM_MIN_CPU_CLOCK:
+ return "PCM_MIN_CPU_CLOCK";
+ case CSR_PSKEY_HOST_INTERFACE_PIO_USB:
+ return "HOST_INTERFACE_PIO_USB";
+ case CSR_PSKEY_CPU_IDLE_MODE:
+ return "CPU_IDLE_MODE";
+ case CSR_PSKEY_DEEP_SLEEP_CLEAR_RTS:
+ return "DEEP_SLEEP_CLEAR_RTS";
+ case CSR_PSKEY_RF_RESONANCE_TRIM:
+ return "RF_RESONANCE_TRIM";
+ case CSR_PSKEY_DEEP_SLEEP_PIO_WAKE:
+ return "DEEP_SLEEP_PIO_WAKE";
+ case CSR_PSKEY_DRAIN_BORE_TIMERS:
+ return "DRAIN_BORE_TIMERS";
+ case CSR_PSKEY_DRAIN_TX_POWER_BASE:
+ return "DRAIN_TX_POWER_BASE";
+ case CSR_PSKEY_MODULE_ID:
+ return "MODULE_ID";
+ case CSR_PSKEY_MODULE_DESIGN:
+ return "MODULE_DESIGN";
+ case CSR_PSKEY_MODULE_SECURITY_CODE:
+ return "MODULE_SECURITY_CODE";
+ case CSR_PSKEY_VM_DISABLE:
+ return "VM_DISABLE";
+ case CSR_PSKEY_MOD_MANUF0:
+ return "MOD_MANUF0";
+ case CSR_PSKEY_MOD_MANUF1:
+ return "MOD_MANUF1";
+ case CSR_PSKEY_MOD_MANUF2:
+ return "MOD_MANUF2";
+ case CSR_PSKEY_MOD_MANUF3:
+ return "MOD_MANUF3";
+ case CSR_PSKEY_MOD_MANUF4:
+ return "MOD_MANUF4";
+ case CSR_PSKEY_MOD_MANUF5:
+ return "MOD_MANUF5";
+ case CSR_PSKEY_MOD_MANUF6:
+ return "MOD_MANUF6";
+ case CSR_PSKEY_MOD_MANUF7:
+ return "MOD_MANUF7";
+ case CSR_PSKEY_MOD_MANUF8:
+ return "MOD_MANUF8";
+ case CSR_PSKEY_MOD_MANUF9:
+ return "MOD_MANUF9";
+ case CSR_PSKEY_DUT_VM_DISABLE:
+ return "DUT_VM_DISABLE";
+ case CSR_PSKEY_USR0:
+ return "USR0";
+ case CSR_PSKEY_USR1:
+ return "USR1";
+ case CSR_PSKEY_USR2:
+ return "USR2";
+ case CSR_PSKEY_USR3:
+ return "USR3";
+ case CSR_PSKEY_USR4:
+ return "USR4";
+ case CSR_PSKEY_USR5:
+ return "USR5";
+ case CSR_PSKEY_USR6:
+ return "USR6";
+ case CSR_PSKEY_USR7:
+ return "USR7";
+ case CSR_PSKEY_USR8:
+ return "USR8";
+ case CSR_PSKEY_USR9:
+ return "USR9";
+ case CSR_PSKEY_USR10:
+ return "USR10";
+ case CSR_PSKEY_USR11:
+ return "USR11";
+ case CSR_PSKEY_USR12:
+ return "USR12";
+ case CSR_PSKEY_USR13:
+ return "USR13";
+ case CSR_PSKEY_USR14:
+ return "USR14";
+ case CSR_PSKEY_USR15:
+ return "USR15";
+ case CSR_PSKEY_USR16:
+ return "USR16";
+ case CSR_PSKEY_USR17:
+ return "USR17";
+ case CSR_PSKEY_USR18:
+ return "USR18";
+ case CSR_PSKEY_USR19:
+ return "USR19";
+ case CSR_PSKEY_USR20:
+ return "USR20";
+ case CSR_PSKEY_USR21:
+ return "USR21";
+ case CSR_PSKEY_USR22:
+ return "USR22";
+ case CSR_PSKEY_USR23:
+ return "USR23";
+ case CSR_PSKEY_USR24:
+ return "USR24";
+ case CSR_PSKEY_USR25:
+ return "USR25";
+ case CSR_PSKEY_USR26:
+ return "USR26";
+ case CSR_PSKEY_USR27:
+ return "USR27";
+ case CSR_PSKEY_USR28:
+ return "USR28";
+ case CSR_PSKEY_USR29:
+ return "USR29";
+ case CSR_PSKEY_USR30:
+ return "USR30";
+ case CSR_PSKEY_USR31:
+ return "USR31";
+ case CSR_PSKEY_USR32:
+ return "USR32";
+ case CSR_PSKEY_USR33:
+ return "USR33";
+ case CSR_PSKEY_USR34:
+ return "USR34";
+ case CSR_PSKEY_USR35:
+ return "USR35";
+ case CSR_PSKEY_USR36:
+ return "USR36";
+ case CSR_PSKEY_USR37:
+ return "USR37";
+ case CSR_PSKEY_USR38:
+ return "USR38";
+ case CSR_PSKEY_USR39:
+ return "USR39";
+ case CSR_PSKEY_USR40:
+ return "USR40";
+ case CSR_PSKEY_USR41:
+ return "USR41";
+ case CSR_PSKEY_USR42:
+ return "USR42";
+ case CSR_PSKEY_USR43:
+ return "USR43";
+ case CSR_PSKEY_USR44:
+ return "USR44";
+ case CSR_PSKEY_USR45:
+ return "USR45";
+ case CSR_PSKEY_USR46:
+ return "USR46";
+ case CSR_PSKEY_USR47:
+ return "USR47";
+ case CSR_PSKEY_USR48:
+ return "USR48";
+ case CSR_PSKEY_USR49:
+ return "USR49";
+ case CSR_PSKEY_USB_VERSION:
+ return "USB_VERSION";
+ case CSR_PSKEY_USB_DEVICE_CLASS_CODES:
+ return "USB_DEVICE_CLASS_CODES";
+ case CSR_PSKEY_USB_VENDOR_ID:
+ return "USB_VENDOR_ID";
+ case CSR_PSKEY_USB_PRODUCT_ID:
+ return "USB_PRODUCT_ID";
+ case CSR_PSKEY_USB_MANUF_STRING:
+ return "USB_MANUF_STRING";
+ case CSR_PSKEY_USB_PRODUCT_STRING:
+ return "USB_PRODUCT_STRING";
+ case CSR_PSKEY_USB_SERIAL_NUMBER_STRING:
+ return "USB_SERIAL_NUMBER_STRING";
+ case CSR_PSKEY_USB_CONFIG_STRING:
+ return "USB_CONFIG_STRING";
+ case CSR_PSKEY_USB_ATTRIBUTES:
+ return "USB_ATTRIBUTES";
+ case CSR_PSKEY_USB_MAX_POWER:
+ return "USB_MAX_POWER";
+ case CSR_PSKEY_USB_BT_IF_CLASS_CODES:
+ return "USB_BT_IF_CLASS_CODES";
+ case CSR_PSKEY_USB_LANGID:
+ return "USB_LANGID";
+ case CSR_PSKEY_USB_DFU_CLASS_CODES:
+ return "USB_DFU_CLASS_CODES";
+ case CSR_PSKEY_USB_DFU_PRODUCT_ID:
+ return "USB_DFU_PRODUCT_ID";
+ case CSR_PSKEY_USB_PIO_DETACH:
+ return "USB_PIO_DETACH";
+ case CSR_PSKEY_USB_PIO_WAKEUP:
+ return "USB_PIO_WAKEUP";
+ case CSR_PSKEY_USB_PIO_PULLUP:
+ return "USB_PIO_PULLUP";
+ case CSR_PSKEY_USB_PIO_VBUS:
+ return "USB_PIO_VBUS";
+ case CSR_PSKEY_USB_PIO_WAKE_TIMEOUT:
+ return "USB_PIO_WAKE_TIMEOUT";
+ case CSR_PSKEY_USB_PIO_RESUME:
+ return "USB_PIO_RESUME";
+ case CSR_PSKEY_USB_BT_SCO_IF_CLASS_CODES:
+ return "USB_BT_SCO_IF_CLASS_CODES";
+ case CSR_PSKEY_USB_SUSPEND_PIO_LEVEL:
+ return "USB_SUSPEND_PIO_LEVEL";
+ case CSR_PSKEY_USB_SUSPEND_PIO_DIR:
+ return "USB_SUSPEND_PIO_DIR";
+ case CSR_PSKEY_USB_SUSPEND_PIO_MASK:
+ return "USB_SUSPEND_PIO_MASK";
+ case CSR_PSKEY_USB_ENDPOINT_0_MAX_PACKET_SIZE:
+ return "USB_ENDPOINT_0_MAX_PACKET_SIZE";
+ case CSR_PSKEY_USB_CONFIG:
+ return "USB_CONFIG";
+ case CSR_PSKEY_RADIOTEST_ATTEN_INIT:
+ return "RADIOTEST_ATTEN_INIT";
+ case CSR_PSKEY_RADIOTEST_FIRST_TRIM_TIME:
+ return "RADIOTEST_FIRST_TRIM_TIME";
+ case CSR_PSKEY_RADIOTEST_SUBSEQUENT_TRIM_TIME:
+ return "RADIOTEST_SUBSEQUENT_TRIM_TIME";
+ case CSR_PSKEY_RADIOTEST_LO_LVL_TRIM_ENABLE:
+ return "RADIOTEST_LO_LVL_TRIM_ENABLE";
+ case CSR_PSKEY_RADIOTEST_DISABLE_MODULATION:
+ return "RADIOTEST_DISABLE_MODULATION";
+ case CSR_PSKEY_RFCOMM_FCON_THRESHOLD:
+ return "RFCOMM_FCON_THRESHOLD";
+ case CSR_PSKEY_RFCOMM_FCOFF_THRESHOLD:
+ return "RFCOMM_FCOFF_THRESHOLD";
+ case CSR_PSKEY_IPV6_STATIC_ADDR:
+ return "IPV6_STATIC_ADDR";
+ case CSR_PSKEY_IPV4_STATIC_ADDR:
+ return "IPV4_STATIC_ADDR";
+ case CSR_PSKEY_IPV6_STATIC_PREFIX_LEN:
+ return "IPV6_STATIC_PREFIX_LEN";
+ case CSR_PSKEY_IPV6_STATIC_ROUTER_ADDR:
+ return "IPV6_STATIC_ROUTER_ADDR";
+ case CSR_PSKEY_IPV4_STATIC_SUBNET_MASK:
+ return "IPV4_STATIC_SUBNET_MASK";
+ case CSR_PSKEY_IPV4_STATIC_ROUTER_ADDR:
+ return "IPV4_STATIC_ROUTER_ADDR";
+ case CSR_PSKEY_MDNS_NAME:
+ return "MDNS_NAME";
+ case CSR_PSKEY_FIXED_PIN:
+ return "FIXED_PIN";
+ case CSR_PSKEY_MDNS_PORT:
+ return "MDNS_PORT";
+ case CSR_PSKEY_MDNS_TTL:
+ return "MDNS_TTL";
+ case CSR_PSKEY_MDNS_IPV4_ADDR:
+ return "MDNS_IPV4_ADDR";
+ case CSR_PSKEY_ARP_CACHE_TIMEOUT:
+ return "ARP_CACHE_TIMEOUT";
+ case CSR_PSKEY_HFP_POWER_TABLE:
+ return "HFP_POWER_TABLE";
+ case CSR_PSKEY_DRAIN_BORE_TIMER_COUNTERS:
+ return "DRAIN_BORE_TIMER_COUNTERS";
+ case CSR_PSKEY_DRAIN_BORE_COUNTERS:
+ return "DRAIN_BORE_COUNTERS";
+ case CSR_PSKEY_LOOP_FILTER_TRIM:
+ return "LOOP_FILTER_TRIM";
+ case CSR_PSKEY_DRAIN_BORE_CURRENT_PEAK:
+ return "DRAIN_BORE_CURRENT_PEAK";
+ case CSR_PSKEY_VM_E2_CACHE_LIMIT:
+ return "VM_E2_CACHE_LIMIT";
+ case CSR_PSKEY_FORCE_16MHZ_REF_PIO:
+ return "FORCE_16MHZ_REF_PIO";
+ case CSR_PSKEY_CDMA_LO_REF_LIMITS:
+ return "CDMA_LO_REF_LIMITS";
+ case CSR_PSKEY_CDMA_LO_ERROR_LIMITS:
+ return "CDMA_LO_ERROR_LIMITS";
+ case CSR_PSKEY_CLOCK_STARTUP_DELAY:
+ return "CLOCK_STARTUP_DELAY";
+ case CSR_PSKEY_DEEP_SLEEP_CORRECTION_FACTOR:
+ return "DEEP_SLEEP_CORRECTION_FACTOR";
+ case CSR_PSKEY_TEMPERATURE_CALIBRATION:
+ return "TEMPERATURE_CALIBRATION";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA:
+ return "TEMPERATURE_VS_DELTA_INTERNAL_PA";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL:
+ return "TEMPERATURE_VS_DELTA_TX_PRE_LVL";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB:
+ return "TEMPERATURE_VS_DELTA_TX_BB";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_ANA_FTRIM:
+ return "TEMPERATURE_VS_DELTA_ANA_FTRIM";
+ case CSR_PSKEY_TEST_DELTA_OFFSET:
+ return "TEST_DELTA_OFFSET";
+ case CSR_PSKEY_RX_DYNAMIC_LVL_OFFSET:
+ return "RX_DYNAMIC_LVL_OFFSET";
+ case CSR_PSKEY_TEST_FORCE_OFFSET:
+ return "TEST_FORCE_OFFSET";
+ case CSR_PSKEY_RF_TRAP_BAD_DIVISION_RATIOS:
+ return "RF_TRAP_BAD_DIVISION_RATIOS";
+ case CSR_PSKEY_RADIOTEST_CDMA_LO_REF_LIMITS:
+ return "RADIOTEST_CDMA_LO_REF_LIMITS";
+ case CSR_PSKEY_INITIAL_BOOTMODE:
+ return "INITIAL_BOOTMODE";
+ case CSR_PSKEY_ONCHIP_HCI_CLIENT:
+ return "ONCHIP_HCI_CLIENT";
+ case CSR_PSKEY_RX_ATTEN_BACKOFF:
+ return "RX_ATTEN_BACKOFF";
+ case CSR_PSKEY_RX_ATTEN_UPDATE_RATE:
+ return "RX_ATTEN_UPDATE_RATE";
+ case CSR_PSKEY_SYNTH_TXRX_THRESHOLDS:
+ return "SYNTH_TXRX_THRESHOLDS";
+ case CSR_PSKEY_MIN_WAIT_STATES:
+ return "MIN_WAIT_STATES";
+ case CSR_PSKEY_RSSI_CORRECTION:
+ return "RSSI_CORRECTION";
+ case CSR_PSKEY_SCHED_THROTTLE_TIMEOUT:
+ return "SCHED_THROTTLE_TIMEOUT";
+ case CSR_PSKEY_DEEP_SLEEP_USE_EXTERNAL_CLOCK:
+ return "DEEP_SLEEP_USE_EXTERNAL_CLOCK";
+ case CSR_PSKEY_TRIM_RADIO_FILTERS:
+ return "TRIM_RADIO_FILTERS";
+ case CSR_PSKEY_TRANSMIT_OFFSET:
+ return "TRANSMIT_OFFSET";
+ case CSR_PSKEY_USB_VM_CONTROL:
+ return "USB_VM_CONTROL";
+ case CSR_PSKEY_MR_ANA_RX_FTRIM:
+ return "MR_ANA_RX_FTRIM";
+ case CSR_PSKEY_I2C_CONFIG:
+ return "I2C_CONFIG";
+ case CSR_PSKEY_IQ_LVL_RX:
+ return "IQ_LVL_RX";
+ case CSR_PSKEY_MR_TX_FILTER_CONFIG:
+ return "MR_TX_FILTER_CONFIG";
+ case CSR_PSKEY_MR_TX_CONFIG2:
+ return "MR_TX_CONFIG2";
+ case CSR_PSKEY_USB_DONT_RESET_BOOTMODE_ON_HOST_RESET:
+ return "USB_DONT_RESET_BOOTMODE_ON_HOST_RESET";
+ case CSR_PSKEY_LC_USE_THROTTLING:
+ return "LC_USE_THROTTLING";
+ case CSR_PSKEY_CHARGER_TRIM:
+ return "CHARGER_TRIM";
+ case CSR_PSKEY_CLOCK_REQUEST_FEATURES:
+ return "CLOCK_REQUEST_FEATURES";
+ case CSR_PSKEY_TRANSMIT_OFFSET_CLASS1:
+ return "TRANSMIT_OFFSET_CLASS1";
+ case CSR_PSKEY_TX_AVOID_PA_CLASS1_PIO:
+ return "TX_AVOID_PA_CLASS1_PIO";
+ case CSR_PSKEY_MR_PIO_CONFIG:
+ return "MR_PIO_CONFIG";
+ case CSR_PSKEY_UART_CONFIG2:
+ return "UART_CONFIG2";
+ case CSR_PSKEY_CLASS1_IQ_LVL:
+ return "CLASS1_IQ_LVL";
+ case CSR_PSKEY_CLASS1_TX_CONFIG2:
+ return "CLASS1_TX_CONFIG2";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA_CLASS1:
+ return "TEMPERATURE_VS_DELTA_INTERNAL_PA_CLASS1";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_EXTERNAL_PA_CLASS1:
+ return "TEMPERATURE_VS_DELTA_EXTERNAL_PA_CLASS1";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL_MR:
+ return "TEMPERATURE_VS_DELTA_TX_PRE_LVL_MR";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_HEADER:
+ return "TEMPERATURE_VS_DELTA_TX_BB_MR_HEADER";
+ case CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_PAYLOAD:
+ return "TEMPERATURE_VS_DELTA_TX_BB_MR_PAYLOAD";
+ case CSR_PSKEY_RX_MR_EQ_TAPS:
+ return "RX_MR_EQ_TAPS";
+ case CSR_PSKEY_TX_PRE_LVL_CLASS1:
+ return "TX_PRE_LVL_CLASS1";
+ case CSR_PSKEY_ANALOGUE_ATTENUATOR:
+ return "ANALOGUE_ATTENUATOR";
+ case CSR_PSKEY_MR_RX_FILTER_TRIM:
+ return "MR_RX_FILTER_TRIM";
+ case CSR_PSKEY_MR_RX_FILTER_RESPONSE:
+ return "MR_RX_FILTER_RESPONSE";
+ case CSR_PSKEY_PIO_WAKEUP_STATE:
+ return "PIO_WAKEUP_STATE";
+ case CSR_PSKEY_MR_TX_IF_ATTEN_OFF_TEMP:
+ return "MR_TX_IF_ATTEN_OFF_TEMP";
+ case CSR_PSKEY_LO_DIV_LATCH_BYPASS:
+ return "LO_DIV_LATCH_BYPASS";
+ case CSR_PSKEY_LO_VCO_STANDBY:
+ return "LO_VCO_STANDBY";
+ case CSR_PSKEY_SLOW_CLOCK_FILTER_SHIFT:
+ return "SLOW_CLOCK_FILTER_SHIFT";
+ case CSR_PSKEY_SLOW_CLOCK_FILTER_DIVIDER:
+ return "SLOW_CLOCK_FILTER_DIVIDER";
+ case CSR_PSKEY_USB_ATTRIBUTES_POWER:
+ return "USB_ATTRIBUTES_POWER";
+ case CSR_PSKEY_USB_ATTRIBUTES_WAKEUP:
+ return "USB_ATTRIBUTES_WAKEUP";
+ case CSR_PSKEY_DFU_ATTRIBUTES_MANIFESTATION_TOLERANT:
+ return "DFU_ATTRIBUTES_MANIFESTATION_TOLERANT";
+ case CSR_PSKEY_DFU_ATTRIBUTES_CAN_UPLOAD:
+ return "DFU_ATTRIBUTES_CAN_UPLOAD";
+ case CSR_PSKEY_DFU_ATTRIBUTES_CAN_DOWNLOAD:
+ return "DFU_ATTRIBUTES_CAN_DOWNLOAD";
+ case CSR_PSKEY_UART_CONFIG_STOP_BITS:
+ return "UART_CONFIG_STOP_BITS";
+ case CSR_PSKEY_UART_CONFIG_PARITY_BIT:
+ return "UART_CONFIG_PARITY_BIT";
+ case CSR_PSKEY_UART_CONFIG_FLOW_CTRL_EN:
+ return "UART_CONFIG_FLOW_CTRL_EN";
+ case CSR_PSKEY_UART_CONFIG_RTS_AUTO_EN:
+ return "UART_CONFIG_RTS_AUTO_EN";
+ case CSR_PSKEY_UART_CONFIG_RTS:
+ return "UART_CONFIG_RTS";
+ case CSR_PSKEY_UART_CONFIG_TX_ZERO_EN:
+ return "UART_CONFIG_TX_ZERO_EN";
+ case CSR_PSKEY_UART_CONFIG_NON_BCSP_EN:
+ return "UART_CONFIG_NON_BCSP_EN";
+ case CSR_PSKEY_UART_CONFIG_RX_RATE_DELAY:
+ return "UART_CONFIG_RX_RATE_DELAY";
+ case CSR_PSKEY_UART_SEQ_TIMEOUT:
+ return "UART_SEQ_TIMEOUT";
+ case CSR_PSKEY_UART_SEQ_RETRIES:
+ return "UART_SEQ_RETRIES";
+ case CSR_PSKEY_UART_SEQ_WINSIZE:
+ return "UART_SEQ_WINSIZE";
+ case CSR_PSKEY_UART_USE_CRC_ON_TX:
+ return "UART_USE_CRC_ON_TX";
+ case CSR_PSKEY_UART_HOST_INITIAL_STATE:
+ return "UART_HOST_INITIAL_STATE";
+ case CSR_PSKEY_UART_HOST_ATTENTION_SPAN:
+ return "UART_HOST_ATTENTION_SPAN";
+ case CSR_PSKEY_UART_HOST_WAKEUP_TIME:
+ return "UART_HOST_WAKEUP_TIME";
+ case CSR_PSKEY_UART_HOST_WAKEUP_WAIT:
+ return "UART_HOST_WAKEUP_WAIT";
+ case CSR_PSKEY_BCSP_LM_MODE:
+ return "BCSP_LM_MODE";
+ case CSR_PSKEY_BCSP_LM_SYNC_RETRIES:
+ return "BCSP_LM_SYNC_RETRIES";
+ case CSR_PSKEY_BCSP_LM_TSHY:
+ return "BCSP_LM_TSHY";
+ case CSR_PSKEY_UART_DFU_CONFIG_STOP_BITS:
+ return "UART_DFU_CONFIG_STOP_BITS";
+ case CSR_PSKEY_UART_DFU_CONFIG_PARITY_BIT:
+ return "UART_DFU_CONFIG_PARITY_BIT";
+ case CSR_PSKEY_UART_DFU_CONFIG_FLOW_CTRL_EN:
+ return "UART_DFU_CONFIG_FLOW_CTRL_EN";
+ case CSR_PSKEY_UART_DFU_CONFIG_RTS_AUTO_EN:
+ return "UART_DFU_CONFIG_RTS_AUTO_EN";
+ case CSR_PSKEY_UART_DFU_CONFIG_RTS:
+ return "UART_DFU_CONFIG_RTS";
+ case CSR_PSKEY_UART_DFU_CONFIG_TX_ZERO_EN:
+ return "UART_DFU_CONFIG_TX_ZERO_EN";
+ case CSR_PSKEY_UART_DFU_CONFIG_NON_BCSP_EN:
+ return "UART_DFU_CONFIG_NON_BCSP_EN";
+ case CSR_PSKEY_UART_DFU_CONFIG_RX_RATE_DELAY:
+ return "UART_DFU_CONFIG_RX_RATE_DELAY";
+ case CSR_PSKEY_AMUX_AIO0:
+ return "AMUX_AIO0";
+ case CSR_PSKEY_AMUX_AIO1:
+ return "AMUX_AIO1";
+ case CSR_PSKEY_AMUX_AIO2:
+ return "AMUX_AIO2";
+ case CSR_PSKEY_AMUX_AIO3:
+ return "AMUX_AIO3";
+ case CSR_PSKEY_LOCAL_NAME_SIMPLIFIED:
+ return "LOCAL_NAME_SIMPLIFIED";
+ case CSR_PSKEY_EXTENDED_STUB:
+ return "EXTENDED_STUB";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+int csr_write_varid_valueless(int dd, uint16_t seqnum, uint16_t varid)
+{
+ unsigned char cmd[] = { 0x02, 0x00, 0x09, 0x00,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ switch (varid) {
+ case CSR_VARID_COLD_RESET:
+ case CSR_VARID_WARM_RESET:
+ case CSR_VARID_COLD_HALT:
+ case CSR_VARID_WARM_HALT:
+ return hci_send_cmd(dd, OGF_VENDOR_CMD, 0x00, sizeof(cmd) + 1, cp);
+ }
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int csr_write_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length)
+{
+ unsigned char cmd[] = { 0x02, 0x00, ((length / 2) + 5) & 0xff, ((length / 2) + 5) >> 8,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+ memcpy(cp + 11, value, length);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + length + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int csr_read_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length)
+{
+ unsigned char cmd[] = { 0x00, 0x00, ((length / 2) + 5) & 0xff, ((length / 2) + 5) >> 8,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+ memcpy(cp + 11, value, length);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + length + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ memcpy(value, rp + 11, length);
+
+ return 0;
+}
+
+int csr_read_varid_uint16(int dd, uint16_t seqnum, uint16_t varid, uint16_t *value)
+{
+ unsigned char cmd[] = { 0x00, 0x00, 0x09, 0x00,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ *value = rp[11] + (rp[12] << 8);
+
+ return 0;
+}
+
+int csr_read_varid_uint32(int dd, uint16_t seqnum, uint16_t varid, uint32_t *value)
+{
+ unsigned char cmd[] = { 0x00, 0x00, 0x09, 0x00,
+ seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ *value = ((rp[11] + (rp[12] << 8)) << 16) + (rp[13] + (rp[14] << 8));
+
+ return 0;
+}
+
+int csr_read_pskey_complex(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint8_t *value, uint16_t length)
+{
+ unsigned char cmd[] = { 0x00, 0x00, ((length / 2) + 8) & 0xff, ((length / 2) + 8) >> 8,
+ seqnum & 0xff, seqnum >> 8, 0x03, 0x70, 0x00, 0x00,
+ pskey & 0xff, pskey >> 8,
+ (length / 2) & 0xff, (length / 2) >> 8,
+ stores & 0xff, stores >> 8, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + length - 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ memcpy(value, rp + 17, length);
+
+ return 0;
+}
+
+int csr_write_pskey_complex(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint8_t *value, uint16_t length)
+{
+ unsigned char cmd[] = { 0x02, 0x00, ((length / 2) + 8) & 0xff, ((length / 2) + 8) >> 8,
+ seqnum & 0xff, seqnum >> 8, 0x03, 0x70, 0x00, 0x00,
+ pskey & 0xff, pskey >> 8,
+ (length / 2) & 0xff, (length / 2) >> 8,
+ stores & 0xff, stores >> 8, 0x00, 0x00 };
+
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+
+ memcpy(cp + 17, value, length);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = sizeof(cmd) + length - 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int csr_read_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint16_t *value)
+{
+ uint8_t array[2] = { 0x00, 0x00 };
+ int err;
+
+ err = csr_read_pskey_complex(dd, seqnum, pskey, stores, array, 2);
+
+ *value = array[0] + (array[1] << 8);
+
+ return err;
+}
+
+int csr_write_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint16_t value)
+{
+ uint8_t array[2] = { value & 0xff, value >> 8 };
+
+ return csr_write_pskey_complex(dd, seqnum, pskey, stores, array, 2);
+}
+
+int csr_read_pskey_uint32(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint32_t *value)
+{
+ uint8_t array[4] = { 0x00, 0x00, 0x00, 0x00 };
+ int err;
+
+ err = csr_read_pskey_complex(dd, seqnum, pskey, stores, array, 4);
+
+ *value = ((array[0] + (array[1] << 8)) << 16) +
+ (array[2] + (array[3] << 8));
+
+ return err;
+}
+
+int csr_write_pskey_uint32(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint32_t value)
+{
+ uint8_t array[4] = { (value & 0xff0000) >> 16, value >> 24,
+ value & 0xff, (value & 0xff00) >> 8 };
+
+ return csr_write_pskey_complex(dd, seqnum, pskey, stores, array, 4);
+}
+
+int psr_put(uint16_t pskey, uint8_t *value, uint16_t size)
+{
+ struct psr_data *item;
+
+ item = malloc(sizeof(*item));
+ if (!item)
+ return -ENOMEM;
+
+ item->pskey = pskey;
+
+ if (size > 0) {
+ item->value = malloc(size);
+ if (!item->value) {
+ free(item);
+ return -ENOMEM;
+ }
+
+ memcpy(item->value, value, size);
+ item->size = size;
+ } else {
+ item->value = NULL;
+ item->size = 0;
+ }
+
+ item->next = NULL;
+
+ if (!head)
+ head = item;
+ else
+ tail->next = item;
+
+ tail = item;
+
+ return 0;
+}
+
+int psr_get(uint16_t *pskey, uint8_t *value, uint16_t *size)
+{
+ struct psr_data *item = head;
+
+ if (!head)
+ return -ENOENT;
+
+ *pskey = item->pskey;
+
+ if (item->value) {
+ if (value && item->size > 0)
+ memcpy(value, item->value, item->size);
+ free(item->value);
+ *size = item->size;
+ } else
+ *size = 0;
+
+ if (head == tail)
+ tail = NULL;
+
+ head = head->next;
+ free(item);
+
+ return 0;
+}
+
+static int parse_line(char *str)
+{
+ uint8_t array[256];
+ uint16_t value, pskey, length = 0;
+ char *off, *end;
+
+ pskey = strtol(str + 1, NULL, 16);
+ off = strstr(str, "=") + 1;
+ if (!off)
+ return -EIO;
+
+ while (1) {
+ value = strtol(off, &end, 16);
+ if (value == 0 && off == end)
+ break;
+
+ array[length++] = value & 0xff;
+ array[length++] = value >> 8;
+
+ if (*end == '\0')
+ break;
+
+ off = end + 1;
+ }
+
+ return psr_put(pskey, array, length);
+}
+
+int psr_read(const char *filename)
+{
+ struct stat st;
+ char *str, *map, *off, *end;
+ int fd, err = 0;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ if (fstat(fd, &st) < 0) {
+ err = -errno;
+ goto close;
+ }
+
+ map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (!map || map == MAP_FAILED) {
+ err = -errno;
+ goto close;
+ }
+
+ off = map;
+
+ while (1) {
+ if (*off == '\r' || *off == '\n') {
+ off++;
+ continue;
+ }
+
+ end = strpbrk(off, "\r\n");
+ if (!end)
+ break;
+
+ str = malloc(end - off + 1);
+ if (!str)
+ break;
+
+ memset(str, 0, end - off + 1);
+ strncpy(str, off, end - off);
+ if (*str == '&')
+ parse_line(str);
+
+ free(str);
+ off = end + 1;
+ }
+
+ munmap(map, st.st_size);
+
+close:
+ close(fd);
+
+ return err;
+}
+
+int psr_print(void)
+{
+ uint8_t array[256];
+ uint16_t pskey, length;
+ char *str, val[7];
+ int i;
+
+ while (1) {
+ if (psr_get(&pskey, array, &length) < 0)
+ break;
+
+ str = csr_pskeytoval(pskey);
+ if (!strcasecmp(str, "UNKNOWN")) {
+ sprintf(val, "0x%04x", pskey);
+ str = NULL;
+ }
+
+ printf("// %s%s\n&%04x =", str ? "PSKEY_" : "",
+ str ? str : val, pskey);
+ for (i = 0; i < length / 2; i++)
+ printf(" %02x%02x", array[i * 2 + 1], array[i * 2]);
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/csr.h b/external/cache/sources/hcitools/csr.h
new file mode 100644
index 0000000..8b94d7b
--- /dev/null
+++ b/external/cache/sources/hcitools/csr.h
@@ -0,0 +1,553 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include
+#include
+
+#define CSR_VARID_PS_CLR_ALL 0x000b /* valueless */
+#define CSR_VARID_PS_FACTORY_SET 0x000c /* valueless */
+#define CSR_VARID_PS_CLR_ALL_STORES 0x082d /* uint16 */
+#define CSR_VARID_BC01_STATUS 0x2801 /* uint16 */
+#define CSR_VARID_BUILDID 0x2819 /* uint16 */
+#define CSR_VARID_CHIPVER 0x281a /* uint16 */
+#define CSR_VARID_CHIPREV 0x281b /* uint16 */
+#define CSR_VARID_INTERFACE_VERSION 0x2825 /* uint16 */
+#define CSR_VARID_RAND 0x282a /* uint16 */
+#define CSR_VARID_MAX_CRYPT_KEY_LENGTH 0x282c /* uint16 */
+#define CSR_VARID_CHIPANAREV 0x2836 /* uint16 */
+#define CSR_VARID_BUILDID_LOADER 0x2838 /* uint16 */
+#define CSR_VARID_BT_CLOCK 0x2c00 /* uint32 */
+#define CSR_VARID_PS_NEXT 0x3005 /* complex */
+#define CSR_VARID_PS_SIZE 0x3006 /* complex */
+#define CSR_VARID_CRYPT_KEY_LENGTH 0x3008 /* complex */
+#define CSR_VARID_PICONET_INSTANCE 0x3009 /* complex */
+#define CSR_VARID_GET_CLR_EVT 0x300a /* complex */
+#define CSR_VARID_GET_NEXT_BUILDDEF 0x300b /* complex */
+#define CSR_VARID_PS_MEMORY_TYPE 0x3012 /* complex */
+#define CSR_VARID_READ_BUILD_NAME 0x301c /* complex */
+#define CSR_VARID_COLD_RESET 0x4001 /* valueless */
+#define CSR_VARID_WARM_RESET 0x4002 /* valueless */
+#define CSR_VARID_COLD_HALT 0x4003 /* valueless */
+#define CSR_VARID_WARM_HALT 0x4004 /* valueless */
+#define CSR_VARID_INIT_BT_STACK 0x4005 /* valueless */
+#define CSR_VARID_ACTIVATE_BT_STACK 0x4006 /* valueless */
+#define CSR_VARID_ENABLE_TX 0x4007 /* valueless */
+#define CSR_VARID_DISABLE_TX 0x4008 /* valueless */
+#define CSR_VARID_RECAL 0x4009 /* valueless */
+#define CSR_VARID_PS_FACTORY_RESTORE 0x400d /* valueless */
+#define CSR_VARID_PS_FACTORY_RESTORE_ALL 0x400e /* valueless */
+#define CSR_VARID_PS_DEFRAG_RESET 0x400f /* valueless */
+#define CSR_VARID_KILL_VM_APPLICATION 0x4010 /* valueless */
+#define CSR_VARID_HOPPING_ON 0x4011 /* valueless */
+#define CSR_VARID_CANCEL_PAGE 0x4012 /* valueless */
+#define CSR_VARID_PS_CLR 0x4818 /* uint16 */
+#define CSR_VARID_MAP_SCO_PCM 0x481c /* uint16 */
+#define CSR_VARID_SINGLE_CHAN 0x482e /* uint16 */
+#define CSR_VARID_RADIOTEST 0x5004 /* complex */
+#define CSR_VARID_PS_CLR_STORES 0x500c /* complex */
+#define CSR_VARID_NO_VARIABLE 0x6000 /* valueless */
+#define CSR_VARID_CONFIG_UART 0x6802 /* uint16 */
+#define CSR_VARID_PANIC_ARG 0x6805 /* uint16 */
+#define CSR_VARID_FAULT_ARG 0x6806 /* uint16 */
+#define CSR_VARID_MAX_TX_POWER 0x6827 /* int8 */
+#define CSR_VARID_DEFAULT_TX_POWER 0x682b /* int8 */
+#define CSR_VARID_PS 0x7003 /* complex */
+
+#define CSR_PSKEY_BDADDR 0x0001 /* bdaddr / uint16[] = { 0x00A5A5, 0x5b, 0x0002 } */
+#define CSR_PSKEY_COUNTRYCODE 0x0002 /* uint16 */
+#define CSR_PSKEY_CLASSOFDEVICE 0x0003 /* bdcod */
+#define CSR_PSKEY_DEVICE_DRIFT 0x0004 /* uint16 */
+#define CSR_PSKEY_DEVICE_JITTER 0x0005 /* uint16 */
+#define CSR_PSKEY_MAX_ACLS 0x000d /* uint16 */
+#define CSR_PSKEY_MAX_SCOS 0x000e /* uint16 */
+#define CSR_PSKEY_MAX_REMOTE_MASTERS 0x000f /* uint16 */
+#define CSR_PSKEY_ENABLE_MASTERY_WITH_SLAVERY 0x0010 /* bool */
+#define CSR_PSKEY_H_HC_FC_MAX_ACL_PKT_LEN 0x0011 /* uint16 */
+#define CSR_PSKEY_H_HC_FC_MAX_SCO_PKT_LEN 0x0012 /* uint8 */
+#define CSR_PSKEY_H_HC_FC_MAX_ACL_PKTS 0x0013 /* uint16 */
+#define CSR_PSKEY_H_HC_FC_MAX_SCO_PKTS 0x0014 /* uint16 */
+#define CSR_PSKEY_LC_FC_BUFFER_LOW_WATER_MARK 0x0015 /* lc_fc_lwm */
+#define CSR_PSKEY_LC_MAX_TX_POWER 0x0017 /* int16 */
+#define CSR_PSKEY_TX_GAIN_RAMP 0x001d /* uint16 */
+#define CSR_PSKEY_LC_POWER_TABLE 0x001e /* power_setting[] */
+#define CSR_PSKEY_LC_PEER_POWER_PERIOD 0x001f /* TIME */
+#define CSR_PSKEY_LC_FC_POOLS_LOW_WATER_MARK 0x0020 /* lc_fc_lwm */
+#define CSR_PSKEY_LC_DEFAULT_TX_POWER 0x0021 /* int16 */
+#define CSR_PSKEY_LC_RSSI_GOLDEN_RANGE 0x0022 /* uint8 */
+#define CSR_PSKEY_LC_COMBO_DISABLE_PIO_MASK 0x0028 /* uint16[] */
+#define CSR_PSKEY_LC_COMBO_PRIORITY_PIO_MASK 0x0029 /* uint16[] */
+#define CSR_PSKEY_LC_COMBO_DOT11_CHANNEL_PIO_BASE 0x002a /* uint16 */
+#define CSR_PSKEY_LC_COMBO_DOT11_BLOCK_CHANNELS 0x002b /* uint16 */
+#define CSR_PSKEY_LC_MAX_TX_POWER_NO_RSSI 0x002d /* int8 */
+#define CSR_PSKEY_LC_CONNECTION_RX_WINDOW 0x002e /* uint16 */
+#define CSR_PSKEY_LC_COMBO_DOT11_TX_PROTECTION_MODE 0x0030 /* uint16 */
+#define CSR_PSKEY_LC_ENHANCED_POWER_TABLE 0x0031 /* enhanced_power_setting[] */
+#define CSR_PSKEY_LC_WIDEBAND_RSSI_CONFIG 0x0032 /* wideband_rssi_config */
+#define CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_LEAD 0x0033 /* uint16 */
+#define CSR_PSKEY_BT_CLOCK_INIT 0x0034 /* uint32 */
+#define CSR_PSKEY_TX_MR_MOD_DELAY 0x0038 /* uint8 */
+#define CSR_PSKEY_RX_MR_SYNC_TIMING 0x0039 /* uint16 */
+#define CSR_PSKEY_RX_MR_SYNC_CONFIG 0x003a /* uint16 */
+#define CSR_PSKEY_LC_LOST_SYNC_SLOTS 0x003b /* uint16 */
+#define CSR_PSKEY_RX_MR_SAMP_CONFIG 0x003c /* uint16 */
+#define CSR_PSKEY_AGC_HYST_LEVELS 0x003d /* agc_hyst_config */
+#define CSR_PSKEY_RX_LEVEL_LOW_SIGNAL 0x003e /* uint16 */
+#define CSR_PSKEY_AGC_IQ_LVL_VALUES 0x003f /* IQ_LVL_VAL[] */
+#define CSR_PSKEY_MR_FTRIM_OFFSET_12DB 0x0040 /* uint16 */
+#define CSR_PSKEY_MR_FTRIM_OFFSET_6DB 0x0041 /* uint16 */
+#define CSR_PSKEY_NO_CAL_ON_BOOT 0x0042 /* bool */
+#define CSR_PSKEY_RSSI_HI_TARGET 0x0043 /* uint8 */
+#define CSR_PSKEY_PREFERRED_MIN_ATTENUATION 0x0044 /* uint8 */
+#define CSR_PSKEY_LC_COMBO_DOT11_PRIORITY_OVERRIDE 0x0045 /* bool */
+#define CSR_PSKEY_LC_MULTISLOT_HOLDOFF 0x0047 /* TIME */
+#define CSR_PSKEY_FREE_KEY_PIGEON_HOLE 0x00c9 /* uint16 */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR0 0x00ca /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR1 0x00cb /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR2 0x00cc /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR3 0x00cd /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR4 0x00ce /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR5 0x00cf /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR6 0x00d0 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR7 0x00d1 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR8 0x00d2 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR9 0x00d3 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR10 0x00d4 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR11 0x00d5 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR12 0x00d6 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR13 0x00d7 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR14 0x00d8 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LINK_KEY_BD_ADDR15 0x00d9 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_ENC_KEY_LMIN 0x00da /* uint16 */
+#define CSR_PSKEY_ENC_KEY_LMAX 0x00db /* uint16 */
+#define CSR_PSKEY_LOCAL_SUPPORTED_FEATURES 0x00ef /* uint16[] = { 0xffff, 0xfe8f, 0xf99b, 0x8000 }*/
+#define CSR_PSKEY_LM_USE_UNIT_KEY 0x00f0 /* bool */
+#define CSR_PSKEY_HCI_NOP_DISABLE 0x00f2 /* bool */
+#define CSR_PSKEY_LM_MAX_EVENT_FILTERS 0x00f4 /* uint8 */
+#define CSR_PSKEY_LM_USE_ENC_MODE_BROADCAST 0x00f5 /* bool */
+#define CSR_PSKEY_LM_TEST_SEND_ACCEPTED_TWICE 0x00f6 /* bool */
+#define CSR_PSKEY_LM_MAX_PAGE_HOLD_TIME 0x00f7 /* uint16 */
+#define CSR_PSKEY_AFH_ADAPTATION_RESPONSE_TIME 0x00f8 /* uint16 */
+#define CSR_PSKEY_AFH_OPTIONS 0x00f9 /* uint16 */
+#define CSR_PSKEY_AFH_RSSI_RUN_PERIOD 0x00fa /* uint16 */
+#define CSR_PSKEY_AFH_REENABLE_CHANNEL_TIME 0x00fb /* uint16 */
+#define CSR_PSKEY_NO_DROP_ON_ACR_MS_FAIL 0x00fc /* bool */
+#define CSR_PSKEY_MAX_PRIVATE_KEYS 0x00fd /* uint8 */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR0 0x00fe /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR1 0x00ff /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR2 0x0100 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR3 0x0101 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR4 0x0102 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR5 0x0103 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR6 0x0104 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_PRIVATE_LINK_KEY_BD_ADDR7 0x0105 /* LM_LINK_KEY_BD_ADDR_T */
+#define CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS 0x0106 /* uint16[] = { 0xffff, 0x03ff, 0xfffe, 0xffff, 0xffff, 0xffff, 0x0ff3, 0xfff8, 0x003f } */
+#define CSR_PSKEY_LM_MAX_ABSENCE_INDEX 0x0107 /* uint8 */
+#define CSR_PSKEY_DEVICE_NAME 0x0108 /* uint16[] */
+#define CSR_PSKEY_AFH_RSSI_THRESHOLD 0x0109 /* uint16 */
+#define CSR_PSKEY_LM_CASUAL_SCAN_INTERVAL 0x010a /* uint16 */
+#define CSR_PSKEY_AFH_MIN_MAP_CHANGE 0x010b /* uint16[] */
+#define CSR_PSKEY_AFH_RSSI_LP_RUN_PERIOD 0x010c /* uint16 */
+#define CSR_PSKEY_HCI_LMP_LOCAL_VERSION 0x010d /* uint16 */
+#define CSR_PSKEY_LMP_REMOTE_VERSION 0x010e /* uint8 */
+#define CSR_PSKEY_HOLD_ERROR_MESSAGE_NUMBER 0x0113 /* uint16 */
+#define CSR_PSKEY_DFU_ATTRIBUTES 0x0136 /* uint8 */
+#define CSR_PSKEY_DFU_DETACH_TO 0x0137 /* uint16 */
+#define CSR_PSKEY_DFU_TRANSFER_SIZE 0x0138 /* uint16 */
+#define CSR_PSKEY_DFU_ENABLE 0x0139 /* bool */
+#define CSR_PSKEY_DFU_LIN_REG_ENABLE 0x013a /* bool */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_MSB 0x015e /* uint16[] */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_MODULUS_LSB 0x015f /* uint16[] */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_M_DASH 0x0160 /* uint16 */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_R2N_MSB 0x0161 /* uint16[] */
+#define CSR_PSKEY_DFUENC_VMAPP_PK_R2N_LSB 0x0162 /* uint16[] */
+#define CSR_PSKEY_BCSP_LM_PS_BLOCK 0x0192 /* BCSP_LM_PS_BLOCK */
+#define CSR_PSKEY_HOSTIO_FC_PS_BLOCK 0x0193 /* HOSTIO_FC_PS_BLOCK */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO0 0x0194 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO1 0x0195 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO2 0x0196 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO3 0x0197 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO4 0x0198 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO5 0x0199 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO6 0x019a /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO7 0x019b /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO8 0x019c /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO9 0x019d /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO10 0x019e /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO11 0x019f /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO12 0x01a0 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO13 0x01a1 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO14 0x01a2 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_PROTOCOL_INFO15 0x01a3 /* PROTOCOL_INFO */
+#define CSR_PSKEY_HOSTIO_UART_RESET_TIMEOUT 0x01a4 /* TIME */
+#define CSR_PSKEY_HOSTIO_USE_HCI_EXTN 0x01a5 /* bool */
+#define CSR_PSKEY_HOSTIO_USE_HCI_EXTN_CCFC 0x01a6 /* bool */
+#define CSR_PSKEY_HOSTIO_HCI_EXTN_PAYLOAD_SIZE 0x01a7 /* uint16 */
+#define CSR_PSKEY_BCSP_LM_CNF_CNT_LIMIT 0x01aa /* uint16 */
+#define CSR_PSKEY_HOSTIO_MAP_SCO_PCM 0x01ab /* bool */
+#define CSR_PSKEY_HOSTIO_AWKWARD_PCM_SYNC 0x01ac /* bool */
+#define CSR_PSKEY_HOSTIO_BREAK_POLL_PERIOD 0x01ad /* TIME */
+#define CSR_PSKEY_HOSTIO_MIN_UART_HCI_SCO_SIZE 0x01ae /* uint16 */
+#define CSR_PSKEY_HOSTIO_MAP_SCO_CODEC 0x01b0 /* bool */
+#define CSR_PSKEY_PCM_CVSD_TX_HI_FREQ_BOOST 0x01b1 /* uint16 */
+#define CSR_PSKEY_PCM_CVSD_RX_HI_FREQ_BOOST 0x01b2 /* uint16 */
+#define CSR_PSKEY_PCM_CONFIG32 0x01b3 /* uint32 */
+#define CSR_PSKEY_USE_OLD_BCSP_LE 0x01b4 /* uint16 */
+#define CSR_PSKEY_PCM_CVSD_USE_NEW_FILTER 0x01b5 /* bool */
+#define CSR_PSKEY_PCM_FORMAT 0x01b6 /* uint16 */
+#define CSR_PSKEY_CODEC_OUT_GAIN 0x01b7 /* uint16 */
+#define CSR_PSKEY_CODEC_IN_GAIN 0x01b8 /* uint16 */
+#define CSR_PSKEY_CODEC_PIO 0x01b9 /* uint16 */
+#define CSR_PSKEY_PCM_LOW_JITTER_CONFIG 0x01ba /* uint32 */
+#define CSR_PSKEY_HOSTIO_SCO_PCM_THRESHOLDS 0x01bb /* uint16[] */
+#define CSR_PSKEY_HOSTIO_SCO_HCI_THRESHOLDS 0x01bc /* uint16[] */
+#define CSR_PSKEY_HOSTIO_MAP_SCO_PCM_SLOT 0x01bd /* uint16 */
+#define CSR_PSKEY_UART_BAUDRATE 0x01be /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_BCSP 0x01bf /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_H4 0x01c0 /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_H5 0x01c1 /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_USR 0x01c2 /* uint16 */
+#define CSR_PSKEY_UART_TX_CRCS 0x01c3 /* bool */
+#define CSR_PSKEY_UART_ACK_TIMEOUT 0x01c4 /* uint16 */
+#define CSR_PSKEY_UART_TX_MAX_ATTEMPTS 0x01c5 /* uint16 */
+#define CSR_PSKEY_UART_TX_WINDOW_SIZE 0x01c6 /* uint16 */
+#define CSR_PSKEY_UART_HOST_WAKE 0x01c7 /* uint16[] */
+#define CSR_PSKEY_HOSTIO_THROTTLE_TIMEOUT 0x01c8 /* TIME */
+#define CSR_PSKEY_PCM_ALWAYS_ENABLE 0x01c9 /* bool */
+#define CSR_PSKEY_UART_HOST_WAKE_SIGNAL 0x01ca /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_H4DS 0x01cb /* uint16 */
+#define CSR_PSKEY_H4DS_WAKE_DURATION 0x01cc /* uint16 */
+#define CSR_PSKEY_H4DS_MAXWU 0x01cd /* uint16 */
+#define CSR_PSKEY_H4DS_LE_TIMER_PERIOD 0x01cf /* uint16 */
+#define CSR_PSKEY_H4DS_TWU_TIMER_PERIOD 0x01d0 /* uint16 */
+#define CSR_PSKEY_H4DS_UART_IDLE_TIMER_PERIOD 0x01d1 /* uint16 */
+#define CSR_PSKEY_ANA_FTRIM 0x01f6 /* uint16 */
+#define CSR_PSKEY_WD_TIMEOUT 0x01f7 /* TIME */
+#define CSR_PSKEY_WD_PERIOD 0x01f8 /* TIME */
+#define CSR_PSKEY_HOST_INTERFACE 0x01f9 /* phys_bus */
+#define CSR_PSKEY_HQ_HOST_TIMEOUT 0x01fb /* TIME */
+#define CSR_PSKEY_HQ_ACTIVE 0x01fc /* bool */
+#define CSR_PSKEY_BCCMD_SECURITY_ACTIVE 0x01fd /* bool */
+#define CSR_PSKEY_ANA_FREQ 0x01fe /* uint16 */
+#define CSR_PSKEY_PIO_PROTECT_MASK 0x0202 /* uint16 */
+#define CSR_PSKEY_PMALLOC_SIZES 0x0203 /* uint16[] */
+#define CSR_PSKEY_UART_BAUD_RATE 0x0204 /* uint16 */
+#define CSR_PSKEY_UART_CONFIG 0x0205 /* uint16 */
+#define CSR_PSKEY_STUB 0x0207 /* uint16 */
+#define CSR_PSKEY_TXRX_PIO_CONTROL 0x0209 /* uint16 */
+#define CSR_PSKEY_ANA_RX_LEVEL 0x020b /* uint16 */
+#define CSR_PSKEY_ANA_RX_FTRIM 0x020c /* uint16 */
+#define CSR_PSKEY_PSBC_DATA_VERSION 0x020d /* uint16 */
+#define CSR_PSKEY_PCM0_ATTENUATION 0x020f /* uint16 */
+#define CSR_PSKEY_LO_LVL_MAX 0x0211 /* uint16 */
+#define CSR_PSKEY_LO_ADC_AMPL_MIN 0x0212 /* uint16 */
+#define CSR_PSKEY_LO_ADC_AMPL_MAX 0x0213 /* uint16 */
+#define CSR_PSKEY_IQ_TRIM_CHANNEL 0x0214 /* uint16 */
+#define CSR_PSKEY_IQ_TRIM_GAIN 0x0215 /* uint16 */
+#define CSR_PSKEY_IQ_TRIM_ENABLE 0x0216 /* iq_trim_enable_flag */
+#define CSR_PSKEY_TX_OFFSET_HALF_MHZ 0x0217 /* int16 */
+#define CSR_PSKEY_GBL_MISC_ENABLES 0x0221 /* uint16 */
+#define CSR_PSKEY_UART_SLEEP_TIMEOUT 0x0222 /* uint16 */
+#define CSR_PSKEY_DEEP_SLEEP_STATE 0x0229 /* deep_sleep_state */
+#define CSR_PSKEY_IQ_ENABLE_PHASE_TRIM 0x022d /* bool */
+#define CSR_PSKEY_HCI_HANDLE_FREEZE_PERIOD 0x0237 /* TIME */
+#define CSR_PSKEY_MAX_FROZEN_HCI_HANDLES 0x0238 /* uint16 */
+#define CSR_PSKEY_PAGETABLE_DESTRUCTION_DELAY 0x0239 /* TIME */
+#define CSR_PSKEY_IQ_TRIM_PIO_SETTINGS 0x023a /* uint8 */
+#define CSR_PSKEY_USE_EXTERNAL_CLOCK 0x023b /* bool */
+#define CSR_PSKEY_DEEP_SLEEP_WAKE_CTS 0x023c /* uint16 */
+#define CSR_PSKEY_FC_HC2H_FLUSH_DELAY 0x023d /* TIME */
+#define CSR_PSKEY_RX_HIGHSIDE 0x023e /* bool */
+#define CSR_PSKEY_TX_PRE_LVL 0x0240 /* uint8 */
+#define CSR_PSKEY_RX_SINGLE_ENDED 0x0242 /* bool */
+#define CSR_PSKEY_TX_FILTER_CONFIG 0x0243 /* uint32 */
+#define CSR_PSKEY_CLOCK_REQUEST_ENABLE 0x0246 /* uint16 */
+#define CSR_PSKEY_RX_MIN_ATTEN 0x0249 /* uint16 */
+#define CSR_PSKEY_XTAL_TARGET_AMPLITUDE 0x024b /* uint8 */
+#define CSR_PSKEY_PCM_MIN_CPU_CLOCK 0x024d /* uint16 */
+#define CSR_PSKEY_HOST_INTERFACE_PIO_USB 0x0250 /* uint16 */
+#define CSR_PSKEY_CPU_IDLE_MODE 0x0251 /* cpu_idle_mode */
+#define CSR_PSKEY_DEEP_SLEEP_CLEAR_RTS 0x0252 /* bool */
+#define CSR_PSKEY_RF_RESONANCE_TRIM 0x0254 /* uint16 */
+#define CSR_PSKEY_DEEP_SLEEP_PIO_WAKE 0x0255 /* uint16 */
+#define CSR_PSKEY_DRAIN_BORE_TIMERS 0x0256 /* uint32[] */
+#define CSR_PSKEY_DRAIN_TX_POWER_BASE 0x0257 /* uint16 */
+#define CSR_PSKEY_MODULE_ID 0x0259 /* uint32 */
+#define CSR_PSKEY_MODULE_DESIGN 0x025a /* uint16 */
+#define CSR_PSKEY_MODULE_SECURITY_CODE 0x025c /* uint16[] */
+#define CSR_PSKEY_VM_DISABLE 0x025d /* bool */
+#define CSR_PSKEY_MOD_MANUF0 0x025e /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF1 0x025f /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF2 0x0260 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF3 0x0261 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF4 0x0262 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF5 0x0263 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF6 0x0264 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF7 0x0265 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF8 0x0266 /* uint16[] */
+#define CSR_PSKEY_MOD_MANUF9 0x0267 /* uint16[] */
+#define CSR_PSKEY_DUT_VM_DISABLE 0x0268 /* bool */
+#define CSR_PSKEY_USR0 0x028a /* uint16[] */
+#define CSR_PSKEY_USR1 0x028b /* uint16[] */
+#define CSR_PSKEY_USR2 0x028c /* uint16[] */
+#define CSR_PSKEY_USR3 0x028d /* uint16[] */
+#define CSR_PSKEY_USR4 0x028e /* uint16[] */
+#define CSR_PSKEY_USR5 0x028f /* uint16[] */
+#define CSR_PSKEY_USR6 0x0290 /* uint16[] */
+#define CSR_PSKEY_USR7 0x0291 /* uint16[] */
+#define CSR_PSKEY_USR8 0x0292 /* uint16[] */
+#define CSR_PSKEY_USR9 0x0293 /* uint16[] */
+#define CSR_PSKEY_USR10 0x0294 /* uint16[] */
+#define CSR_PSKEY_USR11 0x0295 /* uint16[] */
+#define CSR_PSKEY_USR12 0x0296 /* uint16[] */
+#define CSR_PSKEY_USR13 0x0297 /* uint16[] */
+#define CSR_PSKEY_USR14 0x0298 /* uint16[] */
+#define CSR_PSKEY_USR15 0x0299 /* uint16[] */
+#define CSR_PSKEY_USR16 0x029a /* uint16[] */
+#define CSR_PSKEY_USR17 0x029b /* uint16[] */
+#define CSR_PSKEY_USR18 0x029c /* uint16[] */
+#define CSR_PSKEY_USR19 0x029d /* uint16[] */
+#define CSR_PSKEY_USR20 0x029e /* uint16[] */
+#define CSR_PSKEY_USR21 0x029f /* uint16[] */
+#define CSR_PSKEY_USR22 0x02a0 /* uint16[] */
+#define CSR_PSKEY_USR23 0x02a1 /* uint16[] */
+#define CSR_PSKEY_USR24 0x02a2 /* uint16[] */
+#define CSR_PSKEY_USR25 0x02a3 /* uint16[] */
+#define CSR_PSKEY_USR26 0x02a4 /* uint16[] */
+#define CSR_PSKEY_USR27 0x02a5 /* uint16[] */
+#define CSR_PSKEY_USR28 0x02a6 /* uint16[] */
+#define CSR_PSKEY_USR29 0x02a7 /* uint16[] */
+#define CSR_PSKEY_USR30 0x02a8 /* uint16[] */
+#define CSR_PSKEY_USR31 0x02a9 /* uint16[] */
+#define CSR_PSKEY_USR32 0x02aa /* uint16[] */
+#define CSR_PSKEY_USR33 0x02ab /* uint16[] */
+#define CSR_PSKEY_USR34 0x02ac /* uint16[] */
+#define CSR_PSKEY_USR35 0x02ad /* uint16[] */
+#define CSR_PSKEY_USR36 0x02ae /* uint16[] */
+#define CSR_PSKEY_USR37 0x02af /* uint16[] */
+#define CSR_PSKEY_USR38 0x02b0 /* uint16[] */
+#define CSR_PSKEY_USR39 0x02b1 /* uint16[] */
+#define CSR_PSKEY_USR40 0x02b2 /* uint16[] */
+#define CSR_PSKEY_USR41 0x02b3 /* uint16[] */
+#define CSR_PSKEY_USR42 0x02b4 /* uint16[] */
+#define CSR_PSKEY_USR43 0x02b5 /* uint16[] */
+#define CSR_PSKEY_USR44 0x02b6 /* uint16[] */
+#define CSR_PSKEY_USR45 0x02b7 /* uint16[] */
+#define CSR_PSKEY_USR46 0x02b8 /* uint16[] */
+#define CSR_PSKEY_USR47 0x02b9 /* uint16[] */
+#define CSR_PSKEY_USR48 0x02ba /* uint16[] */
+#define CSR_PSKEY_USR49 0x02bb /* uint16[] */
+#define CSR_PSKEY_USB_VERSION 0x02bc /* uint16 */
+#define CSR_PSKEY_USB_DEVICE_CLASS_CODES 0x02bd /* usbclass */
+#define CSR_PSKEY_USB_VENDOR_ID 0x02be /* uint16 */
+#define CSR_PSKEY_USB_PRODUCT_ID 0x02bf /* uint16 */
+#define CSR_PSKEY_USB_MANUF_STRING 0x02c1 /* unicodestring */
+#define CSR_PSKEY_USB_PRODUCT_STRING 0x02c2 /* unicodestring */
+#define CSR_PSKEY_USB_SERIAL_NUMBER_STRING 0x02c3 /* unicodestring */
+#define CSR_PSKEY_USB_CONFIG_STRING 0x02c4 /* unicodestring */
+#define CSR_PSKEY_USB_ATTRIBUTES 0x02c5 /* uint8 */
+#define CSR_PSKEY_USB_MAX_POWER 0x02c6 /* uint16 */
+#define CSR_PSKEY_USB_BT_IF_CLASS_CODES 0x02c7 /* usbclass */
+#define CSR_PSKEY_USB_LANGID 0x02c9 /* uint16 */
+#define CSR_PSKEY_USB_DFU_CLASS_CODES 0x02ca /* usbclass */
+#define CSR_PSKEY_USB_DFU_PRODUCT_ID 0x02cb /* uint16 */
+#define CSR_PSKEY_USB_PIO_DETACH 0x02ce /* uint16 */
+#define CSR_PSKEY_USB_PIO_WAKEUP 0x02cf /* uint16 */
+#define CSR_PSKEY_USB_PIO_PULLUP 0x02d0 /* uint16 */
+#define CSR_PSKEY_USB_PIO_VBUS 0x02d1 /* uint16 */
+#define CSR_PSKEY_USB_PIO_WAKE_TIMEOUT 0x02d2 /* uint16 */
+#define CSR_PSKEY_USB_PIO_RESUME 0x02d3 /* uint16 */
+#define CSR_PSKEY_USB_BT_SCO_IF_CLASS_CODES 0x02d4 /* usbclass */
+#define CSR_PSKEY_USB_SUSPEND_PIO_LEVEL 0x02d5 /* uint16 */
+#define CSR_PSKEY_USB_SUSPEND_PIO_DIR 0x02d6 /* uint16 */
+#define CSR_PSKEY_USB_SUSPEND_PIO_MASK 0x02d7 /* uint16 */
+#define CSR_PSKEY_USB_ENDPOINT_0_MAX_PACKET_SIZE 0x02d8 /* uint8 */
+#define CSR_PSKEY_USB_CONFIG 0x02d9 /* uint16 */
+#define CSR_PSKEY_RADIOTEST_ATTEN_INIT 0x0320 /* uint16 */
+#define CSR_PSKEY_RADIOTEST_FIRST_TRIM_TIME 0x0326 /* TIME */
+#define CSR_PSKEY_RADIOTEST_SUBSEQUENT_TRIM_TIME 0x0327 /* TIME */
+#define CSR_PSKEY_RADIOTEST_LO_LVL_TRIM_ENABLE 0x0328 /* bool */
+#define CSR_PSKEY_RADIOTEST_DISABLE_MODULATION 0x032c /* bool */
+#define CSR_PSKEY_RFCOMM_FCON_THRESHOLD 0x0352 /* uint16 */
+#define CSR_PSKEY_RFCOMM_FCOFF_THRESHOLD 0x0353 /* uint16 */
+#define CSR_PSKEY_IPV6_STATIC_ADDR 0x0354 /* uint16[] */
+#define CSR_PSKEY_IPV4_STATIC_ADDR 0x0355 /* uint32 */
+#define CSR_PSKEY_IPV6_STATIC_PREFIX_LEN 0x0356 /* uint8 */
+#define CSR_PSKEY_IPV6_STATIC_ROUTER_ADDR 0x0357 /* uint16[] */
+#define CSR_PSKEY_IPV4_STATIC_SUBNET_MASK 0x0358 /* uint32 */
+#define CSR_PSKEY_IPV4_STATIC_ROUTER_ADDR 0x0359 /* uint32 */
+#define CSR_PSKEY_MDNS_NAME 0x035a /* char[] */
+#define CSR_PSKEY_FIXED_PIN 0x035b /* uint8[] */
+#define CSR_PSKEY_MDNS_PORT 0x035c /* uint16 */
+#define CSR_PSKEY_MDNS_TTL 0x035d /* uint8 */
+#define CSR_PSKEY_MDNS_IPV4_ADDR 0x035e /* uint32 */
+#define CSR_PSKEY_ARP_CACHE_TIMEOUT 0x035f /* uint16 */
+#define CSR_PSKEY_HFP_POWER_TABLE 0x0360 /* uint16[] */
+#define CSR_PSKEY_DRAIN_BORE_TIMER_COUNTERS 0x03e7 /* uint32[] */
+#define CSR_PSKEY_DRAIN_BORE_COUNTERS 0x03e6 /* uint32[] */
+#define CSR_PSKEY_LOOP_FILTER_TRIM 0x03e4 /* uint16 */
+#define CSR_PSKEY_DRAIN_BORE_CURRENT_PEAK 0x03e3 /* uint32[] */
+#define CSR_PSKEY_VM_E2_CACHE_LIMIT 0x03e2 /* uint16 */
+#define CSR_PSKEY_FORCE_16MHZ_REF_PIO 0x03e1 /* uint16 */
+#define CSR_PSKEY_CDMA_LO_REF_LIMITS 0x03df /* uint16 */
+#define CSR_PSKEY_CDMA_LO_ERROR_LIMITS 0x03de /* uint16 */
+#define CSR_PSKEY_CLOCK_STARTUP_DELAY 0x03dd /* uint16 */
+#define CSR_PSKEY_DEEP_SLEEP_CORRECTION_FACTOR 0x03dc /* int16 */
+#define CSR_PSKEY_TEMPERATURE_CALIBRATION 0x03db /* temperature_calibration */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA 0x03da /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL 0x03d9 /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB 0x03d8 /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_ANA_FTRIM 0x03d7 /* temperature_calibration[] */
+#define CSR_PSKEY_TEST_DELTA_OFFSET 0x03d6 /* uint16 */
+#define CSR_PSKEY_RX_DYNAMIC_LVL_OFFSET 0x03d4 /* uint16 */
+#define CSR_PSKEY_TEST_FORCE_OFFSET 0x03d3 /* bool */
+#define CSR_PSKEY_RF_TRAP_BAD_DIVISION_RATIOS 0x03cf /* uint16 */
+#define CSR_PSKEY_RADIOTEST_CDMA_LO_REF_LIMITS 0x03ce /* uint16 */
+#define CSR_PSKEY_INITIAL_BOOTMODE 0x03cd /* int16 */
+#define CSR_PSKEY_ONCHIP_HCI_CLIENT 0x03cc /* bool */
+#define CSR_PSKEY_RX_ATTEN_BACKOFF 0x03ca /* uint16 */
+#define CSR_PSKEY_RX_ATTEN_UPDATE_RATE 0x03c9 /* uint16 */
+#define CSR_PSKEY_SYNTH_TXRX_THRESHOLDS 0x03c7 /* uint16 */
+#define CSR_PSKEY_MIN_WAIT_STATES 0x03c6 /* uint16 */
+#define CSR_PSKEY_RSSI_CORRECTION 0x03c5 /* int8 */
+#define CSR_PSKEY_SCHED_THROTTLE_TIMEOUT 0x03c4 /* TIME */
+#define CSR_PSKEY_DEEP_SLEEP_USE_EXTERNAL_CLOCK 0x03c3 /* bool */
+#define CSR_PSKEY_TRIM_RADIO_FILTERS 0x03c2 /* uint16 */
+#define CSR_PSKEY_TRANSMIT_OFFSET 0x03c1 /* int16 */
+#define CSR_PSKEY_USB_VM_CONTROL 0x03c0 /* bool */
+#define CSR_PSKEY_MR_ANA_RX_FTRIM 0x03bf /* uint16 */
+#define CSR_PSKEY_I2C_CONFIG 0x03be /* uint16 */
+#define CSR_PSKEY_IQ_LVL_RX 0x03bd /* uint16 */
+#define CSR_PSKEY_MR_TX_FILTER_CONFIG 0x03bb /* uint32 */
+#define CSR_PSKEY_MR_TX_CONFIG2 0x03ba /* uint16 */
+#define CSR_PSKEY_USB_DONT_RESET_BOOTMODE_ON_HOST_RESET 0x03b9 /* bool */
+#define CSR_PSKEY_LC_USE_THROTTLING 0x03b8 /* bool */
+#define CSR_PSKEY_CHARGER_TRIM 0x03b7 /* uint16 */
+#define CSR_PSKEY_CLOCK_REQUEST_FEATURES 0x03b6 /* uint16 */
+#define CSR_PSKEY_TRANSMIT_OFFSET_CLASS1 0x03b4 /* int16 */
+#define CSR_PSKEY_TX_AVOID_PA_CLASS1_PIO 0x03b3 /* uint16 */
+#define CSR_PSKEY_MR_PIO_CONFIG 0x03b2 /* uint16 */
+#define CSR_PSKEY_UART_CONFIG2 0x03b1 /* uint8 */
+#define CSR_PSKEY_CLASS1_IQ_LVL 0x03b0 /* uint16 */
+#define CSR_PSKEY_CLASS1_TX_CONFIG2 0x03af /* uint16 */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_INTERNAL_PA_CLASS1 0x03ae /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_EXTERNAL_PA_CLASS1 0x03ad /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_PRE_LVL_MR 0x03ac /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_HEADER 0x03ab /* temperature_calibration[] */
+#define CSR_PSKEY_TEMPERATURE_VS_DELTA_TX_BB_MR_PAYLOAD 0x03aa /* temperature_calibration[] */
+#define CSR_PSKEY_RX_MR_EQ_TAPS 0x03a9 /* uint16[] */
+#define CSR_PSKEY_TX_PRE_LVL_CLASS1 0x03a8 /* uint8 */
+#define CSR_PSKEY_ANALOGUE_ATTENUATOR 0x03a7 /* bool */
+#define CSR_PSKEY_MR_RX_FILTER_TRIM 0x03a6 /* uint16 */
+#define CSR_PSKEY_MR_RX_FILTER_RESPONSE 0x03a5 /* int16[] */
+#define CSR_PSKEY_PIO_WAKEUP_STATE 0x039f /* uint16 */
+#define CSR_PSKEY_MR_TX_IF_ATTEN_OFF_TEMP 0x0394 /* int16 */
+#define CSR_PSKEY_LO_DIV_LATCH_BYPASS 0x0393 /* bool */
+#define CSR_PSKEY_LO_VCO_STANDBY 0x0392 /* bool */
+#define CSR_PSKEY_SLOW_CLOCK_FILTER_SHIFT 0x0391 /* uint16 */
+#define CSR_PSKEY_SLOW_CLOCK_FILTER_DIVIDER 0x0390 /* uint16 */
+#define CSR_PSKEY_USB_ATTRIBUTES_POWER 0x03f2 /* bool */
+#define CSR_PSKEY_USB_ATTRIBUTES_WAKEUP 0x03f3 /* bool */
+#define CSR_PSKEY_DFU_ATTRIBUTES_MANIFESTATION_TOLERANT 0x03f4 /* bool */
+#define CSR_PSKEY_DFU_ATTRIBUTES_CAN_UPLOAD 0x03f5 /* bool */
+#define CSR_PSKEY_DFU_ATTRIBUTES_CAN_DOWNLOAD 0x03f6 /* bool */
+#define CSR_PSKEY_UART_CONFIG_STOP_BITS 0x03fc /* bool */
+#define CSR_PSKEY_UART_CONFIG_PARITY_BIT 0x03fd /* uint16 */
+#define CSR_PSKEY_UART_CONFIG_FLOW_CTRL_EN 0x03fe /* bool */
+#define CSR_PSKEY_UART_CONFIG_RTS_AUTO_EN 0x03ff /* bool */
+#define CSR_PSKEY_UART_CONFIG_RTS 0x0400 /* bool */
+#define CSR_PSKEY_UART_CONFIG_TX_ZERO_EN 0x0401 /* bool */
+#define CSR_PSKEY_UART_CONFIG_NON_BCSP_EN 0x0402 /* bool */
+#define CSR_PSKEY_UART_CONFIG_RX_RATE_DELAY 0x0403 /* uint16 */
+#define CSR_PSKEY_UART_SEQ_TIMEOUT 0x0405 /* uint16 */
+#define CSR_PSKEY_UART_SEQ_RETRIES 0x0406 /* uint16 */
+#define CSR_PSKEY_UART_SEQ_WINSIZE 0x0407 /* uint16 */
+#define CSR_PSKEY_UART_USE_CRC_ON_TX 0x0408 /* bool */
+#define CSR_PSKEY_UART_HOST_INITIAL_STATE 0x0409 /* hwakeup_state */
+#define CSR_PSKEY_UART_HOST_ATTENTION_SPAN 0x040a /* uint16 */
+#define CSR_PSKEY_UART_HOST_WAKEUP_TIME 0x040b /* uint16 */
+#define CSR_PSKEY_UART_HOST_WAKEUP_WAIT 0x040c /* uint16 */
+#define CSR_PSKEY_BCSP_LM_MODE 0x0410 /* uint16 */
+#define CSR_PSKEY_BCSP_LM_SYNC_RETRIES 0x0411 /* uint16 */
+#define CSR_PSKEY_BCSP_LM_TSHY 0x0412 /* uint16 */
+#define CSR_PSKEY_UART_DFU_CONFIG_STOP_BITS 0x0417 /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_PARITY_BIT 0x0418 /* uint16 */
+#define CSR_PSKEY_UART_DFU_CONFIG_FLOW_CTRL_EN 0x0419 /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_RTS_AUTO_EN 0x041a /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_RTS 0x041b /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_TX_ZERO_EN 0x041c /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_NON_BCSP_EN 0x041d /* bool */
+#define CSR_PSKEY_UART_DFU_CONFIG_RX_RATE_DELAY 0x041e /* uint16 */
+#define CSR_PSKEY_AMUX_AIO0 0x041f /* ana_amux_sel */
+#define CSR_PSKEY_AMUX_AIO1 0x0420 /* ana_amux_sel */
+#define CSR_PSKEY_AMUX_AIO2 0x0421 /* ana_amux_sel */
+#define CSR_PSKEY_AMUX_AIO3 0x0422 /* ana_amux_sel */
+#define CSR_PSKEY_LOCAL_NAME_SIMPLIFIED 0x0423 /* local_name_complete */
+#define CSR_PSKEY_EXTENDED_STUB 0x2001 /* uint16 */
+
+char *csr_builddeftostr(uint16_t def);
+char *csr_buildidtostr(uint16_t id);
+char *csr_chipvertostr(uint16_t ver, uint16_t rev);
+char *csr_pskeytostr(uint16_t pskey);
+char *csr_pskeytoval(uint16_t pskey);
+
+int csr_open_hci(char *device);
+int csr_read_hci(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_hci(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_hci(void);
+
+int csr_open_usb(char *device);
+int csr_read_usb(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_usb(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_usb(void);
+
+int csr_open_bcsp(char *device, speed_t bcsp_rate);
+int csr_read_bcsp(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_bcsp(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_bcsp(void);
+
+int csr_open_h4(char *device);
+int csr_read_h4(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_h4(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_h4(void);
+
+int csr_open_3wire(char *device);
+int csr_read_3wire(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_3wire(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_3wire(void);
+
+int csr_write_varid_valueless(int dd, uint16_t seqnum, uint16_t varid);
+int csr_write_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length);
+int csr_read_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length);
+int csr_read_varid_uint16(int dd, uint16_t seqnum, uint16_t varid, uint16_t *value);
+int csr_read_varid_uint32(int dd, uint16_t seqnum, uint16_t varid, uint32_t *value);
+int csr_read_pskey_complex(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint8_t *value, uint16_t length);
+int csr_write_pskey_complex(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint8_t *value, uint16_t length);
+int csr_read_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint16_t *value);
+int csr_write_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint16_t value);
+int csr_read_pskey_uint32(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint32_t *value);
+int csr_write_pskey_uint32(int dd, uint16_t seqnum, uint16_t pskey, uint16_t stores, uint32_t value);
+
+int psr_put(uint16_t pskey, uint8_t *value, uint16_t size);
+int psr_get(uint16_t *pskey, uint8_t *value, uint16_t *size);
+int psr_read(const char *filename);
+int psr_print(void);
diff --git a/external/cache/sources/hcitools/hciattach.c b/external/cache/sources/hcitools/hciattach.c
new file mode 100644
index 0000000..9e994f9
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach.c
@@ -0,0 +1,1513 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky
+ * Copyright (C) 2002-2010 Marcel Holtmann
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+static volatile sig_atomic_t __io_canceled = 0;
+
+static void sig_hup(int sig)
+{
+}
+
+static void sig_term(int sig)
+{
+ __io_canceled = 1;
+}
+
+static void sig_alarm(int sig)
+{
+ fprintf(stderr, "Initialization timed out.\n");
+ exit(1);
+}
+
+int uart_speed(int s)
+{
+ switch (s) {
+ case 9600:
+ return B9600;
+ case 19200:
+ return B19200;
+ case 38400:
+ return B38400;
+ case 57600:
+ return B57600;
+ case 115200:
+ return B115200;
+ case 230400:
+ return B230400;
+ case 460800:
+ return B460800;
+ case 500000:
+ return B500000;
+ case 576000:
+ return B576000;
+ case 921600:
+ return B921600;
+ case 1000000:
+ return B1000000;
+ case 1152000:
+ return B1152000;
+ case 1500000:
+ return B1500000;
+ case 2000000:
+ return B2000000;
+#ifdef B2500000
+ case 2500000:
+ return B2500000;
+#endif
+#ifdef B3000000
+ case 3000000:
+ return B3000000;
+#endif
+#ifdef B3500000
+ case 3500000:
+ return B3500000;
+#endif
+#ifdef B3710000
+ case 3710000
+ return B3710000;
+#endif
+#ifdef B4000000
+ case 4000000:
+ return B4000000;
+#endif
+ default:
+ return B57600;
+ }
+}
+
+int set_speed(int fd, struct termios *ti, int speed)
+{
+ if (cfsetospeed(ti, uart_speed(speed)) < 0)
+ return -errno;
+
+ if (cfsetispeed(ti, uart_speed(speed)) < 0)
+ return -errno;
+
+ if (tcsetattr(fd, TCSANOW, ti) < 0)
+ return -errno;
+
+ return 0;
+}
+
+/*
+ * Read an HCI event from the given file descriptor.
+ */
+int read_hci_event(int fd, unsigned char* buf, int size)
+{
+ int remain, r;
+ int count = 0;
+
+ if (size <= 0)
+ return -1;
+
+ /* The first byte identifies the packet type. For HCI event packets, it
+ * should be 0x04, so we read until we get to the 0x04. */
+ while (1) {
+ r = read(fd, buf, 1);
+ if (r <= 0)
+ return -1;
+ if (buf[0] == 0x04)
+ break;
+ }
+ count++;
+
+ /* The next two bytes are the event code and parameter total length. */
+ while (count < 3) {
+ r = read(fd, buf + count, 3 - count);
+ if (r <= 0)
+ return -1;
+ count += r;
+ }
+
+ /* Now we read the parameters. */
+ if (buf[2] < (size - 3))
+ remain = buf[2];
+ else
+ remain = size - 3;
+
+ while ((count - 3) < remain) {
+ r = read(fd, buf + count, remain - (count - 3));
+ if (r <= 0)
+ return -1;
+ count += r;
+ }
+
+ return count;
+}
+
+/*
+ * Ericsson specific initialization
+ */
+static int ericsson(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[5];
+
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x09;
+ cmd[2] = 0xfc;
+ cmd[3] = 0x01;
+
+ switch (u->speed) {
+ case 57600:
+ cmd[4] = 0x03;
+ break;
+ case 115200:
+ cmd[4] = 0x02;
+ break;
+ case 230400:
+ cmd[4] = 0x01;
+ break;
+ case 460800:
+ cmd[4] = 0x00;
+ break;
+ case 921600:
+ cmd[4] = 0x20;
+ break;
+ case 2000000:
+ cmd[4] = 0x25;
+ break;
+ case 3000000:
+ cmd[4] = 0x27;
+ break;
+ case 4000000:
+ cmd[4] = 0x2B;
+ break;
+ default:
+ cmd[4] = 0x03;
+ u->speed = 57600;
+ fprintf(stderr, "Invalid speed requested, using %d bps instead\n", u->speed);
+ break;
+ }
+
+ /* Send initialization command */
+ if (write(fd, cmd, 5) != 5) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+ return 0;
+}
+
+/*
+ * Digianswer specific initialization
+ */
+static int digi(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[5];
+
+ /* DigiAnswer set baud rate command */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x07;
+ cmd[2] = 0xfc;
+ cmd[3] = 0x01;
+
+ switch (u->speed) {
+ case 57600:
+ cmd[4] = 0x08;
+ break;
+ case 115200:
+ cmd[4] = 0x09;
+ break;
+ default:
+ cmd[4] = 0x09;
+ u->speed = 115200;
+ break;
+ }
+
+ /* Send initialization command */
+ if (write(fd, cmd, 5) != 5) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+ return 0;
+}
+
+static int texas(int fd, struct uart_t *u, struct termios *ti)
+{
+ return texas_init(fd, &u->speed, ti);
+}
+
+static int texas2(int fd, struct uart_t *u, struct termios *ti)
+{
+ return texas_post(fd, ti);
+}
+
+static int texasalt(int fd, struct uart_t *u, struct termios *ti)
+{
+ return texasalt_init(fd, u->speed, ti);
+}
+
+static int ath3k_ps(int fd, struct uart_t *u, struct termios *ti)
+{
+ return ath3k_init(fd, u->speed, u->init_speed, u->bdaddr, ti);
+}
+
+static int ath3k_pm(int fd, struct uart_t *u, struct termios *ti)
+{
+ return ath3k_post(fd, u->pm);
+}
+
+static int qualcomm(int fd, struct uart_t *u, struct termios *ti)
+{
+ return qualcomm_init(fd, u->speed, ti, u->bdaddr);
+}
+
+static int intel(int fd, struct uart_t *u, struct termios *ti)
+{
+ return intel_init(fd, u->init_speed, &u->speed, ti);
+}
+
+static int bcm43xx(int fd, struct uart_t *u, struct termios *ti)
+{
+ return bcm43xx_init(fd, u->speed, ti, u->bdaddr);
+}
+
+//Realtek_add_start
+//add realtek Bluetooth init and post function.
+static int realtek_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "Realtek Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );
+ return rtk_init(fd, u->proto, u->speed, ti);
+}
+
+static int realtek_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "Realtek Bluetooth post process\n");
+ return rtk_post(fd, u->proto, ti);
+}
+
+// add xradio Bluetooth init and post function.
+static int xradio_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "XRADIO Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );
+ return xr_init(fd, u, ti);
+}
+
+static int xradio_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "XRADIO Bluetooth post process\n");
+ return xr_post(fd, u, ti);
+}
+
+// add sprd Bluetooth init and post function.
+static int sprd_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "SPRD Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );
+ return sprd_config_init(fd, u, ti);
+}
+
+static int sprd_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ fprintf(stderr, "SPRD Bluetooth post process\n");
+ return sprd_config_post(fd, u, ti);
+}
+
+static int read_check(int fd, void *buf, int count)
+{
+ int res;
+
+ do {
+ res = read(fd, buf, count);
+ if (res != -1) {
+ buf += res;
+ count -= res;
+ }
+ } while (count && (errno == 0 || errno == EINTR));
+
+ if (count)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * BCSP specific initialization
+ */
+static int serial_fd;
+static int bcsp_max_retries = 10;
+
+static void bcsp_tshy_sig_alarm(int sig)
+{
+ unsigned char bcsp_sync_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xda,0xdc,0xed,0xed,0xc0};
+ static int retries = 0;
+
+ if (retries < bcsp_max_retries) {
+ retries++;
+ if (write(serial_fd, &bcsp_sync_pkt, 10) < 0)
+ return;
+ alarm(1);
+ return;
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ fprintf(stderr, "BCSP initialization timed out\n");
+ exit(1);
+}
+
+static void bcsp_tconf_sig_alarm(int sig)
+{
+ unsigned char bcsp_conf_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xad,0xef,0xac,0xed,0xc0};
+ static int retries = 0;
+
+ if (retries < bcsp_max_retries){
+ retries++;
+ if (write(serial_fd, &bcsp_conf_pkt, 10) < 0)
+ return;
+ alarm(1);
+ return;
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ fprintf(stderr, "BCSP initialization timed out\n");
+ exit(1);
+}
+
+static int bcsp(int fd, struct uart_t *u, struct termios *ti)
+{
+ unsigned char byte, bcsph[4], bcspp[4],
+ bcsp_sync_resp_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xac,0xaf,0xef,0xee,0xc0},
+ bcsp_conf_resp_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xde,0xad,0xd0,0xd0,0xc0},
+ bcspsync[4] = {0xda, 0xdc, 0xed, 0xed},
+ bcspsyncresp[4] = {0xac,0xaf,0xef,0xee},
+ bcspconf[4] = {0xad,0xef,0xac,0xed},
+ bcspconfresp[4] = {0xde,0xad,0xd0,0xd0};
+ struct sigaction sa;
+ int len;
+
+ if (set_speed(fd, ti, u->speed) < 0) {
+ perror("Can't set default baud rate");
+ return -1;
+ }
+
+ ti->c_cflag |= PARENB;
+ ti->c_cflag &= ~(PARODD);
+
+ if (tcsetattr(fd, TCSANOW, ti) < 0) {
+ perror("Can't set port settings");
+ return -1;
+ }
+
+ alarm(0);
+
+ serial_fd = fd;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = bcsp_tshy_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ /* State = shy */
+
+ bcsp_tshy_sig_alarm(0);
+ while (1) {
+ do {
+ if (read_check(fd, &byte, 1) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+ } while (byte != 0xC0);
+
+ do {
+ if ( read_check(fd, &bcsph[0], 1) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+ } while (bcsph[0] == 0xC0);
+
+ if ( read_check(fd, &bcsph[1], 3) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+
+ if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3])
+ continue;
+ if (bcsph[1] != 0x41 || bcsph[2] != 0x00)
+ continue;
+
+ if (read_check(fd, &bcspp, 4) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+
+ if (!memcmp(bcspp, bcspsync, 4)) {
+ if (write(fd, &bcsp_sync_resp_pkt,10) < 0)
+ return -1;
+ } else if (!memcmp(bcspp, bcspsyncresp, 4))
+ break;
+ }
+
+ /* State = curious */
+
+ alarm(0);
+ sa.sa_handler = bcsp_tconf_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+ alarm(1);
+
+ while (1) {
+ do {
+ if (read_check(fd, &byte, 1) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+ } while (byte != 0xC0);
+
+ do {
+ if (read_check(fd, &bcsph[0], 1) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+ } while (bcsph[0] == 0xC0);
+
+ if (read_check(fd, &bcsph[1], 3) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+
+ if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3])
+ continue;
+
+ if (bcsph[1] != 0x41 || bcsph[2] != 0x00)
+ continue;
+
+ if (read_check(fd, &bcspp, 4) == -1){
+ perror("Failed to read");
+ return -1;
+ }
+
+ if (!memcmp(bcspp, bcspsync, 4))
+ len = write(fd, &bcsp_sync_resp_pkt, 10);
+ else if (!memcmp(bcspp, bcspconf, 4))
+ len = write(fd, &bcsp_conf_resp_pkt, 10);
+ else if (!memcmp(bcspp, bcspconfresp, 4))
+ break;
+ else
+ continue;
+
+ if (len < 0)
+ return -errno;
+ }
+
+ /* State = garrulous */
+
+ return 0;
+}
+
+/*
+ * CSR specific initialization
+ * Inspired strongly by code in OpenBT and experimentations with Brainboxes
+ * Pcmcia card.
+ * Jean Tourrilhes - 14.11.01
+ */
+static int csr(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = {0, 10000000}; /* 10ms - be generous */
+ unsigned char cmd[30]; /* Command */
+ unsigned char resp[30]; /* Response */
+ int clen = 0; /* Command len */
+ static int csr_seq = 0; /* Sequence number of command */
+ int divisor;
+
+ /* It seems that if we set the CSR UART speed straight away, it
+ * won't work, the CSR UART gets into a state where we can't talk
+ * to it anymore.
+ * On the other hand, doing a read before setting the CSR speed
+ * seems to be ok.
+ * Therefore, the strategy is to read the build ID (useful for
+ * debugging) and only then set the CSR UART speed. Doing like
+ * this is more complex but at least it works ;-)
+ * The CSR UART control may be slow to wake up or something because
+ * every time I read its speed, its bogus...
+ * Jean II */
+
+ /* Try to read the build ID of the CSR chip */
+ clen = 5 + (5 + 6) * 2;
+ /* HCI header */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x00; /* CSR command */
+ cmd[2] = 0xfc; /* MANUFACTURER_SPEC */
+ cmd[3] = 1 + (5 + 6) * 2; /* len */
+ /* CSR MSG header */
+ cmd[4] = 0xC2; /* first+last+channel=BCC */
+ /* CSR BCC header */
+ cmd[5] = 0x00; /* type = GET-REQ */
+ cmd[6] = 0x00; /* - msB */
+ cmd[7] = 5 + 4; /* len */
+ cmd[8] = 0x00; /* - msB */
+ cmd[9] = csr_seq & 0xFF;/* seq num */
+ cmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */
+ csr_seq++;
+ cmd[11] = 0x19; /* var_id = CSR_CMD_BUILD_ID */
+ cmd[12] = 0x28; /* - msB */
+ cmd[13] = 0x00; /* status = STATUS_OK */
+ cmd[14] = 0x00; /* - msB */
+ /* CSR BCC payload */
+ memset(cmd + 15, 0, 6 * 2);
+
+ /* Send command */
+ do {
+ if (write(fd, cmd, clen) != clen) {
+ perror("Failed to write init command (GET_BUILD_ID)");
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response (GET_BUILD_ID)");
+ return -1;
+ }
+
+ /* Event code 0xFF is for vendor-specific events, which is
+ * what we're looking for. */
+ } while (resp[1] != 0xFF);
+
+#ifdef CSR_DEBUG
+ {
+ char temp[512];
+ int i;
+ for (i=0; i < rlen; i++)
+ sprintf(temp + (i*3), "-%02X", resp[i]);
+ fprintf(stderr, "Reading CSR build ID %d [%s]\n", rlen, temp + 1);
+ // In theory, it should look like :
+ // 04-FF-13-FF-01-00-09-00-00-00-19-28-00-00-73-00-00-00-00-00-00-00
+ }
+#endif
+ /* Display that to user */
+ fprintf(stderr, "CSR build ID 0x%02X-0x%02X\n",
+ resp[15] & 0xFF, resp[14] & 0xFF);
+
+ /* Try to read the current speed of the CSR chip */
+ clen = 5 + (5 + 4)*2;
+ /* -- HCI header */
+ cmd[3] = 1 + (5 + 4)*2; /* len */
+ /* -- CSR BCC header -- */
+ cmd[9] = csr_seq & 0xFF; /* seq num */
+ cmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */
+ csr_seq++;
+ cmd[11] = 0x02; /* var_id = CONFIG_UART */
+ cmd[12] = 0x68; /* - msB */
+
+#ifdef CSR_DEBUG
+ /* Send command */
+ do {
+ if (write(fd, cmd, clen) != clen) {
+ perror("Failed to write init command (GET_BUILD_ID)");
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response (GET_BUILD_ID)");
+ return -1;
+ }
+
+ /* Event code 0xFF is for vendor-specific events, which is
+ * what we're looking for. */
+ } while (resp[1] != 0xFF);
+
+ {
+ char temp[512];
+ int i;
+ for (i=0; i < rlen; i++)
+ sprintf(temp + (i*3), "-%02X", resp[i]);
+ fprintf(stderr, "Reading CSR UART speed %d [%s]\n", rlen, temp+1);
+ }
+#endif
+
+ if (u->speed > 1500000) {
+ fprintf(stderr, "Speed %d too high. Remaining at %d baud\n",
+ u->speed, u->init_speed);
+ u->speed = u->init_speed;
+ } else if (u->speed != 57600 && uart_speed(u->speed) == B57600) {
+ /* Unknown speed. Why oh why can't we just pass an int to the kernel? */
+ fprintf(stderr, "Speed %d unrecognised. Remaining at %d baud\n",
+ u->speed, u->init_speed);
+ u->speed = u->init_speed;
+ }
+ if (u->speed == u->init_speed)
+ return 0;
+
+ /* Now, create the command that will set the UART speed */
+ /* CSR BCC header */
+ cmd[5] = 0x02; /* type = SET-REQ */
+ cmd[6] = 0x00; /* - msB */
+ cmd[9] = csr_seq & 0xFF; /* seq num */
+ cmd[10] = (csr_seq >> 8) & 0xFF;/* - msB */
+ csr_seq++;
+
+ divisor = (u->speed*64+7812)/15625;
+
+ /* No parity, one stop bit -> divisor |= 0x0000; */
+ cmd[15] = (divisor) & 0xFF; /* divider */
+ cmd[16] = (divisor >> 8) & 0xFF; /* - msB */
+ /* The rest of the payload will be 0x00 */
+
+#ifdef CSR_DEBUG
+ {
+ char temp[512];
+ int i;
+ for(i = 0; i < clen; i++)
+ sprintf(temp + (i*3), "-%02X", cmd[i]);
+ fprintf(stderr, "Writing CSR UART speed %d [%s]\n", clen, temp + 1);
+ // In theory, it should look like :
+ // 01-00-FC-13-C2-02-00-09-00-03-00-02-68-00-00-BF-0E-00-00-00-00-00-00
+ // 01-00-FC-13-C2-02-00-09-00-01-00-02-68-00-00-D8-01-00-00-00-00-00-00
+ }
+#endif
+
+ /* Send the command to set the CSR UART speed */
+ if (write(fd, cmd, clen) != clen) {
+ perror("Failed to write init command (SET_UART_SPEED)");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+ return 0;
+}
+
+/*
+ * Silicon Wave specific initialization
+ * Thomas Moser
+ */
+static int swave(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = { 0, 500000 };
+ char cmd[10], rsp[100];
+ int r;
+
+ // Silicon Wave set baud rate command
+ // see HCI Vendor Specific Interface from Silicon Wave
+ // first send a "param access set" command to set the
+ // appropriate data fields in RAM. Then send a "HCI Reset
+ // Subcommand", e.g. "soft reset" to make the changes effective.
+
+ cmd[0] = HCI_COMMAND_PKT; // it's a command packet
+ cmd[1] = 0x0B; // OCF 0x0B = param access set
+ cmd[2] = 0xfc; // OGF bx111111 = vendor specific
+ cmd[3] = 0x06; // 6 bytes of data following
+ cmd[4] = 0x01; // param sub command
+ cmd[5] = 0x11; // tag 17 = 0x11 = HCI Transport Params
+ cmd[6] = 0x03; // length of the parameter following
+ cmd[7] = 0x01; // HCI Transport flow control enable
+ cmd[8] = 0x01; // HCI Transport Type = UART
+
+ switch (u->speed) {
+ case 19200:
+ cmd[9] = 0x03;
+ break;
+ case 38400:
+ cmd[9] = 0x02;
+ break;
+ case 57600:
+ cmd[9] = 0x01;
+ break;
+ case 115200:
+ cmd[9] = 0x00;
+ break;
+ default:
+ u->speed = 115200;
+ cmd[9] = 0x00;
+ break;
+ }
+
+ /* Send initialization command */
+ if (write(fd, cmd, 10) != 10) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ // We should wait for a "GET Event" to confirm the success of
+ // the baud rate setting. Wait some time before reading. Better:
+ // read with timeout, parse data
+ // until correct answer, else error handling ... todo ...
+
+ nanosleep(&tm, NULL);
+
+ r = read(fd, rsp, sizeof(rsp));
+ if (r > 0) {
+ // guess it's okay, but we should parse the reply. But since
+ // I don't react on an error anyway ... todo
+ // Response packet format:
+ // 04 Event
+ // FF Vendor specific
+ // 07 Parameter length
+ // 0B Subcommand
+ // 01 Setevent
+ // 11 Tag specifying HCI Transport Layer Parameter
+ // 03 length
+ // 01 flow on
+ // 01 Hci Transport type = Uart
+ // xx Baud rate set (see above)
+ } else {
+ // ups, got error.
+ return -1;
+ }
+
+ // we probably got the reply. Now we must send the "soft reset"
+ // which is standard HCI RESET.
+
+ cmd[0] = HCI_COMMAND_PKT; // it's a command packet
+ cmd[1] = 0x03;
+ cmd[2] = 0x0c;
+ cmd[3] = 0x00;
+
+ /* Send reset command */
+ if (write(fd, cmd, 4) != 4) {
+ perror("Can't write Silicon Wave reset cmd.");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+
+ // now the uart baud rate on the silicon wave module is set and effective.
+ // change our own baud rate as well. Then there is a reset event coming in
+ // on the *new* baud rate. This is *undocumented*! The packet looks like this:
+ // 04 FF 01 0B (which would make that a confirmation of 0x0B = "Param
+ // subcommand class". So: change to new baud rate, read with timeout, parse
+ // data, error handling. BTW: all param access in Silicon Wave is done this way.
+ // Maybe this code would belong in a separate file, or at least code reuse...
+
+ return 0;
+}
+
+/*
+ * ST Microelectronics specific initialization
+ * Marcel Holtmann
+ */
+static int st(int fd, struct uart_t *u, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[5];
+
+ /* ST Microelectronics set baud rate command */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x46; // OCF = Hci_Cmd_ST_Set_Uart_Baud_Rate
+ cmd[2] = 0xfc; // OGF = Vendor specific
+ cmd[3] = 0x01;
+
+ switch (u->speed) {
+ case 9600:
+ cmd[4] = 0x09;
+ break;
+ case 19200:
+ cmd[4] = 0x0b;
+ break;
+ case 38400:
+ cmd[4] = 0x0d;
+ break;
+ case 57600:
+ cmd[4] = 0x0e;
+ break;
+ case 115200:
+ cmd[4] = 0x10;
+ break;
+ case 230400:
+ cmd[4] = 0x12;
+ break;
+ case 460800:
+ cmd[4] = 0x13;
+ break;
+ case 921600:
+ cmd[4] = 0x14;
+ break;
+ default:
+ cmd[4] = 0x10;
+ u->speed = 115200;
+ break;
+ }
+
+ /* Send initialization command */
+ if (write(fd, cmd, 5) != 5) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ nanosleep(&tm, NULL);
+ return 0;
+}
+
+static int stlc2500(int fd, struct uart_t *u, struct termios *ti)
+{
+ bdaddr_t bdaddr;
+ unsigned char resp[10];
+ int n;
+ int rvalue;
+
+ /* STLC2500 has an ericsson core */
+ rvalue = ericsson(fd, u, ti);
+ if (rvalue != 0)
+ return rvalue;
+
+#ifdef STLC2500_DEBUG
+ fprintf(stderr, "Setting speed\n");
+#endif
+ if (set_speed(fd, ti, u->speed) < 0) {
+ perror("Can't set baud rate");
+ return -1;
+ }
+
+#ifdef STLC2500_DEBUG
+ fprintf(stderr, "Speed set...\n");
+#endif
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 10)) < 0) {
+ fprintf(stderr, "Failed to set baud rate on chip\n");
+ return -1;
+ }
+
+#ifdef STLC2500_DEBUG
+ for (i = 0; i < n; i++) {
+ fprintf(stderr, "resp[%d] = %02x\n", i, resp[i]);
+ }
+#endif
+
+ str2ba(u->bdaddr, &bdaddr);
+ return stlc2500_init(fd, &bdaddr);
+}
+
+static int bgb2xx(int fd, struct uart_t *u, struct termios *ti)
+{
+ bdaddr_t bdaddr;
+
+ str2ba(u->bdaddr, &bdaddr);
+
+ return bgb2xx_init(fd, &bdaddr);
+}
+
+/*
+ * Broadcom specific initialization
+ * Extracted from Jungo openrg
+ */
+static int bcm2035(int fd, struct uart_t *u, struct termios *ti)
+{
+ int n;
+ unsigned char cmd[30], resp[30];
+
+ /* Reset the BT Chip */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x03;
+ cmd[2] = 0x0c;
+ cmd[3] = 0x00;
+
+ /* Send command */
+ if (write(fd, cmd, 4) != 4) {
+ fprintf(stderr, "Failed to write reset command\n");
+ return -1;
+ }
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 4)) < 0) {
+ fprintf(stderr, "Failed to reset chip\n");
+ return -1;
+ }
+
+ if (u->bdaddr != NULL) {
+ /* Set BD_ADDR */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0xfc;
+ cmd[3] = 0x06;
+ str2ba(u->bdaddr, (bdaddr_t *) (cmd + 4));
+
+ /* Send command */
+ if (write(fd, cmd, 10) != 10) {
+ fprintf(stderr, "Failed to write BD_ADDR command\n");
+ return -1;
+ }
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 10)) < 0) {
+ fprintf(stderr, "Failed to set BD_ADDR\n");
+ return -1;
+ }
+ }
+
+ /* Read the local version info */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ /* Send command */
+ if (write(fd, cmd, 4) != 4) {
+ fprintf(stderr, "Failed to write \"read local version\" "
+ "command\n");
+ return -1;
+ }
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 4)) < 0) {
+ fprintf(stderr, "Failed to read local version\n");
+ return -1;
+ }
+
+ /* Read the local supported commands info */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x02;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ /* Send command */
+ if (write(fd, cmd, 4) != 4) {
+ fprintf(stderr, "Failed to write \"read local supported "
+ "commands\" command\n");
+ return -1;
+ }
+
+ /* Read reply */
+ if ((n = read_hci_event(fd, resp, 4)) < 0) {
+ fprintf(stderr, "Failed to read local supported commands\n");
+ return -1;
+ }
+
+ /* Set the baud rate */
+ memset(cmd, 0, sizeof(cmd));
+ memset(resp, 0, sizeof(resp));
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x18;
+ cmd[2] = 0xfc;
+ cmd[3] = 0x02;
+ switch (u->speed) {
+ case 57600:
+ cmd[4] = 0x00;
+ cmd[5] = 0xe6;
+ break;
+ case 230400:
+ cmd[4] = 0x22;
+ cmd[5] = 0xfa;
+ break;
+ case 460800:
+ cmd[4] = 0x22;
+ cmd[5] = 0xfd;
+ break;
+ case 921600:
+ cmd[4] = 0x55;
+ cmd[5] = 0xff;
+ break;
+ default:
+ /* Default is 115200 */
+ cmd[4] = 0x00;
+ cmd[5] = 0xf3;
+ break;
+ }
+ fprintf(stderr, "Baud rate parameters: DHBR=0x%2x,DLBR=0x%2x\n",
+ cmd[4], cmd[5]);
+
+ /* Send command */
+ if (write(fd, cmd, 6) != 6) {
+ fprintf(stderr, "Failed to write \"set baud rate\" command\n");
+ return -1;
+ }
+
+ if ((n = read_hci_event(fd, resp, 6)) < 0) {
+ fprintf(stderr, "Failed to set baud rate\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+struct uart_t uart[] = {
+ { "any", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ { "ericsson", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, ericsson, NULL },
+
+ { "digi", 0x0000, 0x0000, HCI_UART_H4, 9600, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, digi, NULL },
+
+ { "bcsp", 0x0000, 0x0000, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Xircom PCMCIA cards: Credit Card Adapter and Real Port Adapter */
+ { "xircom", 0x0105, 0x080a, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ /* CSR Casira serial adapter or BrainBoxes serial dongle (BL642) */
+ { "csr", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, csr, NULL },
+
+ /* BrainBoxes PCMCIA card (BL620) */
+ { "bboxes", 0x0160, 0x0002, HCI_UART_H4, 115200, 460800,
+ FLOW_CTL, DISABLE_PM, NULL, csr, NULL },
+
+ /* Silicon Wave kits */
+ { "swave", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, swave, NULL },
+
+ /* Texas Instruments Bluelink (BRF) modules */
+ { "texas", 0x0000, 0x0000, HCI_UART_LL, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, texas, texas2 },
+
+ { "texasalt", 0x0000, 0x0000, HCI_UART_LL, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, texasalt, NULL },
+
+ /* ST Microelectronics minikits based on STLC2410/STLC2415 */
+ { "st", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, st, NULL },
+
+ /* ST Microelectronics minikits based on STLC2500 */
+ { "stlc2500", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, "00:80:E1:00:AB:BA", stlc2500, NULL },
+
+ /* Philips generic Ericsson IP core based */
+ { "philips", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ /* Philips BGB2xx Module */
+ { "bgb2xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, "BD:B2:10:00:AB:BA", bgb2xx, NULL },
+
+ /* Sphinx Electronics PICO Card */
+ { "picocard", 0x025e, 0x1000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ /* Inventel BlueBird Module */
+ { "inventel", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },
+
+ /* COM One Platinium Bluetooth PC Card */
+ { "comone", 0xffff, 0x0101, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* TDK Bluetooth PC Card and IBM Bluetooth PC Card II */
+ { "tdk", 0x0105, 0x4254, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Socket Bluetooth CF Card (Rev G) */
+ { "socket", 0x0104, 0x0096, HCI_UART_BCSP, 230400, 230400,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* 3Com Bluetooth Card (Version 3.0) */
+ { "3com", 0x0101, 0x0041, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, csr, NULL },
+
+ /* AmbiCom BT2000C Bluetooth PC/CF Card */
+ { "bt2000c", 0x022d, 0x2000, HCI_UART_H4, 57600, 460800,
+ FLOW_CTL, DISABLE_PM, NULL, csr, NULL },
+
+ /* Zoom Bluetooth PCMCIA Card */
+ { "zoom", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Sitecom CN-504 PCMCIA Card */
+ { "sitecom", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Billionton PCBTC1 PCMCIA Card */
+ { "billionton", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,
+ 0, DISABLE_PM, NULL, bcsp, NULL },
+
+ /* Broadcom BCM2035 */
+ { "bcm2035", 0x0A5C, 0x2035, HCI_UART_H4, 115200, 460800,
+ FLOW_CTL, DISABLE_PM, NULL, bcm2035, NULL },
+
+ /* Broadcom BCM43XX */
+ { "bcm43xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 3000000,
+ FLOW_CTL, DISABLE_PM, NULL, bcm43xx, NULL },
+
+ { "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm },
+
+ /* QUALCOMM BTS */
+ { "qualcomm", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, qualcomm, NULL },
+
+ /* Intel Bluetooth Module */
+ { "intel", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, intel, NULL },
+
+ /* Three-wire UART */
+ { "3wire", 0x0000, 0x0000, HCI_UART_3WIRE, 115200, 115200,
+ 0, DISABLE_PM, NULL, NULL, NULL },
+
+ /* AMP controller UART */
+ { "amp", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+ AMP_DEV, DISABLE_PM, NULL, NULL, NULL },
+
+//Realtek_add_start
+ /* Realtek Bluetooth H4*/
+ /* H4 will set 115200 baudrate and flow control enable by default*/
+ { "rtk_h4", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, DISABLE_PM, NULL, realtek_init, realtek_post},
+ /* Realtek Bluetooth H5*/
+ /* H5 will set 921600 baudrate and flow control disable by default */
+ /* H5 will be realtek's recommanded protocol */
+ { "rtk_h5", 0x0000, 0x0000, HCI_UART_3WIRE, 115200,115200, 0, DISABLE_PM, NULL, realtek_init, realtek_post},
+//Realtek_add_end
+
+ { "xradio", 0x0000, 0x0000, HCI_UART_H4, 115200, 1500000, 0, DISABLE_PM, NULL, xradio_init, xradio_post},
+ { "sprd", 0x0000, 0x0000, NULL, 115200, 1500000, FLOW_CTL, DISABLE_PM, NULL, sprd_init, sprd_post},
+
+ { NULL, 0 }
+};
+
+static struct uart_t * get_by_id(int m_id, int p_id)
+{
+ int i;
+ for (i = 0; uart[i].type; i++) {
+ if (uart[i].m_id == m_id && uart[i].p_id == p_id)
+ return &uart[i];
+ }
+ return NULL;
+}
+
+static struct uart_t * get_by_type(char *type)
+{
+ int i;
+ for (i = 0; uart[i].type; i++) {
+ if (!strcmp(uart[i].type, type))
+ return &uart[i];
+ }
+ return NULL;
+}
+
+/* Initialize UART driver */
+static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
+{
+ struct termios ti;
+ int fd, i;
+ unsigned long flags = 0;
+
+ if (raw)
+ flags |= 1 << HCI_UART_RAW_DEVICE;
+
+ if (u->flags & AMP_DEV)
+ flags |= 1 << HCI_UART_CREATE_AMP;
+
+ fd = open(dev, O_RDWR | O_NOCTTY);
+ if (fd < 0) {
+ perror("Can't open serial port");
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (tcgetattr(fd, &ti) < 0) {
+ perror("Can't get port settings");
+ return -1;
+ }
+
+ cfmakeraw(&ti);
+
+ ti.c_cflag |= CLOCAL;
+ if (u->flags & FLOW_CTL)
+ ti.c_cflag |= CRTSCTS;
+ else
+ ti.c_cflag &= ~CRTSCTS;
+
+ if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+ perror("Can't set port settings");
+ return -1;
+ }
+
+ /* Set initial baudrate */
+ if (set_speed(fd, &ti, u->init_speed) < 0) {
+ perror("Can't set initial baud rate");
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (send_break) {
+ tcsendbreak(fd, 0);
+ usleep(500000);
+ }
+
+ if (u->init && u->init(fd, u, &ti) < 0)
+ return -1;
+
+ tcflush(fd, TCIOFLUSH);
+
+ /* Set actual baudrate */
+ if (set_speed(fd, &ti, u->speed) < 0) {
+ perror("Can't set baud rate");
+ return -1;
+ }
+
+ /* Set TTY to N_HCI line discipline */
+ i = N_HCI;
+ if (ioctl(fd, TIOCSETD, &i) < 0) {
+ perror("Can't set line discipline");
+ return -1;
+ }
+
+ if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {
+ perror("Can't set UART flags");
+ return -1;
+ }
+
+ if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) {
+ perror("Can't set device");
+ return -1;
+ }
+
+ if (u->post && u->post(fd, u, &ti) < 0)
+ return -1;
+
+ return fd;
+}
+
+static void usage(void)
+{
+ printf("hciattach - HCI UART driver initialization utility\n");
+ printf("Usage:\n");
+ printf("\thciattach [-n] [-p] [-b] [-r] [-t timeout] [-s initial_speed] [speed] [flow|noflow] [bdaddr]\n");
+ printf("\thciattach -l\n");
+}
+
+int main(int argc, char *argv[])
+{
+ struct uart_t *u = NULL;
+ int detach, printpid, raw, opt, i, n, ld, err;
+ int to = 10;
+ int init_speed = 0;
+ int send_break = 0;
+ pid_t pid;
+ struct sigaction sa;
+ struct pollfd p;
+ sigset_t sigs;
+ char dev[PATH_MAX];
+
+ detach = 1;
+ printpid = 0;
+ raw = 0;
+
+ while ((opt=getopt(argc, argv, "bnpt:s:lr")) != EOF) {
+ switch(opt) {
+ case 'b':
+ send_break = 1;
+ break;
+
+ case 'n':
+ detach = 0;
+ break;
+
+ case 'p':
+ printpid = 1;
+ break;
+
+ case 't':
+ to = atoi(optarg);
+ break;
+
+ case 's':
+ init_speed = atoi(optarg);
+ break;
+
+ case 'l':
+ for (i = 0; uart[i].type; i++) {
+ printf("%-10s0x%04x,0x%04x\n", uart[i].type,
+ uart[i].m_id, uart[i].p_id);
+ }
+ exit(0);
+
+ case 'r':
+ raw = 1;
+ break;
+
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ n = argc - optind;
+ if (n < 2) {
+ usage();
+ exit(1);
+ }
+
+ for (n = 0; optind < argc; n++, optind++) {
+ char *opt;
+
+ opt = argv[optind];
+
+ switch(n) {
+ case 0:
+ dev[0] = 0;
+ if (!strchr(opt, '/'))
+ strcpy(dev, "/dev/");
+ strcat(dev, opt);
+ break;
+
+ case 1:
+ if (strchr(argv[optind], ',')) {
+ uint32_t m_id, p_id;
+ sscanf(argv[optind], "%x,%x", &m_id, &p_id);
+ u = get_by_id(m_id, p_id);
+ } else {
+ u = get_by_type(opt);
+ }
+
+ if (!u) {
+ fprintf(stderr, "Unknown device type or id\n");
+ exit(1);
+ }
+
+ break;
+
+ case 2:
+ u->speed = atoi(argv[optind]);
+ break;
+
+ case 3:
+ if (!strcmp("flow", argv[optind]))
+ u->flags |= FLOW_CTL;
+ else
+ u->flags &= ~FLOW_CTL;
+ break;
+
+ case 4:
+ if (!strcmp("sleep", argv[optind]))
+ u->pm = ENABLE_PM;
+ else
+ u->pm = DISABLE_PM;
+ break;
+
+ case 5:
+ u->bdaddr = argv[optind];
+ break;
+ }
+ }
+
+ if (!u) {
+ fprintf(stderr, "Unknown device type or id\n");
+ exit(1);
+ }
+
+ /* If user specified a initial speed, use that instead of
+ the hardware's default */
+ if (init_speed)
+ u->init_speed = init_speed;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ /* 10 seconds should be enough for initialization */
+ alarm(to);
+ bcsp_max_retries = to;
+
+ n = init_uart(dev, u, send_break, raw);
+ if (n < 0) {
+ perror("Can't initialize device");
+ exit(1);
+ }
+
+ printf("Device setup complete\n");
+
+ alarm(0);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGPIPE, &sa, NULL);
+
+ sa.sa_handler = sig_term;
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ sa.sa_handler = sig_hup;
+ sigaction(SIGHUP, &sa, NULL);
+
+ if (detach) {
+ if ((pid = fork())) {
+ if (printpid)
+ printf("%d\n", pid);
+ return 0;
+ }
+
+ for (i = 0; i < 20; i++)
+ if (i != n)
+ close(i);
+ }
+
+ p.fd = n;
+ p.events = POLLERR | POLLHUP;
+
+ sigfillset(&sigs);
+ sigdelset(&sigs, SIGCHLD);
+ sigdelset(&sigs, SIGPIPE);
+ sigdelset(&sigs, SIGTERM);
+ sigdelset(&sigs, SIGINT);
+ sigdelset(&sigs, SIGHUP);
+
+ while (!__io_canceled) {
+ p.revents = 0;
+ err = ppoll(&p, 1, NULL, &sigs);
+ if (err < 0 && errno == EINTR)
+ continue;
+ if (err)
+ break;
+ }
+
+ /* Restore TTY line discipline */
+ ld = N_TTY;
+ if (ioctl(n, TIOCSETD, &ld) < 0) {
+ perror("Can't restore line discipline");
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach.h b/external/cache/sources/hcitools/hciattach.h
new file mode 100644
index 0000000..f92af74
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include
+
+#include
+
+#ifndef N_HCI
+#define N_HCI 15
+#endif
+
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define HCIUARTGETPROTO _IOR('U', 201, int)
+#define HCIUARTGETDEVICE _IOR('U', 202, int)
+#define HCIUARTSETFLAGS _IOW('U', 203, int)
+#define HCIUARTGETFLAGS _IOR('U', 204, int)
+
+#define HCI_UART_H4 0
+#define HCI_UART_BCSP 1
+#define HCI_UART_3WIRE 2
+#define HCI_UART_H4DS 3
+#define HCI_UART_LL 4
+#define HCI_UART_ATH3K 5
+
+#define HCI_UART_RAW_DEVICE 0
+#define HCI_UART_RESET_ON_INIT 1
+#define HCI_UART_CREATE_AMP 2
+
+struct uart_t {
+ char *type;
+ int m_id;
+ int p_id;
+ int proto;
+ int init_speed;
+ int speed;
+ int flags;
+ int pm;
+ char *bdaddr;
+ int (*init) (int fd, struct uart_t *u, struct termios *ti);
+ int (*post) (int fd, struct uart_t *u, struct termios *ti);
+};
+
+#define FLOW_CTL 0x0001
+#define AMP_DEV 0x0002
+#define ENABLE_PM 1
+#define DISABLE_PM 0
+
+int read_hci_event(int fd, unsigned char *buf, int size);
+int set_speed(int fd, struct termios *ti, int speed);
+int uart_speed(int speed);
+
+int texas_init(int fd, int *speed, struct termios *ti);
+int texas_post(int fd, struct termios *ti);
+int texasalt_init(int fd, int speed, struct termios *ti);
+int stlc2500_init(int fd, bdaddr_t *bdaddr);
+int bgb2xx_init(int dd, bdaddr_t *bdaddr);
+int ath3k_init(int fd, int speed, int init_speed, char *bdaddr,
+ struct termios *ti);
+int ath3k_post(int fd, int pm);
+int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr);
+int intel_init(int fd, int init_speed, int *speed, struct termios *ti);
+int bcm43xx_init(int fd, int speed, struct termios *ti, const char *bdaddr);
+
+//Realtek_add_start
+//add realtek init and post process for realtek Bluetooth chip
+int rtk_init(int fd, int proto, int speed, struct termios *ti);
+int rtk_post(int fd, int proto, struct termios *ti);
+//Realtek_add_end
+
+// add xradio init and post process for xradio Bluetooth chip (xr829)
+int xr_init(int fd, struct uart_t *u, struct termios *ti);
+int xr_post(int fd, struct uart_t *u, struct termios *ti);
+
+// add sprd init and post process for sprd Bluetooth chip (UWE5622)
+int sprd_config_init(int fd, struct uart_t *u, struct termios *ti);
+int sprd_config_post(int fd, struct uart_t *u, struct termios *ti);
diff --git a/external/cache/sources/hcitools/hciattach_ath3k.c b/external/cache/sources/hcitools/hciattach_ath3k.c
new file mode 100644
index 0000000..23208c6
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_ath3k.c
@@ -0,0 +1,1044 @@
+/*
+ * Copyright (c) 2009-2010 Atheros Communications Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define FW_PATH "/lib/firmware/ar3k/"
+
+struct ps_cfg_entry {
+ uint32_t id;
+ uint32_t len;
+ uint8_t *data;
+};
+
+struct ps_entry_type {
+ unsigned char type;
+ unsigned char array;
+};
+
+#define MAX_TAGS 50
+#define PS_HDR_LEN 4
+#define HCI_VENDOR_CMD_OGF 0x3F
+#define HCI_PS_CMD_OCF 0x0B
+
+struct ps_cfg_entry ps_list[MAX_TAGS];
+
+static void load_hci_ps_hdr(uint8_t *cmd, uint8_t ps_op, int len, int index)
+{
+ hci_command_hdr *ch = (void *)cmd;
+
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ HCI_PS_CMD_OCF));
+ ch->plen = len + PS_HDR_LEN;
+ cmd += HCI_COMMAND_HDR_SIZE;
+
+ cmd[0] = ps_op;
+ cmd[1] = index;
+ cmd[2] = index >> 8;
+ cmd[3] = len;
+}
+
+#define PS_EVENT_LEN 100
+
+/*
+ * Send HCI command and wait for command complete event.
+ * The event buffer has to be freed by the caller.
+ */
+static int send_hci_cmd_sync(int dev, uint8_t *cmd, int len, uint8_t **event)
+{
+ int err;
+ uint8_t *hci_event;
+ uint8_t pkt_type = HCI_COMMAND_PKT;
+
+ if (len == 0)
+ return len;
+
+ if (write(dev, &pkt_type, 1) != 1)
+ return -EILSEQ;
+ if (write(dev, (unsigned char *)cmd, len) != len)
+ return -EILSEQ;
+
+ hci_event = (uint8_t *)malloc(PS_EVENT_LEN);
+ if (!hci_event)
+ return -ENOMEM;
+
+ err = read_hci_event(dev, (unsigned char *)hci_event, PS_EVENT_LEN);
+ if (err > 0) {
+ *event = hci_event;
+ } else {
+ free(hci_event);
+ return -EILSEQ;
+ }
+
+ return len;
+}
+
+#define HCI_EV_SUCCESS 0x00
+
+static int read_ps_event(uint8_t *event, uint16_t ocf)
+{
+ hci_event_hdr *eh;
+ uint16_t opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, ocf));
+
+ event++;
+
+ eh = (void *)event;
+ event += HCI_EVENT_HDR_SIZE;
+
+ if (eh->evt == EVT_CMD_COMPLETE) {
+ evt_cmd_complete *cc = (void *)event;
+
+ event += EVT_CMD_COMPLETE_SIZE;
+
+ if (cc->opcode == opcode && event[0] == HCI_EV_SUCCESS)
+ return 0;
+ else
+ return -EILSEQ;
+ }
+
+ return -EILSEQ;
+}
+
+static int write_cmd(int fd, uint8_t *buffer, int len)
+{
+ uint8_t *event;
+ int err;
+
+ err = send_hci_cmd_sync(fd, buffer, len, &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+ free(event);
+
+ return err;
+}
+
+#define PS_WRITE 1
+#define PS_RESET 2
+#define WRITE_PATCH 8
+#define ENABLE_PATCH 11
+
+#define HCI_PS_CMD_HDR_LEN 7
+
+#define PS_RESET_PARAM_LEN 6
+#define HCI_MAX_CMD_SIZE 260
+#define PS_RESET_CMD_LEN (HCI_PS_CMD_HDR_LEN + PS_RESET_PARAM_LEN)
+
+#define PS_ID_MASK 0xFF
+
+/* Sends PS commands using vendor specficic HCI commands */
+static int write_ps_cmd(int fd, uint8_t opcode, uint32_t ps_param)
+{
+ uint8_t cmd[HCI_MAX_CMD_SIZE];
+ uint32_t i;
+
+ switch (opcode) {
+ case ENABLE_PATCH:
+ load_hci_ps_hdr(cmd, opcode, 0, 0x00);
+
+ if (write_cmd(fd, cmd, HCI_PS_CMD_HDR_LEN) < 0)
+ return -EILSEQ;
+ break;
+
+ case PS_RESET:
+ load_hci_ps_hdr(cmd, opcode, PS_RESET_PARAM_LEN, 0x00);
+
+ cmd[7] = 0x00;
+ cmd[PS_RESET_CMD_LEN - 2] = ps_param & PS_ID_MASK;
+ cmd[PS_RESET_CMD_LEN - 1] = (ps_param >> 8) & PS_ID_MASK;
+
+ if (write_cmd(fd, cmd, PS_RESET_CMD_LEN) < 0)
+ return -EILSEQ;
+ break;
+
+ case PS_WRITE:
+ for (i = 0; i < ps_param; i++) {
+ load_hci_ps_hdr(cmd, opcode, ps_list[i].len,
+ ps_list[i].id);
+
+ memcpy(&cmd[HCI_PS_CMD_HDR_LEN], ps_list[i].data,
+ ps_list[i].len);
+
+ if (write_cmd(fd, cmd, ps_list[i].len +
+ HCI_PS_CMD_HDR_LEN) < 0)
+ return -EILSEQ;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#define __is_delim(ch) ((ch) == ':')
+#define MAX_PREAMBLE_LEN 4
+
+/* Parse PS entry preamble of format [X:X] for main type and subtype */
+static int get_ps_type(char *ptr, int index, char *type, char *sub_type)
+{
+ int i;
+ int delim = FALSE;
+
+ if (index > MAX_PREAMBLE_LEN)
+ return -EILSEQ;
+
+ for (i = 1; i < index; i++) {
+ if (__is_delim(ptr[i])) {
+ delim = TRUE;
+ continue;
+ }
+
+ if (isalpha(ptr[i])) {
+ if (delim == FALSE)
+ (*type) = toupper(ptr[i]);
+ else
+ (*sub_type) = toupper(ptr[i]);
+ }
+ }
+
+ return 0;
+}
+
+#define ARRAY 'A'
+#define STRING 'S'
+#define DECIMAL 'D'
+#define BINARY 'B'
+
+#define PS_HEX 0
+#define PS_DEC 1
+
+static int get_input_format(char *buf, struct ps_entry_type *format)
+{
+ char *ptr = NULL;
+ char type = '\0';
+ char sub_type = '\0';
+
+ format->type = PS_HEX;
+ format->array = TRUE;
+
+ if (strstr(buf, "[") != buf)
+ return 0;
+
+ ptr = strstr(buf, "]");
+ if (!ptr)
+ return -EILSEQ;
+
+ if (get_ps_type(buf, ptr - buf, &type, &sub_type) < 0)
+ return -EILSEQ;
+
+ /* Check is data type is of array */
+ if (type == ARRAY || sub_type == ARRAY)
+ format->array = TRUE;
+
+ if (type == STRING || sub_type == STRING)
+ format->array = FALSE;
+
+ if (type == DECIMAL || type == BINARY)
+ format->type = PS_DEC;
+ else
+ format->type = PS_HEX;
+
+ return 0;
+}
+
+#define UNDEFINED 0xFFFF
+
+static unsigned int read_data_in_section(char *buf, struct ps_entry_type type)
+{
+ char *ptr = buf;
+
+ if (!buf)
+ return UNDEFINED;
+
+ if (buf == strstr(buf, "[")) {
+ ptr = strstr(buf, "]");
+ if (!ptr)
+ return UNDEFINED;
+
+ ptr++;
+ }
+
+ if (type.type == PS_HEX && type.array != TRUE)
+ return strtol(ptr, NULL, 16);
+
+ return UNDEFINED;
+}
+
+struct tag_info {
+ unsigned section;
+ unsigned line_count;
+ unsigned char_cnt;
+ unsigned byte_count;
+};
+
+static inline int update_char_count(const char *buf)
+{
+ char *end_ptr;
+
+ if (strstr(buf, "[") == buf) {
+ end_ptr = strstr(buf, "]");
+ if (!end_ptr)
+ return 0;
+ else
+ return (end_ptr - buf) + 1;
+ }
+
+ return 0;
+}
+
+/* Read PS entries as string, convert and add to Hex array */
+static void update_tag_data(struct ps_cfg_entry *tag,
+ struct tag_info *info, const char *ptr)
+{
+ char buf[3];
+
+ buf[2] = '\0';
+
+ strncpy(buf, &ptr[info->char_cnt], 2);
+ tag->data[info->byte_count] = strtol(buf, NULL, 16);
+ info->char_cnt += 3;
+ info->byte_count++;
+
+ strncpy(buf, &ptr[info->char_cnt], 2);
+ tag->data[info->byte_count] = strtol(buf, NULL, 16);
+ info->char_cnt += 3;
+ info->byte_count++;
+}
+
+#define PS_UNDEF 0
+#define PS_ID 1
+#define PS_LEN 2
+#define PS_DATA 3
+
+#define PS_MAX_LEN 500
+#define LINE_SIZE_MAX (PS_MAX_LEN * 2)
+#define ENTRY_PER_LINE 16
+
+#define __check_comment(buf) (((buf)[0] == '/') && ((buf)[1] == '/'))
+#define __skip_space(str) while (*(str) == ' ') ((str)++)
+
+static int ath_parse_ps(FILE *stream)
+{
+ char buf[LINE_SIZE_MAX + 1];
+ char *ptr;
+ uint8_t tag_cnt = 0;
+ int16_t byte_count = 0;
+ struct ps_entry_type format;
+ struct tag_info status = { 0, 0, 0, 0 };
+
+ do {
+ int read_count;
+ struct ps_cfg_entry *tag;
+
+ ptr = fgets(buf, LINE_SIZE_MAX, stream);
+ if (!ptr)
+ break;
+
+ __skip_space(ptr);
+ if (__check_comment(ptr))
+ continue;
+
+ /* Lines with a '#' will be followed by new PS entry */
+ if (ptr == strstr(ptr, "#")) {
+ if (status.section != PS_UNDEF) {
+ return -EILSEQ;
+ } else {
+ status.section = PS_ID;
+ continue;
+ }
+ }
+
+ tag = &ps_list[tag_cnt];
+
+ switch (status.section) {
+ case PS_ID:
+ if (get_input_format(ptr, &format) < 0)
+ return -EILSEQ;
+
+ tag->id = read_data_in_section(ptr, format);
+ status.section = PS_LEN;
+ break;
+
+ case PS_LEN:
+ if (get_input_format(ptr, &format) < 0)
+ return -EILSEQ;
+
+ byte_count = read_data_in_section(ptr, format);
+ if (byte_count > PS_MAX_LEN)
+ return -EILSEQ;
+
+ tag->len = byte_count;
+ tag->data = (uint8_t *)malloc(byte_count);
+
+ status.section = PS_DATA;
+ status.line_count = 0;
+ break;
+
+ case PS_DATA:
+ if (status.line_count == 0)
+ if (get_input_format(ptr, &format) < 0)
+ return -EILSEQ;
+
+ __skip_space(ptr);
+
+ status.char_cnt = update_char_count(ptr);
+
+ read_count = (byte_count > ENTRY_PER_LINE) ?
+ ENTRY_PER_LINE : byte_count;
+
+ if (format.type == PS_HEX && format.array == TRUE) {
+ while (read_count > 0) {
+ update_tag_data(tag, &status, ptr);
+ read_count -= 2;
+ }
+
+ if (byte_count > ENTRY_PER_LINE)
+ byte_count -= ENTRY_PER_LINE;
+ else
+ byte_count = 0;
+ }
+
+ status.line_count++;
+
+ if (byte_count == 0)
+ memset(&status, 0x00, sizeof(struct tag_info));
+
+ if (status.section == PS_UNDEF)
+ tag_cnt++;
+
+ if (tag_cnt == MAX_TAGS)
+ return -EILSEQ;
+ break;
+ }
+ } while (ptr);
+
+ return tag_cnt;
+}
+
+#define MAX_PATCH_CMD 244
+struct patch_entry {
+ int16_t len;
+ uint8_t data[MAX_PATCH_CMD];
+};
+
+#define SET_PATCH_RAM_ID 0x0D
+#define SET_PATCH_RAM_CMD_SIZE 11
+#define ADDRESS_LEN 4
+static int set_patch_ram(int dev, char *patch_loc, int len)
+{
+ int err;
+ uint8_t cmd[20];
+ int i, j;
+ char loc_byte[3];
+ uint8_t *event;
+ uint8_t *loc_ptr = &cmd[7];
+
+ if (!patch_loc)
+ return -1;
+
+ loc_byte[2] = '\0';
+
+ load_hci_ps_hdr(cmd, SET_PATCH_RAM_ID, ADDRESS_LEN, 0);
+
+ for (i = 0, j = 3; i < 4; i++, j--) {
+ loc_byte[0] = patch_loc[0];
+ loc_byte[1] = patch_loc[1];
+ loc_ptr[j] = strtol(loc_byte, NULL, 16);
+ patch_loc += 2;
+ }
+
+ err = send_hci_cmd_sync(dev, cmd, SET_PATCH_RAM_CMD_SIZE, &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+ free(event);
+
+ return err;
+}
+
+#define PATCH_LOC_KEY "DA:"
+#define PATCH_LOC_STRING_LEN 8
+static int ps_patch_download(int fd, FILE *stream)
+{
+ char byte[3];
+ char ptr[MAX_PATCH_CMD + 1];
+ int byte_cnt;
+ int patch_count = 0;
+ char patch_loc[PATCH_LOC_STRING_LEN + 1];
+
+ byte[2] = '\0';
+
+ while (fgets(ptr, MAX_PATCH_CMD, stream)) {
+ if (strlen(ptr) <= 1)
+ continue;
+ else if (strstr(ptr, PATCH_LOC_KEY) == ptr) {
+ strncpy(patch_loc, &ptr[sizeof(PATCH_LOC_KEY) - 1],
+ PATCH_LOC_STRING_LEN);
+ if (set_patch_ram(fd, patch_loc, sizeof(patch_loc)) < 0)
+ return -1;
+ } else if (isxdigit(ptr[0]))
+ break;
+ else
+ return -1;
+ }
+
+ byte_cnt = strtol(ptr, NULL, 16);
+
+ while (byte_cnt > 0) {
+ int i;
+ uint8_t cmd[HCI_MAX_CMD_SIZE];
+ struct patch_entry patch;
+
+ if (byte_cnt > MAX_PATCH_CMD)
+ patch.len = MAX_PATCH_CMD;
+ else
+ patch.len = byte_cnt;
+
+ for (i = 0; i < patch.len; i++) {
+ if (!fgets(byte, 3, stream))
+ return -1;
+
+ patch.data[i] = strtoul(byte, NULL, 16);
+ }
+
+ load_hci_ps_hdr(cmd, WRITE_PATCH, patch.len, patch_count);
+ memcpy(&cmd[HCI_PS_CMD_HDR_LEN], patch.data, patch.len);
+
+ if (write_cmd(fd, cmd, patch.len + HCI_PS_CMD_HDR_LEN) < 0)
+ return -1;
+
+ patch_count++;
+ byte_cnt = byte_cnt - MAX_PATCH_CMD;
+ }
+
+ if (write_ps_cmd(fd, ENABLE_PATCH, 0) < 0)
+ return -1;
+
+ return patch_count;
+}
+
+#define PS_RAM_SIZE 2048
+
+static int ps_config_download(int fd, int tag_count)
+{
+ if (write_ps_cmd(fd, PS_RESET, PS_RAM_SIZE) < 0)
+ return -1;
+
+ if (tag_count > 0)
+ if (write_ps_cmd(fd, PS_WRITE, tag_count) < 0)
+ return -1;
+ return 0;
+}
+
+#define PS_ASIC_FILE "PS_ASIC.pst"
+#define PS_FPGA_FILE "PS_FPGA.pst"
+
+static void get_ps_file_name(uint32_t devtype, uint32_t rom_version,
+ char *path)
+{
+ char *filename;
+
+ if (devtype == 0xdeadc0de)
+ filename = PS_ASIC_FILE;
+ else
+ filename = PS_FPGA_FILE;
+
+ snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, filename);
+}
+
+#define PATCH_FILE "RamPatch.txt"
+#define FPGA_ROM_VERSION 0x99999999
+#define ROM_DEV_TYPE 0xdeadc0de
+
+static void get_patch_file_name(uint32_t dev_type, uint32_t rom_version,
+ uint32_t build_version, char *path)
+{
+ if (rom_version == FPGA_ROM_VERSION && dev_type != ROM_DEV_TYPE &&
+ dev_type != 0 && build_version == 1)
+ path[0] = '\0';
+ else
+ snprintf(path, MAXPATHLEN, "%s%x/%s",
+ FW_PATH, rom_version, PATCH_FILE);
+}
+
+#define VERIFY_CRC 9
+#define PS_REGION 1
+#define PATCH_REGION 2
+
+static int get_ath3k_crc(int dev)
+{
+ uint8_t cmd[7];
+ uint8_t *event;
+ int err;
+
+ load_hci_ps_hdr(cmd, VERIFY_CRC, 0, PS_REGION | PATCH_REGION);
+
+ err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event);
+ if (err < 0)
+ return err;
+ /* Send error code if CRC check patched */
+ if (read_ps_event(event, HCI_PS_CMD_OCF) >= 0)
+ err = -EILSEQ;
+
+ free(event);
+
+ return err;
+}
+
+#define DEV_REGISTER 0x4FFC
+#define GET_DEV_TYPE_OCF 0x05
+
+static int get_device_type(int dev, uint32_t *code)
+{
+ uint8_t cmd[8];
+ uint8_t *event;
+ uint32_t reg;
+ int err;
+ uint8_t *ptr = cmd;
+ hci_command_hdr *ch = (void *)cmd;
+
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ GET_DEV_TYPE_OCF));
+ ch->plen = 5;
+ ptr += HCI_COMMAND_HDR_SIZE;
+
+ ptr[0] = (uint8_t)DEV_REGISTER;
+ ptr[1] = (uint8_t)DEV_REGISTER >> 8;
+ ptr[2] = (uint8_t)DEV_REGISTER >> 16;
+ ptr[3] = (uint8_t)DEV_REGISTER >> 24;
+ ptr[4] = 0x04;
+
+ err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, GET_DEV_TYPE_OCF);
+ if (err < 0)
+ goto cleanup;
+
+ reg = event[10];
+ reg = (reg << 8) | event[9];
+ reg = (reg << 8) | event[8];
+ reg = (reg << 8) | event[7];
+ *code = reg;
+
+cleanup:
+ free(event);
+
+ return err;
+}
+
+#define GET_VERSION_OCF 0x1E
+
+static int read_ath3k_version(int pConfig, uint32_t *rom_version,
+ uint32_t *build_version)
+{
+ uint8_t cmd[3];
+ uint8_t *event;
+ int err;
+ int status;
+ hci_command_hdr *ch = (void *)cmd;
+
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ GET_VERSION_OCF));
+ ch->plen = 0;
+
+ err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, GET_VERSION_OCF);
+ if (err < 0)
+ goto cleanup;
+
+ status = event[10];
+ status = (status << 8) | event[9];
+ status = (status << 8) | event[8];
+ status = (status << 8) | event[7];
+ *rom_version = status;
+
+ status = event[14];
+ status = (status << 8) | event[13];
+ status = (status << 8) | event[12];
+ status = (status << 8) | event[11];
+ *build_version = status;
+
+cleanup:
+ free(event);
+
+ return err;
+}
+
+static void convert_bdaddr(char *str_bdaddr, char *bdaddr)
+{
+ char bdbyte[3];
+ char *str_byte = str_bdaddr;
+ int i, j;
+ int colon_present = 0;
+
+ if (strstr(str_bdaddr, ":"))
+ colon_present = 1;
+
+ bdbyte[2] = '\0';
+
+ /* Reverse the BDADDR to LSB first */
+ for (i = 0, j = 5; i < 6; i++, j--) {
+ bdbyte[0] = str_byte[0];
+ bdbyte[1] = str_byte[1];
+ bdaddr[j] = strtol(bdbyte, NULL, 16);
+
+ if (colon_present == 1)
+ str_byte += 3;
+ else
+ str_byte += 2;
+ }
+}
+
+static int write_bdaddr(int pConfig, char *bdaddr)
+{
+ uint8_t *event;
+ int err;
+ uint8_t cmd[13];
+ uint8_t *ptr = cmd;
+ hci_command_hdr *ch = (void *)cmd;
+
+ memset(cmd, 0, sizeof(cmd));
+
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ HCI_PS_CMD_OCF));
+ ch->plen = 10;
+ ptr += HCI_COMMAND_HDR_SIZE;
+
+ ptr[0] = 0x01;
+ ptr[1] = 0x01;
+ ptr[2] = 0x00;
+ ptr[3] = 0x06;
+
+ convert_bdaddr(bdaddr, (char *)&ptr[4]);
+
+ err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event);
+ if (err < 0)
+ return err;
+
+ err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+ free(event);
+
+ return err;
+}
+
+#define BDADDR_FILE "ar3kbdaddr.pst"
+
+static void write_bdaddr_from_file(int rom_version, int fd)
+{
+ FILE *stream;
+ char bdaddr[PATH_MAX];
+ char bdaddr_file[PATH_MAX];
+
+ snprintf(bdaddr_file, MAXPATHLEN, "%s%x/%s",
+ FW_PATH, rom_version, BDADDR_FILE);
+
+ stream = fopen(bdaddr_file, "r");
+ if (!stream)
+ return;
+
+ if (fgets(bdaddr, PATH_MAX - 1, stream))
+ write_bdaddr(fd, bdaddr);
+
+ fclose(stream);
+}
+
+static int ath_ps_download(int fd)
+{
+ int err = 0;
+ int tag_count;
+ int patch_count = 0;
+ uint32_t rom_version = 0;
+ uint32_t build_version = 0;
+ uint32_t dev_type = 0;
+ char patch_file[PATH_MAX];
+ char ps_file[PATH_MAX];
+ FILE *stream;
+
+ /*
+ * Verfiy firmware version. depending on it select the PS
+ * config file to download.
+ */
+ if (get_device_type(fd, &dev_type) < 0) {
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+
+ if (read_ath3k_version(fd, &rom_version, &build_version) < 0) {
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+
+ /* Do not download configuration if CRC passes */
+ if (get_ath3k_crc(fd) < 0) {
+ err = 0;
+ goto download_cmplete;
+ }
+
+ get_ps_file_name(dev_type, rom_version, ps_file);
+ get_patch_file_name(dev_type, rom_version, build_version, patch_file);
+
+ stream = fopen(ps_file, "r");
+ if (!stream) {
+ perror("firmware file open error\n");
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+ tag_count = ath_parse_ps(stream);
+
+ fclose(stream);
+
+ if (tag_count < 0) {
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+
+ /*
+ * It is not necessary that Patch file be available,
+ * continue with PS Operations if patch file is not available.
+ */
+ if (patch_file[0] == '\0')
+ err = 0;
+
+ stream = fopen(patch_file, "r");
+ if (!stream)
+ err = 0;
+ else {
+ patch_count = ps_patch_download(fd, stream);
+ fclose(stream);
+
+ if (patch_count < 0) {
+ err = -EILSEQ;
+ goto download_cmplete;
+ }
+ }
+
+ err = ps_config_download(fd, tag_count);
+
+download_cmplete:
+ if (!err)
+ write_bdaddr_from_file(rom_version, fd);
+
+ return err;
+}
+
+#define HCI_SLEEP_CMD_OCF 0x04
+
+/*
+ * Atheros AR300x specific initialization post callback
+ */
+int ath3k_post(int fd, int pm)
+{
+ int dev_id, dd;
+ struct timespec tm = { 0, 50000 };
+
+ sleep(1);
+
+ dev_id = ioctl(fd, HCIUARTGETDEVICE, 0);
+ if (dev_id < 0) {
+ perror("cannot get device id");
+ return dev_id;
+ }
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("HCI device open failed");
+ return dd;
+ }
+
+ if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) {
+ perror("hci down:Power management Disabled");
+ hci_close_dev(dd);
+ return -1;
+ }
+
+ /* send vendor specific command with Sleep feature Enabled */
+ if (hci_send_cmd(dd, OGF_VENDOR_CMD, HCI_SLEEP_CMD_OCF, 1, &pm) < 0)
+ perror("PM command failed, power management Disabled");
+
+ nanosleep(&tm, NULL);
+ hci_close_dev(dd);
+
+ return 0;
+}
+
+#define HCI_VENDOR_CMD_OGF 0x3F
+#define HCI_PS_CMD_OCF 0x0B
+#define HCI_CHG_BAUD_CMD_OCF 0x0C
+
+#define WRITE_BDADDR_CMD_LEN 14
+#define WRITE_BAUD_CMD_LEN 6
+#define MAX_CMD_LEN WRITE_BDADDR_CMD_LEN
+
+static int set_cntrlr_baud(int fd, int speed)
+{
+ int baud;
+ struct timespec tm = { 0, 500000 };
+ unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE];
+ unsigned char *ptr = cmd + 1;
+ hci_command_hdr *ch = (void *)ptr;
+
+ cmd[0] = HCI_COMMAND_PKT;
+
+ /* set controller baud rate to user specified value */
+ ptr = cmd + 1;
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ HCI_CHG_BAUD_CMD_OCF));
+ ch->plen = 2;
+ ptr += HCI_COMMAND_HDR_SIZE;
+
+ baud = speed/100;
+ ptr[0] = (char)baud;
+ ptr[1] = (char)(baud >> 8);
+
+ if (write(fd, cmd, WRITE_BAUD_CMD_LEN) != WRITE_BAUD_CMD_LEN) {
+ perror("Failed to write change baud rate command");
+ return -ETIMEDOUT;
+ }
+
+ nanosleep(&tm, NULL);
+
+ if (read_hci_event(fd, rsp, sizeof(rsp)) < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/*
+ * Atheros AR300x specific initialization and configuration file
+ * download
+ */
+int ath3k_init(int fd, int speed, int init_speed, char *bdaddr,
+ struct termios *ti)
+{
+ int r;
+ int err = 0;
+ struct timespec tm = { 0, 500000 };
+ unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE];
+ unsigned char *ptr = cmd + 1;
+ hci_command_hdr *ch = (void *)ptr;
+
+ cmd[0] = HCI_COMMAND_PKT;
+
+ /* set both controller and host baud rate to maximum possible value */
+ err = set_cntrlr_baud(fd, speed);
+ if (err < 0)
+ return err;
+
+ err = set_speed(fd, ti, speed);
+ if (err < 0) {
+ perror("Can't set required baud rate");
+ return err;
+ }
+
+ /* Download PS and patch */
+ r = ath_ps_download(fd);
+ if (r < 0) {
+ perror("Failed to Download configuration");
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+
+ /* Write BDADDR */
+ if (bdaddr) {
+ ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+ HCI_PS_CMD_OCF));
+ ch->plen = 10;
+ ptr += HCI_COMMAND_HDR_SIZE;
+
+ ptr[0] = 0x01;
+ ptr[1] = 0x01;
+ ptr[2] = 0x00;
+ ptr[3] = 0x06;
+ str2ba(bdaddr, (bdaddr_t *)(ptr + 4));
+
+ if (write(fd, cmd, WRITE_BDADDR_CMD_LEN) !=
+ WRITE_BDADDR_CMD_LEN) {
+ perror("Failed to write BD_ADDR command\n");
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+
+ if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) {
+ perror("Failed to set BD_ADDR\n");
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+ }
+
+ /* Send HCI Reset */
+ cmd[1] = 0x03;
+ cmd[2] = 0x0C;
+ cmd[3] = 0x00;
+
+ r = write(fd, cmd, 4);
+ if (r != 4) {
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+
+ nanosleep(&tm, NULL);
+ if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) {
+ err = -ETIMEDOUT;
+ goto failed;
+ }
+
+ err = set_cntrlr_baud(fd, speed);
+ if (err < 0)
+ return err;
+
+failed:
+ if (err < 0) {
+ set_cntrlr_baud(fd, init_speed);
+ set_speed(fd, ti, init_speed);
+ }
+
+ return err;
+}
diff --git a/external/cache/sources/hcitools/hciattach_bcm43xx.c b/external/cache/sources/hcitools/hciattach_bcm43xx.c
new file mode 100644
index 0000000..ad9b239
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_bcm43xx.c
@@ -0,0 +1,378 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#ifndef FIRMWARE_DIR
+#define FIRMWARE_DIR "/etc/firmware"
+#endif
+
+#define FW_EXT ".hcd"
+
+#define BCM43XX_CLOCK_48 1
+#define BCM43XX_CLOCK_24 2
+
+#define CMD_SUCCESS 0x00
+
+#define CC_MIN_SIZE 7
+
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+
+static int bcm43xx_read_local_name(int fd, char *name, size_t size)
+{
+ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x14, 0x0C, 0x00 };
+ unsigned char *resp;
+ unsigned int name_len;
+
+ resp = malloc(size + CC_MIN_SIZE);
+ if (!resp)
+ return -1;
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write read local name command\n");
+ goto fail;
+ }
+
+ if (read_hci_event(fd, resp, size) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to read local name, invalid HCI event\n");
+ goto fail;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to read local name, command failure\n");
+ goto fail;
+ }
+
+ name_len = resp[2] - 1;
+
+ strncpy(name, (char *) &resp[7], MIN(name_len, size));
+ name[size - 1] = 0;
+
+ free(resp);
+ return 0;
+
+fail:
+ free(resp);
+ return -1;
+}
+
+static int bcm43xx_reset(int fd)
+{
+ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x03, 0x0C, 0x00 };
+ unsigned char resp[CC_MIN_SIZE];
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write reset command\n");
+ return -1;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to reset chip, invalid HCI event\n");
+ return -1;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to reset chip, command failure\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_set_bdaddr(int fd, const char *bdaddr)
+{
+ unsigned char cmd[] =
+ { HCI_COMMAND_PKT, 0x01, 0xfc, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+ unsigned char resp[CC_MIN_SIZE];
+
+ printf("Set BDADDR UART: %s\n", bdaddr);
+
+ if (str2ba(bdaddr, (bdaddr_t *) (&cmd[4])) < 0) {
+ fprintf(stderr, "Incorrect bdaddr\n");
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write set bdaddr command\n");
+ return -1;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to set bdaddr, invalid HCI event\n");
+ return -1;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to set bdaddr, command failure\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_set_speed(int fd, uint32_t speed)
+{
+ unsigned char cmd[] =
+ { HCI_COMMAND_PKT, 0x18, 0xfc, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+ unsigned char resp[CC_MIN_SIZE];
+
+ printf("Set Controller UART speed to %d bit/s\n", speed);
+
+ cmd[6] = (uint8_t) (speed);
+ cmd[7] = (uint8_t) (speed >> 8);
+ cmd[8] = (uint8_t) (speed >> 16);
+ cmd[9] = (uint8_t) (speed >> 24);
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write update baudrate command\n");
+ return -1;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to update baudrate, invalid HCI event\n");
+ return -1;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to update baudrate, command failure\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_set_clock(int fd, unsigned char clock)
+{
+ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x45, 0xfc, 0x01, 0x00 };
+ unsigned char resp[CC_MIN_SIZE];
+
+ printf("Set Controller clock (%d)\n", clock);
+
+ cmd[4] = clock;
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write update clock command\n");
+ return -1;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to update clock, invalid HCI event\n");
+ return -1;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to update clock, command failure\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_load_firmware(int fd, const char *fw)
+{
+ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x2e, 0xfc, 0x00 };
+ struct timespec tm_mode = { 0, 50000 };
+ struct timespec tm_ready = { 0, 2000000 };
+ unsigned char resp[CC_MIN_SIZE];
+ unsigned char tx_buf[1024];
+ int len, fd_fw, n;
+
+ printf("Flash firmware %s\n", fw);
+
+ fd_fw = open(fw, O_RDONLY);
+ if (fd_fw < 0) {
+ fprintf(stderr, "Unable to open firmware (%s)\n", fw);
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
+ fprintf(stderr, "Failed to write download mode command\n");
+ goto fail;
+ }
+
+ if (read_hci_event(fd, resp, sizeof(resp)) < CC_MIN_SIZE) {
+ fprintf(stderr, "Failed to load firmware, invalid HCI event\n");
+ goto fail;
+ }
+
+ if (resp[4] != cmd[1] || resp[5] != cmd[2] || resp[6] != CMD_SUCCESS) {
+ fprintf(stderr, "Failed to load firmware, command failure\n");
+ goto fail;
+ }
+
+ /* Wait 50ms to let the firmware placed in download mode */
+ nanosleep(&tm_mode, NULL);
+
+ tcflush(fd, TCIOFLUSH);
+
+ while ((n = read(fd_fw, &tx_buf[1], 3))) {
+ if (n < 0) {
+ fprintf(stderr, "Failed to read firmware\n");
+ goto fail;
+ }
+
+ tx_buf[0] = HCI_COMMAND_PKT;
+
+ len = tx_buf[3];
+
+ if (read(fd_fw, &tx_buf[4], len) < 0) {
+ fprintf(stderr, "Failed to read firmware\n");
+ goto fail;
+ }
+
+ if (write(fd, tx_buf, len + 4) != (len + 4)) {
+ fprintf(stderr, "Failed to write firmware\n");
+ goto fail;
+ }
+
+ read_hci_event(fd, resp, sizeof(resp));
+ tcflush(fd, TCIOFLUSH);
+ }
+
+ /* Wait for firmware ready */
+ nanosleep(&tm_ready, NULL);
+
+ close(fd_fw);
+ return 0;
+
+fail:
+ close(fd_fw);
+ return -1;
+}
+
+static int bcm43xx_locate_patch(const char *dir_name,
+ const char *chip_name, char *location)
+{
+ DIR *dir;
+ int ret = -1;
+
+ dir = opendir(dir_name);
+ if (!dir) {
+ fprintf(stderr, "Cannot open directory '%s': %s\n",
+ dir_name, strerror(errno));
+ return -1;
+ }
+
+ /* Recursively look for a BCM43XX*.hcd */
+ while (1) {
+ struct dirent *entry = readdir(dir);
+ if (!entry)
+ break;
+
+ if (entry->d_type & DT_DIR) {
+ char path[PATH_MAX];
+
+ if (!strcmp(entry->d_name, "..") || !strcmp(entry->d_name, "."))
+ continue;
+
+ snprintf(path, PATH_MAX, "%s/%s", dir_name, entry->d_name);
+
+ ret = bcm43xx_locate_patch(path, chip_name, location);
+ if (!ret)
+ break;
+ } else if (!strncmp(chip_name, entry->d_name, strlen(chip_name))) {
+ unsigned int name_len = strlen(entry->d_name);
+ size_t curs_ext = name_len - sizeof(FW_EXT) + 1;
+
+ if (curs_ext > name_len)
+ break;
+
+ if (strncmp(FW_EXT, &entry->d_name[curs_ext], sizeof(FW_EXT)))
+ break;
+
+ /* found */
+ snprintf(location, PATH_MAX, "%s/%s", dir_name, entry->d_name);
+ ret = 0;
+ break;
+ }
+ }
+
+ closedir(dir);
+
+ return ret;
+}
+
+int bcm43xx_init(int fd, int speed, struct termios *ti, const char *bdaddr)
+{
+ char chip_name[20];
+ char fw_path[PATH_MAX];
+
+ printf("bcm43xx_init\n");
+
+ if (bcm43xx_reset(fd))
+ return -1;
+
+ if (bcm43xx_read_local_name(fd, chip_name, sizeof(chip_name)))
+ return -1;
+
+ if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {
+ fprintf(stderr, "Patch not found, continue anyway\n");
+ } else {
+ if (bcm43xx_load_firmware(fd, fw_path))
+ return -1;
+
+ if (bcm43xx_reset(fd))
+ return -1;
+ }
+
+ if (bdaddr)
+ bcm43xx_set_bdaddr(fd, bdaddr);
+
+ if (speed > 3000000 && bcm43xx_set_clock(fd, BCM43XX_CLOCK_48))
+ return -1;
+
+ if (bcm43xx_set_speed(fd, speed))
+ return -1;
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_intel.c b/external/cache/sources/hcitools/hciattach_intel.c
new file mode 100644
index 0000000..749098e
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_intel.c
@@ -0,0 +1,595 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#ifdef INTEL_DEBUG
+#define DBGPRINT(fmt, args...) printf("DBG: " fmt "\n", ## args)
+#define PRINT_PACKET(buf, len, msg) { \
+ int i; \
+ printf("%s\n", msg); \
+ for (i = 0; i < len; i++) \
+ printf("%02X ", buf[i]); \
+ printf("\n"); \
+ }
+#else
+#define DBGPRINT(fmt, args...)
+#define PRINT_PACKET(buf, len, msg)
+#endif
+
+#define PATCH_SEQ_EXT ".bseq"
+#define PATCH_FILE_PATH "/lib/firmware/intel/"
+#define PATCH_MAX_LEN 260
+#define PATCH_TYPE_CMD 1
+#define PATCH_TYPE_EVT 2
+
+#define INTEL_VER_PARAM_LEN 9
+#define INTEL_MFG_PARAM_LEN 2
+
+/**
+ * A data structure for a patch entry.
+ */
+struct patch_entry {
+ int type;
+ int len;
+ unsigned char data[PATCH_MAX_LEN];
+};
+
+/**
+ * A structure for patch context
+ */
+struct patch_ctx {
+ int dev;
+ int fd;
+ int patch_error;
+ int reset_enable_patch;
+};
+
+/**
+ * Send HCI command to the controller
+ */
+static int intel_write_cmd(int dev, unsigned char *buf, int len)
+{
+ int ret;
+
+ PRINT_PACKET(buf, len, "<----- SEND CMD: ");
+
+ ret = write(dev, buf, len);
+ if (ret < 0)
+ return -errno;
+
+ if (ret != len)
+ return -1;
+
+ return ret;
+}
+
+/**
+ * Read the event from the controller
+ */
+static int intel_read_evt(int dev, unsigned char *buf, int len)
+{
+ int ret;
+
+ ret = read_hci_event(dev, buf, len);
+ if (ret < 0)
+ return -1;
+
+ PRINT_PACKET(buf, ret, "-----> READ EVT: ");
+
+ return ret;
+}
+
+/**
+ * Validate HCI events
+ */
+static int validate_events(struct patch_entry *event,
+ struct patch_entry *entry)
+{
+ if (event == NULL || entry == NULL) {
+ DBGPRINT("invalid patch entry parameters");
+ return -1;
+ }
+
+ if (event->len != entry->len) {
+ DBGPRINT("lengths are mismatched:[%d|%d]",
+ event->len, entry->len);
+ return -1;
+ }
+
+ if (memcmp(event->data, entry->data, event->len)) {
+ DBGPRINT("data is mismatched");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Read the next patch entry one line at a time
+ */
+static int get_next_patch_entry(int fd, struct patch_entry *entry)
+{
+ int size;
+ char rb;
+
+ if (read(fd, &rb, 1) <= 0)
+ return 0;
+
+ entry->type = rb;
+
+ switch (entry->type) {
+ case PATCH_TYPE_CMD:
+ entry->data[0] = HCI_COMMAND_PKT;
+
+ if (read(fd, &entry->data[1], 3) < 0)
+ return -1;
+
+ size = (int)entry->data[3];
+
+ if (read(fd, &entry->data[4], size) < 0)
+ return -1;
+
+ entry->len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + size;
+
+ break;
+
+ case PATCH_TYPE_EVT:
+ entry->data[0] = HCI_EVENT_PKT;
+
+ if (read(fd, &entry->data[1], 2) < 0)
+ return -1;
+
+ size = (int)entry->data[2];
+
+ if (read(fd, &entry->data[3], size) < 0)
+ return -1;
+
+ entry->len = HCI_TYPE_LEN + HCI_EVENT_HDR_SIZE + size;
+
+ break;
+
+ default:
+ fprintf(stderr, "invalid patch entry(%d)\n", entry->type);
+ return -1;
+ }
+
+ return entry->len;
+}
+
+/**
+ * Download the patch set to the controller and verify the event
+ */
+static int intel_download_patch(struct patch_ctx *ctx)
+{
+ int ret;
+ struct patch_entry entry;
+ struct patch_entry event;
+
+ DBGPRINT("start patch downloading");
+
+ do {
+ ret = get_next_patch_entry(ctx->fd, &entry);
+ if (ret <= 0) {
+ ctx->patch_error = 1;
+ break;
+ }
+
+ switch (entry.type) {
+ case PATCH_TYPE_CMD:
+ ret = intel_write_cmd(ctx->dev,
+ entry.data,
+ entry.len);
+ if (ret <= 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n",
+ ret);
+ return ret;
+ }
+ break;
+
+ case PATCH_TYPE_EVT:
+ ret = intel_read_evt(ctx->dev, event.data,
+ sizeof(event.data));
+ if (ret <= 0) {
+ fprintf(stderr, "failed to read evt(%d)\n",
+ ret);
+ return ret;
+ }
+ event.len = ret;
+
+ if (validate_events(&event, &entry) < 0) {
+ DBGPRINT("events are mismatched");
+ ctx->patch_error = 1;
+ return -1;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "unknown patch type(%d)\n",
+ entry.type);
+ return -1;
+ }
+ } while (1);
+
+ return ret;
+}
+
+static int open_patch_file(struct patch_ctx *ctx, char *fw_ver)
+{
+ char patch_file[PATH_MAX];
+
+ snprintf(patch_file, PATH_MAX, "%s%s%s", PATCH_FILE_PATH,
+ fw_ver, PATCH_SEQ_EXT);
+ DBGPRINT("PATCH_FILE: %s", patch_file);
+
+ ctx->fd = open(patch_file, O_RDONLY);
+ if (ctx->fd < 0) {
+ DBGPRINT("cannot open patch file. go to post patch");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Prepare the controller for patching.
+ */
+static int pre_patch(struct patch_ctx *ctx)
+{
+ int ret, i;
+ struct patch_entry entry;
+ char fw_ver[INTEL_VER_PARAM_LEN * 2];
+
+ DBGPRINT("start pre_patch");
+
+ entry.data[0] = HCI_COMMAND_PKT;
+ entry.data[1] = 0x11;
+ entry.data[2] = 0xFC;
+ entry.data[3] = 0x02;
+ entry.data[4] = 0x01;
+ entry.data[5] = 0x00;
+ entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + INTEL_MFG_PARAM_LEN;
+
+ ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
+ if (ret < 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n", ret);
+ return ret;
+ }
+
+ ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read evt(%d)\n", ret);
+ return ret;
+ }
+ entry.len = ret;
+
+ if (entry.data[6] != 0x00) {
+ DBGPRINT("command failed. status=%02x", entry.data[6]);
+ ctx->patch_error = 1;
+ return -1;
+ }
+
+ entry.data[0] = HCI_COMMAND_PKT;
+ entry.data[1] = 0x05;
+ entry.data[2] = 0xFC;
+ entry.data[3] = 0x00;
+ entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE;
+
+ ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
+ if (ret < 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n", ret);
+ return ret;
+ }
+
+ ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read evt(%d)\n", ret);
+ return ret;
+ }
+ entry.len = ret;
+
+ if (entry.data[6] != 0x00) {
+ DBGPRINT("command failed. status=%02x", entry.data[6]);
+ ctx->patch_error = 1;
+ return -1;
+ }
+
+ for (i = 0; i < INTEL_VER_PARAM_LEN; i++)
+ sprintf(&fw_ver[i*2], "%02x", entry.data[7+i]);
+
+ if (open_patch_file(ctx, fw_ver) < 0) {
+ ctx->patch_error = 1;
+ return -1;
+ }
+
+ return ret;
+}
+
+/*
+ * check the event is startup event
+ */
+static int is_startup_evt(unsigned char *buf)
+{
+ if (buf[1] == 0xFF && buf[2] == 0x01 && buf[3] == 0x00)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Finalize the patch process and reset the controller
+ */
+static int post_patch(struct patch_ctx *ctx)
+{
+ int ret;
+ struct patch_entry entry;
+
+ DBGPRINT("start post_patch");
+
+ entry.data[0] = HCI_COMMAND_PKT;
+ entry.data[1] = 0x11;
+ entry.data[2] = 0xFC;
+ entry.data[3] = 0x02;
+ entry.data[4] = 0x00;
+ if (ctx->reset_enable_patch)
+ entry.data[5] = 0x02;
+ else
+ entry.data[5] = 0x01;
+
+ entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + INTEL_MFG_PARAM_LEN;
+
+ ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
+ if (ret < 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n", ret);
+ return ret;
+ }
+
+ ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read evt(%d)\n", ret);
+ return ret;
+ }
+ entry.len = ret;
+
+ if (entry.data[6] != 0x00) {
+ fprintf(stderr, "cmd failed. st=%02x\n", entry.data[6]);
+ return -1;
+ }
+
+ do {
+ ret = intel_read_evt(ctx->dev, entry.data,
+ sizeof(entry.data));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read cmd(%d)\n", ret);
+ return ret;
+ }
+ entry.len = ret;
+ } while (!is_startup_evt(entry.data));
+
+ return ret;
+}
+
+/**
+ * Main routine that handles the device patching process.
+ */
+static int intel_patch_device(struct patch_ctx *ctx)
+{
+ int ret;
+
+ ret = pre_patch(ctx);
+ if (ret < 0) {
+ if (!ctx->patch_error) {
+ fprintf(stderr, "I/O error: pre_patch failed\n");
+ return ret;
+ }
+
+ DBGPRINT("patch failed. proceed to post patch");
+ goto post_patch;
+ }
+
+ ret = intel_download_patch(ctx);
+ if (ret < 0) {
+ if (!ctx->patch_error) {
+ fprintf(stderr, "I/O error: download_patch failed\n");
+ close(ctx->fd);
+ return ret;
+ }
+ } else {
+ DBGPRINT("patch done");
+ ctx->reset_enable_patch = 1;
+ }
+
+ close(ctx->fd);
+
+post_patch:
+ ret = post_patch(ctx);
+ if (ret < 0) {
+ fprintf(stderr, "post_patch failed(%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int set_rts(int dev, int rtsval)
+{
+ int arg;
+
+ if (ioctl(dev, TIOCMGET, &arg) < 0) {
+ perror("cannot get TIOCMGET");
+ return -errno;
+ }
+ if (rtsval)
+ arg |= TIOCM_RTS;
+ else
+ arg &= ~TIOCM_RTS;
+
+ if (ioctl(dev, TIOCMSET, &arg) == -1) {
+ perror("cannot set TIOCMGET");
+ return -errno;
+ }
+
+ return 0;
+}
+
+static unsigned char get_intel_speed(int speed)
+{
+ switch (speed) {
+ case 9600:
+ return 0x00;
+ case 19200:
+ return 0x01;
+ case 38400:
+ return 0x02;
+ case 57600:
+ return 0x03;
+ case 115200:
+ return 0x04;
+ case 230400:
+ return 0x05;
+ case 460800:
+ return 0x06;
+ case 921600:
+ return 0x07;
+ case 1843200:
+ return 0x08;
+ case 3250000:
+ return 0x09;
+ case 2000000:
+ return 0x0A;
+ case 3000000:
+ return 0x0B;
+ default:
+ return 0xFF;
+ }
+}
+
+/**
+ * if it failed to change to new baudrate, it will rollback
+ * to initial baudrate
+ */
+static int change_baudrate(int dev, int init_speed, int *speed,
+ struct termios *ti)
+{
+ int ret;
+ unsigned char br;
+ unsigned char cmd[5];
+ unsigned char evt[7];
+
+ DBGPRINT("start baudrate change");
+
+ ret = set_rts(dev, 0);
+ if (ret < 0) {
+ fprintf(stderr, "failed to clear RTS\n");
+ return ret;
+ }
+
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x06;
+ cmd[2] = 0xFC;
+ cmd[3] = 0x01;
+
+ br = get_intel_speed(*speed);
+ if (br == 0xFF) {
+ fprintf(stderr, "speed %d is not supported\n", *speed);
+ return -1;
+ }
+ cmd[4] = br;
+
+ ret = intel_write_cmd(dev, cmd, sizeof(cmd));
+ if (ret < 0) {
+ fprintf(stderr, "failed to send cmd(%d)\n", ret);
+ return ret;
+ }
+
+ /*
+ * wait for buffer to be consumed by the controller
+ */
+ usleep(300000);
+
+ if (set_speed(dev, ti, *speed) < 0) {
+ fprintf(stderr, "can't set to new baud rate\n");
+ return -1;
+ }
+
+ ret = set_rts(dev, 1);
+ if (ret < 0) {
+ fprintf(stderr, "failed to set RTS\n");
+ return ret;
+ }
+
+ ret = intel_read_evt(dev, evt, sizeof(evt));
+ if (ret < 0) {
+ fprintf(stderr, "failed to read evt(%d)\n", ret);
+ return ret;
+ }
+
+ if (evt[4] != 0x00) {
+ fprintf(stderr,
+ "failed to change speed. use default speed %d\n",
+ init_speed);
+ *speed = init_speed;
+ }
+
+ return 0;
+}
+
+/**
+ * An entry point for Intel specific initialization
+ */
+int intel_init(int dev, int init_speed, int *speed, struct termios *ti)
+{
+ int ret = 0;
+ struct patch_ctx ctx;
+
+ if (change_baudrate(dev, init_speed, speed, ti) < 0)
+ return -1;
+
+ ctx.dev = dev;
+ ctx.patch_error = 0;
+ ctx.reset_enable_patch = 0;
+
+ ret = intel_patch_device(&ctx);
+ if (ret < 0)
+ fprintf(stderr, "failed to initialize the device");
+
+ return ret;
+}
diff --git a/external/cache/sources/hcitools/hciattach_qualcomm.c b/external/cache/sources/hcitools/hciattach_qualcomm.c
new file mode 100644
index 0000000..0e02e1e
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_qualcomm.c
@@ -0,0 +1,273 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#define FAILIF(x, args...) do { \
+ if (x) { \
+ fprintf(stderr, ##args); \
+ return -1; \
+ } \
+} while (0)
+
+typedef struct {
+ uint8_t uart_prefix;
+ hci_event_hdr hci_hdr;
+ evt_cmd_complete cmd_complete;
+ uint8_t status;
+ uint8_t data[16];
+} __attribute__((packed)) command_complete_t;
+
+static int read_command_complete(int fd,
+ unsigned short opcode,
+ unsigned char len)
+{
+ command_complete_t resp;
+ unsigned char vsevent[512];
+ int n;
+
+ /* Read reply. */
+ n = read_hci_event(fd, vsevent, sizeof(vsevent));
+ FAILIF(n < 0, "Failed to read response");
+
+ FAILIF(vsevent[1] != 0xFF, "Failed to read response");
+
+ n = read_hci_event(fd, (unsigned char *)&resp, sizeof(resp));
+ FAILIF(n < 0, "Failed to read response");
+
+ /* event must be event-complete */
+ FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE,
+ "Error in response: not a cmd-complete event, "
+ "but 0x%02x!\n", resp.hci_hdr.evt);
+
+ FAILIF(resp.hci_hdr.plen < 4, /* plen >= 4 for EVT_CMD_COMPLETE */
+ "Error in response: plen is not >= 4, but 0x%02x!\n",
+ resp.hci_hdr.plen);
+
+ /* cmd-complete event: opcode */
+ FAILIF(resp.cmd_complete.opcode != 0,
+ "Error in response: opcode is 0x%04x, not 0!",
+ resp.cmd_complete.opcode);
+
+ return resp.status == 0 ? 0 : -1;
+}
+
+static int qualcomm_load_firmware(int fd, const char *firmware, const char *bdaddr_s)
+{
+
+ int fw = open(firmware, O_RDONLY);
+
+ fprintf(stdout, "Opening firmware file: %s\n", firmware);
+
+ FAILIF(fw < 0,
+ "Could not open firmware file %s: %s (%d).\n",
+ firmware, strerror(errno), errno);
+
+ fprintf(stdout, "Uploading firmware...\n");
+ do {
+ /* Read each command and wait for a response. */
+ unsigned char data[1024];
+ unsigned char cmdp[1 + sizeof(hci_command_hdr)];
+ hci_command_hdr *cmd = (hci_command_hdr *) (cmdp + 1);
+ int nr;
+
+ nr = read(fw, cmdp, sizeof(cmdp));
+ if (!nr)
+ break;
+
+ FAILIF(nr != sizeof(cmdp),
+ "Could not read H4 + HCI header!\n");
+ FAILIF(*cmdp != HCI_COMMAND_PKT,
+ "Command is not an H4 command packet!\n");
+
+ FAILIF(read(fw, data, cmd->plen) != cmd->plen,
+ "Could not read %d bytes of data \
+ for command with opcode %04x!\n",
+ cmd->plen, cmd->opcode);
+
+ if ((data[0] == 1) && (data[1] == 2) && (data[2] == 6)) {
+ bdaddr_t bdaddr;
+ if (bdaddr_s != NULL) {
+ str2ba(bdaddr_s, &bdaddr);
+ memcpy(&data[3], &bdaddr, sizeof(bdaddr_t));
+ }
+ }
+
+ {
+ int nw;
+ struct iovec iov_cmd[2];
+ iov_cmd[0].iov_base = cmdp;
+ iov_cmd[0].iov_len = sizeof(cmdp);
+ iov_cmd[1].iov_base = data;
+ iov_cmd[1].iov_len = cmd->plen;
+ nw = writev(fd, iov_cmd, 2);
+ FAILIF(nw != (int) sizeof(cmdp) + cmd->plen,
+ "Could not send entire command \
+ (sent only %d bytes)!\n",
+ nw);
+ }
+
+ /* Wait for response */
+ if (read_command_complete(fd, cmd->opcode, cmd->plen) < 0)
+ return -1;
+ } while (1);
+ fprintf(stdout, "Firmware upload successful.\n");
+
+ close(fw);
+
+ return 0;
+}
+
+int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[5];
+ unsigned char resp[100]; /* Response */
+ char fw[100];
+ int n;
+
+ memset(resp, 0, 100);
+
+ /* Get Manufacturer and LMP version */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ do {
+ n = write(fd, cmd, 4);
+ if (n < 4) {
+ perror("Failed to write init command");
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response");
+ return -1;
+ }
+
+ /* Wait for command complete event for our Opcode */
+ } while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+ /* Verify manufacturer */
+ if ((resp[11] & 0xFF) != 0x1d)
+ fprintf(stderr,
+ "WARNING : module's manufacturer is not Qualcomm\n");
+
+ /* Print LMP version */
+ fprintf(stderr,
+ "Qualcomm module LMP version : 0x%02x\n", resp[10] & 0xFF);
+
+ /* Print LMP subversion */
+ {
+ unsigned short lmp_subv = resp[13] | (resp[14] << 8);
+
+ fprintf(stderr, "Qualcomm module LMP sub-version : 0x%04x\n",
+ lmp_subv);
+ }
+
+ /* Get SoC type */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x00;
+ cmd[2] = 0xFC;
+ cmd[3] = 0x01;
+ cmd[4] = 0x06;
+
+ do {
+ n = write(fd, cmd, 5);
+ if (n < 5) {
+ perror("Failed to write vendor init command");
+ return -1;
+ }
+
+ /* Read reply. */
+ if ((n = read_hci_event(fd, resp, 100)) < 0) {
+ perror("Failed to read vendor init response");
+ return -1;
+ }
+
+ } while (resp[3] != 0 && resp[4] != 2);
+
+ snprintf(fw, sizeof(fw), "/etc/firmware/%c%c%c%c%c%c_%c%c%c%c.bin",
+ resp[18], resp[19], resp[20], resp[21],
+ resp[22], resp[23],
+ resp[32], resp[33], resp[34], resp[35]);
+
+ /* Wait for command complete event for our Opcode */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response");
+ return -1;
+ }
+
+ qualcomm_load_firmware(fd, fw, bdaddr);
+
+ /* Reset */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x03;
+ cmd[2] = 0x0C;
+ cmd[3] = 0x00;
+
+ do {
+ n = write(fd, cmd, 4);
+ if (n < 4) {
+ perror("Failed to write reset command");
+ return -1;
+ }
+
+ /* Read reply. */
+ if ((n = read_hci_event(fd, resp, 100)) < 0) {
+ perror("Failed to read reset response");
+ return -1;
+ }
+
+ } while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+ nanosleep(&tm, NULL);
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_rtk.c b/external/cache/sources/hcitools/hciattach_rtk.c
new file mode 100644
index 0000000..6739406
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_rtk.c
@@ -0,0 +1,2563 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ * Copyright (C) 2013-2014 Realtek Semiconductor Corp.
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#define Config_Android 0 /*1 for android; 0 for Linux*/
+
+#if Config_Android //for Android
+#include
+#include
+#include
+#else //for Linux
+#include
+#include
+#include
+#include
+#include
+#endif
+
+#include "hciattach.h"
+
+#define BAUDRATE_4BYTES
+#define RTK_VERSION "2.3"
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_le16(d) (d)
+#define cpu_to_le32(d) (d)
+#define le16_to_cpu(d) (d)
+#define le32_to_cpu(d) (d)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_le16(d) bswap_16(d)
+#define cpu_to_le32(d) bswap_32(d)
+#define le16_to_cpu(d) bswap_16(d)
+#define le32_to_cpu(d) bswap_32(d)
+#else
+#error "Unknown byte order"
+#endif
+
+/* log related */
+#define LOG_STR "Realtek Bluetooth"
+#define DBG_ON 1
+
+#define RS_DBG(fmt, arg...) \
+ do { \
+ if (DBG_ON) \
+ fprintf(stderr, "%s: " fmt "\n", LOG_STR, ##arg); \
+ } while (0)
+
+#define RS_ERR(fmt, arg...) \
+ do { \
+ fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\
+ perror("reason: "); \
+ } while (0)
+
+#define RS_DUMP(buffer, len) \
+ do { \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ for (int i = 0; i < len; i++) { \
+ if (i && !(i % 16)) { \
+ fprintf(stderr, "\n"); \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ } \
+ fprintf(stderr, "%02x ", buffer[i]); \
+ } \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+struct sk_buff {
+ uint32_t max_len;
+ uint32_t data_len;
+ uint8_t data[0];
+};
+
+/* Skb helpers */
+struct bt_skb_cb {
+ uint8_t pkt_type;
+ uint8_t incoming;
+ uint16_t expect;
+ uint8_t tx_seq;
+ uint8_t retries;
+ uint8_t sar;
+ uint16_t channel;
+};
+
+typedef struct {
+ uint8_t index;
+ uint8_t data[252];
+} __attribute__ ((packed)) download_vendor_patch_cp;
+
+struct hci_command_hdr {
+ uint16_t opcode; /* OCF & OGF */
+ uint8_t plen;
+} __attribute__ ((packed));
+
+struct hci_event_hdr {
+ uint8_t evt;
+ uint8_t plen;
+} __attribute__ ((packed));
+
+struct hci_ev_cmd_complete {
+ uint8_t ncmd;
+ uint16_t opcode;
+} __attribute__ ((packed));
+
+#define HCI_COMMAND_HDR_SIZE 3
+#define HCI_EVENT_HDR_SIZE 2
+
+#define HCI_CMD_READ_BD_ADDR 0x1009
+#define HCI_VENDOR_CHANGE_BDRATE 0xfc17
+#define HCI_VENDOR_READ_RTK_ROM_VERISION 0xfc6d
+#define HCI_VENDOR_READ_LMP_VERISION 0x1001
+#define HCI_VENDOR_READ_CHIP_TYPE 0xfc61
+
+#define ROM_LMP_8723a 0x1200
+
+#define RTK_VENDOR_CONFIG_MAGIC 0x8723ab55
+
+#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
+
+#if Config_Android
+#define FIRMWARE_DIRECTORY "/system/vendor/etc/firmware"
+#define BT_CONFIG_DIRECTORY "/system/vendor/etc/firmware"
+#else
+#define FIRMWARE_DIRECTORY "/system/vendor/etc/firmware"
+#define BT_CONFIG_DIRECTORY "/system/vendor/etc/firmware"
+#endif
+
+#define BT_ADDR_DIR "/data/misc/bluetooth/"
+#define BT_ADDR_FILE "/data/misc/bluetooth/btmac.txt"
+
+#define PATCH_DATA_FIELD_MAX_SIZE 252
+#define READ_DATA_SIZE 16
+
+/* HCI data types */
+#define H5_ACK_PKT 0x00
+#define HCI_COMMAND_PKT 0x01
+#define HCI_ACLDATA_PKT 0x02
+#define HCI_SCODATA_PKT 0x03
+#define HCI_EVENT_PKT 0x04
+#define H5_VDRSPEC_PKT 0x0E
+#define H5_LINK_CTL_PKT 0x0F
+
+
+#define HCI_VERSION_MASK_10 (1<<0) // Bluetooth Core Spec 1.0b
+#define HCI_VERSION_MASK_11 (1<<1) // Bluetooth Core Spec 1.1
+#define HCI_VERSION_MASK_12 (1<<2) // Bluetooth Core Spec 1.2
+#define HCI_VERSION_MASK_20 (1<<3) // Bluetooth Core Spec 2.0+EDR
+#define HCI_VERSION_MASK_21 (1<<4) // Bluetooth Core Spec 2.1+EDR
+#define HCI_VERSION_MASK_30 (1<<5) // Bluetooth Core Spec 3.0+HS
+#define HCI_VERSION_MASK_40 (1<<6) // Bluetooth Core Spec 4.0
+#define HCI_VERSION_MASK_41 (1<<7) // Bluetooth Core Spec 4.1
+#define HCI_VERSION_MASK_42 (1<<8) // Bluetooth Core Spec 4.2
+#define HCI_VERSION_MASK_ALL (0xFFFFFFFF)
+
+#define HCI_REVISION_MASK_ALL (0xFFFFFFFF)
+
+#define LMP_SUBVERSION_NONE (0x0)
+
+#define CHIPTYPE_NONE (0x1F) // Chip Type's range: 0x0 ~ 0xF
+#define CHIP_TYPE_MASK_ALL (0xFFFFFFFF)
+
+#define PROJECT_ID_MASK_ALL (0xFFFFFFFF) // temp used for unknow project id for a new chip
+
+#define CONFIG_MAC_OFFSET_GEN_1_2 (0x3C) // MAC's OFFSET in config/efuse for realtek generation 1~2 bluetooth chip
+#define CONFIG_MAC_OFFSET_GEN_3PLUS (0x44) // MAC's OFFSET in config/efuse for rtk generation 3+ bluetooth chip
+#define CONFIG_MAC_OFFSET_GEN_4PLUS (0x30) // MAC's OFFSET in config/efuse for rtk generation 4+ bluetooth chip
+
+#define PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE (0x1)
+
+#define MAX_PATCH_SIZE_24K (1024*24) // 24K
+#define MAX_PATCH_SIZE_40K (1024*40) // 40K
+
+struct rtk_bt_vendor_config_entry {
+ uint16_t offset;
+ uint8_t entry_len;
+ uint8_t entry_data[0];
+} __attribute__ ((packed));
+
+struct rtk_bt_vendor_config {
+ uint32_t signature;
+ uint16_t data_len;
+ struct rtk_bt_vendor_config_entry entry[0];
+} __attribute__ ((packed));
+
+struct rtk_epatch_entry {
+ uint16_t chipID;
+ uint16_t patch_length;
+ uint32_t start_offset;
+} __attribute__ ((packed));
+
+struct rtk_epatch {
+ uint8_t signature[8];
+ uint32_t fm_version;
+ uint16_t number_of_total_patch;
+ struct rtk_epatch_entry entry[0];
+} __attribute__ ((packed));
+
+typedef enum _RTK_ROM_VERSION_CMD_STATE {
+ cmd_not_send,
+ cmd_has_sent,
+ event_received
+} RTK_ROM_VERSION_CMD_STATE;
+
+#pragma pack(1)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+typedef struct _H5_PKT_HEADER {
+ uint8_t SeqNumber:3;
+ uint8_t AckNumber:3;
+ uint8_t DicPresent:1; /* Data Integrity Check Present */
+ uint8_t ReliablePkt:1;
+ uint16_t PktType:4;
+ uint16_t PayloadLen:12;
+ uint8_t HdrChecksum;
+} H5_PKT_HEADER;
+#else
+typedef struct _H5_PKT_HEADER {
+ uint8_t ReliablePkt:1;
+ uint8_t DicPresent:1; /* Data Integrity Check Present */
+ uint8_t AckNumber:3;
+ uint8_t SeqNumber:3;
+ uint16_t PayloadLen:12;
+ uint16_t PktType:4;
+ uint8_t HdrChecksum;
+} H5_PKT_HEADER;
+#endif
+
+typedef enum _H5_RX_STATE {
+ H5_W4_PKT_DELIMITER,
+ H5_W4_PKT_START,
+ H5_W4_HDR,
+ H5_W4_DATA,
+ H5_W4_CRC
+} H5_RX_STATE;
+
+typedef enum _H5_RX_ESC_STATE {
+ H5_ESCSTATE_NOESC,
+ H5_ESCSTATE_ESC
+} H5_RX_ESC_STATE;
+
+typedef enum _H5_LINK_STATE {
+ H5_SYNC,
+ H5_CONFIG,
+ H5_INIT,
+ H5_PATCH,
+ H5_ACTIVE
+} H5_LINK_STATE;
+
+typedef enum _PATCH_PROTOCOL {
+ PATCH_PROTOCAL_H4,
+ PATCH_PROTOCAL_H5
+} PATCH_PROTOCOL;
+
+struct rtk_h5_struct {
+ uint8_t rxseq_txack; /* rxseq == txack. expected rx SeqNumber */
+ uint8_t rxack; /* Last packet sent by us that the peer ack'ed */
+ uint8_t use_crc;
+ uint8_t is_txack_req; /* txack required? Do we need to send ack's to the peer? */
+ /* Reliable packet sequence number - used to assign seq to each rel pkt. */
+ uint8_t msgq_txseq; /* next pkt seq */
+ uint16_t message_crc;
+ uint32_t rx_count; /* expected pkts to recv */
+ H5_RX_STATE rx_state;
+ H5_RX_ESC_STATE rx_esc_state;
+ H5_LINK_STATE link_estab_state;
+ struct sk_buff *rx_skb;
+ struct sk_buff *host_last_cmd;
+};
+
+struct patch_struct {
+ int nTxIndex; /* current sending pkt number */
+ int nTotal; /* total pkt number */
+ int nRxIndex; /* ack index from board */
+ int nNeedRetry; /* if no response from board */
+};
+
+typedef struct {
+ uint16_t lmp_subversion;
+ uint32_t hci_version_mask;
+ uint32_t hci_revision_mask;
+ uint32_t chip_type_mask;
+ uint32_t project_id_mask;
+ char *patch_name;
+ char *config_name;
+ uint16_t mac_offset;
+ uint32_t max_patch_size;
+} patch_info;
+
+/* h/w config control block */
+typedef struct {
+ uint32_t max_patch_size;
+ uint32_t baudrate;
+ uint16_t lmp_subversion;
+ uint16_t lmp_subversion_default;
+ uint16_t lmp_sub_current;
+ uint8_t state; /* Hardware configuration state */
+ uint8_t eversion;
+ uint32_t project_id_mask;
+ uint8_t hci_version;
+ uint8_t hci_revision;
+ uint8_t chip_type;
+} bt_hw_cfg_cb_t;
+
+static patch_info patch_table[] = {
+/* lmp_subv hci_version_mask hci_revision_mask chip_type_mask project_id_mask fw name config name mac offset max_patch_size */
+ {0x1200, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<0, "rtl8723as_fw", "rtl8723as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723AS
+#ifdef RTL_8723BS_BT_USED
+ {0x8723, ~(HCI_VERSION_MASK_21), ~(1<<0xd), CHIP_TYPE_MASK_ALL, 1<<1, "rtl8723bs_fw", "rtl8723bs_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723BS
+#else
+ {0x8723, ~(HCI_VERSION_MASK_21), ~(1<<0xd), CHIP_TYPE_MASK_ALL, 1<<1, "rtl8723bs_VQ0_fw", "rtl8723bs_VQ0_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8723BS_VQ0
+#endif
+ {0x8821, HCI_VERSION_MASK_ALL, ~(1<<0xc), CHIP_TYPE_MASK_ALL, 1<<2, "rtl8821as_fw", "rtl8821as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8821AS
+/* {0x8761, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<3, "rtl8761at_fw", "rtl8761at_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8761AW */
+ {0x8761, HCI_VERSION_MASK_ALL, ~(1<<0xb), CHIP_TYPE_MASK_ALL, 1<<3, "rtl8761at_fw", "rtl8761at_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8761AW
+ {0x8761, HCI_VERSION_MASK_ALL, (1<<0xb), CHIP_TYPE_MASK_ALL, 1<<14, "rtl8761bt_fw", "rtl8761bt_config", CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, //Rtl8761BW
+
+ {0x8723, HCI_VERSION_MASK_21, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<4, "rtl8703as_fw", "rtl8703as_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, //Rtl8703AS
+
+ {0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<7, 1<<6, "rtl8703bs_fw", "rtl8703bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8703BS
+ {0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<5, 1<<7, "rtl8723cs_xx_fw", "rtl8723cs_xx_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_xx
+ {0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<3, 1<<7, "rtl8723cs_cg_fw", "rtl8723cs_cg_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_cg
+ {0x8703, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, 1<<4, 1<<7, "rtl8723cs_vf_fw", "rtl8723cs_vf_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //rtl8723cs_vf
+/* {0x8822, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, 1<<8, "rtl8822bs_fw", "rtl8822bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8822BS */
+ {0x8822, HCI_VERSION_MASK_ALL, ~(1<<0xc), CHIP_TYPE_MASK_ALL, 1<<8, "rtl8822bs_fw", "rtl8822bs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_24K}, //Rtl8822BS
+ {0x8822, HCI_VERSION_MASK_ALL, (1<<0xc), CHIP_TYPE_MASK_ALL, 1<<13, "rtl8822cs_fw", "rtl8822cs_config", CONFIG_MAC_OFFSET_GEN_4PLUS, MAX_PATCH_SIZE_40K}, //Rtl8822CS
+
+ {0x8723, HCI_VERSION_MASK_ALL, (1<<0xd), ~(1<<7), 1<<9, "rtl8723ds_fw", "rtl8723ds_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //Rtl8723ds
+ {0x8723, HCI_VERSION_MASK_ALL, (1<<0xd), 1<<7, 1<<9, "rtl8703cs_fw", "rtl8703cs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //Rtl8703cs
+ {0x8821, HCI_VERSION_MASK_ALL, (1<<0xc), CHIP_TYPE_MASK_ALL, 1<<10, "rtl8821cs_fw", "rtl8821cs_config", CONFIG_MAC_OFFSET_GEN_3PLUS, MAX_PATCH_SIZE_40K}, //RTL8821CS
+/* todo: RTL8703CS */
+ {LMP_SUBVERSION_NONE, HCI_VERSION_MASK_ALL, HCI_REVISION_MASK_ALL, CHIP_TYPE_MASK_ALL, PROJECT_ID_MASK_ALL, "rtl_none_fw", "rtl_none_config", CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}
+};
+
+static bt_hw_cfg_cb_t hw_cfg_cb;
+static uint8_t gEVersion;
+static RTK_ROM_VERSION_CMD_STATE gRom_version_cmd_state;
+static RTK_ROM_VERSION_CMD_STATE ghci_version_cmd_state;
+static RTK_ROM_VERSION_CMD_STATE gchip_type_cmd_state;
+static int gHwFlowControlEnable;
+static int gFinalSpeed;
+
+/* signature: Realtech */
+static const uint8_t RTK_EPATCH_SIGNATURE[8] = {0x52, 0x65, 0x61, 0x6C, 0x74, 0x65, 0x63, 0x68};
+/* Extension Section IGNATURE:0x77FD0451 */
+static const uint8_t Extension_Section_SIGNATURE[4] = {0x51, 0x04, 0xFD, 0x77};
+
+static int serial_fd;
+static int h5_max_retries = 40;
+static struct rtk_h5_struct rtk_h5;
+static struct patch_struct rtk_patch;
+
+/* bite reverse in bytes
+ 00000001 -> 10000000
+ 00000100 -> 00100000
+ */
+static const uint8_t byte_rev_table[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+/* reverse bit */
+static __inline uint8_t bit_rev8(uint8_t byte)
+{
+ return byte_rev_table[byte];
+}
+
+/* reverse bit */
+static __inline uint16_t bit_rev16(uint16_t x)
+{
+ return (bit_rev8(x & 0xff) << 8) | bit_rev8(x >> 8);
+}
+
+static const uint16_t crc_table[] = {
+ 0x0000, 0x1081, 0x2102, 0x3183,
+ 0x4204, 0x5285, 0x6306, 0x7387,
+ 0x8408, 0x9489, 0xa50a, 0xb58b,
+ 0xc60c, 0xd68d, 0xe70e, 0xf78f
+};
+
+/**
+* Malloc the socket buffer
+*
+* @param skb socket buffer
+* @return the point to the malloc buffer
+*/
+static __inline struct sk_buff *skb_alloc(uint32_t len)
+{
+ struct sk_buff *skb = NULL;
+ skb = malloc(len + 8);
+ if (skb) {
+ skb->max_len = len;
+ skb->data_len = 0;
+ memset(skb->data, 0, len);
+ } else {
+ RS_ERR("Allocate skb fails!!!");
+ skb = NULL;
+ }
+ return skb;
+}
+
+/**
+* Free the socket buffer
+*
+* @param skb socket buffer
+*/
+static __inline void skb_free(struct sk_buff *skb)
+{
+ free(skb);
+ return;
+}
+
+/**
+* Increase the date length in sk_buffer by len,
+* and return the increased header pointer
+*
+* @param skb socket buffer
+* @param len length want to increase
+* @return the pointer to increased header
+*/
+static uint8_t *skb_put(struct sk_buff *skb, uint32_t len)
+{
+ uint32_t old_len = skb->data_len;
+ if ((skb->data_len + len) > (skb->max_len)) {
+ RS_ERR("Buffer too small");
+ return NULL;
+ }
+ skb->data_len += len;
+ return (skb->data + old_len);
+}
+
+/**
+* decrease data length in sk_buffer by to len by cut the tail
+*
+* @warning len should be less than skb->len
+*
+* @param skb socket buffer
+* @param len length want to be changed
+*/
+static void skb_trim(struct sk_buff *skb, int len)
+{
+ if (skb->data_len > len) {
+ skb->data_len = len;
+ } else {
+ RS_ERR("Error: skb->data_len(%ld) < len(%d)", (long int)skb->data_len, len);
+ }
+}
+
+/**
+* Decrease the data length in sk_buffer by len,
+* and move the content forward to the header.
+* the data in header will be removed.
+*
+* @param skb socket buffer
+* @param len length of data
+* @return new data
+*/
+static uint8_t *skb_pull(struct sk_buff *skb, uint32_t len)
+{
+ skb->data_len -= len;
+ char *buf;
+ buf = malloc(skb->data_len);
+ if (!buf) {
+ RS_ERR("Unable to allocate file buffer");
+ exit(1);
+ }
+ memcpy(buf, skb->data+len, skb->data_len);
+ memcpy(skb->data, buf, skb->data_len);
+ free(buf);
+ return skb->data;
+}
+
+/**
+* Add "d" into crc scope, caculate the new crc value
+*
+* @param crc crc data
+* @param d one byte data
+*/
+static void h5_crc_update(uint16_t *crc, uint8_t d)
+{
+ uint16_t reg = *crc;
+
+ reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f];
+ reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f];
+
+ *crc = reg;
+}
+
+struct __una_u16 { uint16_t x; };
+
+static __inline uint16_t __get_unaligned_cpu16(const void *p)
+{
+ const struct __una_u16 *ptr = (const struct __una_u16 *)p;
+ return ptr->x;
+}
+
+static __inline uint16_t get_unaligned_be16(const void *p)
+{
+ return __get_unaligned_cpu16((const uint8_t *)p);
+}
+
+/**
+* Get crc data.
+*
+* @param h5 realtek h5 struct
+* @return crc data
+*/
+static uint16_t h5_get_crc(struct rtk_h5_struct *h5)
+{
+ uint16_t crc = 0;
+ uint8_t *data = h5->rx_skb->data + h5->rx_skb->data_len - 2;
+ crc = data[1] + (data[0] << 8);
+ return crc;
+}
+
+/**
+* Just add 0xc0 at the end of skb,
+* we can also use this to add 0xc0 at start while there is no data in skb
+*
+* @param skb socket buffer
+*/
+static void h5_slip_msgdelim(struct sk_buff *skb)
+{
+ const char pkt_delim = 0xc0;
+ memcpy(skb_put(skb, 1), &pkt_delim, 1);
+}
+
+/**
+* Slip ecode one byte in h5 proto, as follows:
+* 0xc0 -> 0xdb, 0xdc
+* 0xdb -> 0xdb, 0xdd
+* 0x11 -> 0xdb, 0xde
+* 0x13 -> 0xdb, 0xdf
+* others will not change
+*
+* @param skb socket buffer
+* @c pure data in the one byte
+*/
+static void h5_slip_one_byte(struct sk_buff *skb, uint8_t c)
+{
+ const int8_t esc_c0[2] = { 0xdb, 0xdc };
+ const int8_t esc_db[2] = { 0xdb, 0xdd };
+ const int8_t esc_11[2] = { 0xdb, 0xde };
+ const int8_t esc_13[2] = { 0xdb, 0xdf };
+
+ switch (c) {
+ case 0xc0:
+ memcpy(skb_put(skb, 2), &esc_c0, 2);
+ break;
+ case 0xdb:
+ memcpy(skb_put(skb, 2), &esc_db, 2);
+ break;
+ case 0x11:
+ memcpy(skb_put(skb, 2), &esc_11, 2);
+ break;
+ case 0x13:
+ memcpy(skb_put(skb, 2), &esc_13, 2);
+ break;
+ default:
+ memcpy(skb_put(skb, 1), &c, 1);
+ }
+}
+
+/**
+* Decode one byte in h5 proto, as follows:
+* 0xdb, 0xdc -> 0xc0
+* 0xdb, 0xdd -> 0xdb
+* 0xdb, 0xde -> 0x11
+* 0xdb, 0xdf -> 0x13
+* others will not change
+*
+* @param h5 realtek h5 struct
+* @byte pure data in the one byte
+*/
+static void h5_unslip_one_byte(struct rtk_h5_struct *h5, char byte)
+{
+ const uint8_t c0 = 0xc0, db = 0xdb;
+ const uint8_t oof1 = 0x11, oof2 = 0x13;
+ //RS_DBG("HCI 3wire h5_unslip_one_byte");
+
+ if (H5_ESCSTATE_NOESC == h5->rx_esc_state) {
+ if (0xdb == byte) {
+ h5->rx_esc_state = H5_ESCSTATE_ESC;
+ } else {
+ memcpy(skb_put(h5->rx_skb, 1), &byte, 1);
+ //Check Pkt Header's CRC enable bit
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC) {
+ h5_crc_update(&h5->message_crc, byte);
+ }
+ h5->rx_count--;
+ }
+ } else if (H5_ESCSTATE_ESC == h5->rx_esc_state) {
+ switch (byte) {
+ case 0xdc:
+ memcpy(skb_put(h5->rx_skb, 1), &c0, 1);
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)
+ h5_crc_update(&h5->message_crc, 0xc0);
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->rx_count--;
+ break;
+ case 0xdd:
+ memcpy(skb_put(h5->rx_skb, 1), &db, 1);
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)
+ h5_crc_update(&h5->message_crc, 0xdb);
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->rx_count--;
+ break;
+ case 0xde:
+ memcpy(skb_put(h5->rx_skb, 1), &oof1, 1);
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)
+ h5_crc_update(&h5->message_crc, oof1);
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->rx_count--;
+ break;
+ case 0xdf:
+ memcpy(skb_put(h5->rx_skb, 1), &oof2, 1);
+ if ((h5->rx_skb->data[0] & 0x40) != 0 && h5->rx_state != H5_W4_CRC)
+ h5_crc_update(&h5->message_crc, oof2);
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->rx_count--;
+ break;
+ default:
+ RS_ERR("Error: Invalid byte %02x after esc byte", byte);
+ skb_free(h5->rx_skb);
+ h5->rx_skb = NULL;
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+ break;
+ }
+ }
+}
+
+/**
+* Prepare h5 packet, packet format as follow:
+* | LSB 4 octets | 0 ~ 4095 | 2 MSB
+* |packet header | payload | data integrity check |
+*
+* pakcket header fromat is show below:
+* | LSB 3 bits | 3 bits | 1 bits | 1 bits |
+* | 4 bits | 12 bits | 8 bits MSB
+* |sequence number | acknowledgement number | data integrity check present | reliable packet |
+* |packet type | payload length | header checksum
+*
+* @param h5 realtek h5 struct
+* @param data pure data
+* @param len the length of data
+* @param pkt_type packet type
+* @return socket buff after prepare in h5 proto
+*/
+static struct sk_buff *h5_prepare_pkt(struct rtk_h5_struct *h5, uint8_t *data, int32_t len, int32_t pkt_type)
+{
+ struct sk_buff *nskb;
+ uint8_t hdr[4];
+ uint16_t h5_txmsg_crc = 0xffff;
+ int rel, i;
+
+ switch (pkt_type) {
+ case HCI_ACLDATA_PKT:
+ case HCI_COMMAND_PKT:
+ case HCI_EVENT_PKT:
+ rel = 1; /* reliable */
+ break;
+ case H5_ACK_PKT:
+ case H5_VDRSPEC_PKT:
+ case H5_LINK_CTL_PKT:
+ rel = 0; /* unreliable */
+ break;
+ default:
+ RS_ERR("Unknown packet type");
+ return NULL;
+ }
+
+ /* Max len of packet: (original len +4(h5 hdr) + 2(crc)) * 2
+ * (because bytes 0xc0 and 0xdb are escaped, worst case is
+ * when the packet is all made of 0xc0 and 0xdb :))
+ * + 2 (0xc0 delimiters at start and end). */
+ nskb = skb_alloc((len + 6) * 2 + 2);
+ if (!nskb)
+ return NULL;
+
+ /* Add SLIP start byte: 0xc0 */
+ h5_slip_msgdelim(nskb);
+ /* set AckNumber in SlipHeader */
+ hdr[0] = h5->rxseq_txack << 3;
+ h5->is_txack_req = 0;
+
+ if (rel) {
+ /* set reliable pkt bit and SeqNumber */
+ hdr[0] |= 0x80 + h5->msgq_txseq;
+ ++(h5->msgq_txseq);
+ h5->msgq_txseq = (h5->msgq_txseq) & 0x07;
+ }
+
+ /* set DicPresent bit */
+ if (h5->use_crc)
+ hdr[0] |= 0x40;
+
+ /* set packet type and payload length */
+ hdr[1] = ((len << 4) & 0xff) | pkt_type;
+ hdr[2] = (uint8_t)(len >> 4);
+ /* set checksum */
+ hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);
+
+ /* Put h5 header */
+ for (i = 0; i < 4; i++) {
+ h5_slip_one_byte(nskb, hdr[i]);
+
+ if (h5->use_crc)
+ h5_crc_update(&h5_txmsg_crc, hdr[i]);
+ }
+
+ /* Put payload */
+ for (i = 0; i < len; i++) {
+ h5_slip_one_byte(nskb, data[i]);
+
+ if (h5->use_crc)
+ h5_crc_update(&h5_txmsg_crc, data[i]);
+ }
+
+ /* Put CRC */
+ if (h5->use_crc) {
+ h5_txmsg_crc = bit_rev16(h5_txmsg_crc);
+ h5_slip_one_byte(nskb, (uint8_t) ((h5_txmsg_crc >> 8) & 0x00ff));
+ h5_slip_one_byte(nskb, (uint8_t) (h5_txmsg_crc & 0x00ff));
+ }
+
+ /* Add SLIP end byte: 0xc0 */
+ h5_slip_msgdelim(nskb);
+ return nskb;
+}
+
+/**
+* Removed controller acked packet from Host's unacked lists
+*
+* @param h5 realtek h5 struct
+*/
+static void h5_remove_acked_pkt(struct rtk_h5_struct *h5)
+{
+ int pkts_to_be_removed = 0;
+ int seqno = 0;
+ int i = 0;
+
+ seqno = h5->msgq_txseq;
+
+ while (pkts_to_be_removed) {
+ if (h5->rxack == seqno)
+ break;
+
+ pkts_to_be_removed--;
+ seqno = (seqno - 1) & 0x07;
+ }
+
+ if (h5->rxack != seqno) {
+ RS_DBG("Peer acked invalid packet");
+ }
+
+ i = 0;
+ for (i = 0; i < 5; ++i) {
+ if (i >= pkts_to_be_removed)
+ break;
+ i++;
+ }
+
+ if (i != pkts_to_be_removed)
+ RS_DBG("Removed only (%d) out of (%d) pkts", i, pkts_to_be_removed);
+}
+
+/**
+* Realtek send pure ack, send a packet only with an ack
+*
+* @param fd uart file descriptor
+*
+*/
+static void rtk_send_pure_ack_down(int fd)
+{
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, NULL, 0, H5_ACK_PKT);
+ write(fd, nskb->data, nskb->data_len);
+ skb_free(nskb);
+ return;
+}
+
+/**
+* Parse hci event command complete, pull the cmd complete event header
+*
+* @param skb socket buffer
+*
+*/
+static void hci_event_cmd_complete(struct sk_buff *skb)
+{
+ struct hci_ev_cmd_complete *ev = NULL;
+ uint16_t opcode = 0;
+ uint8_t status = 0;
+
+ /* omit length check */
+ /* pull hdr */
+ skb_pull(skb, HCI_EVENT_HDR_SIZE);
+ ev = (struct hci_ev_cmd_complete *)skb->data;
+ opcode = le16_to_cpu(ev->opcode);
+
+ RS_DBG("receive hci command complete event with command: %x", opcode);
+ if (DBG_ON) {
+ RS_DBG("Dump event data with event header (header size %d):", sizeof(struct hci_ev_cmd_complete));
+ RS_DUMP(skb->data, skb->data_len);
+ }
+
+ /* pull command complete event header */
+ skb_pull(skb, sizeof(struct hci_ev_cmd_complete));
+
+ switch (opcode) {
+ case HCI_VENDOR_CHANGE_BDRATE:
+ status = skb->data[0];
+ RS_DBG("Change BD Rate with status:%x", status);
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ rtk_h5.link_estab_state = H5_PATCH;
+ break;
+ case HCI_CMD_READ_BD_ADDR:
+ status = skb->data[0];
+ RS_DBG("Read BD Address with Status:%x", status);
+ if (!status) {
+ RS_DBG("BD Address: %8x%8x", *(int *)&skb->data[1], *(int *)&skb->data[5]);
+ }
+ break;
+ case HCI_VENDOR_READ_LMP_VERISION:
+ ghci_version_cmd_state = event_received;
+ status = skb->data[0];
+ RS_DBG("Read RTK LMP version with Status:%x", status);
+ if (0 == status) {
+ hw_cfg_cb.hci_version = *(uint8_t *)(&skb->data[1]);
+ hw_cfg_cb.hci_revision = *(uint8_t *)(&skb->data[2]);
+ hw_cfg_cb.lmp_subversion = le16_to_cpu(*(uint16_t *)(&skb->data[7]));
+ } else {
+ RS_ERR("READ_RTK_ROM_VERISION return status error!");
+ /* Need to do more */
+ }
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ break;
+ case HCI_VENDOR_READ_CHIP_TYPE:
+ gchip_type_cmd_state = event_received;
+ status = skb->data[0];
+ RS_DBG("Read RTK CHIP TYPE with Status:%x", status);
+ if (0 == status) {
+ hw_cfg_cb.chip_type = *(uint8_t *)(&skb->data[1]);
+ } else {
+ RS_ERR("READ_RTK_CHIP_TYPE return status error!");
+ }
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ break;
+ case HCI_VENDOR_READ_RTK_ROM_VERISION:
+ gRom_version_cmd_state = event_received;
+ status = skb->data[0];
+ RS_DBG("Read RTK rom version with Status:%x", status);
+ if (0 == status)
+ gEVersion = skb->data[1];
+ else if (1 == status)
+ gEVersion = 0;
+ else {
+ gEVersion = 0;
+ RS_ERR("READ_RTK_ROM_VERISION return status error!");
+ /* Need to do more */
+ }
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ break;
+ }
+}
+
+/**
+* Check if it's a hci frame, if it is, complete it with response or parse the cmd complete event
+*
+* @param skb socket buffer
+*
+*/
+static void hci_recv_frame(struct sk_buff *skb)
+{
+ char h5sync[2] = {0x01, 0x7E},
+ h5syncresp[2] = {0x02, 0x7D},
+ h5_sync_resp_pkt[0x8] = {0xc0, 0x00, 0x2F, 0x00, 0xD0, 0x02, 0x7D, 0xc0},
+ h5_conf_resp_pkt_to_Ctrl[0x8] = {0xc0, 0x00, 0x2F, 0x00, 0xD0, 0x04, 0x7B, 0xc0},
+ h5conf[3] = {0x03, 0xFC, 0x10},
+ h5confresp[3] = {0x04, 0x7B, 0x10},
+ cmd_complete_evt_code = 0xe;
+
+ if (rtk_h5.link_estab_state == H5_SYNC) { /* sync */
+ if (!memcmp(skb->data, h5sync, 2)) {
+ RS_DBG("Get Sync Pkt\n");
+ write(serial_fd, &h5_sync_resp_pkt, 0x8);
+ } else if (!memcmp(skb->data, h5syncresp, 2)) {
+ RS_DBG("Get Sync Resp Pkt\n");
+ rtk_h5.link_estab_state = H5_CONFIG;
+ }
+ skb_free(skb);
+ } else if (rtk_h5.link_estab_state == H5_CONFIG) { /* config */
+ if (!memcmp(skb->data, h5sync, 0x2)) {
+ write(serial_fd, &h5_sync_resp_pkt, 0x8);
+ RS_DBG("Get SYNC pkt-active mode\n");
+ } else if (!memcmp(skb->data, h5conf, 0x2)) {
+ write(serial_fd, &h5_conf_resp_pkt_to_Ctrl, 0x8);
+ RS_DBG("Get CONFG pkt-active mode\n");
+ } else if (!memcmp(skb->data, h5confresp, 0x2)) {
+ RS_DBG("Get CONFG resp pkt-active mode\n");
+ rtk_h5.link_estab_state = H5_INIT;//H5_PATCH;
+ //rtk_send_pure_ack_down(serial_fd);
+ } else {
+ RS_DBG("H5_CONFIG receive event\n");
+ rtk_send_pure_ack_down(serial_fd);
+ }
+ skb_free(skb);
+ } else if (rtk_h5.link_estab_state == H5_INIT) {
+ if (skb->data[0] == cmd_complete_evt_code) {
+ hci_event_cmd_complete(skb);
+ }
+
+ rtk_send_pure_ack_down(serial_fd);
+ usleep(10000);
+ rtk_send_pure_ack_down(serial_fd);
+ usleep(10000);
+ rtk_send_pure_ack_down(serial_fd);
+ skb_free(skb);
+ } else if (rtk_h5.link_estab_state == H5_PATCH) { /* patch */
+ rtk_patch.nRxIndex = skb->data[6];
+ if (rtk_patch.nRxIndex & 0x80)
+ rtk_patch.nRxIndex &= ~0x80;
+
+ RS_DBG("rtk_patch.nRxIndex %d\n", rtk_patch.nRxIndex);
+ if (rtk_patch.nRxIndex == rtk_patch.nTotal)
+ rtk_h5.link_estab_state = H5_ACTIVE;
+ skb_free(skb);
+ } else {
+ RS_ERR("receive packets in active state");
+ skb_free(skb);
+ }
+}
+
+/**
+* after rx data is parsed, and we got a rx frame saved in h5->rx_skb,
+* this routinue is called.
+* things todo in this function:
+* 1. check if it's a hci frame, if it is, complete it with response or ack
+* 2. see the ack number, free acked frame in queue
+* 3. reset h5->rx_state, set rx_skb to null.
+*
+* @param h5 realtek h5 struct
+*
+*/
+static void h5_complete_rx_pkt(struct rtk_h5_struct *h5)
+{
+ int pass_up = 1;
+ uint16_t *valuep, value_t;
+ H5_PKT_HEADER *h5_hdr = NULL;
+ /* 1 is offset of uint16_t in H5_PKT_HEADER */
+ valuep = (uint16_t *)(h5->rx_skb->data+1);
+ value_t = le16_to_cpu(*valuep);
+ *valuep = value_t;
+ h5_hdr = (H5_PKT_HEADER *)(h5->rx_skb->data);
+ if (h5_hdr->ReliablePkt) {
+ RS_DBG("Received reliable seqno %u from card", h5->rxseq_txack);
+ h5->rxseq_txack = h5_hdr->SeqNumber + 1;
+ h5->rxseq_txack %= 8;
+ h5->is_txack_req = 1;
+ /* send down an empty ack if needed. */
+ }
+
+ h5->rxack = h5_hdr->AckNumber;
+
+ switch (h5_hdr->PktType) {
+ case HCI_ACLDATA_PKT:
+ case HCI_EVENT_PKT:
+ case HCI_SCODATA_PKT:
+ case HCI_COMMAND_PKT:
+ case H5_LINK_CTL_PKT:
+ pass_up = 1;
+ break;
+ default:
+ pass_up = 0;
+ }
+
+ h5_remove_acked_pkt(h5);
+
+ /* decide if we need to pass up. */
+ if (pass_up) {
+ /* remove h5 header and send packet to hci */
+ skb_pull(h5->rx_skb, sizeof(H5_PKT_HEADER));
+ hci_recv_frame(h5->rx_skb);
+ /* should skb be freed here? */
+ } else {
+ /* free skb buffer */
+ skb_free(h5->rx_skb);
+ }
+
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_skb = NULL;
+}
+
+/**
+* Parse the receive data in h5 proto.
+*
+* @param h5 realtek h5 struct
+* @param data point to data received before parse
+* @param count num of data
+* @return reserved count
+*/
+static int h5_recv(struct rtk_h5_struct *h5, void *data, int count)
+{
+ char *ptr;
+ ptr = (char *)data;
+
+ while (count) {
+ if (h5->rx_count) {
+ if (*ptr == 0xc0) {
+ RS_ERR("short h5 packet");
+ skb_free(h5->rx_skb);
+ h5->rx_state = H5_W4_PKT_START;
+ h5->rx_count = 0;
+ } else {
+ h5_unslip_one_byte(h5, *ptr);
+ }
+ ptr++;
+ count--;
+ continue;
+ }
+
+ switch (h5->rx_state) {
+ case H5_W4_HDR:
+ /* check header checksum. see Core Spec V4 "3-wire uart" page 67 */
+ if ((0xff & (uint8_t) ~(h5->rx_skb->data[0] + h5->rx_skb->data[1] +
+ h5->rx_skb->data[2])) != h5->rx_skb->data[3]) {
+ RS_ERR("h5 hdr checksum error!!!");
+ skb_free(h5->rx_skb);
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+ continue;
+ }
+
+ if (h5->rx_skb->data[0] & 0x80 /* reliable pkt */
+ && (h5->rx_skb->data[0] & 0x07) != h5->rxseq_txack) {
+ RS_ERR("Out-of-order packet arrived, got(%d)expected(%u)",
+ h5->rx_skb->data[0] & 0x07, h5->rxseq_txack);
+ h5->is_txack_req = 1;
+ skb_free(h5->rx_skb);
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+
+ if (rtk_patch.nTxIndex == rtk_patch.nTotal) {
+ /* depend on weather remote will reset ack numb or not!!!!!!!!!!!!!!!special */
+ rtk_h5.rxseq_txack = h5->rx_skb->data[0] & 0x07;
+ }
+ continue;
+ }
+
+ h5->rx_state = H5_W4_DATA;
+
+ /* payload length: May be 0 */
+ h5->rx_count = (h5->rx_skb->data[1] >> 4) + (h5->rx_skb->data[2] << 4);
+ continue;
+ case H5_W4_DATA:
+ if (h5->rx_skb->data[0] & 0x40) { /* pkt with crc */
+ h5->rx_state = H5_W4_CRC;
+ h5->rx_count = 2;
+ } else {
+ h5_complete_rx_pkt(h5); /* Send ACK */
+ }
+ continue;
+
+ case H5_W4_CRC:
+ if (bit_rev16(h5->message_crc) != h5_get_crc(h5)) {
+ RS_ERR("Checksum failed, computed(%04x)received(%04x)",
+ bit_rev16(h5->message_crc), h5_get_crc(h5));
+ skb_free(h5->rx_skb);
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+ continue;
+ }
+ skb_trim(h5->rx_skb, h5->rx_skb->data_len - 2);
+ h5_complete_rx_pkt(h5);
+ continue;
+
+ case H5_W4_PKT_DELIMITER:
+ switch (*ptr) {
+ case 0xc0:
+ h5->rx_state = H5_W4_PKT_START;
+ break;
+ default:
+ break;
+ }
+ ptr++;
+ count--;
+ break;
+
+ case H5_W4_PKT_START:
+ switch (*ptr) {
+ case 0xc0:
+ ptr++;
+ count--;
+ break;
+ default:
+ h5->rx_state = H5_W4_HDR;
+ h5->rx_count = 4;
+ h5->rx_esc_state = H5_ESCSTATE_NOESC;
+ h5->message_crc = 0xffff;
+
+ /* Do not increment ptr or decrement count
+ * Allocate packet. Max len of a H5 pkt=
+ * 0xFFF (payload) +4 (header) +2 (crc) */
+ h5->rx_skb = skb_alloc(0x1005);
+ if (!h5->rx_skb) {
+ h5->rx_state = H5_W4_PKT_DELIMITER;
+ h5->rx_count = 0;
+ return 0;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return count;
+}
+
+/**
+* Read data to buf from uart.
+*
+* @param fd uart file descriptor
+* @param buf point to the addr where read data stored
+* @param count num of data want to read
+* @return num of data successfully read
+*/
+static int read_check(int fd, void *buf, int count)
+{
+ int res;
+ do {
+ res = read(fd, buf, count);
+ if (res != -1) {
+ buf = (uint8_t *)buf + res;
+ count -= res;
+ return res;
+ }
+ } while (count && (errno == 0 || errno == EINTR));
+ return res;
+}
+
+/**
+* Retry to sync when timeout in h5 proto, max retry times is 10.
+*
+* @warning Each time to retry, the time for timeout will be set as 1s.
+*
+* @param sig signaction for timeout
+*
+*/
+static void h5_tshy_sig_alarm(int sig)
+{
+ uint8_t h5sync[2] = {0x01, 0x7E};
+ static int retries;
+ struct itimerval value;
+
+ if (retries < h5_max_retries) {
+ retries++;
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, h5sync, sizeof(h5sync), H5_LINK_CTL_PKT);
+ int len = write(serial_fd, nskb->data, nskb->data_len);
+ RS_DBG("3-wire sync pattern resend : %d, len: %d\n", retries, len);
+ skb_free(nskb);
+
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 250000;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 250000;
+ setitimer(ITIMER_REAL, &value, NULL);
+
+ return;
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("H5 sync timed out\n");
+ exit(1);
+}
+
+/**
+* Retry to config when timeout in h5 proto, max retry times is 10.
+*
+* @warning Each time to retry, the time for timeout will be set as 1s.
+*
+* @param sig signaction for timeout
+*
+*/
+static void h5_tconf_sig_alarm(int sig)
+{
+ uint8_t h5conf[3] = {0x03, 0xFC, 0x14};
+ static int retries;
+ struct itimerval value;
+
+ if (retries < h5_max_retries) {
+ retries++;
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, h5conf, 3, H5_LINK_CTL_PKT);
+ int len = write(serial_fd, nskb->data, nskb->data_len);
+ RS_DBG("3-wire config pattern resend : %d , len: %d", retries, len);
+ skb_free(nskb);
+
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 250000;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 250000;
+ setitimer(ITIMER_REAL, &value, NULL);
+
+ return;
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("H5 config timed out\n");
+ exit(1);
+}
+
+/**
+* Retry to init when timeout in h5 proto, max retry times is 10.
+*
+* @warning Each time to retry, the time for timeout will be set as 1s.
+*
+* @param sig signaction for timeout
+*
+*/
+static void h5_tinit_sig_alarm(int sig)
+{
+ static int retries;
+ if (retries < h5_max_retries) {
+ retries++;
+ if (rtk_h5.host_last_cmd) {
+ int len = write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);
+ RS_DBG("3-wire change baudrate re send:%d, len:%d", retries, len);
+ alarm(1);
+ return;
+ } else {
+ RS_DBG("3-wire init timeout without last command stored\n");
+ }
+ }
+
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("H5 init process timed out");
+ exit(1);
+}
+
+/**
+* Retry to download patch when timeout in h5 proto, max retry times is 10.
+*
+* @warning Each time to retry, the time for timeout will be set as 3s.
+*
+* @param sig signaction for timeout
+*
+*/
+static void h5_tpatch_sig_alarm(int sig)
+{
+ static int retries;
+ if (retries < h5_max_retries) {
+ RS_DBG("patch timerout, retry:\n");
+ if (rtk_h5.host_last_cmd) {
+ write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);
+ RS_DBG("3-wire download patch re send:%d", retries);
+ }
+ retries++;
+ alarm(3);
+ return;
+ }
+ RS_ERR("H5 patch timed out\n");
+ exit(1);
+}
+
+/**
+* Download patch using hci. For h5 proto, not recv reply for 2s will timeout.
+* Call h5_tpatch_sig_alarm for retry.
+*
+* @param dd uart file descriptor
+* @param index current index
+* @param data point to the config file
+* @param len current buf length
+* @return #0 on success
+*
+*/
+static int hci_download_patch(int dd, int index, uint8_t *data, int len, struct termios *ti)
+{
+ uint8_t hcipatch[256] = {0x20, 0xfc, 00};
+ char bytes[READ_DATA_SIZE];
+ int retlen;
+ struct sigaction sa;
+
+ sa.sa_handler = h5_tpatch_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+ alarm(2);
+
+ download_vendor_patch_cp cp;
+ memset(&cp, 0, sizeof(cp));
+ cp.index = index;
+ if (data != NULL) {
+ memcpy(cp.data, data, len);
+ }
+
+ int nValue = rtk_patch.nTotal|0x80;
+ if (index == nValue) {
+ rtk_patch.nTxIndex = rtk_patch.nTotal;
+ } else {
+ rtk_patch.nTxIndex = index;
+ }
+ hcipatch[2] = len+1;
+ memcpy(hcipatch+3, &cp, len+1);
+
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, hcipatch, len+4, HCI_COMMAND_PKT); /* data: len + head: 4 */
+
+ if (rtk_h5.host_last_cmd) {
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ }
+
+ rtk_h5.host_last_cmd = nskb;
+
+ len = write(dd, nskb->data, nskb->data_len);
+ RS_DBG("hci_download_patch nTxIndex:%d nRxIndex: %d\n", rtk_patch.nTxIndex, rtk_patch.nRxIndex);
+
+ if (index & 0x80) {
+ RS_DBG("Hw Flow Control enable after last command sent before last event recv ! ");
+ if (tcsetattr(dd, TCSADRAIN, ti) < 0) {
+ RS_ERR("Can't set port settings");
+ return -1;
+ }
+ }
+
+ while (rtk_patch.nRxIndex != rtk_patch.nTxIndex) { /* receive data and wait last pkt */
+ retlen = read_check(dd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return -1;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+
+ alarm(0);
+ return 0;
+}
+
+/**
+* Download h4 patch
+*
+* @param dd uart file descriptor
+* @param index current index
+* @param data point to the config file
+* @param len current buf length
+* @return ret_index
+*
+*/
+static int hci_download_patch_h4(int dd, int index, uint8_t *data, int len)
+{
+ char bytes[257] = {0};
+ char buf[257] = {0x01, 0x20, 0xfc, 00};
+
+ RS_DBG("dd:%d, index:%d, len:%d", dd, index, len);
+ if (NULL != data) {
+ memcpy(&buf[5], data, len);
+ }
+
+ int cur_index = index;
+ int ret_Index = -1;
+
+ /* Set data struct. */
+ buf[3] = len + 1; /* add index */
+ buf[4] = cur_index;
+ size_t total_len = len + 5;
+
+ /* write */
+ uint16_t w_len;
+ w_len = write(dd, buf, total_len);
+ RS_DBG("h4 write success with len: %d.\n", w_len);
+
+ uint16_t res;
+ res = read(dd, bytes, 8);
+
+ if (DBG_ON) {
+ RS_DBG("h4 read success with len: %d.\n", res);
+ int i = 0;
+ for (i = 0; i < 8; i++) {
+ fprintf(stderr, "byte[%d] = 0x%x\n", i, bytes[i]);
+ }
+ }
+
+ uint8_t rstatus;
+ if ((0x04 == bytes[0]) && (0x20 == bytes[4]) && (0xfc == bytes[5])) {
+ ret_Index = bytes[7];
+ rstatus = bytes[6];
+ RS_DBG("---->ret_Index:%d, ----->rstatus:%d\n", ret_Index, rstatus);
+ if (0x00 != rstatus) {
+ RS_ERR("---->read event status is wrong.\n");
+ return -1;
+ }
+ } else {
+ RS_ERR("==========>Didn't read curret data.\n");
+ return -1;
+ }
+
+ return ret_Index;
+}
+
+/**
+* Realtek change speed with h4 proto. Using vendor specified command packet to achieve this.
+*
+* @warning before write, need to wait 1s for device up
+*
+* @param fd uart file descriptor
+* @param baudrate the speed want to change
+* @return #0 on success
+*/
+static int rtk_vendor_change_speed_h4(int fd, uint32_t baudrate)
+{
+ char bytes[257];
+ uint8_t cmd[8] = {0};
+
+ cmd[0] = 1; /* cmd */
+ cmd[1] = 0x17; /* ocf */
+ cmd[2] = 0xfc; /* ogf, vendor specified */
+
+ cmd[3] = 4; /* length */
+#ifdef BAUDRATE_4BYTES
+ memcpy((uint16_t *)&cmd[4], &baudrate, 4);
+#else
+ memcpy((uint16_t *)&cmd[4], &baudrate, 2);
+
+ cmd[6] = 0;
+ cmd[7] = 0;
+#endif
+
+ /* wait for a while for device to up, just h4 need it */
+ sleep(1);
+
+ if (write(fd, cmd, 8) != 8) {
+ RS_ERR("H4 change uart speed error when writing vendor command");
+ return -1;
+ }
+ RS_DBG("H4 Change uart Baudrate after write ");
+ int res;
+ res = read(fd, bytes, sizeof(bytes));
+
+ if (DBG_ON) {
+ RS_DBG("Realtek Receving H4 change uart speed event:%x", res);
+ RS_DUMP(bytes, res);
+ }
+ if ((0x04 == bytes[0]) && (0x17 == bytes[4]) && (0xfc == bytes[5])) {
+ RS_DBG("H4 change uart speed success, receving status:%x", bytes[6]);
+ if (bytes[6] == 0)
+ return 0;
+ }
+ return -1;
+}
+
+/**
+* Parse realtek Bluetooth config file.
+* The config file if begin with vendor magic: RTK_VENDOR_CONFIG_MAGIC(8723ab55)
+* bt_addr is followed by 0x3c offset, it will be changed by bt_addr param
+* proto, baudrate and flow control is followed by 0xc offset,
+*
+* @param config_buf point to config file content
+* @param filelen length of config file
+* @param bt_addr where bt addr is stored
+* @return baudrate in config file
+*
+*/
+
+static uint32_t rtk_parse_config_file(uint8_t *config_buf, size_t filelen, char bt_addr[6])
+{
+ struct rtk_bt_vendor_config *config = (struct rtk_bt_vendor_config *) config_buf;
+ uint16_t config_len = le16_to_cpu(config->data_len), temp = 0;
+ struct rtk_bt_vendor_config_entry *entry = config->entry;
+
+ uint16_t i;
+ uint32_t baudrate = 0;
+
+ if (le32_to_cpu(config->signature) != RTK_VENDOR_CONFIG_MAGIC) {
+ RS_ERR("config signature magic number(%x) is not set to RTK_VENDOR_CONFIG_MAGIC", (int)config->signature);
+ return 0;
+ }
+
+ if (config_len != filelen - sizeof(struct rtk_bt_vendor_config)) {
+ RS_ERR("config len(%x) is not right(%x)", config_len, filelen-sizeof(struct rtk_bt_vendor_config));
+ return 0;
+ }
+
+ for (i = 0; i < config_len;) {
+ switch (le16_to_cpu(entry->offset)) {
+ case 0x3c:
+ {
+ int j = 0;
+ for (j = 0; j < entry->entry_len; j++)
+ entry->entry_data[j] = bt_addr[entry->entry_len - 1 - j];
+ }
+ break;
+ case 0xc:
+#ifdef BAUDRATE_4BYTES
+ baudrate = *(uint32_t *)entry->entry_data;
+#else
+ baudrate = *(uint16_t *)entry->entry_data;
+#endif
+ gHwFlowControlEnable = 0;
+ if (entry->entry_len >= 12) { //0ffset 0x18 - 0xc
+ gHwFlowControlEnable = (entry->entry_data[12] & 0x4) ? 1:0; //0x18 byte bit2
+ }
+ RS_DBG("config baud rate to :%x, hwflowcontrol:%x, %x", (int)baudrate, entry->entry_data[12], gHwFlowControlEnable);
+ break;
+ default:
+ RS_DBG("config offset(%x),length(%x)", entry->offset, entry->entry_len);
+ break;
+ }
+ temp = entry->entry_len + sizeof(struct rtk_bt_vendor_config_entry);
+ i += temp;
+ entry = (struct rtk_bt_vendor_config_entry *)((uint8_t *)entry + temp);
+ }
+
+ return baudrate;
+}
+
+/**
+* get random realtek Bluetooth addr.
+*
+* @param bt_addr where bt addr is stored
+*
+*/
+static void rtk_get_ram_addr(char bt_addr[0])
+{
+ srand(time(NULL)+getpid()+getpid()*987654+rand());
+
+ uint32_t addr = rand();
+ memcpy(bt_addr, &addr, sizeof(uint8_t));
+}
+
+/**
+* Write the random bt addr to the file /data/misc/bluetooth/btmac.txt.
+*
+* @param bt_addr where bt addr is stored
+*
+*/
+static void rtk_write_btmac2file(char bt_addr[6])
+{
+ int fd;
+ mkdir(BT_ADDR_DIR, 0777);
+ fd = open(BT_ADDR_FILE, O_CREAT|O_RDWR|O_TRUNC, 0666);
+
+ if (fd > 0) {
+ chmod(BT_ADDR_FILE, 0666);
+ char addr[18] = {0};
+ addr[17] = '\0';
+ sprintf(addr, "%2x:%2x:%2x:%2x:%2x:%2x", bt_addr[0], bt_addr[1], bt_addr[2], bt_addr[3], bt_addr[4], bt_addr[5]);
+ write(fd, addr, strlen(addr));
+ close(fd);
+ } else {
+ RS_ERR("open file error:%s\n", BT_ADDR_FILE);
+ }
+}
+
+/**
+* Get realtek Bluetooth config file. The bt addr arg is stored in /data/btmac.txt, if there is not this file,
+* change to /data/misc/bluetooth/btmac.txt. If both of them are not found, using
+* random bt addr.
+*
+* The config file is rtk8723_bt_config whose bt addr will be changed by the one read previous
+*
+* @param config_buf point to the content of realtek Bluetooth config file
+* @param config_baud_rate the baudrate set in the config file
+* @return file_len the length of config file
+*/
+static int rtk_get_bt_config(uint8_t **config_buf, uint32_t *config_baud_rate, patch_info *info)
+{
+ char bt_config_file_name[PATH_MAX] = {0};
+ char bt_addr[6] = {0x00, 0xe0, 0x4c, 0x88, 0x88, 0x88};
+ struct stat st;
+ size_t filelen;
+ int fd;
+ FILE *file = NULL;
+ int i = 0;
+
+ sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, "btmac.txt");
+ RS_DBG("BT mac addr file: %s", bt_config_file_name);
+ if (stat(bt_config_file_name, &st) < 0) {
+ RS_ERR("can't access bt bt_mac_addr file:%s, try use another path", bt_config_file_name);
+ sprintf(bt_config_file_name, BT_ADDR_FILE);
+ if (stat(bt_config_file_name, &st) < 0) {
+ RS_ERR("can't access bt bt_mac_addr file:%s, try use ramdom BT Addr", bt_config_file_name);
+
+ for (i = 0; i < 6; i++)
+ rtk_get_ram_addr(&bt_addr[i]);
+ rtk_write_btmac2file(bt_addr);
+ goto GET_CONFIG;
+ }
+ }
+
+ filelen = st.st_size;
+ file = fopen(bt_config_file_name, "rb");
+ if (file == NULL) {
+ RS_ERR("Can't open bt btaddr file, just use preset BT Addr");
+ } else {
+ fscanf(file, "%2x:%2x:%2x:%2x:%2x:%2x", (int *)&bt_addr[0], (uint32_t *)&bt_addr[1], (uint32_t *)&bt_addr[2], (uint32_t *)&bt_addr[3], (uint32_t *)&bt_addr[4], (uint32_t *)&bt_addr[5]);
+ /* do not set bt_add[0] to zero */
+ /* reserve LAP addr from 0x9e8b00 to 0x9e8b3f, change to 0x008b */
+ if (0x9e == bt_addr[3] && 0x8b == bt_addr[4] && (bt_addr[5] <= 0x3f)) {
+ /* get random value */
+ bt_addr[3] = 0x00;
+ }
+ RS_DBG("BT MAC IS : %02X:%02X:%02X:%02X:%02X:%02X", bt_addr[0], bt_addr[1], bt_addr[2], bt_addr[3], bt_addr[4], bt_addr[5]);
+ }
+
+GET_CONFIG:
+ if (info != NULL) {
+ sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, info->config_name);
+ } else {
+ sprintf(bt_config_file_name, "%s/%s", BT_CONFIG_DIRECTORY, "rtlbt_config");
+ }
+ RS_DBG("Final bt config file: %s", bt_config_file_name);
+
+ if (stat(bt_config_file_name, &st) < 0) {
+ RS_ERR("Can't access firmware, errno:%d", errno);
+ return -1;
+ }
+
+ filelen = st.st_size;
+
+ fd = open(bt_config_file_name, O_RDONLY);
+ if (fd < 0) {
+ perror("Can't open bt config file");
+ return -1;
+ }
+
+ *config_buf = malloc(filelen);
+ if (*config_buf == NULL) {
+ RS_DBG("malloc buffer for config file fail(%x)\n", filelen);
+ close(fd);
+ return -1;
+ }
+
+ /* we may need to parse this config file. */
+ /* for easy debug, only get need data. */
+ if (read(fd, *config_buf, filelen) < (ssize_t)filelen) {
+ perror("Can't load bt config file");
+ free(*config_buf);
+ *config_buf = NULL;
+ close(fd);
+ return -1;
+ }
+
+ *config_baud_rate = rtk_parse_config_file(*config_buf, filelen, bt_addr);
+ RS_DBG("Get config baud rate(4 bytes) from config file:%x", (int)*config_baud_rate);
+
+ close(fd);
+ return filelen;
+}
+
+/**
+* Realtek change speed with h5 proto. Using vendor specified command packet to achieve this.
+*
+* @warning it will waiting 2s for reply.
+*
+* @param fd uart file descriptor
+* @param baudrate the speed want to change
+*
+*/
+static int rtk_vendor_change_speed_h5(int fd, uint32_t baudrate)
+{
+ struct sk_buff *cmd_change_bdrate = NULL;
+ uint8_t cmd[7] = {0};
+ int retlen;
+ char bytes[READ_DATA_SIZE];
+ struct sigaction sa;
+
+ sa.sa_handler = h5_tinit_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ cmd[0] = 0x17; /* ocf */
+ cmd[1] = 0xfc; /* ogf, vendor specified */
+
+ cmd[2] = 4; /* length */
+#ifdef BAUDRATE_4BYTES
+ memcpy((uint16_t *)&cmd[3], &baudrate, 4);
+#else
+ memcpy((uint16_t *)&cmd[3], &baudrate, 2);
+ cmd[5] = 0;
+ cmd[6] = 0;
+#endif
+
+ if (DBG_ON) {
+ RS_DUMP(cmd, 7);
+ RS_DBG("change speed command ready baudrate=%d n", baudrate);
+ }
+ cmd_change_bdrate = h5_prepare_pkt(&rtk_h5, cmd, 7, HCI_COMMAND_PKT);
+ if (!cmd_change_bdrate) {
+ RS_ERR("Prepare command packet for change speed fail");
+ return -1;
+ }
+
+ rtk_h5.host_last_cmd = cmd_change_bdrate;
+ alarm(1);
+ write(fd, cmd_change_bdrate->data, cmd_change_bdrate->data_len);
+
+ while (rtk_h5.link_estab_state == H5_INIT) {
+ retlen = read_check(fd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return -1;
+ }
+
+ /* add pure ack check */
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+
+ alarm(0);
+ return 0;
+}
+
+/**
+* Init realtek Bluetooth h5 proto. h5 proto is added by realtek in the right kernel.
+* Generally there are two steps: h5 sync and h5 config
+*
+* @param fd uart file descriptor
+* @param ti termios struct
+*
+*/
+static int rtk_init_h5(int fd, struct termios *ti)
+{
+ char bytes[READ_DATA_SIZE];
+ struct sigaction sa;
+ int retlen;
+ struct itimerval value;
+
+ /* set even parity here */
+ ti->c_cflag |= PARENB;
+ ti->c_cflag &= ~(PARODD);
+ if (tcsetattr(fd, TCSANOW, ti) < 0) {
+ RS_ERR("Can't set port settings");
+ return -1;
+ }
+
+ alarm(0);
+ serial_fd = fd;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = h5_tshy_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+
+ /* h5 sync */
+ h5_tshy_sig_alarm(0);
+ memset(&rtk_h5, 0, sizeof(rtk_h5));
+ rtk_h5.link_estab_state = H5_SYNC;
+ while (rtk_h5.link_estab_state == H5_SYNC) {
+ retlen = read_check(fd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ RS_ERR("H5 Read Sync Response Failed");
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &value, NULL);
+ return -1;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &value, NULL);
+
+ /* h5 config */
+ sa.sa_handler = h5_tconf_sig_alarm;
+ sigaction(SIGALRM, &sa, NULL);
+ h5_tconf_sig_alarm(0);
+ while (rtk_h5.link_estab_state == H5_CONFIG) {
+ retlen = read_check(fd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ RS_ERR("H5 Read Config Response Failed");
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &value, NULL);
+ return -1;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+ /* retry per 250ms */
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &value, NULL);
+
+ rtk_send_pure_ack_down(fd);
+ RS_DBG("H5 init finished\n");
+ return 0;
+}
+
+/**
+* Download realtek firmware and config file from uart with the proto.
+* Parse the content to serval packets follow the proto and then write the packets from uart
+*
+* @param fd uart file descriptor
+* @param buf addr where stor the content of firmware and config file
+* @param filesize length of buf
+* @param is_sent_changerate if baudrate need to be changed
+* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE
+*
+*/
+static void rtk_download_fw_config(int fd, uint8_t *buf, size_t filesize, int is_sent_changerate, int proto, struct termios *ti)
+{
+ uint8_t iCurIndex = 0;
+ uint8_t iCurLen = 0;
+ uint8_t iEndIndex = 0;
+ uint8_t iLastPacketLen = 0;
+ uint8_t iAdditionPkt = 0;
+ uint8_t iTotalIndex = 0;
+ uint8_t iCmdSentNum = 0; /* the number of CMDs which have been sent */
+ uint8_t *bufpatch;
+
+ iEndIndex = (uint8_t)((filesize-1)/PATCH_DATA_FIELD_MAX_SIZE);
+ iLastPacketLen = (filesize)%PATCH_DATA_FIELD_MAX_SIZE;
+
+ if (is_sent_changerate)
+ iCmdSentNum++;
+ if (gRom_version_cmd_state >= cmd_has_sent)
+ iCmdSentNum++;
+ if (ghci_version_cmd_state >= cmd_has_sent)
+ iCmdSentNum++;
+ if (gchip_type_cmd_state >= cmd_has_sent)
+ iCmdSentNum++;
+
+ iAdditionPkt = (iEndIndex+1+iCmdSentNum)%8?(8-(iEndIndex+1+iCmdSentNum)%8):0;
+ iTotalIndex = iAdditionPkt + iEndIndex;
+ rtk_patch.nTotal = iTotalIndex; /* init TotalIndex */
+
+ RS_DBG("iEndIndex:%d iLastPacketLen:%d iAdditionpkt:%d\n", iEndIndex, iLastPacketLen, iAdditionPkt);
+
+ if (iLastPacketLen == 0)
+ iLastPacketLen = PATCH_DATA_FIELD_MAX_SIZE;
+
+ bufpatch = buf;
+
+ int i;
+ for (i = 0; i <= iTotalIndex; i++) {
+ if (iCurIndex < iEndIndex) {
+ iCurIndex = iCurIndex&0x7F;
+ iCurLen = PATCH_DATA_FIELD_MAX_SIZE;
+ } else if (iCurIndex == iEndIndex) { /* send last data packet */
+ if (iCurIndex == iTotalIndex)
+ iCurIndex = iCurIndex | 0x80;
+ else
+ iCurIndex = iCurIndex&0x7F;
+ iCurLen = iLastPacketLen;
+ } else if (iCurIndex < iTotalIndex) {
+ iCurIndex = iCurIndex&0x7F;
+ bufpatch = NULL;
+ iCurLen = 0;
+ } else { /* send end packet */
+ bufpatch = NULL;
+ iCurLen = 0;
+ iCurIndex = iCurIndex|0x80;
+ }
+
+ if (iCurIndex & 0x80)
+ RS_DBG("Send FW last command");
+
+ if (proto == HCI_UART_H4) {
+ iCurIndex = hci_download_patch_h4(fd, iCurIndex, bufpatch, iCurLen);
+ if ((iCurIndex != i) && (i != rtk_patch.nTotal)) {
+ /* check index but ignore last pkt */
+ RS_DBG("index mismatch i:%d iCurIndex:%d, patch fail\n", i, iCurIndex);
+ return;
+ }
+ } else if (proto == HCI_UART_3WIRE)
+ hci_download_patch(fd, iCurIndex, bufpatch, iCurLen, ti);
+
+ if (iCurIndex < iEndIndex) {
+ bufpatch += PATCH_DATA_FIELD_MAX_SIZE;
+ }
+ iCurIndex++;
+ }
+
+ /* set last ack packet down */
+ if (proto == HCI_UART_3WIRE) {
+ rtk_send_pure_ack_down(fd);
+ }
+}
+
+/**
+* Get realtek Bluetooth firmaware file. The content will be saved in *fw_buf which is malloc here.
+* The length malloc here will be lager than length of firmware file if there is a config file.
+* The content of config file will copy to the tail of *fw_buf in rtk_config.
+*
+* @param fw_buf point to the addr where stored the content of firmware.
+* @param addi_len length of config file.
+* @return length of *fw_buf.
+*
+*/
+static int rtk_get_bt_firmware(uint8_t **fw_buf, size_t addi_len, patch_info *info)
+{
+ char filename[PATH_MAX] = {0};
+ struct stat st;
+ int fd = -1;
+ size_t fwsize, buf_size;
+
+ if (info != NULL) {
+ sprintf(filename, "%s/%s", FIRMWARE_DIRECTORY, info->patch_name);
+ } else {
+ sprintf(filename, "%s/%s", FIRMWARE_DIRECTORY, "rtlbt_fw");
+ }
+
+ RS_DBG("Final bt firmware file: %s", filename);
+
+ if (stat(filename, &st) < 0) {
+ RS_ERR("Can't access firmware, errno:%d", errno);
+ return -1;
+ }
+
+ fwsize = st.st_size;
+ buf_size = fwsize + addi_len;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ RS_ERR("Can't open firmware, errno:%d", errno);
+ return -1;
+ }
+
+ *fw_buf = malloc(buf_size);
+ if (!(*fw_buf)) {
+ RS_ERR("Can't alloc memory for fw&config, errno:%d", errno);
+ close(fd);
+ return -1;
+ }
+
+ if (read(fd, *fw_buf, fwsize) < (ssize_t) fwsize) {
+ free(*fw_buf);
+ *fw_buf = NULL;
+ close(fd);
+ return -1;
+ }
+ RS_DBG("Load FW OK");
+ close(fd);
+ return buf_size;
+}
+
+/* These two function(rtk<-->uart speed transfer) need check Host uart speed at first!!!! IMPORTANT
+ * add more speed if neccessary */
+typedef struct _baudrate_ex {
+ uint32_t rtk_speed;
+ int uart_speed;
+} baudrate_ex;
+
+#ifdef BAUDRATE_4BYTES
+static baudrate_ex baudrates[] = {
+ {0x00006004, 921600},
+ {0x05F75004, 921600}, // RTL8723BS
+ {0x00004003, 1500000},
+ {0x04928002, 1500000}, // RTL8723BS
+ {0x00005002, 2000000}, // same as RTL8723AS
+ {0x00008001, 3000000},
+ {0x00009001, 3000000}, // Lory add new, t169 and t9e use 0x00009001.
+ {0x06DD8001, 3000000}, // RTL8723BS, Baudrate: 2920000
+ {0x036D8001, 3000000}, // RTL8723BS, Baudrate: 2929999
+ {0x06B58001, 3000000}, // RTL8723BS, Baudrate: 2940000
+ {0x02B58001, 3000000}, // RTL8723BS, Baudrate: 2945000
+ {0x02D58001, 3000000}, // RTL8723BS, Baudrate: 2950000
+ {0x05558001, 3000000}, // RTL8723BS, Baudrate: 2960000
+ {0x02AA8001, 3000000}, // RTL8723BS, Baudrate: 2969999
+ {0x052A8001, 3000000}, // RTL8723BS, Baudrate: 2980000
+ {0x04928001, 3000000}, // RTL8723BS, Baudrate: 2998000
+ {0x00007001, 3500000},
+ {0x052A6001, 3500000}, // RTL8723BS
+ {0x00005001, 4000000}, // same as RTL8723AS
+ {0x05AD9005, 547000},
+ {0x0252C00A, 230400},
+ {0x0000701d, 115200},
+ {0x0252C002, 115200}, // RTL8723BS
+ {0x0252C014, 115200} // RTL8723BS
+};
+
+#else
+static baudrate_ex baudrates[] = {
+ {0x7001, 3500000},
+ {0x6004, 921600},
+ {0x4003, 1500000},
+ {0x5001, 4000000},
+ {0x5002, 2000000},
+ {0x8001, 3000000},
+ {0x9001, 3000000},
+ {0x701d, 115200}
+};
+
+#endif
+
+
+/**
+* Change realtek Bluetooth speed to uart speed. It is matching in the struct baudrates:
+*
+* @code
+* baudrate_ex baudrates[] =
+* {
+* {0x7001, 3500000},
+* {0x6004, 921600},
+* {0x4003, 1500000},
+* {0x5001, 4000000},
+* {0x5002, 2000000},
+* {0x8001, 3000000},
+* {0x701d, 115200}
+* };
+* @endcode
+*
+* If there is no match in baudrates, uart speed will be set as #115200.
+*
+* @param rtk_speed realtek Bluetooth speed
+* @param uart_speed uart speed
+*
+*/
+static void rtk_speed_to_uart_speed(uint32_t rtk_speed, uint32_t *uart_speed)
+{
+ *uart_speed = 115200;
+
+ int i;
+ for (i = 0; i < sizeof(baudrates)/sizeof(baudrate_ex); i++) {
+ if (baudrates[i].rtk_speed == le32_to_cpu(rtk_speed)) {
+ *uart_speed = baudrates[i].uart_speed;
+ return;
+ }
+ }
+ return;
+}
+
+/**
+* Change uart speed to realtek Bluetooth speed. It is matching in the struct baudrates:
+*
+* @code
+* baudrate_ex baudrates[] =
+* {
+* {0x7001, 3500000},
+* {0x6004, 921600},
+* {0x4003, 1500000},
+* {0x5001, 4000000},
+* {0x5002, 2000000},
+* {0x8001, 3000000},
+* {0x701d, 115200}
+* };
+* @endcode
+*
+* If there is no match in baudrates, realtek Bluetooth speed will be set as #0x701D.
+*
+* @param uart_speed uart speed
+* @param rtk_speed realtek Bluetooth speed
+*
+*/
+static inline void uart_speed_to_rtk_speed(int uart_speed, uint32_t *rtk_speed)
+{
+ *rtk_speed = 0x701D;
+
+ int i;
+ for (i = 0; i < sizeof(baudrates) / sizeof(baudrate_ex); i++) {
+ if (baudrates[i].uart_speed == uart_speed) {
+ *rtk_speed = baudrates[i].rtk_speed;
+ return;
+ }
+ }
+
+ return;
+}
+
+static void rtk_get_eversion_timeout(int sig)
+{
+ static int retries;
+ RS_DBG("RTK get HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");
+ if (retries < h5_max_retries) {
+ RS_DBG("patch timerout, retry:\n");
+ if (rtk_h5.host_last_cmd) {
+ write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);
+ RS_DBG("3-wire download patch re send:%d", retries);
+ }
+ retries++;
+ alarm(3);
+ return;
+ }
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("rtk get eversion cmd complete event timed out\n");
+ exit(1);
+}
+
+/**
+* Send vendor cmd to get eversion: 0xfc6d
+* If Rom code does not support this cmd, use default.
+*/
+static void rtk_get_eversion(int dd)
+{
+ char bytes[READ_DATA_SIZE];
+ int retlen;
+ struct sigaction sa;
+ /* send HCI_VENDOR_READ_RTK_ROM_VERISION Command */
+ uint8_t read_rom_patch_cmd[3] = {0x6d, 0xfc, 0x00};
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 3, HCI_COMMAND_PKT); /* data: len+head: 4 */
+
+ if (rtk_h5.host_last_cmd) {
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ }
+
+ rtk_h5.host_last_cmd = nskb;
+
+ write(dd, nskb->data, nskb->data_len);
+ gRom_version_cmd_state = cmd_has_sent;
+ RS_DBG("RTK send HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");
+
+ alarm(0);
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = rtk_get_eversion_timeout;
+ sigaction(SIGALRM, &sa, NULL);
+
+ alarm(3);
+ while (gRom_version_cmd_state != event_received) {
+ retlen = read_check(dd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+ alarm(0);
+ return;
+}
+
+static void rtk_get_lmp_version_timeout(int sig)
+{
+ static int retries;
+ RS_DBG("RTK get HCI_VENDOR_READ_RTK_LMP_VERISION_Command\n");
+ if (retries < h5_max_retries) {
+ RS_DBG("patch timerout, retry:\n");
+ if (rtk_h5.host_last_cmd) {
+ write(serial_fd, rtk_h5.host_last_cmd->data, rtk_h5.host_last_cmd->data_len);
+ RS_DBG("3-wire download patch re send:%d", retries);
+ }
+ retries++;
+ alarm(3);
+ return;
+ }
+ tcflush(serial_fd, TCIOFLUSH);
+ RS_ERR("rtk get lmp version cmd complete event timed out\n");
+ exit(1);
+}
+
+static void rtk_get_lmp_version(int dd)
+{
+ char bytes[READ_DATA_SIZE];
+ int retlen;
+ struct sigaction sa;
+ /* send HCI_VENDOR_READ_RTK_ROM_VERISION_Command */
+ uint8_t read_rom_patch_cmd[3] = {0x01, 0x10, 00};
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 3, HCI_COMMAND_PKT); /* data: len+head: 4 */
+
+ if (rtk_h5.host_last_cmd) {
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ }
+
+ rtk_h5.host_last_cmd = nskb;
+
+ write(dd, nskb->data, nskb->data_len);
+ ghci_version_cmd_state = cmd_has_sent;
+ RS_DBG("RTK send HCI_VENDOR_READ_RTK_ROM_VERISION_Command\n");
+
+ alarm(0);
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = rtk_get_lmp_version_timeout;
+ sigaction(SIGALRM, &sa, NULL);
+
+ alarm(3);
+ while (ghci_version_cmd_state != event_received) {
+ retlen = read_check(dd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+ alarm(0);
+ return;
+}
+
+static void rtk_get_chip_type(int dd)
+{
+ char bytes[READ_DATA_SIZE];
+ int retlen;
+ struct sigaction sa;
+ uint8_t read_rom_patch_cmd[8] = {0x61, 0xfc, 0x05, 0x00, 0x94, 0xa0, 0x00, 0xb0};
+ struct sk_buff *nskb = h5_prepare_pkt(&rtk_h5, read_rom_patch_cmd, 8, HCI_COMMAND_PKT); /* data: len+head: 4 */
+
+ if (rtk_h5.host_last_cmd) {
+ skb_free(rtk_h5.host_last_cmd);
+ rtk_h5.host_last_cmd = NULL;
+ }
+
+ rtk_h5.host_last_cmd = nskb;
+
+ write(dd, nskb->data, nskb->data_len);
+ gchip_type_cmd_state = cmd_has_sent;
+ RS_DBG("RTK send HCI_VENDOR_READ_CHIP_TYPE Command");
+
+ alarm(0);
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP;
+ sa.sa_handler = rtk_get_lmp_version_timeout;
+ sigaction(SIGALRM, &sa, NULL);
+
+ alarm(3);
+ while (gchip_type_cmd_state != event_received) {
+ retlen = read_check(dd, &bytes, READ_DATA_SIZE);
+ if (retlen == -1) {
+ perror("read fail");
+ return;
+ }
+ h5_recv(&rtk_h5, &bytes, retlen);
+ }
+ alarm(0);
+ return;
+}
+
+static int check_match_state(bt_hw_cfg_cb_t *cfg, uint32_t mask)
+{
+ patch_info *patch_entry;
+ int res = 0;
+
+ for (patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {
+ if (patch_entry->lmp_subversion != cfg->lmp_subversion)
+ continue;
+ if ((patch_entry->hci_version_mask != HCI_VERSION_MASK_ALL) && ((patch_entry->hci_version_mask & (1 << cfg->hci_version)) == 0))
+ continue;
+ if ((patch_entry->hci_revision_mask != HCI_REVISION_MASK_ALL) && ((patch_entry->hci_revision_mask & (1 << cfg->hci_revision)) == 0))
+ continue;
+ if ((mask & PATCH_OPTIONAL_MATCH_FLAG_CHIPTYPE) && (patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL) && ((patch_entry->chip_type_mask & (1 << cfg->chip_type)) == 0))
+ continue;
+ res++;
+ }
+ RS_DBG("check_match_state return %d(cfg->lmp_subversion:0x%x cfg->hci_vesion:0x%x cfg->hci_revision:0x%x cfg->chip_type:0x%x mask:%08x)",
+ res, cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type, mask);
+ return res;
+}
+
+static patch_info *get_patch_entry(bt_hw_cfg_cb_t *cfg)
+{
+ patch_info *patch_entry;
+
+ RS_DBG("get_patch_entry(lmp_subversion:0x%x hci_vesion:0x%x cfg->hci_revision:0x%x chip_type:0x%x)",
+ cfg->lmp_subversion, cfg->hci_version, cfg->hci_revision, cfg->chip_type);
+ for (patch_entry = patch_table; patch_entry->lmp_subversion != LMP_SUBVERSION_NONE; patch_entry++) {
+ if (patch_entry->lmp_subversion != cfg->lmp_subversion)
+ continue;
+ if ((patch_entry->hci_version_mask != HCI_VERSION_MASK_ALL) && ((patch_entry->hci_version_mask & (1 << cfg->hci_version)) == 0))
+ continue;
+ if ((patch_entry->hci_revision_mask != HCI_REVISION_MASK_ALL) && ((patch_entry->hci_revision_mask & (1<hci_revision)) == 0))
+ continue;
+ if ((patch_entry->chip_type_mask != CHIP_TYPE_MASK_ALL) && ((patch_entry->chip_type_mask & (1<chip_type)) == 0))
+ continue;
+ break;
+ }
+ RS_DBG("get_patch_entry return(patch_name:%s config_name:%s mac_offset:0x%x)",
+ patch_entry->patch_name, patch_entry->config_name, patch_entry->mac_offset);
+ return patch_entry;
+}
+
+/**
+* Config realtek Bluetooth. The configuration parameter is get from config file and fw.
+*
+* @warning maybe only one of config file and fw file exists. The bt_addr arg is stored in "/data/btmac.txt"
+* or "/data/misc/bluetoothd/bt_mac/btmac.txt",
+*
+* @param fd uart file descriptor
+* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE
+* @param speed init_speed in uart struct
+* @param ti termios struct
+* @returns #0 on success
+*/
+static int rtk_config(int fd, int proto, int speed, struct termios *ti)
+{
+ int config_len = -1, buf_len = -1, final_speed = 0;
+ uint8_t *config_file_buf = NULL;
+ uint8_t *buf = NULL;
+ uint32_t baudrate = 0;
+
+ uint8_t *epatch_buf = NULL;
+ struct rtk_epatch *epatch_info = NULL;
+ struct rtk_epatch_entry current_entry;
+ uint8_t need_download_fw = 1;
+ patch_info *prtk_patch_file_info = NULL;
+
+ current_entry.start_offset = 0;
+ current_entry.patch_length = 0;
+ current_entry.chipID = 0;
+
+ /*
+ * 1. if both config file and fw exists, use it and change rate according to config file
+ * 2. if config file not exists while fw does, not change baudrate and only download fw
+ * 3. if fw doesnot exist, only change rate to 3.25M or from config file if it exist. This case is only for early debug before any efuse is setting.
+ */
+
+ /* Get version from ROM */
+ rtk_get_lmp_version(fd);
+ if (check_match_state(&hw_cfg_cb, 0) > 1) {
+ rtk_get_chip_type(fd);
+ RS_DBG("lmp_subversion = 0x%x, hci_version = 0x%x, hci_revision = 0x%x, chip_type = 0x%x",
+ hw_cfg_cb.lmp_subversion, hw_cfg_cb.hci_version, hw_cfg_cb.hci_revision, hw_cfg_cb.chip_type);
+ }
+
+ prtk_patch_file_info = get_patch_entry(&hw_cfg_cb);
+
+ if (prtk_patch_file_info == NULL) {
+ RS_ERR("lmp_version is %x, no matched project found!", hw_cfg_cb.lmp_subversion);
+ need_download_fw = 0;
+ goto FETCH_DONE;
+ }
+
+ config_len = rtk_get_bt_config(&config_file_buf, &baudrate, prtk_patch_file_info);
+ if (config_len < 0) {
+ RS_ERR("Get Config file error, just use efuse settings");
+ config_len = 0;
+ }
+
+ buf_len = rtk_get_bt_firmware(&epatch_buf, config_len, prtk_patch_file_info);
+ if (buf_len < 0) {
+ RS_ERR("Get BT firmware error, continue without bt firmware");
+ goto FETCH_DONE;
+ }
+
+ if (hw_cfg_cb.lmp_subversion == ROM_LMP_8723a) {
+ if (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) == 0) {
+ RS_ERR("8723as Check signature error!");
+ need_download_fw = 0;
+ goto FETCH_DONE;
+ }
+
+ buf = malloc(buf_len);
+ if (!buf) {
+ RS_ERR("Can't alloc memory for fw&config, errno:%d", errno);
+ buf_len = -1;
+ goto FETCH_DONE;
+ }
+
+ RS_DBG("8723as, fw copy direct");
+ memcpy(buf, epatch_buf, buf_len);
+ } else {
+ /* Get version from ROM */
+ rtk_get_eversion(fd); /* gEVersion is set. */
+ RS_DBG("gEVersion=%d", gEVersion);
+ /* check Extension Section Field */
+ if (memcmp(epatch_buf + buf_len - config_len - 4, Extension_Section_SIGNATURE, 4) != 0) {
+ RS_ERR("Check Extension_Section_SIGNATURE error! do not download fw");
+ need_download_fw = 0;
+ goto FETCH_DONE;
+ }
+
+ if (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) != 0) {
+ RS_DBG("Check signature error!");
+ need_download_fw = 0;
+ goto FETCH_DONE;
+ }
+
+ int i = 0;
+ uint32_t value_t = 0;
+ epatch_info = (struct rtk_epatch *)epatch_buf;
+ value_t = le32_to_cpu(epatch_info->fm_version);
+ epatch_info->fm_version = (uint32_t)value_t;
+ value_t = le16_to_cpu(epatch_info->number_of_total_patch);
+ epatch_info->number_of_total_patch = (uint16_t)value_t;
+ RS_DBG("fm_version = 0x%x", epatch_info->fm_version);
+ RS_DBG("number_of_total_patch = %d", epatch_info->number_of_total_patch);
+ /* get right epatch entry */
+ for (i = 0; i < epatch_info->number_of_total_patch; i++) {
+ if (le16_to_cpu(*(uint16_t *)(epatch_buf + 14 + 2 * i)) == gEVersion + 1) {
+ current_entry.chipID = gEVersion + 1;
+ current_entry.patch_length = le16_to_cpu(*(uint16_t *)(epatch_buf + 14 + 2 * epatch_info->number_of_total_patch + 2 * i));
+ current_entry.start_offset = le32_to_cpu(*(uint32_t *)(epatch_buf + 14 + 4 * epatch_info->number_of_total_patch + 4 * i));
+ break;
+ }
+ }
+ RS_DBG("chipID = %d", current_entry.chipID);
+ RS_DBG("patch_length = 0x%x", current_entry.patch_length);
+ RS_DBG("start_offset = 0x%x", current_entry.start_offset);
+ /* get right version patch: buf, buf_len */
+ buf_len = current_entry.patch_length + config_len;
+ RS_DBG("buf_len = 0x%x", buf_len);
+ buf = malloc(buf_len);
+ if (!buf) {
+ RS_ERR("Can't alloc memory for multi fw&config, errno:%d", errno);
+ buf_len = -1;
+ goto FETCH_DONE;
+ }
+ memcpy(buf, &epatch_buf[current_entry.start_offset], current_entry.patch_length);
+ value_t = cpu_to_le32(epatch_info->fm_version);
+ epatch_info->fm_version = (uint32_t)value_t;
+ memcpy(&buf[current_entry.patch_length-4], &epatch_info->fm_version, 4);
+ value_t = cpu_to_le32(epatch_info->fm_version);
+ epatch_info->fm_version = value_t;
+ }
+
+ if (config_len) {
+ memcpy(&buf[buf_len - config_len], config_file_buf, config_len);
+ }
+
+FETCH_DONE:
+ free(epatch_buf);
+ epatch_buf = NULL;
+ if (config_file_buf)
+ free(config_file_buf);
+
+ RS_DBG("Fw:%s exists, config file:%s exists", (buf_len > 0) ? "" : "not", (config_len > 0) ? "" : "not");
+ if ((buf_len > 0) && (config_len == 0)) {
+ rtk_h5.link_estab_state = H5_PATCH;
+ goto DOWNLOAD_FW;
+ }
+
+ /* change baudrate if needed */
+ if (baudrate == 0) {
+ uart_speed_to_rtk_speed(speed, &baudrate);
+ RS_DBG("Since no config file to set uart baudrate, so use user input parameters:%x, %x", (int)speed, (uint32_t)baudrate);
+ } else
+ rtk_speed_to_uart_speed(baudrate, (uint32_t *)&gFinalSpeed);
+
+ if (proto == HCI_UART_3WIRE)
+ rtk_vendor_change_speed_h5(fd, baudrate);
+ else
+ rtk_vendor_change_speed_h4(fd, baudrate);
+
+ usleep(50000);
+ final_speed = gFinalSpeed ? gFinalSpeed : speed;
+ RS_DBG("final_speed %d\n", final_speed);
+ if (set_speed(fd, ti, final_speed) < 0) {
+ RS_ERR("Can't set baud rate:%x, %x, %x", final_speed, gFinalSpeed, speed);
+ return -1;
+ }
+
+ if (gHwFlowControlEnable) {
+ RS_DBG("Hw Flow Control enable");
+ ti->c_cflag |= CRTSCTS;
+ } else {
+ RS_DBG("Hw Flow Control disable");
+ ti->c_cflag &= ~CRTSCTS;
+ }
+ RS_DBG("Hw Flow Control do not enable before download fw! ");
+
+ /* wait for while for controller to setup */
+ usleep(10000);
+
+DOWNLOAD_FW:
+ if (buf && (buf_len > 0) && (need_download_fw)) {
+ /* baudrate 0 means no change baudrate send */
+ memset(&rtk_patch, 0, sizeof(rtk_patch));
+ rtk_patch.nRxIndex = -1;
+
+ rtk_download_fw_config(fd, buf, buf_len, baudrate, proto, ti);
+ free(buf);
+ }
+ RS_DBG("Init Process finished");
+ return 0;
+}
+
+/**
+* Init uart by realtek Bluetooth.
+*
+* @param fd uart file descriptor
+* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE
+* @param speed init_speed in uart struct
+* @param ti termios struct
+* @returns #0 on success, depend on rtk_config
+*/
+int rtk_init(int fd, int proto, int speed, struct termios *ti)
+{
+ RS_DBG("Realtek hciattach version %s \n", RTK_VERSION);
+
+ if (proto == HCI_UART_3WIRE) { /*h4 will do nothing for init */
+ rtk_init_h5(fd, ti);
+ }
+ return rtk_config(fd, proto, speed, ti);
+}
+
+/**
+* Post uart by realtek Bluetooth. If gFinalSpeed is set, set uart speed with it.
+*
+* @param fd uart file descriptor
+* @param proto realtek Bluetooth protocol, shall be either HCI_UART_H4 or HCI_UART_3WIRE
+* @param ti termios struct
+* @returns #0 on success.
+*/
+int rtk_post(int fd, int proto, struct termios *ti)
+{
+ if (gFinalSpeed) {
+ return set_speed(fd, ti, gFinalSpeed);
+ }
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_sprd.c b/external/cache/sources/hcitools/hciattach_sprd.c
new file mode 100755
index 0000000..612e324
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_sprd.c
@@ -0,0 +1,806 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "hciattach.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+#define LOG_STR "SPRD Bluetooth"
+#define DBG_ON 1
+
+#define SPRD_DBG(fmt, arg...) \
+ do { \
+ if (DBG_ON) \
+ fprintf(stderr, "%s: " fmt "\n" , LOG_STR, ##arg); \
+ } while(0)
+
+#define SPRD_ERR(fmt, arg...) \
+ do { \
+ fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\
+ perror(LOG_STR" ERROR reason"); \
+ } while(0)
+
+#define SPRD_DUMP(buffer, len) \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ do { \
+ int i = 0; \
+ for (i = 0; i < len; i++) { \
+ if (i && !(i % 16)) { \
+ fprintf(stderr, "\n"); \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ } \
+ fprintf(stderr, "%02x ", buffer[i]); \
+ } \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+#define CONF_ITEM_TABLE(ITEM, ACTION, BUF, LEN) \
+ { #ITEM, ACTION, &(BUF.ITEM), LEN, (sizeof(BUF.ITEM) / LEN) }
+
+#define UINT8_TO_STREAM(p, u8) \
+ { *(p)++ = (uint8_t)(u8); }
+
+#define STREAM_TO_UINT8(u8, p) \
+ { \
+ (u8) = (uint8_t)(*(p)); \
+ (p) += 1; \
+ }
+
+#define UINT16_TO_STREAM(p, u16) \
+ { \
+ *(p)++ = (uint8_t)(u16); \
+ *(p)++ = (uint8_t)((u16) >> 8); \
+ }
+
+#define STREAM_TO_UINT16(u16, p) \
+ { \
+ (u16) = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
+ (p) += 2; \
+ }
+
+#define UINT32_TO_STREAM(p, u32) \
+ { \
+ *(p)++ = (uint8_t)(u32); \
+ *(p)++ = (uint8_t)((u32) >> 8); \
+ *(p)++ = (uint8_t)((u32) >> 16); \
+ *(p)++ = (uint8_t)((u32) >> 24); \
+ }
+
+#define CONF_COMMENT '#'
+#define CONF_DELIMITERS " =\n\r\t"
+#define CONF_VALUES_DELIMITERS "=\n\r\t#"
+#define CONF_VALUES_PARTITION " ,=\n\r\t#"
+#define CONF_MAX_LINE_LEN 255
+
+#define HCI_PSKEY 0xFCA0
+#define HCI_VSC_ENABLE_COMMMAND 0xFCA1
+#define HCI_RF_PARA 0xFCA2
+
+#define RESPONSE_LENGTH 100
+#define HCI_CMD_MAX_LEN 258
+#define HCI_EVT_CMD_CMPL_OPCODE 3
+#define HCI_PACKET_TYPE_COMMAND 1
+#define HCI_CMD_PREAMBLE_SIZE 3
+
+#define FW_NODE_BYTE 6
+#define FW_DATE_D_BYTE 8
+#define FW_DATE_M_BYTE 9
+#define FW_DATE_Y_BYTE 10
+
+#define BT_CONFIG_PATH "/lib/firmware"
+#define BT_HC_HDR_SIZE (sizeof(HC_BT_HDR))
+#define BT_VND_OP_RESULT_SUCCESS 0
+#define BT_VND_OP_RESULT_FAIL 1
+#define MSG_STACK_TO_HC_HCI_CMD 0x2000
+#define START_STOP_CMD_SIZE 3
+#define DUAL_MODE 0
+#define DISABLE_BT 0
+#define ENABLE_BT 1
+
+typedef void (*hci_cback)(void *);
+typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value, void *buf, int len, int size);
+
+typedef struct {
+ uint16_t event;
+ uint16_t len;
+ uint16_t offset;
+ uint16_t layer_specific;
+ uint8_t data[];
+} HC_BT_HDR;
+
+typedef struct {
+ uint32_t device_class;
+ uint8_t feature_set[16];
+ uint8_t device_addr[6];
+ uint16_t comp_id;
+ uint8_t g_sys_uart0_communication_supported;
+ uint8_t cp2_log_mode;
+ uint8_t LogLevel;
+ uint8_t g_central_or_perpheral;
+ uint16_t Log_BitMask;
+ uint8_t super_ssp_enable;
+ uint8_t common_rfu_b3;
+ uint32_t common_rfu_w[2];
+ uint32_t le_rfu_w[2];
+ uint32_t lmp_rfu_w[2];
+ uint32_t lc_rfu_w[2];
+ uint16_t g_wbs_nv_117;
+ uint16_t g_wbs_nv_118;
+ uint16_t g_nbv_nv_117;
+ uint16_t g_nbv_nv_118;
+ uint8_t g_sys_sco_transmit_mode;
+ uint8_t audio_rfu_b1;
+ uint8_t audio_rfu_b2;
+ uint8_t audio_rfu_b3;
+ uint32_t audio_rfu_w[2];
+ uint8_t g_sys_sleep_in_standby_supported;
+ uint8_t g_sys_sleep_master_supported;
+ uint8_t g_sys_sleep_slave_supported;
+ uint8_t power_rfu_b1;
+ uint32_t power_rfu_w[2];
+ uint32_t win_ext;
+ uint8_t edr_tx_edr_delay;
+ uint8_t edr_rx_edr_delay;
+ uint8_t tx_delay;
+ uint8_t rx_delay;
+ uint32_t bb_rfu_w[2];
+ uint8_t agc_mode;
+ uint8_t diff_or_eq;
+ uint8_t ramp_mode;
+ uint8_t modem_rfu_b1;
+ uint32_t modem_rfu_w[2];
+ uint32_t BQB_BitMask_1;
+ uint32_t BQB_BitMask_2;
+ uint16_t bt_coex_threshold[8];
+ uint32_t other_rfu_w[6];
+} pskey_config_t;
+
+typedef struct {
+ uint16_t g_GainValue_A[6];
+ uint16_t g_ClassicPowerValue_A[10];
+ uint16_t g_LEPowerValue_A[16];
+ uint16_t g_BRChannelpwrvalue_A[8];
+ uint16_t g_EDRChannelpwrvalue_A[8];
+ uint16_t g_LEChannelpwrvalue_A[8];
+ uint16_t g_GainValue_B[6];
+ uint16_t g_ClassicPowerValue_B[10];
+ uint16_t g_LEPowerValue_B[16];
+ uint16_t g_BRChannelpwrvalue_B[8];
+ uint16_t g_EDRChannelpwrvalue_B[8];
+ uint16_t g_LEChannelpwrvalue_B[8];
+ uint16_t LE_fix_powerword;
+ uint8_t Classic_pc_by_channel;
+ uint8_t LE_pc_by_channel;
+ uint8_t RF_switch_mode;
+ uint8_t Data_Capture_Mode;
+ uint8_t Analog_IQ_Debug_Mode;
+ uint8_t RF_common_rfu_b3;
+ uint32_t RF_common_rfu_w[5];
+} rf_config_t;
+
+typedef struct {
+ const char *conf_entry;
+ conf_action_t *p_action;
+ void *buf;
+ int len;
+ int size;
+} conf_entry_t;
+
+static uint8_t local_bdaddr[6]={0x10, 0x11, 0x12, 0x13, 0x14, 0x15};
+static pskey_config_t marlin3_pskey;
+static rf_config_t marlin3_rf_config;
+static int s_bt_fd = -1;
+
+static const conf_entry_t marlin3_pksey_table[] = {
+ CONF_ITEM_TABLE(device_class, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(feature_set, 0, marlin3_pskey, 16),
+ CONF_ITEM_TABLE(device_addr, 0, marlin3_pskey, 6),
+ CONF_ITEM_TABLE(comp_id, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_uart0_communication_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(cp2_log_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(LogLevel, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_central_or_perpheral, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(Log_BitMask, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(super_ssp_enable, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(common_rfu_b3, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(common_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(le_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(lmp_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(lc_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(g_wbs_nv_117, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_wbs_nv_118, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_nbv_nv_117, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_nbv_nv_118, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sco_transmit_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b2, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b3, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(g_sys_sleep_in_standby_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sleep_master_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sleep_slave_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(power_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(power_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(win_ext, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(edr_tx_edr_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(edr_rx_edr_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(tx_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(rx_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(bb_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(agc_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(diff_or_eq, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(ramp_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(modem_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(modem_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(BQB_BitMask_1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(BQB_BitMask_2, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(bt_coex_threshold, 0, marlin3_pskey, 8),
+ CONF_ITEM_TABLE(other_rfu_w, 0, marlin3_pskey, 6),
+ {0, 0, 0, 0, 0}
+};
+
+static const conf_entry_t marlin3_rf_table[] = {
+ CONF_ITEM_TABLE(g_GainValue_A, 0, marlin3_rf_config, 6),
+ CONF_ITEM_TABLE(g_ClassicPowerValue_A, 0, marlin3_rf_config, 10),
+ CONF_ITEM_TABLE(g_LEPowerValue_A, 0, marlin3_rf_config, 16),
+ CONF_ITEM_TABLE(g_BRChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_EDRChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_LEChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_GainValue_B, 0, marlin3_rf_config, 6),
+ CONF_ITEM_TABLE(g_ClassicPowerValue_B, 0, marlin3_rf_config, 10),
+ CONF_ITEM_TABLE(g_LEPowerValue_B, 0, marlin3_rf_config, 16),
+ CONF_ITEM_TABLE(g_BRChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_EDRChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_LEChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(LE_fix_powerword, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Classic_pc_by_channel, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(LE_pc_by_channel, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_switch_mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Data_Capture_Mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Analog_IQ_Debug_Mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_common_rfu_b3, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_common_rfu_w, 0, marlin3_rf_config, 5),
+ {0, 0, 0, 0, 0}
+};
+
+static void log_bin_to_hexstr(uint8_t *bin, uint8_t binsz, const char *log_tag)
+{
+ SPRD_DBG("%s", log_tag);
+ SPRD_DUMP(bin, binsz);
+}
+
+static void parse_number(char *p_conf_name, char *p_conf_value, void *buf, int len, int size)
+{
+ uint8_t *dest = (uint8_t *)buf;
+ char *sub_value, *p;
+ uint32_t value;
+ (void)p_conf_name;
+ sub_value = strtok_r(p_conf_value, CONF_VALUES_PARTITION, &p);
+ do {
+ if (sub_value == NULL)
+ break;
+
+ if (sub_value[0] == '0' && (sub_value[1] == 'x' || sub_value[1] == 'X'))
+ value = strtoul(sub_value, 0, 16) & 0xFFFFFFFF;
+ else
+ value = strtoul(sub_value, 0, 10) & 0xFFFFFFFF;
+
+ switch (size) {
+ case sizeof(uint8_t):
+ *dest = value & 0xFF;
+ dest += size;
+ break;
+
+ case sizeof(uint16_t):
+ *((uint16_t *)dest) = value & 0xFFFF;
+ dest += size;
+ break;
+
+ case sizeof(uint32_t):
+ *((uint32_t *)dest) = value & 0xFFFFFFFF;
+ dest += size;
+ break;
+
+ default:
+ break;
+ }
+ sub_value = strtok_r(NULL, CONF_VALUES_PARTITION, &p);
+ } while (--len);
+}
+
+static unsigned char compare_char(unsigned char ch)
+{
+ unsigned char data = 0x0;
+
+ switch(ch)
+ {
+ case 0:
+ case '0':
+ data = 0x0;
+ break;
+ case 1:
+ case '1':
+ data = 0x1;
+ break;
+ case 2:
+ case '2':
+ data = 0x2;
+ break;
+ case 3:
+ case '3':
+ data = 0x3;
+ break;
+ case 4:
+ case '4':
+ data = 0x4;
+ break;
+ case 5:
+ case '5':
+ data = 0x5;
+ break;
+ case 6:
+ case '6':
+ data = 0x6;
+ break;
+ case 7:
+ case '7':
+ data = 0x7;
+ break;
+ case 8:
+ case '8':
+ data = 0x8;
+ break;
+ case 9:
+ case '9':
+ data = 0x9;
+ break;
+ case 10:
+ case 'a':
+ case 'A':
+ data = 0xA;
+ break;
+ case 11:
+ case 'b':
+ case 'B':
+ data = 0xB;
+ break;
+ case 12:
+ case 'c':
+ case 'C':
+ data = 0xC;
+ break;
+ case 13:
+ case 'd':
+ case 'D':
+ data = 0xD;
+ break;
+ case 14:
+ case 'e':
+ case 'E':
+ data = 0xE;
+ break;
+ case 15:
+ case 'f':
+ case 'F':
+ data = 0xF;
+ break;
+ }
+ return data;
+}
+
+static void set_mac_address(uint8_t *addr)
+{
+ int i = 0;
+ unsigned char buff[255];
+ unsigned char tmp[5];
+ unsigned char str, str2;
+
+ FILE *fp = fopen("/sys/class/addr_mgt/addr_bt", "r");
+
+ SPRD_DBG("%s", __func__);
+
+ fscanf(fp, "%s", buff);
+ fclose(fp);
+
+ for (i=0; i<6; i++)
+ {
+ sprintf(tmp, "%c%c", buff[3*i], buff[3*i+1]);
+ str = compare_char(tmp[0]);
+ str2 = compare_char(tmp[1]);
+ local_bdaddr[i] = (str << 4) | str2;
+ }
+
+ for (i = 0; i < 6; i++)
+ addr[5-i] = (unsigned char)local_bdaddr[i];
+}
+
+static void vnd_load_configure(const char *p_path, const conf_entry_t *entry)
+{
+ FILE *p_file;
+ char *p_name, *p_value, *p;
+ conf_entry_t *p_entry;
+ char line[CONF_MAX_LINE_LEN + 1]; /* add 1 for \0 char */
+
+ SPRD_DBG("Attempt to load conf from %s", p_path);
+
+ if ((p_file = fopen(p_path, "r")) != NULL) {
+ /* read line by line */
+ while (fgets(line, CONF_MAX_LINE_LEN + 1, p_file) != NULL) {
+ if (line[0] == CONF_COMMENT) continue;
+
+ p_name = strtok_r(line, CONF_DELIMITERS, &p);
+
+ if (NULL == p_name) {
+ continue;
+ }
+
+ p_value = strtok_r(NULL, CONF_VALUES_DELIMITERS, &p);
+
+ if (NULL == p_value) {
+ SPRD_DBG("vnd_load_conf: missing value for name: %s", p_name);
+ continue;
+ }
+
+ p_entry = (conf_entry_t*)entry;
+
+ while (p_entry->conf_entry != NULL) {
+ if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0) {
+ if (p_entry->p_action) {
+ p_entry->p_action(p_name, p_value, p_entry->buf, p_entry->len,
+ p_entry->size);
+ } else {
+ SPRD_DBG("%s -> %s", p_name, p_value);
+ parse_number(p_name, p_value, p_entry->buf, p_entry->len,
+ p_entry->size);
+ }
+ break;
+ }
+
+ p_entry++;
+ }
+ }
+
+ fclose(p_file);
+ } else {
+ SPRD_DBG("vnd_load_conf file >%s< not found", p_path);
+ }
+}
+
+static size_t H4Protocol_Send(uint8_t type, const uint8_t* data, size_t length)
+{
+ struct iovec iov[] = {
+ {&type, sizeof(type)},
+ {(uint8_t *)data, length}};
+
+ ssize_t ret = 0;
+ do {
+ ret = writev(s_bt_fd, iov, sizeof(iov) / sizeof(iov[0]));
+ } while (-1 == ret && EAGAIN == errno);
+
+ if (ret == -1) {
+ SPRD_ERR("%s error writing to UART (%s)", __func__, strerror(errno));
+ } else if (ret < length + 1) {
+ SPRD_ERR("%s: %d / %d bytes written - something went wrong...", __func__, ret, length + 1);
+ }
+
+ return ret;
+}
+
+static void *bt_vendor_alloc(int size)
+{
+ void *p = (uint8_t *)malloc(size);
+ return p;
+}
+
+static void bt_vendor_free(void *buffer)
+{
+ free(buffer);
+}
+
+static uint8_t bt_vendor_xmit(uint16_t opcode, void* buffer, hci_cback callback)
+{
+ uint8_t type = HCI_PACKET_TYPE_COMMAND;
+ (void)opcode;
+ HC_BT_HDR* bt_hdr = (HC_BT_HDR *)buffer;
+ H4Protocol_Send(type, bt_hdr->data, bt_hdr->len);
+ return BT_VND_OP_RESULT_SUCCESS;
+}
+
+static uint8_t sprd_vnd_send_hci_vsc(uint16_t cmd, uint8_t *payload, uint8_t len, hci_cback cback)
+{
+ HC_BT_HDR *p_buf;
+ uint8_t *p, ret;
+
+ p_buf = (HC_BT_HDR *)bt_vendor_alloc(
+ BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + len);
+ if (p_buf) {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + len;
+ p = (uint8_t *)(p_buf + 1);
+
+ UINT16_TO_STREAM(p, cmd);
+ *p++ = len;
+ memcpy(p, payload, len);
+ log_bin_to_hexstr((uint8_t *)(p_buf + 1), HCI_CMD_PREAMBLE_SIZE + len, __FUNCTION__);
+ ret = bt_vendor_xmit(cmd, p_buf, cback);
+ bt_vendor_free(p_buf);
+ return ret;
+ }
+ return BT_VND_OP_RESULT_FAIL;
+}
+
+static void hw_core_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem;
+ uint8_t *p, status;
+ uint16_t opcode, mode;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode,p);
+ STREAM_TO_UINT16(mode,p);
+ STREAM_TO_UINT8(status,p);
+ SPRD_DBG("%s hw_core_cback response: [0x%04X, 0x%04X, 0x%02X]", __func__, opcode, mode, status);
+ bt_vendor_free(p_evt_buf);
+}
+
+static void hw_core_enable(unsigned char enable)
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ p = msg_req;
+ UINT16_TO_STREAM(p, DUAL_MODE);
+ UINT8_TO_STREAM(p, enable ? ENABLE_BT : DISABLE_BT);
+ sprd_vnd_send_hci_vsc(HCI_VSC_ENABLE_COMMMAND, msg_req, (uint8_t)(p - msg_req), NULL);
+}
+
+static void hw_rf_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem, len;
+ uint8_t *p, status;
+ uint16_t opcode, mode = 0;
+
+ p = (uint8_t *)(p_evt_buf + 1) + 1;
+ STREAM_TO_UINT8(len, p);
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode, p);
+ if (len == 6)
+ STREAM_TO_UINT16(mode, p);
+
+ STREAM_TO_UINT8(status, p);
+
+ SPRD_DBG("%s hw_rf_cback response: [0x%04X, 0x%04X, 0x%02X]", __func__, opcode, mode, status);
+ /* Must free the RX event buffer */
+ bt_vendor_free(p_evt_buf);
+}
+
+static int marlin3_rf_preload()
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ int i;
+
+ SPRD_DBG("yujian.qin %s", __FUNCTION__);
+ p = msg_req;
+
+ for (i = 0; i < 6; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_GainValue_A[i]);
+
+ for (i = 0; i < 10; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_ClassicPowerValue_A[i]);
+
+ for (i = 0; i < 16; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEPowerValue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_BRChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_EDRChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_GainValue_B[i]);
+
+ for (i = 0; i < 10; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_ClassicPowerValue_B[i]);
+
+ for (i = 0; i < 16; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEPowerValue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_BRChannelpwrvalue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_EDRChannelpwrvalue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEChannelpwrvalue_B[i]);
+
+ UINT16_TO_STREAM(p, marlin3_rf_config.LE_fix_powerword);
+
+ UINT8_TO_STREAM(p, marlin3_rf_config.Classic_pc_by_channel);
+ UINT8_TO_STREAM(p, marlin3_rf_config.LE_pc_by_channel);
+ UINT8_TO_STREAM(p, marlin3_rf_config.RF_switch_mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.Data_Capture_Mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.Analog_IQ_Debug_Mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.RF_common_rfu_b3);
+
+ for (i = 0; i < 5; i++)
+ UINT32_TO_STREAM(p, marlin3_rf_config.RF_common_rfu_w[i]);
+
+ sprd_vnd_send_hci_vsc(HCI_RF_PARA, msg_req, (uint8_t)(p - msg_req), NULL);
+ return 0;
+}
+
+static void marlin3_pskey_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem;
+
+ uint16_t opcode, node, year;
+ uint8_t *p, month, day;
+ (void)opcode;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode, p);
+
+ p = (uint8_t *)(p_evt_buf + 1) + FW_NODE_BYTE;
+ STREAM_TO_UINT16(node, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_Y_BYTE;
+ STREAM_TO_UINT16(year, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_M_BYTE;
+ STREAM_TO_UINT8(month, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_D_BYTE;
+ STREAM_TO_UINT8(day, p);
+
+ SPRD_DBG("Bluetooth Firmware Node: %04X Date: %04x-%02x-%02x", node, year, month, day);
+
+ /* Must free the RX event buffer */
+ bt_vendor_free(p_evt_buf);
+}
+
+static int marlin3_pskey_preload(void *arg)
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ int i;
+ (void)arg;
+
+ SPRD_DBG("%s", __FUNCTION__);
+ p = msg_req;
+ UINT32_TO_STREAM(p, marlin3_pskey.device_class);
+
+ for (i = 0; i < 16; i++)
+ UINT8_TO_STREAM(p, marlin3_pskey.feature_set[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT8_TO_STREAM(p, marlin3_pskey.device_addr[i]);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.comp_id);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_uart0_communication_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.cp2_log_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.LogLevel);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_central_or_perpheral);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.Log_BitMask);
+ UINT8_TO_STREAM(p, marlin3_pskey.super_ssp_enable);
+ UINT8_TO_STREAM(p, marlin3_pskey.common_rfu_b3);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.common_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.le_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.lmp_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.lc_rfu_w[i]);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.g_wbs_nv_117);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_wbs_nv_118);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_nbv_nv_117);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_nbv_nv_118);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sco_transmit_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b1);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b2);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b3);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.audio_rfu_w[i]);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_in_standby_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_master_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_slave_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.power_rfu_b1);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.power_rfu_w[i]);
+
+ UINT32_TO_STREAM(p, marlin3_pskey.win_ext);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.edr_tx_edr_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.edr_rx_edr_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.tx_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.rx_delay);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.bb_rfu_w[i]);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.agc_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.diff_or_eq);
+ UINT8_TO_STREAM(p, marlin3_pskey.ramp_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.modem_rfu_b1);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.modem_rfu_w[i]);
+
+ UINT32_TO_STREAM(p, marlin3_pskey.BQB_BitMask_1);
+ UINT32_TO_STREAM(p, marlin3_pskey.BQB_BitMask_2);
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_pskey.bt_coex_threshold[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.other_rfu_w[i]);
+
+ sprd_vnd_send_hci_vsc(HCI_PSKEY, msg_req, (uint8_t)(p - msg_req), NULL);
+ return 0;
+}
+
+
+int sprd_config_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ uint8_t *recv = NULL;
+ int len = 0;
+
+ s_bt_fd = fd;
+
+ memset(&marlin3_pskey, 0, sizeof(marlin3_pskey));
+ memset(&marlin3_rf_config, 0, sizeof(marlin3_rf_config));
+ vnd_load_configure(BT_CONFIG_PATH "/bt_configure_pskey.ini", &marlin3_pksey_table[0]);
+ vnd_load_configure(BT_CONFIG_PATH "/bt_configure_rf.ini", &marlin3_rf_table[0]);
+ set_mac_address(marlin3_pskey.device_addr);
+
+ marlin3_pskey_preload(NULL);
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ marlin3_pskey_cback(recv);
+
+ marlin3_rf_preload();
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ hw_rf_cback(recv);
+
+ hw_core_enable(1);
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ hw_core_cback(recv);
+
+ return 0;
+}
+
+int sprd_config_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ SPRD_DBG("Done setting line discpline");
+ return 0;
+}
+
diff --git a/external/cache/sources/hcitools/hciattach_sprd_2.c b/external/cache/sources/hcitools/hciattach_sprd_2.c
new file mode 100755
index 0000000..ce621b7
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_sprd_2.c
@@ -0,0 +1,809 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "hciattach.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+#define LOG_STR "SPRD Bluetooth"
+#define DBG_ON 1
+
+#define SPRD_DBG(fmt, arg...) \
+ do { \
+ if (DBG_ON) \
+ fprintf(stderr, "%s: " fmt "\n" , LOG_STR, ##arg); \
+ } while(0)
+
+#define SPRD_ERR(fmt, arg...) \
+ do { \
+ fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\
+ perror(LOG_STR" ERROR reason"); \
+ } while(0)
+
+#define SPRD_DUMP(buffer, len) \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ do { \
+ int i = 0; \
+ for (i = 0; i < len; i++) { \
+ if (i && !(i % 16)) { \
+ fprintf(stderr, "\n"); \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ } \
+ fprintf(stderr, "%02x ", buffer[i]); \
+ } \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+#define CONF_ITEM_TABLE(ITEM, ACTION, BUF, LEN) \
+ { #ITEM, ACTION, &(BUF.ITEM), LEN, (sizeof(BUF.ITEM) / LEN) }
+
+#define UINT8_TO_STREAM(p, u8) \
+ { *(p)++ = (uint8_t)(u8); }
+
+#define STREAM_TO_UINT8(u8, p) \
+ { \
+ (u8) = (uint8_t)(*(p)); \
+ (p) += 1; \
+ }
+
+#define UINT16_TO_STREAM(p, u16) \
+ { \
+ *(p)++ = (uint8_t)(u16); \
+ *(p)++ = (uint8_t)((u16) >> 8); \
+ }
+
+#define STREAM_TO_UINT16(u16, p) \
+ { \
+ (u16) = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
+ (p) += 2; \
+ }
+
+#define UINT32_TO_STREAM(p, u32) \
+ { \
+ *(p)++ = (uint8_t)(u32); \
+ *(p)++ = (uint8_t)((u32) >> 8); \
+ *(p)++ = (uint8_t)((u32) >> 16); \
+ *(p)++ = (uint8_t)((u32) >> 24); \
+ }
+
+#define CONF_COMMENT '#'
+#define CONF_DELIMITERS " =\n\r\t"
+#define CONF_VALUES_DELIMITERS "=\n\r\t#"
+#define CONF_VALUES_PARTITION " ,=\n\r\t#"
+#define CONF_MAX_LINE_LEN 255
+
+#define HCI_PSKEY 0xFCA0
+#define HCI_VSC_ENABLE_COMMMAND 0xFCA1
+#define HCI_RF_PARA 0xFCA2
+
+#define RESPONSE_LENGTH 100
+#define HCI_CMD_MAX_LEN 258
+#define HCI_EVT_CMD_CMPL_OPCODE 3
+#define HCI_PACKET_TYPE_COMMAND 1
+#define HCI_CMD_PREAMBLE_SIZE 3
+
+#define FW_NODE_BYTE 6
+#define FW_DATE_D_BYTE 8
+#define FW_DATE_M_BYTE 9
+#define FW_DATE_Y_BYTE 10
+
+#define BT_CONFIG_PATH "/lib/firmware"
+#define BT_HC_HDR_SIZE (sizeof(HC_BT_HDR))
+#define BT_VND_OP_RESULT_SUCCESS 0
+#define BT_VND_OP_RESULT_FAIL 1
+#define MSG_STACK_TO_HC_HCI_CMD 0x2000
+#define START_STOP_CMD_SIZE 3
+#define DUAL_MODE 0
+#define DISABLE_BT 0
+#define ENABLE_BT 1
+
+typedef void (*hci_cback)(void *);
+typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value, void *buf, int len, int size);
+
+typedef struct {
+ uint16_t event;
+ uint16_t len;
+ uint16_t offset;
+ uint16_t layer_specific;
+ uint8_t data[];
+} HC_BT_HDR;
+
+typedef struct {
+ uint32_t device_class;
+ uint8_t feature_set[16];
+ uint8_t device_addr[6];
+ uint16_t comp_id;
+ uint8_t g_sys_uart0_communication_supported;
+ uint8_t cp2_log_mode;
+ uint8_t LogLevel;
+ uint8_t g_central_or_perpheral;
+ uint16_t Log_BitMask;
+ uint8_t super_ssp_enable;
+ uint8_t common_rfu_b3;
+ uint32_t common_rfu_w[2];
+ uint32_t le_rfu_w[2];
+ uint32_t lmp_rfu_w[2];
+ uint32_t lc_rfu_w[2];
+ uint16_t g_wbs_nv_117;
+ uint16_t g_wbs_nv_118;
+ uint16_t g_nbv_nv_117;
+ uint16_t g_nbv_nv_118;
+ uint8_t g_sys_sco_transmit_mode;
+ uint8_t audio_rfu_b1;
+ uint8_t audio_rfu_b2;
+ uint8_t audio_rfu_b3;
+ uint32_t audio_rfu_w[2];
+ uint8_t g_sys_sleep_in_standby_supported;
+ uint8_t g_sys_sleep_master_supported;
+ uint8_t g_sys_sleep_slave_supported;
+ uint8_t power_rfu_b1;
+ uint32_t power_rfu_w[2];
+ uint32_t win_ext;
+ uint8_t edr_tx_edr_delay;
+ uint8_t edr_rx_edr_delay;
+ uint8_t tx_delay;
+ uint8_t rx_delay;
+ uint32_t bb_rfu_w[2];
+ uint8_t agc_mode;
+ uint8_t diff_or_eq;
+ uint8_t ramp_mode;
+ uint8_t modem_rfu_b1;
+ uint32_t modem_rfu_w[2];
+ uint32_t BQB_BitMask_1;
+ uint32_t BQB_BitMask_2;
+ uint16_t bt_coex_threshold[8];
+ uint32_t other_rfu_w[6];
+} pskey_config_t;
+
+typedef struct {
+ uint16_t g_GainValue_A[6];
+ uint16_t g_ClassicPowerValue_A[10];
+ uint16_t g_LEPowerValue_A[16];
+ uint16_t g_BRChannelpwrvalue_A[8];
+ uint16_t g_EDRChannelpwrvalue_A[8];
+ uint16_t g_LEChannelpwrvalue_A[8];
+ uint16_t g_GainValue_B[6];
+ uint16_t g_ClassicPowerValue_B[10];
+ uint16_t g_LEPowerValue_B[16];
+ uint16_t g_BRChannelpwrvalue_B[8];
+ uint16_t g_EDRChannelpwrvalue_B[8];
+ uint16_t g_LEChannelpwrvalue_B[8];
+ uint16_t LE_fix_powerword;
+ uint8_t Classic_pc_by_channel;
+ uint8_t LE_pc_by_channel;
+ uint8_t RF_switch_mode;
+ uint8_t Data_Capture_Mode;
+ uint8_t Analog_IQ_Debug_Mode;
+ uint8_t RF_common_rfu_b3;
+ uint32_t RF_common_rfu_w[5];
+} rf_config_t;
+
+typedef struct {
+ const char *conf_entry;
+ conf_action_t *p_action;
+ void *buf;
+ int len;
+ int size;
+} conf_entry_t;
+
+static uint8_t local_bdaddr[6]={0x10, 0x11, 0x12, 0x13, 0x14, 0x15};
+static pskey_config_t marlin3_pskey;
+static rf_config_t marlin3_rf_config;
+static int s_bt_fd = -1;
+
+static const conf_entry_t marlin3_pksey_table[] = {
+ CONF_ITEM_TABLE(device_class, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(feature_set, 0, marlin3_pskey, 16),
+ CONF_ITEM_TABLE(device_addr, 0, marlin3_pskey, 6),
+ CONF_ITEM_TABLE(comp_id, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_uart0_communication_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(cp2_log_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(LogLevel, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_central_or_perpheral, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(Log_BitMask, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(super_ssp_enable, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(common_rfu_b3, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(common_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(le_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(lmp_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(lc_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(g_wbs_nv_117, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_wbs_nv_118, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_nbv_nv_117, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_nbv_nv_118, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sco_transmit_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b2, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_b3, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(audio_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(g_sys_sleep_in_standby_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sleep_master_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(g_sys_sleep_slave_supported, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(power_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(power_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(win_ext, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(edr_tx_edr_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(edr_rx_edr_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(tx_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(rx_delay, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(bb_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(agc_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(diff_or_eq, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(ramp_mode, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(modem_rfu_b1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(modem_rfu_w, 0, marlin3_pskey, 2),
+ CONF_ITEM_TABLE(BQB_BitMask_1, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(BQB_BitMask_2, 0, marlin3_pskey, 1),
+ CONF_ITEM_TABLE(bt_coex_threshold, 0, marlin3_pskey, 8),
+ CONF_ITEM_TABLE(other_rfu_w, 0, marlin3_pskey, 6),
+ {0, 0, 0, 0, 0}
+};
+
+static const conf_entry_t marlin3_rf_table[] = {
+ CONF_ITEM_TABLE(g_GainValue_A, 0, marlin3_rf_config, 6),
+ CONF_ITEM_TABLE(g_ClassicPowerValue_A, 0, marlin3_rf_config, 10),
+ CONF_ITEM_TABLE(g_LEPowerValue_A, 0, marlin3_rf_config, 16),
+ CONF_ITEM_TABLE(g_BRChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_EDRChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_LEChannelpwrvalue_A, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_GainValue_B, 0, marlin3_rf_config, 6),
+ CONF_ITEM_TABLE(g_ClassicPowerValue_B, 0, marlin3_rf_config, 10),
+ CONF_ITEM_TABLE(g_LEPowerValue_B, 0, marlin3_rf_config, 16),
+ CONF_ITEM_TABLE(g_BRChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_EDRChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(g_LEChannelpwrvalue_B, 0, marlin3_rf_config, 8),
+ CONF_ITEM_TABLE(LE_fix_powerword, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Classic_pc_by_channel, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(LE_pc_by_channel, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_switch_mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Data_Capture_Mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(Analog_IQ_Debug_Mode, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_common_rfu_b3, 0, marlin3_rf_config, 1),
+ CONF_ITEM_TABLE(RF_common_rfu_w, 0, marlin3_rf_config, 5),
+ {0, 0, 0, 0, 0}
+};
+
+static void log_bin_to_hexstr(uint8_t *bin, uint8_t binsz, const char *log_tag)
+{
+ SPRD_DBG("%s", log_tag);
+ SPRD_DUMP(bin, binsz);
+}
+
+static void parse_number(char *p_conf_name, char *p_conf_value, void *buf, int len, int size)
+{
+ uint8_t *dest = (uint8_t *)buf;
+ char *sub_value, *p;
+ uint32_t value;
+ (void)p_conf_name;
+ sub_value = strtok_r(p_conf_value, CONF_VALUES_PARTITION, &p);
+ do {
+ if (sub_value == NULL)
+ break;
+
+ if (sub_value[0] == '0' && (sub_value[1] == 'x' || sub_value[1] == 'X'))
+ value = strtoul(sub_value, 0, 16) & 0xFFFFFFFF;
+ else
+ value = strtoul(sub_value, 0, 10) & 0xFFFFFFFF;
+
+ switch (size) {
+ case sizeof(uint8_t):
+ *dest = value & 0xFF;
+ dest += size;
+ break;
+
+ case sizeof(uint16_t):
+ *((uint16_t *)dest) = value & 0xFFFF;
+ dest += size;
+ break;
+
+ case sizeof(uint32_t):
+ *((uint32_t *)dest) = value & 0xFFFFFFFF;
+ dest += size;
+ break;
+
+ default:
+ break;
+ }
+ sub_value = strtok_r(NULL, CONF_VALUES_PARTITION, &p);
+ } while (--len);
+}
+
+static unsigned char compare_char(unsigned char ch)
+{
+ unsigned char data = 0x0;
+
+ switch(ch)
+ {
+ case 0:
+ case '0':
+ data = 0x0;
+ break;
+ case 1:
+ case '1':
+ data = 0x1;
+ break;
+ case 2:
+ case '2':
+ data = 0x2;
+ break;
+ case 3:
+ case '3':
+ data = 0x3;
+ break;
+ case 4:
+ case '4':
+ data = 0x4;
+ break;
+ case 5:
+ case '5':
+ data = 0x5;
+ break;
+ case 6:
+ case '6':
+ data = 0x6;
+ break;
+ case 7:
+ case '7':
+ data = 0x7;
+ break;
+ case 8:
+ case '8':
+ data = 0x8;
+ break;
+ case 9:
+ case '9':
+ data = 0x9;
+ break;
+ case 10:
+ case 'a':
+ case 'A':
+ data = 0xA;
+ break;
+ case 11:
+ case 'b':
+ case 'B':
+ data = 0xB;
+ break;
+ case 12:
+ case 'c':
+ case 'C':
+ data = 0xC;
+ break;
+ case 13:
+ case 'd':
+ case 'D':
+ data = 0xD;
+ break;
+ case 14:
+ case 'e':
+ case 'E':
+ data = 0xE;
+ break;
+ case 15:
+ case 'f':
+ case 'F':
+ data = 0xF;
+ break;
+ }
+ return data;
+}
+
+static void set_mac_address(uint8_t *addr)
+{
+ int i = 0;
+
+ FILE *fp = fopen("/sys/class/net/wlan0/address", "r");
+ unsigned char buff[255];
+ unsigned char tmp[5];
+ unsigned char str, str2;
+
+ SPRD_DBG("%s", __func__);
+
+ fscanf(fp, "%s", buff);
+ fclose(fp);
+
+ for (i=0; i<6; i++)
+ {
+ sprintf(tmp, "%c%c", buff[3*i], buff[3*i+1]);
+ str = compare_char(tmp[0]);
+ str2 = compare_char(tmp[1]);
+ local_bdaddr[i] = (str << 4) | str2;
+ }
+
+ for (i = 0; i < 6; i++)
+ addr[5-i] = (unsigned char)local_bdaddr[i];
+
+ addr[0] += 1;
+ addr[1] += 1;
+}
+
+static void vnd_load_configure(const char *p_path, const conf_entry_t *entry)
+{
+ FILE *p_file;
+ char *p_name, *p_value, *p;
+ conf_entry_t *p_entry;
+ char line[CONF_MAX_LINE_LEN + 1]; /* add 1 for \0 char */
+
+ SPRD_DBG("Attempt to load conf from %s", p_path);
+
+ if ((p_file = fopen(p_path, "r")) != NULL) {
+ /* read line by line */
+ while (fgets(line, CONF_MAX_LINE_LEN + 1, p_file) != NULL) {
+ if (line[0] == CONF_COMMENT) continue;
+
+ p_name = strtok_r(line, CONF_DELIMITERS, &p);
+
+ if (NULL == p_name) {
+ continue;
+ }
+
+ p_value = strtok_r(NULL, CONF_VALUES_DELIMITERS, &p);
+
+ if (NULL == p_value) {
+ SPRD_DBG("vnd_load_conf: missing value for name: %s", p_name);
+ continue;
+ }
+
+ p_entry = (conf_entry_t*)entry;
+
+ while (p_entry->conf_entry != NULL) {
+ if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0) {
+ if (p_entry->p_action) {
+ p_entry->p_action(p_name, p_value, p_entry->buf, p_entry->len,
+ p_entry->size);
+ } else {
+ SPRD_DBG("%s -> %s", p_name, p_value);
+ parse_number(p_name, p_value, p_entry->buf, p_entry->len,
+ p_entry->size);
+ }
+ break;
+ }
+
+ p_entry++;
+ }
+ }
+
+ fclose(p_file);
+ } else {
+ SPRD_DBG("vnd_load_conf file >%s< not found", p_path);
+ }
+}
+
+static size_t H4Protocol_Send(uint8_t type, const uint8_t* data, size_t length)
+{
+ struct iovec iov[] = {
+ {&type, sizeof(type)},
+ {(uint8_t *)data, length}};
+
+ ssize_t ret = 0;
+ do {
+ ret = writev(s_bt_fd, iov, sizeof(iov) / sizeof(iov[0]));
+ } while (-1 == ret && EAGAIN == errno);
+
+ if (ret == -1) {
+ SPRD_ERR("%s error writing to UART (%s)", __func__, strerror(errno));
+ } else if (ret < length + 1) {
+ SPRD_ERR("%s: %d / %d bytes written - something went wrong...", __func__, ret, length + 1);
+ }
+
+ return ret;
+}
+
+static void *bt_vendor_alloc(int size)
+{
+ void *p = (uint8_t *)malloc(size);
+ return p;
+}
+
+static void bt_vendor_free(void *buffer)
+{
+ free(buffer);
+}
+
+static uint8_t bt_vendor_xmit(uint16_t opcode, void* buffer, hci_cback callback)
+{
+ uint8_t type = HCI_PACKET_TYPE_COMMAND;
+ (void)opcode;
+ HC_BT_HDR* bt_hdr = (HC_BT_HDR *)buffer;
+ H4Protocol_Send(type, bt_hdr->data, bt_hdr->len);
+ return BT_VND_OP_RESULT_SUCCESS;
+}
+
+static uint8_t sprd_vnd_send_hci_vsc(uint16_t cmd, uint8_t *payload, uint8_t len, hci_cback cback)
+{
+ HC_BT_HDR *p_buf;
+ uint8_t *p, ret;
+
+ p_buf = (HC_BT_HDR *)bt_vendor_alloc(
+ BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + len);
+ if (p_buf) {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + len;
+ p = (uint8_t *)(p_buf + 1);
+
+ UINT16_TO_STREAM(p, cmd);
+ *p++ = len;
+ memcpy(p, payload, len);
+ log_bin_to_hexstr((uint8_t *)(p_buf + 1), HCI_CMD_PREAMBLE_SIZE + len, __FUNCTION__);
+ ret = bt_vendor_xmit(cmd, p_buf, cback);
+ bt_vendor_free(p_buf);
+ return ret;
+ }
+ return BT_VND_OP_RESULT_FAIL;
+}
+
+static void hw_core_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem;
+ uint8_t *p, status;
+ uint16_t opcode, mode;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode,p);
+ STREAM_TO_UINT16(mode,p);
+ STREAM_TO_UINT8(status,p);
+ SPRD_DBG("%s hw_core_cback response: [0x%04X, 0x%04X, 0x%02X]", __func__, opcode, mode, status);
+ bt_vendor_free(p_evt_buf);
+}
+
+static void hw_core_enable(unsigned char enable)
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ p = msg_req;
+ UINT16_TO_STREAM(p, DUAL_MODE);
+ UINT8_TO_STREAM(p, enable ? ENABLE_BT : DISABLE_BT);
+ sprd_vnd_send_hci_vsc(HCI_VSC_ENABLE_COMMMAND, msg_req, (uint8_t)(p - msg_req), NULL);
+}
+
+static void hw_rf_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem, len;
+ uint8_t *p, status;
+ uint16_t opcode, mode = 0;
+
+ p = (uint8_t *)(p_evt_buf + 1) + 1;
+ STREAM_TO_UINT8(len, p);
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode, p);
+ if (len == 6)
+ STREAM_TO_UINT16(mode, p);
+
+ STREAM_TO_UINT8(status, p);
+
+ SPRD_DBG("%s hw_rf_cback response: [0x%04X, 0x%04X, 0x%02X]", __func__, opcode, mode, status);
+ /* Must free the RX event buffer */
+ bt_vendor_free(p_evt_buf);
+}
+
+static int marlin3_rf_preload()
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ int i;
+
+ SPRD_DBG("yujian.qin %s", __FUNCTION__);
+ p = msg_req;
+
+ for (i = 0; i < 6; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_GainValue_A[i]);
+
+ for (i = 0; i < 10; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_ClassicPowerValue_A[i]);
+
+ for (i = 0; i < 16; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEPowerValue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_BRChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_EDRChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEChannelpwrvalue_A[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_GainValue_B[i]);
+
+ for (i = 0; i < 10; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_ClassicPowerValue_B[i]);
+
+ for (i = 0; i < 16; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEPowerValue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_BRChannelpwrvalue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_EDRChannelpwrvalue_B[i]);
+
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_rf_config.g_LEChannelpwrvalue_B[i]);
+
+ UINT16_TO_STREAM(p, marlin3_rf_config.LE_fix_powerword);
+
+ UINT8_TO_STREAM(p, marlin3_rf_config.Classic_pc_by_channel);
+ UINT8_TO_STREAM(p, marlin3_rf_config.LE_pc_by_channel);
+ UINT8_TO_STREAM(p, marlin3_rf_config.RF_switch_mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.Data_Capture_Mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.Analog_IQ_Debug_Mode);
+ UINT8_TO_STREAM(p, marlin3_rf_config.RF_common_rfu_b3);
+
+ for (i = 0; i < 5; i++)
+ UINT32_TO_STREAM(p, marlin3_rf_config.RF_common_rfu_w[i]);
+
+ sprd_vnd_send_hci_vsc(HCI_RF_PARA, msg_req, (uint8_t)(p - msg_req), NULL);
+ return 0;
+}
+
+static void marlin3_pskey_cback(void *p_mem)
+{
+ uint8_t *p_evt_buf = (uint8_t *)p_mem;
+
+ uint16_t opcode, node, year;
+ uint8_t *p, month, day;
+ (void)opcode;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode, p);
+
+ p = (uint8_t *)(p_evt_buf + 1) + FW_NODE_BYTE;
+ STREAM_TO_UINT16(node, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_Y_BYTE;
+ STREAM_TO_UINT16(year, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_M_BYTE;
+ STREAM_TO_UINT8(month, p);
+ p = (uint8_t *)(p_evt_buf + 1) + FW_DATE_D_BYTE;
+ STREAM_TO_UINT8(day, p);
+
+ SPRD_DBG("Bluetooth Firmware Node: %04X Date: %04x-%02x-%02x", node, year, month, day);
+
+ /* Must free the RX event buffer */
+ bt_vendor_free(p_evt_buf);
+}
+
+static int marlin3_pskey_preload(void *arg)
+{
+ uint8_t *p, msg_req[HCI_CMD_MAX_LEN];
+ int i;
+ (void)arg;
+
+ SPRD_DBG("%s", __FUNCTION__);
+ p = msg_req;
+ UINT32_TO_STREAM(p, marlin3_pskey.device_class);
+
+ for (i = 0; i < 16; i++)
+ UINT8_TO_STREAM(p, marlin3_pskey.feature_set[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT8_TO_STREAM(p, marlin3_pskey.device_addr[i]);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.comp_id);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_uart0_communication_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.cp2_log_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.LogLevel);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_central_or_perpheral);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.Log_BitMask);
+ UINT8_TO_STREAM(p, marlin3_pskey.super_ssp_enable);
+ UINT8_TO_STREAM(p, marlin3_pskey.common_rfu_b3);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.common_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.le_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.lmp_rfu_w[i]);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.lc_rfu_w[i]);
+
+ UINT16_TO_STREAM(p, marlin3_pskey.g_wbs_nv_117);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_wbs_nv_118);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_nbv_nv_117);
+ UINT16_TO_STREAM(p, marlin3_pskey.g_nbv_nv_118);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sco_transmit_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b1);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b2);
+ UINT8_TO_STREAM(p, marlin3_pskey.audio_rfu_b3);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.audio_rfu_w[i]);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_in_standby_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_master_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.g_sys_sleep_slave_supported);
+ UINT8_TO_STREAM(p, marlin3_pskey.power_rfu_b1);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.power_rfu_w[i]);
+
+ UINT32_TO_STREAM(p, marlin3_pskey.win_ext);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.edr_tx_edr_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.edr_rx_edr_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.tx_delay);
+ UINT8_TO_STREAM(p, marlin3_pskey.rx_delay);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.bb_rfu_w[i]);
+
+ UINT8_TO_STREAM(p, marlin3_pskey.agc_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.diff_or_eq);
+ UINT8_TO_STREAM(p, marlin3_pskey.ramp_mode);
+ UINT8_TO_STREAM(p, marlin3_pskey.modem_rfu_b1);
+
+ for (i = 0; i < 2; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.modem_rfu_w[i]);
+
+ UINT32_TO_STREAM(p, marlin3_pskey.BQB_BitMask_1);
+ UINT32_TO_STREAM(p, marlin3_pskey.BQB_BitMask_2);
+ for (i = 0; i < 8; i++)
+ UINT16_TO_STREAM(p, marlin3_pskey.bt_coex_threshold[i]);
+
+ for (i = 0; i < 6; i++)
+ UINT32_TO_STREAM(p, marlin3_pskey.other_rfu_w[i]);
+
+ sprd_vnd_send_hci_vsc(HCI_PSKEY, msg_req, (uint8_t)(p - msg_req), NULL);
+ return 0;
+}
+
+
+int sprd_config_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ uint8_t *recv = NULL;
+ int len = 0;
+
+ s_bt_fd = fd;
+
+ memset(&marlin3_pskey, 0, sizeof(marlin3_pskey));
+ memset(&marlin3_rf_config, 0, sizeof(marlin3_rf_config));
+ vnd_load_configure(BT_CONFIG_PATH "/bt_configure_pskey.ini", &marlin3_pksey_table[0]);
+ vnd_load_configure(BT_CONFIG_PATH "/bt_configure_rf.ini", &marlin3_rf_table[0]);
+ set_mac_address(marlin3_pskey.device_addr);
+
+ marlin3_pskey_preload(NULL);
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ marlin3_pskey_cback(recv);
+
+ marlin3_rf_preload();
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ hw_rf_cback(recv);
+
+ hw_core_enable(1);
+ recv = bt_vendor_alloc(RESPONSE_LENGTH);
+ len = read_hci_event(s_bt_fd, recv, RESPONSE_LENGTH);
+ SPRD_DBG("Received event, len: %d", len);
+ SPRD_DUMP(recv, len);
+ hw_core_cback(recv);
+
+ return 0;
+}
+
+int sprd_config_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ SPRD_DBG("Done setting line discpline");
+ return 0;
+}
+
diff --git a/external/cache/sources/hcitools/hciattach_st.c b/external/cache/sources/hcitools/hciattach_st.c
new file mode 100644
index 0000000..dbb7c47
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_st.c
@@ -0,0 +1,278 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "hciattach.h"
+
+static int debug = 0;
+
+static int do_command(int fd, uint8_t ogf, uint16_t ocf,
+ uint8_t *cparam, int clen, uint8_t *rparam, int rlen)
+{
+ //uint16_t opcode = (uint16_t) ((ocf & 0x03ff) | (ogf << 10));
+ unsigned char cp[260], rp[260];
+ int len, size, offset = 3;
+
+ cp[0] = 0x01;
+ cp[1] = ocf & 0xff;
+ cp[2] = ogf << 2 | ocf >> 8;
+ cp[3] = clen;
+
+ if (clen > 0)
+ memcpy(cp + 4, cparam, clen);
+
+ if (debug) {
+ int i;
+ printf("[<");
+ for (i = 0; i < clen + 4; i++)
+ printf(" %02x", cp[i]);
+ printf("]\n");
+ }
+
+ if (write(fd, cp, clen + 4) < 0)
+ return -1;
+
+ do {
+ if (read(fd, rp, 1) < 1)
+ return -1;
+ } while (rp[0] != 0x04);
+
+ if (read(fd, rp + 1, 2) < 2)
+ return -1;
+
+ do {
+ len = read(fd, rp + offset, sizeof(rp) - offset);
+ offset += len;
+ } while (offset < rp[2] + 3);
+
+ if (debug) {
+ int i;
+ printf("[>");
+ for (i = 0; i < offset; i++)
+ printf(" %02x", rp[i]);
+ printf("]\n");
+ }
+
+ if (rp[0] != 0x04) {
+ errno = EIO;
+ return -1;
+ }
+
+ switch (rp[1]) {
+ case 0x0e: /* command complete */
+ if (rp[6] != 0x00)
+ return -ENXIO;
+ offset = 3 + 4;
+ size = rp[2] - 4;
+ break;
+ case 0x0f: /* command status */
+ /* fall through */
+ default:
+ offset = 3;
+ size = rp[2];
+ break;
+ }
+
+ if (!rparam || rlen < size)
+ return -ENXIO;
+
+ memcpy(rparam, rp + offset, size);
+
+ return size;
+}
+
+static int load_file(int dd, uint16_t version, const char *suffix)
+{
+ DIR *dir;
+ struct dirent *d;
+ char pathname[PATH_MAX], filename[NAME_MAX], prefix[20];
+ unsigned char cmd[256];
+ unsigned char buf[256];
+ uint8_t seqnum = 0;
+ int fd, size, len, found_fw_file;
+
+ memset(filename, 0, sizeof(filename));
+
+ snprintf(prefix, sizeof(prefix), "STLC2500_R%d_%02d_",
+ version >> 8, version & 0xff);
+
+ strcpy(pathname, "/lib/firmware");
+ dir = opendir(pathname);
+ if (!dir) {
+ strcpy(pathname, ".");
+ dir = opendir(pathname);
+ if (!dir)
+ return -errno;
+ }
+
+ found_fw_file = 0;
+ while (1) {
+ d = readdir(dir);
+ if (!d)
+ break;
+
+ if (strncmp(d->d_name + strlen(d->d_name) - strlen(suffix),
+ suffix, strlen(suffix)))
+ continue;
+
+ if (strncmp(d->d_name, prefix, strlen(prefix)))
+ continue;
+
+ snprintf(filename, sizeof(filename), "%s/%s",
+ pathname, d->d_name);
+ found_fw_file = 1;
+ }
+
+ closedir(dir);
+
+ if (!found_fw_file)
+ return -ENOENT;
+
+ printf("Loading file %s\n", filename);
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror("Can't open firmware file");
+ return -errno;
+ }
+
+ while (1) {
+ size = read(fd, cmd + 1, 254);
+ if (size <= 0)
+ break;
+
+ cmd[0] = seqnum;
+
+ len = do_command(dd, 0xff, 0x002e, cmd, size + 1, buf, sizeof(buf));
+ if (len < 1)
+ break;
+
+ if (buf[0] != seqnum) {
+ fprintf(stderr, "Sequence number mismatch\n");
+ break;
+ }
+
+ seqnum++;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+int stlc2500_init(int dd, bdaddr_t *bdaddr)
+{
+ unsigned char cmd[16];
+ unsigned char buf[254];
+ uint16_t version;
+ int len;
+ int err;
+
+ /* Hci_Cmd_Ericsson_Read_Revision_Information */
+ len = do_command(dd, 0xff, 0x000f, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ printf("%s\n", buf);
+
+ /* HCI_Read_Local_Version_Information */
+ len = do_command(dd, 0x04, 0x0001, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ version = buf[2] << 8 | buf[1];
+
+ err = load_file(dd, version, ".ptc");
+ if (err < 0) {
+ if (err == -ENOENT)
+ fprintf(stderr, "No ROM patch file loaded.\n");
+ else
+ return -1;
+ }
+
+ err = load_file(dd, buf[2] << 8 | buf[1], ".ssf");
+ if (err < 0) {
+ if (err == -ENOENT)
+ fprintf(stderr, "No static settings file loaded.\n");
+ else
+ return -1;
+ }
+
+ cmd[0] = 0xfe;
+ cmd[1] = 0x06;
+ bacpy((bdaddr_t *) (cmd + 2), bdaddr);
+
+ /* Hci_Cmd_ST_Store_In_NVDS */
+ len = do_command(dd, 0xff, 0x0022, cmd, 8, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ /* HCI_Reset : applies parameters*/
+ len = do_command(dd, 0x03, 0x0003, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ return 0;
+}
+
+int bgb2xx_init(int dd, bdaddr_t *bdaddr)
+{
+ unsigned char cmd[16];
+ unsigned char buf[254];
+ int len;
+
+ len = do_command(dd, 0xff, 0x000f, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ printf("%s\n", buf);
+
+ cmd[0] = 0xfe;
+ cmd[1] = 0x06;
+ bacpy((bdaddr_t *) (cmd + 2), bdaddr);
+
+ len = do_command(dd, 0xff, 0x0022, cmd, 8, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ len = do_command(dd, 0x03, 0x0003, NULL, 0, buf, sizeof(buf));
+ if (len < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_ti.c b/external/cache/sources/hcitools/hciattach_ti.c
new file mode 100644
index 0000000..8322b45
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_ti.c
@@ -0,0 +1,533 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#ifdef HCIATTACH_DEBUG
+#define DPRINTF(x...) printf(x)
+#else
+#define DPRINTF(x...)
+#endif
+
+#define HCIUARTGETDEVICE _IOR('U', 202, int)
+
+#define MAKEWORD(a, b) ((uint16_t)(((uint8_t)(a)) | ((uint16_t)((uint8_t)(b))) << 8))
+
+#define TI_MANUFACTURER_ID 13
+
+#define FIRMWARE_DIRECTORY "/lib/firmware/ti-connectivity/"
+
+#define ACTION_SEND_COMMAND 1
+#define ACTION_WAIT_EVENT 2
+#define ACTION_SERIAL 3
+#define ACTION_DELAY 4
+#define ACTION_RUN_SCRIPT 5
+#define ACTION_REMARKS 6
+
+#define BRF_DEEP_SLEEP_OPCODE_BYTE_1 0x0c
+#define BRF_DEEP_SLEEP_OPCODE_BYTE_2 0xfd
+#define BRF_DEEP_SLEEP_OPCODE \
+ (BRF_DEEP_SLEEP_OPCODE_BYTE_1 | (BRF_DEEP_SLEEP_OPCODE_BYTE_2 << 8))
+
+#define FILE_HEADER_MAGIC 0x42535442
+
+/*
+ * BRF Firmware header
+ */
+struct bts_header {
+ uint32_t magic;
+ uint32_t version;
+ uint8_t future[24];
+ uint8_t actions[0];
+}__attribute__ ((packed));
+
+/*
+ * BRF Actions structure
+ */
+struct bts_action {
+ uint16_t type;
+ uint16_t size;
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+struct bts_action_send {
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+struct bts_action_wait {
+ uint32_t msec;
+ uint32_t size;
+ uint8_t data[0];
+}__attribute__ ((packed));
+
+struct bts_action_delay {
+ uint32_t msec;
+}__attribute__ ((packed));
+
+struct bts_action_serial {
+ uint32_t baud;
+ uint32_t flow_control;
+}__attribute__ ((packed));
+
+static FILE *bts_load_script(const char *file_name, uint32_t *version)
+{
+ struct bts_header header;
+ FILE *fp;
+
+ fp = fopen(file_name, "rb");
+ if (!fp) {
+ perror("can't open firmware file");
+ return NULL;
+ }
+
+ if (1 != fread(&header, sizeof(struct bts_header), 1, fp)) {
+ perror("can't read firmware file");
+ goto errclose;
+ }
+
+ if (header.magic != FILE_HEADER_MAGIC) {
+ fprintf(stderr, "%s not a legal TI firmware file\n", file_name);
+ goto errclose;
+ }
+
+ if (NULL != version)
+ *version = header.version;
+
+ return fp;
+
+errclose:
+ fclose(fp);
+
+ return NULL;
+}
+
+static unsigned long bts_fetch_action(FILE *fp, unsigned char *action_buf,
+ unsigned long buf_size, uint16_t *action_type)
+{
+ struct bts_action action_hdr;
+ unsigned long nread;
+
+ if (!fp)
+ return 0;
+
+ if (1 != fread(&action_hdr, sizeof(struct bts_action), 1, fp))
+ return 0;
+
+ if (action_hdr.size > buf_size) {
+ fprintf(stderr, "bts_next_action: not enough space to read next action\n");
+ return 0;
+ }
+
+ nread = fread(action_buf, sizeof(uint8_t), action_hdr.size, fp);
+ if (nread != (action_hdr.size)) {
+ fprintf(stderr, "bts_next_action: fread failed to read next action\n");
+ return 0;
+ }
+
+ *action_type = action_hdr.type;
+
+ return nread * sizeof(uint8_t);
+}
+
+static void bts_unload_script(FILE *fp)
+{
+ if (fp)
+ fclose(fp);
+}
+
+static int is_it_texas(const uint8_t *respond)
+{
+ uint16_t manufacturer_id;
+
+ manufacturer_id = MAKEWORD(respond[11], respond[12]);
+
+ return TI_MANUFACTURER_ID == manufacturer_id ? 1 : 0;
+}
+
+static const char *get_firmware_name(const uint8_t *respond)
+{
+ static char firmware_file_name[PATH_MAX] = {0};
+ uint16_t version = 0, chip = 0, min_ver = 0, maj_ver = 0;
+
+ version = MAKEWORD(respond[13], respond[14]);
+ chip = (version & 0x7C00) >> 10;
+ min_ver = (version & 0x007F);
+ maj_ver = (version & 0x0380) >> 7;
+
+ if (version & 0x8000)
+ maj_ver |= 0x0008;
+
+ sprintf(firmware_file_name, FIRMWARE_DIRECTORY "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
+
+ return firmware_file_name;
+}
+
+static void brf_delay(struct bts_action_delay *delay)
+{
+ usleep(1000 * delay->msec);
+}
+
+static int brf_set_serial_params(struct bts_action_serial *serial_action,
+ int fd, int *speed, struct termios *ti)
+{
+ fprintf(stderr, "texas: changing baud rate to %u, flow control to %u\n",
+ serial_action->baud, serial_action->flow_control );
+ tcflush(fd, TCIOFLUSH);
+
+ if (serial_action->flow_control)
+ ti->c_cflag |= CRTSCTS;
+ else
+ ti->c_cflag &= ~CRTSCTS;
+
+ if (tcsetattr(fd, TCSANOW, ti) < 0) {
+ perror("Can't set port settings");
+ return -1;
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ if (set_speed(fd, ti, serial_action->baud) < 0) {
+ perror("Can't set baud rate");
+ return -1;
+ }
+
+ if (speed)
+ *speed = serial_action->baud;
+
+ return 0;
+}
+
+static int brf_send_command_socket(int fd, struct bts_action_send *send_action)
+{
+ char response[1024] = {0};
+ hci_command_hdr *cmd = (hci_command_hdr *) send_action->data;
+ uint16_t opcode = cmd->opcode;
+
+ struct hci_request rq;
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = cmd_opcode_ogf(opcode);
+ rq.ocf = cmd_opcode_ocf(opcode);
+ rq.event = EVT_CMD_COMPLETE;
+ rq.cparam = &send_action->data[3];
+ rq.clen = send_action->data[2];
+ rq.rparam = response;
+ rq.rlen = sizeof(response);
+
+ if (hci_send_req(fd, &rq, 15) < 0) {
+ perror("Cannot send hci command to socket");
+ return -1;
+ }
+
+ /* verify success */
+ if (response[0]) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int brf_send_command_file(int fd, struct bts_action_send *send_action,
+ long size)
+{
+ unsigned char response[1024] = {0};
+ long ret = 0;
+
+ /* send command */
+ if (size != write(fd, send_action, size)) {
+ perror("Texas: Failed to write action command");
+ return -1;
+ }
+
+ /* read response */
+ ret = read_hci_event(fd, response, sizeof(response));
+ if (ret < 0) {
+ perror("texas: failed to read command response");
+ return -1;
+ }
+
+ /* verify success */
+ if (ret < 7 || 0 != response[6]) {
+ fprintf( stderr, "TI init command failed.\n" );
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int brf_send_command(int fd, struct bts_action_send *send_action,
+ long size, int hcill_installed)
+{
+ int ret = 0;
+ char *fixed_action;
+
+ /* remove packet type when giving to socket API */
+ if (hcill_installed) {
+ fixed_action = ((char *) send_action) + 1;
+ ret = brf_send_command_socket(fd, (struct bts_action_send *) fixed_action);
+ } else {
+ ret = brf_send_command_file(fd, send_action, size);
+ }
+
+ return ret;
+}
+
+static int brf_do_action(uint16_t brf_type, uint8_t *brf_action, long brf_size,
+ int fd, int *speed, struct termios *ti, int hcill_installed)
+{
+ int ret = 0;
+
+ switch (brf_type) {
+ case ACTION_SEND_COMMAND:
+ DPRINTF("W");
+ ret = brf_send_command(fd,
+ (struct bts_action_send *) brf_action,
+ brf_size, hcill_installed);
+ break;
+ case ACTION_WAIT_EVENT:
+ DPRINTF("R");
+ break;
+ case ACTION_SERIAL:
+ DPRINTF("S");
+ ret = brf_set_serial_params((struct bts_action_serial *) brf_action, fd, speed, ti);
+ break;
+ case ACTION_DELAY:
+ DPRINTF("D");
+ brf_delay((struct bts_action_delay *) brf_action);
+ break;
+ case ACTION_REMARKS:
+ DPRINTF("C");
+ break;
+ default:
+ fprintf(stderr, "brf_init: unknown firmware action type (%d)\n", brf_type);
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * tests whether a given brf action is a HCI_VS_Sleep_Mode_Configurations cmd
+ */
+static int brf_action_is_deep_sleep(uint8_t *brf_action, long brf_size,
+ uint16_t brf_type)
+{
+ uint16_t opcode;
+
+ if (brf_type != ACTION_SEND_COMMAND)
+ return 0;
+
+ if (brf_size < 3)
+ return 0;
+
+ if (brf_action[0] != HCI_COMMAND_PKT)
+ return 0;
+
+ /* HCI data is little endian */
+ opcode = brf_action[1] | (brf_action[2] << 8);
+
+ if (opcode != BRF_DEEP_SLEEP_OPCODE)
+ return 0;
+
+ /* action is deep sleep configuration command ! */
+ return 1;
+}
+
+/*
+ * This function is called twice.
+ * The first time it is called, it loads the brf script, and executes its
+ * commands until it reaches a deep sleep command (or its end).
+ * The second time it is called, it assumes HCILL protocol is set up,
+ * and sends rest of brf script via the supplied socket.
+ */
+static int brf_do_script(int fd, int *speed, struct termios *ti, const char *bts_file)
+{
+ int ret = 0, hcill_installed = bts_file ? 0 : 1;
+ uint32_t vers;
+ static FILE *brf_script_file = NULL;
+ static uint8_t brf_action[512];
+ static long brf_size;
+ static uint16_t brf_type;
+
+ /* is it the first time we are called ? */
+ if (0 == hcill_installed) {
+ DPRINTF("Sending script to serial device\n");
+ brf_script_file = bts_load_script(bts_file, &vers );
+ if (!brf_script_file) {
+ fprintf(stderr, "Warning: cannot find BTS file: %s\n",
+ bts_file);
+ return 0;
+ }
+
+ fprintf( stderr, "Loaded BTS script version %u\n", vers );
+
+ brf_size = bts_fetch_action(brf_script_file, brf_action,
+ sizeof(brf_action), &brf_type);
+ if (brf_size == 0) {
+ fprintf(stderr, "Warning: BTS file is empty !");
+ return 0;
+ }
+ }
+ else {
+ DPRINTF("Sending script to bluetooth socket\n");
+ }
+
+ /* execute current action and continue to parse brf script file */
+ while (brf_size != 0) {
+ ret = brf_do_action(brf_type, brf_action, brf_size,
+ fd, speed, ti, hcill_installed);
+ if (ret == -1)
+ break;
+
+ brf_size = bts_fetch_action(brf_script_file, brf_action,
+ sizeof(brf_action), &brf_type);
+
+ /* if this is the first time we run (no HCILL yet) */
+ /* and a deep sleep command is encountered */
+ /* we exit */
+ if (!hcill_installed &&
+ brf_action_is_deep_sleep(brf_action,
+ brf_size, brf_type))
+ return 0;
+ }
+
+ bts_unload_script(brf_script_file);
+ brf_script_file = NULL;
+ DPRINTF("\n");
+
+ return ret;
+}
+
+int texas_init(int fd, int *speed, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[4];
+ unsigned char resp[100]; /* Response */
+ const char *bts_file;
+ int n;
+
+ memset(resp,'\0', 100);
+
+ /* It is possible to get software version with manufacturer specific
+ HCI command HCI_VS_TI_Version_Number. But the only thing you get more
+ is if this is point-to-point or point-to-multipoint module */
+
+ /* Get Manufacturer and LMP version */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ do {
+ n = write(fd, cmd, 4);
+ if (n < 0) {
+ perror("Failed to write init command (READ_LOCAL_VERSION_INFORMATION)");
+ return -1;
+ }
+ if (n < 4) {
+ fprintf(stderr, "Wanted to write 4 bytes, could only write %d. Stop\n", n);
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response (READ_LOCAL_VERSION_INFORMATION)");
+ return -1;
+ }
+
+ /* Wait for command complete event for our Opcode */
+ } while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+ /* Verify manufacturer */
+ if (! is_it_texas(resp)) {
+ fprintf(stderr,"ERROR: module's manufacturer is not Texas Instruments\n");
+ return -1;
+ }
+
+ fprintf(stderr, "Found a Texas Instruments' chip!\n");
+
+ bts_file = get_firmware_name(resp);
+ fprintf(stderr, "Firmware file : %s\n", bts_file);
+
+ n = brf_do_script(fd, speed, ti, bts_file);
+
+ nanosleep(&tm, NULL);
+
+ return n;
+}
+
+int texas_post(int fd, struct termios *ti)
+{
+ int dev_id, dd, ret = 0;
+
+ sleep(1);
+
+ dev_id = ioctl(fd, HCIUARTGETDEVICE, 0);
+ if (dev_id < 0) {
+ perror("cannot get device id");
+ return -1;
+ }
+
+ DPRINTF("\nAdded device hci%d\n", dev_id);
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("HCI device open failed");
+ return -1;
+ }
+
+ if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) {
+ fprintf(stderr, "Can't init device hci%d: %s (%d)", dev_id,
+ strerror(errno), errno);
+ hci_close_dev(dd);
+ return -1;
+ }
+
+ ret = brf_do_script(dd, NULL, ti, NULL);
+
+ hci_close_dev(dd);
+
+ return ret;
+}
diff --git a/external/cache/sources/hcitools/hciattach_tialt.c b/external/cache/sources/hcitools/hciattach_tialt.c
new file mode 100644
index 0000000..c3caa49
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_tialt.c
@@ -0,0 +1,242 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2010 Marcel Holtmann
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "hciattach.h"
+
+#define FAILIF(x, args...) do { \
+ if (x) { \
+ fprintf(stderr, ##args); \
+ return -1; \
+ } \
+} while(0)
+
+typedef struct {
+ uint8_t uart_prefix;
+ hci_event_hdr hci_hdr;
+ evt_cmd_complete cmd_complete;
+ uint8_t status;
+ uint8_t data[16];
+} __attribute__((packed)) command_complete_t;
+
+static int read_command_complete(int fd, unsigned short opcode, unsigned char len) {
+ command_complete_t resp;
+ /* Read reply. */
+ FAILIF(read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0,
+ "Failed to read response");
+
+ /* Parse speed-change reply */
+ FAILIF(resp.uart_prefix != HCI_EVENT_PKT,
+ "Error in response: not an event packet, but 0x%02x!\n",
+ resp.uart_prefix);
+
+ FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE, /* event must be event-complete */
+ "Error in response: not a cmd-complete event, "
+ "but 0x%02x!\n", resp.hci_hdr.evt);
+
+ FAILIF(resp.hci_hdr.plen < 4, /* plen >= 4 for EVT_CMD_COMPLETE */
+ "Error in response: plen is not >= 4, but 0x%02x!\n",
+ resp.hci_hdr.plen);
+
+ /* cmd-complete event: opcode */
+ FAILIF(resp.cmd_complete.opcode != (uint16_t)opcode,
+ "Error in response: opcode is 0x%04x, not 0x%04x!",
+ resp.cmd_complete.opcode, opcode);
+
+ return resp.status == 0 ? 0 : -1;
+}
+
+typedef struct {
+ uint8_t uart_prefix;
+ hci_command_hdr hci_hdr;
+ uint32_t speed;
+} __attribute__((packed)) texas_speed_change_cmd_t;
+
+static int texas_change_speed(int fd, uint32_t speed)
+{
+ return 0;
+}
+
+static int texas_load_firmware(int fd, const char *firmware) {
+
+ int fw = open(firmware, O_RDONLY);
+
+ fprintf(stdout, "Opening firmware file: %s\n", firmware);
+
+ FAILIF(fw < 0,
+ "Could not open firmware file %s: %s (%d).\n",
+ firmware, strerror(errno), errno);
+
+ fprintf(stdout, "Uploading firmware...\n");
+ do {
+ /* Read each command and wait for a response. */
+ unsigned char data[1024];
+ unsigned char cmdp[1 + sizeof(hci_command_hdr)];
+ hci_command_hdr *cmd = (hci_command_hdr *)(cmdp + 1);
+ int nr;
+ nr = read(fw, cmdp, sizeof(cmdp));
+ if (!nr)
+ break;
+ FAILIF(nr != sizeof(cmdp), "Could not read H4 + HCI header!\n");
+ FAILIF(*cmdp != HCI_COMMAND_PKT, "Command is not an H4 command packet!\n");
+
+ FAILIF(read(fw, data, cmd->plen) != cmd->plen,
+ "Could not read %d bytes of data for command with opcode %04x!\n",
+ cmd->plen,
+ cmd->opcode);
+
+ {
+ int nw;
+#if 0
+ fprintf(stdout, "\topcode 0x%04x (%d bytes of data).\n",
+ cmd->opcode,
+ cmd->plen);
+#endif
+ struct iovec iov_cmd[2];
+ iov_cmd[0].iov_base = cmdp;
+ iov_cmd[0].iov_len = sizeof(cmdp);
+ iov_cmd[1].iov_base = data;
+ iov_cmd[1].iov_len = cmd->plen;
+ nw = writev(fd, iov_cmd, 2);
+ FAILIF(nw != (int) sizeof(cmd) + cmd->plen,
+ "Could not send entire command (sent only %d bytes)!\n",
+ nw);
+ }
+
+ /* Wait for response */
+ if (read_command_complete(fd,
+ cmd->opcode,
+ cmd->plen) < 0) {
+ return -1;
+ }
+
+ } while(1);
+ fprintf(stdout, "Firmware upload successful.\n");
+
+ close(fw);
+ return 0;
+}
+
+int texasalt_init(int fd, int speed, struct termios *ti)
+{
+ struct timespec tm = {0, 50000};
+ char cmd[4];
+ unsigned char resp[100]; /* Response */
+ int n;
+
+ memset(resp,'\0', 100);
+
+ /* It is possible to get software version with manufacturer specific
+ HCI command HCI_VS_TI_Version_Number. But the only thing you get more
+ is if this is point-to-point or point-to-multipoint module */
+
+ /* Get Manufacturer and LMP version */
+ cmd[0] = HCI_COMMAND_PKT;
+ cmd[1] = 0x01;
+ cmd[2] = 0x10;
+ cmd[3] = 0x00;
+
+ do {
+ n = write(fd, cmd, 4);
+ if (n < 0) {
+ perror("Failed to write init command (READ_LOCAL_VERSION_INFORMATION)");
+ return -1;
+ }
+ if (n < 4) {
+ fprintf(stderr, "Wanted to write 4 bytes, could only write %d. Stop\n", n);
+ return -1;
+ }
+
+ /* Read reply. */
+ if (read_hci_event(fd, resp, 100) < 0) {
+ perror("Failed to read init response (READ_LOCAL_VERSION_INFORMATION)");
+ return -1;
+ }
+
+ /* Wait for command complete event for our Opcode */
+ } while (resp[4] != cmd[1] && resp[5] != cmd[2]);
+
+ /* Verify manufacturer */
+ if ((resp[11] & 0xFF) != 0x0d)
+ fprintf(stderr,"WARNING : module's manufacturer is not Texas Instrument\n");
+
+ /* Print LMP version */
+ fprintf(stderr, "Texas module LMP version : 0x%02x\n", resp[10] & 0xFF);
+
+ /* Print LMP subversion */
+ {
+ unsigned short lmp_subv = resp[13] | (resp[14] << 8);
+ unsigned short brf_chip = (lmp_subv & 0x7c00) >> 10;
+ static const char *c_brf_chip[8] = {
+ "unknown",
+ "unknown",
+ "brf6100",
+ "brf6150",
+ "brf6300",
+ "brf6350",
+ "unknown",
+ "wl1271"
+ };
+ char fw[100];
+
+ fprintf(stderr, "Texas module LMP sub-version : 0x%04x\n", lmp_subv);
+
+ fprintf(stderr,
+ "\tinternal version freeze: %d\n"
+ "\tsoftware version: %d\n"
+ "\tchip: %s (%d)\n",
+ lmp_subv & 0x7f,
+ ((lmp_subv & 0x8000) >> (15-3)) | ((lmp_subv & 0x380) >> 7),
+ ((brf_chip > 7) ? "unknown" : c_brf_chip[brf_chip]),
+ brf_chip);
+
+ sprintf(fw, "/etc/firmware/%s.bin", c_brf_chip[brf_chip]);
+ texas_load_firmware(fd, fw);
+
+ texas_change_speed(fd, speed);
+ }
+ nanosleep(&tm, NULL);
+ return 0;
+}
diff --git a/external/cache/sources/hcitools/hciattach_xr.c b/external/cache/sources/hcitools/hciattach_xr.c
new file mode 100644
index 0000000..c42b009
--- /dev/null
+++ b/external/cache/sources/hcitools/hciattach_xr.c
@@ -0,0 +1,557 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "hciattach.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+#define LOG_STR "XRADIO Bluetooth"
+#define DBG_ON 1
+
+#define XR_DBG(fmt, arg...) \
+ do { \
+ if (DBG_ON) \
+ fprintf(stderr, "%s: " fmt "\n" , LOG_STR, ##arg); \
+ } while(0)
+
+#define XR_ERR(fmt, arg...) \
+ do { \
+ fprintf(stderr, "%s ERROR: " fmt "\n", LOG_STR, ##arg);\
+ perror(LOG_STR" ERROR reason"); \
+ } while(0)
+
+#define XR_DUMP(buffer, len) \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ do { \
+ for (int i = 0; i < len; i++) { \
+ if (i && !(i % 16)) { \
+ fprintf(stderr, "\n"); \
+ fprintf(stderr, "%s: ", LOG_STR); \
+ } \
+ fprintf(stderr, "%02x ", buffer[i]); \
+ } \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+#define BT_FW_PATH_NAME "/system/vendor/etc/firmware/fw_xr829_bt.bin"
+#define BT_FW_LOAD_ADDR 0x0000
+#define BT_FW_JUMP_ADDR 0x0000
+#define AW1722 1
+#define AW1732 2
+#define CHIP_NAME AW1722
+
+#define SZ_1K (0x00000400U )
+#define SZ_16K (0x00004000U )
+
+#define SWAP16(d) (((d & 0xff) << 8) | ((d & 0xff00) >> 8))
+#define SWAP32(d) (((d & 0xff) << 24) | ((d & 0xff00) << 8) \
+ | ((d & 0xff0000) >> 8) | ((d & 0xff000000) >> 24))
+
+#define CMD_ID(group, key) (((group) << 3) | (key))
+
+/*----------------------------*/
+/* COMMANDS FORM PC TO MCU */
+/*----------------------------*/
+#define CMD_ID_MEMRW 0x00
+#define CMD_ID_SEQRQ 0x01
+#define CMD_ID_SYSCTL 0x02
+#define CMD_ID_FLASH 0x03
+
+#define CMD_ID_SEQRD CMD_ID(CMD_ID_SEQRQ, 0)
+#define CMD_ID_SEQWR CMD_ID(CMD_ID_SEQRQ, 1)
+/* uart commands */
+#define CMD_ID_SETUART CMD_ID(CMD_ID_SYSCTL, 0)
+#define CMD_ID_SETPC CMD_ID(CMD_ID_SYSCTL, 3)
+
+#define CMD_WRITEN 0
+#define CMD_WRITESEQ 1
+#define CMD_SETBAUD 2
+#define CMD_SETPC 3
+#define DATA_RAW 4
+
+/******************************************************************************
+** Type definitions
+******************************************************************************/
+
+/* vendor serial control block */
+typedef struct
+{
+ int fd; /* fd to Bluetooth device */
+ struct termios *ti; /* serial terminal of BT port */
+} vnd_userial_cb_t;
+
+#pragma pack(1)
+/* command header
+ *
+ * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 byte 6 -7 byte 8-11
+ * ___________________________________________________________________________________________________
+ * | | | | | | | | |
+ * | 'B' | 'R' | 'O' | 'M' | Flags |Reserved | Checksum | Playload Length |
+ * |_________|_________|_________|_________|_________|_________|__________ ________|___________________|
+ */
+typedef struct {
+ uint8_t magic[4]; // magic "BROM"
+ #define CMD_BROM_MAGIC "BROM"
+ uint8_t flags;
+ #define CMD_HFLAG_ERROR (0x1U << 0)
+ #define CMD_HFLAG_ACK (0x1U << 1)
+ #define CMD_HFLAG_CHECK (0x1U << 2)
+ #define CMD_HFLAG_RETRY (0x1U << 3)
+ #define CMD_HFLAG_EXE (0x1U << 4)
+ uint8_t version:4;
+ uint8_t reserved:4;
+ uint16_t checksum;
+ uint32_t payload_len;
+} __attribute__((packed)) cmd_header_t;
+#define MB_CMD_HEADER_SIZE (sizeof(cmd_header_t))
+
+/* acknownledge structure */
+typedef struct {
+ cmd_header_t h;
+ uint8_t err;
+} __attribute__((packed)) cmd_ack_t;
+
+/* sequence read/write command structure */
+typedef struct {
+ cmd_header_t h;
+ uint8_t cmdid;
+ uint32_t addr;
+ uint32_t dlen;
+ uint16_t dcs;
+} __attribute__((packed)) cmd_seq_wr_t;
+
+/* io change command structure */
+typedef struct {
+ cmd_header_t h;
+ uint8_t cmdid;
+ uint32_t val;
+} __attribute__((packed)) cmd_sys_t;
+
+typedef struct {
+ cmd_header_t h;
+ uint8_t cmdid;
+ uint32_t lcr;
+} __attribute__((packed)) cmd_sys_setuart_t;
+
+#pragma pack()
+
+static const uint8_t hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
+static const uint8_t hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x04, 0x60, 0xE3, 0x16, 0x00};
+static vnd_userial_cb_t vnd_userial;
+
+static int32_t cmd_sync_uart(void);
+static int32_t cmd_sync_baud(uint32_t lcr);
+static int32_t cmd_write_seq(uint32_t addr, uint32_t len, uint8_t *data);
+static int32_t cmd_set_pc(uint32_t pc);
+static void userial_set_hw_fctrl(uint8_t hw_fctrl);
+static uint32_t userial_read(uint8_t *p_buffer, uint32_t len, uint32_t timeout);
+static uint32_t userial_write(const uint8_t *p_data, uint32_t len);
+
+/******************************************************************************
+** Functions
+******************************************************************************/
+static uint16_t CheckSum16(uint8_t *data, uint32_t len)
+{
+ uint16_t cs = 0;
+ uint16_t *p = (uint16_t *)data;
+
+ while(len > 1) {
+ cs += *p++;
+ len -= 2;
+ }
+ if (len) {
+ cs += *(uint8_t *)p;
+ }
+ return cs;
+}
+
+static uint64_t time_gettimeofday_us(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (uint64_t)tv.tv_sec * 1000000ULL + (uint64_t)tv.tv_usec;
+}
+
+static uint8_t *memsearch(uint8_t *haystack, uint32_t hlen, uint8_t *needle, uint32_t nlen)
+{
+ while (hlen-- >= nlen) {
+ if (!memcmp(haystack, needle, nlen)) {
+ return haystack;
+ }
+ haystack++;
+ }
+ return NULL;
+}
+
+static int32_t xr_raw_write(int type, uint8_t *data, uint32_t len)
+{
+ uint8_t buffer[MB_CMD_HEADER_SIZE + 13] = {'B', 'R', 'O', 'M', 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t *psend = data;
+ uint32_t lsend = len;
+ cmd_header_t *hdr = (cmd_header_t *)buffer;;
+ cmd_ack_t *ack = (cmd_ack_t *)buffer;
+
+ if (type != DATA_RAW) {
+ psend = buffer;
+ lsend = MB_CMD_HEADER_SIZE + len;
+ memcpy(buffer + MB_CMD_HEADER_SIZE, data, len);
+ hdr->payload_len = len;
+#if ENABLE_DCS
+ hdr->flags = CMD_HFLAG_CHECK;
+#endif
+ hdr->checksum = ~CheckSum16(buffer, MB_CMD_HEADER_SIZE + len);
+ hdr->payload_len = SWAP32(hdr->payload_len);
+ hdr->checksum = SWAP16(hdr->checksum);
+ switch (type) {
+ case CMD_WRITESEQ:
+ {
+ cmd_seq_wr_t *cmd = (cmd_seq_wr_t *)buffer;
+ cmd->addr = SWAP32(cmd->addr);
+ cmd->dlen = SWAP32(cmd->dlen);
+ cmd->dcs = SWAP16(cmd->dcs);
+ }
+ break;
+ case CMD_SETBAUD:
+ {
+ cmd_sys_setuart_t *cmd = (cmd_sys_setuart_t*)buffer;
+ cmd->lcr = SWAP32(cmd->lcr);
+ }
+ break;
+ case CMD_SETPC:
+ {
+ cmd_sys_t *cmd = (cmd_sys_t*)buffer;
+ cmd->val = SWAP32(cmd->val);
+ }
+ break;
+ default:
+ XR_ERR("%s: Unsupport type %d", __func__, type);
+ return -1;
+ }
+ }
+
+ ssize_t ret_w, ret_r;
+ uint64_t t0, t1, t2, t3;
+
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ t0 = time_gettimeofday_us();
+ ret_w = userial_write(psend, lsend);
+ t1 = time_gettimeofday_us();
+
+ memset(buffer, 0, MB_CMD_HEADER_SIZE + 1);
+
+ t2 = time_gettimeofday_us();
+ ret_r = userial_read(buffer, MB_CMD_HEADER_SIZE, 100000);
+ t3 = time_gettimeofday_us();
+
+ XR_DBG("%s, type: %d, write len: %5d, ret: %5d, time: %6lluus, read len: %2d, ret: %2d, %6lluus",
+ __func__, type, lsend, ret_w, t1 - t0, MB_CMD_HEADER_SIZE, ret_r, t3 - t2);
+
+ uint8_t *p = (uint8_t *)memsearch(buffer, MB_CMD_HEADER_SIZE, (uint8_t *)"BROM", 4);
+ if (p != buffer) {
+ if (p == NULL) {
+ XR_ERR("%s: invalid response", __func__);
+ return -1;
+ }
+ uint32_t nowread = buffer + MB_CMD_HEADER_SIZE - p;
+ uint32_t needread = p - buffer;
+ XR_DBG("%s: Index error, re-find header magic", __func__);
+ memcpy(buffer, p, nowread);
+ memset(buffer + nowread, 0x0, needread);
+ userial_read(buffer + nowread, needread, 100000);
+ }
+
+ /* check response */
+ if (ack->h.flags & CMD_HFLAG_ERROR) {
+ userial_read(buffer + MB_CMD_HEADER_SIZE, 1, 100000);
+ XR_ERR("%s: resp error flag, type %d", __func__, ack->err);
+ return -ack->err;
+ }
+
+ if (ack->h.flags & CMD_HFLAG_ACK) {
+ /* convert network byte order to host byte order */
+ ack->h.payload_len = SWAP32(ack->h.payload_len);
+ ack->h.checksum = SWAP16(ack->h.checksum);
+ if (ack->h.payload_len != 0) {
+ XR_ERR("%s: data payload len %d != 0", __func__, ack->h.payload_len);
+ return -1;
+ }
+ }
+
+ if (ack->h.flags & CMD_HFLAG_CHECK) {
+ if (CheckSum16(buffer, MB_CMD_HEADER_SIZE) != 0xffff) {
+ XR_ERR("%s: write data response 0 checksum error", __func__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int32_t cmd_sync_uart(void)
+{
+ uint8_t sync = 0x55;
+ uint8_t ack[3] = {0};
+ ssize_t ret = -1;
+ uint32_t cnt = 0;
+
+ do {
+ XR_DBG("uart sync count:%d.", cnt);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+ userial_write(&sync, 1);
+ ret = userial_read(ack, 2, 2000);
+ if (ret == 2 && ((ack[0] == 'O' && ack[1] == 'K') || (ack[0] == 'K' && ack[1] == 'O'))) {
+ XR_DBG("Receive %s, uart Sync done.", ack);
+ return 0;
+ }
+ } while (cnt++ < 50);
+
+ XR_DBG("uart sync fail.");
+ return -1;
+}
+
+static int32_t cmd_sync_baud(uint32_t lcr)
+{
+ uint8_t buffer[MB_CMD_HEADER_SIZE + 5];
+ cmd_sys_setuart_t *cmd = (cmd_sys_setuart_t*)buffer;
+
+ cmd->cmdid = CMD_ID_SETUART;
+ cmd->lcr = lcr;
+
+ uint8_t cnt = 0;
+ int ret = -1;
+
+ do {
+ XR_DBG("%s count:%d.", __func__, cnt);
+ ret = xr_raw_write(CMD_SETBAUD, buffer + MB_CMD_HEADER_SIZE, 5);
+ if (ret == 0) {
+ set_speed(vnd_userial.fd, vnd_userial.ti, lcr & 0xffffff);
+ return cmd_sync_uart();
+ }
+ } while (cnt++ < 3);
+
+ XR_DBG("cmd_sync_baud fail.");
+ return -1;
+}
+
+static int32_t cmd_write_seq(uint32_t addr, uint32_t len, uint8_t *data)
+{
+ int ret = -1;
+ uint8_t buffer[MB_CMD_HEADER_SIZE + 13];
+ cmd_seq_wr_t *cmd = (cmd_seq_wr_t *)buffer;
+
+ cmd->cmdid = CMD_ID_SEQWR;
+ cmd->addr = addr;
+ cmd->dlen = len;
+#if ENABLE_DCS
+ cmd->dcs = ~CheckSum16(data, len);
+#endif
+
+ ret = xr_raw_write(CMD_WRITESEQ, buffer + MB_CMD_HEADER_SIZE, 11);
+ if (ret == 0) {
+ return xr_raw_write(DATA_RAW, data, len);
+ }
+ return ret;
+}
+
+static int32_t cmd_set_pc(uint32_t pc)
+{
+ uint8_t buffer[MB_CMD_HEADER_SIZE + 5];
+ cmd_sys_t *cmd = (cmd_sys_t*)buffer;
+
+ cmd->cmdid = CMD_ID_SETPC;
+ cmd->val = pc;
+ XR_DBG("set pc %x, val %x", pc, cmd->val);
+
+ return xr_raw_write(CMD_SETPC, buffer + MB_CMD_HEADER_SIZE, 5);
+}
+
+static void userial_set_hw_fctrl(uint8_t hw_fctrl)
+{
+ if (vnd_userial.fd == -1) {
+ XR_ERR("vnd_userial.fd is -1");
+ return;
+ }
+
+ if (hw_fctrl) {
+ XR_DBG("Set HW FlowControl On");
+ vnd_userial.ti->c_cflag |= CRTSCTS;
+ } else {
+ XR_DBG("Set HW FlowControl Off");
+ vnd_userial.ti->c_cflag &= ~CRTSCTS;
+ }
+ tcsetattr(vnd_userial.fd, TCSANOW, vnd_userial.ti);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+}
+
+static uint32_t userial_read(uint8_t *buffer, uint32_t len, uint32_t timeout)
+{
+ fd_set set;
+ struct timeval tv;
+ int rv;
+
+ FD_ZERO(&set); /* clear the set */
+ FD_SET(vnd_userial.fd, &set); /* add our file descriptor to the set */
+
+ /* there was data to read */
+ ssize_t r;
+ uint8_t *pos = (uint8_t*)buffer;
+
+ while (len > 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout;
+
+ rv = select(vnd_userial.fd + 1, &set, NULL, NULL, &tv);
+ if(rv == -1) {
+ XR_ERR("select error"); /* an error accured */
+ break;
+ } else if(rv == 0) {
+ XR_ERR("read timeout"); /* a timeout occured */
+ break;
+ }
+
+ r = read(vnd_userial.fd, pos, len);
+ if (r < 1)
+ break;
+
+ len -= r;
+ pos += r;
+ }
+
+ return pos - buffer;
+}
+
+static uint32_t userial_write(const uint8_t *buffer, uint32_t len)
+{
+ ssize_t r;
+ uint8_t *pos = (uint8_t*)buffer;
+
+ while (len > 0) {
+ r = write(vnd_userial.fd, pos, len);
+ if (r < 1)
+ break;
+
+ len -= r;
+ pos += r;
+ }
+
+ return pos - buffer;
+}
+
+static int32_t load_btfirmware(void)
+{
+ FILE *fwfile_fd = NULL;
+ uint32_t len;
+ uint8_t *data = NULL;
+ uint32_t addr = BT_FW_LOAD_ADDR;
+ uint32_t section = SZ_16K;
+
+ fwfile_fd = fopen(BT_FW_PATH_NAME, "rb");
+ XR_DBG("BT firmware: %s", BT_FW_PATH_NAME);
+ if(!fwfile_fd) {
+ XR_ERR("Unable to open BT firmware %s", BT_FW_PATH_NAME);
+ return -1;
+ }
+
+ data = (uint8_t*)malloc(section);
+ if (data == NULL) {
+ XR_DBG("failed to alloc %d byte memory.", section);
+ fclose(fwfile_fd);
+ return -1;
+ }
+
+ XR_DBG("load bt firmware starting.");
+ while ((len = fread(data, 1, section, fwfile_fd)) > 0) {
+ cmd_write_seq(addr, len, data);
+ addr += len;
+ }
+
+ free(data);
+ fclose(fwfile_fd);
+ XR_DBG("load firmware done.");
+
+ XR_DBG("Firmware run from address 0x%08X", BT_FW_JUMP_ADDR);
+ cmd_set_pc(BT_FW_JUMP_ADDR);
+
+ if (CHIP_NAME == AW1732) {
+ XR_DBG("second time sync starting....");
+ if (cmd_sync_uart() < 0)
+ return -1;
+ cmd_set_pc(BT_FW_JUMP_ADDR);
+ }
+ return addr;
+}
+
+static int hci_cmd_handle(const uint8_t *cmd, uint32_t cmd_len, uint32_t event_len)
+{
+ uint8_t buffer[256];
+
+ XR_DBG("send hci command");
+ userial_write(cmd, cmd_len);
+ XR_DUMP(cmd, cmd_len);
+
+ if (read_hci_event(vnd_userial.fd, buffer, event_len) != event_len) {
+ XR_ERR("Event read error");
+ return -1;
+ }
+ XR_DBG("Received event");
+ XR_DUMP(buffer, event_len);
+ return 0;
+}
+
+int xr_init(int fd, struct uart_t *u, struct termios *ti)
+{
+ vnd_userial.fd = fd;
+ vnd_userial.ti = ti;
+
+ XR_DBG("uart sync starting....");
+ if (cmd_sync_uart() < 0)
+ goto END;
+ XR_DBG("set bandrate to %d.", u->speed);
+ if (cmd_sync_baud(((u->speed) | (3<<24))) < 0)
+ goto END;
+ if (load_btfirmware() < 0)
+ goto END;
+ XR_DBG("bt firmware is running....");
+
+ XR_DBG("set baudrate to %d", u->init_speed);
+ set_speed(vnd_userial.fd, vnd_userial.ti, u->init_speed);
+ userial_set_hw_fctrl(1);
+ usleep(50000);
+
+ XR_DBG("process hci reset...");
+ if (hci_cmd_handle(hci_reset, sizeof(hci_reset), 7) < 0)
+ goto END;
+
+ XR_DBG("process hci update baud...");
+ if (hci_cmd_handle(hci_update_baud_rate, sizeof(hci_update_baud_rate), 7) < 0)
+ goto END;
+
+ usleep(100000);
+
+ return 0;
+
+END:
+ XR_DBG("device fd = %d close", fd);
+ close(vnd_userial.fd);
+ vnd_userial.fd = -1;
+ vnd_userial.ti = NULL;
+
+ return -1;
+}
+
+int xr_post(int fd, struct uart_t *u, struct termios *ti)
+{
+ XR_DBG("Done setting line discpline");
+ return 0;
+}
+
diff --git a/external/cache/sources/hcitools/hciconfig.c b/external/cache/sources/hcitools/hciconfig.c
new file mode 100644
index 0000000..ec83139
--- /dev/null
+++ b/external/cache/sources/hcitools/hciconfig.c
@@ -0,0 +1,2052 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky
+ * Copyright (C) 2002-2010 Marcel Holtmann
+ *
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "textfile.h"
+#include "csr.h"
+
+static struct hci_dev_info di;
+static int all;
+
+static void print_dev_hdr(struct hci_dev_info *di);
+static void print_dev_info(int ctl, struct hci_dev_info *di);
+
+static void print_dev_list(int ctl, int flags)
+{
+ struct hci_dev_list_req *dl;
+ struct hci_dev_req *dr;
+ int i;
+
+ if (!(dl = malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) +
+ sizeof(uint16_t)))) {
+ perror("Can't allocate memory");
+ exit(1);
+ }
+ dl->dev_num = HCI_MAX_DEV;
+ dr = dl->dev_req;
+
+ if (ioctl(ctl, HCIGETDEVLIST, (void *) dl) < 0) {
+ perror("Can't get device list");
+ if(dl) {
+ free(dl);
+ dl = NULL;
+ }
+ exit(1);
+ }
+
+ for (i = 0; i< dl->dev_num; i++) {
+ di.dev_id = (dr+i)->dev_id;
+ if (ioctl(ctl, HCIGETDEVINFO, (void *) &di) < 0)
+ continue;
+ if (hci_test_bit(HCI_RAW, &di.flags) &&
+ !bacmp(&di.bdaddr, BDADDR_ANY)) {
+ int dd = hci_open_dev(di.dev_id);
+ hci_read_bd_addr(dd, &di.bdaddr, 1000);
+ hci_close_dev(dd);
+ }
+ print_dev_info(ctl, &di);
+ }
+ if(dl) {
+ free(dl);
+ dl = NULL;
+ }
+}
+
+static void print_pkt_type(struct hci_dev_info *di)
+{
+ char *str;
+ str = hci_ptypetostr(di->pkt_type);
+ printf("\tPacket type: %s\n", str);
+ bt_free(str);
+}
+
+static void print_link_policy(struct hci_dev_info *di)
+{
+ printf("\tLink policy: %s\n", hci_lptostr(di->link_policy));
+}
+
+static void print_link_mode(struct hci_dev_info *di)
+{
+ char *str;
+ str = hci_lmtostr(di->link_mode);
+ printf("\tLink mode: %s\n", str);
+ bt_free(str);
+}
+
+static void print_dev_features(struct hci_dev_info *di, int format)
+{
+ printf("\tFeatures: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
+ "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ di->features[0], di->features[1], di->features[2],
+ di->features[3], di->features[4], di->features[5],
+ di->features[6], di->features[7]);
+
+ if (format) {
+ char *tmp = lmp_featurestostr(di->features, "\t\t", 63);
+ printf("%s\n", tmp);
+ bt_free(tmp);
+ }
+}
+
+static void print_le_states(uint64_t states)
+{
+ int i;
+ const char *le_states[] = {
+ "Non-connectable Advertising State" ,
+ "Scannable Advertising State",
+ "Connectable Advertising State",
+ "Directed Advertising State",
+ "Passive Scanning State",
+ "Active Scanning State",
+ "Initiating State/Connection State in Master Role",
+ "Connection State in the Slave Role",
+ "Non-connectable Advertising State and Passive Scanning State combination",
+ "Scannable Advertising State and Passive Scanning State combination",
+ "Connectable Advertising State and Passive Scanning State combination",
+ "Directed Advertising State and Passive Scanning State combination",
+ "Non-connectable Advertising State and Active Scanning State combination",
+ "Scannable Advertising State and Active Scanning State combination",
+ "Connectable Advertising State and Active Scanning State combination",
+ "Directed Advertising State and Active Scanning State combination",
+ "Non-connectable Advertising State and Initiating State combination",
+ "Scannable Advertising State and Initiating State combination",
+ "Non-connectable Advertising State and Master Role combination",
+ "Scannable Advertising State and Master Role combination",
+ "Non-connectable Advertising State and Slave Role combination",
+ "Scannable Advertising State and Slave Role combination",
+ "Passive Scanning State and Initiating State combination",
+ "Active Scanning State and Initiating State combination",
+ "Passive Scanning State and Master Role combination",
+ "Active Scanning State and Master Role combination",
+ "Passive Scanning State and Slave Role combination",
+ "Active Scanning State and Slave Role combination",
+ "Initiating State and Master Role combination/Master Role and Master Role combination",
+ NULL
+ };
+
+ printf("Supported link layer states:\n");
+ for (i = 0; le_states[i]; i++) {
+ const char *status;
+
+ status = states & (1 << i) ? "YES" : "NO ";
+ printf("\t%s %s\n", status, le_states[i]);
+ }
+}
+
+static void cmd_rstat(int ctl, int hdev, char *opt)
+{
+ /* Reset HCI device stat counters */
+ if (ioctl(ctl, HCIDEVRESTAT, hdev) < 0) {
+ fprintf(stderr, "Can't reset stats counters hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+}
+
+static void cmd_scan(int ctl, int hdev, char *opt)
+{
+ struct hci_dev_req dr;
+
+ dr.dev_id = hdev;
+ dr.dev_opt = SCAN_DISABLED;
+ if (!strcmp(opt, "iscan"))
+ dr.dev_opt = SCAN_INQUIRY;
+ else if (!strcmp(opt, "pscan"))
+ dr.dev_opt = SCAN_PAGE;
+ else if (!strcmp(opt, "piscan"))
+ dr.dev_opt = SCAN_PAGE | SCAN_INQUIRY;
+
+ if (ioctl(ctl, HCISETSCAN, (unsigned long) &dr) < 0) {
+ fprintf(stderr, "Can't set scan mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+}
+
+static void cmd_le_addr(int ctl, int hdev, char *opt)
+{
+ struct hci_request rq;
+ le_set_random_address_cp cp;
+ uint8_t status;
+ int dd, err, ret;
+
+ if (!opt)
+ return;
+
+ if (hdev < 0)
+ hdev = hci_get_route(NULL);
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ err = -errno;
+ fprintf(stderr, "Could not open device: %s(%d)\n",
+ strerror(-err), -err);
+ exit(1);
+ }
+
+ memset(&cp, 0, sizeof(cp));
+
+ str2ba(opt, &cp.bdaddr);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_SET_RANDOM_ADDRESS;
+ rq.cparam = &cp;
+ rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ ret = hci_send_req(dd, &rq, 1000);
+ if (status || ret < 0) {
+ err = -errno;
+ fprintf(stderr, "Can't set random address for hci%d: "
+ "%s (%d)\n", hdev, strerror(-err), -err);
+ }
+
+ hci_close_dev(dd);
+}
+
+static void cmd_le_adv(int ctl, int hdev, char *opt)
+{
+ struct hci_request rq;
+ le_set_advertise_enable_cp advertise_cp;
+ le_set_advertising_parameters_cp adv_params_cp;
+ uint8_t status;
+ int dd, ret;
+
+ if (hdev < 0)
+ hdev = hci_get_route(NULL);
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ memset(&adv_params_cp, 0, sizeof(adv_params_cp));
+ adv_params_cp.min_interval = htobs(0x0800);
+ adv_params_cp.max_interval = htobs(0x0800);
+ if (opt)
+ adv_params_cp.advtype = atoi(opt);
+ adv_params_cp.chan_map = 7;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_SET_ADVERTISING_PARAMETERS;
+ rq.cparam = &adv_params_cp;
+ rq.clen = LE_SET_ADVERTISING_PARAMETERS_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ ret = hci_send_req(dd, &rq, 1000);
+ if (ret < 0)
+ goto done;
+
+ memset(&advertise_cp, 0, sizeof(advertise_cp));
+ advertise_cp.enable = 0x01;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE;
+ rq.cparam = &advertise_cp;
+ rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ ret = hci_send_req(dd, &rq, 1000);
+
+done:
+ hci_close_dev(dd);
+
+ if (ret < 0) {
+ fprintf(stderr, "Can't set advertise mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (status) {
+ fprintf(stderr,
+ "LE set advertise enable on hci%d returned status %d\n",
+ hdev, status);
+ exit(1);
+ }
+}
+
+static void cmd_no_le_adv(int ctl, int hdev, char *opt)
+{
+ struct hci_request rq;
+ le_set_advertise_enable_cp advertise_cp;
+ uint8_t status;
+ int dd, ret;
+
+ if (hdev < 0)
+ hdev = hci_get_route(NULL);
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ memset(&advertise_cp, 0, sizeof(advertise_cp));
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE;
+ rq.cparam = &advertise_cp;
+ rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ ret = hci_send_req(dd, &rq, 1000);
+
+ hci_close_dev(dd);
+
+ if (ret < 0) {
+ fprintf(stderr, "Can't set advertise mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (status) {
+ fprintf(stderr, "LE set advertise enable on hci%d returned status %d\n",
+ hdev, status);
+ exit(1);
+ }
+}
+
+static void cmd_le_states(int ctl, int hdev, char *opt)
+{
+ le_read_supported_states_rp rp;
+ struct hci_request rq;
+ int err, dd;
+
+ if (hdev < 0)
+ hdev = hci_get_route(NULL);
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ memset(&rp, 0, sizeof(rp));
+ memset(&rq, 0, sizeof(rq));
+
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_READ_SUPPORTED_STATES;
+ rq.rparam = &rp;
+ rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE;
+
+ err = hci_send_req(dd, &rq, 1000);
+
+ hci_close_dev(dd);
+
+ if (err < 0) {
+ fprintf(stderr, "Can't read LE supported states on hci%d:"
+ " %s(%d)\n", hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (rp.status) {
+ fprintf(stderr, "Read LE supported states on hci%d"
+ " returned status %d\n", hdev, rp.status);
+ exit(1);
+ }
+
+ print_le_states(rp.states);
+}
+
+static void cmd_iac(int ctl, int hdev, char *opt)
+{
+ int s = hci_open_dev(hdev);
+
+ if (s < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ if (opt) {
+ int l = strtoul(opt, 0, 16);
+ uint8_t lap[3];
+ if (!strcasecmp(opt, "giac")) {
+ l = 0x9e8b33;
+ } else if (!strcasecmp(opt, "liac")) {
+ l = 0x9e8b00;
+ } else if (l < 0x9e8b00 || l > 0x9e8b3f) {
+ printf("Invalid access code 0x%x\n", l);
+ exit(1);
+ }
+ lap[0] = (l & 0xff);
+ lap[1] = (l >> 8) & 0xff;
+ lap[2] = (l >> 16) & 0xff;
+ if (hci_write_current_iac_lap(s, 1, lap, 1000) < 0) {
+ printf("Failed to set IAC on hci%d: %s\n", hdev, strerror(errno));
+ exit(1);
+ }
+ } else {
+ uint8_t lap[3 * MAX_IAC_LAP];
+ int i, j;
+ uint8_t n;
+ if (hci_read_current_iac_lap(s, &n, lap, 1000) < 0) {
+ printf("Failed to read IAC from hci%d: %s\n", hdev, strerror(errno));
+ exit(1);
+ }
+ print_dev_hdr(&di);
+ printf("\tIAC: ");
+ for (i = 0; i < n; i++) {
+ printf("0x");
+ for (j = 3; j--; )
+ printf("%02x", lap[j + 3 * i]);
+ if (i < n - 1)
+ printf(", ");
+ }
+ printf("\n");
+ }
+ close(s);
+}
+
+static void cmd_auth(int ctl, int hdev, char *opt)
+{
+ struct hci_dev_req dr;
+
+ dr.dev_id = hdev;
+ if (!strcmp(opt, "auth"))
+ dr.dev_opt = AUTH_ENABLED;
+ else
+ dr.dev_opt = AUTH_DISABLED;
+
+ if (ioctl(ctl, HCISETAUTH, (unsigned long) &dr) < 0) {
+ fprintf(stderr, "Can't set auth on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+}
+
+static void cmd_encrypt(int ctl, int hdev, char *opt)
+{
+ struct hci_dev_req dr;
+
+ dr.dev_id = hdev;
+ if (!strcmp(opt, "encrypt"))
+ dr.dev_opt = ENCRYPT_P2P;
+ else
+ dr.dev_opt = ENCRYPT_DISABLED;
+
+ if (ioctl(ctl, HCISETENCRYPT, (unsigned long) &dr) < 0) {
+ fprintf(stderr, "Can't set encrypt on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+}
+
+static void cmd_up(int ctl, int hdev, char *opt)
+{
+ /* Start HCI device */
+ if (ioctl(ctl, HCIDEVUP, hdev) < 0) {
+ if (errno == EALREADY)
+ return;
+ fprintf(stderr, "Can't init device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+}
+
+static void cmd_down(int ctl, int hdev, char *opt)
+{
+ /* Stop HCI device */
+ if (ioctl(ctl, HCIDEVDOWN, hdev) < 0) {
+ fprintf(stderr, "Can't down device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+}
+
+static void cmd_reset(int ctl, int hdev, char *opt)
+{
+ /* Reset HCI device */
+#if 0
+ if (ioctl(ctl, HCIDEVRESET, hdev) < 0 ){
+ fprintf(stderr, "Reset failed for device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+#endif
+ cmd_down(ctl, hdev, "down");
+ cmd_up(ctl, hdev, "up");
+}
+
+static void cmd_ptype(int ctl, int hdev, char *opt)
+{
+ struct hci_dev_req dr;
+
+ dr.dev_id = hdev;
+
+ if (hci_strtoptype(opt, &dr.dev_opt)) {
+ if (ioctl(ctl, HCISETPTYPE, (unsigned long) &dr) < 0) {
+ fprintf(stderr, "Can't set pkttype on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ print_dev_hdr(&di);
+ print_pkt_type(&di);
+ }
+}
+
+static void cmd_lp(int ctl, int hdev, char *opt)
+{
+ struct hci_dev_req dr;
+
+ dr.dev_id = hdev;
+
+ if (hci_strtolp(opt, &dr.dev_opt)) {
+ if (ioctl(ctl, HCISETLINKPOL, (unsigned long) &dr) < 0) {
+ fprintf(stderr, "Can't set link policy on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ print_dev_hdr(&di);
+ print_link_policy(&di);
+ }
+}
+
+static void cmd_lm(int ctl, int hdev, char *opt)
+{
+ struct hci_dev_req dr;
+
+ dr.dev_id = hdev;
+
+ if (hci_strtolm(opt, &dr.dev_opt)) {
+ if (ioctl(ctl, HCISETLINKMODE, (unsigned long) &dr) < 0) {
+ fprintf(stderr, "Can't set default link mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ print_dev_hdr(&di);
+ print_link_mode(&di);
+ }
+}
+
+static void cmd_aclmtu(int ctl, int hdev, char *opt)
+{
+ struct hci_dev_req dr = { .dev_id = hdev };
+ uint16_t mtu, mpkt;
+
+ if (!opt)
+ return;
+
+ if (sscanf(opt, "%4hu:%4hu", &mtu, &mpkt) != 2)
+ return;
+
+ dr.dev_opt = htobl(htobs(mpkt) | (htobs(mtu) << 16));
+
+ if (ioctl(ctl, HCISETACLMTU, (unsigned long) &dr) < 0) {
+ fprintf(stderr, "Can't set ACL mtu on hci%d: %s(%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+}
+
+static void cmd_scomtu(int ctl, int hdev, char *opt)
+{
+ struct hci_dev_req dr = { .dev_id = hdev };
+ uint16_t mtu, mpkt;
+
+ if (!opt)
+ return;
+
+ if (sscanf(opt, "%4hu:%4hu", &mtu, &mpkt) != 2)
+ return;
+
+ dr.dev_opt = htobl(htobs(mpkt) | (htobs(mtu) << 16));
+
+ if (ioctl(ctl, HCISETSCOMTU, (unsigned long) &dr) < 0) {
+ fprintf(stderr, "Can't set SCO mtu on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+}
+
+static void cmd_features(int ctl, int hdev, char *opt)
+{
+ uint8_t features[8], max_page = 0;
+ char *tmp;
+ int i, dd;
+
+ if (!(di.features[7] & LMP_EXT_FEAT)) {
+ print_dev_hdr(&di);
+ print_dev_features(&di, 1);
+ return;
+ }
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (hci_read_local_ext_features(dd, 0, &max_page, features, 1000) < 0) {
+ fprintf(stderr, "Can't read extended features hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ printf("\tFeatures%s: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
+ "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ (max_page > 0) ? " page 0" : "",
+ features[0], features[1], features[2], features[3],
+ features[4], features[5], features[6], features[7]);
+
+ tmp = lmp_featurestostr(di.features, "\t\t", 63);
+ printf("%s\n", tmp);
+ bt_free(tmp);
+
+ for (i = 1; i <= max_page; i++) {
+ if (hci_read_local_ext_features(dd, i, NULL,
+ features, 1000) < 0)
+ continue;
+
+ printf("\tFeatures page %d: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
+ "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", i,
+ features[0], features[1], features[2], features[3],
+ features[4], features[5], features[6], features[7]);
+ }
+
+ hci_close_dev(dd);
+}
+
+static void cmd_name(int ctl, int hdev, char *opt)
+{
+ int dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (opt) {
+ if (hci_write_local_name(dd, opt, 2000) < 0) {
+ fprintf(stderr, "Can't change local name on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ char name[249];
+ int i;
+
+ if (hci_read_local_name(dd, sizeof(name), name, 1000) < 0) {
+ fprintf(stderr, "Can't read local name on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ for (i = 0; i < 248 && name[i]; i++) {
+ if ((unsigned char) name[i] < 32 || name[i] == 127)
+ name[i] = '.';
+ }
+
+ name[248] = '\0';
+
+ print_dev_hdr(&di);
+ printf("\tName: '%s'\n", name);
+ }
+
+ hci_close_dev(dd);
+}
+
+/*
+ * see http://www.bluetooth.org/assigned-numbers/baseband.htm --- all
+ * strings are reproduced verbatim
+ */
+static char *get_minor_device_name(int major, int minor)
+{
+ switch (major) {
+ case 0: /* misc */
+ return "";
+ case 1: /* computer */
+ switch (minor) {
+ case 0:
+ return "Uncategorized";
+ case 1:
+ return "Desktop workstation";
+ case 2:
+ return "Server";
+ case 3:
+ return "Laptop";
+ case 4:
+ return "Handheld";
+ case 5:
+ return "Palm";
+ case 6:
+ return "Wearable";
+ }
+ break;
+ case 2: /* phone */
+ switch (minor) {
+ case 0:
+ return "Uncategorized";
+ case 1:
+ return "Cellular";
+ case 2:
+ return "Cordless";
+ case 3:
+ return "Smart phone";
+ case 4:
+ return "Wired modem or voice gateway";
+ case 5:
+ return "Common ISDN Access";
+ case 6:
+ return "Sim Card Reader";
+ }
+ break;
+ case 3: /* lan access */
+ if (minor == 0)
+ return "Uncategorized";
+ switch (minor / 8) {
+ case 0:
+ return "Fully available";
+ case 1:
+ return "1-17% utilized";
+ case 2:
+ return "17-33% utilized";
+ case 3:
+ return "33-50% utilized";
+ case 4:
+ return "50-67% utilized";
+ case 5:
+ return "67-83% utilized";
+ case 6:
+ return "83-99% utilized";
+ case 7:
+ return "No service available";
+ }
+ break;
+ case 4: /* audio/video */
+ switch (minor) {
+ case 0:
+ return "Uncategorized";
+ case 1:
+ return "Device conforms to the Headset profile";
+ case 2:
+ return "Hands-free";
+ /* 3 is reserved */
+ case 4:
+ return "Microphone";
+ case 5:
+ return "Loudspeaker";
+ case 6:
+ return "Headphones";
+ case 7:
+ return "Portable Audio";
+ case 8:
+ return "Car Audio";
+ case 9:
+ return "Set-top box";
+ case 10:
+ return "HiFi Audio Device";
+ case 11:
+ return "VCR";
+ case 12:
+ return "Video Camera";
+ case 13:
+ return "Camcorder";
+ case 14:
+ return "Video Monitor";
+ case 15:
+ return "Video Display and Loudspeaker";
+ case 16:
+ return "Video Conferencing";
+ /* 17 is reserved */
+ case 18:
+ return "Gaming/Toy";
+ }
+ break;
+ case 5: /* peripheral */ {
+ static char cls_str[48];
+
+ cls_str[0] = '\0';
+
+ switch (minor & 48) {
+ case 16:
+ strncpy(cls_str, "Keyboard", sizeof(cls_str));
+ break;
+ case 32:
+ strncpy(cls_str, "Pointing device", sizeof(cls_str));
+ break;
+ case 48:
+ strncpy(cls_str, "Combo keyboard/pointing device", sizeof(cls_str));
+ break;
+ }
+ if ((minor & 15) && (strlen(cls_str) > 0))
+ strcat(cls_str, "/");
+
+ switch (minor & 15) {
+ case 0:
+ break;
+ case 1:
+ strncat(cls_str, "Joystick", sizeof(cls_str) - strlen(cls_str));
+ break;
+ case 2:
+ strncat(cls_str, "Gamepad", sizeof(cls_str) - strlen(cls_str));
+ break;
+ case 3:
+ strncat(cls_str, "Remote control", sizeof(cls_str) - strlen(cls_str));
+ break;
+ case 4:
+ strncat(cls_str, "Sensing device", sizeof(cls_str) - strlen(cls_str));
+ break;
+ case 5:
+ strncat(cls_str, "Digitizer tablet", sizeof(cls_str) - strlen(cls_str));
+ break;
+ case 6:
+ strncat(cls_str, "Card reader", sizeof(cls_str) - strlen(cls_str));
+ break;
+ default:
+ strncat(cls_str, "(reserved)", sizeof(cls_str) - strlen(cls_str));
+ break;
+ }
+ if (strlen(cls_str) > 0)
+ return cls_str;
+ }
+ case 6: /* imaging */
+ if (minor & 4)
+ return "Display";
+ if (minor & 8)
+ return "Camera";
+ if (minor & 16)
+ return "Scanner";
+ if (minor & 32)
+ return "Printer";
+ break;
+ case 7: /* wearable */
+ switch (minor) {
+ case 1:
+ return "Wrist Watch";
+ case 2:
+ return "Pager";
+ case 3:
+ return "Jacket";
+ case 4:
+ return "Helmet";
+ case 5:
+ return "Glasses";
+ }
+ break;
+ case 8: /* toy */
+ switch (minor) {
+ case 1:
+ return "Robot";
+ case 2:
+ return "Vehicle";
+ case 3:
+ return "Doll / Action Figure";
+ case 4:
+ return "Controller";
+ case 5:
+ return "Game";
+ }
+ break;
+ case 63: /* uncategorised */
+ return "";
+ }
+ return "Unknown (reserved) minor device class";
+}
+
+static void cmd_class(int ctl, int hdev, char *opt)
+{
+ static const char *services[] = { "Positioning",
+ "Networking",
+ "Rendering",
+ "Capturing",
+ "Object Transfer",
+ "Audio",
+ "Telephony",
+ "Information" };
+ static const char *major_devices[] = { "Miscellaneous",
+ "Computer",
+ "Phone",
+ "LAN Access",
+ "Audio/Video",
+ "Peripheral",
+ "Imaging",
+ "Uncategorized" };
+ int s = hci_open_dev(hdev);
+
+ if (s < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ if (opt) {
+ uint32_t cod = strtoul(opt, NULL, 16);
+ if (hci_write_class_of_dev(s, cod, 2000) < 0) {
+ fprintf(stderr, "Can't write local class of device on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint8_t cls[3];
+ if (hci_read_class_of_dev(s, cls, 1000) < 0) {
+ fprintf(stderr, "Can't read class of device on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ print_dev_hdr(&di);
+ printf("\tClass: 0x%02x%02x%02x\n", cls[2], cls[1], cls[0]);
+ printf("\tService Classes: ");
+ if (cls[2]) {
+ unsigned int i;
+ int first = 1;
+ for (i = 0; i < (sizeof(services) / sizeof(*services)); i++)
+ if (cls[2] & (1 << i)) {
+ if (!first)
+ printf(", ");
+ printf("%s", services[i]);
+ first = 0;
+ }
+ } else
+ printf("Unspecified");
+ printf("\n\tDevice Class: ");
+ if ((cls[1] & 0x1f) >= sizeof(major_devices) / sizeof(*major_devices))
+ printf("Invalid Device Class!\n");
+ else
+ printf("%s, %s\n", major_devices[cls[1] & 0x1f],
+ get_minor_device_name(cls[1] & 0x1f, cls[0] >> 2));
+ }
+}
+
+static void cmd_voice(int ctl, int hdev, char *opt)
+{
+ static char *icf[] = { "Linear",
+ "u-Law",
+ "A-Law",
+ "Reserved" };
+
+ static char *idf[] = { "1's complement",
+ "2's complement",
+ "Sign-Magnitude",
+ "Reserved" };
+
+ static char *iss[] = { "8 bit",
+ "16 bit" };
+
+ static char *acf[] = { "CVSD",
+ "u-Law",
+ "A-Law",
+ "Reserved" };
+
+ int s = hci_open_dev(hdev);
+
+ if (s < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ if (opt) {
+ uint16_t vs = htobs(strtoul(opt, NULL, 16));
+ if (hci_write_voice_setting(s, vs, 2000) < 0) {
+ fprintf(stderr, "Can't write voice setting on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint16_t vs;
+ uint8_t ic;
+ if (hci_read_voice_setting(s, &vs, 1000) < 0) {
+ fprintf(stderr, "Can't read voice setting on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ vs = htobs(vs);
+ ic = (vs & 0x0300) >> 8;
+ print_dev_hdr(&di);
+ printf("\tVoice setting: 0x%04x%s\n", vs,
+ ((vs & 0x03fc) == 0x0060) ? " (Default Condition)" : "");
+ printf("\tInput Coding: %s\n", icf[ic]);
+ printf("\tInput Data Format: %s\n", idf[(vs & 0xc0) >> 6]);
+
+ if (!ic) {
+ printf("\tInput Sample Size: %s\n",
+ iss[(vs & 0x20) >> 5]);
+ printf("\t# of bits padding at MSB: %d\n",
+ (vs & 0x1c) >> 2);
+ }
+ printf("\tAir Coding Format: %s\n", acf[vs & 0x03]);
+ }
+}
+
+static void cmd_delkey(int ctl, int hdev, char *opt)
+{
+ bdaddr_t bdaddr;
+ uint8_t all;
+ int dd;
+
+ if (!opt)
+ return;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (!strcasecmp(opt, "all")) {
+ bacpy(&bdaddr, BDADDR_ANY);
+ all = 1;
+ } else {
+ str2ba(opt, &bdaddr);
+ all = 0;
+ }
+
+ if (hci_delete_stored_link_key(dd, &bdaddr, all, 1000) < 0) {
+ fprintf(stderr, "Can't delete stored link key on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ hci_close_dev(dd);
+}
+
+static void cmd_oob_data(int ctl, int hdev, char *opt)
+{
+ uint8_t hash[16], randomizer[16];
+ int i, dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (hci_read_local_oob_data(dd, hash, randomizer, 1000) < 0) {
+ fprintf(stderr, "Can't read local OOB data on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ printf("\tOOB Hash: ");
+ for (i = 0; i < 16; i++)
+ printf(" %02x", hash[i]);
+ printf("\n\tRandomizer:");
+ for (i = 0; i < 16; i++)
+ printf(" %02x", randomizer[i]);
+ printf("\n");
+
+ hci_close_dev(dd);
+}
+
+static void cmd_commands(int ctl, int hdev, char *opt)
+{
+ uint8_t cmds[64];
+ char *str;
+ int i, n, dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (hci_read_local_commands(dd, cmds, 1000) < 0) {
+ fprintf(stderr, "Can't read support commands on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ for (i = 0; i < 64; i++) {
+ if (!cmds[i])
+ continue;
+
+ printf("%s Octet %-2d = 0x%02x (Bit",
+ i ? "\t\t ": "\tCommands:", i, cmds[i]);
+ for (n = 0; n < 8; n++)
+ if (cmds[i] & (1 << n))
+ printf(" %d", n);
+ printf(")\n");
+ }
+
+ str = hci_commandstostr(cmds, "\t", 71);
+ printf("%s\n", str);
+ bt_free(str);
+
+ hci_close_dev(dd);
+}
+
+static void cmd_version(int ctl, int hdev, char *opt)
+{
+ struct hci_version ver;
+ char *hciver, *lmpver;
+ int dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (hci_read_local_version(dd, &ver, 1000) < 0) {
+ fprintf(stderr, "Can't read version info hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ hciver = hci_vertostr(ver.hci_ver);
+ if (((di.type & 0x30) >> 4) == HCI_BREDR)
+ lmpver = lmp_vertostr(ver.lmp_ver);
+ else
+ lmpver = pal_vertostr(ver.lmp_ver);
+
+ print_dev_hdr(&di);
+ printf("\tHCI Version: %s (0x%x) Revision: 0x%x\n"
+ "\t%s Version: %s (0x%x) Subversion: 0x%x\n"
+ "\tManufacturer: %s (%d)\n",
+ hciver ? hciver : "n/a", ver.hci_ver, ver.hci_rev,
+ (((di.type & 0x30) >> 4) == HCI_BREDR) ? "LMP" : "PAL",
+ lmpver ? lmpver : "n/a", ver.lmp_ver, ver.lmp_subver,
+ bt_compidtostr(ver.manufacturer), ver.manufacturer);
+
+ if (hciver)
+ bt_free(hciver);
+ if (lmpver)
+ bt_free(lmpver);
+
+ hci_close_dev(dd);
+}
+
+static void cmd_inq_tpl(int ctl, int hdev, char *opt)
+{
+ int dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (opt) {
+ int8_t level = atoi(opt);
+
+ if (hci_write_inquiry_transmit_power_level(dd, level, 2000) < 0) {
+ fprintf(stderr, "Can't set inquiry transmit power level on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ int8_t level;
+
+ if (hci_read_inq_response_tx_power_level(dd, &level, 1000) < 0) {
+ fprintf(stderr, "Can't read inquiry transmit power level on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ printf("\tInquiry transmit power level: %d\n", level);
+ }
+
+ hci_close_dev(dd);
+}
+
+static void cmd_inq_mode(int ctl, int hdev, char *opt)
+{
+ int dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (opt) {
+ uint8_t mode = atoi(opt);
+
+ if (hci_write_inquiry_mode(dd, mode, 2000) < 0) {
+ fprintf(stderr, "Can't set inquiry mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint8_t mode;
+
+ if (hci_read_inquiry_mode(dd, &mode, 1000) < 0) {
+ fprintf(stderr, "Can't read inquiry mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ printf("\tInquiry mode: ");
+ switch (mode) {
+ case 0:
+ printf("Standard Inquiry\n");
+ break;
+ case 1:
+ printf("Inquiry with RSSI\n");
+ break;
+ case 2:
+ printf("Inquiry with RSSI or Extended Inquiry\n");
+ break;
+ default:
+ printf("Unknown (0x%02x)\n", mode);
+ break;
+ }
+ }
+
+ hci_close_dev(dd);
+}
+
+static void cmd_inq_data(int ctl, int hdev, char *opt)
+{
+ int i, dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (opt) {
+ uint8_t fec = 0, data[HCI_MAX_EIR_LENGTH];
+ char tmp[3];
+ int i, size;
+
+ memset(data, 0, sizeof(data));
+
+ memset(tmp, 0, sizeof(tmp));
+ size = (strlen(opt) + 1) / 2;
+ if (size > HCI_MAX_EIR_LENGTH)
+ size = HCI_MAX_EIR_LENGTH;
+
+ for (i = 0; i < size; i++) {
+ memcpy(tmp, opt + (i * 2), 2);
+ data[i] = strtol(tmp, NULL, 16);
+ }
+
+ if (hci_write_ext_inquiry_response(dd, fec, data, 2000) < 0) {
+ fprintf(stderr, "Can't set extended inquiry response on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint8_t fec, data[HCI_MAX_EIR_LENGTH], len, type, *ptr;
+ char *str;
+
+ if (hci_read_ext_inquiry_response(dd, &fec, data, 1000) < 0) {
+ fprintf(stderr, "Can't read extended inquiry response on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ printf("\tFEC %s\n\t\t", fec ? "enabled" : "disabled");
+ for (i = 0; i < HCI_MAX_EIR_LENGTH; i++)
+ printf("%02x%s%s", data[i], (i + 1) % 8 ? "" : " ",
+ (i + 1) % 16 ? " " : (i < 239 ? "\n\t\t" : "\n"));
+
+ ptr = data;
+ while (*ptr) {
+ len = *ptr++;
+ type = *ptr++;
+ switch (type) {
+ case 0x01:
+ printf("\tFlags:");
+ for (i = 0; i < len - 1; i++)
+ printf(" 0x%2.2x", *((uint8_t *) (ptr + i)));
+ printf("\n");
+ break;
+ case 0x02:
+ case 0x03:
+ printf("\t%s service classes:",
+ type == 0x02 ? "Shortened" : "Complete");
+ for (i = 0; i < (len - 1) / 2; i++) {
+ uint16_t val = bt_get_le16((ptr + (i * 2)));
+ printf(" 0x%4.4x", val);
+ }
+ printf("\n");
+ break;
+ case 0x08:
+ case 0x09:
+ str = malloc(len);
+ if (str) {
+ snprintf(str, len, "%s", ptr);
+ for (i = 0; i < len - 1; i++) {
+ if ((unsigned char) str[i] < 32 || str[i] == 127)
+ str[i] = '.';
+ }
+ printf("\t%s local name: \'%s\'\n",
+ type == 0x08 ? "Shortened" : "Complete", str);
+ free(str);
+ }
+ break;
+ case 0x0a:
+ printf("\tTX power level: %d\n", *((int8_t *) ptr));
+ break;
+ case 0x10:
+ printf("\tDevice ID with %d bytes data\n",
+ len - 1);
+ break;
+ default:
+ printf("\tUnknown type 0x%02x with %d bytes data\n",
+ type, len - 1);
+ break;
+ }
+
+ ptr += (len - 1);
+ }
+
+ printf("\n");
+ }
+
+ hci_close_dev(dd);
+}
+
+static void cmd_inq_type(int ctl, int hdev, char *opt)
+{
+ int dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (opt) {
+ uint8_t type = atoi(opt);
+
+ if (hci_write_inquiry_scan_type(dd, type, 2000) < 0) {
+ fprintf(stderr, "Can't set inquiry scan type on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint8_t type;
+
+ if (hci_read_inquiry_scan_type(dd, &type, 1000) < 0) {
+ fprintf(stderr, "Can't read inquiry scan type on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ printf("\tInquiry scan type: %s\n",
+ type == 1 ? "Interlaced Inquiry Scan" : "Standard Inquiry Scan");
+ }
+
+ hci_close_dev(dd);
+}
+
+static void cmd_inq_parms(int ctl, int hdev, char *opt)
+{
+ struct hci_request rq;
+ int s;
+
+ if ((s = hci_open_dev(hdev)) < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ memset(&rq, 0, sizeof(rq));
+
+ if (opt) {
+ unsigned int window, interval;
+ write_inq_activity_cp cp;
+
+ if (sscanf(opt,"%4u:%4u", &window, &interval) != 2) {
+ printf("Invalid argument format\n");
+ exit(1);
+ }
+
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_WRITE_INQ_ACTIVITY;
+ rq.cparam = &cp;
+ rq.clen = WRITE_INQ_ACTIVITY_CP_SIZE;
+
+ cp.window = htobs((uint16_t) window);
+ cp.interval = htobs((uint16_t) interval);
+
+ if (window < 0x12 || window > 0x1000)
+ printf("Warning: inquiry window out of range!\n");
+
+ if (interval < 0x12 || interval > 0x1000)
+ printf("Warning: inquiry interval out of range!\n");
+
+ if (hci_send_req(s, &rq, 2000) < 0) {
+ fprintf(stderr, "Can't set inquiry parameters name on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint16_t window, interval;
+ read_inq_activity_rp rp;
+
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_READ_INQ_ACTIVITY;
+ rq.rparam = &rp;
+ rq.rlen = READ_INQ_ACTIVITY_RP_SIZE;
+
+ if (hci_send_req(s, &rq, 1000) < 0) {
+ fprintf(stderr, "Can't read inquiry parameters on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ if (rp.status) {
+ printf("Read inquiry parameters on hci%d returned status %d\n",
+ hdev, rp.status);
+ exit(1);
+ }
+ print_dev_hdr(&di);
+
+ window = btohs(rp.window);
+ interval = btohs(rp.interval);
+ printf("\tInquiry interval: %u slots (%.2f ms), window: %u slots (%.2f ms)\n",
+ interval, (float)interval * 0.625, window, (float)window * 0.625);
+ }
+}
+
+static void cmd_page_parms(int ctl, int hdev, char *opt)
+{
+ struct hci_request rq;
+ int s;
+
+ if ((s = hci_open_dev(hdev)) < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ memset(&rq, 0, sizeof(rq));
+
+ if (opt) {
+ unsigned int window, interval;
+ write_page_activity_cp cp;
+
+ if (sscanf(opt,"%4u:%4u", &window, &interval) != 2) {
+ printf("Invalid argument format\n");
+ exit(1);
+ }
+
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_WRITE_PAGE_ACTIVITY;
+ rq.cparam = &cp;
+ rq.clen = WRITE_PAGE_ACTIVITY_CP_SIZE;
+
+ cp.window = htobs((uint16_t) window);
+ cp.interval = htobs((uint16_t) interval);
+
+ if (window < 0x12 || window > 0x1000)
+ printf("Warning: page window out of range!\n");
+
+ if (interval < 0x12 || interval > 0x1000)
+ printf("Warning: page interval out of range!\n");
+
+ if (hci_send_req(s, &rq, 2000) < 0) {
+ fprintf(stderr, "Can't set page parameters name on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint16_t window, interval;
+ read_page_activity_rp rp;
+
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_READ_PAGE_ACTIVITY;
+ rq.rparam = &rp;
+ rq.rlen = READ_PAGE_ACTIVITY_RP_SIZE;
+
+ if (hci_send_req(s, &rq, 1000) < 0) {
+ fprintf(stderr, "Can't read page parameters on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ if (rp.status) {
+ printf("Read page parameters on hci%d returned status %d\n",
+ hdev, rp.status);
+ exit(1);
+ }
+ print_dev_hdr(&di);
+
+ window = btohs(rp.window);
+ interval = btohs(rp.interval);
+ printf("\tPage interval: %u slots (%.2f ms), "
+ "window: %u slots (%.2f ms)\n",
+ interval, (float)interval * 0.625,
+ window, (float)window * 0.625);
+ }
+}
+
+static void cmd_page_to(int ctl, int hdev, char *opt)
+{
+ struct hci_request rq;
+ int s;
+
+ if ((s = hci_open_dev(hdev)) < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ memset(&rq, 0, sizeof(rq));
+
+ if (opt) {
+ unsigned int timeout;
+ write_page_timeout_cp cp;
+
+ if (sscanf(opt,"%5u", &timeout) != 1) {
+ printf("Invalid argument format\n");
+ exit(1);
+ }
+
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_WRITE_PAGE_TIMEOUT;
+ rq.cparam = &cp;
+ rq.clen = WRITE_PAGE_TIMEOUT_CP_SIZE;
+
+ cp.timeout = htobs((uint16_t) timeout);
+
+ if (timeout < 0x01 || timeout > 0xFFFF)
+ printf("Warning: page timeout out of range!\n");
+
+ if (hci_send_req(s, &rq, 2000) < 0) {
+ fprintf(stderr, "Can't set page timeout on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint16_t timeout;
+ read_page_timeout_rp rp;
+
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_READ_PAGE_TIMEOUT;
+ rq.rparam = &rp;
+ rq.rlen = READ_PAGE_TIMEOUT_RP_SIZE;
+
+ if (hci_send_req(s, &rq, 1000) < 0) {
+ fprintf(stderr, "Can't read page timeout on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ if (rp.status) {
+ printf("Read page timeout on hci%d returned status %d\n",
+ hdev, rp.status);
+ exit(1);
+ }
+ print_dev_hdr(&di);
+
+ timeout = btohs(rp.timeout);
+ printf("\tPage timeout: %u slots (%.2f ms)\n",
+ timeout, (float)timeout * 0.625);
+ }
+}
+
+static void cmd_afh_mode(int ctl, int hdev, char *opt)
+{
+ int dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (opt) {
+ uint8_t mode = atoi(opt);
+
+ if (hci_write_afh_mode(dd, mode, 2000) < 0) {
+ fprintf(stderr, "Can't set AFH mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint8_t mode;
+
+ if (hci_read_afh_mode(dd, &mode, 1000) < 0) {
+ fprintf(stderr, "Can't read AFH mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ printf("\tAFH mode: %s\n", mode == 1 ? "Enabled" : "Disabled");
+ }
+}
+
+static void cmd_ssp_mode(int ctl, int hdev, char *opt)
+{
+ int dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (opt) {
+ uint8_t mode = atoi(opt);
+
+ if (hci_write_simple_pairing_mode(dd, mode, 2000) < 0) {
+ fprintf(stderr, "Can't set Simple Pairing mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+ } else {
+ uint8_t mode;
+
+ if (hci_read_simple_pairing_mode(dd, &mode, 1000) < 0) {
+ fprintf(stderr, "Can't read Simple Pairing mode on hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ print_dev_hdr(&di);
+ printf("\tSimple Pairing mode: %s\n",
+ mode == 1 ? "Enabled" : "Disabled");
+ }
+}
+
+static void print_rev_ericsson(int dd)
+{
+ struct hci_request rq;
+ unsigned char buf[102];
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x000f;
+ rq.cparam = NULL;
+ rq.clen = 0;
+ rq.rparam = &buf;
+ rq.rlen = sizeof(buf);
+
+ if (hci_send_req(dd, &rq, 1000) < 0) {
+ printf("\nCan't read revision info: %s (%d)\n",
+ strerror(errno), errno);
+ return;
+ }
+
+ printf("\t%s\n", buf + 1);
+}
+
+static void print_rev_csr(int dd, uint16_t rev)
+{
+ uint16_t buildid, chipver, chiprev, maxkeylen, mapsco;
+
+ if (csr_read_varid_uint16(dd, 0, CSR_VARID_BUILDID, &buildid) < 0) {
+ printf("\t%s\n", csr_buildidtostr(rev));
+ return;
+ }
+
+ printf("\t%s\n", csr_buildidtostr(buildid));
+
+ if (!csr_read_varid_uint16(dd, 1, CSR_VARID_CHIPVER, &chipver)) {
+ if (csr_read_varid_uint16(dd, 2, CSR_VARID_CHIPREV, &chiprev) < 0)
+ chiprev = 0;
+ printf("\tChip version: %s\n", csr_chipvertostr(chipver, chiprev));
+ }
+
+ if (!csr_read_varid_uint16(dd, 3, CSR_VARID_MAX_CRYPT_KEY_LENGTH, &maxkeylen))
+ printf("\tMax key size: %d bit\n", maxkeylen * 8);
+
+ if (!csr_read_pskey_uint16(dd, 4, CSR_PSKEY_HOSTIO_MAP_SCO_PCM, 0x0000, &mapsco))
+ printf("\tSCO mapping: %s\n", mapsco ? "PCM" : "HCI");
+}
+
+static void print_rev_digianswer(int dd)
+{
+ struct hci_request rq;
+ unsigned char req[] = { 0x07 };
+ unsigned char buf[102];
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x000e;
+ rq.cparam = req;
+ rq.clen = sizeof(req);
+ rq.rparam = &buf;
+ rq.rlen = sizeof(buf);
+
+ if (hci_send_req(dd, &rq, 1000) < 0) {
+ printf("\nCan't read revision info: %s (%d)\n",
+ strerror(errno), errno);
+ return;
+ }
+
+ printf("\t%s\n", buf + 1);
+}
+
+static void print_rev_broadcom(uint16_t hci_rev, uint16_t lmp_subver)
+{
+ printf("\tFirmware %d.%d / %d\n",
+ hci_rev & 0xff, lmp_subver >> 8, lmp_subver & 0xff);
+}
+
+static void print_rev_avm(uint16_t hci_rev, uint16_t lmp_subver)
+{
+ if (lmp_subver == 0x01)
+ printf("\tFirmware 03.%d.%d\n", hci_rev >> 8, hci_rev & 0xff);
+ else
+ printf("\tUnknown type\n");
+}
+
+static void cmd_revision(int ctl, int hdev, char *opt)
+{
+ struct hci_version ver;
+ int dd;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ return;
+ }
+
+ if (hci_read_local_version(dd, &ver, 1000) < 0) {
+ fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ return;
+ }
+
+ print_dev_hdr(&di);
+ switch (ver.manufacturer) {
+ case 0:
+ case 37:
+ case 48:
+ print_rev_ericsson(dd);
+ break;
+ case 10:
+ print_rev_csr(dd, ver.hci_rev);
+ break;
+ case 12:
+ print_rev_digianswer(dd);
+ break;
+ case 15:
+ print_rev_broadcom(ver.hci_rev, ver.lmp_subver);
+ break;
+ case 31:
+ print_rev_avm(ver.hci_rev, ver.lmp_subver);
+ break;
+ default:
+ printf("\tUnsupported manufacturer\n");
+ break;
+ }
+ return;
+}
+
+static void cmd_block(int ctl, int hdev, char *opt)
+{
+ bdaddr_t bdaddr;
+ int dd;
+
+ if (!opt)
+ return;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ str2ba(opt, &bdaddr);
+
+ if (ioctl(dd, HCIBLOCKADDR, &bdaddr) < 0) {
+ perror("ioctl(HCIBLOCKADDR)");
+ exit(1);
+ }
+
+ hci_close_dev(dd);
+}
+
+static void cmd_unblock(int ctl, int hdev, char *opt)
+{
+ bdaddr_t bdaddr;
+ int dd;
+
+ if (!opt)
+ return;
+
+ dd = hci_open_dev(hdev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ hdev, strerror(errno), errno);
+ exit(1);
+ }
+
+ if (!strcasecmp(opt, "all"))
+ bacpy(&bdaddr, BDADDR_ANY);
+ else
+ str2ba(opt, &bdaddr);
+
+ if (ioctl(dd, HCIUNBLOCKADDR, &bdaddr) < 0) {
+ perror("ioctl(HCIUNBLOCKADDR)");
+ exit(1);
+ }
+
+ hci_close_dev(dd);
+}
+
+static void print_dev_hdr(struct hci_dev_info *di)
+{
+ static int hdr = -1;
+ char addr[18];
+
+ if (hdr == di->dev_id)
+ return;
+ hdr = di->dev_id;
+
+ ba2str(&di->bdaddr, addr);
+
+ printf("%s:\tType: %s Bus: %s\n", di->name,
+ hci_typetostr((di->type & 0x30) >> 4),
+ hci_bustostr(di->type & 0x0f));
+ printf("\tBD Address: %s ACL MTU: %d:%d SCO MTU: %d:%d\n",
+ addr, di->acl_mtu, di->acl_pkts,
+ di->sco_mtu, di->sco_pkts);
+}
+
+static void print_dev_info(int ctl, struct hci_dev_info *di)
+{
+ struct hci_dev_stats *st = &di->stat;
+ char *str;
+
+ print_dev_hdr(di);
+
+ str = hci_dflagstostr(di->flags);
+ printf("\t%s\n", str);
+ bt_free(str);
+
+ printf("\tRX bytes:%d acl:%d sco:%d events:%d errors:%d\n",
+ st->byte_rx, st->acl_rx, st->sco_rx, st->evt_rx, st->err_rx);
+
+ printf("\tTX bytes:%d acl:%d sco:%d commands:%d errors:%d\n",
+ st->byte_tx, st->acl_tx, st->sco_tx, st->cmd_tx, st->err_tx);
+
+ if (all && !hci_test_bit(HCI_RAW, &di->flags)) {
+ print_dev_features(di, 0);
+
+ if (((di->type & 0x30) >> 4) == HCI_BREDR) {
+ print_pkt_type(di);
+ print_link_policy(di);
+ print_link_mode(di);
+
+ if (hci_test_bit(HCI_UP, &di->flags)) {
+ cmd_name(ctl, di->dev_id, NULL);
+ cmd_class(ctl, di->dev_id, NULL);
+ }
+ }
+
+ if (hci_test_bit(HCI_UP, &di->flags))
+ cmd_version(ctl, di->dev_id, NULL);
+ }
+
+ printf("\n");
+}
+
+static struct {
+ char *cmd;
+ void (*func)(int ctl, int hdev, char *opt);
+ char *opt;
+ char *doc;
+} command[] = {
+ { "up", cmd_up, 0, "Open and initialize HCI device" },
+ { "down", cmd_down, 0, "Close HCI device" },
+ { "reset", cmd_reset, 0, "Reset HCI device" },
+ { "rstat", cmd_rstat, 0, "Reset statistic counters" },
+ { "auth", cmd_auth, 0, "Enable Authentication" },
+ { "noauth", cmd_auth, 0, "Disable Authentication" },
+ { "encrypt", cmd_encrypt, 0, "Enable Encryption" },
+ { "noencrypt", cmd_encrypt, 0, "Disable Encryption" },
+ { "piscan", cmd_scan, 0, "Enable Page and Inquiry scan" },
+ { "noscan", cmd_scan, 0, "Disable scan" },
+ { "iscan", cmd_scan, 0, "Enable Inquiry scan" },
+ { "pscan", cmd_scan, 0, "Enable Page scan" },
+ { "ptype", cmd_ptype, "[type]", "Get/Set default packet type" },
+ { "lm", cmd_lm, "[mode]", "Get/Set default link mode" },
+ { "lp", cmd_lp, "[policy]", "Get/Set default link policy" },
+ { "name", cmd_name, "[name]", "Get/Set local name" },
+ { "class", cmd_class, "[class]", "Get/Set class of device" },
+ { "voice", cmd_voice, "[voice]", "Get/Set voice setting" },
+ { "iac", cmd_iac, "[iac]", "Get/Set inquiry access code" },
+ { "inqtpl", cmd_inq_tpl, "[level]", "Get/Set inquiry transmit power level" },
+ { "inqmode", cmd_inq_mode, "[mode]", "Get/Set inquiry mode" },
+ { "inqdata", cmd_inq_data, "[data]", "Get/Set inquiry data" },
+ { "inqtype", cmd_inq_type, "[type]", "Get/Set inquiry scan type" },
+ { "inqparms", cmd_inq_parms, "[win:int]", "Get/Set inquiry scan window and interval" },
+ { "pageparms", cmd_page_parms, "[win:int]", "Get/Set page scan window and interval" },
+ { "pageto", cmd_page_to, "[to]", "Get/Set page timeout" },
+ { "afhmode", cmd_afh_mode, "[mode]", "Get/Set AFH mode" },
+ { "sspmode", cmd_ssp_mode, "[mode]", "Get/Set Simple Pairing Mode" },
+ { "aclmtu", cmd_aclmtu, "", "Set ACL MTU and number of packets" },
+ { "scomtu", cmd_scomtu, "", "Set SCO MTU and number of packets" },
+ { "delkey", cmd_delkey, "", "Delete link key from the device" },
+ { "oobdata", cmd_oob_data, 0, "Get local OOB data" },
+ { "commands", cmd_commands, 0, "Display supported commands" },
+ { "features", cmd_features, 0, "Display device features" },
+ { "version", cmd_version, 0, "Display version information" },
+ { "revision", cmd_revision, 0, "Display revision information" },
+ { "block", cmd_block, "