#include "includes.h" #include "app_config.h" #include "dev_multiplex_api.h" #include "usb/otg.h" #include "dev_manager.h" #include "music/music_player.h" #define LOG_TAG_CONST APP_ACTION #define LOG_TAG "[APP_ACTION]" #define LOG_ERROR_ENABLE #define LOG_DEBUG_ENABLE #define LOG_INFO_ENABLE /* #define LOG_DUMP_ENABLE */ #define LOG_CLI_ENABLE #include "debug.h" extern u8 sd_io_suspend(u8 sdx, u8 sd_io); extern u8 sd_io_resume(u8 sdx, u8 sd_io); static u8 msg_notify_enable = 0xff; static u8 sd_first_online = 0; static u16 resume = 0; #define USB_ACTIVE 0x1 #define SD_ACTIVE 0x2 #define MULT_IO_IDLE (0) #define MULT_IO_ACTIVE (BIT(0)) #define MULT_IO_SUSPEND (BIT(1)) #define USB_RESET_DELAY 20 struct mult_io { u8 sd_status: 3; u8 usb_status: 3; u8 active: 2; }; struct mult_io mult_flag = {0}; /*----------------------------------------------------------------------------*/ /**@brief 库的调用函数 重载了库驱动 如果返回真则可以发送sd卡的上下线消息 @param 无 @return 无 @note */ /*----------------------------------------------------------------------------*/ #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 int sd_notify_enable(int sd_id) { return msg_notify_enable & BIT(sd_id); } #endif /*----------------------------------------------------------------------------*/ /**@brief 设置是否 sd卡可以推上下线消息 @param 1:可以推 0:不推 @return 无 @note */ /*----------------------------------------------------------------------------*/ void set_sd_notify_enable(int sd_id, u8 en) { if (en) { msg_notify_enable |= BIT(sd_id); } else { msg_notify_enable &= ~BIT(sd_id); } } void mult_sdio_resume_clean() { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if (resume) { sd_io_resume(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 2);//sd_data0 io 状态会被还原 resume = 0; } #endif } void mult_sdio_resume() { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if (resume) { resume--; if (!resume) { sd_io_resume(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 2);//sd_data0 io 状态会被还原 } } #endif } int mult_sdio_suspend() { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if (resume) { printf("%s resume count = %d\n", __FUNCTION__, resume); return 0; } __try_t: if (sd_io_suspend(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 2)) { os_time_dly(1); printf("wait %s\n", __FUNCTION__); goto __try_t; } resume++; //配置绑定的sd_data0 io 为高阻 gpio_set_direction(TCFG_USB_SD_MULTIPLEX_IO, 1); gpio_set_pull_up(TCFG_USB_SD_MULTIPLEX_IO, 0); gpio_set_pull_down(TCFG_USB_SD_MULTIPLEX_IO, 0); gpio_set_die(TCFG_USB_SD_MULTIPLEX_IO, 0); #endif return 0; } void mult_usb_suspend(usb_dev id) { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if (id != (usb_dev) - 1 && usb_otg_online(id) == HOST_MODE) { printf("mult_usb_suspend\n"); usb_otg_io_suspend(id); } #endif } int mult_usb_resume(usb_dev id, u8 mount, u32 delay) { int err = -1; #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if (id != (usb_dev) - 1 && usb_otg_online(id) == HOST_MODE) { usb_otg_io_resume(id); /* * 有一部分U盘在DM和SD DAT0复用时,插入U盘或者模式切到播U盘, * 需要把DPDM拉低一段时间,让U盘自己认为插入了主机 */ if (delay) { usb_otg_suspend(id, 0); os_time_dly(delay); usb_otg_resume(id); } if (mount) { if (dev_manager_online_check_by_logo("udisk0", 0)) { dev_manager_unmount("udisk0"); } if (usb_host_remount(id, MOUNT_RETRY, MOUNT_RESET, MOUNT_TIMEOUT, 0)) { log_error("udisk remount fail\n"); } else { err = dev_manager_mount("udisk0"); return err; } } else { err = 0; } } #endif return err; } int dev_sd_change_usb() { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if ((mult_flag.sd_status == MULT_IO_ACTIVE) || (mult_flag.usb_status == MULT_IO_SUSPEND)) { printf("sd_change_usb start \n"); mult_sdio_suspend(); mult_flag.sd_status = MULT_IO_SUSPEND; mult_usb_resume(g_usb_id, 1, USB_RESET_DELAY); mult_flag.usb_status = MULT_IO_ACTIVE; mult_flag.active = USB_ACTIVE; printf("sd_change_usb finsh \n"); } #endif return 0; } int dev_usb_change_sd() { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if ((mult_flag.usb_status == MULT_IO_ACTIVE) || (mult_flag.sd_status == MULT_IO_SUSPEND)) { printf("dev_usb_change_sd start \n"); mult_usb_suspend(g_usb_id); os_time_dly(1);// mult_flag.usb_status = MULT_IO_SUSPEND; mult_sdio_resume(); mult_flag.sd_status = MULT_IO_ACTIVE; mult_flag.active = SD_ACTIVE; printf("dev_usb_change_sd finsh \n"); } return 0; #endif return true; } int mult_sd_online_mount_before(int sd_dev, usb_dev usb_id) { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if (TCFG_DM_MULTIPLEX_WITH_SD_PORT != sd_dev) { return 0; } sd_first_online = 1; music_player_stop(1);//停止解码 if (mult_flag.active == USB_ACTIVE) { mult_usb_suspend(g_usb_id); } mult_sdio_resume_clean(); mult_flag.usb_status = MULT_IO_SUSPEND; mult_flag.sd_status = MULT_IO_ACTIVE; mult_flag.active = SD_ACTIVE; #endif return 0; } int mult_sd_online_mount_after(int sd_dev, usb_dev usb_id, int err) { int ret = 0; #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if (TCFG_DM_MULTIPLEX_WITH_SD_PORT != sd_dev) { return 0; } if (err) { mult_flag.sd_status = MULT_IO_SUSPEND; mult_sdio_suspend(); mult_usb_resume(usb_id, 1, USB_RESET_DELAY); mult_flag.usb_status = MULT_IO_ACTIVE; mult_flag.active = USB_ACTIVE; } #endif return ret; } int mult_sd_offline_before(void *logo, usb_dev usb_id) { int ret = 0 ; /* u8 dev_logo[16]; */ #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 int str_len = 0; if (!sd_first_online) { //没有收到过上线消息不处理下线 return 0; } if ((TCFG_DM_MULTIPLEX_WITH_SD_PORT == 0) && strcmp("sd0", logo)) { return 0; } if ((TCFG_DM_MULTIPLEX_WITH_SD_PORT == 1) && strcmp("sd1", logo)) { return 0; } printf("MULT_SD_OFFLINE_BEFORE\n"); if (mult_flag.active == SD_ACTIVE) { const char *cur_logo = music_player_get_phy_dev(&str_len); #if (TCFG_DM_MULTIPLEX_WITH_SD_PORT == 0) if (cur_logo && (0 == strncmp(cur_logo, "sd0", str_len))) { printf("SD0 STOP FIRST !!!"); music_player_stop(1);//停止解码 } #else if (cur_logo && (0 == strncmp(cur_logo, "sd1", str_len))) { printf("SD1 STOP FIRST !!!"); music_player_stop(1);//停止解码 } #endif if (dev_manager_check_by_logo(logo)) { dev_manager_del(logo); } /* sprintf(dev_logo, "%s%s", logo, "_rec"); */ /* if (dev_manager_check_by_logo(dev_logo)) { */ /* dev_manager_del(dev_logo); */ /* } */ mult_flag.sd_status = MULT_IO_IDLE; mult_sdio_suspend(); mult_usb_resume(usb_id, 1, USB_RESET_DELAY); mult_flag.usb_status = MULT_IO_ACTIVE; mult_flag.active = USB_ACTIVE; } else if (mult_flag.active == USB_ACTIVE) { if (dev_manager_check_by_logo(logo)) { dev_manager_del(logo); } /* sprintf(dev_logo, "%s%s", logo, "_rec"); */ /* if (dev_manager_check_by_logo(dev_logo)) { */ /* dev_manager_del(dev_logo); */ /* } */ mult_sdio_resume(); mult_flag.sd_status = MULT_IO_SUSPEND; } #endif return ret; } int mult_usb_mount_before(usb_dev usb_id) { u32 reset_delay = 0;; #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 music_player_stop(1);//停止解码 if (mult_flag.active == SD_ACTIVE) { mult_sdio_suspend(); reset_delay = USB_RESET_DELAY; } mult_usb_resume(usb_id, 0, reset_delay); mult_flag.sd_status = MULT_IO_SUSPEND; mult_flag.usb_status = MULT_IO_ACTIVE; mult_flag.active = USB_ACTIVE; #endif return 0; } int mult_usb_online_mount_after(usb_dev usb_id, int err) { int ret = 0; #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 if (err) { mult_flag.usb_status = MULT_IO_SUSPEND; mult_usb_suspend(usb_id); mult_sdio_resume(); mult_flag.sd_status = MULT_IO_ACTIVE; mult_flag.active = SD_ACTIVE; } #endif return ret; } int mult_usb_mount_offline(usb_dev usb_id) { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 mult_usb_suspend(usb_id); mult_sdio_resume(); mult_flag.usb_status = MULT_IO_SUSPEND; if (mult_flag.active == USB_ACTIVE) { mult_flag.sd_status = MULT_IO_SUSPEND; mult_flag.active = 0; } else { mult_flag.sd_status = MULT_IO_ACTIVE; mult_flag.active = SD_ACTIVE; } #endif return 0; } ///*----------------------------------------------------------------------------*/ /**@brief pc模式 usb和sd卡 io 复用初始化 @param 无 @return 无 @note */ /*----------------------------------------------------------------------------*/ void pc_dm_multiplex_init() { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 mult_sdio_suspend();//supend sd卡总线 set_sd_notify_enable(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 0); //sd卡不允许发出上下线消息 gpio_set_die(TCFG_USB_SD_MULTIPLEX_IO, 1); gpio_direction_output(TCFG_USB_SD_MULTIPLEX_IO, 0); os_time_dly(2); gpio_set_direction(TCFG_USB_SD_MULTIPLEX_IO, 1); gpio_set_pull_up(TCFG_USB_SD_MULTIPLEX_IO, 0); gpio_set_pull_down(TCFG_USB_SD_MULTIPLEX_IO, 0); gpio_set_die(TCFG_USB_SD_MULTIPLEX_IO, 0); #endif } void pc_dm_multiplex_exit() { #if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 mult_sdio_resume();//resume sd卡总线 usb_otg_resume(0); set_sd_notify_enable(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 1); //sd卡允许发出上下线消息 #endif }