@@ -2506,6 +2506,227 @@ int pref_getType(const uint8_t command[], uint8_t response[]) {
2506
2506
return 6 ;
2507
2507
}
2508
2508
2509
+ /*
2510
+ * BLE vHCI API
2511
+ */
2512
+ #include " esp_bt.h"
2513
+
2514
+ #define TO_HOST_BUF_SIZE 256 // bytes
2515
+ static RingbufHandle_t buf_handle = NULL ;
2516
+ static SemaphoreHandle_t vhci_send_sem = NULL ;
2517
+
2518
+ static void controller_rcv_pkt_ready () {
2519
+ if (vhci_send_sem) {
2520
+ xSemaphoreGive (vhci_send_sem);
2521
+ }
2522
+ }
2523
+
2524
+ /*
2525
+ * The following callback is called when the bt controller has some data available
2526
+ * this data is put into a queue that is then consumed by calling ble_read
2527
+ */
2528
+ static int host_rcv_pkt (uint8_t *data, uint16_t len) {
2529
+ if (buf_handle == NULL ) {
2530
+ ets_printf (" failed host_rcv_pkt\n " );
2531
+ return ESP_FAIL;
2532
+ }
2533
+
2534
+ UBaseType_t res = xRingbufferSend (buf_handle, data, len, pdMS_TO_TICKS (2000 )); // TODO verify xTicksToWait value
2535
+
2536
+ if (res != pdTRUE) {
2537
+ ets_printf (" unable to send data to ring buffer\n " );
2538
+ }
2539
+ return ESP_OK;
2540
+ }
2541
+
2542
+ static esp_bt_controller_config_t btControllerConfig = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
2543
+ static esp_vhci_host_callback_t vhciHostCb = {
2544
+ controller_rcv_pkt_ready,
2545
+ host_rcv_pkt
2546
+ };
2547
+
2548
+ int ble_begin (const uint8_t command[], uint8_t response[]) {
2549
+ // [0] CMD_START < 0xE0 >
2550
+ // [1] Command < 1 byte >
2551
+
2552
+ esp_err_t ret = ESP_OK;
2553
+
2554
+ if ((ret = esp_bt_controller_init (&btControllerConfig)) != ESP_OK) {
2555
+ ets_printf (" failed esp_bt_controller_init %s\n " , esp_err_to_name (ret));
2556
+
2557
+ goto exit;
2558
+ }
2559
+
2560
+ while (esp_bt_controller_get_status () == ESP_BT_CONTROLLER_STATUS_IDLE);
2561
+
2562
+ if ((ret = esp_bt_controller_enable (ESP_BT_MODE_BLE)) != ESP_OK) {
2563
+ ets_printf (" failed esp_bt_controller_enable %s\n " , esp_err_to_name (ret));
2564
+
2565
+ goto exit;
2566
+ }
2567
+
2568
+ if ((buf_handle = xRingbufferCreate (TO_HOST_BUF_SIZE, RINGBUF_TYPE_BYTEBUF)) == NULL ) {
2569
+ ret = ESP_ERR_NO_MEM;
2570
+ ets_printf (" failed xRingbufferCreate\n " );
2571
+
2572
+ goto exit;
2573
+ }
2574
+
2575
+ vhci_send_sem = xSemaphoreCreateBinary ();
2576
+ if (vhci_send_sem == NULL ) {
2577
+ ets_printf (" Failed to create VHCI send sem\n " );
2578
+ ret = ESP_ERR_NO_MEM;
2579
+ goto exit;
2580
+ }
2581
+ xSemaphoreGive (vhci_send_sem);
2582
+
2583
+ esp_bt_sleep_enable ();
2584
+
2585
+ esp_vhci_host_register_callback (&vhciHostCb);
2586
+
2587
+ exit:
2588
+ response[2 ] = 1 ; // number of parameters
2589
+ response[3 ] = 1 ; // length of first parameter
2590
+ response[4 ] = ret;
2591
+
2592
+ return 6 ;
2593
+ }
2594
+
2595
+ int ble_end (const uint8_t command[], uint8_t response[]) {
2596
+ // [0] CMD_START < 0xE0 >
2597
+ // [1] Command < 1 byte >
2598
+
2599
+ esp_bt_controller_disable ();
2600
+ esp_bt_controller_deinit ();
2601
+
2602
+ if (buf_handle != NULL ) {
2603
+ vRingbufferDelete (buf_handle);
2604
+ }
2605
+
2606
+ if (vhci_send_sem != NULL ) {
2607
+ /* Dummy take and give sema before deleting it */
2608
+ xSemaphoreTake (vhci_send_sem, pdMS_TO_TICKS (2000 ));
2609
+ xSemaphoreGive (vhci_send_sem);
2610
+ vSemaphoreDelete (vhci_send_sem);
2611
+ vhci_send_sem = NULL ;
2612
+ }
2613
+
2614
+ response[2 ] = 1 ; // number of parameters
2615
+ response[3 ] = 1 ; // length of first parameter
2616
+ response[4 ] = 1 ;
2617
+
2618
+ return 6 ;
2619
+ }
2620
+
2621
+ int ble_available (const uint8_t command[], uint8_t response[]) {
2622
+ // [0] CMD_START < 0xE0 >
2623
+ // [1] Command < 1 byte >
2624
+ uint16_t available = 0 ;
2625
+ if (buf_handle != NULL ) {
2626
+ available = TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle);
2627
+ }
2628
+
2629
+ response[2 ] = 1 ; // number of parameters
2630
+ response[3 ] = 2 ; // length of first parameter
2631
+ response[4 ] = (available >> 8 ) & 0xff ;
2632
+ response[5 ] = (available >> 0 ) & 0xff ;
2633
+
2634
+ return 7 ;
2635
+ }
2636
+
2637
+ int ble_peek (const uint8_t command[], uint8_t response[]) {
2638
+ // [0] CMD_START < 0xE0 >
2639
+ // [1] Command < 1 byte >
2640
+ // [2] N args < 1 byte >
2641
+ // [3] the number 2 < 1 byte >
2642
+ // [4..5] size < 2 byte >
2643
+ // this could be useless xQueuePeek
2644
+ uint8_t nargs = command[2 ];
2645
+ // if nargs != 1 -> error
2646
+ size_t res = 0 ;
2647
+ // uint16_t size = ntohs(*((uint16_t *) &command[4]));
2648
+ uint16_t size = *((uint16_t *) &command[4 ]);
2649
+ uint8_t * received = nullptr ;
2650
+
2651
+ if (size > TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle)) {
2652
+ size = 0 ;
2653
+ goto exit;
2654
+ }
2655
+
2656
+ received = (uint8_t *)xRingbufferReceiveUpTo (buf_handle, &res, pdMS_TO_TICKS (2000 ), size);
2657
+
2658
+ memcpy (&response[5 ], received, res);
2659
+
2660
+ exit:
2661
+ response[2 ] = 1 ; // number of parameters
2662
+ response[3 ] = (size >> 8 ) & 0xff ;
2663
+ response[4 ] = (size >> 0 ) & 0xff ;
2664
+
2665
+ return 6 + res;
2666
+ }
2667
+
2668
+ int ble_read (const uint8_t command[], uint8_t response[]) {
2669
+ // [0] CMD_START < 0xE0 >
2670
+ // [1] Command < 1 byte >
2671
+ // [2] N args < 1 byte >
2672
+ // [3] the number 2 < 1 byte >
2673
+ // [4..5] size < 2 byte >
2674
+ uint8_t nargs = command[2 ];
2675
+ // if nargs != 1 -> error
2676
+ size_t res = 0 ;
2677
+ // uint16_t size = ntohs(*((uint16_t *) &command[4]));
2678
+ uint16_t size = *((uint16_t *) &command[4 ]);
2679
+ uint8_t * received = nullptr ;
2680
+
2681
+ if (size > TO_HOST_BUF_SIZE - xRingbufferGetCurFreeSize (buf_handle)) {
2682
+ size = 0 ;
2683
+ goto exit;
2684
+ }
2685
+
2686
+ received = (uint8_t *)xRingbufferReceiveUpTo (buf_handle, &res, pdMS_TO_TICKS (2000 ), size);
2687
+
2688
+ memcpy (&response[5 ], received, res);
2689
+
2690
+ vRingbufferReturnItem (buf_handle, received);
2691
+
2692
+ exit:
2693
+ response[2 ] = 1 ; // number of parameters
2694
+ response[3 ] = (size >> 8 ) & 0xff ;
2695
+ response[4 ] = (size >> 0 ) & 0xff ;
2696
+
2697
+ return 6 + res;
2698
+ }
2699
+
2700
+ int ble_write (const uint8_t command[], uint8_t response[]) {
2701
+ // [0] CMD_START < 0xE0 >
2702
+ // [1] Command < 1 byte >
2703
+ // [2] N args < 1 byte >
2704
+ // [3..4] size < 2 byte >
2705
+ // [4..4+size] buffer < size byte >
2706
+
2707
+ uint8_t nargs = command[2 ];
2708
+ // if nargs != 1 -> error
2709
+
2710
+ uint16_t size = ntohs (*((uint16_t *) &command[3 ]));
2711
+
2712
+ while (!esp_vhci_host_check_send_available ()) { // TODO add timeout
2713
+ // TODO delay
2714
+ }
2715
+
2716
+ if (vhci_send_sem && xSemaphoreTake (vhci_send_sem, pdMS_TO_TICKS (2000 )) == pdTRUE) {
2717
+ esp_vhci_host_send_packet ((uint8_t *)&command[5 ], size);
2718
+ }
2719
+
2720
+ response[2 ] = 1 ; // number of parameters
2721
+ response[3 ] = 2 ; // length of first parameter
2722
+ response[4 ] = (size >> 0 ) & 0xff ;
2723
+ response[5 ] = (size >> 8 ) & 0xff ;
2724
+
2725
+ return 7 ;
2726
+ }
2727
+
2728
+
2729
+
2509
2730
typedef int (*CommandHandlerType)(const uint8_t command[], uint8_t response[]);
2510
2731
2511
2732
const CommandHandlerType commandHandlers[] = {
@@ -2522,7 +2743,15 @@ const CommandHandlerType commandHandlers[] = {
2522
2743
disconnect, NULL , getIdxRSSI, getIdxEnct, reqHostByName, getHostByName, startScanNetworks, getFwVersion, NULL , sendUDPdata, getRemoteData, getTime, getIdxBSSID, getIdxChannel, ping, getSocket,
2523
2744
2524
2745
// 0x40 -> 0x4f
2525
- setEnt, NULL , NULL , NULL , sendDataTcp, getDataBufTcp, insertDataBuf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
2746
+ setEnt, NULL , NULL , NULL , sendDataTcp, getDataBufTcp, insertDataBuf, NULL , NULL , NULL ,
2747
+
2748
+ // BLE functions 0x4a -> 0x4f
2749
+ ble_begin, // 0x4a
2750
+ ble_end, // 0x4b
2751
+ ble_available, // 0x4c
2752
+ ble_peek, // 0x4d
2753
+ ble_read, // 0x4e
2754
+ ble_write, // 0x4f
2526
2755
2527
2756
// 0x50 -> 0x54
2528
2757
setPinMode, setDigitalWrite, setAnalogWrite, getDigitalRead, getAnalogRead,
0 commit comments