@@ -2072,6 +2072,225 @@ int socket_getpeername(const uint8_t command[], uint8_t response[])
20722072 return 14 ;
20732073}
20742074
2075+ /*
2076+ * BLE vHCI API
2077+ */
2078+ #include " esp_bt.h"
2079+
2080+ #define TO_HOST_BUF_SIZE 256 // bytes
2081+ static RingbufHandle_t buf_handle = NULL ;
2082+ static SemaphoreHandle_t vhci_send_sem = NULL ;
2083+
2084+ static void controller_rcv_pkt_ready () {
2085+ if (vhci_send_sem) {
2086+ xSemaphoreGive (vhci_send_sem);
2087+ }
2088+ }
2089+
2090+ /*
2091+ * The following callback is called when the bt controller has some data available
2092+ * this data is put into a queue that is then consumed by calling ble_read
2093+ */
2094+ static int host_rcv_pkt (uint8_t *data, uint16_t len) {
2095+ if (buf_handle == NULL ) {
2096+ ets_printf (" failed host_rcv_pkt\n " );
2097+ return ESP_FAIL;
2098+ }
2099+
2100+ UBaseType_t res = xRingbufferSend (buf_handle, data, len, pdMS_TO_TICKS (2000 )); // TODO verify xTicksToWait value
2101+
2102+ if (res != pdTRUE) {
2103+ ets_printf (" unable to send data to ring buffer\n " );
2104+ }
2105+ return ESP_OK;
2106+ }
2107+
2108+ static esp_bt_controller_config_t btControllerConfig = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
2109+ static esp_vhci_host_callback_t vhciHostCb = {
2110+ controller_rcv_pkt_ready,
2111+ host_rcv_pkt
2112+ };
2113+
2114+ int ble_begin (const uint8_t command[], uint8_t response[]) {
2115+ // [0] CMD_START < 0xE0 >
2116+ // [1] Command < 1 byte >
2117+
2118+ esp_err_t ret = ESP_OK;
2119+
2120+ if ((ret = esp_bt_controller_init (&btControllerConfig)) != ESP_OK) {
2121+ ets_printf (" failed esp_bt_controller_init %s\n " , esp_err_to_name (ret));
2122+
2123+ goto exit;
2124+ }
2125+
2126+ while (esp_bt_controller_get_status () == ESP_BT_CONTROLLER_STATUS_IDLE);
2127+
2128+ if ((ret = esp_bt_controller_enable (ESP_BT_MODE_BLE)) != ESP_OK) {
2129+ ets_printf (" failed esp_bt_controller_enable %s\n " , esp_err_to_name (ret));
2130+
2131+ goto exit;
2132+ }
2133+
2134+ if ((buf_handle = xRingbufferCreate (TO_HOST_BUF_SIZE, RINGBUF_TYPE_BYTEBUF)) == NULL ) {
2135+ ret = ESP_ERR_NO_MEM;
2136+ ets_printf (" failed xRingbufferCreate\n " );
2137+
2138+ goto exit;
2139+ }
2140+
2141+ vhci_send_sem = xSemaphoreCreateBinary ();
2142+ if (vhci_send_sem == NULL ) {
2143+ ets_printf (" Failed to create VHCI send sem\n " );
2144+ ret = ESP_ERR_NO_MEM;
2145+ goto exit;
2146+ }
2147+ xSemaphoreGive (vhci_send_sem);
2148+
2149+ esp_bt_sleep_enable ();
2150+
2151+ esp_vhci_host_register_callback (&vhciHostCb);
2152+
2153+ exit:
2154+ response[2 ] = 1 ; // number of parameters
2155+ response[3 ] = 1 ; // length of first parameter
2156+ response[4 ] = ret;
2157+
2158+ return 6 ;
2159+ }
2160+
2161+ int ble_end (const uint8_t command[], uint8_t response[]) {
2162+ // [0] CMD_START < 0xE0 >
2163+ // [1] Command < 1 byte >
2164+
2165+ esp_bt_controller_disable ();
2166+ esp_bt_controller_deinit ();
2167+
2168+ if (buf_handle != NULL ) {
2169+ vRingbufferDelete (buf_handle);
2170+ }
2171+
2172+ if (vhci_send_sem != NULL ) {
2173+ /* Dummy take and give sema before deleting it */
2174+ xSemaphoreTake (vhci_send_sem, pdMS_TO_TICKS (2000 ));
2175+ xSemaphoreGive (vhci_send_sem);
2176+ vSemaphoreDelete (vhci_send_sem);
2177+ vhci_send_sem = NULL ;
2178+ }
2179+
2180+ response[2 ] = 1 ; // number of parameters
2181+ response[3 ] = 1 ; // length of first parameter
2182+ response[4 ] = 1 ;
2183+
2184+ return 6 ;
2185+ }
2186+
2187+ int ble_available (const uint8_t command[], uint8_t response[]) {
2188+ // [0] CMD_START < 0xE0 >
2189+ // [1] Command < 1 byte >
2190+ uint16_t available = 0 ;
2191+ if (buf_handle != NULL ) {
2192+ available = TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle);
2193+ }
2194+
2195+ response[2 ] = 1 ; // number of parameters
2196+ response[3 ] = 2 ; // length of first parameter
2197+ response[4 ] = (available >> 8 ) & 0xff ;
2198+ response[5 ] = (available >> 0 ) & 0xff ;
2199+
2200+ return 7 ;
2201+ }
2202+
2203+ int ble_peek (const uint8_t command[], uint8_t response[]) {
2204+ // [0] CMD_START < 0xE0 >
2205+ // [1] Command < 1 byte >
2206+ // [2] N args < 1 byte >
2207+ // [3] the number 2 < 1 byte >
2208+ // [4..5] size < 2 byte >
2209+ // this could be useless xQueuePeek
2210+ uint8_t nargs = command[2 ];
2211+ // if nargs != 1 -> error
2212+ size_t res = 0 ;
2213+ // uint16_t size = ntohs(*((uint16_t *) &command[4]));
2214+ uint16_t size = *((uint16_t *) &command[4 ]);
2215+ uint8_t * received = nullptr ;
2216+
2217+ if (size > TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle)) {
2218+ size = 0 ;
2219+ goto exit;
2220+ }
2221+
2222+ received = (uint8_t *)xRingbufferReceiveUpTo (buf_handle, &res, pdMS_TO_TICKS (2000 ), size);
2223+
2224+ memcpy (&response[5 ], received, res);
2225+
2226+ exit:
2227+ response[2 ] = 1 ; // number of parameters
2228+ response[3 ] = (size >> 8 ) & 0xff ;
2229+ response[4 ] = (size >> 0 ) & 0xff ;
2230+
2231+ return 6 + res;
2232+ }
2233+
2234+ int ble_read (const uint8_t command[], uint8_t response[]) {
2235+ // [0] CMD_START < 0xE0 >
2236+ // [1] Command < 1 byte >
2237+ // [2] N args < 1 byte >
2238+ // [3] the number 2 < 1 byte >
2239+ // [4..5] size < 2 byte >
2240+ uint8_t nargs = command[2 ];
2241+ // if nargs != 1 -> error
2242+ size_t res = 0 ;
2243+ // uint16_t size = ntohs(*((uint16_t *) &command[4]));
2244+ uint16_t size = *((uint16_t *) &command[4 ]);
2245+ uint8_t * received = nullptr ;
2246+
2247+ if (size > TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle)) {
2248+ size = 0 ;
2249+ goto exit;
2250+ }
2251+
2252+ received = (uint8_t *)xRingbufferReceiveUpTo (buf_handle, &res, pdMS_TO_TICKS (2000 ), size);
2253+
2254+ memcpy (&response[5 ], received, res);
2255+
2256+ vRingbufferReturnItem (buf_handle, received);
2257+
2258+ exit:
2259+ response[2 ] = 1 ; // number of parameters
2260+ response[3 ] = (size >> 8 ) & 0xff ;
2261+ response[4 ] = (size >> 0 ) & 0xff ;
2262+
2263+ return 6 + res;
2264+ }
2265+
2266+ int ble_write (const uint8_t command[], uint8_t response[]) {
2267+ // [0] CMD_START < 0xE0 >
2268+ // [1] Command < 1 byte >
2269+ // [2] N args < 1 byte >
2270+ // [3..4] size < 2 byte >
2271+ // [4..4+size] buffer < size byte >
2272+
2273+ uint8_t nargs = command[2 ];
2274+ // if nargs != 1 -> error
2275+
2276+ uint16_t size = ntohs (*((uint16_t *) &command[3 ]));
2277+
2278+ while (!esp_vhci_host_check_send_available ()) { // TODO add timeout
2279+ // TODO delay
2280+ }
2281+
2282+ if (vhci_send_sem && xSemaphoreTake (vhci_send_sem, pdMS_TO_TICKS (2000 )) == pdTRUE) {
2283+ esp_vhci_host_send_packet ((uint8_t *)&command[5 ], size);
2284+ }
2285+
2286+ response[2 ] = 1 ; // number of parameters
2287+ response[3 ] = 2 ; // length of first parameter
2288+ response[4 ] = (size >> 0 ) & 0xff ;
2289+ response[5 ] = (size >> 8 ) & 0xff ;
2290+
2291+ return 7 ;
2292+ }
2293+
20752294typedef int (*CommandHandlerType)(const uint8_t command[], uint8_t response[]);
20762295
20772296const CommandHandlerType commandHandlers[] = {
@@ -2088,7 +2307,15 @@ const CommandHandlerType commandHandlers[] = {
20882307 disconnect, NULL , getIdxRSSI, getIdxEnct, reqHostByName, getHostByName, startScanNetworks, getFwVersion, NULL , sendUDPdata, getRemoteData, getTime, getIdxBSSID, getIdxChannel, ping, getSocket,
20892308
20902309 // 0x40 -> 0x4f
2091- setEnt, NULL , NULL , NULL , sendDataTcp, getDataBufTcp, insertDataBuf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
2310+ setEnt, NULL , NULL , NULL , sendDataTcp, getDataBufTcp, insertDataBuf, NULL , NULL , NULL ,
2311+
2312+ // BLE functions 0x4a -> 0x4f
2313+ ble_begin, // 0x4a
2314+ ble_end, // 0x4b
2315+ ble_available, // 0x4c
2316+ ble_peek, // 0x4d
2317+ ble_read, // 0x4e
2318+ ble_write, // 0x4f
20922319
20932320 // 0x50 -> 0x5f
20942321 setPinMode, setDigitalWrite, setAnalogWrite, getDigitalRead, getAnalogRead, NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
0 commit comments