Doug Anson / mbedEndpointNetwork_BLE

Dependencies:   libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler

Committer:
ansond
Date:
Fri Sep 04 21:04:08 2015 +0000
Revision:
35:71eb3663ecbd
Parent:
33:4f6929e123f2
Child:
36:aa73681951ad
update for android 5.x. A wait() call is necessary for 5.x prior to write().

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 33:4f6929e123f2 32 // immediate response variable pointers...
ansond 33:4f6929e123f2 33 uint8_t *_immediate_response_buffer = NULL;
ansond 33:4f6929e123f2 34 int _immediate_response_buffer_length = 0;
ansond 33:4f6929e123f2 35
ansond 5:9233e88b9c83 36 // constructor
ansond 9:bf0cf5828378 37 UartRPC::UartRPC(BLEDevice &ble) : m_dispatcher(ble), m_recv_accumulator() {
ansond 9:bf0cf5828378 38 this->m_recv_raw_data = NULL;
ansond 9:bf0cf5828378 39 this->m_recv_raw_data_length = 0;
ansond 9:bf0cf5828378 40 this->m_local_dispatch_available = false;
ansond 33:4f6929e123f2 41 this->m_location = NULL;
ansond 5:9233e88b9c83 42 }
ansond 5:9233e88b9c83 43
ansond 11:d601b867b297 44 uint8_t __tmp_buffer[MAX_ARGUMENT_LENGTH+1];
ansond 11:d601b867b297 45 uint8_t base64_buffer[MAX_RESULT_LENGTH+1];
ansond 11:d601b867b297 46
ansond 5:9233e88b9c83 47 // dispatch RPC
ansond 11:d601b867b297 48 int UartRPC::dispatch(uint8_t fn_id,void *cb,uint8_t *response,int response_length,const char *format,...)
ansond 5:9233e88b9c83 49 {
ansond 11:d601b867b297 50 // save off the CB if it exists
ansond 11:d601b867b297 51 this->m_cb = cb;
ansond 11:d601b867b297 52
ansond 5:9233e88b9c83 53 // serialize the variable arguments into a long string...
ansond 5:9233e88b9c83 54 va_list args;
ansond 11:d601b867b297 55 memset(__tmp_buffer,0,MAX_ARGUMENT_LENGTH+1);
ansond 5:9233e88b9c83 56 va_start(args, format);
ansond 11:d601b867b297 57 vsnprintf((char *)__tmp_buffer,MAX_ARGUMENT_LENGTH,format,args);
ansond 5:9233e88b9c83 58 va_end(args);
ansond 5:9233e88b9c83 59
ansond 5:9233e88b9c83 60 // dispatch now...
ansond 11:d601b867b297 61 return this->m_dispatcher.dispatch(fn_id,__tmp_buffer,strlen((char *)__tmp_buffer),response,response_length);
ansond 9:bf0cf5828378 62 }
ansond 9:bf0cf5828378 63
ansond 33:4f6929e123f2 64 // set the location instance
ansond 33:4f6929e123f2 65 void UartRPC::setLocationInstance(BLELocation *location) {
ansond 33:4f6929e123f2 66 this->m_location = location;
ansond 33:4f6929e123f2 67 }
ansond 33:4f6929e123f2 68
ansond 9:bf0cf5828378 69 // dispatch locally
ansond 9:bf0cf5828378 70 void UartRPC::dispatch() {
ansond 9:bf0cf5828378 71 // assemble the argument buffer...
ansond 11:d601b867b297 72 memset(__tmp_buffer,0,MAX_ARGUMENT_LENGTH+1);
ansond 11:d601b867b297 73 int length = this->m_recv_accumulator.assemble(__tmp_buffer,MAX_ARGUMENT_LENGTH);
ansond 9:bf0cf5828378 74
ansond 9:bf0cf5828378 75 // DEBUG
ansond 16:fb9c3f2af2df 76 //DBG("UartRPC: dispatch(local): buffer [%s] length=%d\r\n",__tmp_buffer,length);
ansond 9:bf0cf5828378 77
ansond 9:bf0cf5828378 78 // parse the buffer
ansond 9:bf0cf5828378 79 memset(base64_buffer,0,MAX_RESULT_LENGTH+1);
ansond 9:bf0cf5828378 80 int fn_id = 0;
ansond 9:bf0cf5828378 81
ansond 9:bf0cf5828378 82 // strip off head,tail and separator, replace with spaces
ansond 9:bf0cf5828378 83 int final_length = 0;
ansond 9:bf0cf5828378 84 for(int i=0;i<length && final_length == 0;++i) {
ansond 11:d601b867b297 85 if (__tmp_buffer[i] == '[') __tmp_buffer[i] = ' ';
ansond 11:d601b867b297 86 if (__tmp_buffer[i] == '|') __tmp_buffer[i] = ' ';
ansond 11:d601b867b297 87 if (__tmp_buffer[i] == ']') { __tmp_buffer[i] = '\0'; final_length = i; }
ansond 9:bf0cf5828378 88 }
ansond 9:bf0cf5828378 89
ansond 9:bf0cf5828378 90 // scan over the two values
ansond 11:d601b867b297 91 sscanf((char *)__tmp_buffer,"%d %s",&fn_id,base64_buffer);
ansond 9:bf0cf5828378 92 int base64_buffer_length = strlen((char *)base64_buffer);
ansond 9:bf0cf5828378 93
ansond 9:bf0cf5828378 94 // DEBUG
ansond 11:d601b867b297 95 //DBG("UartRPC: dispatch(local): fn_id = 0x%.2x base64_buffer = [%s] length=%d\r\n",fn_id,base64_buffer,base64_buffer_length);
ansond 11:d601b867b297 96
ansond 9:bf0cf5828378 97 // invoke the appropriate function
ansond 16:fb9c3f2af2df 98 //DBG("UartRPC: dispatch(local): requested function ID: 0x%.2x...\r\n",fn_id);
ansond 9:bf0cf5828378 99 switch(fn_id) {
ansond 11:d601b867b297 100 case SOCKET_OPEN_FN: {
ansond 11:d601b867b297 101 // socket open has been attempted... call the CB if it exists and process the status
ansond 16:fb9c3f2af2df 102 //DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN length=%d\r\n",base64_buffer_length);
ansond 11:d601b867b297 103 if (this->m_cb != NULL) {
ansond 11:d601b867b297 104 // cast the callback
ansond 11:d601b867b297 105 ble_dispatch_callback_fn cb = (ble_dispatch_callback_fn)this->m_cb;
ansond 11:d601b867b297 106
ansond 11:d601b867b297 107 // parse the packet received for the status
ansond 11:d601b867b297 108 bool open_ok = false;
ansond 16:fb9c3f2af2df 109 //DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN socket open status: [%s]\r\n",base64_buffer);
ansond 11:d601b867b297 110 int int_open_ok = 0;
ansond 11:d601b867b297 111 sscanf((char *)base64_buffer,"%d",&int_open_ok);
ansond 11:d601b867b297 112 if (int_open_ok == 1) open_ok = true;
ansond 11:d601b867b297 113
ansond 11:d601b867b297 114 // invoke the callback with the status
ansond 16:fb9c3f2af2df 115 //DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN: invoking socket open callback (status: %d)...\r\n",int_open_ok);
ansond 11:d601b867b297 116 cb(open_ok);
ansond 16:fb9c3f2af2df 117 //DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN: callback for socket open (status: %d) completed...\r\n",int_open_ok);
ansond 11:d601b867b297 118 }
ansond 11:d601b867b297 119 else {
ansond 11:d601b867b297 120 // no callback given... so we are stuck...
ansond 11:d601b867b297 121 DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN : ERROR no connect() callback function registered!\r\n");
ansond 11:d601b867b297 122 }
ansond 11:d601b867b297 123
ansond 11:d601b867b297 124 // done with the callback
ansond 11:d601b867b297 125 this->m_cb = NULL;
ansond 11:d601b867b297 126 break;
ansond 11:d601b867b297 127 }
ansond 33:4f6929e123f2 128 case GET_LOCATION_FN: {
ansond 33:4f6929e123f2 129 // reset our local dispatch
ansond 33:4f6929e123f2 130 this->resetLocalDispatch();
ansond 33:4f6929e123f2 131
ansond 33:4f6929e123f2 132 // process the location update response...
ansond 33:4f6929e123f2 133 Base64 b64;
ansond 33:4f6929e123f2 134 base64_buffer_length = final_length;
ansond 33:4f6929e123f2 135 char *location = b64.Decode((char *)base64_buffer,strlen((char *)base64_buffer),(std::size_t *)&base64_buffer_length);
ansond 33:4f6929e123f2 136 int location_length = base64_buffer_length; // modified by Decode()....
ansond 33:4f6929e123f2 137 //DBG("UartRPC: dispatch(local): GET_LOCATION_FN: location(%d): %s\r\n",location_length,location);
ansond 33:4f6929e123f2 138 if (this->m_location != NULL) this->m_location->processLocationUpdateResponse(location,location_length);
ansond 33:4f6929e123f2 139
ansond 33:4f6929e123f2 140 // local dispatch is now ready...
ansond 33:4f6929e123f2 141 this->m_local_dispatch_available = true;
ansond 33:4f6929e123f2 142 break;
ansond 33:4f6929e123f2 143 }
ansond 9:bf0cf5828378 144 case RECV_DATA_FN: {
ansond 11:d601b867b297 145 // reset our local dispatch
ansond 16:fb9c3f2af2df 146 //DBG("UartRPC: dispatch(local): resetting...\r\n");
ansond 11:d601b867b297 147 this->resetLocalDispatch();
ansond 11:d601b867b297 148
ansond 11:d601b867b297 149 // decode the arguments and save off the local dispatch...
ansond 16:fb9c3f2af2df 150 //DBG("UartRPC: dispatch(local): base64 decoding...\r\n");
ansond 11:d601b867b297 151 Base64 b64;
ansond 11:d601b867b297 152 base64_buffer_length = final_length;
ansond 11:d601b867b297 153 this->m_recv_raw_data = b64.Decode((char *)base64_buffer,strlen((char *)base64_buffer),(std::size_t *)&base64_buffer_length);
ansond 11:d601b867b297 154 this->m_recv_raw_data_length = base64_buffer_length; // modified by Decode()....
ansond 11:d601b867b297 155
ansond 9:bf0cf5828378 156 // only RECV_DATA_FN is local... make it ready for retrieval and flag it as ready...
ansond 16:fb9c3f2af2df 157 //DBG("UartRPC: dispatch(local): RECV_DATA_FN length=%d\r\n",this->m_recv_raw_data_length);
ansond 9:bf0cf5828378 158
ansond 9:bf0cf5828378 159 // local dispatch is now ready...
ansond 9:bf0cf5828378 160 this->m_local_dispatch_available = true;
ansond 9:bf0cf5828378 161 break;
ansond 9:bf0cf5828378 162 }
ansond 9:bf0cf5828378 163 default: {
ansond 9:bf0cf5828378 164 // all other function ID's are non-local
ansond 9:bf0cf5828378 165 DBG("UartRPC: dispatch(local): ignoring non-local function call request (id=0x%.2x)...\r\n",fn_id);
ansond 33:4f6929e123f2 166
ansond 33:4f6929e123f2 167 // reset the local dispatch
ansond 9:bf0cf5828378 168 this->resetLocalDispatch();
ansond 9:bf0cf5828378 169 break;
ansond 9:bf0cf5828378 170 }
ansond 9:bf0cf5828378 171 }
ansond 9:bf0cf5828378 172 }
ansond 9:bf0cf5828378 173
ansond 9:bf0cf5828378 174 // is a local dispatch (packet) available?
ansond 9:bf0cf5828378 175 bool UartRPC::localDispatchAvailable() { return this->m_local_dispatch_available; };
ansond 9:bf0cf5828378 176
ansond 9:bf0cf5828378 177 // reset the local dispatch availability
ansond 9:bf0cf5828378 178 void UartRPC::resetLocalDispatch() {
ansond 9:bf0cf5828378 179 if (this->m_recv_raw_data != NULL) free(this->m_recv_raw_data);
ansond 9:bf0cf5828378 180 this->m_recv_raw_data = NULL;
ansond 9:bf0cf5828378 181 this->m_recv_raw_data_length = 0;
ansond 9:bf0cf5828378 182 this->m_local_dispatch_available = false;
ansond 9:bf0cf5828378 183 }
ansond 9:bf0cf5828378 184
ansond 9:bf0cf5828378 185 // transfer the local dispatch and reset
ansond 9:bf0cf5828378 186 int UartRPC::retrieveLocalDispatch(uint8_t *buffer,int buffer_length) {
ansond 9:bf0cf5828378 187 if (this->m_local_dispatch_available == true) {
ansond 9:bf0cf5828378 188 // copy over the dispatch
ansond 9:bf0cf5828378 189 memset(buffer,0,buffer_length);
ansond 9:bf0cf5828378 190 int length = this->m_recv_raw_data_length;
ansond 9:bf0cf5828378 191 if (length > buffer_length) {
ansond 9:bf0cf5828378 192 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 193 length = buffer_length;
ansond 9:bf0cf5828378 194 }
ansond 9:bf0cf5828378 195 memcpy(buffer,this->m_recv_raw_data,length);
ansond 9:bf0cf5828378 196
ansond 9:bf0cf5828378 197 // now reset
ansond 9:bf0cf5828378 198 this->resetLocalDispatch();
ansond 9:bf0cf5828378 199
ansond 9:bf0cf5828378 200 // return the length
ansond 9:bf0cf5828378 201 return length;
ansond 9:bf0cf5828378 202 }
ansond 9:bf0cf5828378 203 return 0;
ansond 9:bf0cf5828378 204 }
ansond 9:bf0cf5828378 205
ansond 9:bf0cf5828378 206 // accumulate to dispatch locally...
ansond 35:71eb3663ecbd 207 bool UartRPC::accumulate(uint8_t *buffer,int buffer_length) {
ansond 35:71eb3663ecbd 208 //DBG("UartRPC:: accumulating... [%s] length=%d bytes...\r\n",buffer,buffer_length);
ansond 35:71eb3663ecbd 209
ansond 9:bf0cf5828378 210 // add to the accumulator
ansond 9:bf0cf5828378 211 this->m_recv_accumulator.add(buffer,buffer_length);
ansond 9:bf0cf5828378 212
ansond 9:bf0cf5828378 213 // determine if we have a completed packet by looking for the "tail"
ansond 9:bf0cf5828378 214 return this->m_recv_accumulator.hasCollectedCharacter(']');
ansond 5:9233e88b9c83 215 }