/** * @file dloader_usb_fastboot.c * * Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. * * Description: usb fastboot package. * * Revision History: * ----------------- */ #include #include #include #include #include #include #include "dloader_usb_fastboot.h" #include "regs_base.h" #include "sdrv_fuse.h" #if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED) #define SD_VENDOR_ID 0x3273 #ifdef CONFIG_E3L #define SD_PRODUCT_ID 0x0003 #else #define SD_PRODUCT_ID 0x0002 #endif #else #define SD_VENDOR_ID 0x18d1 #define SD_PRODUCT_ID 0x4d00 #endif #define SD_VERSION_ID 0x0100 #define SD_FB_CFG_MAX_NBR_CMD 20u #define SD_FB_CFG_MAX_NBR_VAR 20u #define ANDROID_VENDOR_ID 0x18d1 #define ANDROID_PRODUCT_ID 0x4d00 #define SD_ROM_PATCH0_INDEX 112 #define SD_PID_INDEX 12 #define SD_UID_INDEX 4 #define SD_MINOR_INDEX 6 #define ERROR(format, args...) \ ssdk_printf(SSDK_CRIT, "[ERROR]DLOADER_USB_FB:%s %d " format "", __func__, \ __LINE__, ##args); #define DBG(format, args...) \ ssdk_printf(SSDK_CRIT, "[DEBUG]DLOADER_USB_FB:%s %d " format "", __func__, \ __LINE__, ##args); static char usbd_fb_serial[17] = "0000000000000000"; static char usbd_product_str[5] = "0000"; static USBD_DRV_EP_INFO USBD_DrvEP_InfoTbl[] = { {USBD_EP_INFO_TYPE_CTRL | USBD_EP_INFO_DIR_OUT, 0u, 64u}, {USBD_EP_INFO_TYPE_CTRL | USBD_EP_INFO_DIR_IN, 0u, 64u}, {USBD_EP_INFO_TYPE_ISOC | USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 1u, 512u}, {USBD_EP_INFO_TYPE_ISOC | USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 2u, 512u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 3u, 512u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 4u, 512u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 5u, 512u}, {USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 6u, 64u}, {USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 7u, 64u}, {USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 8u, 64u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 9u, 512u}, {USBD_EP_INFO_TYPE_INTR | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 10u, 64u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 11u, 512u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 12u, 512u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 13u, 512u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 14u, 512u}, {USBD_EP_INFO_TYPE_BULK | USBD_EP_INFO_DIR_OUT | USBD_EP_INFO_DIR_IN, 15u, 512u}, {DEF_BIT_NONE, 0u, 0u}}; USBD_DEV_CFG FB_USBD_DevCfg = { SD_VENDOR_ID, /* Vendor ID. */ SD_PRODUCT_ID, /* Product ID. */ SD_VERSION_ID, /* Device release number. */ "Semidrive", /* Manufacturer string. */ usbd_product_str, /* Product string. */ usbd_fb_serial, /* Serial number string. */ USBD_LANG_ID_ENGLISH_US /* String language ID. */ }; static const USBD_DRV_CFG FB_USBD_DrvCfg = { DEVICE_BASE(USB0D), /* Base addr of device controller hw registers. */ 0u, /* Base addr of device controller dedicated mem. */ 0u, /* Size of device controller dedicated mem. */ #if (USBD_CFG_HS_EN == DEF_ENABLED) USBD_DEV_SPD_HIGH, /* Speed of device controller. */ #else USBD_DEV_SPD_FULL, #endif USBD_DrvEP_InfoTbl /* EP Info tbl of device controller. */ }; /* Donnot care about bus events. */ static USBD_BUS_FNCTS FB_USBD_BusFncts; static fastboot_dev_t fb_dev = {USBD_CLASS_NBR_NONE, USBD_DEV_NBR_NONE}; static USBD_FB_CMD fb_cmd_tbl[SD_FB_CFG_MAX_NBR_CMD] = { {"getvar:", USBD_FB_CmdGetVar}, {"download:", USBD_FB_CmdDownload}, }; static CPU_INT16U fb_cmd_len = 2; static USBD_FB_VAR fb_var_tbl[SD_FB_CFG_MAX_NBR_VAR] = { {"version", "0.5"}, {"name", "fastboot"}, }; static CPU_INT16U fb_var_len = 2; static void get_product_no(void) { uint32_t product_id = 0; usbd_product_str[4] = 0; uint8_t *buf = NULL; uint32_t ret = 0; buf = (uint8_t *)&product_id; ret = sdrv_fuse_sense(SD_MINOR_INDEX, &product_id); if (ret) { ERROR("fuse_sense error, use product no = 0000\r\n"); return; } snprintf(usbd_product_str, sizeof(usbd_product_str), "%02X%02X", buf[1], buf[0]); DBG("usbd_product str = %s\r\n", usbd_product_str); } static void get_serialno(void) { uint32_t serial_fuse[2] = {0}; uint8_t *buf = NULL; uint32_t ret = 0; ret = sdrv_fuse_sense(SD_UID_INDEX, &serial_fuse[0]); ret |= sdrv_fuse_sense(SD_UID_INDEX + 1, &serial_fuse[1]); usbd_fb_serial[16] = 0; if (ret) { ERROR("fuse_sense error, use serialno = 0000000000000000\r\n"); return; } buf = (uint8_t *)serial_fuse; snprintf(usbd_fb_serial, sizeof(usbd_fb_serial), "%02X%02X%02X%02X%02X%02X%02X%02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); DBG("patched usbd_fb_serial = %s\r\n", usbd_fb_serial); } static void get_vid_pid(uint16_t *vid, uint16_t *pid) { uint32_t pid_vid_fuse = 0; uint32_t use_semidrive_pid_vid = 0; uint32_t ret = 0; ret = sdrv_fuse_sense(SD_PID_INDEX, &pid_vid_fuse); ret |= sdrv_fuse_sense(SD_ROM_PATCH0_INDEX, &use_semidrive_pid_vid); if (ret) { *pid = ANDROID_PRODUCT_ID; *vid = ANDROID_VENDOR_ID; ERROR("fuse_sense error, use pid = 0x%04x , vid = 0x%04x \r\n", *pid, *vid); return; } *pid = pid_vid_fuse & 0xFFFFU; *vid = (pid_vid_fuse >> 16) & 0xFFFFU; use_semidrive_pid_vid = ((use_semidrive_pid_vid >> 14) & 0x1); DBG("use semidrive pid vid = %d\r\n", use_semidrive_pid_vid); DBG("origin fuse vid:0x%0x pid:0x%0x\r\n", *vid, *pid); if (*pid == 0) { if (use_semidrive_pid_vid) *pid = SD_PRODUCT_ID; else *pid = ANDROID_PRODUCT_ID; } if (*vid == 0) { if (use_semidrive_pid_vid) *vid = SD_VENDOR_ID; else *vid = ANDROID_VENDOR_ID; } DBG("final vid:0x%0x pid:0x%0x\r\n", *vid, *pid); } bool App_USBD_FB_Init(fastboot_dev_t *fbd, CPU_INT08U cfg_hs, CPU_INT08U cfg_fs) { USBD_ERR err; CPU_INT08U fb_nbr; bool valid; DBG(" Initializing MSC class ... \r\n"); USBD_FB_Init(&err); if (err != USBD_ERR_NONE) { ERROR(" ... could not initialize MSC class w/err = %d\r\n\r\n", err); return 0; } fb_nbr = USBD_FB_Add(&err); if (cfg_hs != USBD_CFG_NBR_NONE) { valid = USBD_FB_CfgAdd(fb_nbr, fbd->dev_nbr, cfg_hs, &err); if (!valid) { ERROR(" ... could not add msc instance #%d to HS " "configuration w/err = %d\r\n\r\n", fb_nbr, err); return 0; } } if (cfg_fs != USBD_CFG_NBR_NONE) { valid = USBD_FB_CfgAdd(fb_nbr, fbd->dev_nbr, cfg_fs, &err); if (!valid) { ERROR(" ... could not add msc instance #%d to FS " "configuration w/err = %d\r\n\r\n", fb_nbr, err); return 0; } } fbd->cls_nbr = fb_nbr; #if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED) USBD_DevSetMS_VendorCode(fbd->dev_nbr, 1u, &err); if (err != USBD_ERR_NONE) { ERROR(" ... could not set MS vendor code w/err = %d\r\n\r\n", err); } #endif return 1; } static bool fastboot_common_usb_init(fastboot_dev_t *fbd) { CPU_INT08U dev_nbr; CPU_INT08U cfg_hs_nbr; CPU_INT08U cfg_fs_nbr; bool ok; USBD_ERR err; uint16_t vid; uint16_t pid; DBG("Initializing USB Device...\r\n"); get_vid_pid(&vid, &pid); FB_USBD_DevCfg.VendorID = vid; FB_USBD_DevCfg.ProductID = pid; get_serialno(); get_product_no(); if ((vid != SD_VENDOR_ID) && (vid != ANDROID_VENDOR_ID)) FB_USBD_DevCfg.ManufacturerStrPtr = "MANUFACTER"; USBD_Init(&err); if (err != USBD_ERR_NONE) { ERROR("... init failed w/err = %d\r\n\r\n", err); return 0; } DBG(" Adding controller driver ... \r\n"); /* Add USB device instance. */ dev_nbr = USBD_DevAdd((USBD_DEV_CFG *)&FB_USBD_DevCfg, &FB_USBD_BusFncts, &USBD_DrvAPI_RenesasRZ_DMA, &FB_USBD_DrvCfg, &USBD_DrvBSP_TAISHAN_USB0, &err); if (err != USBD_ERR_NONE) { ERROR(" ... could not add controller driver w/err = %d\r\n\r\n", err); return 0; } /* Device is not self-powered. */ USBD_DevSelfPwrSet(dev_nbr, DEF_NO, &err); cfg_hs_nbr = USBD_CFG_NBR_NONE; cfg_fs_nbr = USBD_CFG_NBR_NONE; #if (USBD_CFG_HS_EN == DEF_ENABLED) DBG(" Adding HS configuration ... \r\n"); /* Add HS configuration. */ cfg_hs_nbr = USBD_CfgAdd(dev_nbr, USBD_DEV_ATTRIB_SELF_POWERED, 100u, USBD_DEV_SPD_HIGH, "HS fastboot config", &err); if (err != USBD_ERR_NONE) { ERROR(" ... could not add HS configuration w/err = %d\r\n\r\n", err); /* Continue if dev is not high-speed. */ if (err != USBD_ERR_DEV_INVALID_SPD) { return 0; } } #endif DBG(" Adding FS configuration ... \r\n"); /* Add FS configuration. */ cfg_fs_nbr = USBD_CfgAdd(dev_nbr, USBD_DEV_ATTRIB_SELF_POWERED, 100u, USBD_DEV_SPD_FULL, "FS fastboot config", &err); if (err != USBD_ERR_NONE) { ERROR(" ... could not add FS configuration w/err = %d\r\n\r\n", err); return 0; } #if (USBD_CFG_HS_EN == DEF_ENABLED) if ((cfg_fs_nbr != USBD_CFG_NBR_NONE) && (cfg_hs_nbr != USBD_CFG_NBR_NONE)) { /* Associate both config for other spd desc. */ USBD_CfgOtherSpeed(dev_nbr, cfg_hs_nbr, cfg_fs_nbr, &err); if (err != USBD_ERR_NONE) { ERROR(" ... could not associate other speed configuration w/err " "= %d\r\n\r\n", err); return 0; } } #endif DBG(" Initializing USB classes ... \r\n"); fbd->dev_nbr = dev_nbr; /* Initialize MSC class. */ ok = App_USBD_FB_Init(fbd, cfg_hs_nbr, cfg_fs_nbr); if (!ok) { ERROR(" ... could not initialize MSC class w/err = %d\r\n\r\n", err); return 0; } return 1; } void fastboot_register_cmd(const char *prefix, USBD_FB_CMD_HDL handle) { if (!prefix || !*prefix || !handle || (fb_cmd_len >= SD_FB_CFG_MAX_NBR_CMD)) { ERROR("Add command fail cmd len=%d\r\n", fb_cmd_len); return; } fb_cmd_tbl[fb_cmd_len].cmd = prefix; fb_cmd_tbl[fb_cmd_len].handler = handle; fb_cmd_len++; } void fastboot_register_var(const char *name, const char *value) { if (!name || !*name || !value || !*value || (fb_var_len >= SD_FB_CFG_MAX_NBR_VAR)) { ERROR("Add variable fail var len=%d\r\n", fb_var_len); return; } fb_var_tbl[fb_var_len].name = name; fb_var_tbl[fb_var_len].value = value; fb_var_len++; } fastboot_t *fastboot_common_init(void *dl_addr, uint32_t dl_sz) { fastboot_dev_t *fbd; bool ok; USBD_ERR err; fbd = &fb_dev; ok = fastboot_common_usb_init(fbd); if (!ok) return NULL; USBD_FB_SetDL(fbd->cls_nbr, dl_addr, dl_sz, &err); USBD_FB_SetCmdTbl(fbd->cls_nbr, fb_cmd_tbl, fb_cmd_len, &err); USBD_FB_SetVarTbl(fbd->cls_nbr, fb_var_tbl, fb_var_len, &err); USBD_DevStart(fbd->dev_nbr, &err); if (err != USBD_ERR_NONE) { ERROR(" ... could not start device stack w/err = %d\r\n\r\n", err); return NULL; } DBG(" .... USB classes initialization done.\r\n"); return &fbd->cls_nbr; } void fastboot_common_okay(fastboot_t *fb, const char *reason) { if (fb) { USBD_FB_Okay(fb, reason); } } void fastboot_common_fail(fastboot_t *fb, const char *reason) { if (fb) { USBD_FB_Fail(fb, reason); } } void fastboot_common_info(fastboot_t *fb, const char *reason) { if (fb) { USBD_FB_Info(fb, reason); } } void fastboot_common_stop(fastboot_t *fb) { USBD_ERR err; if (fb && (*fb == fb_dev.cls_nbr)) { USBD_DevStop(fb_dev.dev_nbr, &err); } }