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