| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- #include "include.h"
- #include "wireless_client.h"
- #include "wireless_init.h"
- #include "usb_audio.h"
- #include "usb_hid.h"
- #include "usb_vendor.h"
- #include "utils_ring_buffer.h"
- #define TRACE_EN 1
- #define TRACE_RATE_EN 0
- #define TRACE_RATE_PERIOD 400 // Unit: connection interval
- #define CFG_CONN_INTV 2 // Unit: 1.25ms
- #define CFG_CONN_LAT 1 // Unit: connection interval
- #define CFG_CONN_TO 20 // Unit: 10ms
- #if TRACE_EN
- #define TRACE(...) my_printf("[WIRELESS] ");\
- my_printf(__VA_ARGS__)
- #define TRACE_R(...) my_print_r(__VA_ARGS__);
- #else
- #define TRACE(...)
- #define TRACE_R(...)
- #endif // TRACE_EN
- #define SWDIAG(func, filed, value)
- #define DBG_FLOW_CTRL_EN 0
- static struct {
- uint16_t con_handle;
- bool is_bond;
- wireless_addr_info_typedef bond_addr_info;
- } wireless_cb AT(.ram_text.wireless.sta);
- static const uint8_t adv_match_seq[4] = {0x03, 0xff, 0x42, 0x06};
- /* Expect set to 2 + payload_length(transmit: e.g USB Vendor is 63) */
- static uint8_t transmit_buffer[1 + 2 + 63];
- #if TRACE_RATE_EN
- static uint32_t statistic_frame_count;
- static uint32_t statistic_hid_pkts_count;
- #endif
- /* The max number of caches uploads from transport layer cannot be modify curr Ver. */
- static struct {
- uint8_t * tbl[5];
- uint8_t siz[5];
- uint8_t widx;
- uint8_t ridx;
- uint8_t cnt;
- bt_timer_mem_t fc_timer_intance;
- bt_timer_handle_t fc_timer_handle;
- } wireless_rxbuf_cb AT(.ram_text.wireless.xfer);
- #define WIRELESS_RXBUF_RELEASE_TIMEOUT 50 /* ms */
- #define wireless_rxbuf_is_empty() (wireless_rxbuf_cb.cnt == 0)
- #define wireless_rxbuf_r_advance() {wireless_rxbuf_cb.ridx=(wireless_rxbuf_cb.ridx+1)%5;wireless_rxbuf_cb.cnt--;}
- #define wireless_rxbuf_r_head_buf() (wireless_rxbuf_cb.tbl[wireless_rxbuf_cb.ridx])
- #define wireless_rxbuf_r_head_siz() (wireless_rxbuf_cb.siz[wireless_rxbuf_cb.ridx])
- #define wireless_rxbuf_w_advance() {wireless_rxbuf_cb.widx=(wireless_rxbuf_cb.widx+1)%5;wireless_rxbuf_cb.cnt++;}
- #define wireless_rxbuf_w_head_buf() (wireless_rxbuf_cb.tbl[wireless_rxbuf_cb.widx])
- #define wireless_rxbuf_w_head_siz() (wireless_rxbuf_cb.siz[wireless_rxbuf_cb.widx])
- #define wireless_conn_is_exist() (wireless_cb.con_handle != 0)
- AT(.com_text.wireless.transmit)
- static void wireless_packet_process(uint8_t *buf, uint32_t size)
- {
- u8 head = buf[WIRELESS_HEAD_POS];
- u8 pos = WIRELESS_PAYLOAD_POS;
- u8 *hid_data = NULL;
- u8 *mic_data = NULL;
- u8 *cmd_data = NULL, cmd_len = 0, cmd_type;
- /* Unpack data */
- if (head & WIRELESS_HEADER_HID_BIT) {
- hid_data = &buf[pos];
- pos += WIRELESS_DATA_LENGTH_HID;
- #if TRACE_RATE_EN
- if (statistic_frame_count > 0 && statistic_frame_count <= TRACE_RATE_PERIOD) {
- statistic_hid_pkts_count++;
- }
- #endif
- }
- if (head & WIRELESS_HEADER_AUDIO_BIT) {
- mic_data = &buf[pos];
- pos += WIRELESS_DATA_LENGTH_AUDIO;
- }
- if (head & WIRELESS_HEADER_CTRL_BIT) {
- cmd_data = &buf[pos];
- cmd_type = cmd_data[WIRELESS_CMD_DATA_TYPE_POS];
- cmd_len = cmd_data[WIRELESS_CMD_DATA_LENGTH_POS];
- pos += 2 + cmd_len;
- }
- /* Check length valid */
- if (pos != size) {
- TRACE("data length err: %d %d\n", pos, size);
- return;
- }
- /* Process */
- #if USB_HID_EN
- if (hid_data && sys_cb.usb_is_active) {
- usb_hid_buffer_push(hid_data, WIRELESS_DATA_LENGTH_HID);
- thread_driver_msg_post(THREAD_DRIVER_MSG_HID_IN);
- }
- #else
- (void)hid_data;
- #endif
- #if USB_MIC_EN
- if (mic_data && sys_cb.usb_is_active) {
- SWDIAG(RECV, IO, ENTER);
- uda_mic_buffer_prepare(mic_data, WIRELESS_DATA_LENGTH_AUDIO);
- thread_driver_msg_post(THREAD_DRIVER_MSG_UAC_DEC);
- SWDIAG(RECV, IO, EXIT);
- }
- #else
- (void)mic_data;
- #endif
- if (cmd_data) {
- TRACE("receive cmd - type:0x%02x data[%d]:\n", cmd_type, cmd_len);
- TRACE_R(&cmd_data[WIRELESS_CMD_DATA_VALUE_POS], cmd_len);
- switch (cmd_type) {
- default:
- break;
- }
- }
- }
- /*
- AT(.com_text.wireless.transmit)
- NO_INLINE static void wireless_packet_rxbuf_check(void)
- {
- #if DBG_FLOW_CTRL_EN
- uint8_t *packet = wireless_rxbuf_r_head_buf();
- uint8_t size = wireless_rxbuf_r_head_siz();
- if (wireless_rxbuf_is_empty()) {
- return;
- }
- if (!wireless_conn_is_exist()) {
- while (!wireless_rxbuf_is_empty()) {
- wireless_rxbuf_release(packet);
- wireless_rxbuf_r_advance();
- packet = wireless_rxbuf_r_head_buf();
- }
- return;
- }
- if ((packet[WIRELESS_HEAD_POS] & WIRELESS_HEADER_HID_BIT)
- #if USB_HID_EN
- && (!usb_hid_buffer_push_check())
- #endif // USB_HID_EN
- )
- {
- return;
- }
- bt_alarm_timer_stop(wireless_rxbuf_cb.fc_timer_handle);
- wireless_packet_process(packet, size);
- GLOBAL_INT_DISABLE();
- wireless_rxbuf_release(packet);
- wireless_rxbuf_r_advance();
- GLOBAL_INT_RESTORE();
- if (!wireless_rxbuf_is_empty()) {
- bt_alarm_timer_start(wireless_rxbuf_cb.fc_timer_handle);
- }
- #endif
- }
- */
- AT(.text.wireless.transmit)
- static void wireless_packet_rxbuf_timeout_callback(bt_timer_handle_t handle)
- {
- if (!wireless_rxbuf_is_empty()) {
- do
- {
- wireless_rxbuf_release(wireless_rxbuf_r_head_buf());
- wireless_rxbuf_r_advance();
- }
- while (!wireless_conn_is_exist() && !wireless_rxbuf_is_empty());
- if (!wireless_rxbuf_is_empty()) {
- bt_alarm_timer_start(wireless_rxbuf_cb.fc_timer_handle);
- }
- }
- }
- AT(.com_text.dbg.statistic)
- void wireless_frame_start_hook(void)
- {
- #if TRACE_RATE_EN
- if (statistic_frame_count <= TRACE_RATE_PERIOD) {
- statistic_frame_count++;
- }
- #endif
- }
- static void wireless_event_packet_handler(uint8_t event_type, uint8_t *packet, uint8_t size)
- {
- switch (event_type) {
- case WIRELESS_EVENT_CONNECTED:
- TRACE("[master]connected - con_handle: 0x%04x\n", GET_LE16(&packet[0]));
- wireless_cb.con_handle = GET_LE16(&packet[0]);
- memcpy((u8 *)&wireless_cb.bond_addr_info, &packet[2], 7);
- /* Record link info */
- bsp_wireless_link_info_write(&wireless_cb.bond_addr_info);
- wireless_cb.is_bond = true;
- /* Trigger event that notify peer the mic and usb status */
- thread_driver_msg_post(THREAD_DRIVER_MSG_UAC_MIC_CTRL);
- thread_driver_msg_post(THREAD_DRIVER_MSG_USB_IND);
- wireless_frame_start_hook_register(wireless_cb.con_handle, wireless_frame_start_hook);
- break;
- case WIRELESS_EVENT_DISCONNECTED:
- TRACE("[master]disconnected - con_handle: 0x%04x reason: 0x%02x\n", GET_LE16(&packet[0]), packet[2]);
- wireless_cb.con_handle = 0;
- wireless_scan_ctrl(true);
- break;
- case WIRELESS_EVENT_ADV_REPORT: {
- wireless_adv_report_t *adv_msg = (wireless_adv_report_t *)&packet[0];
- wireless_adv_slice_t *adv_sli = (wireless_adv_slice_t *)adv_msg->report;
- bool found = false;
- TRACE("adv report - type: 0x%02x addr: ", adv_msg->addr_type);
- TRACE_R(adv_msg->addr, 6);
- do {
- if (wireless_cb.is_bond) {
- if (0 == memcmp(adv_msg->addr, wireless_cb.bond_addr_info.addr, 6)) {
- /* It's the last connected device */
- found = true;
- break;
- }
- // No break: connects to the last device or any non-directional broadcast device.
- }
- /* Try to find the specified seq in undir adv data */
- while (((u8 *)adv_sli - adv_msg->report) < adv_msg->report_len) {
- if (0 == memcmp(adv_sli, adv_match_seq, 4)) {
- found = true;
- break;
- }
- adv_sli = (wireless_adv_slice_t *)(adv_sli->data + adv_sli->length - 1);
- }
- } while (0);
- if (found) {
- wireless_scan_ctrl(false);
- wireless_connect_by_addr(adv_msg->addr, adv_msg->addr_type, CFG_CONN_INTV, CFG_CONN_LAT, CFG_CONN_TO);
- }
- break;
- }
- default:
- break;
- }
- }
- AT(.com_text.wireless.transmit)
- static void wireless_receive_handler(uint16_t con_handle, uint8_t *packet, uint8_t size)
- {
- #if DBG_FLOW_CTRL_EN
- if (con_handle == wireless_cb.con_handle) {
- if (wireless_rxbuf_is_empty()) {
- bt_alarm_timer_start(wireless_rxbuf_cb.fc_timer_handle);
- } else {
- /* ASSERT: fc timer already start */
- }
- wireless_rxbuf_cb.tbl[wireless_rxbuf_cb.widx] = packet;
- wireless_rxbuf_cb.siz[wireless_rxbuf_cb.widx] = size;
- wireless_rxbuf_w_advance();
- } else {
- wireless_rxbuf_release(packet);
- }
- #else
- if (con_handle == wireless_cb.con_handle) {
- wireless_packet_process(packet, size);
- }
- wireless_rxbuf_release(packet);
- #endif
- }
- void wireless_client_init(void)
- {
- TRACE("master init\n");
- memset(&wireless_cb, 0x00, sizeof(wireless_cb));
- memset(&wireless_rxbuf_cb, 0x00, sizeof(wireless_rxbuf_cb));
- wireless_cb.is_bond = bsp_wireless_link_info_read(&wireless_cb.bond_addr_info);
- bt_alarm_timer_mem_extend(&wireless_rxbuf_cb.fc_timer_intance, sizeof(wireless_rxbuf_cb.fc_timer_intance));
- bt_alarm_timer_acquire(&wireless_rxbuf_cb.fc_timer_handle, WIRELESS_RXBUF_RELEASE_TIMEOUT, 0, wireless_packet_rxbuf_timeout_callback);
- wireless_event_handler_register(wireless_event_packet_handler);
- wireless_receive_handler_register(wireless_receive_handler);
- }
- /*
- void ble_app_proc(void)
- {
- #if TRACE_RATE_EN
- if (statistic_frame_count > TRACE_RATE_PERIOD) {
- TRACE("rate: %dhids/%dFrames\n", statistic_hid_pkts_count, TRACE_RATE_PERIOD);
- statistic_hid_pkts_count = 0;
- statistic_frame_count = 0;
- }
- #endif
- wireless_packet_rxbuf_check();
- }
- */
- /* Single packet, no compose with HID or AUDIO */
- void wireless_send_ctrl_cmd(uint8_t type, uint8_t length, uint8_t *value)
- {
- u8 *cmd_data = &transmit_buffer[WIRELESS_PAYLOAD_POS];
- u8 packet_len = 1 + 2 + length;
- u32 tick, timeout = 500;
- u8 mtu = 0;
- wireless_mtu_get(wireless_cb.con_handle, &mtu);
- if (packet_len > mtu || packet_len > sizeof(transmit_buffer)) {
- return;
- }
- cmd_data[WIRELESS_CMD_DATA_TYPE_POS] = type;
- cmd_data[WIRELESS_CMD_DATA_LENGTH_POS] = length;
- if (length && value) {
- memcpy(&cmd_data[WIRELESS_CMD_DATA_VALUE_POS], value, length);
- }
- transmit_buffer[WIRELESS_HEAD_POS] = WIRELESS_HEADER_CTRL_BIT;
- tick = tick_get();
- while (wireless_send_for_con(wireless_cb.con_handle, transmit_buffer, packet_len)) {
- if (tick_check_expire(tick, timeout)) {
- break;
- }
- delay_5ms(1);
- }
- }
|