Files
kernel_drivers_examples/debug/usb/cmd_rockusb.c
2017-05-20 10:46:03 +00:00

1266 lines
37 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define IN_FW_Upgrade
#include <cmd_rockusb.h>
#include <asm/arch/rkplat.h>
#if defined(CONFIG_RK_UDC)
#include <usb/dwc_otg_udc.h>
#endif
#ifdef CONFIG_RK_DWC3_UDC
#include <dwc3-uboot.h>
#include <usb/dwc3_rk_udc.h>
#endif
#include <../board/rockchip/common/config.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_ROCKUSB_TIMEOUT_CHECK
static uint64_t TimeOutBase;
#endif
#ifdef CONFIG_RK_DWC3_UDC
static void rkusb_init_strings(void);
int rkusb_write_bulk_ep(uint32_t nLen, void *buf)
{
usbcmd.tx_giveback.status = SEND_IN_PROGRESS;
usbcmd.tx_giveback.actual = 0;
usbcmd.tx_giveback.buf = NULL;
return RK_Dwc3WriteBulkEndpoint(nLen, buf);
}
int rkusb_read_bulk_ep(uint32_t nLen, void *buf)
{
usbcmd.rx_giveback.status = RECV_READY;
usbcmd.rx_giveback.actual = 0;
usbcmd.rx_giveback.buf = NULL;
return RK_Dwc3ReadBulkEndpoint(nLen, buf);
}
void rkusb_event_handler_for_dwc3(int nEvent)
{
int event = nEvent & 0xffff;
int param = nEvent>>16;
RKUSBINFO("@rkusb_event_handler_for_dwc3 %d\n", event);
switch (event) {
case 1:/* Device_Reset */
case 5:/* Device_Disconnect */
usbcmd.configured = 0;
break;
case 2:/* DEVICE_CONFIGURED */
usbcmd.configured = 1;
usbcmd.txbuf_num = 0;
usbcmd.rxbuf_num = 0;
usbcmd.tx_giveback.status = SEND_FINISHED_OK;
usbcmd.tx_giveback.actual = 0;
rkusb_read_bulk_ep(31, usbcmd.rx_buffer[usbcmd.rxbuf_num]);
usbcmd.rxbuf_num = (usbcmd.rxbuf_num + 1) % 2;
break;
case 3:/* DEVICE_ADDRESS_ASSIGNED */
usbcmd.status = RKUSB_STATUS_IDLE;
break;
case 4:/* DEVICE_CLEAR_FEATURE */
usbcmd.status = RKUSB_STATUS_IDLE;
/* in ep */
if (param == 0) {
usbcmd.txbuf_num = 0;
usbcmd.tx_giveback.status = SEND_FINISHED_OK;
usbcmd.tx_giveback.actual = 0;
}
/* out ep */
if (param == 0x1) {
usbcmd.rxbuf_num = 0;
rkusb_read_bulk_ep(31, usbcmd.rx_buffer[usbcmd.rxbuf_num]);
usbcmd.rxbuf_num = (usbcmd.rxbuf_num + 1) % 2;
}
/* in and out ep */
if (param == 0x10) {
usbcmd.txbuf_num = 0;
usbcmd.tx_giveback.status = SEND_FINISHED_OK;
usbcmd.tx_giveback.actual = 0;
usbcmd.rxbuf_num = 0;
rkusb_read_bulk_ep(31, usbcmd.rx_buffer[usbcmd.rxbuf_num]);
usbcmd.rxbuf_num = (usbcmd.rxbuf_num + 1) % 2;
}
default:
break;
}
}
/* usb设备通过该函数获取到对断发送过来的数据 */
void dwc3_rx_handler(int status, uint32_t actual, void *buf)
{
if (status)
{
usbcmd.rx_giveback.status = RECV_ERROR;
}
else
{
usbcmd.rx_giveback.status = RECV_OK;
usbcmd.rx_giveback.actual = actual;
usbcmd.rx_giveback.buf = buf;
}
}
void dwc3_tx_handler(int status, uint32_t actual, void *buf)
{
if (status) {
usbcmd.tx_giveback.status = SEND_FINISHED_ERROR;
} else {
usbcmd.tx_giveback.status = SEND_FINISHED_OK;
usbcmd.tx_giveback.actual = actual;
usbcmd.tx_giveback.buf = buf;
}
}
/* 初始化usb实例 */
void init_dwc3_udc_instance(struct rk_dwc3_udc_instance *instance)
{
int i;
memset(instance, 0, sizeof(*instance));
/* 设置usb设备描述符,配置描述符, 接口描述符 */
instance->device_desc = &device_descriptor;
instance->config_desc = (void *)&rkusb_config_desc.configuration_desc;
instance->interface_desc = &rkusb_config_desc.interface_desc;
/*
* 在board_f.c里设置的地址
* rx_buffer[0] 保存起始地址
* rx_buffer[1] 保存结束地址
* tx_buffer[0] 保存起始地址
* tx_buffer[1] 保存结束地址
*
* rx_buffer[0] --> ------
* CONFIG_RK_BOOT_BUFFER_SIZE / 2
* rx_buffer[1] --> ------ <-- tx_buffer[0]
* CONFIG_RK_BOOT_BUFFER_SIZE / 2
* rx_buffer[1] --> ------
*/
usbcmd.rx_buffer[0] = (u8 *)gd->arch.rk_boot_buf_addr;
usbcmd.rx_buffer[1] = usbcmd.rx_buffer[0]+(CONFIG_RK_BOOT_BUFFER_SIZE>>2);
usbcmd.tx_buffer[0] = (u8 *)gd->arch.rk_boot_buf_addr + (CONFIG_RK_BOOT_BUFFER_SIZE>>1);
usbcmd.tx_buffer[1] = usbcmd.tx_buffer[0]+(CONFIG_RK_BOOT_BUFFER_SIZE>>2);
/* 设置usb设备端点描述符, tx,rx起止地址 */
for (i = 0; i < 2; i++)
{
instance->endpoint_desc[i] = &rkusb_config_desc.endpoint_desc[i];
instance->rx_buffer[i] = usbcmd.rx_buffer[i];
instance->tx_buffer[i] = usbcmd.tx_buffer[i];
}
/* 设置usb设备tx,rx大小 */
instance->rx_buffer_size = CONFIG_RK_BOOT_BUFFER_SIZE>>2;
instance->tx_buffer_size = CONFIG_RK_BOOT_BUFFER_SIZE>>2;
/* 端点0的字符串描述最终保存在usb_strings和rkusb_string_table */
rkusb_init_strings();
/* 设置usb设备的字符串描述 */
for (i = 0; i < STR_COUNT; i++)
instance->string_desc[i] = rkusb_string_table[i];
/* 事件处理函数 */
instance->device_event = rkusb_event_handler_for_dwc3;
instance->rx_handler = dwc3_rx_handler;
instance->tx_handler = dwc3_tx_handler;
}
#endif
#ifdef CONFIG_RK_UDC
/* USB specific */
void rkusb_receive_firstcbw(void)
{
struct usb_endpoint_instance *ep = &endpoint_instance[1];
/* get first CBW */
ep->rcv_urb->buffer = (u8 *)&usbcmd.cbw;
ep->rcv_urb->buffer_length = 31;
ep->rcv_urb->actual_length = 0;
/* make sure endpoint will be re-enabled */
suspend_usb();
resume_usb(ep, 0);
}
static void rkusb_event_handler (struct usb_device_instance *device,
usb_device_event_t event, int data)
{
RKUSBINFO("@rkusb_event_handler %x\n", event);
switch (event) {
case DEVICE_RESET:
case DEVICE_BUS_INACTIVE:
usbcmd.configured = 0;
break;
case DEVICE_CONFIGURED:
usbcmd.configured = 1;
break;
case DEVICE_ADDRESS_ASSIGNED:
usbcmd.status = RKUSB_STATUS_IDLE;
rkusb_init_endpoints();
rkusb_receive_firstcbw();
case DEVICE_CLEAR_FEATURE:
usbcmd.status = RKUSB_STATUS_IDLE;
endpoint_instance[2].tx_urb->status = SEND_FINISHED_OK;
endpoint_instance[1].rcv_urb->status = RECV_OK;
rkusb_receive_firstcbw();
default:
break;
}
}
#endif
/* utility function for converting char* to wide string used by USB */
static void str2wide(char *str, u16 *wide)
{
int i;
for (i = 0; i < strlen(str) && str[i]; i++) {
#if defined(__LITTLE_ENDIAN)
wide[i] = (u16) str[i];
#elif defined(__BIG_ENDIAN)
wide[i] = ((u16)(str[i])<<8);
#else
#error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined"
#endif
}
}
/* 初始化字符描述符 */
static void rkusb_init_strings(void)
{
struct usb_string_descriptor *string;
rkusb_string_table[STR_LANG] = (struct usb_string_descriptor *)wstr_lang;
string = (struct usb_string_descriptor *)wstr_manufacturer;
string->bLength = sizeof(wstr_manufacturer);
string->bDescriptorType = USB_DT_STRING;
str2wide(CONFIG_USBD_MANUFACTURER, string->wData);
rkusb_string_table[STR_MANUFACTURER] = string;
string = (struct usb_string_descriptor *)wstr_product;
string->bLength = sizeof(wstr_product);
string->bDescriptorType = USB_DT_STRING;
str2wide(CONFIG_USBD_PRODUCT_NAME, string->wData);
rkusb_string_table[STR_PRODUCT] = string;
string = (struct usb_string_descriptor *)wstr_serial;
string->bLength = sizeof(wstr_serial);
string->bDescriptorType = USB_DT_STRING;
str2wide(serial_number, string->wData);
rkusb_string_table[STR_SERIAL] = string;
string = (struct usb_string_descriptor *)wstr_configuration;
string->bLength = sizeof(wstr_configuration);
string->bDescriptorType = USB_DT_STRING;
str2wide(CONFIG_USBD_CONFIGURATION_STR, string->wData);
rkusb_string_table[STR_CONFIGURATION] = string;
string = (struct usb_string_descriptor *)wstr_interface;
string->bLength = sizeof(wstr_interface);
string->bDescriptorType = USB_DT_STRING;
str2wide(CONFIG_USBD_INTERFACE_STR, string->wData);
rkusb_string_table[STR_INTERFACE] = string;
/* 端点0的字符串描述最终保存在usb_strings */
usb_strings = rkusb_string_table;
}
/* fastboot_init has to be called before this fn to get correct serial string */
#ifdef CONFIG_RK_UDC
static void rkusb_init_instances(void)
{
int i;
/* initialize device instance */
memset((void *)device_instance, 0, sizeof(struct usb_device_instance));
device_instance->name = rockusb_name;
device_instance->device_state = STATE_INIT;
#if defined(CONFIG_RKCHIP_RK3126)
/* audi-b rockusb product id adjust */
if (grf_readl(GRF_CHIP_TAG) == 0x3136) {
device_descriptor.idProduct = cpu_to_le16(0x310D);
}
#endif
device_instance->device_descriptor = &device_descriptor;
device_instance->bos_descriptor = &rkusb_bos_desc;
device_instance->event = rkusb_event_handler;
device_instance->cdc_recv_setup = NULL;
device_instance->bus = bus_instance;
device_instance->configurations = NUM_CONFIGS;
device_instance->configuration_instance_array = config_instance;
/* XXX: what is this bus instance for ?, can't it be removed by moving
endpoint_array and serial_number_str is moved to device instance */
/* initialize bus instance */
memset(bus_instance, 0, sizeof(struct usb_bus_instance));
bus_instance->device = device_instance;
bus_instance->endpoint_array = endpoint_instance;
/* XXX: what is the relevance of max_endpoints & maxpacketsize ? */
bus_instance->max_endpoints = 1;
bus_instance->maxpacketsize = 64;
bus_instance->serial_number_str = serial_number;
/* configuration instance */
memset(config_instance, 0, sizeof(struct usb_configuration_instance));
config_instance->interfaces = NUM_INTERFACES;
config_instance->configuration_descriptor =
(struct usb_configuration_descriptor *)&rkusb_config_desc;
config_instance->interface_instance_array = interface_instance;
/* XXX: is alternate instance required in case of no alternate ? */
/* interface instance */
memset(interface_instance, 0, sizeof(struct usb_interface_instance));
interface_instance->alternates = 1;
interface_instance->alternates_instance_array = alternate_instance;
/* alternates instance */
memset(alternate_instance, 0, sizeof(struct usb_alternate_instance));
alternate_instance->interface_descriptor = interface_descriptors;
alternate_instance->endpoints = NUM_ENDPOINTS;
alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs;
/* endpoint instances */
memset(endpoint_instance, 0, sizeof(endpoint_instance));
endpoint_instance[0].endpoint_address = 0;
endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE;
endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL;
endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE;
endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL;
/* XXX: following statement to done along with other endpoints
at another place ? */
#ifdef CONFIG_CMD_FASTBOOT
usbcmd.rx_buffer[0] = (u8 *)gd->arch.fastboot_buf_addr;
usbcmd.rx_buffer[1] = usbcmd.rx_buffer[0]+(CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE_EACH>>1);
usbcmd.tx_buffer[0] = (u8 *)gd->arch.fastboot_buf_addr + CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE_EACH;
usbcmd.tx_buffer[1] = usbcmd.tx_buffer[0]+(CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE_EACH>>1);
#else
usbcmd.rx_buffer[0] = (u8 *)gd->arch.rk_boot_buf_addr;
usbcmd.rx_buffer[1] = usbcmd.rx_buffer[0]+(CONFIG_RK_BOOT_BUFFER_SIZE>>2);
usbcmd.tx_buffer[0] = (u8 *)gd->arch.rk_boot_buf_addr + (CONFIG_RK_BOOT_BUFFER_SIZE>>1);
usbcmd.tx_buffer[1] = usbcmd.tx_buffer[0]+(CONFIG_RK_BOOT_BUFFER_SIZE>>2);
#endif
RKUSBINFO("%p %p %p %p\n",
usbcmd.rx_buffer[0], usbcmd.rx_buffer[1], usbcmd.tx_buffer[0], usbcmd.tx_buffer[1]);
for (i = 1; i <= NUM_ENDPOINTS; i++) {
endpoint_instance[i].endpoint_address =
ep_descriptor_ptrs[i - 1]->bEndpointAddress;
endpoint_instance[i].rcv_attributes =
ep_descriptor_ptrs[i - 1]->bmAttributes;
endpoint_instance[i].rcv_packetSize =
le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
endpoint_instance[i].tx_attributes =
ep_descriptor_ptrs[i - 1]->bmAttributes;
endpoint_instance[i].tx_packetSize = 0x201;
endpoint_instance[i].tx_attributes =
ep_descriptor_ptrs[i - 1]->bmAttributes;
urb_link_init(&endpoint_instance[i].rcv);
urb_link_init(&endpoint_instance[i].rdy);
urb_link_init(&endpoint_instance[i].tx);
urb_link_init(&endpoint_instance[i].done);
RKUSBINFO("ENDPOINT %d,addr %x\n", i, endpoint_instance[i].endpoint_address);
if (endpoint_instance[i].endpoint_address & USB_DIR_IN) {
endpoint_instance[i].tx_urb =
usbd_alloc_urb(device_instance,
&endpoint_instance[i]);
endpoint_instance[i].tx_urb->buffer = usbcmd.tx_buffer[0];
endpoint_instance[i].tx_urb->status = SEND_FINISHED_OK;
} else {
endpoint_instance[i].rcv_urb =
usbd_alloc_urb(device_instance,
&endpoint_instance[i]);
endpoint_instance[i].rcv_urb->buffer = usbcmd.rx_buffer[0];
endpoint_instance[i].rcv_urb->status = RECV_OK;
}
}
}
/* XXX: ep_descriptor_ptrs can be removed by making better use of
RKUSB_config_desc.endpoint_desc */
static void rkusb_init_endpoint_ptrs(void)
{
ep_descriptor_ptrs[0] = &rkusb_config_desc.endpoint_desc[0];
ep_descriptor_ptrs[1] = &rkusb_config_desc.endpoint_desc[1];
}
static void rkusb_init_endpoints(void)
{
int i;
/* XXX: should it be moved to some other function ? */
bus_instance->max_endpoints = NUM_ENDPOINTS + 1;
/* XXX: is this for loop required ?, yes for MUSB it is */
for (i = 1; i <= NUM_ENDPOINTS; i++) {
/* configure packetsize based on HS negotiation status */
if (is_usbd_high_speed()) {
RKUSBINFO("setting up HS USB device ep%x\n", endpoint_instance[i].endpoint_address);
ep_descriptor_ptrs[i - 1]->wMaxPacketSize = 0x200;
} else {
RKUSBINFO("setting up FS USB device ep%x\n", endpoint_instance[i].endpoint_address);
ep_descriptor_ptrs[i - 1]->wMaxPacketSize = 0x40;
}
/* fastboot will send a zero packet if the last data packet is tx_packetSize, but rockusb don't */
endpoint_instance[i].tx_packetSize = 0x201;
endpoint_instance[i].rcv_packetSize = le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
}
}
#endif
/***************************************************************************
* 命令:测试准备0x00
***************************************************************************/
static void FW_TestUnitReady(void)
{
if (FW_StorageGetValid() == 0) {
uint32_t totleBlock = FW_GetTotleBlk();
uint32_t currEraseBlk = FW_GetCurEraseBlock();
usbcmd.csw.Residue = cpu_to_be32((totleBlock<<16)|currEraseBlk);
usbcmd.csw.Status = CSW_FAIL;
} else if (usbcmd.cbw.CDB[1] == 0xFD) {
uint32_t totleBlock = FW_GetTotleBlk();
uint32_t currEraseBlk = 0;
usbcmd.csw.Residue = cpu_to_be32((totleBlock<<16)|currEraseBlk);
usbcmd.csw.Status = CSW_FAIL;
FW_SorageLowFormatEn(1);
} else if (usbcmd.cbw.CDB[1] == 0xFA) {
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.reset_flag = 0x10;
} else if (usbcmd.cbw.CDB[1] == 0xF9) {
usbcmd.csw.Residue = cpu_to_be32(StorageGetCapacity());
usbcmd.csw.Status = CSW_GOOD;
} else if (SecureBootLock) {
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_FAIL;
} else {
usbcmd.csw.Residue = cpu_to_be32(6);
usbcmd.csw.Status = CSW_GOOD;
}
usbcmd.status = RKUSB_STATUS_CSW;
}
/***************************************************************************
函数描述:固件升级命令:读FLASH ID
入口参数:无
出口参数:无
调用函数:无
***************************************************************************/
static void FW_ReadID(void)
{
#ifdef CONFIG_RK_DWC3_UDC
RKUSBINFO("%s \n", __func__);
StorageReadId(usbcmd.tx_buffer[usbcmd.txbuf_num]);
usbcmd.transfer_size = 5;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_TXDATA;
#else
struct usb_endpoint_instance *ep = &endpoint_instance[2];
struct urb *current_urb = NULL;
RKUSBINFO("%s \n", __func__);
current_urb = ep->tx_urb;
if (!current_urb) {
RKUSBERR("%s: current_urb NULL", __func__);
return;
}
StorageReadId((void *)current_urb->buffer);
current_urb->actual_length = 5;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_TXDATA;
#endif
}
/***************************************************************************
函数描述:固件升级命令:设置FLASH 类型
Flash 1:
0:8bit small page; 1:8bit large page 4cyc; 2:8bit large page 5cyc
3:16bit small page; 4:16bit large page 4cyc; 5:16bit large page 5cyc
6:MLC 8bit large page 5cyc 7:MLC 8bit large page 5cyc, 4KB/page
入口参数:
出口参数:
调用函数:
1 2009-4-10 增加出错返回PC工具检测到擦除系统盘出错会擦除所有保留块
后面的块重启后loader会低格重新分配空间
***************************************************************************/
static void FW_LowFormatSysDisk(void)
{
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_CSW;
}
/***************************************************************************
函数描述:获取中间件版权信息
入口参数:无
出口参数:无
调用函数:无
***************************************************************************/
static void FW_GetChipVer(void)
{
#ifdef CONFIG_RK_DWC3_UDC
unsigned int chip_info[4];
RKUSBINFO("%s \n", __func__);
memset(chip_info, 0, sizeof(chip_info));
rk_get_bootrom_chip_version(chip_info);
#if defined(CONFIG_RKCHIP_RK3399)
chip_info[0] = 0x33333043;
#elif defined(CONFIG_RKCHIP_RK3366)
chip_info[0] = 0x33333042;
#endif
memcpy((uint8_t *)usbcmd.tx_buffer[usbcmd.txbuf_num], (uint8_t *)chip_info, 16);
usbcmd.transfer_size = 16;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_TXDATA;
#else
struct usb_endpoint_instance *ep = &endpoint_instance[2];
struct urb *current_urb = NULL;
unsigned int chip_info[4];
RKUSBINFO("%s \n", __func__);
current_urb = ep->tx_urb;
if (!current_urb) {
RKUSBERR("%s: current_urb NULL", __func__);
return;
}
/* notice here chip version should the same as rk tools *.ini config of RKBOOT */
current_urb->buffer[0] = 0;
memset(chip_info, 0, sizeof(chip_info));
rk_get_bootrom_chip_version(chip_info);
#if defined(CONFIG_RKCHIP_RK3036)
chip_info[0] = 0x33303341;
#elif defined(CONFIG_RKCHIP_RK3126) || defined(CONFIG_RKCHIP_RK3128)
chip_info[0] = 0x33313241;
#elif defined(CONFIG_RKCHIP_RK322X)
chip_info[0] = 0x33323241;
#elif defined(CONFIG_RKCHIP_RK3366)
chip_info[0] = 0x33333042;
#endif
memcpy((void *)current_urb->buffer, (void *)chip_info, 16);
current_urb->actual_length = 16;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_TXDATA;
#endif
}
/***************************************************************************
函数描述:测试坏块——0:好块; 1:坏块
入口参数:命令块中的指定物理块地址
出口参数:无
调用函数:无
***************************************************************************/
static void FW_TestBadBlock(void)
{
#ifdef CONFIG_RK_DWC3_UDC
RKUSBINFO("%s \n", __func__);
memset((uint8_t *)usbcmd.tx_buffer[usbcmd.txbuf_num], 0, 64);
usbcmd.transfer_size = 64;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_TXDATA;
#else
uint16_t i;
uint32_t TestResult[16];
struct usb_endpoint_instance *ep = &endpoint_instance[2];
struct urb *current_urb = NULL;
RKUSBINFO("%s \n", __func__);
current_urb = ep->tx_urb;
for (i = 0; i < 16; i++)
TestResult[i] = 0;
memcpy((void *)current_urb->buffer, (void *)TestResult, 64);
current_urb->actual_length = 64;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_TXDATA;
#endif
}
/***************************************************************************
函数描述:按528 PAGE大小读
入口参数:命令块中的物理行地址及传输扇区数
出口参数:无
调用函数:无
***************************************************************************/
static void FW_Read10(void)
{
usbcmd.u_size = get_unaligned_be16(&usbcmd.cbw.CDB[NSECTORS_IN_CDB_INDEX]) * 528;
usbcmd.u_bytes = 0;
usbcmd.lba = get_unaligned_be32(&usbcmd.cbw.CDB[OFFSET_IN_CDB_INDEX]);
usbcmd.status = RKUSB_STATUS_TXDATA_PREPARE;
}
static void FW_Write10(void)
{
uint32_t rxdata_blocks = 0;
/* 从usb通行命令中取出得到的数据传输大小信息 */
usbcmd.d_size = get_unaligned_be16(&usbcmd.cbw.CDB[NSECTORS_IN_CDB_INDEX]) * 528;
usbcmd.d_bytes = 0;
usbcmd.lba = get_unaligned_be32(&usbcmd.cbw.CDB[OFFSET_IN_CDB_INDEX]);
RKUSBINFO("WRITE10 %x len %x\n", usbcmd.lba, usbcmd.d_size);
/* check current lba buffer not include in pre lba buffer */
rxdata_blocks = usbcmd.d_size/528;
if (!(((usbcmd.lba + rxdata_blocks) < usbcmd.pre_read.pre_lba)
|| (usbcmd.lba > (usbcmd.pre_read.pre_lba + usbcmd.pre_read.pre_blocks)))) {
RKUSBINFO("FW_Write10: invalid pre read\n");
usbcmd.pre_read.pre_blocks = 0;
usbcmd.pre_read.pre_lba = 0;
}
usbcmd.rx_giveback.actual = 0;
usbcmd.status = RKUSB_STATUS_RXDATA_PREPARE;
}
/***************************************************************************
函数描述:按物理BLOCK擦除——0:好块; 1:坏块
入口参数:命令块中的物理块地址
出口参数:无
调用函数:无
***************************************************************************/
static void FW_Erase10(void)
{
#ifdef CONFIG_RK_DWC3_UDC
RKUSBINFO("%s \n", __func__);
int status = 0;
if (SecureBootLock == 0) {
status = StorageEraseBlock(get_unaligned_be32(&usbcmd.cbw.CDB[OFFSET_IN_CDB_INDEX]), get_unaligned_be16(&usbcmd.cbw.CDB[NSECTORS_IN_CDB_INDEX]), 0);
}
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = (status == 0) ? 0 : 1;
usbcmd.status = RKUSB_STATUS_CSW;
#else
bool status = 0;
struct usb_endpoint_instance *ep = &endpoint_instance[2];
struct urb *current_urb = NULL;
RKUSBINFO("%s \n", __func__);
current_urb = ep->tx_urb;
if (SecureBootLock == 0) {
StorageEraseBlock(get_unaligned_be32(&usbcmd.cbw.CDB[OFFSET_IN_CDB_INDEX]), get_unaligned_be16(&usbcmd.cbw.CDB[NSECTORS_IN_CDB_INDEX]), 0);
}
current_urb->actual_length = 13;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = status;
usbcmd.status = RKUSB_STATUS_CSW;
#endif
}
/***************************************************************************
函数描述:按物理BLOCK擦除——0:好块; 1:坏块
入口参数:命令块中的物理块地址
出口参数:无
调用函数:无
***************************************************************************/
static void FW_Erase10Force(void)
{
int status = 0;
if (SecureBootLock == 0) {
status = StorageEraseBlock(get_unaligned_be32(&usbcmd.cbw.CDB[OFFSET_IN_CDB_INDEX]), get_unaligned_be16(&usbcmd.cbw.CDB[NSECTORS_IN_CDB_INDEX]), 1);
}
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = (status == 0) ? 0 : 1;
usbcmd.status = RKUSB_STATUS_CSW;
}
static void FW_LBARead10(void)
{
usbcmd.u_size = get_unaligned_be16(&usbcmd.cbw.CDB[NSECTORS_IN_CDB_INDEX]) * 512;
usbcmd.u_bytes = 0;
usbcmd.lba = get_unaligned_be32(&usbcmd.cbw.CDB[2]);
usbcmd.status = RKUSB_STATUS_TXDATA_PREPARE;
RKUSBINFO("LBA_READ %x len %x\n", usbcmd.lba, usbcmd.u_size);
}
static void FW_LBAWrite10(void)
{
uint32_t rxdata_blocks = 0;
usbcmd.d_size = get_unaligned_be16(&usbcmd.cbw.CDB[NSECTORS_IN_CDB_INDEX]) * 512;
usbcmd.d_bytes = 0;
usbcmd.lba = get_unaligned_be32(&usbcmd.cbw.CDB[OFFSET_IN_CDB_INDEX]);
usbcmd.imgwr_mode = usbcmd.cbw.CDB[1];
RKUSBINFO("LBA_WRITE %x len %x\n", usbcmd.lba, usbcmd.d_size);
/* check current lba buffer not include in pre lba buffer */
rxdata_blocks = usbcmd.d_size/512;
if (!(((usbcmd.lba + rxdata_blocks) < usbcmd.pre_read.pre_lba)
|| (usbcmd.lba > (usbcmd.pre_read.pre_lba + usbcmd.pre_read.pre_blocks)))) {
RKUSBINFO("FW_LBAWrite10: invalid pre read\n");
usbcmd.pre_read.pre_blocks = 0;
usbcmd.pre_read.pre_lba = 0;
}
usbcmd.rx_giveback.actual = 0;
usbcmd.status = RKUSB_STATUS_RXDATA_PREPARE;
}
static void FW_GetFlashInfo(void)
{
StorageReadFlashInfo(usbcmd.tx_buffer[usbcmd.txbuf_num]);
usbcmd.transfer_size = 11;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_TXDATA;
}
/***************************************************************************
函数描述:按物理BLOCK擦除——0:好块; 1:坏块
入口参数:命令块中的物理块地址
出口参数:无
调用函数:无
***************************************************************************/
static void FW_LowFormat(void)
{
RKUSBINFO("%s \n", __func__);
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_CSW;
FW_SorageLowFormatEn(1);
}
static void FW_SetResetFlag(void)
{
RKUSBINFO("%s \n", __func__);
usbcmd.reset_flag = 1;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_CSW;
}
/***************************************************************************
函数描述:系统复位
入口参数:无
出口参数:无
调用函数:无
LOG:
20100209,HSL@RK,ADD LUN for deffirent reboot.
0: normal reboot, 1: loader reboot.
***************************************************************************/
static void FW_Reset(void)
{
RKUSBINFO("%x \n", usbcmd.cbw.CDB[1]);
if (usbcmd.cbw.CDB[1])
usbcmd.reset_flag = usbcmd.cbw.CDB[1];
else
usbcmd.reset_flag = 0xff;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_CSW;
}
static int rkusb_send_csw(void)
{
struct bulk_cs_wrap *csw = &usbcmd.csw;
RKUSBINFO("%s tag %x\n", __func__, usbcmd.cbw.Tag);
if (usbcmd.tx_giveback.status != SEND_FINISHED_OK)
return -EBUSY;
csw->Signature = cpu_to_le32(USB_BULK_CS_SIG);
csw->Tag = usbcmd.cbw.Tag;
memcpy(usbcmd.tx_buffer[usbcmd.txbuf_num], (u8 *)&usbcmd.csw, 13);
rkusb_write_bulk_ep(13, usbcmd.tx_buffer[usbcmd.txbuf_num]);
usbcmd.txbuf_num = (usbcmd.txbuf_num + 1) % 2;
rkusb_read_bulk_ep(31, usbcmd.rx_buffer[usbcmd.rxbuf_num]);
usbcmd.rxbuf_num = (usbcmd.rxbuf_num + 1) % 2;
usbcmd.status = RKUSB_STATUS_IDLE;
return 0;
}
void do_rockusb_cmd(void)
{
/* 当usb设备从总线上拿到数据后保存在rx_giveback.buf里 */
memcpy(&usbcmd.cbw, usbcmd.rx_giveback.buf, sizeof(usbcmd.cbw));
/* 获取到cdb */
usbcmd.cmnd = usbcmd.cbw.CDB[0];
//printf("CBW Tag: %x Flags: %x Length : %x CDB[0] : %x\n", usbcmd.cbw.Tag, usbcmd.cbw.Flags, usbcmd.cbw.Length, usbcmd.cmnd);
switch (usbcmd.cmnd) {
case K_FW_TEST_UNIT_READY:
FW_TestUnitReady();
break;
case K_FW_READ_FLASH_ID:
FW_ReadID();
break;
case K_FW_TEST_BAD_BLOCK:
FW_TestBadBlock();
break;
case K_FW_READ_10:
FW_Read10();
break;
case K_FW_WRITE_10:
FW_Write10();
break;
case K_FW_ERASE_10:
FW_Erase10();
break;
case K_FW_ERASE_10_FORCE:
FW_Erase10Force();
break;
case K_FW_LBA_READ_10:
FW_LBARead10();
break;
case K_FW_LBA_WRITE_10:
FW_LBAWrite10();
break;
case K_FW_ERASE_SYS_DISK:
FW_LowFormatSysDisk();
break;
case K_FW_READ_FLASH_INFO:
FW_GetFlashInfo();
break;
case K_FW_GET_CHIP_VER:
FW_GetChipVer();
break;
case K_FW_LOW_FORMAT:
FW_LowFormat();
break;
case K_FW_SET_RESET_FLAG:
FW_SetResetFlag();
break;
case K_FW_RESET:
FW_Reset();
break;
default:
printf("Unknow command\n");
break;
}
}
void rkusb_handle_datarx(void)
{
uint8_t *rxdata_buf = NULL;
uint32_t rxdata_blocks = 0;
uint32_t transfer_length;
uint32_t rx_blocks = 0;
uint32_t block_length ;
int iRet;
/* 每次传输的大小 */
if (usbcmd.cmnd == K_FW_WRITE_10)
block_length = 528;
else if (usbcmd.cmnd == K_FW_LBA_WRITE_10)
block_length = 512;
else
block_length = 512;
/* 实际收到数据的长度 */
if (usbcmd.rx_giveback.actual)
{
usbcmd.d_bytes += usbcmd.rx_giveback.actual;
rxdata_buf = (uint8_t *)usbcmd.rx_giveback.buf;
rxdata_blocks = usbcmd.rx_giveback.actual / block_length;
}
/* 实际收到数据长度比理论值小,说明还有数据没传输过来,继续读取数据 */
if (usbcmd.d_bytes < usbcmd.d_size)
{
/* 还需要传输的数据长度 */
transfer_length = usbcmd.d_size - usbcmd.d_bytes;
rx_blocks = transfer_length / block_length;
if (rx_blocks > RKUSB_BUFFER_BLOCK_MAX)
rx_blocks = RKUSB_BUFFER_BLOCK_MAX;
transfer_length = rx_blocks * block_length;
/* 再次读取剩余的数据 */
rkusb_read_bulk_ep(transfer_length, usbcmd.rx_buffer[usbcmd.rxbuf_num]);
usbcmd.rxbuf_num = (usbcmd.rxbuf_num + 1) % 2;
usbcmd.status = RKUSB_STATUS_RXDATA;
}
else
{
/* 数据传输完毕,发送csw给主机 */
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
rkusb_send_csw();
}
/* 将接收到的数据按块写入存储介质中 */
if (rxdata_blocks)
{
RKUSBINFO("write to media %x, lba %x, buf %p\n", rxdata_blocks, usbcmd.lba, rxdata_buf);
if (usbcmd.cmnd == K_FW_WRITE_10)
{
ISetLoaderFlag(SYS_LOADER_ERR_FLAG);
if (SecureBootLock == 0)
{
iRet = StorageWritePba(usbcmd.lba, rxdata_buf, rxdata_blocks);
usbcmd.lba += rxdata_blocks;
if (iRet != FTL_OK)
RKUSBERR("StorageWritePba failed,err=%d\n", iRet);
}
}
else if (usbcmd.cmnd == K_FW_LBA_WRITE_10)
{
if (usbcmd.lba >= 0xFFFFFF00)
{
StorageVendorSysDataStore(usbcmd.lba - 0xFFFFFF00, rxdata_blocks, (uint32 *)rxdata_buf);
usbcmd.lba += rxdata_blocks;
}
else if (usbcmd.lba == 0xFFFFF000)
{
SecureBootUnlock(rxdata_buf);
}
else if ((usbcmd.lba & 0xFFFF0000) == 0xFFF00000)
{
iRet = vendor_storage_write(*(uint16 *)rxdata_buf, rxdata_buf+8, *(uint16 *)(rxdata_buf+4));
if (iRet == -1) {
RKUSBERR("vendor_storage_write failed,err=%d\n", iRet);
}
usbcmd.lba += rxdata_blocks;
}
else if (SecureBootLock == 0)
{
iRet = StorageWriteLba(usbcmd.lba, rxdata_buf, rxdata_blocks, usbcmd.imgwr_mode);
if (iRet != FTL_OK)
RKUSBERR("StorageWriteLba failed,err=%d\n", iRet);
usbcmd.lba += rxdata_blocks;
}
}
}
}
void rkusb_handle_datatx(void)
{
uint32_t txdata_size = 0;
uint32_t tx_blocks = 0;
uint32_t block_length = 0;
uint32_t pre_blocks = 0;
int iRet;
start:
pre_blocks = 0;
txdata_size = usbcmd.u_size - usbcmd.u_bytes;
if (usbcmd.cmnd == K_FW_READ_10)
block_length = 528;
else if (usbcmd.cmnd == K_FW_LBA_READ_10)
block_length = 512;
tx_blocks = txdata_size / block_length;
if (tx_blocks >= RKUSB_BUFFER_BLOCK_MAX) {
tx_blocks = RKUSB_BUFFER_BLOCK_MAX;
txdata_size = tx_blocks * block_length;
}
if (tx_blocks
&& (usbcmd.pre_read.pre_blocks >= tx_blocks)
&& (usbcmd.pre_read.pre_lba == usbcmd.lba)) {
usbcmd.u_bytes += txdata_size;
usbcmd.lba += tx_blocks;
usbcmd.pre_read.pre_blocks -= tx_blocks;
RKUSBINFO("rkusb_write_bulk_ep buffer %p, len %x\n", usbcmd.tx_buffer[usbcmd.txbuf_num], txdata_size);
rkusb_write_bulk_ep(txdata_size, usbcmd.tx_buffer[usbcmd.txbuf_num]);
usbcmd.txbuf_num = (usbcmd.txbuf_num + 1) % 2;
}
if (usbcmd.u_size == usbcmd.u_bytes) {
pre_blocks = 0;
/* clear pre_read data */
usbcmd.pre_read.pre_lba = 0;
usbcmd.pre_read.pre_blocks = 0;
} else if ((usbcmd.u_bytes == 0) || (tx_blocks == RKUSB_BUFFER_BLOCK_MAX)) {
RKUSBINFO("read u_bytes %x, tx_blocks %x\n", usbcmd.u_bytes, tx_blocks);
pre_blocks = tx_blocks;
usbcmd.pre_read.pre_buffer = usbcmd.tx_buffer[usbcmd.txbuf_num];
usbcmd.pre_read.pre_lba = usbcmd.lba;
usbcmd.pre_read.pre_blocks = tx_blocks;
}
/* read data from media */
if (pre_blocks) {
RKUSBINFO("read lba %x, buffer %p block %x\n", usbcmd.pre_read.pre_lba, usbcmd.pre_read.pre_buffer, pre_blocks);
memset(usbcmd.pre_read.pre_buffer, 0, pre_blocks * block_length);
if (usbcmd.cmnd == K_FW_READ_10) {
iRet = StorageReadPba(usbcmd.pre_read.pre_lba, usbcmd.pre_read.pre_buffer, pre_blocks);
if (iRet != FTL_OK) {
RKUSBERR("StorageReadPba failed,err=%d\n", iRet);
}
} else if (usbcmd.cmnd == K_FW_LBA_READ_10) {
if (usbcmd.lba >= 0xFFFFFF00)
StorageVendorSysDataLoad(usbcmd.pre_read.pre_lba - 0xFFFFFF00, pre_blocks, (uint32 *)usbcmd.pre_read.pre_buffer);
else if (usbcmd.lba == 0xFFFFF000)
SecureBootUnlockCheck(usbcmd.pre_read.pre_buffer);
else if ((usbcmd.lba & 0xFFFF0000) == 0xFFF00000) {
uint16_t req_id = (usbcmd.lba & 0xFFFF);
uint8 *p_buf = usbcmd.pre_read.pre_buffer;
iRet = vendor_storage_read(req_id, p_buf + 8, usbcmd.u_size - 8);
if (iRet == -1) {
RKUSBERR("vendor_storage_read failed,err=%d\n", iRet);
} else {
p_buf[0] = (uint32_t)(req_id & 0xFF);
p_buf[1] = (uint32_t)((req_id >> 8) & 0xFF);
p_buf[4] = (uint32_t)(iRet & 0xFF);
p_buf[5] = (uint32_t)((iRet >> 8) & 0xFF);
}
} else {
iRet = StorageReadLba(usbcmd.pre_read.pre_lba, usbcmd.pre_read.pre_buffer, pre_blocks);
if (iRet != FTL_OK) {
RKUSBERR("StorageReadLba failed,err=%d\n", iRet);
}
}
}
}
if (usbcmd.u_bytes == 0)
goto start;
if (usbcmd.u_size == usbcmd.u_bytes) {
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_CSW;
}
}
static void rkusb_handle_response(void)
{
#ifdef CONFIG_RK_DWC3_UDC
switch (usbcmd.status) {
case RKUSB_STATUS_TXDATA:
RKUSBINFO("rkusb_write_bulk_ep %x\n", usbcmd.transfer_size);
rkusb_write_bulk_ep(usbcmd.transfer_size, usbcmd.tx_buffer[usbcmd.txbuf_num]);
usbcmd.txbuf_num = (usbcmd.txbuf_num + 1) % 2;
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_CSW;
break;
case RKUSB_STATUS_RXDATA:
if (usbcmd.rx_giveback.status == RECV_OK)
rkusb_handle_datarx();
break;
case RKUSB_STATUS_RXDATA_PREPARE:
rkusb_handle_datarx();
break;
case RKUSB_STATUS_TXDATA_PREPARE:
if ((usbcmd.u_bytes == 0) || (usbcmd.tx_giveback.status == SEND_FINISHED_OK))
rkusb_handle_datatx();
break;
default:
break;
}
#else
struct usb_endpoint_instance *ep;
struct urb *current_urb = NULL;
uint32_t actural_length;
switch (usbcmd.status) {
case RKUSB_STATUS_TXDATA:
ep = &endpoint_instance[2];
current_urb = ep->tx_urb;
udc_endpoint_write(ep);
usbcmd.data_size = 0;
RKUSBINFO("udc_endpoint_write %x\n", current_urb->actual_length);
if (usbcmd.data_size == 0) {
usbcmd.csw.Residue = cpu_to_be32(usbcmd.cbw.DataTransferLength);
usbcmd.csw.Status = CSW_GOOD;
usbcmd.status = RKUSB_STATUS_CSW;
}
break;
case RKUSB_STATUS_RXDATA:
ep = &endpoint_instance[1];
current_urb = ep->rcv_urb;
actural_length = current_urb->actual_length;
if (actural_length)
rkusb_handle_datarx();
break;
case RKUSB_STATUS_RXDATA_PREPARE:
rkusb_handle_datarx();
break;
case RKUSB_STATUS_TXDATA_PREPARE:
ep = &endpoint_instance[2];
current_urb = ep->tx_urb;
if ((usbcmd.u_bytes == 0) || (current_urb->status == SEND_FINISHED_OK))
rkusb_handle_datatx();
break;
default:
break;
}
#endif
}
static int rkusb_timeout_check(int flag)
{
#ifdef CONFIG_RK_DWC3_UDC
if (flag) {
if (GetVbus()) {
if (!usbcmd.configured) {
if (get_timer(TimeOutBase) > (10*1000)) {
printf("Usb Timeout, Return for boot recovery!\n");
return 1;
}
}
} else {
TimeOutBase = get_ticks();
}
}
return 0;
#else
/* TV Box: usb default as host, so Vbus always is high,
* if recovery key pressed and not connect to pc,
* 10s timeout enter recovery.
*/
if (flag) {
if (GetVbus()) {
if (!UsbConnectStatus()) {
if (get_timer(TimeOutBase) > (10*1000)) {
printf("Usb Timeout, Return for boot recovery!\n");
return 1;
}
}
} else {
TimeOutBase = get_ticks();
}
}
return 0;
#endif
}
static void rkusb_reset_check(void)
{
if (usbcmd.reset_flag == 0x03) {
/* reboot to maskrom */
usbcmd.reset_flag = 0;
ISetLoaderFlag(0xEF08A53C);
mdelay(10);
reset_cpu(0);
} else if (usbcmd.reset_flag == 0x10) {
/* lock loader */
usbcmd.reset_flag = 0;
SecureBootLockLoader();
} else if (usbcmd.reset_flag == 0xFF) {
/* reboot */
usbcmd.reset_flag = 0;
mdelay(10);
reset_cpu(0);
} else if (usbcmd.reset_flag == 0x01) {
/* force to reboot to system, no check loader mode */
usbcmd.reset_flag = 0;
ISetLoaderFlag(SYS_LOADER_REBOOT_FLAG | BOOT_NORECOVER);
mdelay(10);
reset_cpu(0);
}
}
static void rkusb_lowformat_check(void)
{
FW_SorageLowFormat();
}
int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
/* usb实例,表示一个usb设备 */
struct rk_dwc3_udc_instance instance;
int ret;
RKUSBINFO("<<Dwc3>> do_rockusb come in.\n");
memset(&usbcmd, 0, sizeof(struct cmd_rockusb_interface));
/* 初始化usb实例 */
init_dwc3_udc_instance(&instance);
/* 将usb实例关联到global_rk_instance */
rk_dwc3_startup(&instance);
/* 打开usb连接 */
ret = rk_dwc3_connect();
if (ret) {
RKUSBINFO("<<Dwc3>> rk_dwc3_connect failed.\n");
goto Exit_DoRockusb;
}
#ifdef CONFIG_ROCKUSB_TIMEOUT_CHECK
TimeOutBase = get_ticks();
#endif
while (1)
{
/* 在通信过程中有中断则处理中断 */
dwc3_uboot_handle_interrupt();
/* usb总线没有数据传输的时候就是idle状态 */
if (usbcmd.status == RKUSB_STATUS_IDLE)
{
/* 当总线上有接收到数据时
* 按照通信双方约定
* 先传输命令,根据命令执行相应操作
* 所以这里解析命令
*
* 当收到对端数据后dwc3_rx_handler进行数据接收
*/
if (usbcmd.rx_giveback.actual > 0)
{
usbcmd.status = RKUSB_STATUS_CMD;
do_rockusb_cmd();
}
}
if (usbcmd.status == RKUSB_STATUS_RXDATA ||
usbcmd.status == RKUSB_STATUS_TXDATA ||
usbcmd.status == RKUSB_STATUS_RXDATA_PREPARE ||
usbcmd.status == RKUSB_STATUS_TXDATA_PREPARE)
{
rkusb_handle_response();
}
if (usbcmd.status == RKUSB_STATUS_CSW)
{
rkusb_send_csw();
}
rkusb_reset_check();
rkusb_lowformat_check();
#ifdef CONFIG_ROCKUSB_TIMEOUT_CHECK
/* if press key enter rockusb, flag = 1 */
if (rkusb_timeout_check(flag) == 1) {
/* if timeout, return 1 for enter recovery */
goto Exit_DoRockusb;
}
#endif
}
Exit_DoRockusb:
rk_dwc3_disconnect();
return 1;
}
U_BOOT_CMD(rockusb, CONFIG_SYS_MAXARGS, 1, do_rockusb,
"Use the UMS [User Mass Storage]",
"ums <USB_controller> <mmc_dev> e.g. ums 0 0"
);