www.pudn.com > 蓝牙协议源代码.zip > uartif.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  
 * 
 */ 
 
/*-----------------------------------------------------------------------------------*/ 
/* uartif.c 
 * 
 * Implementation of the HCI UART transport layer for RTXC 
 */ 
/*-----------------------------------------------------------------------------------*/ 
 
#include "lwbtopts.h" 
#include "phybusif.h" 
#include "netif/lwbt/hci.h" 
#include "lwip/debug.h" 
 
#include "rtxcapi.h" 
#include "csema.h" 
 
#include  /* For TX of data. Change this to represent the processor you are using with your RTXC OS */ 
 
/* Define this to send one byte on the UART */ 
#define UART_SEND(x) do {U0TB = x; KS_wait(SIO0OSEM);} while(0) 
 
/*-----------------------------------------------------------------------------------*/ 
/*  
 * phybusif_init(): 
 * 
 * Initializes the physical bus interface 
 */ 
/*-----------------------------------------------------------------------------------*/ 
void 
phybusif_init(void) 
{ 
} 
/*-----------------------------------------------------------------------------------*/ 
/*  
 * phybusif_reset(): 
 * 
 * Resets the physical bus interface control block to its initial state. 
 */ 
/*-----------------------------------------------------------------------------------*/ 
err_t 
phybusif_reset(struct phybusif_cb *cb)  
{ 
  /* Init new ctrl block */ 
  /* Alloc new pbuf. lwIP will handle dealloc */ 
  if((cb->p = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL)) == NULL) { 
    DEBUGF(PHYBUSIF_DEBUG, ("phybusif_reset: Could not allocate memory for pbuf\n")); 
    return ERR_MEM; /* Could not allocate memory for pbuf */ 
  } 
  cb->q = cb->p; /* Make p the pointer to the head of the pbuf chain and q to the tail */ 
   
  cb->tot_recvd = 0; 
  cb->recvd = 0;  
 
  cb->bcount = 0;  
  cb->bsize = 0; 
 
  cb->state = W4_PACKET_TYPE; 
  return ERR_OK; 
} 
/*-----------------------------------------------------------------------------------*/ 
/*  
 * phybusif_reset(): 
 * 
 * Handle incoming DMA data by parsing the HCI header and forwarding it to the HCI. 
 */ 
/*-----------------------------------------------------------------------------------*/ 
err_t 
phybusif_input(struct phybusif_cb *cb)  
{ 
  u16_t i = 0; 
  u8_t n; 
 
  for(i = cb->bcount; i < cb->bsize; i++) { 
    switch(cb->state) { 
    case W4_PACKET_TYPE: 
      switch(cb->dmabuf[i]) { 
      case HCI_ACL_DATA_PACKET: 
	cb->state = W4_ACL_HDR; 
	break; 
      case HCI_EVENT_PACKET: 
	cb->state = W4_EVENT_HDR; 
	break; 
      default: 
        DEBUGF(PHYBUSIF_DEBUG, ("phybusif_input: Unknown packet type 0x%x\n", cb->dmabuf[i])); 
	break; 
      } 
      break; 
    case W4_EVENT_HDR: 
      ((u8_t *)cb->q->payload)[cb->recvd] = cb->dmabuf[i]; 
      cb->tot_recvd++; 
      cb->recvd++; 
      if(cb->recvd == HCI_EVENT_HDR_LEN) { 
	cb->evhdr = cb->p->payload; 
	pbuf_header(cb->p, -HCI_EVENT_HDR_LEN); 
	cb->recvd = cb->tot_recvd = 0; 
	if(cb->evhdr->len > 0) { 
	  cb->state = W4_EVENT_PARAM; 
	} else { 
	  hci_event_input(cb->p); /* Handle incoming event */ 
	  pbuf_free(cb->p); 
	  phybusif_reset(cb); 
	  cb->bcount = i + 1; 
	  return ERR_OK; /* Since there most likley won't be any more data in the input buffer */ 
	} 
      } 
      break; 
    case W4_EVENT_PARAM: 
      ((u8_t *)cb->q->payload)[cb->recvd] = cb->dmabuf[i]; 
      cb->tot_recvd++; 
      cb->recvd++; 
      if(cb->recvd == cb->q->len) { /* Pbuf full. alloc and add new tail to chain */ 
        cb->recvd = 0; 
        if((cb->q = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL)) == NULL) { 
	  DEBUGF(PHYBUSIF_DEBUG, ("phybusif_input: Could not allocate memory for event parameter pbuf\n")); 
	  return ERR_MEM; /* Could not allocate memory for pbuf */ 
	} 
	pbuf_chain(cb->p, cb->q); 
	pbuf_free(cb->q); 
      } 
      if(cb->tot_recvd == cb->evhdr->len) { 
	hci_event_input(cb->p); /* Handle incoming event */ 
        pbuf_free(cb->p); 
	phybusif_reset(cb); 
	cb->bcount = i + 1; 
        return ERR_OK; /* Since there most likley won't be any more data in the input buffer */ 
      } 
      break; 
    case W4_ACL_HDR: 
      ((u8_t *)cb->q->payload)[cb->recvd] = cb->dmabuf[i]; 
      cb->tot_recvd++; 
      cb->recvd++; 
      if(cb->recvd == HCI_ACL_HDR_LEN) { 
	cb->aclhdr = cb->p->payload; 
	pbuf_header(cb->p, -HCI_ACL_HDR_LEN); 
	cb->recvd = cb->tot_recvd = 0; 
	if(cb->aclhdr->len > 0) { 
	  cb->state = W4_ACL_DATA; 
	} else { 
	  DEBUGF(PHYBUSIF_DEBUG, ("phybusif_reset: Forward Empty ACL packet to higher layer\n")); 
	  hci_acl_input(cb->p); /* Handle incoming ACL data */ 
	  phybusif_reset(cb); 
	  cb->bcount = i + 1; 
	  return ERR_OK; /* Since there most likley won't be any more data in the input buffer */ 
	} 
      } 
      break; 
    case W4_ACL_DATA: 
      ((u8_t *)cb->q->payload)[cb->recvd] = cb->dmabuf[i]; 
      cb->tot_recvd++; 
      cb->recvd++; 
      if(cb->recvd == cb->q->len) { /* Pbuf full. alloc and add new tail to chain */ 
        cb->recvd = 0; 
        if((cb->q = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL)) == NULL) { 
	  DEBUGF(PHYBUSIF_DEBUG, ("phybusif_input: Could not allocate memory for ACL data pbuf\n")); 
	  return ERR_MEM; /* Could not allocate memory for pbuf */ 
	} 
        pbuf_chain(cb->p, cb->q); 
	pbuf_free(cb->q); 
      } 
      if(cb->tot_recvd == cb->aclhdr->len) { 
	DEBUGF(PHYBUSIF_DEBUG, ("phybusif_input: Forward ACL packet to higher layer\n")); 
	hci_acl_input(cb->p); /* Handle incoming ACL data */ 
	phybusif_reset(cb); 
	cb->bcount = i + 1; 
        return ERR_OK; /* Since there most likley won't be any more data in the input buffer */ 
      } 
      break; 
    default: 
      DEBUGF(PHYBUSIF_DEBUG, ("phybusif_input: Unknown state\n\n")); 
      break; 
    } 
  } /* for */ 
  /* All data from dma input buffer handled, go wait for more */ 
  cb->bcount = i; 
  return ERR_OK; 
} 
/*-----------------------------------------------------------------------------------*/ 
/*  
 * phybusif_output(): 
 * 
 * Called by HCI to output data on the physical bus (UART). 
 */ 
/*-----------------------------------------------------------------------------------*/ 
void 
phybusif_output(struct pbuf *p, unsigned int len)  
{ 
  static struct pbuf *q; 
  static int i; 
  static unsigned char *ptr; 
  unsigned char c; 
  
  /* Send pbuf on UART */ 
  for(q = p; q != NULL; q = q->next) { 
    ptr = q->payload; 
    for(i = 0; i < q->len && len; i++) { 
      c = *ptr++; 
      UART_SEND(c); 
      --len; 
    } 
  } 
} 
/*-----------------------------------------------------------------------------------*/