static ssize_t update_firmware_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
	int ret0, ret1;	
	int i, j;
	ret0 = i2c_smbus_read_byte_data(g_client,0x00); 
	ret1 = i2c_smbus_read_byte_data(g_client,0x01);
        
	if (!strcmp(buf, "1")) 
    {  
            
	    if ((ret1 == 0xf1) && (ret0 != 0x80) && (ret0 != 0x81) && (ret0 != 0x82))

	    { /*application chesmu error, update */

    		for(i = 0; i < 3; i++) 
            {    /* max update tries time is set 3 */

    		    ret0 = i2c_update_firmware(); /*update firmware*/
    		    if (ret0 == 0) 
                { 
        			mdelay(800);   /*wait for ts reset*/
        			break;
    		    }
    		}
	    }

	}
	//    else if (!strcmp(buf, "2")) {   /*update firmware from project menu*/      

	else if ( buf[0] == '2') 
    {   /*update firmware from project menu*/      

	    for(i = 0; i < 3; i++) 
        {    /* max update tries time is set 3 */

    		ret0 = i2c_smbus_write_byte_data(g_client, 0x0d, 0x20); /* inform app switch to upgrade mode*/

    		printk("ret0 = %d\n", ret0);
    		if (!ret0) 
            { 
                        
    		    ret0 = i2c_update_firmware();   /*update firmware*/

    		    if (ret0 == 0) 
                { /*update firmware success */ 
        			printk("update firmware success\n!");
        			mdelay(800); /*wait for ts reset*/
        			return 1;
    		    }
    		    else if (ret0 == -2)   /*update error,reboot*/ 
    			    arm_pm_restart(0);
    		}
	    }
	}
        
	return ret0;
}
static ssize_t cyp_update_firmware_store(struct kobject *kobj, 
							struct kobj_attribute *attr, const char *buf, size_t count)
{
	int ret = -1;
	struct i2c_msg msg;
	uint8_t out_bootloader_buffer[20] = {0x00,0x00,0xFF,0xA5,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};

	printk("Update_firmware_store.\n");
	if (buf[0] == '2') {
		disable_irq(g_client->irq);
		msg.addr = g_client->addr;
		msg.flags = 0;
		msg.buf = out_bootloader_buffer;
		msg.len = 12;

		/* into bootloader mode */
		ret = i2c_smbus_write_byte_data(g_client, 0x00, 0x01);
		msleep(200);
		ret = i2c_smbus_read_byte_data(g_client, 0x01);		/* read status bit */
		if (ret < 0) {
			printk("Into bootloader mode error1.\n");
			msleep(200);
			i2c_transfer(g_client->adapter, &msg, 1);		/* out of bootloader mode */
			enable_irq(g_client->irq);
			return -1;
		} else if ( 0x10 == (ret&0x10) ) {
			printk("Into bootloader mode success.\n");
		} else {
			printk("Into bootloader mode error2.\n");
			msleep(200);
			i2c_transfer(g_client->adapter, &msg, 1);		/* out of bootloader mode */
			enable_irq(g_client->irq);
			return -1;
		}

		/*update firmware*/
		ret = i2c_update_firmware();
		if (ret < 0) {
			printk("i2c_update_firmware_error.\n");
			msleep(200);
			i2c_transfer(g_client->adapter, &msg, 1);		/* out of bootloader mode */
			enable_irq(g_client->irq);
			return -1;
		}

		/* out of bootloader mode */
		msleep(200);
		msg.addr = g_client->addr;
		msg.flags = 0;
		msg.buf = out_bootloader_buffer;
		msg.len = 12;
		ret = i2c_transfer(g_client->adapter, &msg, 1);
		if (ret < 0) {
			printk("Out of bootloader mode error1.\n");
			return -1;
		}
		msleep(200);
		enable_irq(g_client->irq);
		ret = i2c_smbus_read_byte_data(g_client, 0x01);
		if ( 0 == (ret&0x10) ) {
			printk("Out of bootloader mode success.\n");
			msleep(5000);
			return 1;
		} else {
			printk("Out of bootloader mode error2.\n");
			return -1;
		}
	}
	return -1;
}
static ssize_t 
update_firmware_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
	int i;
	int ret = -1;
	int ret1;
	int *p = &i;

	printk("Update_firmware_store.\n");
#ifndef CONFIG_MELFAS_RESTORE_FIRMWARE
	if ((buf[0] == '2')&&(buf[1] == '\0')) {

		/* driver detect its device  */
		for (i = 0; i < 3; i++) {
			ret = i2c_smbus_read_byte_data(g_client, 0x00);
			if (ret >= 0) {
				goto firmware_find_device;
			}
		}
		printk("Dont find melfas_ts device\n");
		return -1;

firmware_find_device: 
		ret = i2c_smbus_read_byte_data(g_client, 0x21);			/* read firmware version */
		printk("%s: reg21 = 0x%x\n", __FUNCTION__, ret);
#else
	if (buf[0] == '2') {
#endif
		disable_irq(g_client->irq);
		free_irq(g_client->irq, ts);
		g_client->addr = MELFAS_UPDATE_FIRMWARE_MODE_ADDR;

		/*update firmware*/
		ret = i2c_update_firmware();

		ret1 = gpio_tlmm_config(GPIO_CFG(TS_INT_GPIO, 0, GPIO_INPUT, GPIO_PULL_UP, GPIO_2MA), GPIO_ENABLE);
		ret1 = gpio_configure(TS_INT_GPIO, GPIOF_INPUT | IRQF_TRIGGER_FALLING);
		mdelay(10);
		g_client->addr = 0x23;									/* touchscreen i2c addr */
		enable_irq(g_client->irq);
		ret1 = request_irq(g_client->irq, melfas_ts_irq_handler, 0, g_client->name, ts);
		if (0 != ret1)
		{
			printk("request irq failed!\n");
		}

		if( 0 != ret ){
			printk("Update firmware failed!\n\n");
		} else {
			printk("update firmware success!\n\n");
			mdelay(200);										/* for "printk" */
#ifdef CONFIG_MELFAS_RESTORE_FIRMWARE
			mdelay(8000);
#else
			arm_pm_restart(0,p);
#endif
		}
	}

	return ret;
 }

static int i2c_update_firmware(void)
{
	char *buf;
	struct file	*filp;
    struct inode *inode = NULL;
	mm_segment_t oldfs;
    uint16_t	length;
	int ret = 0;           //"/data/melfas_ts_update_firmware.bin";
	const char filename[]="/sdcard/update/melfas_ts_update_firmware.bin";

	/* open file */
    oldfs = get_fs();
    set_fs(KERNEL_DS);
    filp = filp_open(filename, O_RDONLY, S_IRUSR);
    if (IS_ERR(filp)) {
        printk("%s: file %s filp_open error\n", __FUNCTION__,filename);
        set_fs(oldfs);
        return -1;
    }

    if (!filp->f_op) {
        printk("%s: File Operation Method Error\n", __FUNCTION__);
        filp_close(filp, NULL);
        set_fs(oldfs);
        return -1;
    }

    inode = filp->f_path.dentry->d_inode;
    if (!inode) {
        printk("%s: Get inode from filp failed\n", __FUNCTION__);
        filp_close(filp, NULL);
        set_fs(oldfs);
        return -1;
    }
    printk("%s file offset opsition: %u\n", __FUNCTION__, (unsigned)filp->f_pos);

    /* file's size */
    length = i_size_read(inode->i_mapping->host);
   	printk("%s: length=%d\n", __FUNCTION__, length);
	if (!( length > 0 && length < MCSDL_MAX_FILE_LENGTH )){
		printk("file size error\n");
		filp_close(filp, NULL);
        set_fs(oldfs);
		return -1;
	}

	/* allocation buff size */
	buf = vmalloc((length+(length%2)));		/* buf size if even */
	if (!buf) {
		printk("alloctation memory failed\n");
		filp_close(filp, NULL);
        set_fs(oldfs);
		return -1;
	}
	if ( length%2 == 1 ) {
		buf[length] = 0xFF;						  		/* Fill Empty space */
	}

    /* read data */
    if (filp->f_op->read(filp, buf, length, &filp->f_pos) != length) {
        printk("%s: file read error\n", __FUNCTION__);
        filp_close(filp, NULL);
        set_fs(oldfs);
		vfree(buf);
        return -1;
    }

#ifndef CONFIG_MELFAS_RESTORE_FIRMWARE
	/* disable other I2C device */
	if (&TS_updateFW_gs_data->timer != NULL) {
		if (TS_updateFW_gs_data->use_irq) {
			disable_irq(TS_updateFW_gs_data->client->irq);
		} else {
			hrtimer_cancel(&TS_updateFW_gs_data->timer);
		}
		cancel_work_sync(&TS_updateFW_gs_data->work);
		mutex_lock(&TS_updateFW_gs_data->mlock);
		i2c_smbus_write_byte_data(TS_updateFW_gs_data->client, 0x20, 0);
		mutex_unlock(&TS_updateFW_gs_data->mlock);
		printk("hrtimer_cancel_GS\n");
	}
	if (&TS_updateFW_aps_data->timer != NULL) {
		hrtimer_cancel(&TS_updateFW_aps_data->timer);
		cancel_work_sync(&TS_updateFW_aps_data->work);
		if (TS_updateFW_aps_wq) {
			printk("destroy_aps_wq\n");
			destroy_workqueue(TS_updateFW_aps_wq);
		}
		mutex_lock(&TS_updateFW_aps_data->mlock);
		i2c_smbus_write_byte_data(TS_updateFW_aps_data->client, 0, 0);
		mutex_unlock(&TS_updateFW_aps_data->mlock);
		printk("hrtimer_cancel_APS\n");
	}
	mdelay(1000);
#endif

	ret = mcsdl_download(buf, length+(length%2));

 	filp_close(filp, NULL);
    set_fs(oldfs);
	vfree(buf);
	printk("%s: free file buffer\n", __FUNCTION__);
	return ret;
}