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

bt_network/BleUartRPC/Dispatcher.cpp

Committer:
ansond
Date:
2015-11-03
Revision:
38:30e71f1206b1
Parent:
36:aa73681951ad

File content as of revision 38:30e71f1206b1:

/**
 * @file    Dispatcher.cpp
 * @brief   BLE UART RPC dispatcher implmentation
 * @author  Doug Anson
 * @version 1.0
 * @see     
 *
 * Copyright (c) 2014
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
 #include "Dispatcher.h"
 #include "UartRPCFunctions.h"
 
 // forward declarations
 extern "C" int ble_rpc_recv_data(uint8_t *buffer,int buffer_length);
  
 #ifdef DBG
    #undef DBG
 #endif
 #define DBG  std::printf
 
 // constructor
 Dispatcher::Dispatcher(BLEDevice &ble) :  m_uart(ble), m_splitter(), m_splitter_count(0), m_splitter_index(0) {
     ble.onDataWritten(this,&Dispatcher::onDataWritten);
     memset(this->m_send_packet,0,MAX_PACKET_LENGTH+1);
 }
 
 void Dispatcher::onDataWritten(const GattCharacteristicWriteCBParams *params) {
     int length = (int)params->len;
     uint8_t *data = (uint8_t *)params->data;
     bool send_ack = false;
     //DBG("onDataWritten: received: [%s] length=%d\r\n",data,length);
     
     if (strstr((char *)data,"ACK") == NULL) {
         // process this input from the peer
         ble_rpc_recv_data(data,length);
         
         // we received something... so send an ack
         send_ack = true;
     }
     else {
         // received an ACK so note it...
         //DBG("onDataWritten: received ACK (OK)... continuing...\r\n");
         ;
     }
     
     // write the next segment (if any...)
     this->uart_write(send_ack);
 }
 
 int Dispatcher::uart_write(bool send_ack) {
     if (this->m_splitter_count > 0) {
         int length = this->m_splitter.getSplitLength();        // fixed
         int index = this->m_splitter_index;
         if (index < (this->m_splitter_count-1)) {
            // wont be partial length...
            //DBG("dispatcher(): sending segment %d (of %d): [%s]\r\n",index+1,this->m_splitter.getNumFragments(),this->m_splitter.get(index));
            this->uart_write(this->m_splitter.get(index),UART_SEGMENT_LENGTH);
         }
         else {
            // partial length so we pad with spaces... 
            uint8_t *tmp = this->m_splitter.get(index);
            int padded_length = strlen((char *)tmp);
            int diff = UART_SEGMENT_LENGTH-padded_length;
            for(int j=0;j<diff;++j) memcpy((tmp+padded_length+j)," ",1);
            padded_length = strlen((char *)tmp);
            
            // send the last segment which may be a partial length one...
            //DBG("dispatcher(): sending segment %d (of %d): [%s] length: %d (padded %d)...\r\n",index+1,this->m_splitter.getNumFragments(),tmp,padded_length,diff);
            this->uart_write(tmp,padded_length);
         }
         
         // update splitter index
         ++this->m_splitter_index;
         
         // note when we are done...
         if (this->m_splitter_index == this->m_splitter_count) {
             this->m_splitter_index = 0;
             this->m_splitter_count = 0;
             this->m_splitter.reset();
         }
         
         // return the length
         //DBG("dispatcher(): sent %d bytes\r\n",length);
         return length;
     }
     else if (send_ack) {
        // just send and ack as we received something...
        //DBG("dispatcher(): sending ACK...\r\n"); 
        return this->uart_write((uint8_t *)"ACK\n",4);
     }
     else {
        // nothing to send
        //DBG("dispatcher(): nothing to send()...\r\n");
        return 0;
     }
 }
 
 int Dispatcher::uart_write(uint8_t *data,int data_length) {
     return this->m_uart.write(data,data_length);
 }
 
 // dispatch 
 int Dispatcher::dispatch(uint8_t fn_id,uint8_t *args,int args_length,uint8_t *response,int response_length) {
     //DBG("dispatcher(): fn_id=0x%.2x args=[%s] args_length=%d response_length=%d\r\n",fn_id,args,args_length,response_length);
     //DBG("dispatcher(): fn_id=0x%.2x args_length=%d response_length=%d\r\n",fn_id,args_length,response_length);
          
     // prepare the send packet
     //DBG("dispatcher(): preparing the send packet...\r\n");
     int len = this->prepare_send_packet(fn_id,args,args_length);
     
     // Split into chunks and pad the last one
     //DBG("dispatcher(): splitting into segments for UART transmission...\r\n");
     this->m_splitter.reset();
     this->m_splitter_count = this->m_splitter.split(this->m_send_packet,len);
     
     // send the first of the segments and wait for an ack...
     this->m_splitter_index = 0;
     len = this->uart_write();
    
     // return the number of bytes sent...
     //DBG("dispatcher(): send started. sent %d bytes...\r\n",len);
     return len;
 }
 
 // prepare the packet to send
 int Dispatcher::prepare_send_packet(uint8_t fn_id,uint8_t *args,int args_length) {
     // clear the packet
     memset(this->m_send_packet,0,MAX_PACKET_LENGTH+1);
     sprintf((char *)this->m_send_packet,"[%d|%s]",fn_id,args);
     return strlen((char *)this->m_send_packet);
 }