Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler
bt_network/BleUartRPC/UartRPC.cpp@9:bf0cf5828378, 2015-02-18 (annotated)
- 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?
User | Revision | Line number | New 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 | } |