C++程序  |  389行  |  12.02 KB

 /*
  * Copyright (C) 2009/2010 Motorola Inc.
  * All Rights Reserved.
  * Motorola Confidential Restricted.
  */


#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <termios.h>

#include "common.h"
#include "masterclear_bp.h"


/* @ set usb in unsuspend mode */
int set_usb_unsuspend()
{
        int ret;
        int count = sizeof(setup_cmd)-1;

        FILE *fp = fopen(USB1_SETUP_FILE, "w");
        if (fp == NULL) {
            LOGE("Can't open %s\n", USB1_SETUP_FILE);
            fclose(fp);
            return 1;
        }
        else {
            if ((ret = fwrite(setup_cmd,1,count,fp))<count)
            {
              LOGE("Write %s failed.\n",USB1_SETUP_FILE);
              fclose(fp);
              return 1;
            }
        }
        fclose(fp);
        return 0;
}

/* @dump the  buff data to debug */
void CMD_DBG_data_dump(void* databuff, int len)
{
#ifdef TC_DEBUG
    int max_col = CMD_DBG_MAX_DUMP_COLS;
    int row = 0;
    int col = 0;
    int num_col;
    int buffer_index = 0;
    UINT8 value;

    char string_buffer[(TC_DBG_MAX_DUMP_COLS * 3) + 1];  /* Each column takes up 3 characters, plus NULL */
    for (row = 0; row <= (len / max_col); row++)
    {
        /* Reset string buffer for each new row */
        memset(string_buffer, 0, sizeof(string_buffer));

        /* For all rows, the number of columns is the max number, except for the last row */
        num_col = (row == (len / max_col)) ? (len % max_col) : max_col;
        if (num_col != 0)
        {
            for (col = 0; col < num_col; col++)
            {
                value = ((UINT8*)databuff)[buffer_index++];
                LOGE("%s%02x ", string_buffer, value);
            }
            LOGE("%s", string_buffer);
        }
    }

#endif
}

/*=============================================================================================*//**
@brief Initializes the communcation interface with the bp command engine

@return Status of initialization

@note
 - If no command engine is present, CMD_ENGINE_INIT_NOT_PRESENT must be returned
*//*==============================================================================================*/
CMD_ENGINE_INIT_T CMD_ENGINE_init(void)
{
    UINT8 try_count = 1;
    CMD_ENGINE_INIT_T status = CMD_ENGINE_INIT_FAIL;
    cmd_engine_fd = -1;
    /* Keep trying to connect to the command engine until we are successful, or we hit the retry max */
    usleep(4000000);
    while (cmd_engine_fd < 0)
    {
    LOGE("open dev\n");
        if ( (cmd_engine_fd = open (CMD_ENGINE_DEVICE, O_RDWR)) < 0 )
        {
            if (try_count == CMD_ENGINE_CONNECT_MAX_TRY)
            {
                LOGE("Reached max number of retries, giving up...\n");
                break;
            }
            else
            {
                /* Try to connect again, wait a bit before retry */
                try_count++;
                usleep(CMD_ENGINE_CONNECT_TRY_DELAY);
            }
        }
        else
        {
            struct termios tio;
            tcgetattr( cmd_engine_fd, &tio );

            /* Modify local options */
            tio.c_lflag &= ~( ECHO | ECHOE | ECHOK | ECHONL ); // None ECHO mode
            tio.c_lflag &= ~( ICANON | ISIG );    // raw data

            /* Modify input options */
            tio.c_iflag = IGNBRK | IGNPAR; //work code

            /* Modify output options */
            tio.c_oflag &= ~( OPOST );     // work code

            /* Modify control options */
            tio.c_cflag |= ( CLOCAL | CREAD | CRTSCTS );   //enable receiver & hardware flow control
            tio.c_cflag &= ~( CSIZE );     //disable bit mask for data bits
            tio.c_cflag |= CS8;            //set 8-bit characters
            tio.c_cflag &= ~( PARENB );    //disable parity bit*/

            /* Modify the Baud Rate */
            cfsetispeed( &tio, B115200 );
            cfsetospeed( &tio, B115200 );

            /* Clear the line and prepare to activate the new settings */
            tcflush( cmd_engine_fd, TCIFLUSH );

            /* Set the options */
            tcsetattr( cmd_engine_fd, TCSANOW, &tio );

            status = CMD_ENGINE_INIT_SUCCESS;
        }
    }
    return(status);
}

/*=========================================================================*//*
 brief read command response from bp
@param[in]  bytes_to_write - The number of bytes to read
@param[out] data           - Data to read

@return TRUE = success, FALSE = failure
*//*=================================================================================*/

BOOL CMD_ENGINE_read(UINT32 bytes_to_read, UINT8 *data)
{
    BOOL   is_success = FALSE;
    UINT32 total_bytes_read = 0;
    UINT32 bytes_read = 0;

    /* Return error if the aux engine handle is not init'd */
    if (cmd_engine_fd == CMD_ENGINE_FD_NOT_INIT)
    {
        LOGE(" engine device is not open!\n");
    }
    else
    {
        while( total_bytes_read != bytes_to_read )
        {
            bytes_read = read(cmd_engine_fd, &data[total_bytes_read], bytes_to_read - total_bytes_read);
            LOGE("Attempted to read %d bytes and read %d bytes.\n", bytes_to_read - total_bytes_read, bytes_read);

            if( bytes_read <= 0 )
            {
                LOGE("Failed to read  engine device.\n");
                break;
            }
            total_bytes_read += bytes_read;
        }
        if( total_bytes_read == bytes_to_read )
        {
            LOGE("Successfully read %d bytes.\n", total_bytes_read);
            is_success = TRUE;
        }
    }

    return (is_success);
}

/*=============================================================================================*//**
@brief Writes the specified number of bytes to the command engine

@param[in]  bytes_to_write - The number of bytes to write
@param[out] data           - Data to write

@return TRUE = success, FALSE = failure

@note
 - The write is synchronous, the function will block until the requested number of bytes are written
*//*==============================================================================================*/
BOOL CMD_ENGINE_write(UINT32 bytes_to_write, UINT8 *data)
{
    BOOL   is_success  = FALSE;
    UINT32 bytes_wrote = 0;

    /* Return error if the aux engine handle is not init'd */
    if (cmd_engine_fd == CMD_ENGINE_FD_NOT_INIT)
    {
        LOGE("engine device is not open!\n");
    }
    else
    {
        bytes_wrote = write(cmd_engine_fd, data, bytes_to_write);
        if (bytes_wrote != bytes_to_write)
        {
            LOGE("Failed to write to engine device, attempted to write %d bytes, but wrote %d.\n",bytes_to_write, bytes_wrote);
        }
        else
        {
            LOGE("Successfully wrote %d bytes.\n", bytes_wrote);
            is_success = TRUE;
        }
    }

    return (is_success);
}



/*=============================================================================================*//**
@brief Convert network byte order to host byte order for command request headers

@param[in]  hdr_in  - Network byte order command request header
@param[out] hdr_out - Host byte order command request header
*//*==============================================================================================*/
void CMD_ENGINE_UTIL_hdr_req_ntoh(CMD_DEFS_CMD_REQ_HDR_T* hdr_in,CMD_DEFS_CMD_REQ_HDR_T* hdr_out)
{
    memcpy(hdr_out, hdr_in, sizeof(CMD_DEFS_CMD_REQ_HDR_T));
    hdr_out->opcode = ((hdr_in->opcode & 0x00FF) << 8) | ((hdr_in->opcode & 0xFF00) >> 8);
    hdr_out->length = ((hdr_in->length & 0x000000FF) << 24) |
        ((hdr_in->length & 0x0000FF00) << 8) |
        ((hdr_in->length & 0x00FF0000) >> 8) |
        ((hdr_in->length & 0xFF000000) >> 24);

}

/*================================================================*//**
@ brief change bp from flash mode to normal mode
*//*=================================================================*/
int bp_flashmode_to_normalmode(void)
{
    int fd;
    ssize_t result;
    fd = open(MDM_CTRL_DEVICE, O_WRONLY);
    if (fd < 0)
    {
      LOGE("failed open mdm_ctrl\n");
      return fd;
    }
    LOGE("open mdm_ctrl ok\n");

    //shutdown BP
    // echo shutdown > /sys/class/radio/mdm6600/command
    result = write(fd, MDM_CMD_SHUTDONW, sizeof(MDM_CMD_SHUTDONW)-1);
    if (result < (ssize_t)(sizeof(MDM_CMD_SHUTDONW)-1))
    {
        LOGE("Failed to shutdown BP\n");
        return -1;
    }
    usleep(1000000);

    //set BP power up mode
    // echo bootmode_normal > /sys/class/radio/mdm6600/command
    result = write(fd, MDM_CMD_NORMAL_MODE, sizeof(MDM_CMD_NORMAL_MODE)-1);
    if (result < (ssize_t)(sizeof(MDM_CMD_NORMAL_MODE)-1))
    {
        LOGE("Failed to set BP boot mode\n");
        return -1;
    }

    //power up BP
    // echo powerup > /sys/class/radio/mdm6600/command
    result = write(fd, MDM_CMD_POWERUP, sizeof(MDM_CMD_POWERUP)-1);
    if (result < (ssize_t)(sizeof(MDM_CMD_POWERUP)-1))
    {
        LOGE("Failed to powerup BP\n");
        return -1;
    }
    usleep(2000000);
    close(fd);

    LOGE("Finished boot BP to normal mode\n");
    return 0;
}

/*=============================================================================================*//**
@brief BP master clear

*//*==============================================================================================*/

int bp_master_clear(void)
{
    UINT8                  bp_ver_len;
    const UINT8            *bp_rsp_data_ptr;
    int                    write_len  = 0;
    int                    read_len = 0;
    UINT8                  *write_buff = NULL;
    UINT8                  *read_buff = NULL;

    CMD_ENGINE_INIT_T  aux_status;
    CMD_DEFS_CMD_REQ_HDR_T cmd_header = {0};
    CMD_DEFS_CMD_RSP_HDR_T  c_rsp_hdr;

    write_len = sizeof(CMD_DEFS_CMD_REQ_HDR_T);
    /* Build up the CMD request */
    cmd_header.cmd_rsp_flag     = CMD_DEFS_HDR_FLAG_CMD_RSP_COMMAND;
    cmd_header.opcode           = CMD_CMN_DRV_BP_MASTERCLEAR_OPCODE;
    cmd_header.no_rsp_reqd_flag = CMD_DEFS_HDR_FLAG_RESPONSE_EXPECTED;
    cmd_header.length           = CMD_BP_MASTER_RESET_DATALENTH;

    /* cancel the usb suspend mode so that usb devices can be detected when bp power up */
    if(set_usb_unsuspend()!=0)
    {
       LOGE("USB is suspended, master clear is ignored.\n");
       return 1;
    }
    LOGE("finished unsuspend\n");

    /* change bp from flash mode to normal mode*/
    bp_flashmode_to_normalmode();
    LOGE("from flash to normal mode\n");
    /* Send the command and receive the response */
    aux_status = CMD_ENGINE_init();
    if (aux_status == CMD_ENGINE_INIT_NOT_PRESENT)
    {
        LOGE("Aux engine is not present, skipping  engine setup.\n");
        return 1;
    }
    else if (aux_status != CMD_ENGINE_INIT_SUCCESS)
    {
        LOGE("Failed to init the engine! aux_status = %d.\n", aux_status);
        return 1;
    }
    LOGE("engine init finished\n");
    write_len = sizeof(CMD_DEFS_CMD_REQ_HDR_T)+cmd_header.length;
    if ( (write_buff = (UINT8 *)malloc(write_len)) == NULL)
    {
        LOGE("Out of memory - malloc failed on write_buff, length = %d.\n", write_len);
        return 1;
    }

    CMD_ENGINE_UTIL_hdr_req_ntoh(&cmd_header, (CMD_DEFS_CMD_REQ_HDR_T *) write_buff);
    write_buff[write_len-1] = CMD_BP_MASTER_CLEAR;

    CMD_DBG_data_dump(write_buff, write_len);

    if (CMD_ENGINE_write(write_len, write_buff) != TRUE)
    {
           LOGE("Write data to aux engine failed!\n");
           return 1;
    }
    else
    {
       LOGE("Transferred %d byte(s) CMD opcode = 0x%04x to aux engine succeeded.\n",write_len, cmd_header.opcode);
    }
    LOGE("write finished\n");
    free(write_buff);
    /* Verify BP response was not a failure */
    if (CMD_ENGINE_read(sizeof(c_rsp_hdr), (UINT8 *) &c_rsp_hdr) != TRUE)
    {
            LOGE("Reading header failed!\n");
            return 1;
    }
    else
    {
            /* Network byte order to host byte order... */
           CMD_DBG_data_dump(&c_rsp_hdr, sizeof(c_rsp_hdr));
    }

    if ( (c_rsp_hdr.fail_flag & CMD_DEFS_RSP_FLAG_FAIL) ||
    ( (c_rsp_hdr.rsp_code != CMD_RSP_CODE_CMD_RSP_GENERIC) &&
         (c_rsp_hdr.rsp_code != CMD_RSP_CODE_NOT_SET) ) )
    {
         return 1;
    }

    close(cmd_engine_fd);
    return 0;
}