static void bq27410_battery_update_work(struct work_struct *work) { struct file *filp; int retval; unsigned long len = sizeof(g_filename); struct bq27410_device_info *di = container_of(work, struct bq27410_device_info, work.work); retval = update_get_flen(g_filename); if(retval == 0){ printk("bq27410_battery_update_work:update_get_flen error.\n"); return; } mutex_lock(&g_bq27410_mutex); retval = bq27410_update_flash_data(filp, g_filename, len, NULL); mutex_unlock(&g_bq27410_mutex); if(retval == 0) { #if UPDATE_FIRMWARE_RESTART printk("bq27410_battery_update_work ,update success,restart the system.\n"); virtual_battery_enable = 0; //after update firmware ,restart the system. sys_sync(); msleep(200); kernel_restart(NULL); return; #else printk("bq27410_battery_update_work ,update success.\n"); #endif } else{ printk("bq27410_battery_update_work:update failed.\n"); return; } bq27410_write_batt_insert(g_client); msleep(2000); bq27410_write_batt_insert(g_client); INIT_DELAYED_WORK(&bq27410_di->work, bq27410_battery_work); schedule_delayed_work(&bq27410_di->work, bq27410_di->interval); }
static int bq27410_update_write(struct file *filp, const char __user *buff, unsigned long len, void *data) { int ret = 0; char update_file[100]; memset(update_file, 0, 100); if(copy_from_user(&update_file, buff, len)) { return -EFAULT; } update_file[len-1] = 0; ret = update_get_flen(update_file); if(ret == 0){ printk("bq27410_update_write:update_get_flen error.\n"); return -EFAULT; } mutex_lock(&g_bq27410_mutex); printk("update file: %d-[%s].\n", len, update_file); if(bq27410_update_flash_data(filp, update_file, len, data) < 0) ret = bq27410_update_flash_data(filp, update_file, len, data); mutex_unlock(&g_bq27410_mutex); if(ret) { //after update firmware ,restart the system. printk("%s,after update firmware ,restart the system.\n", __FUNCTION__); sys_sync(); msleep(200); bq27410_update_flag = 3; // kernel_restart(NULL); } else{ printk("bq27410_update_write:update failed.\n"); bq27410_update_flag = 4; } return len; }
static int bq27410_update_fw(struct file *filp, char *buff, unsigned long len, void *data) { struct file * file_data = NULL; mm_segment_t old_fs; int file_len; char *data_buf = NULL; int ret; char buf[128]; char *pch = NULL; s32 base = 16; int count = 0; int wCount = 0; int xCount = 0; int cCount = 0; #define isspace(c) ((c) == ' ') file_len = update_get_flen(buff); ///Open update file. file_data = update_file_open(buff, &old_fs); if(file_data == NULL) { return -1; } data_buf = kzalloc(file_len, GFP_KERNEL); if(file_len > 0) { ret = file_data->f_op->read(file_data, data_buf, file_len, &file_data->f_pos); //printk("get file strlen(data_buf): %d.\n", strlen(data_buf)); pch = data_buf; while(count < file_len) { if(*pch == 'W') { wCount = 0; pch +=2; count +=2; while(*pch != 'W' && *pch != 'X' && *pch != 'C') { while(isspace(*pch)) { pch++; count ++; } ret = simple_strtoul(pch, NULL, base); buf[wCount] = ret; wCount++; //printk("%x ", ret); pch +=2; count +=2; while((*pch == '\r') || (*pch == '\n')) { pch +=2; count +=2; } } //printk("\n"); //printk("\n W count = %d , wCount=%d\n", count, wCount); ret = bq27410_write(g_client,buf[1],&buf[2],wCount - 2); //printk("W ret =%d ", ret); } else if(*pch == 'X') { xCount = 0; pch +=2; count +=2; while(*pch != 'W' && *pch != 'X' && *pch != 'C') { while(isspace(*pch)) { pch++; count ++; } ret = simple_strtoul(pch, NULL, 10); //printk("%d ", ret); xCount++; if(ret < 0x10) { pch +=1; count +=1; } else if(ret < 0x100){ pch +=2; count +=2; } else if(ret < 0x1000){ pch +=3; count +=3; } else if(ret < 0x10000){ pch +=4; count +=4; } while((*pch == '\r') || (*pch == '\n')) { pch +=2; count +=2; } if(ret == 4000) { count = file_len; break; } } //printk("\n X count = %d, xCount=%d \n", count, xCount); //printk("\n"); msleep(ret); } else if(*pch == 'C') { cCount = 0; pch +=2; count +=2; while(*pch != 'W' && *pch != 'X' && *pch != 'C') { while(isspace(*pch)) { pch++; count ++; } ret = simple_strtoul(pch, NULL, base); buf[cCount] = ret; //printk("%x ", ret); cCount++; pch +=2; count +=2; while((*pch == '\r') || (*pch == '\n')) { pch +=2; count +=2; break; } } //printk("\n"); //printk("\n C count = %d , cCount=%d\n", count, cCount); ret = bq27410_read(g_client,buf[1],&buf[2],cCount - 2); //printk("C ret =%d ", ret); } } } if(data_buf){ kfree(data_buf); data_buf = NULL; } ///Close file update_file_close(file_data, old_fs); return 0; }