1101 lines
28 KiB
C
1101 lines
28 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2014, The linux Foundation. All rights reserved.
|
|
*
|
|
* Not a Contribution.
|
|
*
|
|
* Copyright (C) 2009-2012 Broadcom Corporation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
******************************************************************************/
|
|
|
|
/************************************************************************************
|
|
*
|
|
* Filename: rfcommtest.c
|
|
*
|
|
* Description: RFCOMM Test application
|
|
*
|
|
***********************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <dlfcn.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
#include <fcntl.h>
|
|
#include <sys/prctl.h>
|
|
#include <sys/capability.h>
|
|
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
|
|
#include <private/android_filesystem_config.h>
|
|
#include <android/log.h>
|
|
|
|
#include <hardware/hardware.h>
|
|
#include <hardware/bluetooth.h>
|
|
#include "bt_target.h"
|
|
#include "bt_testapp.h"
|
|
|
|
/************************************************************************************
|
|
** Constants & Macros
|
|
************************************************************************************/
|
|
|
|
#define PID_FILE "/data/.bdt_pid"
|
|
|
|
#ifndef MAX
|
|
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
|
#endif
|
|
|
|
#define CASE_RETURN_STR(const) case const: return #const;
|
|
#define DISCONNECT 3
|
|
|
|
/************************************************************************************
|
|
** Local type definitions
|
|
************************************************************************************/
|
|
|
|
/************************************************************************************
|
|
** Static variables
|
|
************************************************************************************/
|
|
|
|
static unsigned char main_done = 0;
|
|
static bt_status_t status;
|
|
|
|
/* Main API */
|
|
static bluetooth_device_t* bt_device;
|
|
|
|
const bt_interface_t* sBtInterface = NULL;
|
|
const btrfcomm_interface_t *sRfcInterface = NULL;
|
|
|
|
static gid_t groups[] = { AID_NET_BT, AID_INET, AID_NET_BT_ADMIN,
|
|
AID_SYSTEM, AID_MISC, AID_SDCARD_RW,
|
|
AID_NET_ADMIN, AID_VPN};
|
|
|
|
/* Set to 1 when the Bluedroid stack is enabled */
|
|
static unsigned char bt_enabled = 0;
|
|
static bool strict_mode = FALSE;
|
|
|
|
/************************************************************************************
|
|
** Static functions
|
|
************************************************************************************/
|
|
|
|
static void process_cmd(char *p, unsigned char is_job);
|
|
static void bdt_log(const char *fmt_str, ...);
|
|
|
|
|
|
/************************************************************************************
|
|
** Externs
|
|
************************************************************************************/
|
|
|
|
/************************************************************************************
|
|
** Functions
|
|
************************************************************************************/
|
|
|
|
|
|
/************************************************************************************
|
|
** Shutdown helper functions
|
|
************************************************************************************/
|
|
|
|
static void bdt_shutdown(void)
|
|
{
|
|
bdt_log("shutdown bdroid test app\n");
|
|
main_done = 1;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
** Android's init.rc does not yet support applying linux capabilities
|
|
*****************************************************************************/
|
|
|
|
static int str2bd(char *str, bt_bdaddr_t *addr)
|
|
{
|
|
int32_t i = 0;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
addr->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
|
|
str++;
|
|
}
|
|
return 0;
|
|
}
|
|
static void config_permissions(void)
|
|
{
|
|
struct __user_cap_header_struct header;
|
|
struct __user_cap_data_struct cap[2];
|
|
|
|
bdt_log("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), getgid());
|
|
|
|
header.pid = 0;
|
|
|
|
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
|
|
|
|
setuid(AID_BLUETOOTH);
|
|
setgid(AID_BLUETOOTH);
|
|
|
|
header.version = _LINUX_CAPABILITY_VERSION_3;
|
|
|
|
cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
|
|
cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
|
|
cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].permitted |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
|
|
cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted |= CAP_TO_MASK(CAP_SYS_RAWIO);
|
|
cap[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE);
|
|
cap[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
|
|
cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].permitted |= CAP_TO_MASK(CAP_WAKE_ALARM);
|
|
|
|
cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
|
|
cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
|
|
cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].effective |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
|
|
cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective |= CAP_TO_MASK(CAP_SYS_RAWIO);
|
|
cap[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE);
|
|
cap[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
|
|
cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].effective |= CAP_TO_MASK(CAP_WAKE_ALARM);
|
|
|
|
capset(&header, &cap[0]);
|
|
setgroups(sizeof(groups)/sizeof(groups[0]), groups);
|
|
}
|
|
#if 0
|
|
/*Pin_Request_cb */
|
|
static void pin_remote_request_callback (bt_bdaddr_t *remote_bd_addr,
|
|
bt_bdname_t *bd_name, uint32_t cod)
|
|
{
|
|
bt_pin_code_t pin_code;
|
|
/* Default 1234 is the Pin code */
|
|
pin_code.pin[0] = 0x31;
|
|
pin_code.pin[1] = 0x32;
|
|
pin_code.pin[2] = 0x33;
|
|
pin_code.pin[3] = 0x34;
|
|
|
|
bdt_log("bdt PIN Remote Request");
|
|
sBtInterface->pin_reply(remote_bd_addr ,1 , 4 , &pin_code);
|
|
}
|
|
#endif
|
|
|
|
/* Pairing in Case of SSP */
|
|
static void ssp_remote_requst_callback(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
|
|
uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key)
|
|
{
|
|
if (pairing_variant == BT_SSP_VARIANT_PASSKEY_ENTRY)
|
|
{
|
|
bdt_log("bdt ssp remote request not supported");
|
|
return;
|
|
}
|
|
bdt_log("bdt accept SSP pairing");
|
|
sBtInterface->ssp_reply(remote_bd_addr, pairing_variant, 1, pass_key);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
** Logger API
|
|
*****************************************************************************/
|
|
|
|
void bdt_log(const char *fmt_str, ...)
|
|
{
|
|
static char buffer[1024];
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt_str);
|
|
vsnprintf(buffer, 1024, fmt_str, ap);
|
|
va_end(ap);
|
|
|
|
fprintf(stdout, "%s\n", buffer);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
** Misc helper functions
|
|
*******************************************************************************/
|
|
static const char* dump_bt_status(bt_status_t status)
|
|
{
|
|
switch(status)
|
|
{
|
|
CASE_RETURN_STR(BT_STATUS_SUCCESS)
|
|
CASE_RETURN_STR(BT_STATUS_FAIL)
|
|
CASE_RETURN_STR(BT_STATUS_NOT_READY)
|
|
CASE_RETURN_STR(BT_STATUS_NOMEM)
|
|
CASE_RETURN_STR(BT_STATUS_BUSY)
|
|
CASE_RETURN_STR(BT_STATUS_UNSUPPORTED)
|
|
|
|
default:
|
|
return "unknown status code";
|
|
}
|
|
}
|
|
#if 0
|
|
static void hex_dump(char *msg, void *data, int size, int trunc)
|
|
{
|
|
unsigned char *p = data;
|
|
unsigned char c;
|
|
int n;
|
|
char bytestr[4] = {0};
|
|
char addrstr[10] = {0};
|
|
char hexstr[ 16*3 + 5] = {0};
|
|
char charstr[16*1 + 5] = {0};
|
|
|
|
bdt_log("%s \n", msg);
|
|
|
|
/* truncate */
|
|
if(trunc && (size>32))
|
|
size = 32;
|
|
|
|
for(n=1;n<=size;n++) {
|
|
if (n%16 == 1) {
|
|
/* store address for this line */
|
|
snprintf(addrstr, sizeof(addrstr), "%.4x",
|
|
(unsigned int)((uintptr_t)p-(uintptr_t)data) );
|
|
}
|
|
|
|
c = *p;
|
|
if (isalnum(c) == 0) {
|
|
c = '.';
|
|
}
|
|
|
|
/* store hex str (for left side) */
|
|
snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
|
|
strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
|
|
|
|
/* store char str (for right side) */
|
|
snprintf(bytestr, sizeof(bytestr), "%c", c);
|
|
strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
|
|
|
|
if(n%16 == 0) {
|
|
/* line completed */
|
|
bdt_log("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
|
|
hexstr[0] = 0;
|
|
charstr[0] = 0;
|
|
} else if(n%8 == 0) {
|
|
/* half line: add whitespaces */
|
|
strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1);
|
|
strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
|
|
}
|
|
p++; /* next byte */
|
|
}
|
|
|
|
if (strlen(hexstr) > 0) {
|
|
/* print rest of buffer if not empty */
|
|
bdt_log("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
|
|
}
|
|
}
|
|
#endif
|
|
/*******************************************************************************
|
|
** Console helper functions
|
|
*******************************************************************************/
|
|
|
|
void skip_blanks(char **p)
|
|
{
|
|
while (**p == ' ')
|
|
(*p)++;
|
|
}
|
|
|
|
uint32_t get_int(char **p, int DefaultValue)
|
|
{
|
|
uint32_t Value = 0;
|
|
unsigned char UseDefault;
|
|
|
|
UseDefault = 1;
|
|
skip_blanks(p);
|
|
|
|
while ( ((**p)<= '9' && (**p)>= '0') )
|
|
{
|
|
Value = Value * 10 + (**p) - '0';
|
|
UseDefault = 0;
|
|
(*p)++;
|
|
}
|
|
|
|
if (UseDefault)
|
|
return DefaultValue;
|
|
else
|
|
return Value;
|
|
}
|
|
|
|
int get_signed_int(char **p, int DefaultValue)
|
|
{
|
|
int Value = 0;
|
|
unsigned char UseDefault;
|
|
unsigned char NegativeNum = 0;
|
|
|
|
UseDefault = 1;
|
|
skip_blanks(p);
|
|
|
|
if ( (**p) == '-')
|
|
{
|
|
NegativeNum = 1;
|
|
(*p)++;
|
|
}
|
|
while ( ((**p)<= '9' && (**p)>= '0') )
|
|
{
|
|
Value = Value * 10 + (**p) - '0';
|
|
UseDefault = 0;
|
|
(*p)++;
|
|
}
|
|
|
|
if (UseDefault)
|
|
return DefaultValue;
|
|
else
|
|
return ((NegativeNum == 0)? Value : -Value);
|
|
}
|
|
|
|
void get_str(char **p, char *Buffer)
|
|
{
|
|
skip_blanks(p);
|
|
|
|
while (**p != 0 && **p != ' ')
|
|
{
|
|
*Buffer = **p;
|
|
(*p)++;
|
|
Buffer++;
|
|
}
|
|
|
|
*Buffer = 0;
|
|
}
|
|
|
|
uint32_t get_hex(char **p, int DefaultValue)
|
|
{
|
|
uint32_t Value = 0;
|
|
unsigned char UseDefault;
|
|
|
|
UseDefault = 1;
|
|
skip_blanks(p);
|
|
|
|
while ( ((**p)<= '9' && (**p)>= '0') ||
|
|
((**p)<= 'f' && (**p)>= 'a') ||
|
|
((**p)<= 'F' && (**p)>= 'A') )
|
|
{
|
|
if (**p >= 'a')
|
|
Value = Value * 16 + (**p) - 'a' + 10;
|
|
else if (**p >= 'A')
|
|
Value = Value * 16 + (**p) - 'A' + 10;
|
|
else
|
|
Value = Value * 16 + (**p) - '0';
|
|
UseDefault = 0;
|
|
(*p)++;
|
|
}
|
|
|
|
if (UseDefault)
|
|
return DefaultValue;
|
|
else
|
|
return Value;
|
|
}
|
|
|
|
void get_bdaddr(const char *str, bt_bdaddr_t *bd) {
|
|
char *d = ((char *)bd), *endp;
|
|
int i;
|
|
for(i = 0; i < 6; i++) {
|
|
*d++ = strtol(str, &endp, 16);
|
|
if (*endp != ':' && i != 5) {
|
|
memset(bd, 0, sizeof(bt_bdaddr_t));
|
|
return;
|
|
}
|
|
str = endp + 1;
|
|
}
|
|
}
|
|
|
|
#define is_cmd(str) ((strlen(str) == strlen(cmd)) && strncmp((const char *)&cmd, str, strlen(str)) == 0)
|
|
#define if_cmd(str) if (is_cmd(str))
|
|
|
|
typedef void (t_console_cmd_handler) (char *p);
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
t_console_cmd_handler *handler;
|
|
const char *help;
|
|
unsigned char is_job;
|
|
} t_cmd;
|
|
|
|
|
|
const t_cmd console_cmd_list[];
|
|
static int console_cmd_maxlen = 0;
|
|
|
|
static void cmdjob_handler(void *param)
|
|
{
|
|
char *job_cmd = (char*)param;
|
|
|
|
bdt_log("cmdjob starting (%s)", job_cmd);
|
|
|
|
process_cmd(job_cmd, 1);
|
|
|
|
bdt_log("cmdjob terminating");
|
|
|
|
free(job_cmd);
|
|
}
|
|
|
|
static int create_cmdjob(char *cmd)
|
|
{
|
|
pthread_t thread_id;
|
|
char *job_cmd;
|
|
|
|
job_cmd = malloc(strlen(cmd)+1); /* freed in job handler */
|
|
if (job_cmd)
|
|
{
|
|
strlcpy(job_cmd, cmd, sizeof(job_cmd));
|
|
if (pthread_create(&thread_id, NULL,
|
|
(void*)cmdjob_handler, (void*)job_cmd)!=0)
|
|
perror("pthread_create");
|
|
}
|
|
else
|
|
bdt_log("Rfcomm_test: Cannot allocate memory for cmdjob");
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
** Load stack lib
|
|
*******************************************************************************/
|
|
|
|
int HAL_load(void)
|
|
{
|
|
int err = 0;
|
|
|
|
hw_module_t* module;
|
|
hw_device_t* device;
|
|
|
|
bdt_log("Loading HAL lib + extensions");
|
|
|
|
err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
|
|
if (err == 0)
|
|
{
|
|
err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
|
|
if (err == 0) {
|
|
bt_device = (bluetooth_device_t *)device;
|
|
sBtInterface = bt_device->get_bluetooth_interface();
|
|
}
|
|
}
|
|
|
|
bdt_log("HAL library loaded (%s)", strerror(err));
|
|
|
|
return err;
|
|
}
|
|
|
|
int HAL_unload(void)
|
|
{
|
|
int err = 0;
|
|
|
|
bdt_log("Unloading HAL lib");
|
|
|
|
sBtInterface = NULL;
|
|
sRfcInterface = NULL;
|
|
|
|
bdt_log("HAL library unloaded (%s)", strerror(err));
|
|
|
|
return err;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
** HAL test functions & callbacks
|
|
*******************************************************************************/
|
|
|
|
void setup_test_env(void)
|
|
{
|
|
int i = 0;
|
|
|
|
while (console_cmd_list[i].name != NULL)
|
|
{
|
|
console_cmd_maxlen = MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name));
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void check_return_status(bt_status_t status)
|
|
{
|
|
if (status != BT_STATUS_SUCCESS)
|
|
{
|
|
bdt_log("HAL REQUEST FAILED status : %d (%s)", status, dump_bt_status(status));
|
|
}
|
|
else
|
|
{
|
|
bdt_log("HAL REQUEST SUCCESS");
|
|
}
|
|
}
|
|
|
|
static void adapter_state_changed(bt_state_t state)
|
|
{
|
|
bdt_log("ADAPTER STATE UPDATED : %s", (state == BT_STATE_OFF)?"OFF":"ON");
|
|
if (state == BT_STATE_ON) {
|
|
bt_enabled = 1;
|
|
} else {
|
|
bt_enabled = 0;
|
|
}
|
|
}
|
|
|
|
static void dut_mode_recv(uint16_t opcode, uint8_t *buf, uint8_t len)
|
|
{
|
|
bdt_log("DUT MODE RECV : NOT IMPLEMENTED");
|
|
}
|
|
#if BLE_INCLUDED == TRUE
|
|
static void le_test_mode(bt_status_t status, uint16_t packet_count)
|
|
{
|
|
bdt_log("LE TEST MODE END status:%s number_of_packets:%d", dump_bt_status(status), packet_count);
|
|
}
|
|
#endif
|
|
|
|
static void device_found_cb(int num_properties, bt_property_t *properties)
|
|
{
|
|
int i;
|
|
for (i = 0; i < num_properties; i++)
|
|
{
|
|
if (properties[i].type == BT_PROPERTY_BDNAME)
|
|
{
|
|
bdt_log("AP name is : %s\n",
|
|
(char*)properties[i].val);
|
|
}
|
|
}
|
|
}
|
|
|
|
static bt_callbacks_t bt_callbacks = {
|
|
sizeof(bt_callbacks_t),
|
|
adapter_state_changed,
|
|
NULL, /*adapter_properties_cb */
|
|
NULL, /* remote_device_properties_cb */
|
|
device_found_cb, /* device_found_cb */
|
|
NULL, /* discovery_state_changed_cb */
|
|
NULL, /* pin_request_cb */
|
|
ssp_remote_requst_callback, /* ssp_request_cb */
|
|
NULL, /*bond_state_changed_cb */
|
|
NULL, /* acl_state_changed_cb */
|
|
NULL, /* thread_evt_cb */
|
|
dut_mode_recv, /*dut_mode_recv_cb */
|
|
// NULL, /*authorize_request_cb */
|
|
#if BLE_INCLUDED == TRUE
|
|
le_test_mode, /* le_test_mode_cb */
|
|
#else
|
|
NULL,
|
|
#endif
|
|
NULL, /* energy_info_cb */
|
|
NULL /* get_testapp_interface */
|
|
};
|
|
|
|
static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data)
|
|
{
|
|
static timer_t timer;
|
|
static bool timer_created;
|
|
|
|
if (!timer_created)
|
|
{
|
|
struct sigevent sigevent;
|
|
memset(&sigevent, 0, sizeof(sigevent));
|
|
sigevent.sigev_notify = SIGEV_THREAD;
|
|
sigevent.sigev_notify_function = (void (*)(union sigval))cb;
|
|
sigevent.sigev_value.sival_ptr = data;
|
|
timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
|
|
timer_created = true;
|
|
}
|
|
|
|
struct itimerspec new_value;
|
|
new_value.it_value.tv_sec = delay_millis / 1000;
|
|
new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
|
|
new_value.it_interval.tv_sec = 0;
|
|
new_value.it_interval.tv_nsec = 0;
|
|
timer_settime(timer, 0, &new_value, NULL);
|
|
|
|
return true;
|
|
}
|
|
|
|
static int acquire_wake_lock(const char *lock_name)
|
|
{
|
|
return BT_STATUS_SUCCESS;
|
|
}
|
|
|
|
static int release_wake_lock(const char *lock_name)
|
|
{
|
|
return BT_STATUS_SUCCESS;
|
|
}
|
|
|
|
static bt_os_callouts_t callouts = {
|
|
sizeof(bt_os_callouts_t),
|
|
set_wake_alarm,
|
|
acquire_wake_lock,
|
|
release_wake_lock,
|
|
};
|
|
|
|
/* Rfcomm Client */
|
|
void bdt_rfcomm(void)
|
|
{
|
|
bdt_log("rfcomm client");
|
|
|
|
sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
|
|
if (sRfcInterface)
|
|
{
|
|
sRfcInterface->rdut_rfcomm(0);
|
|
}
|
|
else
|
|
{
|
|
bdt_log("interface not loaded");
|
|
}
|
|
}
|
|
|
|
/* Rfcomm Server */
|
|
void bdt_rfcomm_server (void)
|
|
{
|
|
bdt_log("rfcomm server");
|
|
|
|
sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
|
|
if (sRfcInterface)
|
|
{
|
|
sRfcInterface->rdut_rfcomm(1);
|
|
}
|
|
else
|
|
{
|
|
bdt_log("interface not loaded");
|
|
}
|
|
}
|
|
|
|
/* Rfcomm disconnect */
|
|
void bdt_rfcomm_disc_from_server(void)
|
|
{
|
|
bdt_log("rfcomm disc from Server");
|
|
|
|
sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
|
|
if (sRfcInterface)
|
|
{
|
|
sRfcInterface->rdut_rfcomm(3);
|
|
}
|
|
else
|
|
{
|
|
bdt_log("interface not loaded");
|
|
}
|
|
}
|
|
|
|
void bdt_init(void)
|
|
{
|
|
bdt_log("INIT BT ");
|
|
status = sBtInterface->init(&bt_callbacks, false);
|
|
if (status == BT_STATUS_SUCCESS) {
|
|
status = sBtInterface->set_os_callouts(&callouts);
|
|
}
|
|
check_return_status(status);
|
|
}
|
|
|
|
void bdt_enable(void)
|
|
{
|
|
bdt_log("ENABLE BT");
|
|
if (bt_enabled) {
|
|
bdt_log("Bluetooth is already enabled");
|
|
return;
|
|
}
|
|
status = sBtInterface->enable(strict_mode);
|
|
|
|
check_return_status(status);
|
|
}
|
|
|
|
void bdt_disable(void)
|
|
{
|
|
bdt_log("DISABLE BT");
|
|
if (!bt_enabled) {
|
|
bdt_log("Bluetooth is already disabled");
|
|
return;
|
|
}
|
|
status = sBtInterface->disable();
|
|
|
|
check_return_status(status);
|
|
}
|
|
void bdt_dut_mode_configure(char *p)
|
|
{
|
|
int32_t mode = -1;
|
|
|
|
bdt_log("BT DUT MODE CONFIGURE");
|
|
if (!bt_enabled) {
|
|
bdt_log("Bluetooth must be enabled for test_mode to work.");
|
|
return;
|
|
}
|
|
mode = get_signed_int(&p, mode);
|
|
if ((mode != 0) && (mode != 1)) {
|
|
bdt_log("Please specify mode: 1 to enter, 0 to exit");
|
|
return;
|
|
}
|
|
status = sBtInterface->dut_mode_configure(mode);
|
|
|
|
check_return_status(status);
|
|
}
|
|
|
|
#define HCI_LE_RECEIVER_TEST_OPCODE 0x201D
|
|
#define HCI_LE_TRANSMITTER_TEST_OPCODE 0x201E
|
|
#define HCI_LE_END_TEST_OPCODE 0x201F
|
|
|
|
void bdt_le_test_mode(char *p)
|
|
{
|
|
int cmd;
|
|
unsigned char buf[3];
|
|
int arg1, arg2, arg3;
|
|
|
|
bdt_log("BT LE TEST MODE");
|
|
if (!bt_enabled) {
|
|
bdt_log("Bluetooth must be enabled for le_test to work.");
|
|
return;
|
|
}
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
cmd = get_int(&p, 0);
|
|
switch (cmd)
|
|
{
|
|
case 0x1: /* RX TEST */
|
|
arg1 = get_int(&p, -1);
|
|
if (arg1 < 0) bdt_log("%s Invalid arguments", __FUNCTION__);
|
|
buf[0] = arg1;
|
|
status = sBtInterface->le_test_mode(HCI_LE_RECEIVER_TEST_OPCODE, buf, 1);
|
|
break;
|
|
case 0x2: /* TX TEST */
|
|
arg1 = get_int(&p, -1);
|
|
arg2 = get_int(&p, -1);
|
|
arg3 = get_int(&p, -1);
|
|
if ((arg1 < 0) || (arg2 < 0) || (arg3 < 0))
|
|
bdt_log("%s Invalid arguments", __FUNCTION__);
|
|
buf[0] = arg1;
|
|
buf[1] = arg2;
|
|
buf[2] = arg3;
|
|
status = sBtInterface->le_test_mode(HCI_LE_TRANSMITTER_TEST_OPCODE, buf, 3);
|
|
break;
|
|
case 0x3: /* END TEST */
|
|
status = sBtInterface->le_test_mode(HCI_LE_END_TEST_OPCODE, buf, 0);
|
|
break;
|
|
default:
|
|
bdt_log("Unsupported command");
|
|
return;
|
|
break;
|
|
}
|
|
if (status != BT_STATUS_SUCCESS)
|
|
{
|
|
bdt_log("%s Test 0x%x Failed with status:0x%x", __FUNCTION__, cmd, status);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void bdt_cleanup(void)
|
|
{
|
|
bdt_log("CLEANUP");
|
|
sBtInterface->cleanup();
|
|
}
|
|
|
|
/*******************************************************************************
|
|
** Console commands
|
|
*******************************************************************************/
|
|
|
|
static int pos = 0;
|
|
|
|
void do_help(char *p)
|
|
{
|
|
int i = 0;
|
|
char line[128];
|
|
|
|
while (console_cmd_list[i].name != NULL)
|
|
{
|
|
pos = snprintf(line, sizeof(line), "%s", (char*)console_cmd_list[i].name);
|
|
bdt_log("%s %s\n", (char*)line, (char*)console_cmd_list[i].help);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void do_quit(char *p)
|
|
{
|
|
bdt_shutdown();
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* BT TEST CONSOLE COMMANDS
|
|
*
|
|
* Parses argument lists and passes to API test function
|
|
*
|
|
*/
|
|
|
|
void do_init(char *p)
|
|
{
|
|
bdt_init();
|
|
}
|
|
|
|
void do_enable(char *p)
|
|
{
|
|
bdt_enable();
|
|
}
|
|
|
|
void do_disable(char *p)
|
|
{
|
|
bdt_disable();
|
|
}
|
|
void do_dut_mode_configure(char *p)
|
|
{
|
|
bdt_dut_mode_configure(p);
|
|
}
|
|
|
|
void do_le_test_mode(char *p)
|
|
{
|
|
bdt_le_test_mode(p);
|
|
}
|
|
|
|
void do_cleanup(char *p)
|
|
{
|
|
bdt_cleanup();
|
|
}
|
|
|
|
/********* Rfcomm Test toot ***************/
|
|
void do_rfcomm(char *p)
|
|
{
|
|
bdt_rfcomm();
|
|
}
|
|
|
|
|
|
/**********************************************
|
|
Rfcomm connection to remote device
|
|
************************************************/
|
|
void do_rfc_con( char *p)
|
|
{
|
|
char buf[64];
|
|
tRFC conn_param;
|
|
|
|
bdt_log("bdt do_rfc_con");
|
|
memset(buf, 0, 64);
|
|
/*Enter BD address */
|
|
get_str(&p, buf);
|
|
str2bd(buf, &conn_param.data.conn.bdadd);
|
|
memset(buf ,0 , 64);
|
|
get_str(&p, buf);
|
|
conn_param.data.conn.scn = atoi(buf);
|
|
bdt_log("SCN =%d",conn_param.data.conn.scn);
|
|
/* Connection */
|
|
conn_param.param = RFC_TEST_CLIENT;
|
|
sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
|
|
if (sRfcInterface)
|
|
{
|
|
sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
|
|
}
|
|
else
|
|
{
|
|
bdt_log("interface not loaded");
|
|
}
|
|
}
|
|
|
|
|
|
/* For PTS test case BV21 and BV22 */
|
|
|
|
void do_rfc_con_for_test_msc_data(char *p)
|
|
{
|
|
char buf[64];
|
|
tRFC conn_param;
|
|
|
|
bdt_log("bdt do_rfc_con_for_test_msc_data");
|
|
memset(buf, 0, 64);
|
|
/*Enter BD address */
|
|
get_str(&p, buf);
|
|
str2bd(buf, &conn_param.data.conn.bdadd);
|
|
memset(buf ,0 , 64);
|
|
get_str(&p, buf);
|
|
conn_param.data.conn.scn = atoi(buf);
|
|
bdt_log("SCN =%d",conn_param.data.conn.scn);
|
|
/* Connection */
|
|
conn_param.param = RFC_TEST_CLIENT_TEST_MSC_DATA;
|
|
sRfcInterface = (btrfcomm_interface_t *)sBtInterface->
|
|
get_testapp_interface(TEST_APP_RFCOMM);
|
|
if (sRfcInterface)
|
|
{
|
|
sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
|
|
}
|
|
else
|
|
{
|
|
bdt_log("interface not loaded");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Role Switch */
|
|
void do_role_switch(char *p)
|
|
{
|
|
char buf[64];
|
|
tRFC conn_param ;
|
|
|
|
bdt_log("bdt do_role_switch");
|
|
memset(buf ,0 , 64);
|
|
/* Bluetooth Device address */
|
|
get_str(&p, buf);
|
|
str2bd(buf, &conn_param.data.role_switch.bdadd);
|
|
memset(buf ,0 , 64);
|
|
get_str(&p, buf);
|
|
conn_param.data.role_switch.role = atoi(buf);
|
|
/* Role Switch */
|
|
conn_param.param = RFC_TEST_ROLE_SWITCH; //role switch
|
|
sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
|
|
if (sRfcInterface)
|
|
{
|
|
sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
|
|
}
|
|
else
|
|
{
|
|
bdt_log("interface not loaded");
|
|
}
|
|
}
|
|
|
|
void do_rfc_rls (char *p)
|
|
{
|
|
tRFC conn_param;
|
|
|
|
bdt_log("bdt rfc_rls");
|
|
conn_param.param = RFC_TEST_FRAME_ERROR;
|
|
sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
|
|
if (sRfcInterface)
|
|
{
|
|
sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
|
|
}
|
|
else
|
|
{
|
|
bdt_log("interface not loaded");
|
|
}
|
|
|
|
}
|
|
|
|
void do_rfc_send_data (char *p)
|
|
{
|
|
tRFC conn_param;
|
|
|
|
bdt_log("bdt rfc_send_data");
|
|
conn_param.param = RFC_TEST_WRITE_DATA;
|
|
sRfcInterface = (btrfcomm_interface_t *)sBtInterface->get_testapp_interface(TEST_APP_RFCOMM);
|
|
if (sRfcInterface)
|
|
{
|
|
sRfcInterface->rdut_rfcomm_test_interface(&conn_param);
|
|
}
|
|
else
|
|
{
|
|
bdt_log("interface not loaded");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void do_rfcomm_server(char *p)
|
|
{
|
|
bdt_rfcomm_server();
|
|
}
|
|
|
|
void do_rfcomm_disc_frm_server(char *p)
|
|
{
|
|
bdt_rfcomm_disc_from_server();
|
|
}
|
|
/*******************************************************************
|
|
*
|
|
* CONSOLE COMMAND TABLE
|
|
*
|
|
*/
|
|
|
|
const t_cmd console_cmd_list[] =
|
|
{
|
|
/*
|
|
* INTERNAL
|
|
*/
|
|
|
|
{ "help", do_help, "lists all available console commands", 0 },
|
|
{ "quit", do_quit, "", 0},
|
|
|
|
/*
|
|
* API CONSOLE COMMANDS
|
|
*/
|
|
|
|
/* Init and Cleanup shall be called automatically */
|
|
{ "enable", do_enable, ":: enables bluetooth", 0 },
|
|
{ "disable", do_disable, ":: disables bluetooth", 0 },
|
|
{ "dut_mode_configure", do_dut_mode_configure, ":: DUT mode - 1 to enter,0 to exit", 0 },
|
|
{ "le_test_mode", do_le_test_mode, ":: LE Test Mode - RxTest - 1 <rx_freq>, \n\t \
|
|
TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>, \n\t \
|
|
End Test - 3 <no_args>", 0 },
|
|
/* add here */
|
|
{ "rfcomm", do_rfcomm, "rfcomm test", 0},
|
|
{ "server_rfcomm", do_rfcomm_server ,"rfcomm server test", 0},
|
|
{ "dis_client", do_rfcomm_disc_frm_server, "disc from Server", 0},
|
|
{ "rfc_con", do_rfc_con, "rfc_con", 0 },
|
|
{ "rfc_msccon", do_rfc_con_for_test_msc_data, "rfc_msccon", 0 },
|
|
{ "rfc_rls", do_rfc_rls, "rls", 0 },
|
|
{ "rfc_senddata", do_rfc_send_data, "rfc_senddata", 0 },
|
|
{ "role_sw", do_role_switch, "role_sw", 0},
|
|
/* last entry */
|
|
{NULL, NULL, "", 0},
|
|
};
|
|
|
|
/*
|
|
* Main console command handler
|
|
*/
|
|
|
|
static void process_cmd(char *p, unsigned char is_job)
|
|
{
|
|
char cmd[128];
|
|
int i = 0;
|
|
char *p_saved = p;
|
|
|
|
get_str(&p, cmd);
|
|
|
|
/* table commands */
|
|
while (console_cmd_list[i].name != NULL)
|
|
{
|
|
if (is_cmd(console_cmd_list[i].name))
|
|
{
|
|
if (!is_job && console_cmd_list[i].is_job)
|
|
create_cmdjob(p_saved);
|
|
else
|
|
{
|
|
console_cmd_list[i].handler(p);
|
|
}
|
|
return;
|
|
}
|
|
i++;
|
|
}
|
|
bdt_log("%s : unknown command\n", p_saved);
|
|
do_help(NULL);
|
|
}
|
|
|
|
int main (int argc, char * argv[])
|
|
{
|
|
|
|
config_permissions();
|
|
bdt_log("\n:::::::::::::::::::::::::::::::::::::::::::::::::::");
|
|
bdt_log(":: Bluedroid test app starting");
|
|
|
|
if ( HAL_load() < 0 ) {
|
|
perror("HAL failed to initialize, exit\n");
|
|
unlink(PID_FILE);
|
|
exit(0);
|
|
}
|
|
|
|
setup_test_env();
|
|
|
|
/* Automatically perform the init */
|
|
bdt_init();
|
|
|
|
while(!main_done)
|
|
{
|
|
char line[128];
|
|
|
|
/* command prompt */
|
|
printf( ">" );
|
|
fflush(stdout);
|
|
|
|
fgets (line, 128, stdin);
|
|
|
|
if (line[0]!= '\0')
|
|
{
|
|
/* remove linefeed */
|
|
line[strlen(line)-1] = 0;
|
|
|
|
process_cmd(line, 0);
|
|
memset(line, '\0', 128);
|
|
}
|
|
}
|
|
|
|
/* FIXME: Commenting this out as for some reason, the application does not exit otherwise*/
|
|
//bdt_cleanup();
|
|
//cleanup:
|
|
HAL_unload();
|
|
|
|
bdt_log(":: Bluedroid test app terminating");
|
|
|
|
return 0;
|
|
}
|