Project import generated by Copybara. GitOrigin-RevId: 476af6c46a320325a2c516b0e6610867279a913a
diff --git a/Android.mk b/Android.mk new file mode 100755 index 0000000..d61ca11 --- /dev/null +++ b/Android.mk
@@ -0,0 +1,21 @@ +ifeq ($(BOARD_HAVE_BLUETOOTH),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES:= \ + $(call include-path-for,bluez)/lib/ \ + +LOCAL_SRC_FILES:= \ + compat/getline.c \ + btconfig.c + +LOCAL_SHARED_LIBRARIES := \ + libbluetooth \ + +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE:=btconfig + +include $(BUILD_EXECUTABLE) +endif
diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..e90dfed --- /dev/null +++ b/COPYING
@@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 + + +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 Library General +Public License instead of this License.
diff --git a/ChangeLog.txt b/ChangeLog.txt new file mode 100755 index 0000000..00581d5 --- /dev/null +++ b/ChangeLog.txt
@@ -0,0 +1,5 @@ +10/03/2012: define HI_MAGIC_NUMBER as unsigned short int, send sleep mode enabled command before do soft reset in master blaster mode since sleep mode is enabled from PS_ASIC.pst. version:1.05 +06/08/2012: Sync the structure tBtHost_Interest and PsSysCfgTransmitPowerControlEntry with BtTest version: 1.04 +04/26/2012: Support RX test and get BER at "Masterblaster" mode version: 1.03 +0 +03/14/2012: BtAgent is running at customer platform. It communicates with the host via USB. It looks like a router, which is forwarding packet between the host and AR3002. BtSoc.exe is running at the host. Like BtUART.exe, it can send command or receive event from AR3002 via BtAgent. version: 1.02
diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..520e903 --- /dev/null +++ b/Makefile
@@ -0,0 +1,23 @@ + # Copyright (c) 2008-2009 Atheros 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 version 2 as + # published by the Free Software Foundation; + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + + +CC := arm-none-linux-gnueabi-gcc +CFLAGS=-I../../../bluez/bluez/lib/ -mtune=arm1136j-s -march=armv6 +LDFLAGS=-lbluetooth -L../../../bluez/dist/usr/lib -L../../../../a5s_linux_sdk/ambarella/prebuild/third-party/ncurses/lib/ + +all: btconfig + +btconfig: btconfig.c + $(CC) -Wall -g btconfig.c $(CFLAGS) $(LDFLAGS) -o btconfig + +clean: + rm btconfig
diff --git a/README b/README new file mode 100755 index 0000000..21a93cf --- /dev/null +++ b/README
@@ -0,0 +1,68 @@ +Compilation Instructions +======================== + +In order to compile Bluetooth utilities you need following software packages: + - Linux Bluetooth protocol stack (BlueZ) + - GCC compiler + - D-Bus library + - GLib library + - Lexical Analyzer (flex, lex) + - YACC (yacc, bison, byacc) + +To install these packages, switch to root previlege. + +Fedora Core: +1] Linux Bluetooth protocol stack (BlueZ): + Download latest source code of BlueZ stack from: + http://www.bluez.org/download/ +2]GCC Compiler: + =>yum install gcc + +3]D-Bus library: + =>yum install dbus + +4]Lexical Analyzer (flex, lex) + =>yum install flex + +5]YACC (yacc, bison, byacc) + =>yum install byacc bison + + +Ubuntu: +1] Linux Bluetooth protocol stack (BlueZ): + Download latest source code of BlueZ stack from: + http://www.bluez.org/download/ + +2]GCC Compiler: + =>sudo apt-get install gcc + +3]D-Bus library + =>sudo apt-get install libdbus-glib-1-dev + +4]Lexical Analyzer (flex, lex) + =>sudo apt-get install flex + +5]YACC (yacc, bison, byacc) + =>sudo apt-get install byacc + +After downloading these packages please follow README file from bluez source folder to install Bluez stack. + +Once BlueZ Stack is installed, go to btconfig folder and give make command to compile btconfig source code: + =>make + + "btconfig" executable will be genearated and copied to /usr/bin folder, so that you can access it from any location. + +Application usage +================= + +Use following command to get help about the features supported by btconfig: + => btconfig --help + => btconfig + +To get the help about syntax and additional parameters of the command: + E.g. To get help about Write BD Address (wba) command + => btconfig wba + Read PS tag operation + => btconfig rpst + +
diff --git a/btconfig.c b/btconfig.c new file mode 100755 index 0000000..a3dc89b --- /dev/null +++ b/btconfig.c
@@ -0,0 +1,5308 @@ +/* + * Copyright (c) 2008-2009 Atheros 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 version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * <Configuration utility for AR3001> + * + * <btconfig.c> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <ctype.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <signal.h> +#include <time.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <linux/types.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <bluetooth/bluetooth.h> +#include <bluetooth/hci.h> +#include <bluetooth/hci_lib.h> + +#include "compat/getline.h" +#include "btconfig.h" +#include "masterblaster.h" + +#define BT_PORT 2398 +/* Global Variables */ +static int sid, cid, aid; +static int Tag_Count = 0; +static int Patch_Count = 0; +static unsigned short DynMem_Count = 0; +static int Total_tag_lenght = 0; +static BOOL CtrlCBreak = FALSE; +bdaddr_t BdAddr; +/* Function Declarations */ +static int LoadConfFile(const char *path, int basetag, int format); +static int ParseFiles(FILE *fpt, int basetag, int format); +static void LoadPSHeader(UCHAR *HCI_PS_Command,UCHAR opcode,int length,int index); +static BOOL PSOperations(int dd, UCHAR Opcode, int Param1, UINT32 *out); +static BOOL SU_LERxTest(int dev_id, UCHAR channel); +static BOOL SU_LETxTest(int dev_id, UCHAR channel, UCHAR length, UCHAR payload); +static int PSInit(int dd); +static void usage(void); +static int writeHciCommand(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, UCHAR *buf); +static int MemBlkRead(int dd, UINT32 Address,UCHAR *pBuffer, UINT32 Length); +static int MemBlkwrite(int dd, UINT32 Address,UCHAR *pBuffer, UINT32 Length); +static int Dut(int dd); +static int ReadAudioStats(int dd); +static int ReadGlobalDMAStats(int dd); +static int ResetGlobalDMAStats(int dd); +static int ReadTpcTable(int dd); +static int ReadHostInterest(int dd,tBtHostInterest *pHostInt); +static int ReadMemoryBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ); +static int WriteMemoryBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ); +static int write_otpRaw(int dev_id, int address, int length, UCHAR *data); +static int read_otpRaw(int dev_id, int address, int length, UCHAR *data); +static void dumpHex(UCHAR *buf, int length, int col); +static void sig_term(int sig); +static UCHAR LEMode = 0; + +static struct option main_options[] = { + { "help", 0, 0, 'h' }, + { "device", 1, 0, 'i' }, + { 0, 0, 0, 0 } +}; +//Read the configuration files, file paths are hardcoded in btconfig.h +static int LoadConfFile(const char *path, int basetag, int format){ + + FILE *fp; + //printf("\nOpening file :%s\n",path); + fp = fopen(path,"r"); + if(fp == NULL){ + // perror("File open error"); + return FALSE; + } + // Parse file + if(!ParseFiles(fp,basetag,format)){ + printf("\nError :Invalid file format\n"); + return FALSE; + } + // Load conf data to PS + + fclose(fp); + return TRUE; +} + + +unsigned int uGetInputDataFormat(char **str, struct ST_PS_DATA_FORMAT *pstFormat) +{ + char *pCharLine = *str; + if(pCharLine[0] != '[') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + return TRUE; + } + switch(pCharLine[1]) { + case 'H': + case 'h': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'a') || (pCharLine[3]== 'A')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 5; + *str += 5; + return TRUE; + } + else { + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); //[H:A + return FALSE; + } + } + if((pCharLine[3]== 'S') || (pCharLine[3]== 's')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = FALSE; + //pCharLine += 5; + *str += 5; + //printf("\nDEBUG H-1:%s\n",pCharLine); + return TRUE; + } + else { + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); //[H:A + return FALSE; + } + } + else if(pCharLine[3] == ']') { //[H:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 4; + *str += 4; + return TRUE; + } + else { //[H: + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); + return FALSE; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 3; + *str += 5; + return TRUE; + } + else { //[H + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); + return FALSE; + } + break; + + case 'A': + case 'a': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 5; + *str += 5; + return TRUE; + } + else { + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); //[A:H + return FALSE; + } + } + else if(pCharLine[3]== ']') { //[A:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 4; + *str += 5; + return TRUE; + } + else { //[A: + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); + return FALSE; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 3; + *str += 5; + return TRUE; + } + else { //[H + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); + return FALSE; + } + break; + + case 'S': + case 's': + if(pCharLine[2]==':') { + if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) { + if(pCharLine[4] == ']') { + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 5; + *str += 5; + return TRUE; + } + else { + printf("\nuGetInputDataFormat - Invalid Data Format \r\n");//[A:H + return FALSE; + } + } + else if(pCharLine[3]== ']') { //[A:] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 4; + *str += 5; + return TRUE; + } + else { //[A: + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); + return FALSE; + } + } + else if(pCharLine[2]==']') { //[H] + pstFormat->eDataType = eHex; + pstFormat->bIsArray = TRUE; + //pCharLine += 3; + *str += 5; + return TRUE; + } + else { //[H + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); + return FALSE; + } + break; + + default: + printf("\nuGetInputDataFormat - Invalid Data Format \r\n"); + return FALSE; + } +} + +unsigned int uReadDataInSection(char *pCharLine, struct ST_PS_DATA_FORMAT stPS_DataFormat) +{ + if(stPS_DataFormat.eDataType == eHex) { + if(stPS_DataFormat.bIsArray == TRUE) { + //Not implemented + printf("\nNO IMP\n"); + return (0x0FFF); + } + else { + //printf("\nDEBUG H-2 %d\n",strtol(pCharLine, NULL, 16)); + return (strtol(pCharLine, NULL, 16)); + } + } + else { + //Not implemented + printf("\nNO IMP-1\n"); + return (0x0FFF); + } +} + + +static int ParseFiles(FILE *fpt, int basetag, int format){ + int i,j,k,linecnt,ByteCount=0,ByteCount_Org =0,data,Cnt; + char *str,line[LINE_SIZE_MAX],byte[3]; + int ParseSelection=RAM_PS_SECTION; + struct ST_PS_DATA_FORMAT stPS_DataFormat; + struct ST_READ_STATUS stReadStatus = {0, 0, 0,0}; + unsigned int uReadCount; + + switch(format){ + case MB_FILEFORMAT_PS: + linecnt = 0; + j=0; + + while ((str = fgets(line, LINE_SIZE_MAX, fpt)) != NULL) { + SKIP_BLANKS(str); + //Comment line + if ((str[0]== '/') && (str[1]== '/')) + continue; + + if (str[0]== '#'){ + if (stReadStatus.uSection != 0){ + printf("\nParseFiles - Invalid file format %d\r\n",ParseSelection); + return FALSE; + } + else { + stReadStatus.uSection = 1; + continue; + } + + } + if ((str[0]== '/') && (str[1]== '*')) + { + str+=2; + SKIP_BLANKS(str); + if(!strncmp(str,"PA",2)||!strncmp(str,"Pa",2)||!strncmp(str,"pa",2)){ + + ParseSelection=RAM_PATCH_SECTION; + } + if(!strncmp(str,"DY",2)||!strncmp(str,"Dy",2)||!strncmp(str,"dy",2)){ + + ParseSelection=RAM_DYN_MEM_SECTION; + } + if(!strncmp(str,"PS",2)||!strncmp(str,"Ps",2)||!strncmp(str,"ps",2)){ + + ParseSelection=RAM_PS_SECTION; + } + linecnt = 0; + stReadStatus.uSection = 0; + continue; + } + + switch(ParseSelection){ + + case RAM_PS_SECTION: + if (stReadStatus.uSection == 1){ //TagID + SKIP_BLANKS(str); + if(!uGetInputDataFormat(&str, &stPS_DataFormat)) { + return FALSE; + } + PsTagEntry[Tag_Count].TagId = uReadDataInSection(str, stPS_DataFormat); + stReadStatus.uSection = 2; + } + else if (stReadStatus.uSection == 2){ //TagLength + if(!uGetInputDataFormat(&str, &stPS_DataFormat)) { + return FALSE; + } + ByteCount = uReadDataInSection(str, stPS_DataFormat); + + if (ByteCount > RAMPS_MAX_PS_DATA_PER_TAG){ + printf("\nParseFiles - INVALID %d: One of the table exceeds maximum table size of %d\r\n",ParseSelection, MAX_RADIO_CFG_TABLE_SIZE); + return FALSE; + } + PsTagEntry[Tag_Count].TagLen = (ByteCount & 0xFF); + stReadStatus.uSection = 3; + stReadStatus.uLineCount = 0; + } + else if( stReadStatus.uSection == 3) { //Data + if(stReadStatus.uLineCount == 0) { + if(!uGetInputDataFormat(&str,&stPS_DataFormat)) { + return FALSE; + } + } + SKIP_BLANKS(str); + stReadStatus.uCharCount = 0; + uReadCount = (ByteCount > BYTES_OF_PS_DATA_PER_LINE)? BYTES_OF_PS_DATA_PER_LINE: ByteCount; + if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == TRUE) { + while(uReadCount > 0) { + PsTagEntry[Tag_Count].TagData[stReadStatus.uByteCount] = (UCHAR)(CONV_HEX_DIGIT_TO_VALUE(str[stReadStatus.uCharCount]) << 4) | (UCHAR)(CONV_HEX_DIGIT_TO_VALUE(str[stReadStatus.uCharCount + 1])); + PsTagEntry[Tag_Count].TagData[stReadStatus.uByteCount+1] = (UCHAR)(CONV_HEX_DIGIT_TO_VALUE(str[stReadStatus.uCharCount + 3]) << 4) | (UCHAR)(CONV_HEX_DIGIT_TO_VALUE(str[stReadStatus.uCharCount + 4])); + stReadStatus.uCharCount += 6; // read two bytes, plus a space; + stReadStatus.uByteCount += 2; + uReadCount -= 2; + } + + if(ByteCount > BYTES_OF_PS_DATA_PER_LINE) { + ByteCount -= BYTES_OF_PS_DATA_PER_LINE; + } + else { + ByteCount = 0; + } + } + else { + //to be implemented + printf("\nParseFiles - To be implemented"); + } + + stReadStatus.uLineCount++; + + if(ByteCount == 0) { + stReadStatus.uSection = 0; + stReadStatus.uCharCount = 0; + stReadStatus.uLineCount = 0; + stReadStatus.uByteCount = 0; + } + else { + stReadStatus.uCharCount = 0; + } + + if((stReadStatus.uSection == 0)&&(++Tag_Count == RAMPS_MAX_PS_TAGS_PER_FILE)) + { + printf("\n ParseFiles - INVALID %d: Number of tables exceeds %d\r\n",ParseSelection, RAMPS_MAX_PS_TAGS_PER_FILE); + return FALSE; + } + + + } + break; + default: + { + printf("\nParseFiles - Invalid file format %d\r\n",ParseSelection); + return FALSE; + } + break; + + + } + linecnt++; + } + break; + case MB_FILEFORMAT_DY: + { + linecnt = 0; + while ((str = fgets(line, LINE_SIZE_MAX, fpt)) != NULL) { + SKIP_BLANKS(str); + //Comment line + if ((str[0]== '/') && (str[1]== '/')) + continue; + + if ((str[0]== '/') && (str[1]== '*')) + { + continue; + } + + + if((linecnt % 2) == 0) + { + ByteCount = (UINT16)strtol(str, NULL, 16); + RamDynMemOverride.Len= (ByteCount & 0xFF); + } + else + { + for (i=0,k=0; k < ByteCount; i += 2,k++) { + memcpy(byte, &str[i], 2); + byte[2] = '\0'; + data = strtoul(byte, NULL, 16); + RamDynMemOverride.Data[k] = (data & 0xFF); + } + DynMem_Count = TRUE; + } + linecnt++; + } + } + break; + case MB_FILEFORMAT_PATCH: + { + j=0; + Cnt=0; + linecnt = 0; + while ((str = fgets(line, LINE_SIZE_MAX, fpt)) != NULL) { + SKIP_BLANKS(str); + //Comment line + if ((str[0]== '/') && (str[1]== '/')) + continue; + + if ((str[0]== '/') && (str[1]== '*')) + { + continue; + } + + if(linecnt==0) + { + ByteCount = (UINT16)strtol(str, NULL, 16); + ByteCount_Org = ByteCount; + while(ByteCount > MAX_BYTE_LENGTH){ + RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH; + Patch_Count ++; + ByteCount= ByteCount - MAX_BYTE_LENGTH; + } + RamPatch[Patch_Count].Len= (ByteCount & 0xFF); + Patch_Count ++; + + } + else + { + while(ByteCount_Org > MAX_BYTE_LENGTH){ + for (i = 0, k=0; i < MAX_BYTE_LENGTH*2; i += 2,k++) { + memcpy(byte, &str[Cnt], 2); + byte[2] = '\0'; + data = strtoul(byte, NULL, 16); + RamPatch[j].Data[k] = (data & 0xFF); + Cnt += 2; + } + j++; + ByteCount_Org = ByteCount_Org - MAX_BYTE_LENGTH; + } + if(j == 0){ + j++; + } + for (k=0; k < ByteCount_Org;k++) { + memcpy(byte, &str[Cnt], 2); + byte[2] = '\0'; + data = strtoul(byte, NULL, 16); + RamPatch[j].Data[k] = (data & 0xFF); + Cnt += 2; + } + } + + linecnt++; + } + + } + break; + + + + } + return TRUE; +} + +static void LoadPSHeader(UCHAR *HCI_PS_Command,UCHAR opcode,int length,int index) { + + HCI_PS_Command[0]= opcode; + HCI_PS_Command[1]= (index & 0xFF); + HCI_PS_Command[2]= ((index>>8) & 0xFF); + HCI_PS_Command[3]= length; + +} + + +static BOOL PSOperations(int dd, UCHAR Opcode, int Param1, UINT32 *out) { + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int Length,i,j,iRet; + memset(&buf,0,sizeof(buf)); + switch(Opcode){ + case WRITE_PATCH: + for(i=0;i< Param1;i++){ + LoadPSHeader(buf,Opcode,RamPatch[i].Len,i); + for(j=0;j<RamPatch[i].Len;j++){ + buf[4+j]=RamPatch[i].Data[j]; + } + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_PS,RamPatch[i].Len + PS_COMMAND_HEADER, buf); + if(buf[iRet-1] != 0){ + return FALSE; + } + } + break; + + case ENABLE_PATCH: + Length =0; + i=0; + LoadPSHeader(buf,Opcode,Length,i); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf); + if(buf[iRet-1] != 0){ + return FALSE; + } + break; + + case PS_RESET: + Length =0; + i=0; + LoadPSHeader(buf,Opcode,Length,i); + buf[8] = (Param1 & 0xFF); + buf[9] = ((Param1 >> 8) & 0xFF); + Length = 6; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,Length + PS_COMMAND_HEADER, buf); + if(buf[iRet-1] != 0){ + return FALSE; + } + break; + + case PS_READ: { + UCHAR *len = (UCHAR *)out; + ssize_t plen = 0; + Length = len[0] | ( len[1] << 8); + LoadPSHeader(buf,Opcode,Length,Param1); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, Length + PS_COMMAND_HEADER, buf); + if(buf[iRet-1] != 0) { + return FALSE; + } + do { + plen = read(dd, buf, HCI_MAX_EVENT_SIZE); + if (plen < 0) + return FALSE; + } while (buf[HCI_EVENT_HEADER_SIZE] != DEBUG_EVENT_TYPE_PS); + memcpy((UCHAR *)out, buf + HCI_EVENT_HEADER_SIZE + 1, plen - HCI_EVENT_HEADER_SIZE - 1); + break; + } + + case PS_WRITE: + for(i=0;i< Param1;i++){ + LoadPSHeader(buf,Opcode,PsTagEntry[i].TagLen,PsTagEntry[i].TagId); + for(j=0;j<PsTagEntry[i].TagLen;j++){ + buf[4+j]=PsTagEntry[i].TagData[j]; + } + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PsTagEntry[i].TagLen + PS_COMMAND_HEADER, buf); + if(buf[iRet-1] != 0){ + return FALSE; + } + } + break; + + case PS_DYNMEM_OVERRIDE: + LoadPSHeader(buf,Opcode,RamDynMemOverride.Len,RamDynMemOverride.Len); + for(j=0;j<RamDynMemOverride.Len;j++){ + buf[4+j]=RamDynMemOverride.Data[j]; + } + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_PS,RamDynMemOverride.Len + PS_COMMAND_HEADER, buf); + if(buf[iRet-1] != 0){ + return FALSE; + } + break; + + case PS_VERIFY_CRC: + //printf("PSOperations - PS_VERIFY_CRC:VALUE of CRC:%d\r\n",Param1); + Length =0; + LoadPSHeader(buf,Opcode,Length,Param1); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, PS_COMMAND_HEADER, buf); + if(buf[iRet-1] != 0){ + return FALSE; + } + break; + + case PS_GET_LENGTH: { + ssize_t plen = 0; + LoadPSHeader(buf,Opcode,0,Param1); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, PS_COMMAND_HEADER, buf); + if(buf[iRet-1] != 0){ + return FALSE; + } + do { + plen = read(dd, buf, HCI_MAX_EVENT_SIZE); + if (plen < 0) + return FALSE; + } while (buf[HCI_EVENT_HEADER_SIZE] != DEBUG_EVENT_TYPE_PS); + *((UINT16 *)out) = (buf[HCI_EVENT_HEADER_SIZE + 2] << 8) | buf[HCI_EVENT_HEADER_SIZE + 1]; + break; + } + } + return TRUE; +} + + +static int GetDeviceType(int dd){ + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int iRet; + unsigned int Reg = 0; + + memset(&buf,0,sizeof(buf)); + buf[0] = (FPGA_REGISTER & 0xFF); + buf[1] = ((FPGA_REGISTER >> 8) & 0xFF); + buf[2] = ((FPGA_REGISTER >> 16) & 0xFF); + buf[3] = ((FPGA_REGISTER >> 24) & 0xFF); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY,4, buf); + if(buf[6] != 0){ + return FALSE; + } + + Reg = buf[10]; + Reg = ((Reg << 8) | buf[9]); + Reg = ((Reg << 8) | buf[8]); + Reg = ((Reg << 8) | buf[7]); + return Reg; +} +/* PS Operations */ +static int PSInit(int dd){ + int i,Crc=0,DevType =0; + BOOL BDADDR_Present = 0; + BOOL File_Present = 0; + + //DevType = GetDeviceType(dd); + //printf("\nDevice Type:%x\n",DevType); + if(DevType){ + if(DevType == 0xdeadc0de){ + + if(!LoadConfFile(PS_ASIC_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PS)){ + printf("\nPlease copy PS file to :%s\n",PS_ASIC_FILENAME); + //return FALSE; + } + else + File_Present = 1; + } + else{ + if(!LoadConfFile(PS_FPGA_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PS)){ + printf("\nPlease copy PS file to :%s\n",PS_FPGA_FILENAME); + File_Present = 1; + //return FALSE; + } + else + File_Present = 1; + } + } + else{ + if(!LoadConfFile(PS_ASIC_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PS)){ + printf("\nPlease copy PS file to :%s\n",PS_ASIC_FILENAME); + File_Present = 1; + //return FALSE; + } + else + File_Present = 1; + } + + if(!LoadConfFile(PATCH_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PATCH)){ + printf("\nPlease copy Patch file to :%s\n",PATCH_FILENAME); + File_Present = 1; + } + else + File_Present = 1; + + if(!File_Present){ + printf("\nPS and Patch files are not present\n"); + return FALSE; + } + if(Tag_Count == 0){ + Total_tag_lenght = 10; + + } + else{ + for(i=0; i<Tag_Count; i++){ + if(PsTagEntry[i].TagId == 1){ + BDADDR_Present = TRUE; + //printf("ReadPSFiles - BD ADDR is present in Patch File \r\n"); + } + + if(PsTagEntry[i].TagLen % 2 == 1){ + Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen + 1; + } + else{ + Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen; + } + + } + } + + if(Tag_Count > 0 && !BDADDR_Present){ + //printf("\nReadPSFiles - BD ADDR is not present adding 10 extra bytes \r\n"); + Total_tag_lenght=Total_tag_lenght + 10; + } + Total_tag_lenght = Total_tag_lenght+ 10 + (Tag_Count*4); + +// printf("\nPSInitialize - PATCH:%d, DYN:%d, TAG:%d Total_tag_lenght:%d\n",Patch_Count,DynMem_Count,Tag_Count,Total_tag_lenght); + + if(Patch_Count > 0) + Crc |= RAM_PATCH_REGION; + if(DynMem_Count) + Crc |= RAM_DYN_MEM_REGION; + if(Tag_Count > 0) + Crc |= RAM_PS_REGION; + + if(Patch_Count || DynMem_Count || Tag_Count ){ + if(Patch_Count > 0){ + if(!PSOperations(dd,WRITE_PATCH,Patch_Count, NULL)){ + printf("\nPSInitialize - *** WRITE_PATCH FAILED**** \r\n"); + return FALSE; + } + if(!PSOperations(dd,ENABLE_PATCH,0, NULL)){ + printf("\nPSInitialize - *** ENABLE_PATCH FAILED**** \r\n"); + return FALSE; + } + } + if(DynMem_Count){ + if(!PSOperations(dd,PS_DYNMEM_OVERRIDE,DynMem_Count, NULL)){ + printf("\nPSInitialize - *** PS_DYNMEM_OVERRIDE FAILED**** \r\n"); + return FALSE; + } + } + if(!PSOperations(dd,PS_RESET,Total_tag_lenght, NULL)){ + printf("\nPSInitialize - *** PS RESET FAILED**** \r\n"); + return FALSE; + } + if(Tag_Count > 0){ + if(!PSOperations(dd,PS_WRITE,Tag_Count, NULL)){ + printf("\nPSInitialize - *** PS_WRITE FAILED**** \r\n"); + return FALSE; + } + } + + } + + if(!PSOperations(dd,PS_VERIFY_CRC,Crc, NULL)){ + printf("\nVerify CRC failed\n"); + return FALSE; + } + return TRUE; + +} + +static int writeHciCommand(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, UCHAR *buf){ +#ifdef DUMP_DEBUG +#define cmd_opcode_pack(ogf, ocf) (uint16_t)((ocf & 0x03ff)|(ogf << 10)) +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htobs(d) (d) +#elif __BYTE_ORDER == __BIG_ENDIAN +#define htobs(d) bswap_16(d); +#else +#error "Unknown byte order" +#endif + int i = 0, j = 0; + uint16_t opcode = htobs(cmd_opcode_pack(ogf, ocf)); + + printf("\nDump:\n"); + printf("0x%02X ", opcode & 0xff); + i++; + printf("0x%02X ", (opcode & 0xff00) >> 8); + i++; + printf("0x%02X ", plen); + i++; + for (j = 0; j < plen; i++, j++) { + printf("0x%02X ", buf[j]); + if (((i+1) % 8) == 0 && i != 0) + printf("\n"); + } + if (((i+1) % 8) != 0) printf("\n"); + buf[6] = 0; + return plen; +#else + struct hci_filter flt; + uint16_t opcode, topcode; + + /* Setup filter */ + hci_filter_clear(&flt); + hci_filter_set_ptype(HCI_EVENT_PKT, &flt); + hci_filter_all_events(&flt); + if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { + perror("HCI filter setup failed"); + exit(EXIT_FAILURE); + } + + //printf("< HCI Command: ogf 0x%02x, ocf 0x%04x, plen %d\n", ogf, ocf, plen); + if (hci_send_cmd(dd, ogf, ocf, plen, buf) < 0) { + perror("Send failed"); + hci_close_dev(dd); + exit(EXIT_FAILURE); + } + sleep(0.4); + opcode = (ogf << 10 | ocf); + do { + plen = read(dd, buf,HCI_MAX_EVENT_SIZE); + if (plen < 0) { + perror("Read failed"); + hci_close_dev(dd); + exit(EXIT_FAILURE); + } + topcode=(uint16_t)(buf[4] | (buf[5] << 8)); + }while(topcode != opcode); + return plen; +#endif +} +static int MemBlkRead(int dd,UINT32 Address,UCHAR *pBuffer, UINT32 Length){ + UINT32 Size, ByteLeft,IntCnt; + UCHAR *pData,*pTemp=pBuffer; + int iRet; + int TempVal; + + IntCnt =0; + TempVal = (Length % 4); + if (TempVal !=0) + { + Length = Length + (4- (Length%4)); + } + ByteLeft = Length; + while (ByteLeft > 0) + { + Size = (ByteLeft > MEM_BLK_DATA_MAX) ? MEM_BLK_DATA_MAX : ByteLeft; + // printf("\nMemBlkwrite : Size :%x Address :%x\n",Size, Address); + pData = (UCHAR *) malloc(Size + 6); + pData[0]= 0x00;//depot/esw/projects/azure/AR3001_3_0/src/hci/Hci_Vsc_Proc.c + pData[1]= (Address & 0xFF); + pData[2]= ((Address >> 8) & 0xFF); + pData[3]= ((Address >> 16) & 0xFF); + pData[4]= ((Address >> 24) & 0xFF); + pData[5]= Size; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_MEMOP,6,pData); + if(pData[6]!= 0){ + printf("\nwrite memory command failed due to reason 0x%X\n",pData[6]); + free(pData); + return FALSE; + } + if ((read(dd, pData,HCI_MAX_EVENT_SIZE)) < 0) { + perror("Read failed"); + exit(EXIT_FAILURE); + } + + if(pData[3]!=3) { + perror("Read failed"); + exit(EXIT_FAILURE); + } + memcpy(pTemp,(pData+4),Size); + pTemp+=Size; + IntCnt = Size; + ByteLeft -= Size; + Address += Size; + free(pData); + } + return TRUE; +} + + +static int MemBlkwrite(int dd,UINT32 Address,UCHAR *pBuffer, UINT32 Length){ + UINT32 Size, ByteLeft,IntCnt; + UCHAR *pData; + int iRet; + ByteLeft = Length; + IntCnt =0; + while (ByteLeft > 0) + { + + Size = (ByteLeft > MEM_BLK_DATA_MAX) ? MEM_BLK_DATA_MAX : ByteLeft; + // printf("\nMemBlkwrite : Size :%x Address :%x\n",Size, Address); + pData = (UCHAR *) malloc(Size + 6); + pData[0]= 0x01; + pData[1]= (Address & 0xFF); + pData[2]= ((Address >> 8) & 0xFF); + pData[3]= ((Address >> 16) & 0xFF); + pData[4]= ((Address >> 24) & 0xFF); + pData[5]= Size; + memcpy(&pData[6],&pBuffer[IntCnt],Size); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_MEMOP,Size+6,pData); + if(pData[6]!= 0){ + printf("\nwrite memory command faileddue to reason 0x%X\n",pData[6]); + free(pData); + return FALSE; + } + IntCnt = Size; + ByteLeft -= Size; + Address += Size; + free(pData); + } + return TRUE; +} + +static int Dut(int dd){ + int iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 3; //All scan enabled + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf); + if(buf[6] != 0){ + printf("\nWrite scan mode command failed due to reason 0x%X\n",buf[6]); + return FALSE; + } + sleep(1); + memset(&buf,0,HCI_MAX_EVENT_SIZE); + iRet = writeHciCommand(dd, OGF_TEST_CMD, OCF_ENABLE_DEVICE_UNDER_TEST_MODE, 0, buf); + if(buf[6] != 0){ + printf("\nDUT mode command failed due to reason 0x%X\n",buf[6]); + return FALSE; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 0; //SEQN Track enable =0 + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_TEST_MODE_SEQN_TRACKING , 1, buf); + if(buf[6] != 0){ + printf("\nTest Mode seqn Tracking failed due to reason 0x%X\n",buf[6]); + return FALSE; + } + return TRUE; +} + + +void Audio_DumpStats(tAudioStat *AudioStats) +{ + printf("\n\n"); + printf(" Audio Statistics\n"); + printf(">RxCmplt: %d\n",AudioStats->RxCmplt); + printf(">TxCmplt: %d\n",AudioStats->TxCmplt); + printf(">RxSilenceInsert: %d\n",AudioStats->RxSilenceInsert); + printf(">RxAirPktDump: %d\n",AudioStats->RxAirPktDump); + printf(">MaxPLCGenInterval: %d\n",AudioStats->MaxPLCGenInterval); + printf(">RxAirPktStatusGood: %d\n",AudioStats->RxAirPktStatusGood); + printf(">RxAirPktStatusError: %d\n",AudioStats->RxAirPktStatusError); + printf(">RxAirPktStatusLost: %d\n",AudioStats->RxAirPktStatusLost); + printf(">RxAirPktStatusPartial: %d\n",AudioStats->RxAirPktStatusPartial); + printf(">SampleMin: %d\n",AudioStats->SampleMin); + printf(">SampleMax: %d\n",AudioStats->SampleMax); + printf(">SampleCounter: %d\n",AudioStats->SampleCounter); + printf("\n\n"); + + memset((UCHAR *)AudioStats, 0, sizeof(tAudioStat)); + AudioStats->SampleMax =SHRT_MIN; + AudioStats->SampleMin =SHRT_MAX; +} + +static int ReadAudioStats(int dd){ + + tBtHostInterest HostInt; + tAudioStat Stats; + + ReadHostInterest(dd, &HostInt); + if(!HostInt.AudioStatAddr || (HostInt.Version < 0x0300)){ + printf("\nAudio Stat not present\n"); + return FALSE; + } + ReadMemoryBlock(dd,HostInt.AudioStatAddr,(UCHAR *)&Stats,sizeof(tAudioStat)); + Audio_DumpStats(&Stats); + return TRUE; +} + +void BRM_DumpStats(tBRM_Stats *Stats) +{ + printf("\n Link Controller Voice DMA Statistics\n"); + printf(" %22s: %u\n", "VoiceTxDmaIntrs", Stats->VoiceTxDmaIntrs); + printf(" %22s: %u\n", "VoiceTxPktAvail", Stats->VoiceTxPktAvail); + printf(" %22s: %u\n", "VoiceTxPktDumped", Stats->VoiceTxPktDumped); + printf(" %22s: %u\n", "VoiceTxErrors", Stats->VoiceTxErrorIntrs); + printf(" %22s: %u\n", "VoiceTxDmaErrors", Stats->VoiceTxDmaErrorIntrs); + printf(" %22s: %u\n", "VoiceTxSilenceInserts", Stats->VoiceTxDmaSilenceInserts); + printf("\n"); + printf(" %22s: %u\n", "VoiceRxDmaIntrs", Stats->VoiceRxDmaIntrs); + printf(" %22s: %u\n", "VoiceRxGoodPkts", Stats->VoiceRxGoodPkts); + printf(" %22s: %u\n", "VoiceRxPktDumped", Stats->VoiceRxPktDumped); + printf(" %22s: %u\n", "VoiceRxErrors", Stats->VoiceRxErrorIntrs); + printf(" %22s: %u\n", "VoiceRxCRC", Stats->VoiceRxErrCrc); + printf(" %22s: %u\n", "VoiceRxUnderOverFlow", Stats->VoiceRxErrUnderOverFlow); + printf("\n"); + printf(" %22s: %u\n", "SchedOnVoiceError", Stats->SchedOnVoiceError); + printf(" %22s: %u\n", "VoiceTxReapOnError", Stats->VoiceTxReapOnError); + printf(" %22s: %u\n", "VoiceRxReapOnError", Stats->VoiceRxReapOnError); + printf(" %22s: %u\n", "VoiceSchedulingError", Stats->VoiceSchedulingError); + + printf("\n Link Controller ACL DMA Statistics\n"); + printf(" %22s: %u\n", "DmaIntrs", Stats->DmaIntrs); + printf(" %22s: %u\n", "ErrWrongLlid", Stats->ErrWrongLlid); + printf(" %22s: %u\n", "ErrL2CapLen", Stats->ErrL2CapLen); + printf(" %22s: %u\n", "ErrUnderOverFlow", Stats->ErrUnderOverFlow); + printf(" %22s: %u\n", "RxBufferDumped", Stats->RxBufferDumped); + printf(" %22s: %u\n", "ErrWrongLmpPktType", Stats->ErrWrongLmpPktType); + printf(" %22s: %u\n", "ErrWrongL2CapPktType", Stats->ErrWrongL2CapPktType); + printf(" %22s: %u\n", "IgnoredPkts", Stats->IgnoredPkts); + printf("\n"); + printf(" %22s: %u\n", "Data TxBuffers", Stats->DataTxBuffers); + printf(" %22s: %u\n", "Data RxBuffers", Stats->DataRxBuffers); + printf(" %22s: %u\n", "LMP TxBuffers", Stats->LmpTxBuffers); + printf(" %22s: %u\n", "LMP RxBuffers", Stats->LmpRxBuffers); + printf(" %22s: %u\n", "HEC Errors", Stats->HecFailPkts); + printf(" %22s: %u\n", "CRC Errors", Stats->CrcFailPkts); + + // Buffer Management + printf("\n Buffer Management Statistics\n"); + printf(" %22s: %u\n", "CtrlErrNoLmpBufs", Stats->CtrlErrNoLmpBufs); + + printf("\n Sniff Statistics\n"); + printf(" %22s: %u\n", "SniffSchedulingError", Stats->SniffSchedulingError); + printf(" %22s: %u\n", "SniffIntervalNoCorr", Stats->SniffIntervalNoCorr); + + // Other stats + printf("\n Other Statistics\n"); + printf(" %22s: %u\n", "ForceOverQosJob", Stats->ForceOverQosJob); + //printf(" %22s: %u\n", "Temp 1", Stats->Temp1); + //printf(" %22s: %u\n", "Temp 2", Stats->Temp2); + + // Test Mode Stats + printf("\n Test Mode Statistics\n"); + printf(" %22s: %u\n", "TestModeDroppedTxPkts", Stats->TestModeDroppedTxPkts); + printf(" %22s: %u\n", "TestModeDroppedLmps", Stats->TestModeDroppedLmps); + + // Error Stats + printf("\n General Error Statistics\n"); + printf(" %22s: %u\n", "TimePassedIntrs", Stats->TimePassedIntrs); + printf(" %22s: %u\n", "NoCommandIntrs", Stats->NoCommandIntrs); +} + +static int ReadGlobalDMAStats(int dd){ + tBtHostInterest HostInt; + tBRM_Stats Stats; + + ReadHostInterest(dd, &HostInt); + if(!HostInt.GlobalDmaStats || (HostInt.Version < 0x0100)){ + printf("\nGlobal DMA stats not present\n"); + return FALSE; + } + ReadMemoryBlock(dd,HostInt.GlobalDmaStats,(UCHAR *)&Stats,sizeof(tBRM_Stats)); + BRM_DumpStats(&Stats); + return TRUE; +} + +static int ResetGlobalDMAStats(int dd){ + tBtHostInterest HostInt; + tBRM_Stats Stats; + + ReadHostInterest(dd, &HostInt); + if(!HostInt.GlobalDmaStats || (HostInt.Version < 0x0100)){ + printf("\nGlobal DMA stats not present\n"); + return FALSE; + } + memset(&Stats,0,sizeof(Stats)); + printf("\nHarry\n"); + WriteMemoryBlock(dd,HostInt.GlobalDmaStats,(UCHAR *)&Stats,sizeof(tBRM_Stats)); + printf("\nDMA stattestics has been reset\n"); + return TRUE; +} + +static int ReadTpcTable(int dd){ + tBtHostInterest HostInt; + tPsSysCfgTransmitPowerControlTable TpcTable; + int i; + + ReadHostInterest(dd, &HostInt); + if(!HostInt.TpcTableAddr || (HostInt.Version < 0x0100)){ + printf("\nTPC table not present\n"); + return FALSE; + } + ReadMemoryBlock(dd,HostInt.TpcTableAddr,(UCHAR *)&TpcTable,sizeof(TpcTable)); + for(i=0;i< TpcTable.NumOfEntries; i++){ + printf("Level [%d] represents %3d dBm\n",i,TpcTable.t[i].TxPowerLevel); + } + return TRUE; +} + +/* +static void dump_conf_data(){ + printf("\nTAG_COUNT %d\n",Tag_Count); + int i=0,j=0; + for(i=0;i<Tag_Count;i++){ + printf("\nTAG ID :%X LEN:%X\n",PsTagEntry[i].TagId,PsTagEntry[i].TagLen); + for(j=0;j<PsTagEntry[i].TagLen;j++) + printf("\t %x",PsTagEntry[i].TagData[j]); + } + printf("\n"); + printf("\nPATCH_COUNT %d\n",Patch_Count); + for(i=0;i<Patch_Count;i++){ + printf("\tPATCH LEN:%X\t",RamPatch[i].Len); + for(j=0;j<RamPatch[i].Len;j++) + printf("\t %x",RamPatch[i].Data[j]); + } + printf("\n"); + + printf("\tDYMA LEN:%X\t",RamDynMemOverride.Len); + for(j=0;j<RamDynMemOverride.Len;j++) + printf("\t %x",RamDynMemOverride.Data[j]); + printf("\n"); + +} +*/ +static const char *psreset_help = + "Usage:\n" + "\n psreset\n"; + +static void cmd_psreset(int dev_id, int argc, char **argv){ + int dd,Length =0,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if(argc > 1){ + printf("\n%s\n",psreset_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + PSInit(dd); + memset(&buf,0,sizeof(buf)); + iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_RESET,Length,buf); + if(buf[6] != 0){ + printf("\nError: HCI RESET failed due to reason 0x%X\n",buf[6]); + return; + } + + // Bttest work around for external 32k + + + int IsForeverRepeat=0; + int IsCmdIdle=0; + int address=0, width = 0, value=0; + int loop=0,Reg=0; + do + { + + address = 0x00020024; + width = 4; + buf[0] = (address & 0xFF); + buf[1] = ((address >>8) & 0xFF); + buf[2] = ((address>>16) & 0xFF); + buf[3] = ((address>>24) & 0xFF); + buf[4] = (UCHAR)width; //Memory width + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf); + if(buf[6] != 0){ + printf("\nRead Memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + value = buf[10]; + value = ((value << 8) | buf[9]); + value = ((value << 8) | buf[8]); + value = ((value << 8) | buf[7]); + + + if(value&0x40000000) + IsForeverRepeat=1; + else + IsForeverRepeat=0; + + + address = 0x00020020; + width = 4; + buf[0] = (address & 0xFF); + buf[1] = ((address >>8) & 0xFF); + buf[2] = ((address>>16) & 0xFF); + buf[3] = ((address>>24) & 0xFF); + buf[4] = (UCHAR)width; //Memory width + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf); + if(buf[6] != 0){ + printf("\nRead Memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + value = buf[10]; + value = ((value << 8) | buf[9]); + value = ((value << 8) | buf[8]); + value = ((value << 8) | buf[7]); + + if((value&0x0000000f)==0x8) + IsCmdIdle=1; + else + IsCmdIdle=0; + + } + while(!(IsForeverRepeat&IsCmdIdle));//Wait til brm issues forever idle + + + address = 0x000200a8; + width = 4; + buf[0] = (address & 0xFF); + buf[1] = ((address >>8) & 0xFF); + buf[2] = ((address>>16) & 0xFF); + buf[3] = ((address>>24) & 0xFF); + buf[4] = (UCHAR)width; //Memory width + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf); + if(buf[6] != 0){ + printf("\nRead Memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + value = buf[10]; + value = ((value << 8) | buf[9]); + value = ((value << 8) | buf[8]); + value = ((value << 8) | buf[7]); + + + value |= 0x1; + + loop = 0; + while ( loop < 10 ) { + + loop++; + + address = 0x000200a8; + width = 4; + + buf[0] = (address & 0xFF); + buf[1] = ((address >>8) & 0xFF); + buf[2] = ((address>>16) & 0xFF); + buf[3] = ((address>>24) & 0xFF); + buf[4] = width; //Memory width + buf[5] = (value & 0xFF); + buf[6] = ((value >> 8) & 0xFF); + buf[7] = ((value >> 16) & 0xFF); + buf[8] = ((value >> 24) & 0xFF); + buf[9] = 0xFF; + buf[10] = 0xFF; + buf[11] = 0xFF; + buf[12] = 0xFF; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed\n"); + hci_close_dev(dd); + return; + } + + address = 0x00004064; + width = 4; + buf[0] = (address & 0xFF); + buf[1] = ((address >>8) & 0xFF); + buf[2] = ((address>>16) & 0xFF); + buf[3] = ((address>>24) & 0xFF); + buf[4] = (UCHAR)width; //Memory width + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf); + if(buf[6] != 0){ + printf("\nRead Memory address failed\n"); + hci_close_dev(dd); + return; + } + Reg = buf[10]; + Reg = ((Reg << 8) | buf[9]); + Reg = ((Reg << 8) | buf[8]); + Reg = ((Reg << 8) | buf[7]); + + if(Reg & 0x04) { + break; + } + } + +//-------------------------------------------------------------- + + + hci_close_dev(dd); + printf("\nReset Done\n"); +} +static const char *reset_help = + "Usage:\n" + "\n reset\n"; + +static void cmd_reset(int dev_id, int argc, char **argv){ + int dd,Length =0,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if(argc > 1) { + printf("\n%s\n",reset_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,sizeof(buf)); + iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_RESET,Length,buf); + if(buf[6] != 0){ + printf("\nError: HCI RESET failed due to reason 0x%X\n",buf[6]); + return; + } + + hci_close_dev(dd); + printf("\nReset Done\n"); +} +static const char *rba_help = + "Usage:\n" + "\n rba\n"; + +static void cmd_rba(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if(argc > 1){ + printf("\n%s\n",rba_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + iRet = writeHciCommand(dd, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, buf); + if(buf[6] != 0){ + printf("\nread bdaddr command failed due to reason 0x%X\n",buf[6] ); + return; + } + printf("\nBD ADDRESS: \n"); + int i; + for(i=iRet-1;i > 7;i--){ + printf("%02X:",buf[i]); + } + printf("%X \n\n",buf[7]); + hci_close_dev(dd); + +} + +static const char *dtx_help = + "Usage:\n" + "\n dtx\n"; + +static void cmd_dtx(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if(argc > 1){ + printf("\n%s\n",dtx_help); + return; + } + + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_DISABLE_TX, 0, buf); + if(buf[6] != 0){ + printf("\nDisable TX command failed due to reason 0x%X\n",buf[6]); + return; + } + else { + printf("\nDisable TX command passed\n"); + } + hci_close_dev(dd); + +} + +static const char *ssm_help = + "Usage:\n" + "\n ssm [0|1]\n" + "\nExample:\n" + "\tssm 0\t(Sleep disabled)\n" + "\tssm 1\t(Sleep enabled)\n"; + +static void cmd_ssm(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if(argc != 2){ + printf("\n%s\n",ssm_help); + return; + } + + if(atoi(argv[1]) > 1){ + printf("\nInvalid sleep mode :%d\n",atoi(argv[1])); + return; + } + + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = atoi(argv[1]);; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_SLEEP_MODE, 1, buf); + if(buf[6] != 0){ + printf("\nSet sleep mode command failed due to reason 0x%X\n",buf[6]); + return; + } + else { + printf("\nSet sleep mode command passed\n"); + } + hci_close_dev(dd); + +} + +static const char *wba_help = + "Usage:\n" + "\n wba <bdaddr>\n" + "\nExample:\n" + "\n wba 00:03:ff:56:23:89\n"; + +static void cmd_wba(int dev_id, int argc, char **argv){ + //printf("\nFeature not implemented\n"); + int dd,iRet; + bdaddr_t bdaddr; + + UCHAR buf[HCI_MAX_EVENT_SIZE]; + if(argc < 2){ + printf("\n%s\n",wba_help); + return; + } + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + str2ba(argv[1],&bdaddr); + if((strlen(argv[1]) < 17)||(strlen(argv[1]) > 17)){ + printf("\nInvalid BD address : %s\n",argv[1]); + printf("\n%s\n",wba_help); + hci_close_dev(dd); + return; + } + LoadPSHeader(buf,PS_WRITE,BD_ADDR_SIZE,BD_ADDR_PSTAG); + int i,j=0; + for(i= 0,j=4;i< BD_ADDR_SIZE;i++,j++){ + buf[j] = bdaddr.b[i]; + } + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,BD_ADDR_SIZE + PS_COMMAND_HEADER, buf); + if(buf[6] != 0){ + printf("\n Write BD address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + memset(&buf,0,sizeof(buf)); + iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_RESET,0,buf); + if(buf[iRet-1] != 0){ + printf("\nError: HCI RESET failed\n"); + hci_close_dev(dd); + return; + } + memset(&buf,0,sizeof(buf)); + iRet = writeHciCommand(dd, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, buf); + if(buf[6] != 0){ + printf("\nread bdaddr command failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + printf("\nBD address changed successfully\n"); + hci_close_dev(dd); +} + +static const char *edutm_help = + "Usage:\n" + "\n edutm\n"; + +static void cmd_edutm(int dev_id, int argc, char **argv){ + int Crc = 0; + int dd; + //UCHAR buf[HCI_MAX_EVENT_SIZE]; + UCHAR ZeroBuf[MEM_BLK_DATA_MAX*2] = {0}; + if(argc > 1){ + printf("\n%s\n",edutm_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } +/* + Patch_Count = 20; + for(i=0; i < Patch_Count; i++){ + RamPatch[i].Len = MAX_BYTE_LENGTH; + memset(&RamPatch[i].Data,0,MAX_BYTE_LENGTH); + } + printf("\nCMD DUT MODE\n"); +*/ +//When Patch file is present write the patch, if not present just enter DUT mode + if(!LoadConfFile(TESTPATCH_FILENAME,0xFFFFFFFF,MB_FILEFORMAT_PATCH)){ + if(!Dut(dd)){ + hci_close_dev(dd); + return; + } + printf("\nDevice is in test mode ...\n"); + hci_close_dev(dd); + return; + } + //dump_conf_data(); + Crc |= RAM_PATCH_REGION; + if(!MemBlkwrite(dd,(UINT32)MC_BCAM_COMPARE_ADDRESS, ZeroBuf, HCI_3_PATCH_SPACE_LENGTH_1)){ + printf("\nError in clearing the patch space 1\n"); + return; + } + + if(!MemBlkwrite(dd,(UINT32)MC_BCAM_VALID_ADDRESS, ZeroBuf, HCI_3_PATCH_SPACE_LENGTH_1)){ + printf("\nError in clearing the patch space 2\n"); + return; + } + printf("\nLoading Patch from file :%s\n",TESTPATCH_FILENAME); + if(!PSOperations(dd,WRITE_PATCH,Patch_Count, NULL)){ + printf("EnterDUT_HCI_3 : patch write failed \r\n"); + return; + } + if(!PSOperations(dd,ENABLE_PATCH,0, NULL)){ + printf("EnterDUT_HCI_3 : patch enable failed \r\n"); + return; + } + if(!PSOperations(dd,PS_VERIFY_CRC,Crc, NULL)){ + printf("EnterDUT_HCI_3 : verify crc failed \r\n"); + return; + } + if(!Dut(dd)){ + hci_close_dev(dd); + return; + } + printf("\nDevice is in test mode ...\n"); + hci_close_dev(dd); +} + + +static int ReadMemorySmallBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ){ + int iRet; + UCHAR *pData; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + pData = (UCHAR *) malloc(Length + 6); + memset(pData,0,Length+6); + pData[0]= 0x00; //Memory Read Opcode + pData[1]= (StartAddress & 0xFF); + pData[2]= ((StartAddress >> 8) & 0xFF); + pData[3]= ((StartAddress >> 16) & 0xFF); + pData[4]= ((StartAddress >> 24) & 0xFF); + pData[5]= Length; + + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_MEMOP,Length+6,pData); + if(pData[6]!= 0){ + printf("\nwrite memory command failed due to reason 0x%X\n",pData[6]); + free(pData); + return FALSE; + } + int plen =0; + do{ + plen = read(dd, buf,HCI_MAX_EVENT_SIZE); + if (plen < 0) { + free(pData); + perror("Read failed"); + exit(EXIT_FAILURE); + } + }while (buf[HCI_EVENT_HEADER_SIZE] != DEBUG_EVENT_TYPE_MEMBLK); + memcpy(pBufToWrite,(buf+HCI_EVENT_HEADER_SIZE+1),Length); + free(pData); + return TRUE; +} + +static int ReadMemoryBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ){ + + int ModResult,i; + + if(Length > MEM_BLK_DATA_MAX){ + ModResult = Length % MEM_BLK_DATA_MAX; + for(i=0;i < (Length - ModResult);i += MEM_BLK_DATA_MAX) { + ReadMemorySmallBlock(dd, (StartAddress + i),(pBufToWrite + i), MEM_BLK_DATA_MAX); + } + if(ModResult){ + ReadMemorySmallBlock(dd, (StartAddress + i),(pBufToWrite + i), ModResult); + } + } + else{ + + ReadMemorySmallBlock(dd, StartAddress, pBufToWrite, Length); + } + return TRUE; +} + +static int WriteMemorySmallBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ){ + int iRet; + UCHAR *pData; + + printf("\nStart Address:%x Length:%x %x\n",StartAddress,Length,MEM_BLK_DATA_MAX); + /*if(Length <= MEM_BLK_DATA_MAX) + return FALSE; */ + pData = (UCHAR *) malloc(Length + 6); + memset(pData,0,Length+6); + pData[0]= 0x01; //Write Read Opcode + pData[1]= (StartAddress & 0xFF); + pData[2]= ((StartAddress >> 8) & 0xFF); + pData[3]= ((StartAddress >> 16) & 0xFF); + pData[4]= ((StartAddress >> 24) & 0xFF); + pData[5]= Length; + + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_MEMOP,Length+6,pData); + if(pData[6]!= 0){ + printf("\nwrite memory command failed due to reason 0x%X\n",pData[6]); + free(pData); + return FALSE; + } + free(pData); + return TRUE; +} + + +static int WriteMemoryBlock(int dd, int StartAddress,UCHAR *pBufToWrite, int Length ){ + + int ModResult,i; + + if(Length > MEM_BLK_DATA_MAX){ + ModResult = Length % MEM_BLK_DATA_MAX; + for(i=0;i < (Length - ModResult);i += MEM_BLK_DATA_MAX) { + WriteMemorySmallBlock(dd, (StartAddress + i),(pBufToWrite + i), MEM_BLK_DATA_MAX); + } + if(ModResult){ + WriteMemorySmallBlock(dd, (StartAddress + i),(pBufToWrite + i), ModResult); + } + } + else{ + + WriteMemorySmallBlock(dd, StartAddress, pBufToWrite, Length); + } + return TRUE; +} + + +static int ReadHostInterest(int dd,tBtHostInterest *pHostInt){ + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int iRet; + int HostInterestAddress; + memset(&buf,0,HCI_MAX_EVENT_SIZE); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_HOST_INTEREST, 0, buf); + if(buf[6] != 0){ + printf("\nhost interest command failed due to reason 0x%X\n",buf[6]); + return FALSE; + } + HostInterestAddress = buf[iRet-1]; + HostInterestAddress = ((HostInterestAddress << 8)|buf[iRet-2]); + HostInterestAddress = ((HostInterestAddress << 8)|buf[iRet-3]); + HostInterestAddress = ((HostInterestAddress << 8)|buf[iRet-4]); + ReadMemoryBlock(dd, HostInterestAddress,(UCHAR*)pHostInt, sizeof(tBtHostInterest)); + + if(pHostInt->MagicNumber != HI_MAGIC_NUMBER){ + if((pHostInt->MagicNumber != 0xFBAD)|| (pHostInt->Version != 0xDECA)) + return 0; + } + return TRUE; + +} + +static int contRxAtGivenChannel(int dd, UCHAR *pString){ + int Address, Mask, Reg, RxFreq,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + //1. Disable all scans and set intervals and scan windows eually + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 0; //All scan disabled + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf); + if(buf[6] != 0){ + printf("\nWrite scan mode command failed due to reason 0x%X\n",buf[6]); + return 0; + } + short int inq_scan = 0x1000; + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = (inq_scan&0xFF); + buf[1] = ((inq_scan >> 8)& 0xFF); + buf[2] = (inq_scan&0xFF); + buf[3] = ((inq_scan >> 8)& 0xFF); + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_INQ_ACTIVITY, 4, buf); + if(buf[6] != 0){ + printf("\nWrite inquiry scan activity command failed due to reason 0x%X\n",buf[6]); + return 0; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = (inq_scan&0xFF); + buf[1] = ((inq_scan >> 8)& 0xFF); + buf[2] = (inq_scan&0xFF); + buf[3] = ((inq_scan >> 8)& 0xFF); + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_PAGE_ACTIVITY, 4, buf); + if(buf[6] != 0){ + printf("\nWrite page scan activity command failed due to reason 0x%X\n",buf[6]); + return 0; + } + //2. Disbable AGC + Address = LC_JTAG_MODEM_REGS_ADDRESS + AGC_BYPASS_ADDRESS; + Mask = AGC_BYPASS_ENABLE_MASK; + Reg = AGC_BYPASS_ENABLE_SET(1); + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = (Address & 0xFF); + buf[1] = ((Address >>8) & 0xFF); + buf[2] = ((Address>>16) & 0xFF); + buf[3] = ((Address>>24) & 0xFF); + buf[4] = 0x04; //Memory width + buf[5] = (Reg & 0xFF); + buf[6] = ((Reg >> 8) & 0xFF); + buf[7] = ((Reg >> 16) & 0xFF); + buf[8] = ((Reg >> 24) & 0xFF); + buf[9] = (Mask & 0xFF); + buf[10] = ((Mask >>8) & 0xFF); + buf[11] = ((Mask>>16) & 0xFF); + buf[12] = ((Mask>>24) & 0xFF); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite to AGC bypass register failed due to reason 0x%X\n",buf[6]); + return 0; + } + // 3. Disable frequency hoping and set rx frequency + + RxFreq = (int)pString; + Address = LC_DEV_PARAM_CTL_ADDRESS; + Mask = LC_DEV_PARAM_CTL_FREQ_HOP_EN_MASK | + LC_DEV_PARAM_CTL_RX_FREQ_MASK | + LC_DEV_PARAM_CTL_WHITEN_EN_MASK; + Reg = LC_DEV_PARAM_CTL_RX_FREQ_SET(RxFreq); + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = (Address & 0xFF); + buf[1] = ((Address >>8) & 0xFF); + buf[2] = ((Address>>16) & 0xFF); + buf[3] = ((Address>>24) & 0xFF); + buf[4] = 0x04; //Memory width + buf[5] = (Reg & 0xFF); + buf[6] = ((Reg >> 8) & 0xFF); + buf[7] = ((Reg >> 16) & 0xFF); + buf[8] = ((Reg >> 24) & 0xFF); + buf[9] = (Mask & 0xFF); + buf[10] = ((Mask >>8) & 0xFF); + buf[11] = ((Mask>>16) & 0xFF); + buf[12] = ((Mask>>24) & 0xFF); + + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite to Rx Freq register failed due to reason 0x%X\n",buf[6]); + return 0; + } + // 4. Enable page scan only (Note: the old way puts device into inq scan mode only ???) + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 2; //Page scan enabled + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf); + if(buf[6] != 0){ + printf("\nPage scan enable command failed due to reason 0x%X\n",buf[6]); + return 0; + } + // 5. Increase correlator + Address = LC_JTAG_MODEM_REGS_ADDRESS + CORR_PARAM1_ADDRESS; + Mask = CORR_PARAM1_TIM_THR_MASK; + Reg = CORR_PARAM1_TIM_THR_SET(0x3f); + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = (Address & 0xFF); + buf[1] = ((Address >>8) & 0xFF); + buf[2] = ((Address>>16) & 0xFF); + buf[3] = ((Address>>24) & 0xFF); + buf[4] = 0x04; //Memory width + buf[5] = (Reg & 0xFF); + buf[6] = ((Reg >> 8) & 0xFF); + buf[7] = ((Reg >> 16) & 0xFF); + buf[8] = ((Reg >> 24) & 0xFF); + buf[9] = (Mask & 0xFF); + buf[10] = ((Mask >>8) & 0xFF); + buf[11] = ((Mask>>16) & 0xFF); + buf[12] = ((Mask>>24) & 0xFF); + + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 12, buf); + if(buf[6] != 0){ + printf("\nWrite to Correlator register failed due to reason 0x%X\n",buf[6]); + return 0; + } + + return TRUE; +} +static const char *cwrx_help = + "Usage:\n" + "\n cwrx <Channel>\n"; + +static void cmd_cwrx(int dev_id, int argc, char **argv){ + + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + UCHAR channel; + BOOL Ok = TRUE; + if(argc != 2){ + printf("\n%s\n",cwrx_help); + return; + } + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + channel = atoi(argv[1]); + if(channel > 78 || channel < 0){ + printf("\nPlease enter channel 0-78!\n"); + return; + } + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + // Disable sleep mode + memset(&buf,0,sizeof(buf)); + buf[0] = 0; + iRet = writeHciCommand(dd,OGF_VENDOR_CMD,OCF_SLEEP_MODE,1,buf); + if(buf[6] != 0){ + printf("\nError: Sleep mode failed due to reason 0x%X\n",buf[6]); + Ok = 0; + } + printf (" Continuoux Rx at channel %d\n",channel); + Ok = contRxAtGivenChannel(dd, &channel); + + // All modes come here + if (Ok) + { + printf (" Continuoux Rx at channel %d Done...\n",channel); + } + else + { + printf ("\nERROR ---> Could not enter continuous Rx mode\n"); + } + + hci_close_dev(dd); +} +static const char *mb_help = + "Usage:\n" + "\n mb\n"; + +static void cmd_mb(int dev_id, int argc, char **argv){ + + int newfd, FieldNum,dd,iRet,need_raw, iDataSize, address,width,value,mask, fdmax, k, l; + bdaddr_t bdaddr; + tBRM_Control_packet MasterBlaster; + UCHAR SkipRxSlot; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + char FieldAlias; + BOOL TestEnabled = 0,Ok = TRUE; + UINT8 setContTxType; + tBtHostInterest HostInt; + fd_set master, read_fds; + uint32_t m_BerTotalBits, m_BerGoodBits; + uint8_t m_pattern[16]; + uint16_t m_pPatternlength; + struct hci_filter flt; + struct hci_dev_info di; + struct timeval timeout; + + if(argc > 1) { + printf("\n%s\n",mb_help); + return; + } + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + iRet = writeHciCommand(dd, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, buf); + if (buf[6] != 0) { + printf("\nread bdaddr command failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + int i,j; + char bda[18]; + for (i=iRet-1,j=0;i>7;i--,j+=3) { + sprintf(&bda[j],"%X",((buf[i]>>4)&0xFF)); + sprintf(&bda[j+1],"%X",(buf[i]&0x0F)); + sprintf(&bda[j+2],":"); + } + sprintf(&bda[15],"%X",((buf[7]>>4)&0xFF)); + sprintf(&bda[16],"%X",(buf[7]&0x0F)); + bda[18] ='\0'; + str2ba(bda,&bdaddr); + + InitMasterBlaster(&MasterBlaster, &bdaddr, &SkipRxSlot); +#ifndef DUMP_DEBUG + Ok = ReadHostInterest(dd,&HostInt); + if(Ok) { + if (HostInt.TpcTableAddr && (HostInt.Version >= 0x0100)) { + Ok = ReadMemoryBlock(dd, HostInt.TpcTableAddr, (UCHAR *)&TpcTable, sizeof(TpcTable)); + MasterBlaster.testCtrl.Power = TpcTable.NumOfEntries - 1; + } + } + if(!Ok) { + printf ("\nCould not load TPC table.\n"); + sleep (2); + Ok = TRUE; + } +#endif + + PrintMasterBlasterMenu (&MasterBlaster); + m_BerGoodBits = 0; + m_BerTotalBits = 0; + m_pattern[0] = 0x0f; + m_pPatternlength = 1; + + FD_ZERO(&master); + FD_ZERO(&read_fds); + FD_SET(0, &master); + fdmax = 0; + newfd = -1; + + while (1) { + read_fds = master; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + iRet = select(fdmax+1, &read_fds, NULL, NULL, &timeout); + if (iRet == -1) { + perror("cmd_mb select() error!"); + goto exits_mb; + } + if (iRet == 0) continue; + + for(i = 0; i <= fdmax; i++) { + if(FD_ISSET(i, &read_fds)) { + if (i==0) { // input + scanf("%s",buf); + FieldAlias = (char)buf[0]; + FieldNum = CheckField(MasterBlaster, &FieldAlias); + if (FieldNum == INVALID_MASTERBLASTER_FIELD) { + printf ("\nERROR ---> Invalid command. Try again.\n"); + printf ("mb>"); + continue; + } + + if (!strncmp(&FieldAlias, MasterBlasterMenu[EXX].Alias, 1)) { + printf("\nExit the Master Blaster Mode without reset\n"); + goto exits_mb; + } + + // if the test is in rx and the key is neither 'd' nor 'g', then stop the test, renew the option, and procced + // if the test is in tx and the key is not 'e', then stop the test, renew the option, and procced + // if the test is in (LE) continuous rx/tx and the key is not 'j' , then stop the test, renew the option, and procced + if (((TestEnabled == MB_RX_TEST) && strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1) && strncmp(&FieldAlias, MasterBlasterMenu[GB].Alias, 1)) + || ((TestEnabled == MB_TX_TEST) && strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1)) + || ((TestEnabled == MB_CONT_RX_TEST || TestEnabled == MB_CONT_TX_TEST + || TestEnabled == MB_LE_RX_TEST || TestEnabled == MB_LE_TX_TEST) && + (strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1)))) { + printf (" ... Please wait ..."); + if (MasterBlaster.ContTxMode) { + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 255; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_CONT_TX_TESTER, 14, buf); + if(buf[6] != 0) { + printf("\nContinious Tx Tester command failed due to reason 0x%X\n",buf[6]); + Ok = 0; + } else + Ok = TRUE; + } + if (TestEnabled == MB_RX_TEST) { + if (need_raw) { + if (ioctl(dd, HCISETRAW, 0) < 0) + perror("Can't clear raw mode \n"); + } + FD_CLR(newfd, &master); + newfd = -1; + fdmax = 0; + } + // Ok = Diag::Reset (Unit, ""); + //PSInit(dd); + // The default setting is sleep mode enabled. + memset(&buf,0,sizeof(buf)); + buf[0] = 1; + iRet = writeHciCommand(dd,OGF_VENDOR_CMD,OCF_SLEEP_MODE,1,buf); + if(buf[6] != 0) { + printf("\nError: Sleep mode failed due to reason 0x%X\n",buf[6]); + } + + memset(&buf,0,sizeof(buf)); + iRet = writeHciCommand(dd,OGF_HOST_CTL,OCF_RESET,0,buf); + if (buf[6] != 0) { + printf("\nError: HCI RESET failed due to reason 0x%X\n",buf[6]); + Ok = FALSE; + } else + Ok = TRUE; + if (!Ok) { + printf ("\nERROR ---> Could not stop test mode\n"); + } else if (!strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1) + || !strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1) + || ((TestEnabled != MB_NO_TEST) && + (!strncmp(&FieldAlias, MasterBlasterMenu[CR].Alias, 1) || + !strncmp(&FieldAlias, MasterBlasterMenu[CT].Alias, 1) || + !strncmp(&FieldAlias, MasterBlasterMenu[LR].Alias, 1) || + !strncmp(&FieldAlias, MasterBlasterMenu[LT].Alias, 1))) || + !strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1)) { + TestEnabled = MB_NO_TEST; + } + sleep(1); + } + if (!strncmp(&FieldAlias,MasterBlasterMenu[EX].Alias,1)) { // Exit + TestEnabled = MB_NO_TEST; + printf ("\n Exit ..\n"); + goto exits_mb; + } else if (!strncmp(&FieldAlias,MasterBlasterMenu[ST].Alias,1)) { // Stop Test + TestEnabled = MB_NO_TEST; + PrintMasterBlasterMenu (&MasterBlaster); + continue; + } else if (!strncmp(&FieldAlias,MasterBlasterMenu[GB].Alias,1)) { // get BER + printf("\n\tGoodBits %d, total is %d\n", m_BerGoodBits, m_BerTotalBits); + printf("mb>\n"); + continue; + } else if (!strncmp(&FieldAlias,MasterBlasterMenu[PO].Alias,1)) { // set Power + MasterBlasterMenu[FieldNum].pFunc (&MasterBlaster, &FieldAlias); + } else if (!MasterBlasterMenu[FieldNum].pFunc (&MasterBlaster, MasterBlasterMenu[FieldNum].Options)) { + printf ("\nERROR ---> Invalid option. Try again.\n"); + printf ("mb>"); + continue; + } + PrintMasterBlasterMenu(&MasterBlaster); + + // Enable RX test mode + if ((!strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1) && (TestEnabled == MB_NO_TEST)) + || (strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1) && (TestEnabled == MB_RX_TEST))) { + Ok = Dut(dd); + if (!Ok) { + printf("\nERROR ---> Could not enter DUT mode\n"); + printf("mb>"); + continue; + } + + printf("."); + if (hci_devinfo(dev_id, &di) < 0) { + printf("Can't get device info\n"); + printf("mb>"); + continue; + } + + need_raw = !hci_test_bit(HCI_RAW, &di.flags); + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = eBRM_TestMode_Rx; + buf[1] = MasterBlaster.testCtrl.Packet; + buf[2] = MasterBlaster.testCtrl.DataLen & 0xFF; + buf[3] = ((MasterBlaster.testCtrl.DataLen>>8) & 0xFF); + buf[4] = MasterBlaster.testCtrl.HopMode; + buf[5] = MasterBlaster.testCtrl.TxFreq; + buf[6] = MasterBlaster.testCtrl.Power; + buf[7] = MasterBlaster.testCtrl.RxFreq; + buf[8] = MasterBlaster.bdaddr[0]; + buf[9] = MasterBlaster.bdaddr[1]; + buf[10] = MasterBlaster.bdaddr[2]; + buf[11] = MasterBlaster.bdaddr[3]; + buf[12] = MasterBlaster.bdaddr[4]; + buf[13] = MasterBlaster.bdaddr[5]; + buf[14] = SkipRxSlot; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_RX_TESTER, 15, buf); + if (buf[6] != 0) { + printf("\nRx Tester command failed due to reason 0x%X\n",buf[6]); + printf("\nERROR --> Could not enable master blaster mode\n"); + TestEnabled = MB_NO_TEST; + Ok = 0; + } else { + printf(" rx test is in progress. Press 's' to stop the test\n"); + TestEnabled = MB_RX_TEST; + hci_filter_clear(&flt); + hci_filter_all_ptypes(&flt); + hci_filter_all_events(&flt); + + if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { + printf("Can't set filter for hci\n"); + printf("mb>"); + continue; + } + + if (need_raw) { + if (ioctl(dd, HCISETRAW, 1) < 0) { + printf("Can't set raw mode on hci\n"); + printf("mb>"); + continue; + } + } + newfd = dd; + FD_SET(newfd, &master); + fdmax = dd; + } + printf("mb>"); + continue; + } else if ((!strncmp(&FieldAlias, MasterBlasterMenu[RX].Alias, 1)) && (TestEnabled == MB_RX_TEST)) { + printf(" rx test is in progress. Press 's' to stop the test\n"); + printf("mb>"); + continue; + } + + // Enable TX test mode + if ((!strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1) && (TestEnabled == MB_NO_TEST)) + || (strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1) && (TestEnabled == MB_TX_TEST))) { + // Disable sleep mode + printf ("."); + Ok = TRUE; + memset(&buf,0,sizeof(buf)); + buf[0] = 0; + iRet = writeHciCommand(dd,OGF_VENDOR_CMD,OCF_SLEEP_MODE,1,buf); + if(buf[6] != 0) { + printf("\nError: Sleep mode failed due to reason 0x%X\n",buf[6]); + Ok = 0; + } + + if (!Ok) { + printf ("\nERROR ---> Could not disable sleep mode\n"); + printf ("mb>"); + continue; + } + + printf ("."); + Ok = Dut(dd); + if (!Ok) { + printf("\nERROR ---> Could not enter DUT mode\n"); + printf("mb>"); + continue; + } + + printf("."); + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = MasterBlaster.testCtrl.Mode ; + buf[1] = MasterBlaster.testCtrl.Packet; + buf[2] = MasterBlaster.testCtrl.DataLen & 0xFF; + buf[3] = ((MasterBlaster.testCtrl.DataLen>>8) & 0xFF); + buf[4] = MasterBlaster.testCtrl.HopMode; + buf[5] = MasterBlaster.testCtrl.TxFreq; + buf[6] = MasterBlaster.testCtrl.Power; + buf[7] = MasterBlaster.testCtrl.RxFreq; + buf[8] = MasterBlaster.bdaddr[0]; + buf[9] = MasterBlaster.bdaddr[1]; + buf[10] = MasterBlaster.bdaddr[2]; + buf[11] = MasterBlaster.bdaddr[3]; + buf[12] = MasterBlaster.bdaddr[4]; + buf[13] = MasterBlaster.bdaddr[5]; + buf[14] = SkipRxSlot; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_TX_TESTER, 15, buf); + if (buf[6] != 0) { + printf("\nTx Tester command failed due to reason 0x%X\n",buf[6]); + printf("\nERROR --> Could not enable master blaster mode\n"); + TestEnabled = MB_NO_TEST; + Ok = 0; + } else { + printf(" tx test is in progress. Press 's' to stop the test\n"); + TestEnabled = MB_TX_TEST; + } + printf("mb>"); + continue; + } else if ((!strncmp(&FieldAlias, MasterBlasterMenu[TX].Alias, 1)) && TestEnabled == MB_TX_TEST) { + printf(" tx test is in progress. Press 's' to stop the test\n"); + printf("mb>"); + continue; + } + + /* Enable (LE) continuous tx/rx test modes */ + if (((!strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1)) && (TestEnabled == MB_NO_TEST)) + || (strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1) && (TestEnabled == MB_CONT_RX_TEST + || TestEnabled == MB_CONT_TX_TEST || TestEnabled == MB_LE_RX_TEST || TestEnabled == MB_LE_TX_TEST))) { + // Disable sleep mode + printf ("."); + Ok = TRUE; + memset(&buf,0,sizeof(buf)); + buf[0] = 0; + iRet = writeHciCommand(dd,OGF_VENDOR_CMD,OCF_SLEEP_MODE,1,buf); + if (buf[6] != 0) { + printf("\nError: Sleep mode failed due to reason 0x%X\n",buf[6]); + Ok = 0; + } + + if (!Ok) { + printf ("\nERROR ---> Could not disable sleep mode\n"); + printf ("mb>"); + continue; + } + + /* LE Rx Mode */ + if (MasterBlaster.LERxMode == ENABLE) { + Ok = SU_LERxTest(dd, MasterBlaster.testCtrl.RxFreq); + TestEnabled = MB_LE_RX_TEST; + } else if (MasterBlaster.LETxMode == ENABLE) { + Ok = SU_LETxTest(dd, MasterBlaster.testCtrl.TxFreq, MasterBlaster.testCtrl.DataLen, + MasterBlaster.LETxParms.PktPayload); + TestEnabled = MB_LE_TX_TEST; + } else if (MasterBlaster.ContRxMode == ENABLE) { + UCHAR RxFreq = MasterBlaster.testCtrl.RxFreq; + Ok = contRxAtGivenChannel(dd, &RxFreq); + TestEnabled = MB_CONT_RX_TEST; + } else /* Continous TX mode */ { + printf("."); + Ok = Dut(dd); + if (!Ok) { + printf("\nERROR ---> Could not enter DUT mode\n"); + printf("mb>"); + continue; + } + /* Enable master blaster mode */ + printf("."); + if (CW_Single_Tone == MasterBlaster.ContTxType) + setContTxType = Cont_Tx_Raw_1MHz; + else + setContTxType = MasterBlaster.ContTxType; + + memset(&buf, 0, HCI_MAX_EVENT_SIZE); + buf[0] = MasterBlaster.testCtrl.Mode ; + buf[1] = MasterBlaster.testCtrl.Packet; + buf[2] = MasterBlaster.testCtrl.DataLen & 0xFF; + buf[3] = ((MasterBlaster.testCtrl.DataLen>>8) & 0xFF); + buf[4] = MasterBlaster.ContTxType; + buf[5] = MasterBlaster.testCtrl.TxFreq; + buf[6] = MasterBlaster.testCtrl.Power; + buf[7] = MasterBlaster.testCtrl.RxFreq; + buf[8] = MasterBlaster.bdaddr[0]; + buf[9] = MasterBlaster.bdaddr[1]; + buf[10] = MasterBlaster.bdaddr[2]; + buf[11] = MasterBlaster.bdaddr[3]; + buf[12] = MasterBlaster.bdaddr[4]; + buf[13] = MasterBlaster.bdaddr[5]; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_CONT_TX_TESTER, 14, buf); + if(buf[6] != 0){ + printf("\nContinious Tx Tester command failed due to reason 0x%X\n",buf[6]); + Ok = FALSE; + } else + Ok = TRUE; + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + address = 0x00022914; + value = 0x00200000; + mask = 0x00200000; + width = 4; + buf[0] = (address & 0xFF); + buf[1] = ((address >>8) & 0xFF); + buf[2] = ((address>>16) & 0xFF); + buf[3] = ((address>>24) & 0xFF); + buf[4] = width; //Memory width + buf[5] = (value & 0xFF); + buf[6] = ((value >> 8) & 0xFF); + buf[7] = ((value >> 16) & 0xFF); + buf[8] = ((value >> 24) & 0xFF); + buf[9] = (mask & 0xFF); + buf[10] = ((mask >>8) & 0xFF); + buf[11] = ((mask>>16) & 0xFF); + buf[12] = ((mask>>24) & 0xFF); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]); + Ok = FALSE; + } else + Ok = TRUE; + + TestEnabled = MB_CONT_TX_TEST; + } + if (Ok) { + printf("Test is in progress. Press 's' to stop the test\n"); + } else { + printf("\nERROR ---> Could not enable master blaster mode\n"); + TestEnabled = MB_NO_TEST; + } + printf("mb>"); + continue; + } else if ((!strncmp(&FieldAlias, MasterBlasterMenu[EN].Alias, 1)) && TestEnabled) { + printf (" Test mode is in progress. Press 's' to stop the test\n"); + printf ("mb>"); + continue; + } + } + else if (i == newfd) { + iRet = read(i, buf, sizeof(buf)); + iDataSize = iRet - 5; +// printf("first:%x,nbyte:%d, packet:%d, pattern:%x\n",buf[0], iRet, (uint16_t)(buf[3] | (buf[4] << 8)), buf[5]); + if (buf[0] == 0x2) { // ACL data + m_BerTotalBits = m_BerTotalBits + iDataSize * 8; + for(j=0,l=0;j<iDataSize;j++,l++) { + if (l == m_pPatternlength) l = 0; + for(k=0;k<8;k++){ + if((m_pattern[l]&(1<<k)) == (buf[8+j]&(1<<k))) + m_BerGoodBits++; + } + } + } + } + } + } + } +exits_mb: + if (need_raw) { + if (ioctl(dd, HCISETRAW, 0) < 0) + perror("Can't clear raw mode \n"); + } + hci_close_dev(dd); +} +/* +static void cmd_gid(int dev_id, int argc, char **argv){ + printf("\nFeature not implemented\n"); +} +*/ +static const char *wsm_help = + "Usage:\n" + "\n wsm [0|1|2|3]\n" + "\nExample:\n" + "\twsm 0\t(Scan disabled)\n" + "\twsm 1\t(Inquiry scan enabled)\n" + "\twsm 2\t(Page scan enabled)\n" + "\twsm 3\t(Inquiry and Page scan enabled)\n"; + +static void cmd_wsm(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + if(argc < 2){ + printf("\n%s\n",wsm_help); + return; + } + if(atoi(argv[1]) > 3){ + printf("\nInvalid scan mode :%d\n",atoi(argv[1])); + return; + } + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = atoi(argv[1]); + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf); + if(buf[6] != 0){ + printf("\nWrite scan mode command failed due to reason 0x%X\n",buf[6]); + return; + } + hci_close_dev(dd); + printf("\nScan Mode set to :%d\n",atoi(argv[1])); +} + +static void dumpHex(UCHAR *buf, int length, int col) +{ + int i; + for (i = 0; i < length; i++) { + printf("0x%02x ", buf[i]); + if (((i+1) % col) == 0 && i != 0) + printf("\n"); + } + if (((i+1) % col) != 0) printf("\n"); +} + +static void ReverseHexString(char *pStr) +{ + int i, j; + char temp; + int len = strlen(pStr); + + for (i = 0; pStr[i] == ' ' || pStr[i] == '\t'; i++); + + if (pStr[i] == '0' && pStr[i+1] == 'x') + i += 2; + + for (j = len - 1; i < j - 2; i += 2, j -= 2) { + temp = pStr[i]; + pStr[i] = pStr[j - 1]; + pStr[j - 1] = temp; + temp = pStr[i + 1]; + pStr[i + 1] = pStr[j]; + pStr[j] = temp; + } +} + +static void GetByteSeq(UCHAR *pDst, UCHAR *pSrc, int Size) +{ + UCHAR LowNibble, Nibble = 0; + UCHAR *pLastHex; + UCHAR *pStr = pSrc; + + while (*pStr == ' ' || *pStr == '\t') pStr++; + + if ((pStr[0] == '0') && (pStr[1] == 'x')) + pStr += 2; + + pLastHex = pStr - 1; + while (IS_HEX(*(pLastHex + 1))) + pLastHex++; + + LowNibble = 0; + + while (Size > 0) { + if (pStr <= pLastHex) { + Nibble = CONV_HEX_DIGIT_TO_VALUE(*pStr); + pStr++; + } else { + Nibble = 0; + } + + if (LowNibble) { + *pDst |= (UCHAR)(Nibble & 0x0F); + LowNibble = 0; + pDst++; + Size--; + } else { + *pDst = (UCHAR)((Nibble << 4) & 0xF0); + LowNibble = 1; + } + } +} + +unsigned int GetUInt(char **ppLine, unsigned int DefaultValue) +{ + char *pStr = *ppLine; + unsigned int Value = 0; + + // Is it a hex value? + if ((*pStr == '0') && (*(pStr+1) == 'x')) + { + // We have a hex value + + pStr += 2; + + while (IS_HEX(*pStr)) + { + Value = CONV_HEX_DIGIT_TO_VALUE(*pStr) + (Value*16); + pStr++; + } + + } + else if (IS_DIGIT(*pStr)) + { + // We have a decimal value + while (IS_DIGIT(*pStr)) + { + Value = CONV_DEC_DIGIT_TO_VALUE(*pStr) + (Value*10); + pStr++; + } + } + else + { + // We don't have a value at all - return default value + return DefaultValue; + } + + // Update the BtString ptr + *ppLine = pStr; + return Value; +} + +static const char *mbr_help = + "Usage:\n" + "\n mbr <address> <length> \n" + "\n Example \n" + "\n mbr 0x00004FFC 10 \n" + "\n mbr 0x00004FFC 0x10 \n"; + +static void cmd_mbr(int dev_id, int argc, char **argv){ + int dd; + UCHAR buf[HCI_MAX_EVENT_SIZE*20]; + + if(argc != 3){ + printf("\n%s\n",mbr_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + int length = GetUInt(&(argv[2]),0); + int address = GetUInt(&(argv[1]),0); + + if ((address == 0) || (length==0)){ + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE*20); + if(!MemBlkRead(dd,address,buf, length)) { + printf("\nmemory bulk read command failed\n"); + return; + } + printf("\ndata: \n"); + int i; + for(i=0;i < length;i+=4){ + printf("%08X: ",address+i); + printf("%08X",*((int*)(buf+i))); + printf("\n"); + } + printf("\n"); + + hci_close_dev(dd); + +} + +static const char *psr_help = + "Usage:\n" + "\n psr \n"; + +static void cmd_psr(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + if(argc > 1){ + printf("\n%s\n",psr_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + LoadPSHeader(buf,PS_RESET,0,0); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER+2, buf); + if(buf[7] != 0){ /* Check for status */ + printf("\n PS Reset failed\n"); + hci_close_dev(dd); + return; + } + hci_close_dev(dd); + printf("PS reset done\n"); +} + +static const char *rpst_help = + "Usage:\n" + "\n rpst <tag id> <tag length> \n" + "\n Example:\n" + "\n rpst 1 6 \n"; +static void cmd_rpst(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int tag_id,tag_len,i,j; + if(argc != 3){ + printf("\n%s\n",rpst_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + tag_id = GetUInt(&(argv[1]),0); + tag_len = GetUInt(&(argv[2]),0); + LoadPSHeader(buf,PS_READ,tag_len,tag_id); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf); + if(buf[6] != 0){ + printf("\n read PS tag failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + iRet = read(dd,&buf,HCI_MAX_EVENT_SIZE); + if(iRet < 0){ + printf("\n read PS tag failed\n"); + hci_close_dev(dd); + return; + } + printf("\nTag ID :%X\nTag Length:%X\nTag Data:\n",tag_id,tag_len); + + for(i=4,j=1;i<iRet;i++,j++){ + printf("%02X ",buf[i]); + if(j%16 == 0) + printf("\n"); + } + printf("\n\n"); + hci_close_dev(dd); +} +static const char *wpst_help = + "Usage:\n" + "\n wpst <tag id> <tag length> <tag data>\n" + "\n Example:\n" + "\n wpst 1 6 00 03 F4 55 AB 77 \n"; + +static void cmd_wpst(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int tag_id,tag_len,i; + if(argc < 4){ + printf("\n%s\n",wpst_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + tag_id = GetUInt(&(argv[1]),0); + tag_len = GetUInt(&(argv[2]),0); + if(argc < tag_len+3){ + printf("\n Tag Data is less than Tag Length\n"); + hci_close_dev(dd); + return; + } + LoadPSHeader(buf,PS_WRITE,tag_len,tag_id); + for(i=0;i<tag_len;i++){ + buf[i+4] = strtol(argv[i+3], NULL, 16); + } + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER + tag_len, buf); + if(buf[6] != 0){ + printf("\n Write PS tag failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + hci_close_dev(dd); +} + +static const char *setam_help = + "Usage:\n" + "\nsetam <storage medium> <access mode>\n" + "\nstorage medium: 0-RAM 1-EEPROM\n" + "\naccess mode: 0-Read-only 1-Write-only 2-Read-Write 3- Disabled\n" + "\nExample:\n" + "\nsetam 0 3\n"; +static void cmd_setam(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int medium,mode; + if(argc !=3){ + printf("\n%s\n",setam_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + medium = GetUInt(&(argv[1]),0); + mode = GetUInt(&(argv[2]),0); + LoadPSHeader(buf,PS_SET_ACCESS_MODE,mode,medium); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf); + if(buf[6] != 0){ + printf("\nSet Access mode failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + hci_close_dev(dd); + printf("\nAccess mode changed successfully!\n"); +} + +static const char *setap_help = + "Usage:\n" + "\nsetap <storage medium> <priority>\n" + "\nstorage medium: 0-RAM 1-EEPROM\n" + "\npriority: #Highest number corresponds to highest priority\n" + "\nExample:\n" + "\nsetap 0 1\n"; + +static void cmd_setap(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int medium,priority; + if(argc !=3){ + printf("\n%s\n",setap_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + medium = GetUInt(&(argv[1]),0); + priority = GetUInt(&(argv[2]),0); + LoadPSHeader(buf,PS_SET_ACCESS_MODE,priority,medium); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf); + if(buf[6] != 0){ + printf("\nSet Access priority failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + hci_close_dev(dd); + printf("\nPriority changed successfully!\n"); +} + +static const char *rpsraw_help = + "Usage:\n" + "\n rpsraw <offset> <length> \n" + "\n Example:\n" + "\n rpsraw 0x012c 10\n"; +static void cmd_rpsraw(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int offset,len,i,j; + if(argc != 3){ + printf("\n%s\n",rpsraw_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + offset = GetUInt(&(argv[1]),0); + len = GetUInt(&(argv[2]),0); + LoadPSHeader(buf,PS_READ_RAW,len,offset); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER, buf); + if(buf[6] != 0){ + printf("\n read PS raw failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + iRet = read(dd,&buf,HCI_MAX_EVENT_SIZE); + if(iRet < 0){ + printf("\n read PS raw failed\n"); + hci_close_dev(dd); + return; + } + printf("\nOffset :%X\nLength:%X\nData:\n",offset,len); + + for(i=4,j=1;i<iRet;i++,j++){ + printf("%02X ",buf[i]); + if(j%16 == 0) + printf("\n"); + } + printf("\n\n"); + hci_close_dev(dd); +} +static const char *wpsraw_help = + "Usage:\n" + "\n wpsraw <offset> <length> <data>\n" + "\n Example:\n" + "\n wpsraw 0x012C 6 00 03 F4 55 AB 77 \n"; + +static void cmd_wpsraw(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int offset,len,i; + if(argc < 4){ + printf("\n%s\n",wpsraw_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + offset = GetUInt(&(argv[1]),0); + len = GetUInt(&(argv[2]),0); + if(argc < len+3){ + printf("\nData is less than Length\n"); + hci_close_dev(dd); + return; + } + LoadPSHeader(buf,PS_WRITE_RAW,len,offset); + for(i=0;i<len;i++){ + buf[i+4] = strtol(argv[i+3], NULL, 16); + } + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS,PS_COMMAND_HEADER + len, buf); + if(buf[6] != 0){ + printf("\n Write PS tag failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + hci_close_dev(dd); +} + +static const char *peek_help = + "\nUsage:" + "\npeek <address> <width>\n" + "\nExample:\n" + "\npeek 0x00004FFC 5\n"; +static void cmd_peek(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int address,width,value; + if(argc < 2){ + printf("\n%s\n",peek_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(&buf,0,HCI_MAX_EVENT_SIZE); + address = GetUInt(&(argv[1]),0); + if(argc == 3) + width = GetUInt(&(argv[2]),0x4); + else + width = 4; + + buf[0] = (address & 0xFF); + buf[1] = ((address >>8) & 0xFF); + buf[2] = ((address>>16) & 0xFF); + buf[3] = ((address>>24) & 0xFF); + buf[4] = (UCHAR)width; //Memory width + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_MEMORY, 5, buf); + if(buf[6] != 0){ + printf("\nRead Memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + value = buf[10]; + value = ((value << 8) | buf[9]); + value = ((value << 8) | buf[8]); + value = ((value << 8) | buf[7]); + + printf("\n0x%X : 0x%X \n",address,value); + //printf("\n0x%X : 0x%02X%02X%02X%02X \n",address,buf[7],buf[8],buf[9],buf[10]); + hci_close_dev(dd); +} + +static const char *cwtx_help = + "\nUsage:" + "\ncwtx <channel number>\n" + "\nExample:\n" + "\ncwtx 40" + "\n\n"; + +static void cmd_cwtx(int dev_id, int argc, char **argv){ + int dd,iRet, Length = 0; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int channel; + if(argc != 2){ + printf("\n%s\n",cwtx_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + channel = atoi(argv[1]); + if(channel > 78 || channel < 0){ + printf("\nPlease enter channel 0-78!\n"); + hci_close_dev(dd); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_RESET,Length,buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 0x80; + buf[1] = 0x20; + buf[2] = 0x02; + buf[3] = 0x00; + buf[4] = 0x04; + buf[5] = 0xFF; + buf[6] = 0x08; + buf[7] = 0xC0; + buf[8] = 0x00; + buf[9] = 0xFF; + buf[10] = 0xFF; + buf[11] = 0xFF; + buf[12] = 0xFF; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + /* hcitool cmd 0x3F 0x06 0x34 0x20 0x02 0x00 0x04 0x88 0xA0 0x00 0x02 0xFF 0xFF 0xFF 0xFF */ + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 0x34; + buf[1] = 0x20; + buf[2] = 0x02; + buf[3] = 0x00; + buf[4] = 0x04; + buf[5] = 0x88; + buf[6] = 0xA0; + buf[7] = 0x00; + buf[8] = 0x02; + buf[9] = 0xFF; + buf[10] = 0xFF; + buf[11] = 0xFF; + buf[12] = 0xFF; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + + /* hcitool cmd 0x3F 0x06 0x28 0x20 0x02 0x00 0x04 0x00 0x90 0x05 0x20 0xFF 0xFF 0xFF 0xFF */ + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 0x28; + buf[1] = 0x20; + buf[2] = 0x02; + buf[3] = 0x00; + buf[4] = 0x04; + buf[5] = 0x00; + buf[6] = 0x90; + buf[7] = 0x05; + buf[8] = 0x20; + buf[9] = 0xFF; + buf[10] = 0xFF; + buf[11] = 0xFF; + buf[12] = 0xFF; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + + /* hcitool cmd 0x3F 0x06 0x7C 0x08 0x02 0x00 0x04 0x01 0x00 0x00 0x4B 0xFF 0xFF 0xFF 0xFF */ + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 0x7C; + buf[1] = 0x08; + buf[2] = 0x02; + buf[3] = 0x00; + buf[4] = 0x04; + buf[5] = 0x01; + buf[6] = 0x00; + buf[7] = 0x00; + buf[8] = 0x4B; + buf[9] = 0xFF; + buf[10] = 0xFF; + buf[11] = 0xFF; + buf[12] = 0xFF; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + + + /* hcitool cmd 0x3F 0x06 0x00 0x08 0x02 0x00 0x04 $number 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF */ + memset(&buf,0,HCI_MAX_EVENT_SIZE); + buf[0] = 0x00; + buf[1] = 0x08; + buf[2] = 0x02; + buf[3] = 0x00; + buf[4] = 0x04; + buf[5] = (UCHAR)channel; /* Num */ + buf[6] = 0x00; + buf[7] = 0x00; + buf[8] = 0x00; + buf[9] = 0xFF; + buf[10] = 0xFF; + buf[11] = 0xFF; + buf[12] = 0xFF; + iRet = writeHciCommand(dd, OGF_VENDOR_CMD,OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + printf("\nEntering continuous wave Tx on channel %d\n",channel); + + hci_close_dev(dd); +} + + +static const char *poke_help = + "\nUsage:" + "\npoke <address> <value> <mask> <width>\n" + "\nExample:\n" + "\npoke 0x580000 0x22005FF 0xFFFFFFFF 4" + "\n\n"; + +static void cmd_poke(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + int address,width,value,mask; + if(argc < 2){ + printf("\n%s\n",poke_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + address = GetUInt(&(argv[1]),0); + value = GetUInt(&(argv[2]),0); + printf("\nARGC :%d\n",argc); + if(argc < 4) + mask = 0xffffffff; + else + mask = GetUInt(&(argv[3]),0xFFFFFFFF); + if(argc < 5) + width = 4; + else + width = GetUInt(&(argv[4]),0x4); + buf[0] = (address & 0xFF); + buf[1] = ((address >>8) & 0xFF); + buf[2] = ((address>>16) & 0xFF); + buf[3] = ((address>>24) & 0xFF); + buf[4] = width; //Memory width + buf[5] = (value & 0xFF); + buf[6] = ((value >> 8) & 0xFF); + buf[7] = ((value >> 16) & 0xFF); + buf[8] = ((value >> 24) & 0xFF); + buf[9] = (mask & 0xFF); + buf[10] = ((mask >>8) & 0xFF); + buf[11] = ((mask>>16) & 0xFF); + buf[12] = ((mask>>24) & 0xFF); + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_WRITE_MEMORY, 13, buf); + if(buf[6] != 0){ + printf("\nWrite memory address failed due to reason 0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + printf("\nPoke successful!\n"); + hci_close_dev(dd); +} + + + +static const char *dump_help = + "\nUsage:" + "\ndump audio - Display Audio statistics\n" + "\ndump dma- Display DMA statistics\n" + "\ndump dma r - Display and Reset DMA statistics\n" + "\ndump tpc - Dump TPC tables\n" + "\nExample:\n" + "\ndump audio" + "\ndump dma" + "\ndump dma r" + "\ndump tpc" + "\n"; + + +static void cmd_dump(int dev_id, int argc, char **argv){ + int dd; + if(argc < 2){ + printf("\n%s\n",dump_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + if(!strncmp(argv[1],"audio",5)){ + ReadAudioStats(dd); + } + else if(!strncmp(argv[1],"dma",3)){ + ReadGlobalDMAStats(dd); + if(argc == 3 && !strncmp(argv[2],"r",1)){ + ResetGlobalDMAStats(dd); + } + } + else if(!strncmp(argv[1],"tpc",3)){ + ReadTpcTable(dd); + } + else{ + printf("\nInvalid option"); + printf("\n%s\n",dump_help); + } + + hci_close_dev(dd); + return; +} + +static const char *rafh_help = + "\nUsage:" + "\nrafh <connection handle>\n" + "\nExample:\n" + "\nrafh 0x15" + "\n\n"; + +static void cmd_rafh(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + short int handle; + + if(argc < 2){ + printf("\n%s\n",rafh_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + handle = GetUInt(&(argv[1]),0); + buf[0] = (handle & 0xFF); + buf[1] = ((handle >>8) & 0xFF); + iRet = writeHciCommand(dd, OGF_STATUS_PARAM,OCF_READ_AFH_MAP, 2, buf); + if(buf[6] != 0){ + printf("\nRead AFH failed due to reason :0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + + if(buf[9] == 0) + printf(" AFH is disabled"); + else + printf(" AFH is enabled"); + + handle = (buf[7] | (buf[8] << 8)); + printf("\n AFH chaneel classification for handle: 0x%X",handle); + int i; + printf("\n Channel Classification Map :"); + for(i=iRet-1; i>9 ; i--){ + printf("%X",buf[i]); + } + printf("\n"); + hci_close_dev(dd); +} + +static const char *safh_help = + "\nUsage:" + "\nsafh <host channel classification>\n" + "\nExample:\n" + "\nsafh 0x7FFFFFFFFFFFFFFFFFFF" + "\n\n"; + +static void cmd_safh(int dev_id, int argc, char **argv){ + int dd,iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if(argc < 2){ + printf("\n%s\n",safh_help); + return; + } + int i,j; + i = strlen(argv[1]); + if(i > 20 || i < 20){ + printf("\n%s\n",safh_help); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(&buf,0,HCI_MAX_EVENT_SIZE); + const char *map = argv[1]; + char byte[3]; + int data; + for (i = 0,j=9; i < 20 ; i+=2,j--) { + memcpy(byte,&map[i],2); + byte[2] = '\0'; + data = strtol(byte, NULL, 16); + buf[j] = (data & 0xFF); + } + iRet = writeHciCommand(dd, OGF_HOST_CTL,OCF_SET_AFH_CLASSIFICATION,10, buf); + if(buf[6] != 0){ + printf("\nSet AFH failed due to reason :0x%X\n",buf[6]); + hci_close_dev(dd); + return; + } + printf("\nSet AFH successful!\n"); + hci_close_dev(dd); +} + +static const char *wotp_help = + "\nUsage:" + "\nwotp <address> <data> [length=1]\n" + "\nExample:\n" + "\nwotp 0x15 0x2020 2" + "\n\n"; + +static void cmd_wotp(int dev_id, int argc, char **argv) +{ + UINT32 address, length; + + if (argc < 3) { + printf("\n%s\n", wotp_help); + return; + } + if (argc == 4) + length = GetUInt(&argv[3], 1); + else + length = 1; + address = GetUInt(&argv[1], 0xffffffff); + if (address == 0xffffffff) { + printf("\n%s\n", wotp_help); + return; + } + ReverseHexString(argv[2]); + if (!write_otpRaw(dev_id, address, length, (UCHAR *)argv[2])) + printf("Write to OTP sucessful!\n"); +} + +static int write_otpRaw(int dev_id, int address, int length, UCHAR *data) +{ + int dd, iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return dd; + } + memset(&buf, 0, HCI_MAX_EVENT_SIZE); + buf[0] = 0x12; /* write RAW OTP */ + buf[1] = address & 0xFF; /* PS tag */ + buf[2] = (address >> 8) & 0xFF; + buf[3] = length; /* Entry Size */ + GetByteSeq(buf + 4, data, 244); /* Entry Data */ + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, 244 + PS_COMMAND_HEADER, buf); + if (buf[6] != 0) { + printf("\nWrite to OTP failed due to reason :0x%X\n", buf[6]); + hci_close_dev(dd); + return buf[6]; + } + hci_close_dev(dd); + return 0; +} + +static const char *rotp_help = + "\nUsage:" + "\nrotp <address> [length=1]\n" + "\nExample:\n" + "\nrotp 0x15 2" + "\n\n"; + +static void cmd_rotp(int dev_id, int argc, char **argv) +{ + UINT32 address, length; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if (argc < 2) { + printf("\n%s\n", rotp_help); + return; + } + if (argc == 3) + length = GetUInt(&argv[2], 1); + else + length = 1; + address = GetUInt(&argv[1], 0xffffffff); + if (address == 0xffffffff) { + printf("\n%s\n", rotp_help); + return; + } + if (!read_otpRaw(dev_id, address, length, buf)) + dumpHex(buf, length, 8); +} + +static int read_otpRaw(int dev_id, int address, int length, UCHAR *data) +{ + int dd, iRet, plen; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return dd; + } + memset(&buf, 0, HCI_MAX_EVENT_SIZE); + buf[0] = 0x11; /* read OTP */ + buf[1] = address & 0xFF; /* PS tag */ + buf[2] = (address >> 8) & 0xFF; + buf[3] = length; /* Entry Size */ + buf[4] = 0x00; /* Entry Data */ + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_PS, 244 + PS_COMMAND_HEADER, buf); + if (buf[6] != 0) { + printf("\nRead from OTP failed due to reason :0x%X\n", buf[6]); + hci_close_dev(dd); + return buf[6]; + } + do { + plen = read(dd, buf, HCI_MAX_EVENT_SIZE); + if (plen < 0) { + perror("Read OTP error\n"); + exit(EXIT_FAILURE); + } + } while (buf[HCI_EVENT_HEADER_SIZE] != DEBUG_EVENT_TYPE_PS); + memcpy(data, buf + HCI_EVENT_HEADER_SIZE + 1, length); + hci_close_dev(dd); + return 0; +} + +static int SU_GetId(int dev_id, char *pStr, tSU_RevInfo *pRetRevInfo) +{ + tSU_RevInfo RevInfo; + int dd, iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + RevInfo.RomVersion = 0x99999999; + RevInfo.BuildVersion = 0x99999999; + RevInfo.RadioFormat = 0xffff; + RevInfo.SysCfgFormat = 0xffff; + + memset(buf, 0, HCI_MAX_EVENT_SIZE); + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return dd; + } + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_READ_VERSION, 0, buf); + if (buf[6] != 0) { + printf("\nRead version failed due to reason :0x%X\n", buf[6]); + return buf[6]; + } + RevInfo.RomVersion = buf[7] + (buf[8]<<8) + (buf[9]<<16) + (buf[10]<<24); + RevInfo.BuildVersion = buf[11] + (buf[12]<<8) + (buf[13]<<16) + (buf[14]<<24); + return 0; +} + +/*static const char *otp_help = + "\nUsage:" + "\notp [dump|imp|exp|test|rpid|wpid|rvid|wvid|rba|wba|hid|cpw|cpw|pwridx|ledo] [file]\n" + "\notp wba <BdAddr>:\n" + "\n\n"; +*/ + +static void cmd_otp(int dev_id, int argc, char **argv) +{ + UCHAR buf[512], format[16]; + FILE *pF = NULL; + UINT32 data; + int i; + + if (argc == 1 || !strcmp(argv[1], "dump")) { + printf("dump:\n"); + for (i = 0; i < 4; i++) { + if (read_otpRaw(dev_id, 128 * i, 128, &buf[128*i])) { + printf("read failed\n"); + return; + } + } + dumpHex(buf, 512, 8); + } else if (!strcmp(argv[1], "test")) { + printf("test:\n"); + printf("To be continue.\n"); + } else if (!strcmp(argv[1], "imp")) { + if (argc < 3 || !*argv[2]) { + printf("Import file content into OTP. File name is required\n"); + return; + } + printf("Import from %s into OTP:\n", argv[2]); + if (!(pF = fopen(argv[2], "rb"))) { + printf("Open file failed\n"); + return; + } + fread(&buf[0], sizeof(buf), 1, pF); + fclose(pF); + for (i = 0; i < 512; i += 4) { + data = buf[i]; + data <<= 8; + data += buf[i+1]; + data <<= 8; + data += buf[i+2]; + data <<= 8; + data += buf[i+3]; + sprintf((char *)&format, "0x%08x", data); + if (write_otpRaw(dev_id, i, 4, (UCHAR *)format)) { + printf("Failed!(%d)\n", i); + return; + } + } + printf("Done\n"); + } else if (!strcmp(argv[1], "exp")) { + for (i = 0; i < 4; i++) { + if (read_otpRaw(dev_id, 128 * i, 128, &buf[128*i])) { + printf("Failed\n"); + return; + } + } + if (argc < 3 || !*argv[2] || (!(pF = fopen(argv[2], "wb")))) { + /* export the content to the screen */ + dumpHex(buf, 512, 8); + } else { + /* export the content to the file */ + fwrite(&buf[0], sizeof(buf), 1, pF); + fclose(pF); + } + printf("Done\n"); + } else if (!strcmp(argv[1], "ledo")) { + int opendrain; + tSU_RevInfo RevInfo; + + if (SU_GetId(dev_id, NULL, &RevInfo)) + return; + + printf("RomVer:%02X.%02X.%02X.%02X \n", (UINT8)((RevInfo.RomVersion >> (8*3)) & 0xff), + (UINT8)((RevInfo.RomVersion >> (8*2)) & 0xff), + (UINT8)((RevInfo.RomVersion >> 8) & 0xff), + (UINT8)(RevInfo.RomVersion & 0xff)); + if (((UINT8)((RevInfo.RomVersion >> (8*3)) & 0xff) == 0x01) && + ((UINT8)((RevInfo.RomVersion >> (8*2)) & 0xff) == 0x02) && + ((UINT8)((RevInfo.RomVersion >> 8) & 0xff) == 0x02) && + ((UINT8)(RevInfo.RomVersion & 0xff) == 0x00)) { + UINT8 LedValue[] = {0xCE, 0xDA, 0x04, 0x0C, 0x58, + 0x04, 0x05, 0x06, 0xff, 0x50, + 0x40, 0x01, 0x24, 0x08, 0x00, + 0x00}; + for (opendrain = 112; opendrain < 128; opendrain++) { + if (write_otpRaw(dev_id, opendrain, 1, &LedValue[opendrain-112])) { + printf("Failed\n"); + return; + } + } + printf("OTP led opendrain done\n"); + } else { + printf("Wrong RomVer\n"); + } + } else if (!strcmp(argv[1], "cpw")) { + UINT32 cin_value = 0, cout_value = 0; + char tempStr[8]; + + if (argc < 3) { + printf("\n Enter cin_value : "); + scanf("%d", &cin_value); + } else + cin_value = GetUInt(&argv[2], 0); + if (cin_value < 0 || cin_value > 128) { + printf("Invalid cin_value = %d\n", cin_value); + return; + } + if (argc < 4) { + printf("\n Enter cout_value : "); + scanf("%d", &cout_value); + } else + cout_value = GetUInt(&argv[3], 0); + if (cout_value < 0 || cout_value > 128) { + printf("Invalid cout_value = %d\n", cout_value); + return; + } + if (cout_value & 0x01) cin_value += 0x80; + sprintf(tempStr, "0x%02x", cin_value); + if (write_otpRaw(dev_id, 4, 1, (UCHAR *)tempStr)) { + printf("CapTune Error\n"); + return; + } + sprintf(tempStr, "0x%02x", cout_value >> 1); + if (write_otpRaw(dev_id, 5, 1, (UCHAR *)tempStr)) { + printf("CapTune Error\n"); + return; + } + sprintf(tempStr, "0x40"); + if (write_otpRaw(dev_id, 5, 1, (UCHAR *)tempStr)) { + printf("CapTune Error\n"); + return; + } + printf("Done\n"); + } else if (!strcmp(argv[1], "pwridx")) { + char tempStr[8]; + sprintf(tempStr, "0x02"); + if (write_otpRaw(dev_id, 21, 1, (UCHAR *)tempStr)) { + printf("Failed\n"); + return; + } + printf("Done\n"); + } else if (!strcmp(argv[1], "hid")) { + char tempStr[8]; + UINT32 value = 0; + if (argc < 3 || !*argv[2]) { + printf("\n Enter HID value(0|1) : "); + scanf("%d", &value); + } else + value = GetUInt(&argv[2], 0); + if (value != 0 && value != 1) { + printf("\n Error: Syntax \"otp hid 0x00|0x01\"\n"); + return; + } + sprintf(tempStr, "0x%02x", value); + if (write_otpRaw(dev_id, 12, 1, (UCHAR *)tempStr)) { + printf("Failed\n"); + return; + } + printf("Done\n"); + } else if (!strcmp(argv[1], "wpid")) { + UINT32 offset = 134; + size_t len = 0; + char pid[8] = {0}; + char *ofs = NULL; + printf("\n Enter OTP_PID_OFFSET(default 134) : "); + getline(&ofs, &len, stdin); + sscanf(ofs, "%d", &offset); + if (ofs) free(ofs); + memset(pid, 0, sizeof(pid)); + if (argc < 3 || !*argv[2]) { + printf("\n Enter PID : "); + fgets((char *)pid, 7, stdin); + } else + strncpy((char *)pid, argv[2], 7); + len = strlen(pid) - 1; + if (pid[len] == '\n' || pid[len] == '\r') + pid[len] = 0; + ReverseHexString(pid); + if (write_otpRaw(dev_id, offset, 4, (UCHAR *)pid)) { + printf("Failed\n"); + return; + } + printf("Done\n"); + } else if (!strcmp(argv[1], "rpid")) { + UINT32 offset = 134; + size_t len = 0; + UCHAR Data[2]; + char *ofs = NULL; + printf("\n Enter OTP_PID_OFFSET(default 134) : "); + getline(&ofs, &len, stdin); + sscanf(ofs, "%d", &offset); + if (ofs) free(ofs); + if (read_otpRaw(dev_id, offset, 2, Data)) { + printf("Failed\n"); + return; + } + printf("The OTP PID is 0x%02x%02x\n", Data[1], Data[0]); + } else if (!strcmp(argv[1], "wvid")) { + UINT32 offset = 136; + size_t len = 0; + char vid[8] = {0}; + char *ofs = NULL; + printf("\n Enter OTP_VID_OFFSET(default 136) : "); + getline(&ofs, &len, stdin); + sscanf(ofs, "%d", &offset); + if (ofs) free(ofs); + memset(vid, 0, sizeof(vid)); + if (argc < 3 || !*argv[2]) { + printf("\n Enter VID : "); + fgets(vid, 8, stdin); + } else + strncpy(vid, argv[2], 7); + len = strlen(vid) - 1; + if (vid[len] == '\n' || vid[len] == '\r') + vid[len] = 0; + ReverseHexString(vid); + if (write_otpRaw(dev_id, offset, 2, (UCHAR *)vid)) { + printf("Failed\n"); + return; + } + printf("Done\n"); + } else if (!strcmp(argv[1], "rvid")) { + UINT32 offset = 136; + size_t len = 0; + char *ofs = NULL; + UCHAR Data[2]; + printf("\n Enter OTP_VID_OFFSET(default 136) : "); + getline(&ofs, &len, stdin); + sscanf(ofs, "%d", &offset); + if (ofs) free(ofs); + if (read_otpRaw(dev_id, offset, 2, Data)) { + printf("Failed\n"); + return; + } + printf("The OTP VID is 0x%02x%02x\n", Data[1], Data[0]); + } else if (!strcmp(argv[1], "wba")) { + UINT32 offset = 128; + size_t len = 0; + char bdaddr[16] = {0}; + char *ofs = NULL; + printf("\n Enter OTP_BDA_OFFSET(default 128) : "); + getline(&ofs, &len, stdin); + sscanf(ofs, "%d", &offset); + if (ofs) free(ofs); + memset(bdaddr, 0, sizeof(bdaddr)); + if (argc < 3 || !*argv[2]) { + printf("\n Enter BDADDR : "); + fgets(bdaddr, 16, stdin); + } else + strncpy(bdaddr, argv[2], 15); + len = strlen(bdaddr) - 1; + if (bdaddr[len] == '\n' || bdaddr[len] == '\r') + bdaddr[len] = 0; + ReverseHexString(bdaddr); + if (write_otpRaw(dev_id, offset, 6, (UCHAR *)bdaddr)) { + printf("Failed\n"); + return; + } + printf("Done\n"); + } else if (!strcmp(argv[1], "rba")) { + UINT32 offset = 128; + size_t len = 0; + char *ofs = NULL; + UCHAR Data[6]; + printf("\n Enter OTP_BDA_OFFSET(default 128) : "); + getline(&ofs, &len, stdin); + sscanf(ofs, "%d", &offset); + if (ofs) free(ofs); + if (read_otpRaw(dev_id, offset, 6, Data)) { + printf("Failed\n"); + return; + } + printf("The OTP BDADDR is 0x%02x%02x%02x%02x%02x%02x\n", + Data[5], Data[4], Data[3], Data[2], Data[1], Data[0]); + } +} + +static const char *plb_help = + "\nUsage:" + "\nplb [1|0]\n" + "\nplb 1\n" + "\n\n"; + +static void cmd_plb(int dev_id, int argc, char **argv) +{ + int dd, enable, iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + if (argc < 2) + enable = 1; + else + enable = GetUInt(&argv[1], 1); + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(buf, 0, HCI_MAX_EVENT_SIZE); + buf[0] = 0x09; /* audio commmand opcode */ + buf[4] = (enable == 0) ? 0x00 : 0x01; /* audio command param */ + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_AUDIO_CMD, 8, buf); + if (buf[6] != 0) { + printf("\nError in setting PCM CODEC loopback :0x%X\n", buf[6]); + hci_close_dev(dd); + return; + } + printf("\nPCM CODEC loopback is %s\n", (enable == 0) ? "OFF" : "ON"); + hci_close_dev(dd); +} + +static const char *psw_help = + "\nUsage:" + "\npsw [1|0] [Frequency]\n" + "\npsw 1 3000\n" + "\n\n"; + +static void cmd_psw(int dev_id, int argc, char **argv) +{ + int dd, enable, freq, iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + if (argc < 2) { + enable = 1; + freq = 440; + } + else if (argc < 3) { + printf("aa\n"); + enable = GetUInt(&argv[1], 1); + freq = 440; + } else { + enable = GetUInt(&argv[1], 1); + freq = GetUInt(&argv[2], 440); + } + if (freq > 3700) { + printf("Invalid frequency. It should be in the range of 0 to 3700\n"); + return; + } + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + memset(buf, 0, HCI_MAX_EVENT_SIZE); + buf[0] = 0x0a; /* audio command opcode */ + buf[4] = (enable == 0) ? 0x00 : 0x01; /* audio command param */ + buf[5] = 0x00; + buf[6] = freq & 0xff; + buf[7] = (freq >> 8) & 0xff; + + iRet = writeHciCommand(dd, OGF_VENDOR_CMD, OCF_AUDIO_CMD, 8, buf); + if (buf[6] != 0) { + printf("\nError in running PCM sine wave playback :0x%X\n", buf[6]); + hci_close_dev(dd); + return; + } + printf("PCM CODEC PCM sine wave playback is %s\n", (enable == 0) ? "OFF" : "ON"); + hci_close_dev(dd); +} + +static const char *lert_help= + "\nUsage:" + "\nlert <rx_channel>\n" + "\nlert 30 \n" + "\n\n"; + +static void cmd_lert(int dev_id, int argc, char **argv) +{ + int dd; + UCHAR channel; + if (argc < 2) { + printf("\n%s\n", lert_help); + return; + } + channel = (UCHAR)GetUInt(&argv[1], 0); + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + SU_LERxTest(dd, channel); + hci_close_dev(dd); +} + +static BOOL SU_LERxTest(int dd, UCHAR channel) +{ + int iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if (channel < MB_MIN_FREQUENCY_LE || channel > MB_MAX_FREQUENCY_LE) { + printf("Invalid rx channel. It should be in the range of %d to %d\n", + MB_MIN_FREQUENCY_LE, MB_MAX_FREQUENCY_LE); + return FALSE; + } + + memset(buf, 0, HCI_MAX_EVENT_SIZE); + buf[0] = channel; /* rx_channel */ + iRet = writeHciCommand(dd, OGF_LE_CTL, OCF_LE_RECEIVER_TEST, 1, buf); + if (buf[6] != 0) { + printf("\nError in putting the device into LE RX mode\n"); + return FALSE; + } + return TRUE; +} + +static const char *lett_help= + "\nUsage:" + "\nlett <rx_channel> <length> <packet_payload>\n" + "\nlett 30 30 5\n" + "\n\n"; + +static void cmd_lett(int dev_id, int argc, char **argv) +{ + int dd; + UCHAR channel, length, payload; + if (argc < 4) { + printf("\n%s\n", lett_help); + return; + } + channel = (UCHAR)GetUInt(&argv[1], 0); + length = (UCHAR)GetUInt(&argv[2], 0); + payload = (UCHAR)GetUInt(&argv[3], 0); + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + SU_LETxTest(dd, channel, length, payload); + hci_close_dev(dd); +} + +static BOOL SU_LETxTest(int dd, UCHAR channel, UCHAR length, UCHAR payload) +{ + int iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if (channel < MB_MIN_FREQUENCY_LE || channel > MB_MAX_FREQUENCY_LE) { + printf("Invalid tx channel. It should be in the range of %d to %d\n", + MB_MIN_FREQUENCY_LE, MB_MAX_FREQUENCY_LE); + return FALSE; + } + if (length < MB_MIN_DATALEN_LE || length > MB_MAX_DATALEN_LE) { + printf("Invalid data length. It should be in the range of %d to %d\n", + MB_MIN_DATALEN_LE, MB_MAX_DATALEN_LE); + return FALSE; + } + if (payload > 7) { + printf("Invalid packet payload. It should be in the range of 0 to 7\n"); + return FALSE; + } + + memset(buf, 0, HCI_MAX_EVENT_SIZE); + buf[0] = channel; /* tx_channel */ + buf[1] = length; /* length of test data */ + buf[2] = payload; /* packet payload */ + iRet = writeHciCommand(dd, OGF_LE_CTL, OCF_LE_TRANSMITTER_TEST, 3, buf); + if (buf[6] != 0) { + printf("\nError in putting the device into LE TX mode\n"); + return FALSE; + } + return TRUE; +} + +static const char *lete_help = + "\nUsage:" + "\nlete\n" + "\n\n"; + +static void cmd_lete(int dev_id, int argc, char **argv) +{ + int dd, iRet; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + memset(buf, 0, HCI_MAX_EVENT_SIZE); + iRet = writeHciCommand(dd, OGF_LE_CTL, OCF_LE_TEST_END, 0, buf); + if (buf[6] != 0) { + printf("\nError in ending LE test\n"); + hci_close_dev(dd); + return; + } + printf("Number of packets = %d\n", buf[7] | (buf[8] << 8)); + hci_close_dev(dd); +} + +static const char *tputs_help = + "\nUsage:" + "\ntput-s [BD_Addr] [Judgment value] Logfile times" + "\ntput-s 11:22:33:44:55:66 150 log.txt 10" + "\n\n"; + +static void CalculateTput(int dd, UINT16 hci_handle, char *filename, double threshold, int tx_size) +{ + time_t start, finish, checkbreak; + UCHAR buf[1009]; + FILE *fp = NULL; + int aclnum = 8; + int retval; + unsigned long sentnum = 0; + double TimeResult = 0; + fd_set rfds; + struct hci_filter flt; + struct timeval tv1, tv2, timeout; + unsigned long long start_utime, end_utime, time_diff; + unsigned long long throughput; + + hci_filter_clear(&flt); + hci_filter_set_ptype(HCI_EVENT_PKT, &flt); + hci_filter_set_event(EVT_NUM_COMP_PKTS, &flt); + if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { + perror("HCI filter setup failed"); + exit(EXIT_FAILURE); + } + start = time(NULL); + gettimeofday(&tv1, NULL); + start_utime = tv1.tv_sec*1000000 + tv1.tv_usec; + while (sentnum < 1024 * tx_size) { + while (aclnum > 0) { + aclnum--; + buf[0] = HCI_ACLDATA_PKT; + /* ACL packet header */ + buf[1] = hci_handle & 0xFF; + buf[2] = ((hci_handle >> 8) & 0x0E); + buf[3] = 1004 & 0xff; + buf[4] = (1004 >> 8) & 0xff; + /* L2CAP packet header */ + buf[5] = 1000 & 0xff; + buf[6] = (1000 >> 8) & 0xff; + buf[7] = 0x40 & 0xff; + buf[8] = 0; + + memset(buf+9, sentnum++, 1000); + while (write(dd, (const void *)buf, 1009) < 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + perror("HCI send packet failed"); + exit(EXIT_FAILURE); + } + } + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + FD_ZERO(&rfds); + FD_SET(dd, &rfds); + retval = select(dd+1, &rfds, NULL, NULL, &timeout); + if (retval == -1) { + perror("select()"); + exit(EXIT_FAILURE); + } else if (retval) { + /* Data is available now */ + ssize_t plen; + UCHAR buffer[64]; + int i; + plen = read(dd, buffer, 64); + if (plen < 0) { + perror("HCI read buffer failed"); + exit(EXIT_FAILURE); + } + for (i = 0; i < buffer[HCI_EVENT_HEADER_SIZE]; i++) + aclnum += (buffer[HCI_EVENT_HEADER_SIZE+(i+1)*2+1] | (buffer[HCI_EVENT_HEADER_SIZE+(i+1)*2+2] << 8)); + } + checkbreak = time(NULL); + if ((checkbreak - start) >= 300) break; + } + finish = time(NULL); + gettimeofday(&tv2, NULL); + end_utime = tv2.tv_sec*1000000 + tv2.tv_usec; + time_diff = end_utime - start_utime; + throughput = time_diff/1000; + throughput = (sentnum * 1000)/throughput; + printf("Transfer Completed! throughput [%0d KB/s]", (int)throughput); + printf(" result [%s]\n", threshold > throughput ? " Fail " : " Pass "); + if (filename && *filename) + fp = fopen(filename, "at+"); + if (fp) { + fprintf(fp, "Transfer Completed! throughput [%.0f KB/s]", TimeResult); + fprintf(fp, " result [%s]\n", threshold > TimeResult ? " Fail " : " Pass "); + fclose(fp); + } +} + +static void cmd_tputs(int dev_id, int argc, char **argv) +{ + int j, dd, iRet, loop = 1, tx_test_size = 1; + UINT16 Ps_EntrySize = 0; + UINT16 hci_handle = 0; + double threshold = 0.0; + char *filename = NULL; + struct sigaction sa; + FILE *fp = NULL; + bdaddr_t bdaddr; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + UCHAR Ps_Data[HCI_MAX_EVENT_SIZE]; + UINT16 *pPs_Data; + BOOL Ok = FALSE; + char timeString[9] = {0}; + char dateString[15] = {0}; + time_t current_time; + struct tm *time_info; + tSU_RevInfo RevInfo; + + if (argc < 3) { + printf("\n%s\n", tputs_help); + return; + } + + if (str2ba(argv[1],&bdaddr)) { + printf("\nPlease input valid bdaddr.\n"); + return; + } + threshold = atof(argv[2]); + if (!threshold) { + printf("\nPlease input valid throughput threshold.\n"); + return; + } + if (argc > 3) + filename = strdup(argv[3]); + if (argc > 4) + loop = GetUInt(&argv[4], 1); + if (argc > 5) + tx_test_size = GetUInt(&argv[5],1); + if (dev_id < 0) + dev_id = hci_get_route(NULL); + + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + CtrlCBreak = FALSE; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sig_term; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + PSInit(dd); + memset(buf, 0, sizeof(buf)); + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_RESET, 0, buf); + if (buf[6] != 0) { + printf("Error: HCI RESET failed.\n"); + hci_close_dev(dd); + return; + } + sleep(1); + for (j = 0; j < loop; j++) { + int i = 0; + if (!j) sleep(1); + printf("\n-----------------------------------"); + printf("\nTimes %d/%d\n", j + 1, loop); + + time(¤t_time); + time_info = localtime(¤t_time); + strftime(timeString, sizeof(timeString), "%H %M %S", time_info); + strftime(dateString, sizeof(dateString), "%b %d %Y", time_info); + if (j == 0) { + if (filename && *filename) + fp = fopen(filename, "at+"); + if (fp != NULL) + fprintf(fp, "\n[%s %s] \nCMD : TPUT-S %s %f %s %d\n", + dateString, timeString, argv[1], threshold, filename, loop); + /* SFLAGS FW */ + Ok = PSOperations(dd, PS_GET_LENGTH, PSTAG_RF_TEST_BLOCK_START, (UINT32 *)&Ps_EntrySize); + if (Ok) { + Ps_Data[0] = Ps_EntrySize & 0xff; + Ps_Data[1] = (Ps_EntrySize >> 8) & 0xff; + Ok = PSOperations(dd, PS_READ, PSTAG_RF_TEST_BLOCK_START, (UINT32 *)&Ps_Data); + if (Ok) { + pPs_Data = (UINT16 *)&Ps_Data[0]; + if (*pPs_Data == BT_SOC_INIT_TOOL_START_MAGIC_WORD) { + RevInfo.RadioFormat = *(pPs_Data + 1); + RevInfo.RadioContent = *(pPs_Data + 2); + } + } + } + + /* Get syscfg info */ + Ok = PSOperations(dd, PS_GET_LENGTH, PSTAG_SYSCFG_PARAM_TABLE0, (UINT32 *)&Ps_EntrySize); + if (Ok) { + Ps_Data[0] = Ps_EntrySize & 0xff; + Ps_Data[1] = (Ps_EntrySize >> 8) & 0xff; + Ok = PSOperations(dd, PS_READ, PSTAG_SYSCFG_PARAM_TABLE0, (UINT32 *)&Ps_Data); + if (Ok) { + pPs_Data = (UINT16 *)&Ps_Data[0]; + if (*pPs_Data == 0xC1C1) { + RevInfo.SysCfgFormat = *(pPs_Data + 1); + RevInfo.SysCfgContent = *(pPs_Data + 2); + } + + } + } + + if (RevInfo.SysCfgFormat != 0xff) { + printf("SysCfg - Format: %d.%d\n",((RevInfo.SysCfgFormat >> 4) & 0xfff), (RevInfo.SysCfgFormat & 0xf)); + printf(" Content: %d\n", RevInfo.SysCfgContent); + if (fp) { + fprintf(fp, "SysCfg - Format: %d.%d\n",((RevInfo.SysCfgFormat >> 4) & 0xfff), + (RevInfo.SysCfgFormat & 0xf)); + fprintf(fp, " Content: %d\n", RevInfo.SysCfgContent); + } + } else { + printf("SysCfg - N/A\n"); + if(fp) + fprintf(fp, "SysCfg - N/A\n"); + } + + /* bd addr */ + memset(&buf, 0, sizeof(buf)); + iRet = writeHciCommand(dd, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, buf); + if (buf[6] != 0) { + printf("\nCould not read the BD_ADDR (time out)\n"); + } else { + char temp[16] = {0}; + memset(temp, 0, sizeof(temp)); + sprintf(temp, "%02X%02X%02X%02X%02X%02X", buf[iRet-1], buf[iRet-2], + buf[iRet-3], buf[iRet-4], buf[iRet-5], buf[iRet-6]); + printf("\nLocal BDAddress : 0x%s\n", temp); + if (fp) + fprintf(fp, "Local BDAddress : 0x%s\n", temp); + } + + if (fp) { + fclose(fp); + fp = NULL; + } + } + printf("Sending packages to 0x%s\n", argv[1]); + while (i++ < 3) { + iRet = hci_create_connection(dd, &bdaddr, 0xCC18, 0, 0, &hci_handle, 0); + if (!iRet || CtrlCBreak) break; + } + + if (iRet) { + if (filename && *filename) { + fp = fopen(filename, "at+"); + if (fp) { + fprintf(fp, "Transfer Failed! \n"); + fclose(fp); + fp = NULL; + } + } + printf("Transfer Failed! \n"); + CtrlCBreak = TRUE; + hci_close_dev(dd); + return; + } + CalculateTput(dd, hci_handle, filename, threshold, tx_test_size); + + hci_disconnect(dd, hci_handle, 0, 30); + + if (CtrlCBreak) break; + } + CtrlCBreak = TRUE; + hci_close_dev(dd); +} + +static void cmd_tputr(int dev_id, int argc, char **argv) +{ + int dd, iRet; + ssize_t plen; + UINT16 hci_handle = 0; + UCHAR buf[HCI_MAX_EVENT_SIZE]; + struct hci_filter flt; + struct sigaction sa; + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + CtrlCBreak = FALSE; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sig_term; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + memset(buf, 0, sizeof(buf)); + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_RESET, 0, buf); + if (buf[6] != 0) { + printf("Error: HCI RESET failed.\n"); + hci_close_dev(dd); + return; + } + sleep(1); + memset(buf, 0, sizeof(buf)); + buf[0] = 0x02; + iRet = writeHciCommand(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, buf); + if (buf[6] != 0) { + printf("Error: Write scan failed\n"); + return; + } + hci_filter_clear(&flt); + hci_filter_set_ptype(HCI_EVENT_PKT, &flt); + hci_filter_all_events(&flt); + if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { + perror("HCI filter setup failed"); + exit(EXIT_FAILURE); + } + printf("Start listening ...\n"); + do { + plen = read(dd, buf, HCI_MAX_EVENT_SIZE); + if (plen < 0) { + printf("reading failed...\n"); + if (errno == EAGAIN || errno == EINTR) continue; + else { + perror("HCI read failed"); + exit(EXIT_FAILURE); + } + } + if (buf[1] == EVT_CONN_REQUEST) { + int i, j; + ssize_t plen = 0; + printf("Connection come in\n"); + for (i = 0, j = 3; i < BD_ADDR_SIZE; i++, j++) + buf[i] = buf[j]; + buf[BD_ADDR_SIZE] = 0x01; + if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ, 7, buf)) { + printf("Accept connection error\n"); + return; + } + do { + plen = read(dd, buf, HCI_MAX_EVENT_SIZE); + if (plen < 0) { + perror("Read failed"); + exit(EXIT_FAILURE); + } + } while (buf[1] != EVT_CONN_COMPLETE); + if (buf[3] == 0) { + printf("Connection up\n"); + } else { + printf("Connection failed\n"); + } + hci_handle = (buf[4] | (buf[5] << 8)) & 0x0EFF; + } else if (buf[1] == EVT_DISCONN_COMPLETE) { + UINT16 hdl = buf[4] | (buf[5] << 8); + printf("Disconnect...\n"); + if (hdl == hci_handle) { + break; + } + } else if (CtrlCBreak) { + printf("CtrlBreak...\n"); + break; + } + } while (plen >= 0); + CtrlCBreak = TRUE; + hci_close_dev(dd); +} + +static void cleanup() +{ + if (cid>=0) { + close(cid); + } + if (sid>=0) { + close(sid); + } +} + +int sock_recv(int sockid, unsigned char *buf, int buflen) +{ + int recvbytes; + recvbytes = recv(sockid, buf, buflen, 0); + if (recvbytes == 0) { + printf("Connection close!? zero bytes received\n"); + return -1; + } else if (recvbytes > 0) { + return recvbytes; + } + return -1; +} + +int sock_send(int sockid, unsigned char *buf, int bytes) +{ + int cnt; + unsigned char* bufpos = buf; + while (bytes) { + cnt = write(sockid, bufpos, bytes); + if (cnt != bytes) + printf("cnt:%d,bytes:%d\n",cnt, bytes); + + if (!cnt) { + break; + } + if (cnt == -1) { + if (errno == EINTR) { + continue; + } else { + return -1; + } + } + + bytes -= cnt; + bufpos += cnt; + } + return (bufpos - buf); +} + +static void cmd_btagent(int dev_id, int argc, char **argv) +{ + int dd, i, j, k, l, iRet, need_raw, rx_enable, iDataSize; + uint32_t m_BerTotalBits, m_BerGoodBits; + uint8_t m_pattern[16]; + uint16_t m_pPatternlength; + int port = BT_PORT; + struct sigaction sa; + unsigned char buf[1024]; + struct hci_filter flt; + struct hci_dev_info di; + struct timeval timeout; + +/* master file descriptor list */ + fd_set master; + fd_set read_fds; + +/* server address */ + struct sockaddr_in serveraddr; + + int fdmax; + +/* listening socket descriptor */ + int listener = -1; + +/* newly accept()ed socket descriptor */ + int newfd = -1; + + int nbytes; + +/* for setsockopt() SO_REUSEADDR, below */ + int yes = 1; + + int addrlen; + + if (argc > 1) + port = atoi(argv[1]); + if (port == 0) + port = BT_PORT; + else if (port < 0 || port >65534) { + perror("\nERROR: Invalid port number\n"); + return; + } + + if (dev_id < 0) + dev_id = hci_get_route(NULL); + dd = hci_open_dev(dev_id); + if (dd < 0) { + perror("\nERROR: Can not open HCI device\n"); + return; + } + + if (hci_devinfo(dev_id, &di) < 0) { + perror("Can't get device info\n"); + hci_close_dev(dd); + return; + } + + need_raw = !hci_test_bit(HCI_RAW, &di.flags); + + hci_filter_clear(&flt); + hci_filter_all_ptypes(&flt); + hci_filter_all_events(&flt); + + if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { + perror("Can't set filter for hci\n"); + hci_close_dev(dd); + return; + } + + if (need_raw) { + if (ioctl(dd, HCISETRAW, 1) < 0) { + perror("Can't set raw mode on hci\n"); + hci_close_dev(dd); + return; + } + } + + CtrlCBreak = FALSE; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sig_term; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + + /* clear the master and temp sets */ + FD_ZERO(&master); + FD_ZERO(&read_fds); + + /* get the listener */ + if((listener = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { + perror("Server-socket() error lol!"); + return; + } + + if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(int)) == -1) { + perror("Server-setsockopt() error lol!"); + close(listener); + return; + } + + if(setsockopt(listener, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(int)) == -1) { + perror("Server-setsockopt() error TCP_NODELAY\n"); + close(listener); + return; + } + + /* bind */ + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); + serveraddr.sin_port = htons(port); + memset(&(serveraddr.sin_zero), 0, 8); + + if(bind(listener, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1) { + perror("Server-bind() error lol!"); + close(listener); + return; + } + + /* listen */ + if(listen(listener, 10) == -1) { + perror("Server-listen() error lol!"); + close(listener); + return; + } + + /* add the listener to the master set */ + FD_SET(listener, &master); + + /* add hci handler to the master set */ + FD_SET(dd, &master); + + FD_SET(0, &master); + /* keep track of the biggest file descriptor */ + fdmax = listener; + if (dd > listener) fdmax = dd; + + printf("Start BtAgent, press 'q' to exit.\n"); + + rx_enable = 0; + m_BerGoodBits = 0; + m_BerTotalBits = 0; + m_pattern[0] = 0x0f; + m_pPatternlength = 1; + + while (1) { + read_fds = master; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + iRet = select(fdmax+1, &read_fds, NULL, NULL, &timeout); + if (iRet == -1) { + perror("Server-select() error lol!"); + if (newfd > 0) close(newfd); + close(listener); + goto exits; + } + if (CtrlCBreak) break; + if (iRet == 0) continue; + + /*run through the existing connections looking for data to be read*/ + for(i = 0; i <= fdmax; i++) { + if(FD_ISSET(i, &read_fds)) { + + if(i == 0) { + printf("Shutting down btagent\n"); + iRet = getchar(); + if (iRet == 'q') goto exits; + continue; + } + + if(i == listener) { + /* handle new connections */ + addrlen = sizeof(struct sockaddr_in); + if((newfd = accept(listener, (struct sockaddr *)&serveraddr, &addrlen)) == -1) { + perror("Server-accept() error lol!"); + goto exits; + } + else { + printf("Server-accept() is OK...%d\n",newfd); + FD_SET(newfd, &master); /* add to master set */ + if(newfd > fdmax) + fdmax = newfd; + } + } + else if (i == newfd) { + /* handle data from a client */ + if((nbytes = sock_recv(i, buf, sizeof(buf))) < 0) { + /* got error or connection closed by client */ + close(i); + /* remove from master set */ + FD_CLR(i, &master); + } + else { + + for (j=0; j<nbytes; j++) + printf("%x ",buf[j]); + printf("\n"); + if (buf[0] == 0x7) { // BTAGENT_CMD_EVENT + if (buf[3] == 0x01) { // BTAGENT_CMD_EVENT_GETBER + buf[11] = (m_BerTotalBits & 0xff000000) >> 24; + buf[10] = (m_BerTotalBits & 0xff0000) >> 16; + buf[9] = (m_BerTotalBits & 0xff00) >> 8; + buf[8] = m_BerTotalBits & 0xff; + buf[7] = (m_BerGoodBits & 0xff000000) >> 24; + buf[6] = (m_BerGoodBits & 0xff0000) >> 16; + buf[5] = (m_BerGoodBits & 0xff00) >> 8; + buf[4] = m_BerGoodBits & 0xff; + buf[3] = 1; // BTAGENT_CMD_EVENT_GETBER + buf[2] = 0; + buf[1] = 9; + buf[0] = 7; + sock_send(newfd, buf, 9+3); + usleep(2000); + } + else if (buf[3] == 0x02) { // BTAGENT_CMD_EVENT_PATTERN + m_pPatternlength = (uint16_t)(buf[1] | (buf[2] << 8)); + m_pPatternlength --; + if (m_pPatternlength > 16) m_pPatternlength = 16; + memcpy(m_pattern,&buf[4],m_pPatternlength); + printf("PatternLength:%d,%x\n",m_pPatternlength,buf[4]); + } + continue; + } + + if (rx_enable == 1) { + if ((buf[4] == 0x03) && (buf[5] == 0x0c)) + rx_enable = 0; + } + write(dd, &buf[3], nbytes - 3); + } + } + else if (i == dd) { + nbytes = read(dd, &buf[3], sizeof(buf) - 3); + iDataSize = nbytes - 5; +// printf("nbyte:%d, packet:%d, pattern:%x\n",nbytes, (uint16_t)(buf[6] | (buf[7] << 8)), buf[8]); + if (buf[3] == 0x2) { // ACL data + if (rx_enable) { + m_BerTotalBits = m_BerTotalBits + iDataSize * 8; + for(j=0,l=0;j<iDataSize;j++,l++) { + if (l == m_pPatternlength) l = 0; + for(k=0;k<8;k++){ + if((m_pattern[l]&(1<<k)) == (buf[8+j]&(1<<k))) + m_BerGoodBits++; + } + } + } + } + else { + if ((buf[7] == 0x5b) && (buf[8] == 0xfc)) { // Rx start CMD's event + rx_enable = 1; + m_BerTotalBits = 0; + m_BerGoodBits = 0; + } + buf[2] = 0; + buf[1] = (uint16_t)nbytes; + buf[0] = 3; + if (newfd > 0) { + sock_send(newfd, buf, nbytes+3); + usleep(2000); + } + } + } + } + } + } +exits: + if (need_raw) { + if (ioctl(dd, HCISETRAW, 0) < 0) + perror("Can't clear raw mode \n"); + } + + hci_close_dev(dd); + if (listener > 0) close(listener); + if (newfd > 0) close(newfd); + printf("Total:%d,Good:%d\n",m_BerTotalBits, m_BerGoodBits); +} + +static void sig_term(int sig) +{ + if (CtrlCBreak) return; + CtrlCBreak = TRUE; +} + +static struct { + char *cmd; + char *cmd_option; + void (*func)(int dev_id, int argc, char **argv); + char *doc; +} command[] = { + { "psreset"," ", cmd_psreset, "Download PS files and Reset Target" }, + { "reset"," ", cmd_reset, "Reset Target" }, + { "rba"," ", cmd_rba, "Read BD Address" }, + { "wba","<bdaddr> ", cmd_wba, "Write BD Address" }, + { "edutm"," ", cmd_edutm, "Enter DUT Mode" }, + { "wsm","<mode> ", cmd_wsm, "Write Scan Mode" }, + { "mb"," ", cmd_mb, "Enter Master Blaster Mode" }, + { "mbr","<address> <length> ", cmd_mbr, "Block memory read" }, + { "peek","<address> <width> ", cmd_peek, "Read Value of an Address" }, + { "poke","<address> <value> <mask> <width> ", cmd_poke, "Write Value to an Address" }, + { "cwtx","<channel number> ", cmd_cwtx, "Enter Continuous wave Tx" }, + { "cwrx","<channel number> ", cmd_cwrx, "Enter Continuous wave Rx" }, + { "rpst","<length> <id> ", cmd_rpst, "Read PS Tag" }, + { "wpst","<length> <id> <data> ", cmd_wpst, "Write PS Tag" }, + { "psr"," ", cmd_psr, "PS Reset" }, + { "setap","<storage medium> <priority>", cmd_setap, "Set Access Priority" }, + { "setam","<storage medium> <access mode>", cmd_setam, "Set Access Mode" }, + { "rpsraw","<offset> <length> ", cmd_rpsraw, "Read Raw PS" }, + { "wpsraw","<offset> <length> <data>", cmd_wpsraw, "Write Raw PS" }, + { "ssm","<disable|enable> ", cmd_ssm, "Set Sleep Mode" }, + { "dtx"," ", cmd_dtx, "Disable TX" }, + { "dump","<option> ", cmd_dump, "Display Host Controller Information" }, + { "rafh","<connection handle> ", cmd_rafh, "Read AFH channel Map" }, + { "safh","<channel classification> ", cmd_safh, "Set AFH Host Channel Classification" }, + { "wotp", "<address> <data> [length=1]", cmd_wotp, "Write Length (default 1) bytes of Data to OTP started at Address" }, + { "rotp", "<address> [length=1]", cmd_rotp, "Read Length (default 1) bytes of Data to OTP started at Address" }, + { "otp", "[dump|imp|exp|test|rpid|wpid|rvid|wvid|rba|wba|hid|cpw|pwridx|ledo] [file]; opt wba <BdAddr>", + cmd_otp, "Misc OTP operation: dump/import otp content; imp file content into otp; test otp; otp wba <BdAddr>" }, + { "plb", "[1|0]", cmd_plb, "Enable/disable PCM CODEC loopback" }, + { "psw", "[1|0] [Frequency]", cmd_psw, "Enable/disable PCM sine wave playback at frequency (0..3700)" }, + { "lert", "<rx_channel>", cmd_lert, "Put unit in LE RX mode at rx_channel (0..39)" }, + { "lett", "<tx_channel> <length> <packet_payload>", cmd_lett, "Put unit in LE TX mode at tx_channel (0..39) with packet of given length (0..37) and packet_payload" }, + { "lete", " ", cmd_lete, "End LE test" }, + { "tput-s", "[BD_Addr] [Judgment value] Logfile times data_size", cmd_tputs, "Throughput test - sender side" }, + { "tput-r", " ", cmd_tputr, "Throughput test - receiver side" }, + { "btagent","<port number>", cmd_btagent, "BT Agent for IQFact" }, + { NULL, NULL, NULL, NULL } +}; +/* + { "get_id", cmd_gid, "Get Chip Identification Number" }, +*/ +static void usage(void) +{ + int i; + + printf("btconfig - BTCONFIG Tool ver %s\n", VERSION); + printf("Usage:\n" + "\tbtconfig [options] <command> [command parameters]\n"); + printf("Options:\n" + "\t--help\tDisplay help\n" + "\t-i dev\tHCI device\n"); + printf("Commands:\n"); + for (i = 0; command[i].cmd; i++) + printf("\t%-8s %-40s\t%s\n", command[i].cmd,command[i].cmd_option,command[i].doc); + printf("\n" + "For more information on the usage of each command use:\n" + "\tbtconfig <command> --help\n" ); +} + +int main(int argc, char *argv[]) +{ + int opt, i, dev_id = -1; + bdaddr_t ba; + + while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) { + switch (opt) { + case 'i': + dev_id = hci_devid(optarg); + if (dev_id < 0) { + perror("Invalid device"); + exit(1); + } + break; + + case 'h': + default: + usage(); + exit(0); + } + } + + argc -= optind; + argv += optind; + optind = 0; + + if (argc < 1) { + usage(); + exit(0); + } + + if (dev_id != -1 && hci_devba(dev_id, &ba) < 0) { + perror("Device is not available"); + exit(1); + } + + for (i = 0; command[i].cmd; i++) { + if (strcmp(command[i].cmd, argv[0])) + continue; + command[i].func(dev_id, argc, argv); + break; + } + return 0; +} + + +// MAster BLaster fucntions +tMasterBlasterField MasterBlasterMenu[] = +{ + {"ContRxMode", "n", "toggle coNtinuous Rx", 0, ContRxModeOption, SetMasterBlasterContRxMode}, + {"ContTxMode", "c", "toggle Continuous Tx", 0, ContTxModeOption, SetMasterBlasterContTxMode}, + {"LERxMode", "q", "toggle LE Rx mode", 0, ContRxModeOption, SetMasterBlasterLERxMode}, + {"LETxMode", "w", "toggle LE Tx mode", 0, ContTxModeOption, SetMasterBlasterLETxMode}, + {"LETxPktPayload", "y", "set LE Tx packet payload", 0, LETxPktPayloadOption, SetMasterBlasterLETxPktPayload}, + {"ContTxType", "u", "toggle continUous Tx Type", Cont_Tx_Raw_1MHz, ContTxTypeOption, SetMasterBlasterContTxType}, + {"TestMode", "m", "toggle test Mode", eBRM_TestMode_TX_1010, TestModeOption, SetMasterBlasterTestMode}, + {"HopMode", "h", "toggle Hop mode", 0, HopModeOption, SetMasterBlasterHopMode}, + {"TxFreq", "t", "set Tx freq", 39, NULL, SetMasterBlasterTxFreq}, + {"RxFreq", "r", "set Rx freq", 39, NULL, SetMasterBlasterRxFreq}, + {"PacketType", "p", "toggle Packet type", TxTest_PktType_DH1, PacketTypeOption, SetMasterBlasterPacketType}, + {"DataLen", "l", "set data Length", 15, NULL, SetMasterBlasterDataLen}, + {"Power", "o", "toggle pOwer", 9, NULL, SetMasterBlasterPower}, + {"BdAddr", "a", "set bdAddr", 0, NULL, SetMasterBlasterBdAddr}, + {"SetBERType", "k", "set BER type", eBRM_BERMode_ALL_DATA, BERPacketTypeOption,SetMasterBlasterBERType}, + {"GetBER", "g", "get BER type", 0, NULL, SetMasterBlasterNothing}, + {"EnableRxTest", "d", "Enable rx test mode", 0, NULL, SetMasterBlasterNothing}, + {"EnableTxTest", "e", "Enable tx test mode", 0, NULL, SetMasterBlasterNothing}, + {"EnableTest", "j", "Start test mode", 0, NULL, SetMasterBlasterNothing}, + {"StopTest", "s", "Stop test mode", 0, NULL, SetMasterBlasterNothing}, + {"Exit", "x", "eXit", 0, NULL, SetMasterBlasterNothing}, + {"ExitWithoutReset", "b", "Exit without reset", 0, NULL, SetMasterBlasterNothing}, +}; + +tPsSysCfgTransmitPowerControlTable TpcTable; + +//---------------------------------------------------------------------------- + +void InitMasterBlaster (tBRM_Control_packet *MasterBlaster, bdaddr_t *BdAddr, UCHAR *SkipRxSlot) +{ + *SkipRxSlot = 0x01; + MasterBlaster->testCtrl.Mode = MasterBlasterMenu[TM].Default; + MasterBlaster->testCtrl.HopMode = MasterBlasterMenu[HM].Default; + MasterBlaster->testCtrl.Packet = MasterBlasterMenu[PT].Default; + MasterBlaster->testCtrl.TxFreq = MasterBlasterMenu[TF].Default; + MasterBlaster->testCtrl.RxFreq = MasterBlasterMenu[RF].Default; + MasterBlaster->testCtrl.Power = MasterBlasterMenu[PO].Default; + MasterBlaster->testCtrl.DataLen = MasterBlasterMenu[DL].Default; + MasterBlaster->ContTxMode = MasterBlasterMenu[CT].Default; + MasterBlaster->ContTxType = MasterBlasterMenu[CX].Default; + MasterBlaster->ContRxMode = MasterBlasterMenu[CR].Default; + MasterBlaster->BERType = MasterBlasterMenu[SB].Default; + MasterBlaster->LERxMode = MasterBlasterMenu[LR].Default; + MasterBlaster->LETxMode = MasterBlasterMenu[LT].Default; + MasterBlaster->LETxParms.PktPayload = MasterBlasterMenu[LTM].Default; + memcpy(MasterBlaster->bdaddr,&BdAddr->b[0],6); + + TpcTable.NumOfEntries = 0; +} + +//---------------------------------------------------------------------------- + +int CheckField (tBRM_Control_packet MasterBlaster, char *FieldAlias) +{ + if (((!strncmp(FieldAlias,MasterBlasterMenu[HM].Alias,1)) && MasterBlaster.ContTxMode) || + (((!strncmp(FieldAlias,MasterBlasterMenu[TF].Alias,1)) || (!strncmp(FieldAlias,MasterBlasterMenu[RF].Alias,1))) && MasterBlaster.testCtrl.HopMode == 1) || + ((!strncmp(FieldAlias,MasterBlasterMenu[CX].Alias,1)) && MasterBlaster.ContTxMode == 0)) + { + return INVALID_MASTERBLASTER_FIELD; + } + unsigned int i; + for (i = 0; i < sizeof(MasterBlasterMenu)/sizeof(tMasterBlasterField); ++i) + { + if (!strncmp(FieldAlias,MasterBlasterMenu[i].Alias,1)) + { + return i; + } + } + + return INVALID_MASTERBLASTER_FIELD; +} + +//---------------------------------------------------------------------------- + +int GetTestModeOptionIndex (int Value) +{ + unsigned int i; + for (i = 0; i < sizeof(TestModeOption)/sizeof(tMasterBlasterOption); ++i) + { + if (Value == TestModeOption[i].Value) + { + return i; + } + } + // assert (0); + return -1; +} + +//---------------------------------------------------------------------------- + +int GetPacketTypeOptionIndex (int Value) +{ + unsigned int i; + for (i = 0; i < sizeof(PacketTypeOption)/sizeof(tMasterBlasterOption); ++i) + { + if (Value == PacketTypeOption[i].Value) + { + return i; + } + } + //assert (0); + return -1; +} + +//---------------------------------------------------------------------------- + +void PrintMasterBlasterMenu(tBRM_Control_packet *MasterBlaster) +{ + unsigned int i; + printf ("\n---------- Master Blaster Mode ----------\n\n"); + for (i = 0; i < sizeof(MasterBlasterMenu)/sizeof(tMasterBlasterField); ++i) + { + if (((i == HM || i == RF) && (MasterBlaster->ContTxMode == ENABLE)) || + ((i == TF || i == RF) && (MasterBlaster->testCtrl.HopMode == 1)) || + ((i == CX) && (MasterBlaster->ContTxMode == DISABLE)) || + ((i == CX || i == HM || i == TF || i == PT || i == DL || i == PO || i == BA) && + (MasterBlaster->ContRxMode == ENABLE))) + { + continue; + } + + printf ("\t%s - %s\n", MasterBlasterMenu[i].Alias, MasterBlasterMenu[i].Usage); + } + printf ("\n-----------------------------------------\n\n"); + + char BdAddr[18]; + //strcpy(MasterBlaster.bdaddr,BdAddr); + + printf ("ContRxMode: %s\n", ContRxModeOption[MasterBlaster->ContRxMode].Name); + printf ("ContTxMode: %s\n", ContTxModeOption[MasterBlaster->ContTxMode].Name); + printf ("LERxMode: %s\n", ContTxModeOption[MasterBlaster->LERxMode].Name); + printf ("LETxMode: %s\n", ContTxModeOption[MasterBlaster->LETxMode].Name); + + // LE Rx mode + if (MasterBlaster->LERxMode == ENABLE) + { + if (MasterBlaster->testCtrl.RxFreq > MB_MAX_FREQUENCY_LE) + MasterBlaster->testCtrl.RxFreq = MB_MAX_FREQUENCY_LE; + printf("RxFreq: %d\n", MasterBlaster->testCtrl.RxFreq); + } + // LE Tx mode + if (MasterBlaster->LETxMode == ENABLE) + { + if (MasterBlaster->testCtrl.DataLen > MB_MAX_DATALEN_LE) + MasterBlaster->testCtrl.DataLen = MB_MAX_DATALEN_LE; + printf("TxFreq: %d\n", MasterBlaster->testCtrl.TxFreq); + printf("DataLen: %d\n", MasterBlaster->testCtrl.DataLen); + printf("PktPayload: %s\n", LETxPktPayloadOption[MasterBlaster->LETxParms.PktPayload].Name); + } + // Continous Rx mode + else if (MasterBlaster->ContRxMode == ENABLE) + { + printf ("BER Type: %s\n",BERPacketTypeOption[MasterBlaster->BERType].Name); + printf ("RxFreq: %d\n", MasterBlaster->testCtrl.RxFreq); + } + // Continous Tx mode and Tx test mode + else + { + printf ("BER Type: %s\n",BERPacketTypeOption[MasterBlaster->BERType].Name); + if (MasterBlaster->ContTxMode == ENABLE) + { + printf ("ContTxType: %s\n", ContTxTypeOption[MasterBlaster->ContTxType].Name); + if (ContTxTypeOption[MasterBlaster->ContTxType].Value != CW_Single_Tone) + printf ("TestMode: %s\n", TestModeOption[GetTestModeOptionIndex(MasterBlaster->testCtrl.Mode)].Name); + printf ("TxFreq: %d\n", MasterBlaster->testCtrl.TxFreq); + } + else + { + printf ("TestMode: %s\n", TestModeOption[GetTestModeOptionIndex(MasterBlaster->testCtrl.Mode)].Name); + printf ("HopMode: %s\n", HopModeOption[MasterBlaster->testCtrl.HopMode].Name); + + if (MasterBlaster->testCtrl.HopMode == 0) + { + printf ("TxFreq: %d\n", MasterBlaster->testCtrl.TxFreq); + printf ("RxFreq: %d\n", MasterBlaster->testCtrl.RxFreq); + } + } + if (TpcTable.NumOfEntries > 0) + { + printf ("Power: Step = %d/%d; Level = %d dBm\n", MasterBlaster->testCtrl.Power+1, + TpcTable.NumOfEntries, TpcTable.t[MasterBlaster->testCtrl.Power].TxPowerLevel); + } + else + { + printf ("Power: Step = Max; Level = N/A\n"); + } + if ((MasterBlaster->ContTxMode == ENABLE && ContTxTypeOption[MasterBlaster->ContTxType].Value == Cont_Tx_Regular) || + (MasterBlaster->ContTxMode == DISABLE)) + { + printf ("PacketType: %s\n", PacketTypeOption[GetPacketTypeOptionIndex(MasterBlaster->testCtrl.Packet)].Name); + printf ("DataLen: %d\n", MasterBlaster->testCtrl.DataLen); + } + if (ContTxTypeOption[MasterBlaster->ContTxType].Value != CW_Single_Tone) {//for single tone, no bdaddr + ba2str((const bdaddr_t *)MasterBlaster->bdaddr, BdAddr); + printf ("BdAddr: 0x%s\n\n",BdAddr); + } + } + printf ("\nmb>\n"); +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterTestMode(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = (int)MasterBlaster->testCtrl.Mode; + + if (ToggleOption (&Value, Option, TestModeOption, + sizeof(TestModeOption)/sizeof(tMasterBlasterOption), TM,1)) + { + MasterBlaster->testCtrl.Mode = (UCHAR)Value; + // Enable continous Tx should disable continous Rx + MasterBlaster->ContRxMode = DISABLE; + MasterBlaster->ContTxMode = DISABLE; + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterHopMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = (int)MasterBlaster->testCtrl.HopMode; + + if (ToggleOption (&Value, Option, HopModeOption, + sizeof(HopModeOption)/sizeof(tMasterBlasterOption), HM,1)) + { + MasterBlaster->testCtrl.HopMode = (UCHAR)Value; + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterTxFreq (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + //char Buffer[20]; + tMasterBlasterOption NewValue; + int LoopCount = 4; + int Value = (int)MasterBlaster->testCtrl.TxFreq; + int MaxFreq = LEMode ? MB_MAX_FREQUENCY_LE : MB_MAX_FREQUENCY; + int MinFreq = LEMode ? MB_MIN_FREQUENCY_LE : MB_MIN_FREQUENCY; + + while (--LoopCount > 0) + { + printf ("\n Enter Tx frequency (%d..%d): ", MinFreq, MaxFreq); + scanf("%d",&NewValue.Value); +// fgets(NewValue,3,stdin); + if (MinMaxOption (&Value, &NewValue, MinFreq, MaxFreq)) + { + MasterBlaster->testCtrl.TxFreq = (UCHAR)Value; + return TRUE; + } + else if (LoopCount > 1) + { + printf ("\n ERROR ---> Invalid Tx frequency.\n"); + } + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterRxFreq (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + tMasterBlasterOption NewValue; + int LoopCount = 4; + int Value = (int)MasterBlaster->testCtrl.RxFreq; + int MaxFreq = LEMode ? MB_MAX_FREQUENCY_LE : MB_MAX_FREQUENCY; + int MinFreq = LEMode ? MB_MIN_FREQUENCY_LE : MB_MIN_FREQUENCY; + + while (--LoopCount > 0) + { + printf ("\n Enter Rx frequency (%d..%d): ", MinFreq, MaxFreq); + scanf("%d",&NewValue.Value); + if (MinMaxOption (&Value, &NewValue, MinFreq, MaxFreq)) + { + MasterBlaster->testCtrl.RxFreq = (UCHAR)Value; + return TRUE; + } + else if (LoopCount > 1) + { + printf ("\n ERROR ---> Invalid Rx frequency.\n"); + } + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterPacketType (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = (int)MasterBlaster->testCtrl.Packet; + + if (ToggleOption (&Value, Option, PacketTypeOption, + sizeof(PacketTypeOption)/sizeof(tMasterBlasterOption), PT,1)) + { + MasterBlaster->testCtrl.Packet = (UCHAR)Value; + MasterBlaster->testCtrl.DataLen = MaxDataLenOption[GetPacketTypeOptionIndex(Value)]; + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterDataLen (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + tMasterBlasterOption NewValue; + int LoopCount = 4; + int MaxLen = LEMode ? MB_MAX_DATALEN_LE : MB_MAX_DATALEN; + int MinLen = LEMode ? MB_MIN_DATALEN_LE : MB_MIN_DATALEN; + + while (--LoopCount > 0) + { + printf ("\n Enter data length (%d..%d): ", MinLen, MaxLen); + scanf("%d",&NewValue.Value); + if (MinMaxOption (&MasterBlaster->testCtrl.DataLen, &NewValue, MinLen, MaxLen)) + { + return TRUE; + } + else if (LoopCount > 1) + { + printf ("\n ERROR ---> Invalid data length.\n"); + } + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterPower (tBRM_Control_packet *MasterBlaster, char *Option) +{ + if (TpcTable.NumOfEntries > MAX_TRANSMIT_POWER_CONTROL_ENTRIES) + { + printf ("\nNumber of entries in TPC table exceeds the limit.\n"); + sleep(3); + return TRUE; + } + + if (TpcTable.NumOfEntries == 0) + { + printf ("\nThere is no entry in TPC table.\n"); + sleep(3); + return TRUE; + } + + int Value = (int)MasterBlaster->testCtrl.Power; + + if (ToggleMinMaxOption (&Value, Option, PO, 0, TpcTable.NumOfEntries-1,1)) + { + MasterBlaster->testCtrl.Power = (UCHAR)Value; + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterBdAddr (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + char Buffer[20]; + bdaddr_t bdaddr; + + printf ("\n Enter BdAddr: "); +// gets(Buffer); + scanf("%s",Buffer); + str2ba(Buffer,&bdaddr); + strncpy(MasterBlaster->bdaddr,bdaddr.b,6); + return TRUE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterContTxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = (int)MasterBlaster->ContTxMode; + + if (ToggleOption (&Value, Option, ContTxModeOption, + sizeof(ContTxModeOption)/sizeof(tMasterBlasterOption), CT,1)) + { + MasterBlaster->ContTxMode = (UCHAR)Value; + if (MasterBlaster->ContTxMode == ENABLE) + { + // Enable continous Tx should disable continous Rx + MasterBlaster->ContRxMode = DISABLE; + MasterBlaster->LERxMode = DISABLE; + MasterBlaster->LETxMode = DISABLE; + LEMode = FALSE; + } + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterContTxType (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = (int)MasterBlaster->ContTxType; + + if (ToggleOption (&Value, Option, ContTxTypeOption, + sizeof(ContTxTypeOption)/sizeof(tMasterBlasterOption), CX,1)) + { + MasterBlaster->ContTxType = (UCHAR)Value; + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterLERxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = MasterBlaster->LERxMode; + + if (ToggleOption (&Value, Option, ContRxModeOption, + sizeof(ContRxModeOption)/sizeof(tMasterBlasterOption), LR, 1)) + { + MasterBlaster->LERxMode = (UCHAR)Value; + if (MasterBlaster->LERxMode == ENABLE) + { + /* Enable continous Tx should disable other modes */ + MasterBlaster->LETxMode = DISABLE; + MasterBlaster->ContTxMode = DISABLE; + MasterBlaster->ContRxMode = DISABLE; + if (MasterBlaster->testCtrl.RxFreq > 39) + { + MasterBlaster->testCtrl.RxFreq = 39; + } + LEMode = TRUE; + } + else + { + LEMode = FALSE; + } + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterLETxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = MasterBlaster->LETxMode; + + if (ToggleOption (&Value, Option, ContTxModeOption, + sizeof(ContTxModeOption)/sizeof(tMasterBlasterOption), LT, 1)) + { + MasterBlaster->LETxMode = (UCHAR)Value; + if (MasterBlaster->LETxMode == ENABLE) + { + /* Enable continous Tx should disable other modes */ + MasterBlaster->LERxMode = DISABLE; + MasterBlaster->ContTxMode = DISABLE; + MasterBlaster->ContRxMode = DISABLE; + if (MasterBlaster->testCtrl.TxFreq > MB_MAX_FREQUENCY_LE) + { + MasterBlaster->testCtrl.TxFreq = 39; + } + LEMode = TRUE; + } + else + { + LEMode = FALSE; + } + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterLETxPktPayload(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = MasterBlaster->LETxParms.PktPayload; + + if (ToggleOption(&Value, Option, LETxPktPayloadOption, + sizeof(LETxPktPayloadOption)/sizeof(tMasterBlasterOption), LTM, 1)) + { + MasterBlaster->LETxParms.PktPayload = (UCHAR)Value; + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterContRxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = (int)MasterBlaster->ContRxMode; + printf("\n N op\n"); + if (ToggleOption (&Value, Option, ContRxModeOption, + sizeof(ContRxModeOption)/sizeof(tMasterBlasterOption), CR,1)) + { + MasterBlaster->ContRxMode = (UCHAR)Value; + if (MasterBlaster->ContRxMode == ENABLE) + { + // Enable continous Tx should disable continous Rx + MasterBlaster->ContTxMode = DISABLE; + MasterBlaster->LERxMode = DISABLE; + MasterBlaster->LETxMode = DISABLE; + LEMode = FALSE; + } + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- +int SetMasterBlasterBERType (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + int Value = (int)MasterBlaster->BERType; + if (ToggleOption (&Value, Option, BERPacketTypeOption, + sizeof(BERPacketTypeOption)/sizeof(tMasterBlasterOption), SB, 1)) + { + MasterBlaster->BERType = (UCHAR)Value; + return TRUE; + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int SetMasterBlasterNothing (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option) +{ + UNUSED(MasterBlaster); + UNUSED(Option); + + return TRUE; +} + +//---------------------------------------------------------------------------- + +int ToggleOption (int *Value, tMasterBlasterOption *Option, tMasterBlasterOption *OptionArray, + int Size, int FieldID, int Step) +{ + char Opt = Option->Name[0]; + + int Backward = ((Opt - 'A' + 'a') == MasterBlasterMenu[FieldID].Alias[0]); + int i; + for (i = 0; i < Size; ++i) + { + if (*Value == OptionArray[i].Value) + { + if (Backward) + { + i = ((i - Step) < 0) ? (Size - Step + i) : (i - Step); + } + else + { + i = (i + Step) % Size; + } + *Value = OptionArray[i].Value; + return TRUE; + } + } + return FALSE; +} + +//---------------------------------------------------------------------------- + +int MinMaxOption (int *Value, tMasterBlasterOption *Option, int Min, int Max) +{ + int NewValue = Option->Value; + + if (NewValue < Min || NewValue > Max) + { + return FALSE; + } + *Value = NewValue; + return TRUE; +} + +//---------------------------------------------------------------------------- + +int ToggleMinMaxOption (int *Value, char *Option, int FieldID, int Min, int Max, int Step) +{ + char Opt = *Option; + int Backward = ((Opt - 'A' + 'a') == MasterBlasterMenu[FieldID].Alias[0]); + + if (Backward) + { + *Value = ((*Value - Step) < Min) ? (Max + 1 - (Step - (*Value - Min))) : (*Value - Step); + } + else + { + *Value = ((*Value + Step) > Max) ? (Min + (Step - (Max + 1 - *Value))) : (*Value + Step); + } + return TRUE; + +} + +//----------------------------------------------------------------------------
diff --git a/btconfig.h b/btconfig.h new file mode 100755 index 0000000..13de972 --- /dev/null +++ b/btconfig.h
@@ -0,0 +1,267 @@ +/* + * Copyright (c) 2008-2009 Atheros 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 version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * <Header File> + * + * <btconfig.h> + */ + +#ifndef _BTCONFIG_H_ +#define _BTCONFIG_H_ + +#define VERSION "1.05" +#define PS_ASIC_FILENAME "/etc/firmware/ar3k/1020200/PS_ASIC.pst" +#define PS_FPGA_FILENAME "/etc/firmware/ar3k/1020200/PS_FPGA.pst" +#define TESTPATCH_FILENAME "/etc/firmware/ar3k/1020200/Testpatch.txt" +#define PATCH_FILENAME "/etc/firmware/ar3k/1020200/RamPatch.txt" + +#define TRUE 1 +#define FALSE 0 +#define LINE_SIZE_MAX 3000 +#define BD_ADDR_SIZE 6 +#define BD_ADDR_PSTAG 1 +#define WRITE_PATCH 8 +#define ENABLE_PATCH 11 +#define PS_RESET 2 +#define PS_READ 0 +#define PS_WRITE 1 +#define PS_READ_RAW 3 +#define PS_WRITE_RAW 4 +#define PS_GET_LENGTH 5 +#define PS_SET_ACCESS_MODE 6 +#define PS_SET_ACCESS_PRIORITY 7 +#define PS_WRITE 1 +#define PS_DYNMEM_OVERRIDE 10 +#define PS_VERIFY_CRC 9 +#define CHANGE_BDADDR 15 +#define PS_COMMAND_HEADER 4 +#define HCI_EVENT_SIZE 7 +#define PS_RETRY_COUNT 3 +#define RAM_PS_REGION (1<<0) +#define RAM_PATCH_REGION (1<<1) +#define RAM_DYN_MEM_REGION (1<<2) +#define RAMPS_MAX_PS_DATA_PER_TAG 244 +#define RAMPS_MAX_PS_TAGS_PER_FILE 50 +#define PSTAG_RF_TEST_BLOCK_START (300) +#define PSTAG_SYSTEM_BLOCK_START (1) +#define BT_SOC_INIT_TOOL_START_MAGIC_WORD 0xB1B1 +#define PSTAG_RF_PARAM_TABLE0 (PSTAG_RF_TEST_BLOCK_START+0) +#define PSTAG_SYSCFG_PARAM_TABLE0 (PSTAG_SYSTEM_BLOCK_START+18) +#define PATCH_MAX_LEN 20000 +#define DYN_MEM_MAX_LEN 40 +#define SKIP_BLANKS(str) while (*str == ' ') str++ +#define MAX_RADIO_CFG_TABLE_SIZE 1000 +#define MAX_BYTE_LENGTH 244 +#define DEBUG_EVENT_TYPE_PS 0x02 +#define DEBUG_EVENT_TYPE_MEMBLK 0x03 +#define HCI_EVENT_HEADER_SIZE 0x03 +#define HI_MAGIC_NUMBER ((const unsigned short int) 0xFADE) +#define HI_VERSION (0x0300) //Version 3.0 +#define EEPROM_CONFIG 0x00020C00 +#define FPGA_REGISTER 0x4FFC + +// Vendor specific command OCF +#define OCF_PS 0x000B +#define OCF_MEMOP 0x0014 +#define OGF_TEST_CMD 0x06 +#define OCF_HOST_INTEREST 0x000A +#define OCF_CONT_TX_TESTER 0x0023 +#define OCF_TX_TESTER 0x001B +#define OCF_SLEEP_MODE 0x0004 +#define OCF_READ_MEMORY 0x0005 +#define OCF_WRITE_MEMORY 0x0006 +#define OCF_DISABLE_TX 0x002D +#define OCF_TEST_MODE_SEQN_TRACKING 0x0018 +#define OCF_READ_VERSION 0x001E +#define OCF_AUDIO_CMD 0x0013 +#define OCF_GET_BERTYPE 0x005C +#define OCF_RX_TESTER 0x005B + +#define UCHAR unsigned char +#define BOOL unsigned short +#define UINT16 unsigned short int +#define UINT32 unsigned int +#define SINT16 signed short int +#define UINT8 unsigned char +#define SINT8 signed char + +typedef struct tPsTagEntry +{ + int TagId; + UCHAR TagLen; + UCHAR TagData[RAMPS_MAX_PS_DATA_PER_TAG]; +} tPsTagEntry, *tpPsTagEntry; + +typedef struct tRamPatch +{ + int Len; + UCHAR Data[PATCH_MAX_LEN]; +} tRamPatch, *ptRamPatch; + +typedef struct tRamDynMemOverride +{ + int Len; + UCHAR Data[DYN_MEM_MAX_LEN]; +} tRamDynMemOverride, *ptRamDynMemOverride; + +tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE]; +tRamPatch RamPatch[50]; +tRamDynMemOverride RamDynMemOverride; + +enum MB_FILEFORMAT { + MB_FILEFORMAT_PS, + MB_FILEFORMAT_PATCH, + MB_FILEFORMAT_DY, +}; +enum RamPsSection +{ + RAM_PS_SECTION, + RAM_PATCH_SECTION, + RAM_DYN_MEM_SECTION +}; + +enum eType { + eHex, + edecimal, +}; + +struct ST_PS_DATA_FORMAT { + enum eType eDataType; + BOOL bIsArray; +}; +#define CONV_DEC_DIGIT_TO_VALUE(c) ((c) - '0') +#define IS_HEX(c) (IS_BETWEEN((c), '0', '9') || IS_BETWEEN((c), 'a', 'f') || IS_BETWEEN((c), 'A', 'F')) +#define IS_BETWEEN(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper))) +#define IS_DIGIT(c) (IS_BETWEEN((c), '0', '9')) +#define CONV_HEX_DIGIT_TO_VALUE(c) (IS_DIGIT(c) ? ((c) - '0') : (IS_BETWEEN((c), 'A', 'Z') ? ((c) - 'A' + 10) : ((c) - 'a' + 10))) +#define BYTES_OF_PS_DATA_PER_LINE 16 +struct ST_READ_STATUS { + unsigned uTagID; + unsigned uSection; + unsigned uLineCount; + unsigned uCharCount; + unsigned uByteCount; +}; + +//DUT MODE related +#define MC_BCAM_COMPARE_ADDRESS 0x00008080 +#define HCI_3_PATCH_SPACE_LENGTH_1 (0x80) +#define HCI_3_PATCH_SPACE_LENGTH_2 (0x279C) +#define MEM_BLK_DATA_MAX (244) +#define MC_BCAM_VALID_ADDRESS 0x00008100 + +//Audio stat + +typedef struct tAudio_Stat { + UINT16 RxSilenceInsert; + UINT16 RxAirPktDump; + UINT16 RxCmplt; + UINT16 TxCmplt; + UINT16 MaxPLCGenInterval; + UINT16 RxAirPktStatusGood; + UINT16 RxAirPktStatusError; + UINT16 RxAirPktStatusLost; + UINT16 RxAirPktStatusPartial; + SINT16 SampleMin; + SINT16 SampleMax; + UINT16 SampleCounter; + UINT16 SampleStatEnable; +} tAudioStat; + +//DMA stats + +typedef struct tBRM_Stats { + // DMA Stats + UINT32 DmaIntrs; + + // Voice Stats + UINT16 VoiceTxDmaIntrs; + UINT16 VoiceTxErrorIntrs; + UINT16 VoiceTxDmaErrorIntrs; + UINT16 VoiceTxPktAvail; + UINT16 VoiceTxPktDumped; + UINT16 VoiceTxDmaSilenceInserts; + + UINT16 VoiceRxDmaIntrs; + UINT16 VoiceRxErrorIntrs; + UINT16 VoiceRxGoodPkts; + UINT16 VoiceRxErrCrc; + UINT16 VoiceRxErrUnderOverFlow; + UINT16 VoiceRxPktDumped; + + UINT16 VoiceTxReapOnError; + UINT16 VoiceRxReapOnError; + UINT16 VoiceSchedulingError; + UINT16 SchedOnVoiceError; + + UINT16 Temp1; + UINT16 Temp2; + + // Control Stats + UINT16 ErrWrongLlid; + UINT16 ErrL2CapLen; + UINT16 ErrUnderOverFlow; + UINT16 RxBufferDumped; + UINT16 ErrWrongLmpPktType; + UINT16 ErrWrongL2CapPktType; + UINT16 HecFailPkts; + UINT16 IgnoredPkts; + UINT16 CrcFailPkts; + UINT16 HwErrRxOverflow; + + UINT16 CtrlErrNoLmpBufs; + + // ACL Stats + UINT16 DataTxBuffers; + UINT16 DataRxBuffers; + UINT16 DataRxErrCrc; + UINT16 DataRxPktDumped; + UINT16 LmpTxBuffers; + UINT16 LmpRxBuffers; + UINT16 ForceOverQosJob; + + // Sniff Stats + UINT16 SniffSchedulingError; + UINT16 SniffIntervalNoCorr; + + // Test Mode Stats + UINT16 TestModeDroppedTxPkts; + UINT16 TestModeDroppedLmps; + + // Error Stats + UINT16 TimePassedIntrs; + UINT16 NoCommandIntrs; + +} tBRM_Stats; + +typedef struct tSYSUTIL_ChipId { + char *pName; + UINT32 HwRev; +} tSYSUTIL_ChipId; + +typedef struct tSU_RevInfo { + tSYSUTIL_ChipId *pChipId; + tSYSUTIL_ChipId *pChipRadioId; + UINT32 ChipRadioId; + UINT32 SubRadioId; + UINT32 RomVersion; + UINT32 RomBuildNumber; + UINT32 BuildVersion; + UINT32 BuildNumber; + UINT16 RadioFormat; + UINT16 RadioContent; + UINT16 SysCfgFormat; + UINT16 SysCfgContent; + UINT8 ProductId; +} tSU_RevInfo; + +#endif
diff --git a/btconfig.tar.bz2 b/btconfig.tar.bz2 new file mode 100644 index 0000000..129811c --- /dev/null +++ b/btconfig.tar.bz2 Binary files differ
diff --git a/build_btconfig.sh b/build_btconfig.sh new file mode 100755 index 0000000..2885118 --- /dev/null +++ b/build_btconfig.sh
@@ -0,0 +1,10 @@ +source ../../../../a5s_linux_sdk/ambarella/build/env/CodeSourcery.env +PATH=$PATH:$ARM_LINUX_TOOLCHAIN_DIR/bin + +make -f Makefile + +rm -rf fakeroot +mkdir -p fakeroot/usr/bin +cp -d btconfig fakeroot/usr/bin + +tar cjfv btconfig.tar.bz2 fakeroot
diff --git a/compat/arc4random.c b/compat/arc4random.c new file mode 100755 index 0000000..29528ce --- /dev/null +++ b/compat/arc4random.c
@@ -0,0 +1,158 @@ +/* + * Arc4 random number generator for OpenBSD. + * Copyright 1996 David Mazieres <dm@lcs.mit.edu>. + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + */ + +/* + * This code is derived from section 17.1 of Applied Cryptography, + * second edition, which describes a stream cipher allegedly + * compatible with RSA Labs "RC4" cipher (the actual description of + * which is a trade secret). The same algorithm is used as a stream + * cipher called "arcfour" in Tatu Ylonen's ssh package. + * + * Here the stream cipher has been modified always to include the time + * when initializing the state. That makes it impossible to + * regenerate the same random sequence twice, so this can't be used + * for encryption, but will generate good random numbers. + * + * RC4 is a registered trademark of RSA Laboratories. + */ + +#include <sys/time.h> + +#include <fcntl.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> + +#include "arc4random.h" + +struct arc4_stream { + uint8_t i; + uint8_t j; + uint8_t s[256]; +}; + +static int rs_initialized; +static struct arc4_stream rs; +static int arc4_count; + +static void +arc4_init(struct arc4_stream *as) +{ + int n; + + for (n = 0; n < 256; n++) + as->s[n] = n; + as->i = 0; + as->j = 0; +} + +static void +arc4_addrandom(struct arc4_stream *as, unsigned char *dat, int datlen) +{ + int n; + uint8_t si; + + as->i--; + for (n = 0; n < 256; n++) { + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si + dat[n % datlen]); + as->s[as->i] = as->s[as->j]; + as->s[as->j] = si; + } + as->j = as->i; +} + +static uint8_t +arc4_getbyte(struct arc4_stream *as) +{ + uint8_t si, sj; + + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si); + sj = as->s[as->j]; + as->s[as->i] = sj; + as->s[as->j] = si; + return (as->s[(si + sj) & 0xff]); +} + +static uint32_t +arc4_getword(struct arc4_stream *as) +{ + uint32_t val; + + val = arc4_getbyte(as) << 24; + val |= arc4_getbyte(as) << 16; + val |= arc4_getbyte(as) << 8; + val |= arc4_getbyte(as); + return val; +} + +static void +arc4_stir(struct arc4_stream *as) +{ + int fd; + struct { + struct timeval tv; + unsigned int rnd[(128 - sizeof(struct timeval)) / + sizeof(unsigned int)]; + } rdat; + int n; + + gettimeofday(&rdat.tv, NULL); + fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + n = read(fd, rdat.rnd, sizeof(rdat.rnd)); + close(fd); + } + + /* fd < 0? Ah, what the heck. We'll just take + * whatever was on the stack... */ + arc4_addrandom(as, (void *) &rdat, sizeof(rdat)); + + /* + * Throw away the first N words of output, as suggested in the + * paper "Weaknesses in the Key Scheduling Algorithm of RC4" + * by Fluher, Mantin, and Shamir. (N = 256 in our case.) + */ + for (n = 0; n < 256 * 4; n++) + arc4_getbyte(as); + arc4_count = 1600000; +} + +void +arc4random_stir() +{ + + if (!rs_initialized) { + arc4_init(&rs); + rs_initialized = 1; + } + arc4_stir(&rs); +} + +void +arc4random_addrandom(unsigned char *dat, int datlen) +{ + + if (!rs_initialized) + arc4random_stir(); + arc4_addrandom(&rs, dat, datlen); +} + +uint32_t +arc4random() +{ + + arc4_count -= 4; + if (!rs_initialized || arc4_count <= 0) + arc4random_stir(); + return arc4_getword(&rs); +}
diff --git a/compat/arc4random.h b/compat/arc4random.h new file mode 100755 index 0000000..6724cef --- /dev/null +++ b/compat/arc4random.h
@@ -0,0 +1,36 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2010 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ARC4RANDOM_H +#define ARC4RANDOM_H + +#include <stdint.h> + +void arc4random_stir(void); +void arc4random_addrandom(unsigned char *, int); +uint32_t arc4random(void); +#endif
diff --git a/compat/closefrom.c b/compat/closefrom.c new file mode 100755 index 0000000..5c02005 --- /dev/null +++ b/compat/closefrom.c
@@ -0,0 +1,42 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <unistd.h> + +#include "closefrom.h" + +int +closefrom(int fd) +{ + int max = getdtablesize(); + int i; + int r = 0; + + for (i = fd; i < max; i++) + r += close(i); + return r; +}
diff --git a/compat/closefrom.h b/compat/closefrom.h new file mode 100755 index 0000000..6b8709b --- /dev/null +++ b/compat/closefrom.h
@@ -0,0 +1,31 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CLOSEFROM_H +#define CLOSEFROM_H +int closefrom(int); +#endif
diff --git a/compat/getline.c b/compat/getline.c new file mode 100755 index 0000000..79fcf1e --- /dev/null +++ b/compat/getline.c
@@ -0,0 +1,75 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "getline.h" + +/* Redefine a small buffer for our simple text config files */ +#undef BUFSIZ +#define BUFSIZ 128 + +ssize_t +getline(char ** __restrict buf, size_t * __restrict buflen, + FILE * __restrict fp) +{ + size_t bytes, newlen; + char *newbuf, *p; + + if (buf == NULL || buflen == NULL) { + errno = EINVAL; + return -1; + } + if (*buf == NULL) + *buflen = 0; + + bytes = 0; + do { + if (feof(fp)) + break; + if (*buf == NULL || bytes != 0) { + newlen = *buflen + BUFSIZ; + newbuf = realloc(*buf, newlen); + if (newbuf == NULL) + return -1; + *buf = newbuf; + *buflen = newlen; + } + p = *buf + bytes; + memset(p, 0, BUFSIZ); + if (fgets(p, BUFSIZ, fp) == NULL) + break; + bytes += strlen(p); + } while (bytes == 0 || *(*buf + (bytes - 1)) != '\n'); + if (bytes == 0) + return -1; + return bytes; +}
diff --git a/compat/getline.h b/compat/getline.h new file mode 100755 index 0000000..be3b57c --- /dev/null +++ b/compat/getline.h
@@ -0,0 +1,36 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef GETLINE_H +#define GETLINE_H + +#include <sys/types.h> +#include <stdio.h> + +ssize_t getline(char ** __restrict buf, size_t * __restrict buflen, + FILE * __restrict fp); +#endif
diff --git a/compat/linkaddr.c b/compat/linkaddr.c new file mode 100755 index 0000000..8c7a6c8 --- /dev/null +++ b/compat/linkaddr.c
@@ -0,0 +1,120 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <net/if_dl.h> + +#include <string.h> + +/* States*/ +#define NAMING 0 +#define GOTONE 1 +#define GOTTWO 2 +#define RESET 3 +/* Inputs */ +#define DIGIT (4*0) +#define END (4*1) +#define DELIM (4*2) +#define LETTER (4*3) + +void +link_addr(addr, sdl) + const char *addr; + struct sockaddr_dl *sdl; +{ + char *cp = sdl->sdl_data; + char *cplim = sdl->sdl_len + (char *)(void *)sdl; + int byte = 0, state = NAMING; + int newaddr = 0; + + (void)memset(&sdl->sdl_family, 0, (size_t)sdl->sdl_len - 1); + sdl->sdl_family = AF_LINK; + do { + state &= ~LETTER; + if ((*addr >= '0') && (*addr <= '9')) { + newaddr = *addr - '0'; + } else if ((*addr >= 'a') && (*addr <= 'f')) { + newaddr = *addr - 'a' + 10; + } else if ((*addr >= 'A') && (*addr <= 'F')) { + newaddr = *addr - 'A' + 10; + } else if (*addr == 0) { + state |= END; + } else if (state == NAMING && + (((*addr >= 'A') && (*addr <= 'Z')) || + ((*addr >= 'a') && (*addr <= 'z')))) + state |= LETTER; + else + state |= DELIM; + addr++; + switch (state /* | INPUT */) { + case NAMING | DIGIT: + case NAMING | LETTER: + *cp++ = addr[-1]; + continue; + case NAMING | DELIM: + state = RESET; + sdl->sdl_nlen = cp - sdl->sdl_data; + continue; + case GOTTWO | DIGIT: + *cp++ = byte; + /* FALLTHROUGH */ + case RESET | DIGIT: + state = GOTONE; + byte = newaddr; + continue; + case GOTONE | DIGIT: + state = GOTTWO; + byte = newaddr + (byte << 4); + continue; + default: /* | DELIM */ + state = RESET; + *cp++ = byte; + byte = 0; + continue; + case GOTONE | END: + case GOTTWO | END: + *cp++ = byte; + /* FALLTHROUGH */ + case RESET | END: + break; + } + break; + } while (cp < cplim); + sdl->sdl_alen = cp - LLADDR(sdl); + newaddr = cp - (char *)(void *)sdl; + if ((size_t) newaddr > sizeof(*sdl)) + sdl->sdl_len = newaddr; + return; +}
diff --git a/compat/strlcpy.c b/compat/strlcpy.c new file mode 100755 index 0000000..2cdd6a5 --- /dev/null +++ b/compat/strlcpy.c
@@ -0,0 +1,51 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include "strlcpy.h" + +size_t +strlcpy(char *dst, const char *src, size_t size) +{ + const char *s = src; + size_t n = size; + + if (n && --n) + do { + if (!(*dst++ = *src++)) + break; + } while (--n); + + if (!n) { + if (size) + *dst = '\0'; + while (*src++); + } + + return src - s - 1; +}
diff --git a/compat/strlcpy.h b/compat/strlcpy.h new file mode 100755 index 0000000..75eaec8 --- /dev/null +++ b/compat/strlcpy.h
@@ -0,0 +1,34 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2009 Roy Marples <roy@marples.name> + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef STRLCPY_H +#define STRLCPY_H + +#include <sys/types.h> + +size_t strlcpy(char *, const char *, size_t); +#endif
diff --git a/masterblaster.h b/masterblaster.h new file mode 100755 index 0000000..c5fd410 --- /dev/null +++ b/masterblaster.h
@@ -0,0 +1,413 @@ +/* + * Copyright (c) 2008-2009 Atheros 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 version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * <Header file contains required data for master blaster mode> + * + * <masterblaster.h> + */ + +#ifndef _MASTERBLASTER_H_ +#define _MASTERBLASTER_H_ +#include "btconfig.h" + +#define INVALID_MASTERBLASTER_FIELD (-1) +#define UNUSED(x) (x=x) +// Bluetooth Packet Type Identifiers +#define MAX_TRANSMIT_POWER_CONTROL_ENTRIES 15 + +#define LC_JTAG_MODEM_REGS_ADDRESS 0x00020800 +#define AGC_BYPASS_ADDRESS 0x0000040c +#define AGC_BYPASS_ENABLE_MASK 0x00000001 +#define AGC_BYPASS_ENABLE_LSB 0 +#define AGC_BYPASS_ENABLE_SET(x) (((x) << AGC_BYPASS_ENABLE_LSB) & AGC_BYPASS_ENABLE_MASK) +#define LC_DEV_PARAM_CTL_ADDRESS 0x00020010 +#define LC_DEV_PARAM_CTL_FREQ_HOP_EN_MASK 0x00000001 +#define LC_DEV_PARAM_CTL_RX_FREQ_MASK 0x00007f00 +#define LC_DEV_PARAM_CTL_WHITEN_EN_MASK 0x00008000 +#define LC_DEV_PARAM_CTL_RX_FREQ_SET(x) (((x) << LC_DEV_PARAM_CTL_RX_FREQ_LSB) & LC_DEV_PARAM_CTL_RX_FREQ_MASK) +#define LC_DEV_PARAM_CTL_RX_FREQ_LSB 8 + +#define CORR_PARAM1_ADDRESS 0x00000048 +#define CORR_PARAM1_TIM_THR_MASK 0xfc000000 +#define CORR_PARAM1_TIM_THR_LSB 26 +#define CORR_PARAM1_TIM_THR_SET(x) (((x) << CORR_PARAM1_TIM_THR_LSB) & CORR_PARAM1_TIM_THR_MASK) + +typedef struct tBtHost_Interest { + UINT16 MagicNumber; + UINT16 Version; + UINT32 TraceDataAddr; + UINT32 GlobalDmaStats; // BRM Global DMA Statistics + UINT32 TpcTableAddr; // SysCfg Transmit power table + UINT32 AudioStatAddr; + UINT32 AudioInternalAddr; + UINT32 SysCfgAddr; + UINT32 ReservedRamAddr; + UINT32 HostConfigAddr; + UINT32 RamVersionAddr; + // Version 1.01 + UINT32 BrmGlobalDataAddr; // BRM Global Context pointer + UINT32 LeGlobalDataAddr; // LE Global Context pointer + // Version 1.02 + UINT32 MmGlobalDataAddr; +} tBtHostInterest; + +typedef struct PsSysCfgTransmitPowerControlEntry { + SINT8 TxPowerLevel; + UINT32 RadioConfig; + UINT32 EdrRadioConfig; + SINT16 Slope; + SINT16 EdrSlope; + UINT8 TxFreqCorr; + UINT8 EdrTxFreqCorr; +} tPsSysCfgTransmitPowerControlEntry; + +typedef struct PsSysCfgTransmitPowerControlTable { + int NumOfEntries; + tPsSysCfgTransmitPowerControlEntry t[MAX_TRANSMIT_POWER_CONTROL_ENTRIES]; +} tPsSysCfgTransmitPowerControlTable; +typedef UCHAR tBRM_PktType; + +enum { + TxTest_PktType_NULL = 0x00, + TxTest_PktType_POLL = 0x01, + TxTest_PktType_FHS = 0x02, + TxTest_PktType_DM1 = 0x03, + TxTest_PktType_DH1 = 0x04, + TxTest_PktType_HV1 = 0x05, + TxTest_PktType_HV2 = 0x06, + TxTest_PktType_HV3 = 0x07, + TxTest_PktType_DV = 0x08, + TxTest_PktType_AUX1 = 0x09, + TxTest_PktType_DM3 = 0x0A, + TxTest_PktType_DH3 = 0x0B, + TxTest_PktType_DM5 = 0x0E, + TxTest_PktType_DH5 = 0x0F, + TxTest_PktType_2DH1 = 0x24, + TxTest_PktType_2DH3 = 0x2A, + TxTest_PktType_2DH5 = 0x2E, + TxTest_PktType_3DH1 = 0x28, + TxTest_PktType_3DH3 = 0x2B, + TxTest_PktType_3DH5 = 0x2F, + TxTest_PktType_Invalid = 0xff, +}; + +typedef UCHAR tBRM_eSCO_PktType; + +enum { + TxTest_PktType_EV3 = 0x17, + TxTest_PktType_EV4 = 0x1C, + TxTest_PktType_EV5 = 0x1D, + TxTest_PktType_2EV3 = 0x36, + TxTest_PktType_2EV5 = 0x3C, + TxTest_PktType_3EV3 = 0x37, + TxTest_PktType_3EV5 = 0x3D, +}; + +typedef UCHAR tBRM_PktMode; + +enum { + eBRM_Mode_Basic = 0, + eBRM_Mode_2Mbps = 2, + eBRM_Mode_3Mbps = 3 +}; + +// tBRM_TestMode +enum { + eBRM_TestMode_Pause = 0, + eBRM_TestMode_TX_0, + eBRM_TestMode_TX_1, + eBRM_TestMode_TX_1010, + eBRM_TestMode_TX_PRBS, + eBRM_TestMode_Loop_ACL, + eBRM_TestMode_Loop_SCO, + eBRM_TestMode_Loop_ACL_No_Whitening, + eBRM_TestMode_Loop_SCO_No_Whitening, + eBRM_TestMode_TX_11110000, + eBRM_TestMode_Rx, + eBRM_TestMode_Exit = 255, +}; +enum { + Cont_Tx_Raw_1MHz = 0, + Cont_Tx_Raw_2MHz, + Cont_Tx_Raw_3MHz, + Cont_Tx_Regular, + CW_Single_Tone, +}; +typedef UCHAR tBRM_TestMode; + +typedef struct tBRM_TestControl { + tBRM_TestMode Mode; + UCHAR HopMode; + UCHAR TxFreq; + UCHAR RxFreq; + UCHAR Power; +// UCHAR PollPeriod; + UCHAR Packet; + UCHAR SkipRxSlot; + int DataLen; +} tBRM_TestControl; + +typedef struct tLE_TxParms { + UCHAR PktPayload; +} tLE_TxParms; + +typedef struct tBRM_Control_packet { + tBRM_TestControl testCtrl; + UCHAR bdaddr[6]; + UCHAR ContTxMode; // Continuous TX Mode + UCHAR ContTxType; + UCHAR ContRxMode; // Continuous RX Mode + UCHAR BERType; + UCHAR LERxMode; + UCHAR LETxMode; + tLE_TxParms LETxParms; +} tBRM_Control_packet; + + +#define DM1_MAX_PAYLOAD 17 +#define DH1_MAX_PAYLOAD 27 +#define DM3_MAX_PAYLOAD 121 +#define DH3_MAX_PAYLOAD 183 +#define DM5_MAX_PAYLOAD 224 +#define DH5_MAX_PAYLOAD 339 +#define AUX1_MAX_PAYLOAD 29 +#define E2_DH1_MAX_PAYLOAD 54 +#define E2_DH3_MAX_PAYLOAD 367 +#define E2_DH5_MAX_PAYLOAD 679 +#define E3_DH1_MAX_PAYLOAD 83 +#define E3_DH3_MAX_PAYLOAD 552 +#define E3_DH5_MAX_PAYLOAD 1021 + +enum E_MasterBlasterFieldID +{ + CR = 0, + CT, + LR, + LT, + LTM, + CX, + TM, + HM, + TF, + RF, + PT, + DL, + PO, + BA, + SB, + GB, + RX, + TX, + EN, + ST, + EX, + EXX, +}; + +enum E_MasterBlasterTestFlag +{ + MB_NO_TEST = 0, + MB_RX_TEST, + MB_TX_TEST, + MB_CONT_RX_TEST, + MB_CONT_TX_TEST, + MB_LE_RX_TEST, + MB_LE_TX_TEST, +}; + +enum E_DisableEnable +{ + DISABLE = 0, + ENABLE = 1, +}; + +#define MB_MIN_DATALEN 0 +#define MB_MAX_DATALEN 1021 +#define MB_MIN_FREQUENCY 0 +#define MB_MAX_FREQUENCY 79 +#define MB_MIN_FREQUENCY_LE 0 +#define MB_MAX_FREQUENCY_LE 39 +#define MB_MIN_DATALEN_LE 0 +#define MB_MAX_DATALEN_LE 37 +typedef struct STR_MasterBlasterOption +{ + char *Name; + int Value; +} tMasterBlasterOption; + +typedef struct STR_MasterBlasterField +{ + char *Name; + char *Alias; + char *Usage; + int Default; + tMasterBlasterOption *Options; + int (*pFunc)(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +} tMasterBlasterField; + +static tMasterBlasterOption TestModeOption[] = +{ + {"TX_0", eBRM_TestMode_TX_0}, + {"TX_1", eBRM_TestMode_TX_1}, + {"TX_1010", eBRM_TestMode_TX_1010}, + {"TX_PRBS", eBRM_TestMode_TX_PRBS}, + {"TX_11110000", eBRM_TestMode_TX_11110000}, + {"RX", eBRM_TestMode_Rx}, +}; + +static tMasterBlasterOption HopModeOption[] = +{ + {"Disable", DISABLE}, + {"Enable", ENABLE}, +}; + +static tMasterBlasterOption PacketTypeOption[] = +{ + {"DM1", TxTest_PktType_DM1}, + {"DM3", TxTest_PktType_DM3}, + {"DM5", TxTest_PktType_DM5}, + {"DH1", TxTest_PktType_DH1}, + {"DH3", TxTest_PktType_DH3}, + {"DH5", TxTest_PktType_DH5}, + {"2-DH1", TxTest_PktType_2DH1}, + {"2-DH3", TxTest_PktType_2DH3}, + {"2-DH5", TxTest_PktType_2DH5}, + {"3-DH1", TxTest_PktType_3DH1}, + {"3-DH3", TxTest_PktType_3DH3}, + {"3-DH5", TxTest_PktType_3DH5}, +}; + +static int MaxDataLenOption[] = +{ + DM1_MAX_PAYLOAD, + DM3_MAX_PAYLOAD, + DM5_MAX_PAYLOAD, + DH1_MAX_PAYLOAD, + DH3_MAX_PAYLOAD, + DH5_MAX_PAYLOAD, + E2_DH1_MAX_PAYLOAD, + E2_DH3_MAX_PAYLOAD, + E2_DH5_MAX_PAYLOAD, + E3_DH1_MAX_PAYLOAD, + E3_DH3_MAX_PAYLOAD, + E3_DH5_MAX_PAYLOAD, +}; + +enum { + eBRM_BERMode_ALL = 0, // ALL type + eBRM_BERMode_ALL_DATA, // All type except dm1,dm3,dm5 + eBRM_BERMode_DM1, + eBRM_BERMode_DM3, + eBRM_BERMode_DM5, + eBRM_BERMode_DH1, + eBRM_BERMode_DH3, + eBRM_BERMode_DH5, + eBRM_BERMode_2DH1, + eBRM_BERMode_2DH3, + eBRM_BERMode_2DH5, + eBRM_BERMode_3DH1, + eBRM_BERMode_3DH3, + eBRM_BERMode_3DH5, +}; + +static tMasterBlasterOption BERPacketTypeOption[] = +{ + {"ALL", eBRM_BERMode_ALL}, + {"ALL_DATA", eBRM_BERMode_ALL_DATA}, + {"DM1", eBRM_BERMode_DM1}, + {"DM3", eBRM_BERMode_DM3}, + {"DM5", eBRM_BERMode_DM5}, + {"DH1", eBRM_BERMode_DH1}, + {"DH3", eBRM_BERMode_DH3}, + {"DH5", eBRM_BERMode_DH5}, + {"2DH1", eBRM_BERMode_2DH1}, + {"2DH3", eBRM_BERMode_2DH3}, + {"2DH5", eBRM_BERMode_2DH5}, + {"3DH1", eBRM_BERMode_3DH1}, + {"3DH3", eBRM_BERMode_3DH3}, + {"3DH5", eBRM_BERMode_3DH5}, +}; + +static tMasterBlasterOption ContTxModeOption[] = +{ + {"Disable", DISABLE}, + {"Enable", ENABLE}, +}; + +static tMasterBlasterOption ContTxTypeOption[] = +{ + {"Raw_1MHz", Cont_Tx_Raw_1MHz}, + {"Raw_2MHz", Cont_Tx_Raw_2MHz}, + {"Raw_3MHz", Cont_Tx_Raw_3MHz}, + {"Regular_BT_Packet_Format", Cont_Tx_Regular}, + {"CW_Single_Tone", CW_Single_Tone}, +}; + +static tMasterBlasterOption ContRxModeOption[] = +{ + {"Disable", DISABLE}, + {"Enable", ENABLE}, +}; + +static tMasterBlasterOption LETxPktPayloadOption[] = +{ + {"Random_9", 0}, + {"11110000", 1}, + {"10101010", 2}, + {"Random_15", 3}, + {"11111111", 4}, + {"00000000", 5}, + {"00001111", 6}, + {"01010101", 7}, +}; + +//---------------------------------------------------------------------------- +// Prototypes +//---------------------------------------------------------------------------- + +void InitMasterBlaster (tBRM_Control_packet *MasterBlaster, bdaddr_t *BdAddr, UCHAR *SkipRxSlot); + +int CheckField (tBRM_Control_packet MasterBlaster, char *FieldAlias); +int GetTestModeOptionIndex (int Mode); +int GetPacketTypeOptionIndex (int PacketType); + +void PrintMasterBlasterMenu (tBRM_Control_packet *MasterBlaster); +int SetMasterBlasterTestMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterHopMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterPacketType (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterTxFreq (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterRxFreq (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterPower (tBRM_Control_packet *MasterBlaster, char *Option); +int SetMasterBlasterDataLen (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterBdAddr (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterContTxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterContTxType (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterNothing (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterContRxMode (tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterLERxMode(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterLETxMode(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterLETxPktPayload(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); +int SetMasterBlasterBERType(tBRM_Control_packet *MasterBlaster, tMasterBlasterOption *Option); + +int ToggleOption (int *Value, tMasterBlasterOption *Option, tMasterBlasterOption *OptionArray, + int Size, int FieldID, int Step); +int MinMaxOption (int *Value, tMasterBlasterOption *Option, int Min, int Max); +int ToggleMinMaxOption (int *Value, char *Option, int FieldID, int Min, int Max, int Step); + +//---------------------------------------------------------------------------- +// Variables +//---------------------------------------------------------------------------- + +extern tMasterBlasterField MasterBlasterMenu[]; +extern tPsSysCfgTransmitPowerControlTable TpcTable; + +#endif // _MASTERBLASTER_H_