@@ -2600,6 +2600,227 @@ int pref_getType(const uint8_t command[], uint8_t response[]) {
2600
2600
return 6 ;
2601
2601
}
2602
2602
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
+
2603
2824
typedef int (*CommandHandlerType)(const uint8_t command[], uint8_t response[]);
2604
2825
2605
2826
const CommandHandlerType commandHandlers[] = {
@@ -2616,7 +2837,15 @@ const CommandHandlerType commandHandlers[] = {
2616
2837
disconnect, NULL , getIdxRSSI, getIdxEnct, reqHostByName, getHostByName, startScanNetworks, getFwVersion, NULL , sendUDPdata, getRemoteData, getTime, getIdxBSSID, getIdxChannel, ping, getSocket,
2617
2838
2618
2839
// 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
2620
2849
2621
2850
// 0x50 -> 0x54
2622
2851
setPinMode, setDigitalWrite, setAnalogWrite, getDigitalRead, getAnalogRead,
0 commit comments