#include #include #include #include "fr30xx.h" #include "co_util.h" #include "bt_types.h" #include "me_api.h" #include "hfg_api.h" #include "gatt_api.h" #include "app_at.h" #include "app_task.h" #include "app_ble.h" #include "app_bt.h" #include "app_audio.h" #include "app_hw.h" #include "btdm_mem.h" #include "fdb_app.h" #include "heap.h" #include "app_ble.h" #include "user_bt.h" #include "user_ipc_st.h" #include "dsp_mem.h" #define AT_RECV_MAX_LEN 32 static uint8_t app_at_recv_char; static uint8_t at_recv_buffer[AT_RECV_MAX_LEN]; static uint8_t at_recv_index = 0; static uint8_t at_recv_state = 0; void btdm_host_send_vendor_cmd(uint8_t type, uint8_t length, void *data); void btdm_host_vendor_cmd_cmp_evt(uint8_t status, uint8_t len, uint8_t const *param) { printf("status: 0x%02x.\r\n", status); for (uint32_t i=0; ievt_id,evt->step,evt->calorie,evt->sleep,evt->action); // } // printf("EVENT: "); // for (uint32_t i=0; i= 1000) { mini_second = 0; second++; if (second >= 60) { second = 0; minute++; if (minute >= 60) { minute = 0; hour++; } } } gsensor_cmd[5] = hour; gsensor_cmd[6] = minute; gsensor_cmd[7] = second; gsensor_cmd[8] = mini_second; gsensor_cmd[9] = mini_second >> 8; btdm_host_send_vendor_cmd(0x12, sizeof(gsensor_cmd), gsensor_cmd); } break; case 'G': printf("hello world!\r\n"); break; case 'H': printf("VAL: 0x%08x.\r\n", *(volatile uint32_t *)ascii_strn2val((const char *)&data[0], 16, 8)); break; case 'I': *(volatile uint32_t *)ascii_strn2val((const char *)&data[0], 16, 8) = ascii_strn2val((const char *)&data[9], 16, 8); printf("OK\r\n"); break; case 'J': printf("OOL VAL: 0x%02x.\r\n", ool_read(ascii_strn2val((const char *)&data[0], 16, 2))); break; case 'K': ool_write(ascii_strn2val((const char *)&data[0], 16, 2), ascii_strn2val((const char *)&data[3], 16, 2)); printf("OK\r\n"); break; case 'L': printf("VAL: 0x%02x.\r\n", *(volatile uint8_t *)(ascii_strn2val((const char *)&data[0], 16, 8))); break; case 'M': *(volatile uint8_t *)(ascii_strn2val((const char *)&data[0], 16, 8)) = ascii_strn2val((const char *)&data[9], 16, 2); printf("OK\r\n"); break; // case 'P': // co_printf("VAL: 0x%02x.\r\n", *(uint8_t *)(MODEM_BASE + ascii_strn2val((const char *)&data[0], 16, 2))); // break; // case 'Q': // *(uint8_t *)(MODEM_BASE + ascii_strn2val((const char *)&data[0], 16, 2)) = ascii_strn2val((const char *)&data[3], 16, 2); // co_printf("OK\r\n"); // break; // case 'S': // co_printf("VAL: 0x%02x.\r\n", frspim_rd(FR_SPI_RF_COB_CHAN, ascii_strn2val((const char *)&data[0], 16, 2), 1)); // break; // case 'T': // frspim_wr(FR_SPI_RF_COB_CHAN, ascii_strn2val((const char *)&data[0], 16, 2), 1, ascii_strn2val((const char *)&data[3], 16, 2)); // co_printf("OK\r\n"); // break; case 'U': { uint32_t *ptr = (uint32_t *)(ascii_strn2val((const char *)&data[0], 16, 8) & (~3)); uint8_t count = ascii_strn2val((const char *)&data[9], 16, 2); uint32_t *start = (uint32_t *)((uint32_t)ptr & (~0x0f)); for(uint8_t i=0; ieType); if(event->eType == BTEVENT_COMMAND_COMPLETE){ btdm_free(event->p.meToken); } } __RAM_CODE static void app_at_recv_cmd_B(uint8_t sub_cmd, uint8_t *data) { struct gap_ble_addr peer_addr; BD_ADDR addr; HfgResponse *rsp; BtStatus status; MeCommandToken *token; uint16_t page_timeout = 0x400; switch(sub_cmd) { case 'A': // AT#BA00 //app_ble_advertising_start(ascii_strn2val((const char *)&data[0], 16, 2)); break; case 'B': // AT#BB01 //app_ble_advertising_stop(ascii_strn2val((const char *)&data[0], 16, 2)); break; case 'C': app_ble_scan_start(); break; case 'D': app_ble_scan_stop(); break; case 'E': // AT#BE0123456789ab_01 peer_addr.addr.addr[5] = ascii_strn2val((const char *)&data[0], 16, 2); peer_addr.addr.addr[4] = ascii_strn2val((const char *)&data[2], 16, 2); peer_addr.addr.addr[3] = ascii_strn2val((const char *)&data[4], 16, 2); peer_addr.addr.addr[2] = ascii_strn2val((const char *)&data[6], 16, 2); peer_addr.addr.addr[1] = ascii_strn2val((const char *)&data[8], 16, 2); peer_addr.addr.addr[0] = ascii_strn2val((const char *)&data[10], 16, 2); peer_addr.addr_type = ascii_strn2val((const char *)&data[13], 16, 2); app_ble_conn_start(&peer_addr); break; case 'F': app_ble_conn_stop(); break; #if BTDM_STACK_ENABLE_BT == 1 case 'H': ME_Inquiry(BT_IAC_GIAC, 5, 5); break; case 'I': ME_CancelInquiry(); break; case 'J': { BtStatus status; addr.A[0] = ascii_strn2val((const char*)&data[0],16,2); addr.A[1] = ascii_strn2val((const char*)&data[2],16,2); addr.A[2] = ascii_strn2val((const char*)&data[4],16,2); addr.A[3] = ascii_strn2val((const char*)&data[6],16,2); addr.A[4] = ascii_strn2val((const char*)&data[8],16,2); addr.A[5] = ascii_strn2val((const char*)&data[10],16,2); status = HFG_CreateServiceLink(&hfg_channel[0], &addr); if (status == BT_STATUS_PENDING) { printf("Opening Channel...\r\n"); } else { printf("Could not open channel, status: %d\r\n", status); } } break; case 'K': status = BT_STATUS_NO_RESOURCES; rsp = (HfgResponse *)btdm_malloc(sizeof(HfgResponse)); if(rsp != NULL){ status = HFG_CreateCodecConnection(&hfg_channel[0], 1, rsp); } if(status != BT_STATUS_PENDING){ btdm_free((void *)rsp); } printf("status = %d\r\n",status); break; case 'L': flashdb_del(FDB_KEY_BT_LINKKEY); break; case 'M': token = btdm_malloc(sizeof(MeCommandToken)); token->p.general.in.hciCommand = 0x0c18;//HCC_WRITE_PAGE_TIMEOUT; token->p.general.in.parmLen = 2; token->p.general.in.parms = (uint8_t *)&page_timeout; token->callback = user_hci_callback; //token is freed at this callback status = ME_SendHciCommandAsync(token); printf("status = %d\r\n",status); break; case 'N': { addr.A[0] = ascii_strn2val((const char*)&data[0],16,2); addr.A[1] = ascii_strn2val((const char*)&data[2],16,2); addr.A[2] = ascii_strn2val((const char*)&data[4],16,2); addr.A[3] = ascii_strn2val((const char*)&data[6],16,2); addr.A[4] = ascii_strn2val((const char*)&data[8],16,2); addr.A[5] = ascii_strn2val((const char*)&data[10],16,2); user_bt_env.connect_times = 3; status = bt_connect(&addr); printf("status = %d\r\n",status); } break; #endif case 'O': // { // uint8_t battery_level[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; // struct gatt_send_event ntf[6]; // uint8_t i=0; // for(i=0;i<6;i++){ // ntf[i].conidx = 0; // ntf[i].svc_id = svc_id; // ntf[i].att_idx = 2; // ntf[i].data_len = 15; // ntf[i].p_data = &battery_level[0]; // gatt_notification(&ntf[i]); // } // } break; case 'P': addr.A[0] = ascii_strn2val((const char*)&data[0],16,2); addr.A[1] = ascii_strn2val((const char*)&data[2],16,2); addr.A[2] = ascii_strn2val((const char*)&data[4],16,2); addr.A[3] = ascii_strn2val((const char*)&data[6],16,2); addr.A[4] = ascii_strn2val((const char*)&data[8],16,2); addr.A[5] = ascii_strn2val((const char*)&data[10],16,2); bt_disconnect(&addr,false); break; case 'Q': addr.A[0] = ascii_strn2val((const char*)&data[0],16,2); addr.A[1] = ascii_strn2val((const char*)&data[2],16,2); addr.A[2] = ascii_strn2val((const char*)&data[4],16,2); addr.A[3] = ascii_strn2val((const char*)&data[6],16,2); addr.A[4] = ascii_strn2val((const char*)&data[8],16,2); addr.A[5] = ascii_strn2val((const char*)&data[10],16,2); bt_disconnect(&addr,true); break; case 'R': // ME_SetLocalDeviceName((const uint8_t *)"FR30xx_m", sizeof("FR30xx_m")); //app_btdm_init(); break; case 'S': { BtAccessModeInfo access_mode_nc = { .inqInterval = 0x800, .inqWindow = 0x12, .pageInterval = 0x800, .pageWindow = 0x12, }; status = ME_SetAccessibleModeNC(BAM_GENERAL_ACCESSIBLE, &access_mode_nc); printf("status = %d\r\n",status); } break; case 'T': { status = ME_SetAccessibleModeNC(BAM_NOT_ACCESSIBLE, NULL); printf("status = %d\r\n",status); } break; } printf("OK\r\n"); } #include "user_bt_pbap.h" uint8_t voltage_str[] = "AT+IPHONEACCEV=1,1,6"; uint8_t cmps_str[] = "AT+CPMS=?"; //bt hf&pbap related cmd static void app_at_recv_cmd_C(uint8_t sub_cmd, uint8_t *data) { printf("%s \r\n", __func__); BtStatus status; uint8_t state; BD_ADDR addr; switch(sub_cmd) { case 'A': status = bt_answer_call(user_bt_env.last_active_index); printf("status = %d\r\n",status); break; case 'B': status = bt_hang_up(user_bt_env.last_active_index); printf("status = %d\r\n",status); break; case 'C': status = bt_redial(user_bt_env.last_active_index); printf("status = %d\r\n",status); break; case 'D': { //uint8_t number[] = "15907515643"; status = bt_dial_number(user_bt_env.last_active_index,&data[1],data[0]); printf("status = %d\r\n",status); } break; case 'E': status = bt_list_current_calls(user_bt_env.last_active_index); printf("status = %d\r\n",status); break; case 'F': status = bt_transfer_sco(user_bt_env.last_active_index); printf("status = %d\r\n",status); break; case 'G': { uint8_t dtmf = data[0]; status = bt_send_dtmf(user_bt_env.last_active_index,dtmf); printf("status = %d\r\n",status); } break; case 'H': { //vol---[0x00,0x0f] uint8_t vol = ascii_strn2val((const char*)&data[0],16,2); status = bt_report_spk_volume(user_bt_env.last_active_index,vol); printf("status = %d\r\n",status); } break; case 'I': { status = bt_send_hf_cmd(user_bt_env.last_active_index,voltage_str); printf("status = %d\r\n",status); } break; case 'J': { uint8_t enabled = ascii_strn2val((const char*)&data[0],16,2); status = bt_enable_voice_recognition(user_bt_env.last_active_index, enabled); printf("status = %d\r\n",status); } break; case 'K': printf("voice recog enabled : %d\r\n",bt_is_voice_rec_active(user_bt_env.last_active_index)); break; case 'L': //BD_ADDR addr; //user_bt_env.dev[0].remote_bd; #if BTDM_STACK_ENABLE_PBAP state = user_bt_get_state(user_bt_env.last_active_index); if(state >=BT_STATE_CONNECTED) { memcpy(&addr.A[0], &user_bt_env.dev[user_bt_env.last_active_index].remote_bd, 6); //printf("%x%x%x%x%x%x\r\n",addr.A[0],addr.A[1],addr.A[2],addr.A[3],addr.A[4],addr.A[5]); } else { addr.A[0] = ascii_strn2val((const char*)&data[0],16,2); addr.A[1] = ascii_strn2val((const char*)&data[2],16,2); addr.A[2] = ascii_strn2val((const char*)&data[4],16,2); addr.A[3] = ascii_strn2val((const char*)&data[6],16,2); addr.A[4] = ascii_strn2val((const char*)&data[8],16,2); addr.A[5] = ascii_strn2val((const char*)&data[10],16,2); } status = PBAP_ClientConnect(&pbap_client[0],&addr); printf("status = %d\r\n",status); #endif break; case 'M': #if BTDM_STACK_ENABLE_PBAP status = PBAP_ClientDisconnect(&pbap_client[0]); printf("status = %d\r\n",status); #endif break; case 'N': { #if BTDM_STACK_ENABLE_PBAP uint8_t pbName[64]; PbapPullPbParms parms; memcpy(pbName,PB_LOCAL_MCH_NAME,sizeof(PB_LOCAL_MCH_NAME)); parms.pbName = pbName; memset(parms.filter.byte,0,PBAP_FILTER_SIZE); parms.filter.byte[0] = 0x84; parms.listStartOffset = 0; parms.maxListCount = 100; //0---search missed call and total pb size parms.format= VCARD_FORMAT_30; status = PBAP_PullPhonebook(&pbap_client[0], &parms); printf("status = %d\r\n",status); #endif } break; case 'O': { #if BTDM_STACK_ENABLE_PBAP PbapPullVcardListingParms parms; uint8_t search_val[12]; //= "13262651013"; memcpy(search_val,&data[0],11); uint8_t folder[] = "telecom/pb"; parms.folderName = folder; parms.order = VCARD_SORT_ORDER_INDEXED; parms.listStartOffset = 0x00; parms.maxListCount = 4; parms.searchAttribute = VCARD_SEARCH_ATTRIB_NUMBER; parms.searchValue = (const char *)search_val; status = PBAP_PullVcardListing(&pbap_client[0], &parms); printf("status = %d\r\n",status); #endif } break; case 'P': { #if BTDM_STACK_ENABLE_PBAP uint8_t pbName[64]; PbapPullPbParms parms; memcpy(pbName,PB_LOCAL_STORE_NAME,sizeof(PB_LOCAL_STORE_NAME)); parms.pbName = pbName; memset(parms.filter.byte,0,PBAP_FILTER_SIZE); parms.filter.byte[0] = 0x07;//0x84; parms.listStartOffset = 0; parms.maxListCount = 20; //0---search missed call and total pb size parms.format= VCARD_FORMAT_30; status = PBAP_PullPhonebook(&pbap_client[0], &parms); printf("status = %d\r\n",status); #endif } break; case 'R': { user_connect_pbap_client(); } break; case 'T': { user_pull_phonebook(0,0,25); } break; case 'X': { uint8_t mute_str[] = "AT+CMUT=1"; status = bt_send_hf_cmd(user_bt_env.last_active_index,mute_str); printf("status = %d\r\n",status); } break; case 'Y': { flash_wr_test(); } break; case 'Q': { user_del_pbap_info(); } break; default: break; } printf("OK\r\n"); } ///bt media related cmd static void app_at_recv_cmd_E(uint8_t sub_cmd, uint8_t *data) { BD_ADDR addr; BtStatus status; switch(sub_cmd) { case 'A': status = AVRCP_SetPanelKey(user_bt_env.dev[user_bt_env.last_active_index].rcp_chan, AVRCP_POP_PLAY, TRUE); printf("status = %d\r\n",status); break; case 'B': status = AVRCP_SetPanelKey(user_bt_env.dev[user_bt_env.last_active_index].rcp_chan, AVRCP_POP_PAUSE, TRUE); printf("status = %d\r\n",status); break; case 'C': status = AVRCP_SetPanelKey(user_bt_env.dev[user_bt_env.last_active_index].rcp_chan, AVRCP_POP_FORWARD, TRUE); printf("status = %d\r\n",status); break; case 'D': { status = AVRCP_SetPanelKey(user_bt_env.dev[user_bt_env.last_active_index].rcp_chan, AVRCP_POP_BACKWARD, TRUE); printf("status = %d\r\n",status); } break; case 'E': { printf("vol %d\r\n",data[0]); uint8_t vol = data[0];//ascii_strn2val((const char*)&data[0],16,2); status = bt_set_media_volume(user_bt_env.last_active_index,vol); printf("status = %d %d\r\n",status,vol); } break; case 'F': { status = bt_get_media_info(user_bt_env.last_active_index,0x41); printf("status = %d\r\n",status); } break; case 'G': { status = bt_get_playstatus(user_bt_env.last_active_index); printf("status = %d\r\n",status); } break; case 'H': #if BTDM_STACK_ENABLE_SPP addr.A[0] = ascii_strn2val((const char*)&data[0],16,2); addr.A[1] = ascii_strn2val((const char*)&data[2],16,2); addr.A[2] = ascii_strn2val((const char*)&data[4],16,2); addr.A[3] = ascii_strn2val((const char*)&data[6],16,2); addr.A[4] = ascii_strn2val((const char*)&data[8],16,2); addr.A[5] = ascii_strn2val((const char*)&data[10],16,2); status = spp_connect(&spp_dev[0],&addr); printf("status = %d\r\n",status); #endif break; case 'I': #if BTDM_STACK_ENABLE_SPP status = spp_disconnect(&spp_dev[0]); printf("status = %d\r\n",status); #endif break; case 'J': { #if BTDM_STACK_ENABLE_SPP uint8_t test_data[] = {'1','2','3','4'}; status = spp_send(&spp_dev[0],test_data,sizeof(test_data)); printf("status = %d\r\n",status); #endif } break; default: break; } printf("OK\r\n"); } __RAM_CODE static void app_at_recv_cmd_D(uint8_t sub_cmd, uint8_t *data) { switch(sub_cmd) { case 'A': flash_erase(QSPI0, ascii_strn2val((const char*)&data[0],16,8), 0x1000); break; default: break; } printf("OK\r\n"); } __RAM_CODE void app_at_cmd_recv_handler(uint8_t *data, uint16_t length) { switch(data[0]) { case 'A': app_at_recv_cmd_A(data[1], &data[2]); break; case 'B': app_at_recv_cmd_B(data[1], &data[2]); break; case 'C': app_at_recv_cmd_C(data[1], &data[2]); break; case 'D': app_at_recv_cmd_D(data[1], &data[2]); break; case 'E': app_at_recv_cmd_E(data[1], &data[2]); break; default: break; } } static void app_at_recv_c(uint8_t c) { switch(at_recv_state) { case 0: if(c == 'A') { at_recv_state++; } break; case 1: if(c == 'T') at_recv_state++; else at_recv_state = 0; break; case 2: if(c == '#') at_recv_state++; else at_recv_state = 0; break; case 3: at_recv_buffer[at_recv_index++] = c; if((c == '\n') ||(at_recv_index >= AT_RECV_MAX_LEN)) { struct app_task_event *event; event = app_task_event_alloc(APP_TASK_EVENT_AT_CMD, at_recv_index, false); if(event) { memcpy(event->param, at_recv_buffer, at_recv_index); app_task_event_post(event, false); } at_recv_state = 0; at_recv_index = 0; } break; } } void app_at_rx_done(struct __UART_HandleTypeDef *handle) { app_at_recv_c(app_at_recv_char); if (handle) { uart_receive_IT(handle, &app_at_recv_char, 1); } } void app_at_init(void) { hw_log_init(false); uart_receive_IT(&uart_log_handle, &app_at_recv_char, 1); } void uart3_irq(void) { uart_IRQHandler(&uart_log_handle); } int fputc(int c, FILE *fp) { uart_transmit(&uart_log_handle, (void *)&c, 1); return c; } void uart_transmit_byte(uint8_t *p,uint32_t len) { uart_transmit(&uart_log_handle, (void *)p, len); }