#ifdef SUPPORT_MS_EXTENSIONS #pragma bss_seg(".source_dev0_file.data.bss") #pragma data_seg(".source_dev0_file.data") #pragma const_seg(".source_dev0_file.text.const") #pragma code_seg(".source_dev0_file.text") #endif #include "classic/hci_lmp.h" #include "source_node.h" #include "jlstream.h" #include "media/audio_base.h" #include "app_config.h" /* 若源节点为中断节点,则需打开SOURCE_DEV0_IRQ_ENABLE 并且在中断中调用source_dev0_packet_rx_notify, 用于中断收到数据时,主动唤醒数据流 */ #define SOURCE_DEV0_IRQ_ENABLE 0 //中断节点使能 #define SOURCE_DEV0_MSBC_TEST_ENABLE 0 //MSBC解码测试, 使用MSBC固定数据测试 #if TCFG_SOURCE_DEV0_NODE_ENABLE struct source_dev0_file_hdl { u8 start; //启动标志 struct stream_node *node; //节点句柄 u8 bt_addr[6]; //蓝牙MAC地址 }; #if SOURCE_DEV0_MSBC_TEST_ENABLE unsigned char source_test_data[60] = { 0x01, 0x08, 0xAD, 0x00, 0x00, 0x35, 0xC3, 0x31, 0x01, 0x00, 0x7F, 0xEF, 0x76, 0xDF, 0xFB, 0x9D, 0xB8, 0x05, 0x08, 0x6E, 0x04, 0x4E, 0x0B, 0x83, 0xF6, 0xBA, 0x62, 0xD0, 0x62, 0xB9, 0x1B, 0x27, 0x6E, 0x5F, 0xB9, 0xDB, 0x9E, 0x2F, 0x76, 0xE9, 0x1B, 0xDD, 0xBA, 0xAA, 0xF7, 0x4E, 0xC3, 0xBD, 0xDB, 0xB7, 0x2F, 0x74, 0xEF, 0x5B, 0xDD, 0x3C, 0x3A, 0xF7, 0x6C, 0x00 }; #endif /* 输入源节点数据 hdl 节点私有句柄 *len 源节点数据长度 return 源节点数据指针 */ static u8 *source_dev0_get_packet(struct source_dev0_file_hdl *hdl, u32 *len) { u8 *packet = NULL; u32 packet_len = 0; //do something #if SOURCE_DEV0_MSBC_TEST_ENABLE u8 test_buf[4] = {0x08, 0x38, 0xc8, 0xf8}; packet_len = sizeof(source_test_data); packet = source_test_data; static u8 i = 0; packet[1] = test_buf[i++]; if (i > 3) { i = 0; } #endif *len = packet_len; return packet; } //释放源节点数据 static int source_dev0_free_packet(struct source_dev0_file_hdl *hdl, u8 *packet) { /* free(packet); */ return 0; } //自定义源节点挂起 static void source_dev0_suspend(struct source_dev0_file_hdl *hdl) { /* do something 1、启动丢数-避免suspend时 自定义源节点数据溢出 2、挂起时,源节点需要的其他流程 */ } //自定义源节点 初始化 static void source_dev0_open(struct source_dev0_file_hdl *hdl) { /* do something 1、关闭丢数-用于suspend流程保护 2、(中断节点需要)注册自定义源节点收包回调 source_dev0_packet_rx_notify 3、自定义源节点启动流程 */ } //自定义源节点 停止 static void source_dev0_close(struct source_dev0_file_hdl *hdl) { //do something } /* 自定义源节点 参数设置 *fmt 目标参数,如采样率,数据类型,通道模式 */ static void source_dev0_get_fmt(struct source_dev0_file_hdl *hdl, struct stream_fmt *fmt) { #if SOURCE_DEV0_MSBC_TEST_ENABLE fmt->sample_rate = 16000; //采样率 fmt->coding_type = AUDIO_CODING_MSBC; //数据类型 fmt->channel_mode = AUDIO_CH_LR; //通道模式 #endif } /* (当前节点为中断节点使用) 自定义源节点收包回调 - 用于自定义源节点收到数时, 唤醒数据流 */ static void source_dev0_packet_rx_notify(void *_hdl) { struct source_dev0_file_hdl *hdl = (struct source_dev0_file_hdl *)_hdl; //启动状态才触发 if (hdl->start) { jlstream_wakeup_thread(NULL, hdl->node, NULL); } } static enum stream_node_state source_dev0_get_frame(void *_hdl, struct stream_frame **_frame) { u32 len = 0; struct source_dev0_file_hdl *hdl = (struct source_dev0_file_hdl *)_hdl; struct stream_frame *frame; //1、获取当前节点数据 u8 *packet = source_dev0_get_packet(hdl, &len); if (!packet) { *_frame = NULL; //表示源节点获取不到数据 return NODE_STA_RUN | NODE_STA_SOURCE_NO_DATA; } //2、申请数据流frame空间 frame = jlstream_get_frame(hdl->node->oport, len); frame->len = len; //3、将当前节点数据拷贝到frame memcpy(frame->data, packet, len); //4、释放当前节点数据 source_dev0_free_packet(hdl, packet); *_frame = frame; return NODE_STA_RUN; } static void *source_dev0_init(void *priv, struct stream_node *node) { struct source_dev0_file_hdl *hdl = zalloc(sizeof(*hdl)); hdl->node = node; #if SOURCE_DEV0_IRQ_ENABLE node->type |= NODE_TYPE_IRQ; #endif/*SOURCE_DEV0_IRQ_ENABLE*/ return hdl; } //获取当前蓝牙地址 static int source_dev0_ioc_set_bt_addr(struct source_dev0_file_hdl *hdl, u8 *bt_addr) { memcpy(hdl->bt_addr, bt_addr, 6); return 0; } //获取当前节点数据参数 static void source_dev0_ioc_get_fmt(struct source_dev0_file_hdl *hdl, struct stream_fmt *fmt) { source_dev0_get_fmt(hdl, fmt); } static void source_dev0_ioc_suspend(struct source_dev0_file_hdl *hdl) { hdl->start = 0; source_dev0_suspend(hdl); } static void source_dev0_ioc_start(struct source_dev0_file_hdl *hdl) { source_dev0_open(hdl); hdl->start = 1; } static void source_dev0_ioc_stop(struct source_dev0_file_hdl *hdl) { hdl->start = 0; source_dev0_close(hdl); } static int source_dev0_ioctl(void *_hdl, int cmd, int arg) { struct source_dev0_file_hdl *hdl = (struct source_dev0_file_hdl *)_hdl; switch (cmd) { case NODE_IOC_SET_BTADDR: source_dev0_ioc_set_bt_addr(hdl, (u8 *)arg); break; case NODE_IOC_GET_FMT: source_dev0_ioc_get_fmt(hdl, (struct stream_fmt *)arg); break; case NODE_IOC_SET_SCENE: break; case NODE_IOC_SUSPEND: source_dev0_ioc_suspend(hdl); break; case NODE_IOC_START: source_dev0_ioc_start(hdl); break; case NODE_IOC_STOP: source_dev0_ioc_stop(hdl); break; } return 0; } static void source_dev0_release(void *_hdl) { struct source_dev0_file_hdl *hdl = (struct source_dev0_file_hdl *)_hdl; free(hdl); } REGISTER_SOURCE_NODE_PLUG(source_dev0_file_plug) = { .uuid = NODE_UUID_SOURCE_DEV0, .init = source_dev0_init, .get_frame = source_dev0_get_frame, .ioctl = source_dev0_ioctl, .release = source_dev0_release, }; #endif