diff --git a/epicardium/modules/ble.c b/epicardium/modules/ble.c index 7e0ab68ca6607779358ae2cce6050aa8f95824fb..dfb332e5b7ae85a574b183fa5f7c2b609e5a9542 100644 --- a/epicardium/modules/ble.c +++ b/epicardium/modules/ble.c @@ -7,6 +7,12 @@ #include "fit/fit_api.h" #include "hci_vs.h" +#include "att_defs.h" +#include "util/bstream.h" +#include "att_api.h" + +#include "modules.h" + #include "FreeRTOS.h" #include "timers.h" @@ -26,7 +32,6 @@ uint32_t SystemHeapStart; /* Task ID for the ble handler */ static TaskHandle_t ble_task_id = NULL; - /*! Default pool descriptor. */ static wsfBufPoolDesc_t mainPoolDesc[WSF_BUF_POOLS] = { @@ -164,6 +169,133 @@ static void scheduleTimer(void) } } +#define UART_START_HDL 0x800 /*!< \brief Service start handle. */ +#define UART_END_HDL (BATT_MAX_HDL - 1) /*!< \brief Service end handle. */ + +/************************************************************************************************** + Handles +**************************************************************************************************/ + +/*! \brief UART Service Handles */ +enum +{ + UART_SVC_HDL = UART_START_HDL, /*!< \brief UART service declaration */ + UART_RX_CH_HDL, /*!< \brief UART rx characteristic */ + UART_RX_HDL, /*!< \brief UART rx value */ + UART_TX_CH_HDL, /*!< \brief UART tx characteristic */ + UART_TX_HDL, /*!< \brief UART tx value */ + UART_TX_CH_CCC_HDL, /*!< \brief UART tx CCCD */ + BATT_MAX_HDL /*!< \brief Maximum handle. */ +}; +/**@}*/ + +static const uint8_t UARTSvc[] = {0x9E,0xCA,0xDC,0x24,0x0E,0xE5,0xA9,0xE0,0x93,0xF3,0xA3,0xB5,0x01,0x00,0x40,0x6E}; + +static const uint8_t uartRxCh[] = {ATT_PROP_WRITE, UINT16_TO_BYTES(UART_RX_HDL), 0x9E,0xCA,0xDC,0x24,0x0E,0xE5,0xA9,0xE0,0x93,0xF3,0xA3,0xB5,0x02,0x00,0x40,0x6E}; +const uint8_t attUartRxChUuid[] = {0x9E,0xCA,0xDC,0x24,0x0E,0xE5, 0xA9,0xE0,0x93,0xF3,0xA3,0xB5,0x02,0x00,0x40,0x6E}; + +static const uint8_t uartTxCh[] = {ATT_PROP_READ | ATT_PROP_NOTIFY, UINT16_TO_BYTES(UART_TX_HDL), 0x9E,0xCA,0xDC,0x24,0x0E,0xE5,0xA9,0xE0,0x93,0xF3,0xA3,0xB5,0x03,0x00,0x40,0x6E}; +const uint8_t attUartTxChUuid[] = {0x9E,0xCA,0xDC,0x24,0x0E,0xE5, 0xA9,0xE0,0x93,0xF3,0xA3,0xB5,0x03,0x00,0x40,0x6E}; +/* Battery level client characteristic configuration */ + + + +void *SvcUARTAddGroupDyn(void) +{ + void *pSHdl; + uint8_t initCcc[] = {UINT16_TO_BYTES(0x0000)}; + uint8_t initUARTVal[] = {0x20}; + + /* Create the service */ + pSHdl = AttsDynCreateGroup(UART_START_HDL, UART_END_HDL); + + if (pSHdl != NULL) + { + /* Primary service */ + AttsDynAddAttrConst(pSHdl, attPrimSvcUuid, UARTSvc, sizeof(UARTSvc), 0, ATTS_PERMIT_READ); + + + /* UART rx characteristic */ + AttsDynAddAttrConst(pSHdl, attChUuid, uartRxCh, sizeof(uartRxCh), 0, ATTS_PERMIT_READ); + // XXX: attUartRxChUuid is 16 bytes but nothing says so.... + /* UART rx value */ + // XXX: not sure if max value of 128 is fine... + AttsDynAddAttr(pSHdl, attUartRxChUuid, NULL, 0, 128, + ATTS_SET_WRITE_CBACK | ATTS_SET_VARIABLE_LEN, ATTS_PERMIT_WRITE); + + + /* UART tx characteristic */ + AttsDynAddAttrConst(pSHdl, attChUuid, uartTxCh, sizeof(uartTxCh), 0, ATTS_PERMIT_READ); + /* UART tx value */ + /* TODO: do we need ATTS_SET_READ_CBACK ? */ + AttsDynAddAttr(pSHdl, attUartTxChUuid, initUARTVal, sizeof(uint8_t), sizeof(uint8_t), + 0, ATTS_PERMIT_READ); + /* UART tx CCC descriptor */ + AttsDynAddAttr(pSHdl, attCliChCfgUuid, initCcc, sizeof(uint16_t), sizeof(uint16_t), + ATTS_SET_CCC, ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); + } + + return pSHdl; +} + +dmConnId_t active_connection = 0; + +#if 0 +uint8_t UARTReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, + uint16_t offset, attsAttr_t *pAttr) +{ + //AppHwBattRead(pAttr->pValue); + + return ATT_SUCCESS; +} +#endif + +uint8_t UARTWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, + uint16_t offset, uint16_t len, uint8_t *pValue, + attsAttr_t *pAttr) +{ + active_connection = connId; + + //printf("UARTWriteCback %d: ", len); + int i; + for(i=0; i<len; i++) { + //printf("%c", pValue[i]); + serial_enqueue_char(pValue[i]); + } + serial_enqueue_char('\r'); + //printf("\n"); + +#if 0 + AttsSetAttr(UART_TX_HDL, len, pValue); + AttsHandleValueNtf(connId, UART_TX_HDL, len, pValue); +#endif + + return ATT_SUCCESS; +} + +uint8_t ble_uart_tx_buf[129]; +uint8_t ble_uart_buf_tx_fill; + +void ble_uart_write(uint8_t *pValue, uint8_t len) +{ + int i; + for(i=0; i<len; i++) { + if(pValue[i] >= 0x20 && pValue[i] < 0x7f) { + ble_uart_tx_buf[ble_uart_buf_tx_fill] = pValue[i]; + ble_uart_buf_tx_fill++; + } else if(pValue[i] >= '\r') { + if(ble_uart_buf_tx_fill > 0) { + AttsSetAttr(UART_TX_HDL, ble_uart_buf_tx_fill, ble_uart_tx_buf); + if(active_connection) { + AttsHandleValueNtf(active_connection, UART_TX_HDL, ble_uart_buf_tx_fill, ble_uart_tx_buf); + } + ble_uart_buf_tx_fill = 0; + } + } + } +} + + static void ble_init(void) { WsfInit(); @@ -173,6 +305,14 @@ static void ble_init(void) NVIC_SetPriority(BTLE_RX_RCVD_IRQn, 2); FitStart(); + /* Add the UART service dynamically */ + AttsDynInit(); + void *pSHdl; + pSHdl = SvcUARTAddGroupDyn(); + //AttsDynRegister(pSHdl, UARTReadCback, UARTWriteCback); + AttsDynRegister(pSHdl, NULL, UARTWriteCback); + + /* Register a handler for Application events */ AppUiActionRegister(SetAddress); diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h index 182fdae7e1bee27bce1b3d56d94f35bce9eb979e..ac6186ad9193cf374527b26c59b4fdc9b73b7741 100644 --- a/epicardium/modules/modules.h +++ b/epicardium/modules/modules.h @@ -15,13 +15,17 @@ void fatfs_init(void); #define SERIAL_READ_BUFFER_SIZE 128 void vSerialTask(void *pvParameters); +void serial_enqueue_char(char chr); + /* ---------- PMIC --------------------------------------------------------- */ /* In 1/10s */ #define PMIC_PRESS_SLEEP 20 #define PMIC_PRESS_POWEROFF 40 void vPmicTask(void *pvParameters); +/* ---------- BLE ---------------------------------------------------------- */ +void ble_uart_write(uint8_t *pValue, uint8_t len); + // Forces an unlock of the display. Only to be used in epicardium void disp_forcelock(); - #endif /* MODULES_H */ diff --git a/epicardium/modules/serial.c b/epicardium/modules/serial.c index 8cffa3ac40f8a66ddcd7dc0c5491cc4b5d8b59f8..db188ebe4474e8ac03cf0dbe773bf00e28e49e6e 100644 --- a/epicardium/modules/serial.c +++ b/epicardium/modules/serial.c @@ -29,6 +29,7 @@ void epic_uart_write_str(const char *str, intptr_t length) { UART_Write(ConsoleUart, (uint8_t *)str, length); cdcacm_write((uint8_t *)str, length); + ble_uart_write((uint8_t *)str, length); } /* @@ -72,7 +73,7 @@ static void uart_callback(uart_req_t *req, int error) portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -static void enqueue_char(char chr) +void serial_enqueue_char(char chr) { if (chr == 0x3) { /* Control-C */ @@ -122,15 +123,15 @@ void vSerialTask(void *pvParameters) ulTaskNotifyTake(pdTRUE, portTICK_PERIOD_MS * 1000); if (read_req.num > 0) { - enqueue_char(*read_req.data); + serial_enqueue_char(*read_req.data); } while (UART_NumReadAvail(ConsoleUart) > 0) { - enqueue_char(UART_ReadByte(ConsoleUart)); + serial_enqueue_char(UART_ReadByte(ConsoleUart)); } while (cdcacm_num_read_avail() > 0) { - enqueue_char(cdcacm_read()); + serial_enqueue_char(cdcacm_read()); } } }