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);
发布了18 篇原创文章 · 获赞 6 · 访问量 6354

猜你喜欢

转载自blog.csdn.net/lewanhah01/article/details/104027808