⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bt_ip_lap.c

📁 蓝牙协议源代码 bluetooth stack for lwip
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -