Doug Anson / mbedEndpointNetwork_BLE

Dependencies:   libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler

Committer:
ansond
Date:
Wed Feb 18 06:58:01 2015 +0000
Revision:
9:bf0cf5828378
Parent:
6:98af441fd960
Child:
11:d601b867b297
updates - working

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 5:9233e88b9c83 1 /**
ansond 5:9233e88b9c83 2 * @file UartRPC.cpp
ansond 5:9233e88b9c83 3 * @brief BLE UART RPC implementation
ansond 5:9233e88b9c83 4 * @author Doug Anson
ansond 5:9233e88b9c83 5 * @version 1.0
ansond 5:9233e88b9c83 6 * @see
ansond 5:9233e88b9c83 7 *
ansond 5:9233e88b9c83 8 * Copyright (c) 2014
ansond 5:9233e88b9c83 9 *
ansond 5:9233e88b9c83 10 * Licensed under the Apache License, Version 2.0 (the "License");
ansond 5:9233e88b9c83 11 * you may not use this file except in compliance with the License.
ansond 5:9233e88b9c83 12 * You may obtain a copy of the License at
ansond 5:9233e88b9c83 13 *
ansond 5:9233e88b9c83 14 * http://www.apache.org/licenses/LICENSE-2.0
ansond 5:9233e88b9c83 15 *
ansond 5:9233e88b9c83 16 * Unless required by applicable law or agreed to in writing, software
ansond 5:9233e88b9c83 17 * distributed under the License is distributed on an "AS IS" BASIS,
ansond 5:9233e88b9c83 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ansond 5:9233e88b9c83 19 * See the License for the specific language governing permissions and
ansond 5:9233e88b9c83 20 * limitations under the License.
ansond 5:9233e88b9c83 21 */
ansond 5:9233e88b9c83 22
ansond 5:9233e88b9c83 23 #include "UartRPC.h"
ansond 9:bf0cf5828378 24 #include "UartRPCFunctions.h"
ansond 5:9233e88b9c83 25 #include "Base64.h"
ansond 5:9233e88b9c83 26
ansond 5:9233e88b9c83 27 #ifdef DBG
ansond 5:9233e88b9c83 28 #undef DBG
ansond 5:9233e88b9c83 29 #endif
ansond 5:9233e88b9c83 30 #define DBG std::printf
ansond 5:9233e88b9c83 31
ansond 5:9233e88b9c83 32 // constructor
ansond 9:bf0cf5828378 33 UartRPC::UartRPC(BLEDevice &ble) : m_dispatcher(ble), m_recv_accumulator() {
ansond 9:bf0cf5828378 34 this->m_recv_raw_data = NULL;
ansond 9:bf0cf5828378 35 this->m_recv_raw_data_length = 0;
ansond 9:bf0cf5828378 36 this->m_local_dispatch_available = false;
ansond 5:9233e88b9c83 37 }
ansond 5:9233e88b9c83 38
ansond 5:9233e88b9c83 39 // dispatch RPC
ansond 6:98af441fd960 40 int UartRPC::dispatch(uint8_t fn_id,uint8_t *response,int response_length,const char *format,...)
ansond 5:9233e88b9c83 41 {
ansond 5:9233e88b9c83 42 // serialize the variable arguments into a long string...
ansond 5:9233e88b9c83 43 va_list args;
ansond 5:9233e88b9c83 44 uint8_t buffer[MAX_ARGUMENT_LENGTH+1];
ansond 9:bf0cf5828378 45 memset(buffer,0,MAX_ARGUMENT_LENGTH+1);
ansond 5:9233e88b9c83 46 va_start(args, format);
ansond 5:9233e88b9c83 47 vsnprintf((char *)buffer,MAX_ARGUMENT_LENGTH,format,args);
ansond 5:9233e88b9c83 48 va_end(args);
ansond 5:9233e88b9c83 49
ansond 5:9233e88b9c83 50 // dispatch now...
ansond 5:9233e88b9c83 51 return this->m_dispatcher.dispatch(fn_id,buffer,strlen((char *)buffer),response,response_length);
ansond 9:bf0cf5828378 52 }
ansond 9:bf0cf5828378 53
ansond 9:bf0cf5828378 54 // dispatch locally
ansond 9:bf0cf5828378 55 void UartRPC::dispatch() {
ansond 9:bf0cf5828378 56 // assemble the argument buffer...
ansond 9:bf0cf5828378 57 uint8_t buffer[MAX_RESULT_LENGTH+1];
ansond 9:bf0cf5828378 58 memset(buffer,0,MAX_RESULT_LENGTH+1);
ansond 9:bf0cf5828378 59 int length = this->m_recv_accumulator.assemble(buffer,MAX_RESULT_LENGTH);
ansond 9:bf0cf5828378 60
ansond 9:bf0cf5828378 61 // DEBUG
ansond 9:bf0cf5828378 62 DBG("UartRPC: dispatch(local): buffer [%s] length=%d\r\n",buffer,length);
ansond 9:bf0cf5828378 63
ansond 9:bf0cf5828378 64 // parse the buffer
ansond 9:bf0cf5828378 65 uint8_t base64_buffer[MAX_RESULT_LENGTH+1];
ansond 9:bf0cf5828378 66 memset(base64_buffer,0,MAX_RESULT_LENGTH+1);
ansond 9:bf0cf5828378 67 int fn_id = 0;
ansond 9:bf0cf5828378 68
ansond 9:bf0cf5828378 69 // strip off head,tail and separator, replace with spaces
ansond 9:bf0cf5828378 70 int final_length = 0;
ansond 9:bf0cf5828378 71 for(int i=0;i<length && final_length == 0;++i) {
ansond 9:bf0cf5828378 72 if (buffer[i] == '[') buffer[i] = ' ';
ansond 9:bf0cf5828378 73 if (buffer[i] == '|') buffer[i] = ' ';
ansond 9:bf0cf5828378 74 if (buffer[i] == ']') { buffer[i] = '\0'; final_length = i; }
ansond 9:bf0cf5828378 75 }
ansond 9:bf0cf5828378 76
ansond 9:bf0cf5828378 77 // scan over the two values
ansond 9:bf0cf5828378 78 sscanf((char *)buffer,"%d %s",&fn_id,base64_buffer);
ansond 9:bf0cf5828378 79 int base64_buffer_length = strlen((char *)base64_buffer);
ansond 9:bf0cf5828378 80
ansond 9:bf0cf5828378 81 // DEBUG
ansond 9:bf0cf5828378 82 DBG("UartRPC: dispatch(local): fn_id = 0x%.2x base64_buffer = [%s] length=%d\r\n",fn_id,base64_buffer,base64_buffer_length);
ansond 9:bf0cf5828378 83
ansond 9:bf0cf5828378 84 // reset our local dispatch
ansond 9:bf0cf5828378 85 DBG("UartRPC: dispatch(local): resetting...\r\n");
ansond 9:bf0cf5828378 86 this->resetLocalDispatch();
ansond 9:bf0cf5828378 87
ansond 9:bf0cf5828378 88 // decode the arguments and save off the local dispatch...
ansond 9:bf0cf5828378 89 DBG("UartRPC: dispatch(local): base64 decoding...\r\n");
ansond 9:bf0cf5828378 90 Base64 b64;
ansond 9:bf0cf5828378 91 base64_buffer_length = final_length;
ansond 9:bf0cf5828378 92 this->m_recv_raw_data = b64.Decode((char *)base64_buffer,strlen((char *)base64_buffer),(std::size_t *)&base64_buffer_length);
ansond 9:bf0cf5828378 93 this->m_recv_raw_data_length = base64_buffer_length; // modified by Decode()....
ansond 9:bf0cf5828378 94
ansond 9:bf0cf5828378 95 // invoke the appropriate function
ansond 9:bf0cf5828378 96 DBG("UartRPC: dispatch(local): requested function ID: 0x%.2x...\r\n",fn_id);
ansond 9:bf0cf5828378 97 switch(fn_id) {
ansond 9:bf0cf5828378 98 case RECV_DATA_FN: {
ansond 9:bf0cf5828378 99 // only RECV_DATA_FN is local... make it ready for retrieval and flag it as ready...
ansond 9:bf0cf5828378 100 DBG("UartRPC: dispatch(local): RECV_DATA_FN length=%d buffer=[%s]\r\n",this->m_recv_raw_data_length,this->m_recv_raw_data);
ansond 9:bf0cf5828378 101
ansond 9:bf0cf5828378 102 // local dispatch is now ready...
ansond 9:bf0cf5828378 103 this->m_local_dispatch_available = true;
ansond 9:bf0cf5828378 104 break;
ansond 9:bf0cf5828378 105 }
ansond 9:bf0cf5828378 106 default: {
ansond 9:bf0cf5828378 107 // all other function ID's are non-local
ansond 9:bf0cf5828378 108 DBG("UartRPC: dispatch(local): ignoring non-local function call request (id=0x%.2x)...\r\n",fn_id);
ansond 9:bf0cf5828378 109 this->resetLocalDispatch();
ansond 9:bf0cf5828378 110 break;
ansond 9:bf0cf5828378 111 }
ansond 9:bf0cf5828378 112 }
ansond 9:bf0cf5828378 113 }
ansond 9:bf0cf5828378 114
ansond 9:bf0cf5828378 115 // is a local dispatch (packet) available?
ansond 9:bf0cf5828378 116 bool UartRPC::localDispatchAvailable() { return this->m_local_dispatch_available; };
ansond 9:bf0cf5828378 117
ansond 9:bf0cf5828378 118 // reset the local dispatch availability
ansond 9:bf0cf5828378 119 void UartRPC::resetLocalDispatch() {
ansond 9:bf0cf5828378 120 if (this->m_recv_raw_data != NULL) free(this->m_recv_raw_data);
ansond 9:bf0cf5828378 121 this->m_recv_raw_data = NULL;
ansond 9:bf0cf5828378 122 this->m_recv_raw_data_length = 0;
ansond 9:bf0cf5828378 123 this->m_local_dispatch_available = false;
ansond 9:bf0cf5828378 124 }
ansond 9:bf0cf5828378 125
ansond 9:bf0cf5828378 126 // transfer the local dispatch and reset
ansond 9:bf0cf5828378 127 int UartRPC::retrieveLocalDispatch(uint8_t *buffer,int buffer_length) {
ansond 9:bf0cf5828378 128 if (this->m_local_dispatch_available == true) {
ansond 9:bf0cf5828378 129 // copy over the dispatch
ansond 9:bf0cf5828378 130 memset(buffer,0,buffer_length);
ansond 9:bf0cf5828378 131 int length = this->m_recv_raw_data_length;
ansond 9:bf0cf5828378 132 if (length > buffer_length) {
ansond 9:bf0cf5828378 133 DBG("UartRPC::retrieveLocalDispatch: WARNING: input buffer is too small (is %d bytes, needs to be %d bytes)...\r\n",buffer_length,length);
ansond 9:bf0cf5828378 134 length = buffer_length;
ansond 9:bf0cf5828378 135 }
ansond 9:bf0cf5828378 136 memcpy(buffer,this->m_recv_raw_data,length);
ansond 9:bf0cf5828378 137
ansond 9:bf0cf5828378 138 // now reset
ansond 9:bf0cf5828378 139 this->resetLocalDispatch();
ansond 9:bf0cf5828378 140
ansond 9:bf0cf5828378 141 // return the length
ansond 9:bf0cf5828378 142 return length;
ansond 9:bf0cf5828378 143 }
ansond 9:bf0cf5828378 144 return 0;
ansond 9:bf0cf5828378 145 }
ansond 9:bf0cf5828378 146
ansond 9:bf0cf5828378 147 // accumulate to dispatch locally...
ansond 9:bf0cf5828378 148 bool UartRPC::accumulate(uint8_t *buffer,int buffer_length) {
ansond 9:bf0cf5828378 149 // add to the accumulator
ansond 9:bf0cf5828378 150 this->m_recv_accumulator.add(buffer,buffer_length);
ansond 9:bf0cf5828378 151
ansond 9:bf0cf5828378 152 // determine if we have a completed packet by looking for the "tail"
ansond 9:bf0cf5828378 153 return this->m_recv_accumulator.hasCollectedCharacter(']');
ansond 5:9233e88b9c83 154 }