@@ -2600,6 +2600,227 @@ int pref_getType(const uint8_t command[], uint8_t response[]) {
26002600 return 6 ;
26012601}
26022602
2603+ /*
2604+ * BLE vHCI API
2605+ */
2606+ #include " esp_bt.h"
2607+
2608+ #define TO_HOST_BUF_SIZE 256 // bytes
2609+ static RingbufHandle_t buf_handle = NULL ;
2610+ static SemaphoreHandle_t vhci_send_sem = NULL ;
2611+
2612+ static void controller_rcv_pkt_ready () {
2613+ if (vhci_send_sem) {
2614+ xSemaphoreGive (vhci_send_sem);
2615+ }
2616+ }
2617+
2618+ /*
2619+ * The following callback is called when the bt controller has some data available
2620+ * this data is put into a queue that is then consumed by calling ble_read
2621+ */
2622+ static int host_rcv_pkt (uint8_t *data, uint16_t len) {
2623+ if (buf_handle == NULL ) {
2624+ ets_printf (" failed host_rcv_pkt\n " );
2625+ return ESP_FAIL;
2626+ }
2627+
2628+ UBaseType_t res = xRingbufferSend (buf_handle, data, len, pdMS_TO_TICKS (2000 )); // TODO verify xTicksToWait value
2629+
2630+ if (res != pdTRUE) {
2631+ ets_printf (" unable to send data to ring buffer\n " );
2632+ }
2633+ return ESP_OK;
2634+ }
2635+
2636+ static esp_bt_controller_config_t btControllerConfig = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
2637+ static esp_vhci_host_callback_t vhciHostCb = {
2638+ controller_rcv_pkt_ready,
2639+ host_rcv_pkt
2640+ };
2641+
2642+ int ble_begin (const uint8_t command[], uint8_t response[]) {
2643+ // [0] CMD_START < 0xE0 >
2644+ // [1] Command < 1 byte >
2645+
2646+ esp_err_t ret = ESP_OK;
2647+
2648+ if ((ret = esp_bt_controller_init (&btControllerConfig)) != ESP_OK) {
2649+ ets_printf (" failed esp_bt_controller_init %s\n " , esp_err_to_name (ret));
2650+
2651+ goto exit;
2652+ }
2653+
2654+ while (esp_bt_controller_get_status () == ESP_BT_CONTROLLER_STATUS_IDLE);
2655+
2656+ if ((ret = esp_bt_controller_enable (ESP_BT_MODE_BLE)) != ESP_OK) {
2657+ ets_printf (" failed esp_bt_controller_enable %s\n " , esp_err_to_name (ret));
2658+
2659+ goto exit;
2660+ }
2661+
2662+ if ((buf_handle = xRingbufferCreate (TO_HOST_BUF_SIZE, RINGBUF_TYPE_BYTEBUF)) == NULL ) {
2663+ ret = ESP_ERR_NO_MEM;
2664+ ets_printf (" failed xRingbufferCreate\n " );
2665+
2666+ goto exit;
2667+ }
2668+
2669+ vhci_send_sem = xSemaphoreCreateBinary ();
2670+ if (vhci_send_sem == NULL ) {
2671+ ets_printf (" Failed to create VHCI send sem\n " );
2672+ ret = ESP_ERR_NO_MEM;
2673+ goto exit;
2674+ }
2675+ xSemaphoreGive (vhci_send_sem);
2676+
2677+ esp_bt_sleep_enable ();
2678+
2679+ esp_vhci_host_register_callback (&vhciHostCb);
2680+
2681+ exit:
2682+ response[2 ] = 1 ; // number of parameters
2683+ response[3 ] = 1 ; // length of first parameter
2684+ response[4 ] = ret;
2685+
2686+ return 6 ;
2687+ }
2688+
2689+ int ble_end (const uint8_t command[], uint8_t response[]) {
2690+ // [0] CMD_START < 0xE0 >
2691+ // [1] Command < 1 byte >
2692+
2693+ esp_bt_controller_disable ();
2694+ esp_bt_controller_deinit ();
2695+
2696+ if (buf_handle != NULL ) {
2697+ vRingbufferDelete (buf_handle);
2698+ }
2699+
2700+ if (vhci_send_sem != NULL ) {
2701+ /* Dummy take and give sema before deleting it */
2702+ xSemaphoreTake (vhci_send_sem, pdMS_TO_TICKS (2000 ));
2703+ xSemaphoreGive (vhci_send_sem);
2704+ vSemaphoreDelete (vhci_send_sem);
2705+ vhci_send_sem = NULL ;
2706+ }
2707+
2708+ response[2 ] = 1 ; // number of parameters
2709+ response[3 ] = 1 ; // length of first parameter
2710+ response[4 ] = 1 ;
2711+
2712+ return 6 ;
2713+ }
2714+
2715+ int ble_available (const uint8_t command[], uint8_t response[]) {
2716+ // [0] CMD_START < 0xE0 >
2717+ // [1] Command < 1 byte >
2718+ uint16_t available = 0 ;
2719+ if (buf_handle != NULL ) {
2720+ available = TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle);
2721+ }
2722+
2723+ response[2 ] = 1 ; // number of parameters
2724+ response[3 ] = 2 ; // length of first parameter
2725+ response[4 ] = (available >> 8 ) & 0xff ;
2726+ response[5 ] = (available >> 0 ) & 0xff ;
2727+
2728+ return 7 ;
2729+ }
2730+
2731+ int ble_peek (const uint8_t command[], uint8_t response[]) {
2732+ // [0] CMD_START < 0xE0 >
2733+ // [1] Command < 1 byte >
2734+ // [2] N args < 1 byte >
2735+ // [3] the number 2 < 1 byte >
2736+ // [4..5] size < 2 byte >
2737+ // this could be useless xQueuePeek
2738+ uint8_t nargs = command[2 ];
2739+ // if nargs != 1 -> error
2740+ size_t res = 0 ;
2741+ // uint16_t size = ntohs(*((uint16_t *) &command[4]));
2742+ uint16_t size = *((uint16_t *) &command[4 ]);
2743+ uint8_t * received = nullptr ;
2744+
2745+ if (size > TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle)) {
2746+ size = 0 ;
2747+ goto exit;
2748+ }
2749+
2750+ received = (uint8_t *)xRingbufferReceiveUpTo (buf_handle, &res, pdMS_TO_TICKS (2000 ), size);
2751+
2752+ memcpy (&response[5 ], received, res);
2753+
2754+ exit:
2755+ response[2 ] = 1 ; // number of parameters
2756+ response[3 ] = (size >> 8 ) & 0xff ;
2757+ response[4 ] = (size >> 0 ) & 0xff ;
2758+
2759+ return 6 + res;
2760+ }
2761+
2762+ int ble_read (const uint8_t command[], uint8_t response[]) {
2763+ // [0] CMD_START < 0xE0 >
2764+ // [1] Command < 1 byte >
2765+ // [2] N args < 1 byte >
2766+ // [3] the number 2 < 1 byte >
2767+ // [4..5] size < 2 byte >
2768+ uint8_t nargs = command[2 ];
2769+ // if nargs != 1 -> error
2770+ size_t res = 0 ;
2771+ // uint16_t size = ntohs(*((uint16_t *) &command[4]));
2772+ uint16_t size = *((uint16_t *) &command[4 ]);
2773+ uint8_t * received = nullptr ;
2774+
2775+ if (size > TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle)) {
2776+ size = 0 ;
2777+ goto exit;
2778+ }
2779+
2780+ received = (uint8_t *)xRingbufferReceiveUpTo (buf_handle, &res, pdMS_TO_TICKS (2000 ), size);
2781+
2782+ memcpy (&response[5 ], received, res);
2783+
2784+ vRingbufferReturnItem (buf_handle, received);
2785+
2786+ exit:
2787+ response[2 ] = 1 ; // number of parameters
2788+ response[3 ] = (size >> 8 ) & 0xff ;
2789+ response[4 ] = (size >> 0 ) & 0xff ;
2790+
2791+ return 6 + res;
2792+ }
2793+
2794+ int ble_write (const uint8_t command[], uint8_t response[]) {
2795+ // [0] CMD_START < 0xE0 >
2796+ // [1] Command < 1 byte >
2797+ // [2] N args < 1 byte >
2798+ // [3..4] size < 2 byte >
2799+ // [4..4+size] buffer < size byte >
2800+
2801+ uint8_t nargs = command[2 ];
2802+ // if nargs != 1 -> error
2803+
2804+ uint16_t size = ntohs (*((uint16_t *) &command[3 ]));
2805+
2806+ while (!esp_vhci_host_check_send_available ()) { // TODO add timeout
2807+ // TODO delay
2808+ }
2809+
2810+ if (vhci_send_sem && xSemaphoreTake (vhci_send_sem, pdMS_TO_TICKS (2000 )) == pdTRUE) {
2811+ esp_vhci_host_send_packet ((uint8_t *)&command[5 ], size);
2812+ }
2813+
2814+ response[2 ] = 1 ; // number of parameters
2815+ response[3 ] = 2 ; // length of first parameter
2816+ response[4 ] = (size >> 0 ) & 0xff ;
2817+ response[5 ] = (size >> 8 ) & 0xff ;
2818+
2819+ return 7 ;
2820+ }
2821+
2822+
2823+
26032824typedef int (*CommandHandlerType)(const uint8_t command[], uint8_t response[]);
26042825
26052826const CommandHandlerType commandHandlers[] = {
@@ -2616,7 +2837,15 @@ const CommandHandlerType commandHandlers[] = {
26162837 disconnect, NULL , getIdxRSSI, getIdxEnct, reqHostByName, getHostByName, startScanNetworks, getFwVersion, NULL , sendUDPdata, getRemoteData, getTime, getIdxBSSID, getIdxChannel, ping, getSocket,
26172838
26182839 // 0x40 -> 0x4f
2619- setEnt, NULL , NULL , NULL , sendDataTcp, getDataBufTcp, insertDataBuf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
2840+ setEnt, NULL , NULL , NULL , sendDataTcp, getDataBufTcp, insertDataBuf, NULL , NULL , NULL ,
2841+
2842+ // BLE functions 0x4a -> 0x4f
2843+ ble_begin, // 0x4a
2844+ ble_end, // 0x4b
2845+ ble_available, // 0x4c
2846+ ble_peek, // 0x4d
2847+ ble_read, // 0x4e
2848+ ble_write, // 0x4f
26202849
26212850 // 0x50 -> 0x54
26222851 setPinMode, setDigitalWrite, setAnalogWrite, getDigitalRead, getAnalogRead,
0 commit comments