📄 test.c
字号:
/* * test.c -- Test layer used to verify stack * * Copyright (C) 2000, 2001 Axis Communications AB * * Author: Mats Friden <matsf.friden@axis.com> * * 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. * * Exceptionally, Axis Communications AB grants discretionary and * conditional permissions for additional use of the text contained * in the company's release of the AXIS OpenBT Stack under the * provisions set forth hereunder. * * Provided that, if you use the AXIS OpenBT Stack with other files, * that do not implement functionality as specified in the Bluetooth * System specification, to produce an executable, this does not by * itself cause the resulting executable to be covered by the GNU * General Public License. Your use of that executable is in no way * restricted on account of using the AXIS OpenBT Stack code with it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the provisions of the GNU * General Public License. * * $Id: test.c,v 1.31 2001/10/18 15:49:25 pkj Exp $x * *//****************** INCLUDE FILES SECTION ***********************************/#define __NO_VERSION__ /* don't define kernel_version in module.h */#ifdef __KERNEL__#include <linux/malloc.h>#include <linux/interrupt.h>#include <linux/bluetooth/test.h>#include <linux/bluetooth/btcommon.h>#include <linux/bluetooth/btmem.h>#include <linux/bluetooth/l2cap.h>#include <linux/bluetooth/unplug_test.h>#else#include <string.h>#include <errno.h>#include "include/test.h"#include "include/btcommon.h"#include "include/btdebug.h"#include "include/btmem.h"#include "include/l2cap.h"#include "include/unplug_test.h"#endif/****************** DEBUG CONSTANT AND MACRO SECTION ************************/#define TEST_DBG_STR " TEST "#define TEST_DEBUG_STATE 1#define TEST_DEBUG_CON 1#define TEST_DEBUG_RCV 1#define TEST_DEBUG_XMIT 1#define TEST_DEBUG_MISC 1#define TEST_DEBUG_DATA 1#if TEST_DEBUG_STATE/* State machine */#define D_STATE(fmt...) printk(TEST_DBG_STR fmt)#define PRINTSTATE(con) (printk("Current state : %s\n",\ state_name[con->current_state]))#else/* State machine */#define D_STATE(fmt)#define PRINTSTATE(con)#endif#if TEST_DEBUG_RCV/* Receive data */#define D_RCV(fmt...) printk(TEST_DBG_STR fmt)#else#define D_RCV(fmt...)#endif#if TEST_DEBUG_XMIT/* Send data */#define D_XMIT(fmt...) printk(TEST_DBG_STR fmt)#else#define D_XMIT(fmt...)#endif#if TEST_DEBUG_MISC/* Misc */#define D_MISC(fmt...) printk(TEST_DBG_STR fmt)#else#define D_MISC(fmt...)#endif#if TEST_DEBUG_DATA#define PRINTPKT(str, data, len) print_data(str, data, len)#else#define PRINTPKT(str, data, len)#endif/* Values used for the L2CAP configuration process */#define TEST_MTU 672 /* Default, why should we be different */#define TEST_QOS 0x01 /* Best effort */#define TEST_FLUSH_TIMEOUT 0xffff /* Reliable channel, infinite amout of retransmissions */#define PRINTPSM(con) (printk("PSM : 0x%x\n", con->psm))/****************** TYPE DEFINITION SECTION *********************************/l2cap_con *testcon;l2cap_con *testcon2;l2cap_con *testcon3;s32 emulate_pending = 0;s32 test_inmtu = 0;s32 dont_send_config_req = 0;s32 use_multiple_conf_params = 0;s32 disable_testpsm = 0;s32 dont_send_disconnect_rsp = 0;u8 testdata[UPTEST_DATA_LEN];#ifdef __KERNEL__#define strtoul simple_strtoul#endifvoid test_init(void){ protocol_layer this_layer; DSYS("Initialising TEST\n"); /* Set the confirm and indication functions for the L2CAP-layer */ this_layer.con_ind = test_connect_ind; this_layer.conf_ind = test_config_ind; this_layer.disc_ind = test_disconnect_ind; this_layer.con_pnd = test_connect_pnd; this_layer.con_cfm = test_connect_cfm; this_layer.conf_cfm = test_config_cfm; this_layer.disc_cfm = test_disconnect_cfm; this_layer.receive_data = test_receive_data; l2cap_register_upper(L2CAP_TEST_LAYER, &this_layer); l2cap_register_upper(L2CAP_TEST2_LAYER, &this_layer); l2cap_register_upper(L2CAP_TEST3_LAYER, &this_layer);}void test_shutdown(void){ DSYS("Shutting down TEST\n");}s32test_connect_req(BD_ADDR bd){ s32 retval = 0; D_STATE("test_connect_req to psm 0x%x\n", L2CAP_TEST_LAYER); if ((retval = l2ca_connect_req(bd, L2CAP_TEST_LAYER)) < 0) { D_ERR(" tcs_connect_req: l2ca_connect_req failed\n"); } return retval;}s32test_connect_psmreq(BD_ADDR bd, u16 psm){ D_STATE("test_connect_req on psm 0x%x\n", psm); return l2ca_connect_req(bd, psm);}static voidtest_timeout(unsigned long ptr){ struct l2cap_con *con = (struct l2cap_con *)ptr; printk("Test timeout\n"); if (emulate_pending) { printk("Now sending config rsp non-pending...\n"); emulate_pending = 0; if (l2ca_connect_rsp(con, RES_SUCCESS, STAT_NOINFO)) { D_ERR("test_connect_ind: l2ca_connect_rsp failed\n"); return; } emulate_pending = 0; }}void test_connect_ind(l2cap_con *con) {#ifdef __KERNEL__ static struct timer_list test_timer;#endif D_STATE("test_connect_ind : remote cid : %d\n", con->remote_cid); PRINTPSM(con); if (emulate_pending) { printk("Sending connect rsp pending and waiting 5 secs\n"); if (l2ca_connect_rsp(con, RES_PENDING, STAT_AUTHENTPEND)) { D_ERR("test_connect_ind: l2ca_connect_rsp failed\n"); return; } /* start 5 sec timer */ #ifdef __KERNEL__ init_timer(&test_timer); test_timer.function = test_timeout; test_timer.data = (unsigned long)con; test_timer.expires = jiffies + 5*HZ; add_timer(&test_timer); return;#else sleep(5);#endif } if (disable_testpsm == 1) { /* send back psm not supp */ if (l2ca_connect_rsp(con, RES_PSMNEG, 0)) { D_ERR("test_connect_ind: l2ca_connect_rsp failed\n"); return; } printk("Now enabling test psm:s again...\n"); disable_testpsm = 0; return; } printk("now sending back result success !\n"); if (l2ca_connect_rsp(con, RES_SUCCESS, STAT_NOINFO)) { D_ERR("test_connect_ind: l2ca_connect_rsp failed\n"); return; } /* (temp fix for test interface) store connection */ if (con->psm == L2CAP_TEST_LAYER) testcon = con; else if (con->psm == L2CAP_TEST2_LAYER) testcon2 = con; else if (con->psm == L2CAP_TEST3_LAYER) testcon3 = con;}/* only client receives connect pnd */void test_connect_pnd(l2cap_con *con, s32 status){ D_STATE("test_connect_pnd : reason %d\n", status); PRINTPSM(con); if (con->psm == L2CAP_TEST_LAYER) testcon = con; else if (con->psm == L2CAP_TEST2_LAYER) testcon2 = con; else if (con->psm == L2CAP_TEST3_LAYER) testcon3 = con;}/* only client receives connect cfm */void test_connect_cfm(l2cap_con *con, s32 status){ D_STATE("test_connect_cfm\n"); PRINTPSM(con); if(status) { D_STATE("Connect failed: Status %d\n", status); return; } if (!l2ca_local_conf_done(con)) { if (dont_send_config_req) { printk("Don't send back config_req...\n"); printk("Now waiting for initator to shutdown link...\n"); dont_send_config_req = 0; return; } /* still haven't sent config request yet */ if (use_multiple_conf_params) { if (l2ca_config_req(con, 1280, NULL, 0x1234, 0)) { D_ERR("test_config_cfm : Configuration request failed\n"); } } else { if (l2ca_config_req(con, 0, NULL, 0, 0)) { D_ERR("test_config_cfm : Configuration request failed\n"); } } /* store connection */ if (con->psm == L2CAP_TEST_LAYER) testcon = con; else if (con->psm == L2CAP_TEST2_LAYER) testcon2 = con; else if (con->psm == L2CAP_TEST3_LAYER) testcon3 = con; } else D_RCV("test_config_cfm : already have sent config request\n");}/* someone wants to configure l2cap... */void test_config_ind(l2cap_con* con){ D_STATE("test_config_ind : remote cid : %d remote_mtu : %d\n", con->remote_cid, con->remote_mtu); /* check if we have sent a pos response yet */ if (!l2ca_remote_conf_done(con)) { /* still haven't sent a pos configure response*/ if (l2ca_config_rsp(con, 0, NULL, CONF_SUCCESS)) { D_ERR("test_config_ind : Configuration response failed\n"); } } else printk("test_config_ind : already have sent back a pos response\n"); /* check if we received a pos response on a previous config req */ if (!l2ca_local_conf_done(con)) { /* still haven't sent config request yet */ D_RCV("Setting local mtu to %d on con (%d:%d)\n", con->local_mtu, con->local_cid, con->remote_cid); if (dont_send_config_req) { printk("Don't send back config_req...\n"); printk("Now waiting for initator to shutdown link...\n"); dont_send_config_req = 0; return; } /* still haven't sent config request yet */ if (use_multiple_conf_params) { if (l2ca_config_req(con, 1280, NULL, 0x1234, 0)) { D_ERR("test_config_cfm : Configuration request failed\n"); } } else { if (l2ca_config_req(con, test_inmtu, NULL, 0, 0)) D_ERR("test_config_ind : configuration request failed\n"); if (test_inmtu) { printk("Set back our test_inmtu to default\n"); test_inmtu = 0; } } } else D_RCV("already ready with config req\n");}void test_config_cfm(l2cap_con *con, s32 status){ D_STATE("test_config_cfm : remote cid : %d\n", con->remote_cid); D_STATE("Now we have an open l2cap channel\n"); /* negotiate upper protocol */}void test_disconnect_ind(l2cap_con *con) { D_STATE("test_disconnect_ind : (%d:%d)\n", con->local_cid, con->remote_cid); if(!dont_send_disconnect_rsp) { l2ca_disconnect_rsp(con); }}void test_disconnect_cfm(l2cap_con *con){ D_STATE("TEST_disconnect_cfm: remote cid : %d\n", con->remote_cid);}s32 test_disconnect_req(l2cap_con *con){ if (!con) return -1; D_STATE("test_disconnect_req\n"); return l2ca_disconnect_req(con);}void test_receive_data(l2cap_con *con, unsigned char* data, u32 len){ PRINTPSM(con); PRINTPKT("test_receive_data : ", data, len); }s32 test_send_data(l2cap_con *con, u8 *testdata, s32 len){ bt_tx_buf *tx_buf; printk("test_send_data : sending %d bytes\n", len); if (!con) { D_ERR("test_send_data : No connection object\n"); return -1; } /* tx bufs are all the same for each upper layer ... FIX one common */ tx_buf = subscribe_bt_buf(sizeof(rfcomm_tx_buf) + len); if (!tx_buf) { D_ERR("test_send_data : didn't get a valid tx_buf\n"); return -ENOMEM; } tx_buf->cur_len = len; memcpy(tx_buf->data+sizeof(rfcomm_tx_buf), testdata, len); return l2cap_send_data(tx_buf, con);}/* FIXME -- add new commands in user application menu !!!! */s32test_process_cmd(unsigned char *cmd, s32 size){ #ifdef CONFIG_BLUETOOTH_UNPLUG_TEST int testcase, tmp[10], i; unsigned char bd[6], char_buf[4]; char_buf[3] = 0; if(!strncmp(cmd, "bb_conn ", 8)) { char *p = cmd + 8; for (i = 5; i >= 0; i--) { bd[i] = strtoul(p, &p, 16); printk("bb_conn read [%d] = 0x%x\n", i, bd[i]); p=p+1; } printk("Connecting BB to bd : %02X:%02X:%02X:%02X:%02X:%02X\n", bd[5], bd[4], bd[3], bd[2], bd[1], bd[0]); l2cap_create_con(bd); return lp_connect_req(bd); } else if(strncmp(cmd, "t ", 2) == 0) { testcase = strtoul(cmd+2, NULL, 0); if (testcase > 0) { return process_test_cmd(testcase); } else { printk("test_process_cmd: Couldn't parse testcase\n"); } } else if(!strncmp(cmd, "bb_disc ", 8)) { int i = strtoul(cmd+8, NULL, 0); return lp_disconnect((unsigned short)i); } else if(!strncmp(cmd, "lcid_disconnect ", 16)) { l2cap_con *con = NULL; int i = strtoul(cmd + 16, NULL, 0); if((con = get_lcon(i))) { return l2ca_disconnect_req(con); } else { printk("Didn't find lcid %d\n", i); return -1; } } else if(!strncmp(cmd, "test_case_reject ", 17)) { unsigned short fake_psm = 0x4561; char *p = cmd + 8; for (i = 0; i < 6; i++) { bd[i] = strtoul(p, &p, 0); printk("bb_conn read [%d] = 0x%x\n", i, bd[i]); p++; } return l2ca_connect_req(bd, fake_psm); } else if(!strncmp(cmd, "tx_data ", 8)) { int lcid, len; char *p = cmd+8; l2cap_con *con; lcid = strtoul(p, &p, 0); len = strtoul(p+1, &p, 0); /* first find connection based on local cid */ con = get_lcon(lcid); if (!con) { printk("Found no connection with lcid : %d\n", lcid); return -1; } return test_send_data(con, testdata, len); } else if(!strncmp(cmd, "sdptest ", 8)) { int n = strtoul(cmd+8, NULL, 0); return do_sdp_test(n); } else if(!strcmp(cmd, "test_case_disable_disconnect")) { dont_send_disconnect_rsp = 1; return 0; } else if(!strcmp(cmd, "test_case_enable_disconnect")) { dont_send_disconnect_rsp = 0; return 0; } else { printk("Unknown test cmd!\n"); return -1; } #else printk("test_process_cmd: Not available\n"); return 0;#endif}/****************** END OF FILE test.c ***************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -