boolean OTAUpdateClass::parseUpdateMD5(String* vxp_name, String* vxp_digest) { LFlash.begin(); LFile update_md5 = LFlash.open(UPDATE_MD5); if(!update_md5) { DEBUG_UPDATE("OTAUpdate::parseUpdateMD5 - could not open %s\r\n", UPDATE_MD5); return false; } String line = ""; while(update_md5.available()) { line += (char) update_md5.read(); } update_md5.close(); line.trim(); // Warning : buffer line contain HTTP header ! // should look for vxp name and md5 from the end of buffer // look for index of last word (md5 name file) int idx = line.lastIndexOf(" "); // get md4 name file from index until end of buffer *vxp_name = line.substring(idx); // get md5 from index and index - 32 bytes (lenght of md5 is constant) *vxp_digest = line.substring(idx - 33, idx - 1); vxp_name->trim(); vxp_digest->trim(); DEBUG_UPDATE("OTAUpdate::parseUpdateMD5 - %s [%s]\r\n", vxp_name->c_str(), vxp_digest->c_str()); return true; }
boolean OTAUpdateClass::copyFile(const char* src, const char* dst) { char buffer[DIGEST_SIZE_BUFFER]; LFlash.begin(); LFile fsrc = LFlash.open(src, FILE_READ); if(!fsrc) { DEBUG_UPDATE("OTAUpdate::copyFile - error opening src %s\r\n", src); return false; } LFile fdst = LFlash.open(dst, FILE_WRITE); if(!fsrc) { fsrc.close(); DEBUG_UPDATE("OTAUpdate::copyFile - error opening dst %s\r\n", dst); return false; } fdst.seek(0); int size = fsrc.size(); int done = 0; while(done < size) { int read = fsrc.read(buffer, DIGEST_SIZE_BUFFER); fdst.write(buffer, read); done += read; } fsrc.close(); fdst.close(); return true; }
boolean OTAUpdateClass::parseUpdateMD5(String* vxp_name, String* vxp_digest) { LFlash.begin(); LFile update_md5 = LFlash.open(UPDATE_MD5); if(!update_md5) { DEBUG_UPDATE("OTAUpdate::parseUpdateMD5 - could not open %s\r\n", UPDATE_MD5); return false; } String line = ""; while(update_md5.available()) { line += (char) update_md5.read(); } update_md5.close(); line.trim(); int idx = line.indexOf(" "); *vxp_digest = line.substring(0, idx); *vxp_name = line.substring(idx + 1); vxp_name->trim(); vxp_digest->trim(); DEBUG_UPDATE("OTAUpdate::parseUpdateMD5 - %s [%s]\r\n", vxp_name->c_str(), vxp_digest->c_str()); return true; }
boolean OTAUpdateClass::checkUpdate(void) { String vxp_name, vxp_digest; if(!downloadFile(UPDATE_MD5)) { return false; } if(!parseUpdateMD5(&vxp_name, &vxp_digest)) { return false; } if(checkMD5(this->firmware_name, vxp_digest.c_str())) { DEBUG_UPDATE("found no new firmware!\r\n"); return false; } DEBUG_UPDATE("found a new firmware %s [%s]!\r\n", vxp_name.c_str(), vxp_digest.c_str()); if(!downloadFile(UPDATE_VXP)) { return false; } if(!checkMD5("C:\\" UPDATE_VXP, vxp_digest.c_str())) { DEBUG_UPDATE("new firmware has a wrong md5sum!\r\n"); return false; } DEBUG_UPDATE("new firmware is ok!\r\n"); return true; }
s32 init_update_proc(struct goodix_ts_data *ts) { u8 flag = 0; struct task_struct *thread = NULL; s32 retry = 0; DEBUG_MSG("Ready to run update thread.\n"); update_msg.fw_flag = get_ic_fw_msg(ts); if (fail == update_msg.fw_flag) { DEBUG_UPDATE("Try get ic msg in update mode.\n"); for (retry = 0; retry < 5; retry++) { if (success == guitar_update_mode(ts)) { break; } } if (retry >= 5) { update_msg.fw_flag = fail; } else { DEBUG_UPDATE("Get ic msg in update mode.\n"); update_msg.fw_flag = get_ic_fw_msg(ts); update_msg.ic_fw_msg.version = 0xfff0; if (update_msg.force_update == 0xAA) { flag = 0xff; } } guitar_leave_update_mode(); } else { guitar_reset(10); } if (success == update_msg.fw_flag) { update_msg.gt_loc = -1; thread = kthread_run(guitar_update_proc, (void*)ts, "guitar_update"); if (IS_ERR(thread)) { dev_err(&ts->client->dev, " failed to create update thread\n"); } if (0xff == flag) { return 0xff; } } return success; }
static u8 clear_mix_flag(struct goodix_ts_data *ts) { s32 i = 0; u8 buf[3]; buf[0] = 0x14; buf[1] = 0x00; buf[2] = 0x80; for (i = 0; i < 5; i++) { if (i2c_write_bytes(ts->client, buf, 3) > 0) { break; } } i2c_end_cmd(ts); if (i >= 5) { DEBUG_UPDATE("Clear mix flag failed!\n"); return fail; } return success; }
boolean OTAUpdateClass::downloadFile(const char* name) { // make some http requests to check for firmware updates LGPRSClient c; uint8_t buffer[DIGEST_SIZE_BUFFER]; int n , size, max_millis; // download the firmware if(!c.connect(this->host, 80)) { DEBUG_UPDATE("OTAUpdate::downloadFile - error connecting to update host\r\n"); return false; } // connected... send the get request DEBUG_UPDATE("OTAUpdate::downloadFile %s:80 'GET /%s/%s'\r\n", this->host, this->path, &name[4]); c.printf("GET /%s/%s\n", this->path, &name[4]); // save the result max_millis = millis() + 10000; LFlash.begin(); LFlash.remove((char*) name); LFile ota = LFlash.open(name, FILE_WRITE); ota.seek(0); size = 0; while(c.connected()) { int n = c.read(buffer, 1024); if(n > 0) { max_millis = millis() + 2000; ota.write(buffer, n); size += n; } else { if(millis() > max_millis) { DEBUG_UPDATE("OTAUpdate::downloadFile - timed out!\r\n"); c.stop(); ota.close(); return false; } else { delay(100); } } } c.stop(); ota.close(); DEBUG_UPDATE("OTAUpdate::downloadFile - done! got %d bytes\r\n", size); return size > 0; }
boolean OTAUpdateClass::checkMD5(const char* name, const char* hash) { char local_hash[DIGEST_SIZE_CHAR]; DEBUG_UPDATE("OTAUpdate::checkMD5 - %s %s\r\n", name, hash); // calculate the md5 sum of the new firmware if(!md5sum(name, local_hash)) { DEBUG_UPDATE("OTAUpdate::checkMD5 - error calculating md5sum!\r\n"); return false; } // check if the md5sum of the firmware matches if(strcmp(hash, local_hash) != 0) { DEBUG_UPDATE("OTAUpdate::checkMD5 - error md5sum mismatch!\r\n"); return false; } DEBUG_UPDATE("OTAUpdate::checkMD5 - OK\r\n"); return true; }
boolean OTAUpdateClass::startFirmware(const char* name) { DEBUG_UPDATE("OTAUpdate::startFirmware - %s\r\n", name); // update autostart.txt for the new firmware LFlash.begin(); LFile dst = LFlash.open("autostart.txt", FILE_WRITE); if(!dst) { DEBUG_UPDATE("OTAUpdate::performUpdate - error opening autostart.txt\r\n"); return false; } dst.seek(0); dst.printf("[autostart]\r\nApp=%s\r\n", name); dst.close(); // reset the board reset(); return true; }
boolean OTAUpdateClass::startUpdate(void) { String vxp_name, vxp_digest; // check if all required files exist if(!LFlash.exists((char*)OTA_FW) || !LFlash.exists((char*)UPDATE_MD5) || !LFlash.exists((char*)UPDATE_VXP)) { DEBUG_UPDATE("OTAUpdate::startUpdate - not all required files found\r\n"); return false; } // check if the update files are ok if(!checkUpdateFiles(&vxp_name, &vxp_digest)) { DEBUG_UPDATE("OTAUpdate::startUpdate - check files failed\r\n"); return false; } // if yes, start the OTA FW upgrade DEBUG_UPDATE("OTAUpdate::startUpdate - updating to firmware %s [%s]\r\n", vxp_name.c_str(), vxp_digest.c_str()); return startFirmware("C:\\" OTA_FW); }
/* * Steps of reset guitar *1. INT脚输出低,延时5ms *2. RESET脚拉低100ms,转输入悬浮态 *3. I2C寻址GUITAR *4. 延时100ms读取0xff(3、4轮询80次,直至成功) *5. Oxff等于0x55则返回成功,否则失败 */ static int guitar_update_mode( struct goodix_ts_data *ts ) { int ret = 1; u8 retry; unsigned char inbuf[3] = {0,0xff,0}; // step 1 GPIO_DIRECTION_OUTPUT(INT_PORT, 0); GPIO_SET_VALUE(INT_PORT, 0); msleep(5); //step 2 guitar_reset(100); for(retry=0;retry < 80; retry++) { //step 3 ret =i2c_write_bytes(ts->client, inbuf, 0); //Test I2C connection. if (ret > 0) { DEBUG_UPDATE("<Set update mode>I2C is OK!\n"); //step 4 msleep(100); ret =i2c_read_bytes(ts->client, inbuf, 3); if (ret > 0) { DEBUG_UPDATE("The value of 0x00ff is 0x%02x\n", inbuf[2]); //step 5 if(inbuf[2] == 0x55) { return success; } } } msleep(10); } DEBUG_UPDATE(KERN_INFO"Detect address %0X\n", ts->client->addr); return fail; }
static u8 get_ic_msg(struct goodix_ts_data *ts, u16 addr, u8* msg, s32 len) { s32 i = 0; msg[0] = addr >> 8 & 0xff; msg[1] = addr & 0xff; for (i = 0; i < 5; i++) { if (i2c_read_bytes(ts->client, msg, ADDR_LENGTH + len) > 0) { break; } } i2c_end_cmd(ts); if (i >= 5) { DEBUG_UPDATE("Read data from 0x%02x%02x failed!\n", msg[0], msg[1]); return fail; } return success; }
static u8 guitar_update_firmware(struct goodix_ts_data *ts, st_fw_head* fw_head, u8 *nvram) { int retry; int ret; u32 status = 0; u8 buf[32]; //Cuts the frequency buf[0] = 0x15; buf[1] = 0x22; buf[2] = 0x18; ret = i2c_write_bytes(ts->client, buf, 3); if (ret <= 0) { return fail; } get_ic_msg(ts, 0x1522, buf, 1); DEBUG_UPDATE("IC OSC_CAL:0x%02x.\n", buf[2]); for (retry = 0; retry < 10; retry++) { //Write the 1st part (pid and vid) /* if (!(status & 0x01)) { buf[0] = UPDATE_FW_MSG_ADDR_H; buf[1] = UPDATE_FW_MSG_ADDR_L; buf[2] = fw_head->type; buf[3] = fw_head->version >> 8; buf[4] = fw_head->version & 0xff; ret = i2c_write_bytes(ts->client, buf, 5); if (ret <= 0) { continue; } else { DEBUG_UPDATE("Update pid and vid successfully!\n"); status |= 0x01; msleep(1); } } */ //Write the 2nd part (nvram) if (!(status & 0x02)) { if (fail == guitar_update_nvram(ts, fw_head, nvram)) { continue; } else { DEBUG_UPDATE("Update nvram successfully!\n"); status |= 0x02; msleep(1); } } //Write the 3rd part (check sum) if (1) { buf[0] = 0x4f; buf[1] = 0xf3; memcpy(&buf[2], fw_head->chk_sum, sizeof(fw_head->chk_sum)); ret = i2c_write_bytes(ts->client, buf, 5); if (ret <= 0) { continue; } else { DEBUG_UPDATE("Update check sum successfully!\n"); break; } } } if (retry >= 10) { return fail; } else { for (retry = 0; retry < 10; retry++) { buf[0] = 0x00; buf[1] = 0xff; buf[2] = 0x44; ret = i2c_write_bytes(ts->client, buf, 3); if (ret > 0) { break; } } if (retry >= 10) { DEBUG_UPDATE("Write address at 0x00ff error!\n"); return fail; } msleep(10); } for (retry = 0; retry < 30; retry++) { msleep(1); if (fail == get_ic_msg(ts, 0x00ff, buf, 1)) { DEBUG_UPDATE("Read address at 0x00ff error!\t retry:%d\n", retry); continue; } if (0xcc == buf[ADDR_LENGTH]) { return success; } else { DEBUG_UPDATE("The value of 0x00ff: 0x%02x!\t retry:%d\n", buf[ADDR_LENGTH], retry); continue; } } DEBUG_UPDATE("The value of 0x00ff error.\n"); return fail; }
boolean OTAUpdateClass::begin(const char* host, const char* port, const char* path) { DEBUG_UPDATE("OTAUpdate::begin - %s %s\r\n", host, path); // initialize our memory structures this->initialized = false; memset(this->firmware_name, 0, OTA_MAX_PATH_LEN); memset(this->firmware_digest, 0, DIGEST_SIZE_CHAR); memset(this->host, 0, OTA_MAX_PATH_LEN); memset(this->path, 0, OTA_MAX_PATH_LEN); memset(this->port, 0, OTA_MAX_PATH_LEN); strncpy(this->host, host, OTA_MAX_PATH_LEN-1); strncpy(this->path, path, OTA_MAX_PATH_LEN-1); strncpy(this->port, port, OTA_MAX_PATH_LEN-1); // read the firmware information LFlash.begin(); LFile cfg = LFlash.open("autostart.txt", FILE_READ); if (!cfg) { DEBUG_UPDATE("OTAUpdateClass::begin - could not read autostart.txt\r\n"); return false; } DEBUG_UPDATE("OTAUpdateClass::begin - reading autostart.txt\r\n"); while (cfg.available()) { String line = ""; char c = '\n'; // read the setting part of the line while (cfg.available()) { c = cfg.read(); line += c; if(c == '\n') { break; } } // look for = in the config line line.trim(); int idx = line.indexOf("="); if(idx >= 0) { String setting = line.substring(0, idx); String value = line.substring(idx+1); setting.trim(); value.trim(); DEBUG_UPDATE("autostart.txt: %s=%s\r\n", setting.c_str(), value.c_str()); if(setting == "App") { value.toCharArray(firmware_name, OTA_MAX_PATH_LEN); this->initialized = true; break; } } } cfg.close(); if(this->initialized) { // we found the app name... calculate the md5 sum md5sum(this->firmware_name, this->firmware_digest); DEBUG_UPDATE("OTAUpdate::begin - %s [%s]\r\n", this->firmware_name, this->firmware_digest); } else { DEBUG_UPDATE("OTAUpdate::begin - could not find firmware name\r\n"); return false; } return true; }
static u8 get_ic_fw_msg(struct goodix_ts_data *ts) { s32 ret = 0; s32 i = 0; u8 buf[32]; if (fail == clear_mix_flag(ts)) { return fail; } //Get the mask version in rom of IC if (fail == get_ic_msg(ts, READ_MSK_VER_ADDR_H << 8 | READ_MSK_VER_ADDR_L, buf, 4)) { DEBUG_UPDATE("Read mask version failed!\n"); return fail; } memcpy(update_msg.ic_fw_msg.msk_ver, &buf[ADDR_LENGTH], 4); DEBUG_UPDATE("IC The mask version in rom is %c%c%c%c.\n", update_msg.ic_fw_msg.msk_ver[0],update_msg.ic_fw_msg.msk_ver[1], update_msg.ic_fw_msg.msk_ver[2],update_msg.ic_fw_msg.msk_ver[3]); #if 1 //Get the firmware msg in IC, include firmware version and checksum flag for (i = 0; i < 2; i++) { if (fail == get_ic_msg(ts, READ_FW_MSG_ADDR_H<< 8 | READ_FW_MSG_ADDR_L, buf, 4)) { DEBUG_UPDATE("Get firmware msg in IC error.\n"); return fail; } update_msg.force_update = buf[ADDR_LENGTH]; if (i == 0 && update_msg.force_update == 0xAA) { DEBUG_UPDATE("The check sum in ic is error.\n"); DEBUG_UPDATE("IC will be reset.\n"); DEBUG_UPDATE("If the check sum is still error,\n "); DEBUG_UPDATE("The IC will be updated by force.\n"); guitar_reset(10); continue; //msleep(100); } break; } //ic_fw_msg.type = buf[ADDR_LENGTH + 1]; update_msg.ic_fw_msg.version = buf[ADDR_LENGTH + 2] << 8 | buf[ADDR_LENGTH + 3]; DEBUG_UPDATE("IC VID:0x%x\n", (int)update_msg.ic_fw_msg.version); DEBUG_UPDATE("IC force update:%x\n", update_msg.force_update); #endif //Cuts the frequency buf[0] = 0x15; buf[1] = 0x22; buf[2] = 0x18; ret = i2c_write_bytes(ts->client, buf, 3); if (ret <= 0) { return fail; } i2c_end_cmd(ts); //Get the pid at 0x4011 in nvram if (fail == get_ic_msg(ts, 0x4011, buf, 1)) { DEBUG_UPDATE("Read pid failed!\n"); return fail; } update_msg.ic_fw_msg.type = buf[ADDR_LENGTH]; DEBUG_UPDATE("IC PID:%x\n", update_msg.ic_fw_msg.type); // guitar_reset(10); return success; }
boolean OTAUpdateClass::downloadFile(const char* name) { // make some http requests to check for firmware updates LGPRSClient c; uint8_t buffer[DIGEST_SIZE_BUFFER]; int n , size, max_millis; char buff[256]; static char endofheader[5] ; boolean HTTPHeaderreached = false; char byc; //convert string to int String sthostport = this->port; unsigned int uinthostport = sthostport.toInt(); // download the firmware if(!c.connect(this->host, uinthostport)) { DEBUG_UPDATE("OTAUpdate::downloadFile - error connecting to update host\r\n"); return false; } // connected... send the get request DEBUG_UPDATE("OTAUpdate::downloadFile %s:%d 'GET /%s/%s'\r\n", this->host, uinthostport, this->path, &name[4]); sprintf(buff, "GET /%s/%s", this->path, &name[4]); c.print(buff); //c.printf("GET /%s/%s", this->path, &name[4]); c.println(" HTTP/1.1"); c.print("Host: "); c.println(this->host); c.println("Connection: close"); c.println(); // save the result max_millis = millis() + 10000; LFlash.begin(); LFlash.remove((char*) name); LFile ota = LFlash.open(name, FILE_WRITE); ota.seek(0); size = 0; // get data content of the file while(c.connected()) { //skip byte until end of HTTP Header if(HTTPHeaderreached == false) { // read byte byc = c.read(); if(byc > 0) { max_millis = millis() + 2000; // if HTTP header is not reached, read until find double CRLF Serial.print(byc); // proceed a right shift of the array for(int i = 0; i < 3; i++) { endofheader[i] = endofheader[i+1]; } // add last received char at the end of the array endofheader[3] = byc; //don't forget null caracter endofheader[4] = '\0'; // compare array with end of HTTP header key (double CRLF) if (strcmp("\r\n\r\n", endofheader ) == 0) { // return true DEBUG_UPDATE("OTAUpdate::downloadFile - end of HTTP header reached\r\n"); HTTPHeaderreached = true; } else { HTTPHeaderreached = false; } } else { if(millis() > max_millis) { DEBUG_UPDATE("OTAUpdate::downloadFile - timed out!\r\n"); c.stop(); ota.close(); return false; } else { delay(100); } } } else { int n = c.read(buffer, 1024); if(n > 0) { max_millis = millis() + 2000; ota.write(buffer, n); size += n; DEBUG_UPDATE("size = %d\r", size); } else { if(millis() > max_millis) { DEBUG_UPDATE("OTAUpdate::downloadFile - timed out!\r\n"); c.stop(); ota.close(); return false; } else { delay(100); } } } } c.stop(); ota.close(); DEBUG_UPDATE("\r\nOTAUpdate::downloadFile - done! got %d bytes\r\n", size); return size > 0; }
static int guitar_update_proc(void *v_ts) { s32 ret; u32 retry = 100; u32 i = 0; struct goodix_ts_data* ts = NULL; u8* data = NULL; u8* ic_nvram = NULL; st_fw_head fw_head; u8 buf[32]; ts = (struct goodix_ts_data*)v_ts; data = kzalloc(UPDATE_DATA_LENGTH, GFP_KERNEL); if (NULL == data) { DEBUG_UPDATE("data failed apply for memory.\n"); return fail; } ic_nvram = kzalloc(UPDATE_DATA_LENGTH, GFP_KERNEL); if (NULL == ic_nvram) { DEBUG_UPDATE("ic_nvram failed apply for memory.\n"); goto app_mem_failed; } DEBUG_UPDATE("Apply for memory successfully.memory size: %d.\n", UPDATE_DATA_LENGTH); msleep(1000); DEBUG_UPDATE("Updating...\n"); if (fail == load_update_file(ts, &fw_head, &data[2], NULL)) { DEBUG_UPDATE("Load file data failed!\n"); goto load_failed; } DEBUG_UPDATE("Load file data successfully!\n"); if (ts->use_irq) { if(!ts->irq_is_disable) { disable_irq(ts->client->irq); } ts->irq_is_disable = 2; } for (i = 0; i < 5; i++) { if (fail == guitar_update_mode(ts)) { DEBUG_UPDATE("Next try![Enter update mode]\n"); continue; } else { DEBUG_UPDATE("Set update mode successfully.\n"); break; } } if (i >= 5) { DEBUG_UPDATE("Set update mode failed.\n"); return fail; } retry = 0; while(retry++ < 5) { if (fail == guitar_update_firmware(ts, &fw_head, &data[2])) { DEBUG_UPDATE("Update firmware failed.\n"); continue; } DEBUG_UPDATE("Update firmware successfully.\n"); //while(1) // simulation store operation failed if (fail == guitar_nvram_store(ts)) { DEBUG_UPDATE("Store nvram failed.\n"); continue; } msleep(100); if (fail == get_ic_msg(ts, 0x1201, buf, 1)) { DEBUG_UPDATE("Read NVRCS failed.(Store)\n"); continue; } if (buf[ADDR_LENGTH] & 0x01) { DEBUG_UPDATE("Check NVRCS(0x%02x) failed.(Store)\n", buf[ADDR_LENGTH]); continue; } DEBUG_UPDATE("Store nvram successfully.\n"); if (fail == guitar_nvram_recall(ts)) { DEBUG_UPDATE("Recall nvram failed.\n"); continue; } msleep(5); if (fail == get_ic_msg(ts, 0x1201, buf, 1)) { DEBUG_UPDATE("Read NVRCS failed.(Recall)\n"); continue; } if (buf[ADDR_LENGTH] & 0x02) { DEBUG_UPDATE("Check NVRCS(0x%02x) failed.(Recall)\n", buf[ADDR_LENGTH]); continue; } DEBUG_UPDATE("Recall nvram successfully.\n"); ic_nvram[0] = fw_head.st_addr[0]; ic_nvram[1] = fw_head.st_addr[1]; for ( i = 0; i < 10; i++) { ret = i2c_read_bytes(ts->client, ic_nvram, ADDR_LENGTH + fw_head.lenth); if (ret <= 0) { continue; } break; } if (i >= 10) { DEBUG_UPDATE("Read nvram failed!\n"); continue; } DEBUG_UPDATE("Read nvram successfully!\n"); if (false == is_equal(&data[2], &ic_nvram[2], fw_head.lenth)) { DEBUG_UPDATE("Nvram not equal!\n"); continue; } DEBUG_UPDATE("Check nvram by byte successfully!\n"); if (update_msg.gt_loc > 0) { DEBUG_UPDATE("Location:%d, Ret:%d.\n", (s32)update_msg.gt_loc, (s32)ret); memset(buf, 0, sizeof(buf)); ret = update_msg.file->f_op->write(update_msg.file, buf, 6, &update_msg.gt_loc); if (ret < 0) { DEBUG_UPDATE("Didn't clear the focre update flag in file.\n"); } else { DEBUG_UPDATE("Clear the focre update flag in file.Location:%d, Ret:%d.\n", (s32)update_msg.gt_loc, (s32)ret); } } DEBUG_UPDATE("Update successfully!\n"); break; } set_fs(update_msg.old_fs); filp_close(update_msg.file, NULL); guitar_leave_update_mode(); DEBUG_UPDATE("Leave update mode!\n"); //Reset guitar DEBUG_UPDATE("Reset IC and send config!\n"); guitar_reset(10); for (i = 0; i < 3; i++) { if (fail == goodix_init_panel(ts, 1)) { msleep(10); continue; } break; } if (i >= 3) { DEBUG_UPDATE("Send config data failed.\n"); } msleep(10); if (ts->use_irq) { ts->irq_is_disable = 0; enable_irq(ts->client->irq); } load_failed: kfree(ic_nvram); app_mem_failed: kfree(data); if (retry < 5) { return success; } DEBUG_UPDATE("Update failed!\n"); return fail; }
static u8 guitar_update_nvram(struct goodix_ts_data *ts, st_fw_head* fw_head, u8 *nvram) { int length = 0; int ret = 0; int write_bytes = 0; int retry = 0; int i = 0; int comp = 0; u16 st_addr = 0; u8 w_buf[PACK_SIZE + ADDR_LENGTH]; u8 r_buf[PACK_SIZE + ADDR_LENGTH]; if (fw_head->lenth > PACK_SIZE) { write_bytes = PACK_SIZE; } else { write_bytes = fw_head->lenth; } clear_mix_flag(ts); st_addr = (fw_head->st_addr[0] << 8) | (fw_head->st_addr[1]&0xff); memcpy(&w_buf[2], &nvram[length], write_bytes); DEBUG_UPDATE("Total length:%d\n", (int)fw_head->lenth); while(length < fw_head->lenth) { w_buf[0] = st_addr >> 8; w_buf[1] = st_addr & 0xff; DEBUG_UPDATE("Write address:0x%02x%02x\tlength:%d\n", w_buf[0], w_buf[1], write_bytes); ret = i2c_write_bytes(ts->client, w_buf, ADDR_LENGTH + write_bytes); if (ret <= 0) { if (retry++ > 10) { DEBUG_UPDATE("Write the same address 10 times.Give up!\n"); return fail; } DEBUG_UPDATE("Write error![guitar_update_nvram]\n"); continue; } else { // DEBUG_UPDATE("w_buf:\n"); // DEBUG_ARRAY(w_buf, ADDR_LENGTH + write_bytes); /* r_buf[0] = 0x14; r_buf[1] = 0x00; r_buf[2] = 0x80; i2c_write_bytes(ts->client, r_buf, 3); r_buf[0] = 0x14; r_buf[1] = 0x00; i2c_read_bytes(ts->client, r_buf, 3); DEBUG_UPDATE("I2CCS:0x%x\n", r_buf[2]);//*/ r_buf[0] = w_buf[0]; r_buf[1] = w_buf[1]; for (i = 0; i < 10; i++) { ret = i2c_read_bytes(ts->client, r_buf, ADDR_LENGTH + write_bytes); if (ret <= 0) { continue; } break; } if (i >= 10) { DEBUG_UPDATE("Read error! Can't check the nvram data.\n"); return fail; } // DEBUG_UPDATE("r_buf:\n"); // DEBUG_ARRAY(r_buf, ADDR_LENGTH + write_bytes); #if 0 if (fail == guitar_nvram_store(ts)) { DEBUG_UPDATE("Store nvram failed.\n"); //continue; } return fail; #endif if (false == is_equal(r_buf, w_buf, ADDR_LENGTH + write_bytes)) { if (comp ++ > 10) { DEBUG_UPDATE("Compare error!\n"); return fail; } DEBUG_UPDATE("Updating nvram: Not equal!\n"); DEBUG_UPDATE("r_buf:\n"); DEBUG_ARRAY(r_buf, ADDR_LENGTH + write_bytes); DEBUG_UPDATE("w_buf:\n"); // DEBUG_ARRAY(w_buf, ADDR_LENGTH + write_bytes); continue; //return fail; } } comp = 0; retry = 0; length += PACK_SIZE; st_addr += PACK_SIZE; if ((length + PACK_SIZE) > fw_head->lenth) { write_bytes = fw_head->lenth - length; } memcpy(&w_buf[2], &nvram[length], write_bytes); } return success; }
u8 load_update_file(struct goodix_ts_data *ts, st_fw_head* fw_head, u8* data, u8* path) { u8 mask_num = 0; int ret = 0; int i = 0; u8 buf[FW_HEAD_LENGTH]; if (path) { update_msg.file = filp_open(path, O_RDWR, 0666); if (IS_ERR(update_msg.file)) { DEBUG_UPDATE("Open update file(%s) error!\n", path); return fail; } } else { //Begin to search update file for (i = 0; i < SEARCH_FILE_TIMES; i++) { update_msg.file = filp_open(UPDATE_FILE_PATH_1, O_RDWR, 0666); if (IS_ERR(update_msg.file)) { update_msg.file = filp_open(UPDATE_FILE_PATH_2, O_RDWR, 0666);//O_RDWR if (IS_ERR(update_msg.file)) { DEBUG_UPDATE("%3d:Searching file...\n", i); msleep(3000); continue; } else { break; } } else { break; } } if (i >= 100) { DEBUG_UPDATE("Can't find update file.\n"); return fail; } DEBUG_UPDATE("Find the update file.\n"); } update_msg.old_fs = get_fs(); set_fs(KERNEL_DS); update_msg.file->f_pos = IGNORE_LENGTH; //Make sure the file is the right file.(By compare the "Guitar" flag) ret = update_msg.file->f_op->read(update_msg.file, (char*)&buf, 6, &update_msg.file->f_pos); if (ret < 0) { DEBUG_UPDATE("Read \"Guitar\" flag error.\n"); goto load_failed; } if (false == is_equal(buf, "Guitar", 6)) { DEBUG_UPDATE("The flag is %s.Not equal!\n" "The update file is incorrect!\n", buf); goto load_failed; } DEBUG_UPDATE("The file flag is :%s.\n", buf); //Get the total number of masks update_msg.file->f_pos++; //ignore one byte. ret = update_msg.file->f_op->read(update_msg.file, &mask_num, 1, &update_msg.file->f_pos); if (ret < 0) { DEBUG_UPDATE("Didn't get the mask number from the file.\n"); goto load_failed; } DEBUG_UPDATE("FILE The total number of masks is:%d.\n", mask_num); update_msg.file->f_pos = FILE_HEAD_LENGTH + IGNORE_LENGTH; //Get the correct nvram data //The correct conditions: //1. the product id is the same //2. the mask id is the same //3. the nvram version in update file is greater than the nvram version in ic //or force update flag is marked or the check sum in ic is wrong update_msg.gt_loc = -1; for ( i = 0; i < mask_num; i++) { ret = update_msg.file->f_op->read(update_msg.file, (char*)buf, FW_HEAD_LENGTH, &update_msg.file->f_pos); if (ret < 0) { DEBUG_UPDATE("Read update file head error.\n"); goto load_failed; } memcpy(fw_head, buf, sizeof(st_fw_head)); fw_head->version = buf[1] << 8 | buf[2]; fw_head->lenth = buf[9] << 8 | buf[10]; DEBUG_UPDATE("No.%d firmware\n", i); DEBUG_UPDATE("FILE PID:%x\n", fw_head->type); DEBUG_UPDATE("FILE VID:0x%x\n", fw_head->version); DEBUG_UPDATE("FILE mask version:%c%c%c%c.\n", fw_head->msk_ver[0], fw_head->msk_ver[1],fw_head->msk_ver[2],fw_head->msk_ver[3]); DEBUG_UPDATE("FILE start address:0x%02x%02x.\n", fw_head->st_addr[0], fw_head->st_addr[1]); DEBUG_UPDATE("FILE length:%d\n", (int)fw_head->lenth); DEBUG_UPDATE("FILE force update flag:%s\n", fw_head->force_update); DEBUG_UPDATE("FILE chksum:0x%02x%02x%02x\n", fw_head->chk_sum[0], fw_head->chk_sum[1], fw_head->chk_sum[2]); //First two conditions if (is_equal(fw_head->msk_ver, update_msg.ic_fw_msg.msk_ver, sizeof(update_msg.ic_fw_msg.msk_ver)) && update_msg.ic_fw_msg.type == fw_head->type) { DEBUG_UPDATE("Get the same mask version and same pid.\n"); //The third condition if (fw_head->version > update_msg.ic_fw_msg.version || is_equal(fw_head->force_update, "GOODIX", 6) || update_msg.force_update == 0xAA) { // DEBUG_UPDATE("FILE read position:%d\n", file->f_pos); // file->f_pos = FW_HEAD_LENGTH + FILE_HEAD_LENGTH + IGNORE_LENGTH; if (is_equal(fw_head->force_update, "GOODIX", 6)) { update_msg.gt_loc = update_msg.file->f_pos - FW_HEAD_LENGTH + sizeof(st_fw_head) - sizeof(fw_head->force_update); } ret = update_msg.file->f_op->read(update_msg.file, (char*)data, fw_head->lenth, &update_msg.file->f_pos); if (ret <= 0) { DEBUG_UPDATE("Read firmware data in file error.\n"); goto load_failed; } // DEBUG_ARRAY(data, 512); // set_fs(ts->old_fs); // filp_close(ts->file, NULL); DEBUG_UPDATE("Load data from file successfully.\n"); return success; } DEBUG_UPDATE("Don't meet the third condition.\n"); goto load_failed; } update_msg.file->f_pos += UPDATE_DATA_LENGTH; } load_failed: set_fs(update_msg.old_fs); filp_close(update_msg.file, NULL); return fail; }