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@38:30e71f1206b1, 2015-11-03 (annotated)
- Committer:
- ansond
- Date:
- Tue Nov 03 17:03:51 2015 +0000
- Revision:
- 38:30e71f1206b1
- Parent:
- 36:aa73681951ad
merged with IoS and android tweaks
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ansond | 5:9233e88b9c83 | 1 | /** |
ansond | 5:9233e88b9c83 | 2 | * @file Dispatcher.cpp |
ansond | 5:9233e88b9c83 | 3 | * @brief BLE UART RPC dispatcher implmentation |
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 "Dispatcher.h" |
ansond | 33:4f6929e123f2 | 24 | #include "UartRPCFunctions.h" |
ansond | 5:9233e88b9c83 | 25 | |
ansond | 33:4f6929e123f2 | 26 | // forward declarations |
ansond | 9:bf0cf5828378 | 27 | extern "C" int ble_rpc_recv_data(uint8_t *buffer,int buffer_length); |
ansond | 33:4f6929e123f2 | 28 | |
ansond | 6:98af441fd960 | 29 | #ifdef DBG |
ansond | 6:98af441fd960 | 30 | #undef DBG |
ansond | 6:98af441fd960 | 31 | #endif |
ansond | 6:98af441fd960 | 32 | #define DBG std::printf |
ansond | 6:98af441fd960 | 33 | |
ansond | 5:9233e88b9c83 | 34 | // constructor |
ansond | 9:bf0cf5828378 | 35 | Dispatcher::Dispatcher(BLEDevice &ble) : m_uart(ble), m_splitter(), m_splitter_count(0), m_splitter_index(0) { |
ansond | 9:bf0cf5828378 | 36 | ble.onDataWritten(this,&Dispatcher::onDataWritten); |
ansond | 9:bf0cf5828378 | 37 | memset(this->m_send_packet,0,MAX_PACKET_LENGTH+1); |
ansond | 9:bf0cf5828378 | 38 | } |
ansond | 9:bf0cf5828378 | 39 | |
ansond | 9:bf0cf5828378 | 40 | void Dispatcher::onDataWritten(const GattCharacteristicWriteCBParams *params) { |
ansond | 9:bf0cf5828378 | 41 | int length = (int)params->len; |
ansond | 9:bf0cf5828378 | 42 | uint8_t *data = (uint8_t *)params->data; |
ansond | 9:bf0cf5828378 | 43 | bool send_ack = false; |
ansond | 14:bcb9a9ffd425 | 44 | //DBG("onDataWritten: received: [%s] length=%d\r\n",data,length); |
ansond | 9:bf0cf5828378 | 45 | |
ansond | 9:bf0cf5828378 | 46 | if (strstr((char *)data,"ACK") == NULL) { |
ansond | 9:bf0cf5828378 | 47 | // process this input from the peer |
ansond | 9:bf0cf5828378 | 48 | ble_rpc_recv_data(data,length); |
ansond | 9:bf0cf5828378 | 49 | |
ansond | 9:bf0cf5828378 | 50 | // we received something... so send an ack |
ansond | 9:bf0cf5828378 | 51 | send_ack = true; |
ansond | 9:bf0cf5828378 | 52 | } |
ansond | 9:bf0cf5828378 | 53 | else { |
ansond | 9:bf0cf5828378 | 54 | // received an ACK so note it... |
ansond | 16:fb9c3f2af2df | 55 | //DBG("onDataWritten: received ACK (OK)... continuing...\r\n"); |
ansond | 16:fb9c3f2af2df | 56 | ; |
ansond | 9:bf0cf5828378 | 57 | } |
ansond | 9:bf0cf5828378 | 58 | |
ansond | 9:bf0cf5828378 | 59 | // write the next segment (if any...) |
ansond | 9:bf0cf5828378 | 60 | this->uart_write(send_ack); |
ansond | 9:bf0cf5828378 | 61 | } |
ansond | 9:bf0cf5828378 | 62 | |
ansond | 9:bf0cf5828378 | 63 | int Dispatcher::uart_write(bool send_ack) { |
ansond | 9:bf0cf5828378 | 64 | if (this->m_splitter_count > 0) { |
ansond | 9:bf0cf5828378 | 65 | int length = this->m_splitter.getSplitLength(); // fixed |
ansond | 9:bf0cf5828378 | 66 | int index = this->m_splitter_index; |
ansond | 9:bf0cf5828378 | 67 | if (index < (this->m_splitter_count-1)) { |
ansond | 9:bf0cf5828378 | 68 | // wont be partial length... |
ansond | 16:fb9c3f2af2df | 69 | //DBG("dispatcher(): sending segment %d (of %d): [%s]\r\n",index+1,this->m_splitter.getNumFragments(),this->m_splitter.get(index)); |
ansond | 9:bf0cf5828378 | 70 | this->uart_write(this->m_splitter.get(index),UART_SEGMENT_LENGTH); |
ansond | 9:bf0cf5828378 | 71 | } |
ansond | 9:bf0cf5828378 | 72 | else { |
ansond | 9:bf0cf5828378 | 73 | // partial length so we pad with spaces... |
ansond | 9:bf0cf5828378 | 74 | uint8_t *tmp = this->m_splitter.get(index); |
ansond | 9:bf0cf5828378 | 75 | int padded_length = strlen((char *)tmp); |
ansond | 9:bf0cf5828378 | 76 | int diff = UART_SEGMENT_LENGTH-padded_length; |
ansond | 9:bf0cf5828378 | 77 | for(int j=0;j<diff;++j) memcpy((tmp+padded_length+j)," ",1); |
ansond | 9:bf0cf5828378 | 78 | padded_length = strlen((char *)tmp); |
ansond | 9:bf0cf5828378 | 79 | |
ansond | 9:bf0cf5828378 | 80 | // send the last segment which may be a partial length one... |
ansond | 16:fb9c3f2af2df | 81 | //DBG("dispatcher(): sending segment %d (of %d): [%s] length: %d (padded %d)...\r\n",index+1,this->m_splitter.getNumFragments(),tmp,padded_length,diff); |
ansond | 9:bf0cf5828378 | 82 | this->uart_write(tmp,padded_length); |
ansond | 9:bf0cf5828378 | 83 | } |
ansond | 9:bf0cf5828378 | 84 | |
ansond | 9:bf0cf5828378 | 85 | // update splitter index |
ansond | 9:bf0cf5828378 | 86 | ++this->m_splitter_index; |
ansond | 9:bf0cf5828378 | 87 | |
ansond | 9:bf0cf5828378 | 88 | // note when we are done... |
ansond | 9:bf0cf5828378 | 89 | if (this->m_splitter_index == this->m_splitter_count) { |
ansond | 9:bf0cf5828378 | 90 | this->m_splitter_index = 0; |
ansond | 9:bf0cf5828378 | 91 | this->m_splitter_count = 0; |
ansond | 9:bf0cf5828378 | 92 | this->m_splitter.reset(); |
ansond | 9:bf0cf5828378 | 93 | } |
ansond | 9:bf0cf5828378 | 94 | |
ansond | 9:bf0cf5828378 | 95 | // return the length |
ansond | 35:71eb3663ecbd | 96 | //DBG("dispatcher(): sent %d bytes\r\n",length); |
ansond | 9:bf0cf5828378 | 97 | return length; |
ansond | 9:bf0cf5828378 | 98 | } |
ansond | 9:bf0cf5828378 | 99 | else if (send_ack) { |
ansond | 35:71eb3663ecbd | 100 | // just send and ack as we received something... |
ansond | 35:71eb3663ecbd | 101 | //DBG("dispatcher(): sending ACK...\r\n"); |
ansond | 9:bf0cf5828378 | 102 | return this->uart_write((uint8_t *)"ACK\n",4); |
ansond | 9:bf0cf5828378 | 103 | } |
ansond | 9:bf0cf5828378 | 104 | else { |
ansond | 9:bf0cf5828378 | 105 | // nothing to send |
ansond | 35:71eb3663ecbd | 106 | //DBG("dispatcher(): nothing to send()...\r\n"); |
ansond | 9:bf0cf5828378 | 107 | return 0; |
ansond | 9:bf0cf5828378 | 108 | } |
ansond | 6:98af441fd960 | 109 | } |
ansond | 6:98af441fd960 | 110 | |
ansond | 6:98af441fd960 | 111 | int Dispatcher::uart_write(uint8_t *data,int data_length) { |
ansond | 11:d601b867b297 | 112 | return this->m_uart.write(data,data_length); |
ansond | 5:9233e88b9c83 | 113 | } |
ansond | 5:9233e88b9c83 | 114 | |
ansond | 5:9233e88b9c83 | 115 | // dispatch |
ansond | 6:98af441fd960 | 116 | int Dispatcher::dispatch(uint8_t fn_id,uint8_t *args,int args_length,uint8_t *response,int response_length) { |
ansond | 11:d601b867b297 | 117 | //DBG("dispatcher(): fn_id=0x%.2x args=[%s] args_length=%d response_length=%d\r\n",fn_id,args,args_length,response_length); |
ansond | 16:fb9c3f2af2df | 118 | //DBG("dispatcher(): fn_id=0x%.2x args_length=%d response_length=%d\r\n",fn_id,args_length,response_length); |
ansond | 11:d601b867b297 | 119 | |
ansond | 6:98af441fd960 | 120 | // prepare the send packet |
ansond | 16:fb9c3f2af2df | 121 | //DBG("dispatcher(): preparing the send packet...\r\n"); |
ansond | 6:98af441fd960 | 122 | int len = this->prepare_send_packet(fn_id,args,args_length); |
ansond | 6:98af441fd960 | 123 | |
ansond | 6:98af441fd960 | 124 | // Split into chunks and pad the last one |
ansond | 16:fb9c3f2af2df | 125 | //DBG("dispatcher(): splitting into segments for UART transmission...\r\n"); |
ansond | 9:bf0cf5828378 | 126 | this->m_splitter.reset(); |
ansond | 9:bf0cf5828378 | 127 | this->m_splitter_count = this->m_splitter.split(this->m_send_packet,len); |
ansond | 6:98af441fd960 | 128 | |
ansond | 9:bf0cf5828378 | 129 | // send the first of the segments and wait for an ack... |
ansond | 9:bf0cf5828378 | 130 | this->m_splitter_index = 0; |
ansond | 11:d601b867b297 | 131 | len = this->uart_write(); |
ansond | 6:98af441fd960 | 132 | |
ansond | 6:98af441fd960 | 133 | // return the number of bytes sent... |
ansond | 16:fb9c3f2af2df | 134 | //DBG("dispatcher(): send started. sent %d bytes...\r\n",len); |
ansond | 6:98af441fd960 | 135 | return len; |
ansond | 6:98af441fd960 | 136 | } |
ansond | 6:98af441fd960 | 137 | |
ansond | 6:98af441fd960 | 138 | // prepare the packet to send |
ansond | 6:98af441fd960 | 139 | int Dispatcher::prepare_send_packet(uint8_t fn_id,uint8_t *args,int args_length) { |
ansond | 6:98af441fd960 | 140 | // clear the packet |
ansond | 6:98af441fd960 | 141 | memset(this->m_send_packet,0,MAX_PACKET_LENGTH+1); |
ansond | 6:98af441fd960 | 142 | sprintf((char *)this->m_send_packet,"[%d|%s]",fn_id,args); |
ansond | 6:98af441fd960 | 143 | return strlen((char *)this->m_send_packet); |
ansond | 5:9233e88b9c83 | 144 | } |