btstack源码分析-扬帆起航(主函数后传)

通过上一章,我们知道,主机向控制器发送了复位命令,发起第一次传输:

btstack_chipset_intel_download_firmware
    ...
    // get started
    state = 0;
    state_machine(NULL);
    ...

随后控制器将返回响应(事件)到主机,此时主函数已有执行:

// go
btstack_run_loop_execute();  
    the_run_loop->execute();    // --> btstack_run_loop_windows_execute

已经对注册到data_sources链表的struct btstack_data_source类型的成员的句柄进行事件监测,控制器一返回数据,对应struct btstack_data_source结构体类型的成员的process成员将被调用;

添加struct btstack_data_source类型的成员到链表data_sources,在打开usb设备中执行:

usb_open()    //hci_transport_h2_winusb.c
    ...
    usb_try_open_device();
    ...
    // setup btstack data soures
    usb_data_source_event_in.source.handle = usb_overlapped_event_in.hEvent;
    btstack_run_loop_set_data_source_handler(&usb_data_source_event_in, &usb_process_event_in);
    btstack_run_loop_add_data_source(&usb_data_source_event_in);

    usb_data_source_command_out.source.handle = usb_overlapped_command_out.hEvent;
    btstack_run_loop_set_data_source_handler(&usb_data_source_command_out, &usb_process_command_out);
    btstack_run_loop_add_data_source(&usb_data_source_command_out);

    usb_data_source_acl_in.source.handle = usb_overlapped_acl_in.hEvent;
    btstack_run_loop_set_data_source_handler(&usb_data_source_acl_in, &usb_process_acl_in);
    btstack_run_loop_add_data_source(&usb_data_source_acl_in);

    usb_data_source_acl_out.source.handle = usb_overlapped_acl_out.hEvent;
    btstack_run_loop_set_data_source_handler(&usb_data_source_acl_out, &usb_process_acl_out);
    btstack_run_loop_add_data_source(&usb_data_source_acl_out);
    ...

usb_process_event_in定义如下:

static void usb_process_event_in(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {

    btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);

    DWORD bytes_read;
    BOOL ok = WinUsb_GetOverlappedResult(usb_interface_0_handle, &usb_overlapped_event_in, &bytes_read, FALSE);
    if(!ok){
        DWORD err = GetLastError();
        if (err == ERROR_IO_INCOMPLETE){
            // IO_INCOMPLETE -> wait for completed
            btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
        } else {
            log_error("usb_process_event_in: error reading");
        }
        return;
    }

    // notify uppper
    packet_handler(HCI_EVENT_PACKET, hci_event_in_buffer, bytes_read);

    // re-submit transfer
    usb_submit_event_in_transfer();
}

这里关键是packet_handler的调用,packet_handler是一个局部的函数指针变量,通过usb_register_packet_handler函数设置:

static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = &usb_dummy_handler;

static void usb_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
    log_info("registering packet handler");
    packet_handler = handler;
}

还记得usb_register_packet_handler哪里被调用了么,没错!就是这里:

btstack_chipset_intel_download_firmware
    ...
    transport->register_packet_handler(&transport_packet_handler);
    ...

transport_packet_handler定义如下:

static void transport_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
    UNUSED(packet_type);
    // we also get events with packet_type ACL from the controller
    hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size);
    switch (hci_event_packet_get_type(packet)){
        case HCI_EVENT_COMMAND_COMPLETE:
        case HCI_EVENT_VENDOR_SPECIFIC:
            state_machine(packet);
            break;
        default:
            break;
    }
}

主机发出软复位命令后,控制器响应数据,此时packet的内容(0e 04 01 03 0c 00),并且此时state=1:

static void state_machine(uint8_t * packet){
    if (packet){
        ...
        // command complete
        if (packet[0] == 0x0e){
            waiting_for_command_complete = 0;
        }
    }

    switch (state){
        ...
        case 1:
        // check if HCI Reset was supported
        if (packet[0] == 0x0e && packet[1] == 0x04 && packet[3] == 0x03 && packet[4] == 0x0c && packet[5] == 0x00){
            log_info("HCI Reset was successful, no need for firmware upload / or not an Intel chipset");
            (*done)(0);
            break;
        }

        // Read Intel Version
        state++;
        transport_send_cmd(&hci_intel_read_version);
        break;
        ...
    }
}

上面看到,全局函数指针done被运行,done已知被赋值为intel_firmware_done,定义如下:

static void intel_firmware_done(int result){

    printf("Done %x\n", result);

    // close
    transport->close();

    //

    // init HCI
    hci_init(transport, NULL);

#ifdef ENABLE_CLASSIC
    hci_set_link_key_db(btstack_link_key_db_fs_instance());
#endif    

    // inform about BTstack state
    hci_event_callback_registration.callback = &packet_handler;
    hci_add_event_handler(&hci_event_callback_registration);

    // setup app
    btstack_main(main_argc, main_argv);
}

这个函数做了如下几件大事:

intel_firmware_done

    关闭usb设备,后面重新打开
    transport->close();

    hci_init(transport, NULL);
        创建hci_stack并进行初始化
        transport->register_packet_handler(&packet_handler); 重新注册了usb的回调函数
        /*
            static void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
                hci_dump_packet(packet_type, 1, packet, size);
                switch (packet_type) {
                    case HCI_EVENT_PACKET:
                        event_handler(packet, size);
                        break;
                    case HCI_ACL_DATA_PACKET:
                        acl_handler(packet, size);
                        break;
                    #ifdef ENABLE_CLASSIC
                    case HCI_SCO_DATA_PACKET:
                        sco_handler(packet, size);
                        break;
                    #endif
                    default:
                        break;
                }
            }
        */
    
    这是上层应用的入口,上层应用可以是可client、service、可以是包含电池服务的外围设备或心跳服务的外围设备等等。
    btstack_main(main_argc, main_argv);

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Uubt is for McU UsB BlueTooth ============================= This is a demo application for bluetooth USB dongle connected to STM32F4DISCOVERY (http://www.st.com/internet/evalboard/product/252419.jsp) board based on BTstack (http://code.google.com/p/btstack) project and ST USB libraries. LICENSING --------- My files are licensed under the terms of GPLv3, although I haven't thoroughly investigated the licenses compatibility for packages used. Please note that files from different projects involved use different licences. WHAT IS SPECIAL --------------- Pure FOSS components using hardware comprized of very cheap STM32F4DISCOVERY board and commodity bluetooth USB dongles. WHAT YOU NEED ------------- - STM32F4DISCOVERY board - cable to connect it to USB dongle (I use normal USB A male to micro-USB cable + USB A female/USB A female adapter) - USB dongle: USB parameters are currently hardcoded rather than read from descriptors, so you should verify that they match (I use lsusb -v for that purpose). Dongles tested thus far are: CSR and Atheros AR3011. Firmware loading is implemented for some Atheros chips but it is not very stable. - toolchain and libraries. I use linux, code sourcery lite (eabi build), https://github.com/texane/stlink project. You should download btstack source and STM32F4DISCOVERY firmware package (http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f4discovery_fw.zip). COMPILING --------- Currently 2 build flavours are supported: bare (no OS) and for ChibiOS/RT (http://www.chibios.org). To build for ChibiOS/RT, additionally download respective sources (I use trunk, which is currently at 2.3.4+). You will probably not need newlib_stubs.c here. The description below is for no-OS build. Fix ST libs (mine are marked as 1.1.0 revision) using the patch provided. Btstack source probably needs configuring (I'm not sure). Couple of build options are currently implemented via Makefile variables, see Makefile head for
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值