BLE mbed Endpoint network stack for mbedConnectorInterface. The stack makes use of a special BLE Socket abstraction to create socket() semantics over BLE.

Dependencies:   libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Dispatcher.cpp Source File

Dispatcher.cpp

Go to the documentation of this file.
00001 /**
00002  * @file    Dispatcher.cpp
00003  * @brief   BLE UART RPC dispatcher implmentation
00004  * @author  Doug Anson
00005  * @version 1.0
00006  * @see     
00007  *
00008  * Copyright (c) 2014
00009  *
00010  * Licensed under the Apache License, Version 2.0 (the "License");
00011  * you may not use this file except in compliance with the License.
00012  * You may obtain a copy of the License at
00013  *
00014  *     http://www.apache.org/licenses/LICENSE-2.0
00015  *
00016  * Unless required by applicable law or agreed to in writing, software
00017  * distributed under the License is distributed on an "AS IS" BASIS,
00018  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019  * See the License for the specific language governing permissions and
00020  * limitations under the License.
00021  */
00022  
00023  #include "Dispatcher.h"
00024  #include "UartRPCFunctions.h"
00025  
00026  // forward declarations
00027  extern "C" int ble_rpc_recv_data(uint8_t *buffer,int buffer_length);
00028   
00029  #ifdef DBG
00030     #undef DBG
00031  #endif
00032  #define DBG  std::printf
00033  
00034  // constructor
00035  Dispatcher::Dispatcher(BLEDevice &ble) :  m_uart(ble), m_splitter(), m_splitter_count(0), m_splitter_index(0) {
00036      ble.onDataWritten(this,&Dispatcher::onDataWritten);
00037      memset(this->m_send_packet,0,MAX_PACKET_LENGTH+1);
00038  }
00039  
00040  void Dispatcher::onDataWritten(const GattCharacteristicWriteCBParams *params) {
00041      int length = (int)params->len;
00042      uint8_t *data = (uint8_t *)params->data;
00043      bool send_ack = false;
00044      //DBG("onDataWritten: received: [%s] length=%d\r\n",data,length);
00045      
00046      if (strstr((char *)data,"ACK") == NULL) {
00047          // process this input from the peer
00048          ble_rpc_recv_data(data,length);
00049          
00050          // we received something... so send an ack
00051          send_ack = true;
00052      }
00053      else {
00054          // received an ACK so note it...
00055          //DBG("onDataWritten: received ACK (OK)... continuing...\r\n");
00056          ;
00057      }
00058      
00059      // write the next segment (if any...)
00060      this->uart_write(send_ack);
00061  }
00062  
00063  int Dispatcher::uart_write(bool send_ack) {
00064      if (this->m_splitter_count > 0) {
00065          int length = this->m_splitter.getSplitLength();        // fixed
00066          int index = this->m_splitter_index;
00067          if (index < (this->m_splitter_count-1)) {
00068             // wont be partial length...
00069             //DBG("dispatcher(): sending segment %d (of %d): [%s]\r\n",index+1,this->m_splitter.getNumFragments(),this->m_splitter.get(index));
00070             this->uart_write(this->m_splitter.get(index),UART_SEGMENT_LENGTH);
00071          }
00072          else {
00073             // partial length so we pad with spaces... 
00074             uint8_t *tmp = this->m_splitter.get(index);
00075             int padded_length = strlen((char *)tmp);
00076             int diff = UART_SEGMENT_LENGTH-padded_length;
00077             for(int j=0;j<diff;++j) memcpy((tmp+padded_length+j)," ",1);
00078             padded_length = strlen((char *)tmp);
00079             
00080             // send the last segment which may be a partial length one...
00081             //DBG("dispatcher(): sending segment %d (of %d): [%s] length: %d (padded %d)...\r\n",index+1,this->m_splitter.getNumFragments(),tmp,padded_length,diff);
00082             this->uart_write(tmp,padded_length);
00083          }
00084          
00085          // update splitter index
00086          ++this->m_splitter_index;
00087          
00088          // note when we are done...
00089          if (this->m_splitter_index == this->m_splitter_count) {
00090              this->m_splitter_index = 0;
00091              this->m_splitter_count = 0;
00092              this->m_splitter.reset();
00093          }
00094          
00095          // return the length
00096          //DBG("dispatcher(): sent %d bytes\r\n",length);
00097          return length;
00098      }
00099      else if (send_ack) {
00100         // just send and ack as we received something...
00101         //DBG("dispatcher(): sending ACK...\r\n"); 
00102         return this->uart_write((uint8_t *)"ACK\n",4);
00103      }
00104      else {
00105         // nothing to send
00106         //DBG("dispatcher(): nothing to send()...\r\n");
00107         return 0;
00108      }
00109  }
00110  
00111  int Dispatcher::uart_write(uint8_t *data,int data_length) {
00112      return this->m_uart.write(data,data_length);
00113  }
00114  
00115  // dispatch 
00116  int Dispatcher::dispatch(uint8_t fn_id,uint8_t *args,int args_length,uint8_t *response,int response_length) {
00117      //DBG("dispatcher(): fn_id=0x%.2x args=[%s] args_length=%d response_length=%d\r\n",fn_id,args,args_length,response_length);
00118      //DBG("dispatcher(): fn_id=0x%.2x args_length=%d response_length=%d\r\n",fn_id,args_length,response_length);
00119           
00120      // prepare the send packet
00121      //DBG("dispatcher(): preparing the send packet...\r\n");
00122      int len = this->prepare_send_packet(fn_id,args,args_length);
00123      
00124      // Split into chunks and pad the last one
00125      //DBG("dispatcher(): splitting into segments for UART transmission...\r\n");
00126      this->m_splitter.reset();
00127      this->m_splitter_count = this->m_splitter.split(this->m_send_packet,len);
00128      
00129      // send the first of the segments and wait for an ack...
00130      this->m_splitter_index = 0;
00131      len = this->uart_write();
00132     
00133      // return the number of bytes sent...
00134      //DBG("dispatcher(): send started. sent %d bytes...\r\n",len);
00135      return len;
00136  }
00137  
00138  // prepare the packet to send
00139  int Dispatcher::prepare_send_packet(uint8_t fn_id,uint8_t *args,int args_length) {
00140      // clear the packet
00141      memset(this->m_send_packet,0,MAX_PACKET_LENGTH+1);
00142      sprintf((char *)this->m_send_packet,"[%d|%s]",fn_id,args);
00143      return strlen((char *)this->m_send_packet);
00144  }