📄 bt_ip_lap.c
字号:
/*
* Copyright (c) 2003 EISLAB, Lulea University of Technology.
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
*
* This file is part of the lwBT Bluetooth stack.
*
* Author: Conny Ohult <conny@sm.luth.se>
*
*/
/*-----------------------------------------------------------------------------------*/
/* bt_ip_lap.c
*
* This is a control application that initialises a host controller and connects to a
* network as a DT through a DUN or LAP enabled device. When a network connection has
* been established, it initialises its own LAP server.
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/stats.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "phybusif.h"
#include "netif/lwbt/lwbt_memp.h"
#include "netif/lwbt/hci.h"
#include "netif/lwbt/l2cap.h"
#include "netif/lwbt/sdp.h"
#include "netif/lwbt/rfcomm.h"
#include "netif/lwbt/ppp.h"
#include "netif/lwbt/nat.h"
#include "apps/httpd.h"
#include "stdlib.h"
#define BT_IP_DEBUG DBG_ON /* Controls debug messages */
enum bt_profile {
LAP_PROFILE, DUN_PROFILE
};
struct bt_state {
enum bt_profile profile;
struct tcp_pcb *tcppcb;
struct bd_addr bdaddr;
struct pbuf *p;
u8_t btctrl;
u8_t cn;
} bt_ip_state;
/* Forward declarations */
err_t rfcomm_connected(void *arg, struct rfcomm_pcb *tpcb, err_t err);
err_t l2cap_connected(void *arg, struct l2cap_pcb *pcb, u16_t result, u16_t status);
err_t inquiry_complete(void *arg, struct hci_pcb *pcb, struct hci_inq_res *ires, u16_t result);
err_t command_complete(void *arg, struct hci_pcb *pcb, u8_t ogf, u8_t ocf, u8_t result);
err_t pin_req(void *arg, struct bd_addr *bdaddr);
err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err);
void nat_reset_all(void);
static const u8_t lap_service_record[] = {
0x35, 0x8,
0x9, 0x0, 0x0, 0xa, 0x0, 0x0, 0xff, 0xff, /* Service record handle attribute */
0x35, 0x8,
0x9, 0x0, 0x1, 0x35, 0x3, 0x19, 0x11, 0x2, /* Service class ID list attribute */
0x35, 0x11,
0x9, 0x0, 0x4, 0x35, 0xc, 0x35, 0x3, 0x19, 0x1, 0x0, 0x35, 0x5, 0x19, 0x0, 0x3, 0x8, 0x1 /* Protocol descriptor list attribute */
};
u8_t bt_ip_netifn;
/*-----------------------------------------------------------------------------------*/
/*
* bt_ip_start():
*
* Called by the main application to initialize and connect to a network
*
*/
/*-----------------------------------------------------------------------------------*/
void
bt_ip_start(void)
{
hci_reset_all();
l2cap_reset_all();
sdp_reset_all();
rfcomm_reset_all();
ppp_reset_all();
LWIP_DEBUGF(BT_IP_DEBUG, ("bt_ip_start\n"));
hci_cmd_complete(command_complete);
hci_pin_req(pin_req);
bt_ip_state.btctrl = 0;
bt_ip_state.p = NULL;
bt_ip_state.tcppcb = NULL;
bt_ip_netifn = 0;
hci_reset();
}
/*-----------------------------------------------------------------------------------*/
/*
* bt_ip_tmr():
*
* Called by the main application to initialize and connect to a network
*
*/
/*-----------------------------------------------------------------------------------*/
void
bt_ip_tmr(void)
{
u8_t update_cmd[12];
update_cmd[0] = 1;
update_cmd[1] = 0;
update_cmd[2] = bt_ip_state.bdaddr.addr[5];
update_cmd[3] = bt_ip_state.bdaddr.addr[4];
update_cmd[4] = bt_ip_state.bdaddr.addr[3];
update_cmd[5] = bt_ip_state.bdaddr.addr[2];
update_cmd[6] = bt_ip_state.bdaddr.addr[1];
update_cmd[7] = bt_ip_state.bdaddr.addr[0];
update_cmd[8] = 0x00;
update_cmd[9] = 0x00;
update_cmd[10] = 0x00;
update_cmd[11] = 0x00;
LWIP_DEBUGF(BT_IP_DEBUG, ("bt_ip_tmr: Update cmd bd address: 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", update_cmd[2], update_cmd[3], update_cmd[4], update_cmd[5], update_cmd[6], update_cmd[7]));
if(bt_ip_state.tcppcb != NULL) {
tcp_write(bt_ip_state.tcppcb, &update_cmd, 12, 1);
}
}
/*-----------------------------------------------------------------------------------*/
/*
* ppp_is_disconnected():
*
* Called by PPP when the remote PPP protocol or upper layer was disconnected.
* Disconnects the IP layer.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
ppp_is_disconnected(void *arg, struct ppp_pcb *pcb, u16_t proto, err_t err)
{
//TODO: CHECK PROTOCOL
LWIP_DEBUGF(BT_IP_DEBUG, ("ppp_disconnected\n"));
ppp_close(pcb);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* rfcomm_disconnected():
*
* Called by RFCOMM when the remote RFCOMM protocol or upper layer was disconnected.
* Disconnects the PPP protocol.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
rfcomm_disconnected(void *arg, struct rfcomm_pcb *pcb, err_t err)
{
err_t ret = ERR_OK;
LWIP_DEBUGF(BT_IP_DEBUG, ("rfcomm_disconnected: CN = %d\n", rfcomm_cn(pcb)));
if(rfcomm_cn(pcb) != 0) {
ret = ppp_lp_disconnected(pcb);
}
rfcomm_close(pcb);
return ret;
}
/*-----------------------------------------------------------------------------------*/
/*
* l2cap_disconnected_ind():
*
* Called by L2CAP to indicate that remote L2CAP protocol disconnected.
* Disconnects the RFCOMM protocol and the ACL link before it initializes a search for
* other devices.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
l2cap_disconnected_ind(void *arg, struct l2cap_pcb *pcb, err_t err)
{
err_t ret = ERR_OK;
LWIP_DEBUGF(BT_IP_DEBUG, ("l2cap_disconnected_ind: L2CAP disconnected\n"));
if(pcb->psm == SDP_PSM) {
sdp_lp_disconnected(pcb);
l2cap_close(pcb);
} else if(pcb->psm == RFCOMM_PSM) {
ret = rfcomm_lp_disconnected(pcb);
/* We can do this since we know that we are the only channel on the ACL link. If ACL link already is
down we get an ERR_CONN returned */
hci_disconnect(&(pcb->remote_bdaddr), HCI_OTHER_END_TERMINATED_CONN_USER_ENDED);
l2cap_close(pcb);
bt_ip_start();
}
return ret;
}
/*-----------------------------------------------------------------------------------*/
/*
* bluetoothif_init():
*
* Called by lwIP to initialize the lwBT network interface.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
bluetoothif_init(struct netif *netif)
{
netif->name[0] = 'b';
netif->name[1] = '0' + bt_ip_netifn++;
netif->output = ppp_netif_output;
netif->state = NULL;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_connected():
*
* Called by TCP when a connection has been established.
* Connects to a remote gateway and give the TCP connection to the HTTP server
* application
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
u8_t update_cmd[12];
LWIP_DEBUGF(BT_IP_DEBUG, ("tcp_connected\n"));
update_cmd[0] = 1;
update_cmd[1] = 0;
update_cmd[2] = bt_ip_state.bdaddr.addr[5];
update_cmd[3] = bt_ip_state.bdaddr.addr[4];
update_cmd[4] = bt_ip_state.bdaddr.addr[3];
update_cmd[5] = bt_ip_state.bdaddr.addr[2];
update_cmd[6] = bt_ip_state.bdaddr.addr[1];
update_cmd[7] = bt_ip_state.bdaddr.addr[0];
LWIP_DEBUGF(BT_IP_DEBUG, ("tcp_connected: bd address: 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", bt_ip_state.bdaddr.addr[0], bt_ip_state.bdaddr.addr[1], bt_ip_state.bdaddr.addr[2], bt_ip_state.bdaddr.addr[3], bt_ip_state.bdaddr.addr[4], bt_ip_state.bdaddr.addr[5]));
LWIP_DEBUGF(BT_IP_DEBUG, ("tcp_connected: Update cmd bd address: 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", update_cmd[2], update_cmd[3], update_cmd[4], update_cmd[5], update_cmd[6], update_cmd[7]));
update_cmd[8] = 0x00;
update_cmd[9] = 0x00;
update_cmd[10] = 0x00;
update_cmd[11] = 0x00;
tcp_write(pcb, &update_cmd, 12, 1);
LWIP_DEBUGF(BT_IP_DEBUG, ("tcp_connected: Update command sent\n"));
bt_ip_state.tcppcb = pcb;
return http_accept((void *)&(bt_ip_state.bdaddr), pcb, ERR_OK);
}
/*-----------------------------------------------------------------------------------*/
err_t
ppp_accept(void *arg, struct ppp_pcb *pcb, err_t err)
{
LWIP_DEBUGF(BT_IP_DEBUG, ("ppp_accept\n"));
if(err != ERR_OK) {
netif_remove(pcb->bluetoothif);
pcb->bluetoothif = NULL;
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
err_t
modem_emu(void *arg, struct rfcomm_pcb *pcb, struct pbuf *p, err_t err)
{
u8_t *data = p->payload;
struct pbuf *q = NULL;
u16_t proto;
u8_t code;
u8_t i;
LWIP_DEBUGF(BT_IP_DEBUG, ("modem_emu: p->len == %d p->tot_len == %d\n", p->len, p->tot_len));
for (i = 0; i < p->len; ++i) {
if(data[i] == PPP_END) {
if ((p->len - i) >= 7) {
if (data[i + 2] == PPP_ESC) {
proto = ntohs(*((u16_t *)(((u8_t *)p->payload) + i + 4)));
}
else {
proto = ntohs(*((u16_t *)(((u8_t *)p->payload) + i + 3)));
}
if(proto == PPP_LCP) {
code = data[i + 7] ^ 0x20;
if(code == LCP_CFG_REQ) {
rfcomm_recv(pcb, ppp_input);
ppp_input(arg, pcb, p, ERR_OK);
}
}
}
return ERR_OK;
}
}
if(arg != NULL) {
q = pbuf_alloc(PBUF_RAW, p->len + ((struct pbuf *)arg)->len, PBUF_RAM);
memcpy((u8_t *)q->payload, (u8_t *)((struct pbuf *)arg)->payload, ((struct pbuf *)arg)->len);
memcpy(((u8_t *)q->payload) + ((struct pbuf *)arg)->len, (u8_t *)p->payload, p->len);
pbuf_free((struct pbuf *)arg);
(struct pbuf *)arg = NULL;
pbuf_free(p);
data = q->payload;
p = q;
}
for (i = 0; i < p->len; ++i) {
LWIP_DEBUGF(BT_IP_DEBUG, ("modem_emu: %c %d\n", data[i], data[i]));
}
if(p->len == 0) {
LWIP_DEBUGF(BT_IP_DEBUG, ("modem_emu: p->len == 0\n"));
q = pbuf_alloc(PBUF_RAW, sizeof("OK\r\n"), PBUF_RAM);
((u8_t *)q->payload) = "OK\r\n";
pbuf_free(p);
} else if(!strncmp(data, "ATD", 3)) {
LWIP_DEBUGF(BT_IP_DEBUG, ("modem_emu: !strncasecmp(data, \"ATD\", 3)\n"));
q = pbuf_alloc(PBUF_RAW, sizeof("CONNECT\r\n"), PBUF_RAM);
((u8_t *)q->payload) = "CONNECT\r\n";
pbuf_free(p);
} else if(!strncmp(data, "CLIENT", 6)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -