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

📄 bt_ip_dt.c

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

#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 "apps/httpd.h"

#include "stdlib.h"

#define BT_IP_DEBUG DBG_ON /* Control debug messages */

enum bt_profile {
  LAP_PROFILE, DUN_PROFILE
};

struct bt_state {
  enum bt_profile profile;
  struct tcp_pcb *tcppcb;
  struct bd_addr bdaddr;
  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);

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.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);
}
/*-----------------------------------------------------------------------------------*/
/*
 * ppp_connected():
 *
 * Called by PPP when a LCP and IPCP connection has been established.
 * Connects to a given TCP host.
 *
 */
/*-----------------------------------------------------------------------------------*/
err_t
ppp_connected(void *arg, struct ppp_pcb *pcb, err_t err)
{
  struct tcp_pcb *tcppcb;
  struct ip_addr ipaddr;

  LWIP_DEBUGF(BT_IP_DEBUG, ("ppp_connected: err = %d\n", err));
  
  /* return ppp_echo(pcb, NULL); */

  if(err != ERR_OK) {
    netif_remove(pcb->bluetoothif);
    pcb->bluetoothif = NULL;
    //TODO: RESTART??
    return ERR_OK;
  }

  tcppcb = tcp_new();
  IP4_ADDR(&ipaddr, 130,240,45,234);
  return tcp_connect(tcppcb, &ipaddr, 8989, tcp_connected);
}
/*-----------------------------------------------------------------------------------*/
/*
 * at_input():
 *
 * Called by RFCOMM during the DUN profile GPRS connection attempt.
 * When a GPRS connection is established, PPP is connected.
 *
 */
/*-----------------------------------------------------------------------------------*/
u8_t at_state;
err_t
at_input(void *arg, struct rfcomm_pcb *pcb, struct pbuf *p, err_t err) 
{
  struct ppp_pcb *ppppcb;
  struct ip_addr ipaddr, netmask, gw;
  struct netif *netif;;
  
  //  u16_t i;
  struct pbuf *q;
  
  //for(q = p; q != NULL; q = q->next) {
  //  for(i = 0; i < q->len; ++i) {
  //    LWIP_DEBUGF(BT_IP_DEBUG, ("at_input: 0x%x\n",((u8_t *)p->payload)[i]));
  //  }
  //  LWIP_DEBUGF(BT_IP_DEBUG, ("*\n"));
  //}
  
  LWIP_DEBUGF(BT_IP_DEBUG, ("at_input: %s\n", ((u8_t *)p->payload)));
  LWIP_DEBUGF(BT_IP_DEBUG, ("state == %d\n", at_state));
  if(at_state == 0 && ((u8_t *)p->payload)[2] == 'O') {
    //q = pbuf_alloc(PBUF_RAW, sizeof("AT&F\r")-1, PBUF_RAM);
    //((u8_t *)q->payload) = "AT&F\r";
    q = pbuf_alloc(PBUF_RAW, sizeof("ATE1\r"), PBUF_RAM);
    ((u8_t *)q->payload) = "ATE1\r";
    if(rfcomm_cl(pcb)) {
      rfcomm_uih_credits(pcb, 2, q);
    } else {
      rfcomm_uih(pcb, rfcomm_cn(pcb), q);
    }
    pbuf_free(q);
    
    at_state = 1;
  } else if(at_state == 1 && ((u8_t *)p->payload)[2] == 'O') {
    q = pbuf_alloc(PBUF_RAW, sizeof("AT+cgdcont=1,\"IP\",\"online.telia.se\"\r"), PBUF_RAM);
    ((u8_t *)q->payload) = "AT+cgdcont=1,\"IP\",\"online.telia.se\"\r";
    if(rfcomm_cl(pcb)) {
      rfcomm_uih_credits(pcb, 2, q);
    } else {
      rfcomm_uih(pcb, rfcomm_cn(pcb), q);
    }
    pbuf_free(q);
   
    at_state = 4;
  } else if(at_state == 4 && ((u8_t *)p->payload)[2] == 'O') {
    q = pbuf_alloc(PBUF_RAW, sizeof("ATD*99***1#\r"), PBUF_RAM);
    ((u8_t *)q->payload) = "ATD*99***1#\r";
    if(rfcomm_cl(pcb)) {
      rfcomm_uih_credits(pcb, 2, q);
    } else {
      rfcomm_uih(pcb, rfcomm_cn(pcb), q);
    }
    pbuf_free(q);
  
    at_state = 5;
  } else if(at_state == 5 && ((u8_t *)p->payload)[2] == 'C') {
    at_state = 6;
    /* Establish a PPP connection */
    if((ppppcb = ppp_new(pcb)) == NULL) {
      LWIP_DEBUGF(BT_IP_DEBUG, ("rfcomm_msc_rsp: Could not alloc PPP pcb\n"));
      return ERR_MEM;
    }
    /* Add PPP network interface to lwIP */
    gw.addr = 0;
    ipaddr.addr = 0;
    IP4_ADDR(&netmask, 255,255,255,0);
    
    netif = netif_add(&ipaddr, &netmask, &gw, NULL, bluetoothif_init, ip_input);
    
    netif_set_default(netif);
    
    ppp_netif(ppppcb, netif);

    rfcomm_recv(pcb, ppp_input);
    ppp_disconnected(ppppcb, ppp_is_disconnected);
    return ppp_connect(ppppcb, ppp_connected);
  }
  pbuf_free(p);

  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
 * pin_req():
 *
 * Called by HCI when a request for a PIN code has been received. A PIN code is 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -