Home | History | Annotate | Download | only in recovery
      1  /*
      2   * Copyright (C) 2009/2010 Motorola Inc.
      3   * All Rights Reserved.
      4   * Motorola Confidential Restricted.
      5   */
      6 
      7 
      8 #include <stdlib.h>
      9 #include <stdio.h>
     10 #include <errno.h>
     11 #include <unistd.h>
     12 #include <sys/types.h>
     13 #include <fcntl.h>
     14 #include <termios.h>
     15 
     16 #include "common.h"
     17 #include "masterclear_bp.h"
     18 
     19 
     20 /* @ set usb in unsuspend mode */
     21 int set_usb_unsuspend()
     22 {
     23         int ret;
     24         int count = sizeof(setup_cmd)-1;
     25 
     26         FILE *fp = fopen(USB1_SETUP_FILE, "w");
     27         if (fp == NULL) {
     28             LOGE("Can't open %s\n", USB1_SETUP_FILE);
     29             fclose(fp);
     30             return 1;
     31         }
     32         else {
     33             if ((ret = fwrite(setup_cmd,1,count,fp))<count)
     34             {
     35               LOGE("Write %s failed.\n",USB1_SETUP_FILE);
     36               fclose(fp);
     37               return 1;
     38             }
     39         }
     40         fclose(fp);
     41         return 0;
     42 }
     43 
     44 /* @dump the  buff data to debug */
     45 void CMD_DBG_data_dump(void* databuff, int len)
     46 {
     47 #ifdef TC_DEBUG
     48     int max_col = CMD_DBG_MAX_DUMP_COLS;
     49     int row = 0;
     50     int col = 0;
     51     int num_col;
     52     int buffer_index = 0;
     53     UINT8 value;
     54 
     55     char string_buffer[(TC_DBG_MAX_DUMP_COLS * 3) + 1];  /* Each column takes up 3 characters, plus NULL */
     56     for (row = 0; row <= (len / max_col); row++)
     57     {
     58         /* Reset string buffer for each new row */
     59         memset(string_buffer, 0, sizeof(string_buffer));
     60 
     61         /* For all rows, the number of columns is the max number, except for the last row */
     62         num_col = (row == (len / max_col)) ? (len % max_col) : max_col;
     63         if (num_col != 0)
     64         {
     65             for (col = 0; col < num_col; col++)
     66             {
     67                 value = ((UINT8*)databuff)[buffer_index++];
     68                 LOGE("%s%02x ", string_buffer, value);
     69             }
     70             LOGE("%s", string_buffer);
     71         }
     72     }
     73 
     74 #endif
     75 }
     76 
     77 /*=============================================================================================*//**
     78 @brief Initializes the communcation interface with the bp command engine
     79 
     80 @return Status of initialization
     81 
     82 @note
     83  - If no command engine is present, CMD_ENGINE_INIT_NOT_PRESENT must be returned
     84 *//*==============================================================================================*/
     85 CMD_ENGINE_INIT_T CMD_ENGINE_init(void)
     86 {
     87     UINT8 try_count = 1;
     88     CMD_ENGINE_INIT_T status = CMD_ENGINE_INIT_FAIL;
     89     cmd_engine_fd = -1;
     90     /* Keep trying to connect to the command engine until we are successful, or we hit the retry max */
     91     usleep(4000000);
     92     while (cmd_engine_fd < 0)
     93     {
     94     LOGE("open dev\n");
     95         if ( (cmd_engine_fd = open (CMD_ENGINE_DEVICE, O_RDWR)) < 0 )
     96         {
     97             if (try_count == CMD_ENGINE_CONNECT_MAX_TRY)
     98             {
     99                 LOGE("Reached max number of retries, giving up...\n");
    100                 break;
    101             }
    102             else
    103             {
    104                 /* Try to connect again, wait a bit before retry */
    105                 try_count++;
    106                 usleep(CMD_ENGINE_CONNECT_TRY_DELAY);
    107             }
    108         }
    109         else
    110         {
    111             struct termios tio;
    112             tcgetattr( cmd_engine_fd, &tio );
    113 
    114             /* Modify local options */
    115             tio.c_lflag &= ~( ECHO | ECHOE | ECHOK | ECHONL ); // None ECHO mode
    116             tio.c_lflag &= ~( ICANON | ISIG );    // raw data
    117 
    118             /* Modify input options */
    119             tio.c_iflag = IGNBRK | IGNPAR; //work code
    120 
    121             /* Modify output options */
    122             tio.c_oflag &= ~( OPOST );     // work code
    123 
    124             /* Modify control options */
    125             tio.c_cflag |= ( CLOCAL | CREAD | CRTSCTS );   //enable receiver & hardware flow control
    126             tio.c_cflag &= ~( CSIZE );     //disable bit mask for data bits
    127             tio.c_cflag |= CS8;            //set 8-bit characters
    128             tio.c_cflag &= ~( PARENB );    //disable parity bit*/
    129 
    130             /* Modify the Baud Rate */
    131             cfsetispeed( &tio, B115200 );
    132             cfsetospeed( &tio, B115200 );
    133 
    134             /* Clear the line and prepare to activate the new settings */
    135             tcflush( cmd_engine_fd, TCIFLUSH );
    136 
    137             /* Set the options */
    138             tcsetattr( cmd_engine_fd, TCSANOW, &tio );
    139 
    140             status = CMD_ENGINE_INIT_SUCCESS;
    141         }
    142     }
    143     return(status);
    144 }
    145 
    146 /*=========================================================================*//*
    147  brief read command response from bp
    148 @param[in]  bytes_to_write - The number of bytes to read
    149 @param[out] data           - Data to read
    150 
    151 @return TRUE = success, FALSE = failure
    152 *//*=================================================================================*/
    153 
    154 BOOL CMD_ENGINE_read(UINT32 bytes_to_read, UINT8 *data)
    155 {
    156     BOOL   is_success = FALSE;
    157     UINT32 total_bytes_read = 0;
    158     UINT32 bytes_read = 0;
    159 
    160     /* Return error if the aux engine handle is not init'd */
    161     if (cmd_engine_fd == CMD_ENGINE_FD_NOT_INIT)
    162     {
    163         LOGE(" engine device is not open!\n");
    164     }
    165     else
    166     {
    167         while( total_bytes_read != bytes_to_read )
    168         {
    169             bytes_read = read(cmd_engine_fd, &data[total_bytes_read], bytes_to_read - total_bytes_read);
    170             LOGE("Attempted to read %d bytes and read %d bytes.\n", bytes_to_read - total_bytes_read, bytes_read);
    171 
    172             if( bytes_read <= 0 )
    173             {
    174                 LOGE("Failed to read  engine device.\n");
    175                 break;
    176             }
    177             total_bytes_read += bytes_read;
    178         }
    179         if( total_bytes_read == bytes_to_read )
    180         {
    181             LOGE("Successfully read %d bytes.\n", total_bytes_read);
    182             is_success = TRUE;
    183         }
    184     }
    185 
    186     return (is_success);
    187 }
    188 
    189 /*=============================================================================================*//**
    190 @brief Writes the specified number of bytes to the command engine
    191 
    192 @param[in]  bytes_to_write - The number of bytes to write
    193 @param[out] data           - Data to write
    194 
    195 @return TRUE = success, FALSE = failure
    196 
    197 @note
    198  - The write is synchronous, the function will block until the requested number of bytes are written
    199 *//*==============================================================================================*/
    200 BOOL CMD_ENGINE_write(UINT32 bytes_to_write, UINT8 *data)
    201 {
    202     BOOL   is_success  = FALSE;
    203     UINT32 bytes_wrote = 0;
    204 
    205     /* Return error if the aux engine handle is not init'd */
    206     if (cmd_engine_fd == CMD_ENGINE_FD_NOT_INIT)
    207     {
    208         LOGE("engine device is not open!\n");
    209     }
    210     else
    211     {
    212         bytes_wrote = write(cmd_engine_fd, data, bytes_to_write);
    213         if (bytes_wrote != bytes_to_write)
    214         {
    215             LOGE("Failed to write to engine device, attempted to write %d bytes, but wrote %d.\n",bytes_to_write, bytes_wrote);
    216         }
    217         else
    218         {
    219             LOGE("Successfully wrote %d bytes.\n", bytes_wrote);
    220             is_success = TRUE;
    221         }
    222     }
    223 
    224     return (is_success);
    225 }
    226 
    227 
    228 
    229 /*=============================================================================================*//**
    230 @brief Convert network byte order to host byte order for command request headers
    231 
    232 @param[in]  hdr_in  - Network byte order command request header
    233 @param[out] hdr_out - Host byte order command request header
    234 *//*==============================================================================================*/
    235 void CMD_ENGINE_UTIL_hdr_req_ntoh(CMD_DEFS_CMD_REQ_HDR_T* hdr_in,CMD_DEFS_CMD_REQ_HDR_T* hdr_out)
    236 {
    237     memcpy(hdr_out, hdr_in, sizeof(CMD_DEFS_CMD_REQ_HDR_T));
    238     hdr_out->opcode = ((hdr_in->opcode & 0x00FF) << 8) | ((hdr_in->opcode & 0xFF00) >> 8);
    239     hdr_out->length = ((hdr_in->length & 0x000000FF) << 24) |
    240         ((hdr_in->length & 0x0000FF00) << 8) |
    241         ((hdr_in->length & 0x00FF0000) >> 8) |
    242         ((hdr_in->length & 0xFF000000) >> 24);
    243 
    244 }
    245 
    246 /*================================================================*//**
    247 @ brief change bp from flash mode to normal mode
    248 *//*=================================================================*/
    249 int bp_flashmode_to_normalmode(void)
    250 {
    251     int fd;
    252     ssize_t result;
    253     fd = open(MDM_CTRL_DEVICE, O_WRONLY);
    254     if (fd < 0)
    255     {
    256       LOGE("failed open mdm_ctrl\n");
    257       return fd;
    258     }
    259     LOGE("open mdm_ctrl ok\n");
    260 
    261     //shutdown BP
    262     // echo shutdown > /sys/class/radio/mdm6600/command
    263     result = write(fd, MDM_CMD_SHUTDONW, sizeof(MDM_CMD_SHUTDONW)-1);
    264     if (result < (ssize_t)(sizeof(MDM_CMD_SHUTDONW)-1))
    265     {
    266         LOGE("Failed to shutdown BP\n");
    267         return -1;
    268     }
    269     usleep(1000000);
    270 
    271     //set BP power up mode
    272     // echo bootmode_normal > /sys/class/radio/mdm6600/command
    273     result = write(fd, MDM_CMD_NORMAL_MODE, sizeof(MDM_CMD_NORMAL_MODE)-1);
    274     if (result < (ssize_t)(sizeof(MDM_CMD_NORMAL_MODE)-1))
    275     {
    276         LOGE("Failed to set BP boot mode\n");
    277         return -1;
    278     }
    279 
    280     //power up BP
    281     // echo powerup > /sys/class/radio/mdm6600/command
    282     result = write(fd, MDM_CMD_POWERUP, sizeof(MDM_CMD_POWERUP)-1);
    283     if (result < (ssize_t)(sizeof(MDM_CMD_POWERUP)-1))
    284     {
    285         LOGE("Failed to powerup BP\n");
    286         return -1;
    287     }
    288     usleep(2000000);
    289     close(fd);
    290 
    291     LOGE("Finished boot BP to normal mode\n");
    292     return 0;
    293 }
    294 
    295 /*=============================================================================================*//**
    296 @brief BP master clear
    297 
    298 *//*==============================================================================================*/
    299 
    300 int bp_master_clear(void)
    301 {
    302     UINT8                  bp_ver_len;
    303     const UINT8            *bp_rsp_data_ptr;
    304     int                    write_len  = 0;
    305     int                    read_len = 0;
    306     UINT8                  *write_buff = NULL;
    307     UINT8                  *read_buff = NULL;
    308 
    309     CMD_ENGINE_INIT_T  aux_status;
    310     CMD_DEFS_CMD_REQ_HDR_T cmd_header = {0};
    311     CMD_DEFS_CMD_RSP_HDR_T  c_rsp_hdr;
    312 
    313     write_len = sizeof(CMD_DEFS_CMD_REQ_HDR_T);
    314     /* Build up the CMD request */
    315     cmd_header.cmd_rsp_flag     = CMD_DEFS_HDR_FLAG_CMD_RSP_COMMAND;
    316     cmd_header.opcode           = CMD_CMN_DRV_BP_MASTERCLEAR_OPCODE;
    317     cmd_header.no_rsp_reqd_flag = CMD_DEFS_HDR_FLAG_RESPONSE_EXPECTED;
    318     cmd_header.length           = CMD_BP_MASTER_RESET_DATALENTH;
    319 
    320     /* cancel the usb suspend mode so that usb devices can be detected when bp power up */
    321     if(set_usb_unsuspend()!=0)
    322     {
    323        LOGE("USB is suspended, master clear is ignored.\n");
    324        return 1;
    325     }
    326     LOGE("finished unsuspend\n");
    327 
    328     /* change bp from flash mode to normal mode*/
    329     bp_flashmode_to_normalmode();
    330     LOGE("from flash to normal mode\n");
    331     /* Send the command and receive the response */
    332     aux_status = CMD_ENGINE_init();
    333     if (aux_status == CMD_ENGINE_INIT_NOT_PRESENT)
    334     {
    335         LOGE("Aux engine is not present, skipping  engine setup.\n");
    336         return 1;
    337     }
    338     else if (aux_status != CMD_ENGINE_INIT_SUCCESS)
    339     {
    340         LOGE("Failed to init the engine! aux_status = %d.\n", aux_status);
    341         return 1;
    342     }
    343     LOGE("engine init finished\n");
    344     write_len = sizeof(CMD_DEFS_CMD_REQ_HDR_T)+cmd_header.length;
    345     if ( (write_buff = (UINT8 *)malloc(write_len)) == NULL)
    346     {
    347         LOGE("Out of memory - malloc failed on write_buff, length = %d.\n", write_len);
    348         return 1;
    349     }
    350 
    351     CMD_ENGINE_UTIL_hdr_req_ntoh(&cmd_header, (CMD_DEFS_CMD_REQ_HDR_T *) write_buff);
    352     write_buff[write_len-1] = CMD_BP_MASTER_CLEAR;
    353 
    354     CMD_DBG_data_dump(write_buff, write_len);
    355 
    356     if (CMD_ENGINE_write(write_len, write_buff) != TRUE)
    357     {
    358            LOGE("Write data to aux engine failed!\n");
    359            return 1;
    360     }
    361     else
    362     {
    363        LOGE("Transferred %d byte(s) CMD opcode = 0x%04x to aux engine succeeded.\n",write_len, cmd_header.opcode);
    364     }
    365     LOGE("write finished\n");
    366     free(write_buff);
    367     /* Verify BP response was not a failure */
    368     if (CMD_ENGINE_read(sizeof(c_rsp_hdr), (UINT8 *) &c_rsp_hdr) != TRUE)
    369     {
    370             LOGE("Reading header failed!\n");
    371             return 1;
    372     }
    373     else
    374     {
    375             /* Network byte order to host byte order... */
    376            CMD_DBG_data_dump(&c_rsp_hdr, sizeof(c_rsp_hdr));
    377     }
    378 
    379     if ( (c_rsp_hdr.fail_flag & CMD_DEFS_RSP_FLAG_FAIL) ||
    380     ( (c_rsp_hdr.rsp_code != CMD_RSP_CODE_CMD_RSP_GENERIC) &&
    381          (c_rsp_hdr.rsp_code != CMD_RSP_CODE_NOT_SET) ) )
    382     {
    383          return 1;
    384     }
    385 
    386     close(cmd_engine_fd);
    387     return 0;
    388 }
    389