示例#1
0
static int AMI304_Report_Value(int en_dis)
{
	struct ami304_i2c_data *data = i2c_get_clientdata(ami304_i2c_client);
	char report_enable = 0;

	if( !en_dis )
		return 0;

	if(atomic_read(&o_status))
	{
		input_report_abs(data->input_dev, ABS_RX, ami304mid_data.yaw);	/* yaw */
		input_report_abs(data->input_dev, ABS_RY, ami304mid_data.pitch);/* pitch */
		input_report_abs(data->input_dev, ABS_RZ, ami304mid_data.roll);/* roll */
		input_report_abs(data->input_dev, ABS_RUDDER, ami304mid_data.mag_status);/* status of orientation sensor */
		report_enable = 1;
	}

	if(atomic_read(&a_status))
	{
		input_report_abs(data->input_dev, ABS_X, ami304mid_data.nax);/* x-axis raw acceleration */
		input_report_abs(data->input_dev, ABS_Y, ami304mid_data.nay);/* y-axis raw acceleration */
		input_report_abs(data->input_dev, ABS_Z, ami304mid_data.naz);/* z-axis raw acceleration */
		report_enable = 1;
	}

	if(atomic_read(&m_status))
	{
		input_report_abs(data->input_dev, ABS_HAT0X, ami304mid_data.nmx); /* x-axis of raw magnetic vector */
		input_report_abs(data->input_dev, ABS_HAT0Y, ami304mid_data.nmy); /* y-axis of raw magnetic vector */
		input_report_abs(data->input_dev, ABS_BRAKE, ami304mid_data.nmz); /* z-axis of raw magnetic vector */
		input_report_abs(data->input_dev, ABS_WHEEL, ami304mid_data.mag_status);/* status of magnetic sensor */
		report_enable = 1;
	}

	if (AMI304_DEBUG_DEV_DEBOUNCE & ami304_debug_mask)
	{
		AMID("yaw: %d, pitch: %d, roll: %d\n", ami304mid_data.yaw, ami304mid_data.pitch, ami304mid_data.roll);
		AMID("nax: %d, nay: %d, naz: %d\n", ami304mid_data.nax, ami304mid_data.nay, ami304mid_data.naz);
		AMID("nmx: %d, nmy: %d, nmz: %d\n", ami304mid_data.nmx, ami304mid_data.nmy, ami304mid_data.nmz);
		AMID("mag_status: %d\n", ami304mid_data.mag_status);
	}

	if(report_enable)
		input_sync(data->input_dev);

	return 0;
}
static void gtco_urb_callback(struct urb *urbinfo)
{
	struct gtco *device = urbinfo->context;
	struct input_dev  *inputdev;
	int               rc;
	u32               val = 0;
	s8                valsigned = 0;
	char              le_buffer[2];

	inputdev = device->inputdevice;

	
	if (urbinfo->status == -ECONNRESET ||
	    urbinfo->status == -ENOENT ||
	    urbinfo->status == -ESHUTDOWN) {

		
		return;
	}

	if (urbinfo->status != 0) {
		goto resubmit;
	}


	
	if (inputdev->id.product == PID_1000 ||
	    inputdev->id.product == PID_1001 ||
	    inputdev->id.product == PID_1002) {

		switch (device->buffer[0]) {
		case 5:
			
			val = ((u16)(device->buffer[8]) << 1);
			val |= (u16)(device->buffer[7] >> 7);
			input_report_abs(inputdev, ABS_PRESSURE,
					 device->buffer[8]);

			
			device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);

			
		case 4:
			

			
			if (device->buffer[6] & 0x40)
				device->buffer[6] |= 0x80;

			if (device->buffer[7] & 0x40)
				device->buffer[7] |= 0x80;


			valsigned = (device->buffer[6]);
			input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned);

			valsigned = (device->buffer[7]);
			input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned);

			
		case 2:
		case 3:
			
			val = (device->buffer[5]) & MASK_BUTTON;

			input_event(inputdev, EV_MSC, MSC_SERIAL, val);

			
		case 1:
			
			val = get_unaligned_le16(&device->buffer[1]);
			input_report_abs(inputdev, ABS_X, val);

			val = get_unaligned_le16(&device->buffer[3]);
			input_report_abs(inputdev, ABS_Y, val);

			
			val = device->buffer[5] & MASK_INRANGE ? 1 : 0;
			input_report_abs(inputdev, ABS_DISTANCE, val);

			
			
			if (device->buffer[0] == 1) {

				val = device->buffer[5] & MASK_BUTTON;
				dbg("======>>>>>>REPORT 1: val 0x%X(%d)",
				    val, val);

				input_event(inputdev, EV_MSC, MSC_SERIAL, val);
			}
			break;

		case 7:
			
			input_event(inputdev, EV_MSC, MSC_SCAN,
				    device->buffer[1]);
			break;
		}
	}

	
	if (inputdev->id.product == PID_400 ||
	    inputdev->id.product == PID_401) {

		
		if (device->buffer[0] == 2) {
			
			input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]);
		}

		
		if (device->buffer[0] == 1) {
			char buttonbyte;

			
			if (device->max_X > 0x10000) {

				val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]);
				val |= (u32)(((u8)device->buffer[3] & 0x1) << 16);

				input_report_abs(inputdev, ABS_X, val);

				le_buffer[0]  = (u8)((u8)(device->buffer[3]) >> 1);
				le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7);

				le_buffer[1]  = (u8)(device->buffer[4] >> 1);
				le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);

				val = get_unaligned_le16(le_buffer);
				input_report_abs(inputdev, ABS_Y, val);

				buttonbyte = device->buffer[5] >> 1;
			} else {
示例#3
0
int thread_fn() {
    if(enable_update == 1){
        // ksocket things
        struct timeval start, stop;  
        struct sockaddr_in addr_srv;
        int char_size = 21,rate = 50, recv_size,ctr = 0,thresh=1000;
        unsigned long cnt=0;
        char buf[char_size], *tmp, bufs[24];
        char extra[10];
        int addr_len,len,ax,ay,az,count,axs,ays,azs;
        unsigned long elapsed;
        //float adx, ady, adz;
        
        enable_count++;
        #ifdef KSOCKET_ADDR_SAFE
        mm_segment_t old_fs;
        old_fs = get_fs();
        set_fs(KERNEL_DS);
        #endif

        sprintf(current->comm, "ksockThrd");	
        /**buf = "Hello!";*/
        memset(&addr_srv, 0, sizeof(addr_srv));
        addr_srv.sin_family = AF_INET;
        addr_srv.sin_port = htons(port);
        addr_srv.sin_addr.s_addr = inet_addr("152.14.93.160");
        addr_len = sizeof(struct sockaddr_in);
        
        // Connect the socket
        ca->sockfd_globl = ksocket(AF_INET, SOCK_STREAM, 0);
        if (debug==1)
            printk("sockfd_cli = 0x%p\n", ca->sockfd_globl);
        if (ca->sockfd_globl == NULL){
            printk("socket failed\n");
            return -1;
        }
        if (kconnect(ca->sockfd_globl, (struct sockaddr*)&addr_srv, addr_len) < 0){
            printk("connect failed\n");
            return -1;
        } 

        tmp = inet_ntoa(addr_srv.sin_addr);
        if (debug==1)
            printk("connected to : %s %d\n", tmp, ntohs(addr_srv.sin_port));
        kfree(tmp);
        
        rate = ca->rate;
        len = sprintf(bufs, "%s%d%s%d", "03,ON,",10,",",10);
        if (debug==1)
            printk("Sending: %s\n",bufs);       
        ksend(ca->sockfd_globl, bufs, len, 0);
        memset(bufs,'\0',sizeof(bufs));
        ctr = thresh;  
        do_gettimeofday(&start);  
        while(1){            
            if(enable_update == 0){
                if (debug==1){
                    printk(KERN_INFO "thread1 break\n");
                    printk(KERN_ALERT "Closing accl socket now!\n\n");
                }
                //kclose(sockfd_cli);
                kclose(ca->sockfd_globl);
                #ifdef KSOCKET_ADDR_SAFE
                    set_fs(old_fs);
                #endif    
                break;
            }  
            memset(buf,'\0',sizeof(buf)); 
            //printk("1.buf:%s",buf);         
            if((recv_size = krecv(ca->sockfd_globl, buf, char_size, 0))>0){
                //printk("buf:%s",buf);
                //printk("bufs:%s\n",bufs);   
                count = sscanf(buf, "%d,%d,%d,%d,%d,%d!%s",&ax,&axs,&ay,&ays,&az,&azs,extra);
                //printk("recv_size:%d, count: %d\n",recv_size,count);                  
                //printk("ax:%d, axs:%d, ay:%d,ays:%d, az:%d, azs:%d, extra: %s\n", ax,axs,ay,ays,az,azs,extra);
                //Apply logic for sign
                if(axs==1)
                    ax *= -1;
                if(ays==1)
                    ay *= -1;
                if(azs==1)
                    az *= -1;                
                input_report_abs(cloudaccl_input_dev, ABS_X, ax);
                input_report_abs(cloudaccl_input_dev, ABS_Y, ay);
                input_report_abs(cloudaccl_input_dev, ABS_Z, az);
                input_sync(cloudaccl_input_dev); 
                accx = ax;
                accy = ay;
                accz = az;
                ctr--;
                cnt++;
                //printk(KERN_ALERT "Reported(%d)::ax:%d,ay:%d,az:%d\n", cnt,ax,ay,az);  
                if (ctr==0){
                    ctr=thresh;
                    do_gettimeofday(&stop);
                    elapsed = (stop.tv_sec-start.tv_sec)*1000000 + stop.tv_usec-start.tv_usec;
                    printk("Reported(%ld)::ax:%d,ay:%d,az:%d\n", cnt,ax,ay,az);
                    printk(KERN_ALERT "L:%d,%ld,%ld\n", enable_count,cnt,elapsed); 
                    do_gettimeofday(&start);  
                }
            
            }
            //schedule();
        }        
    }
    return 0;
}
static inline int bma250_report_data(struct driver_data *dd)
{
	int rc = 0;
	u8 rx_buf[8];
	char bypass = 0;
	int retrycount = 0;
	struct bma250_accel_data    data;
	struct bma250_platform_data *pdata = dd->ic_dev->dev.platform_data;

read_data_start:
	if (slave_hw)
		pdata->bypass_state(READ_BYPASS_STATE, &bypass);

	if (!slave_hw || !bypass) {
		/* Bypass mode */
		FIFO_ACCESS_MUTEX_LOCK();
		rc = bma250_ic_read(dd->ic_dev, BMA250_X_AXIS_LSB_REG,
			rx_buf, 7);
		FIFO_ACCESS_MUTEX_UNLOCK();
		if (rc) {
			if (retrycount > BMA250_READDATA_RETRY)
				goto report_error;
			else {
				retrycount++;
				msleep(BMA250_BYPASS_STABEL);
				goto read_data_start;
			}
		}
		/* 10bit signed to 16bit signed */
		data.accel_x = ((rx_buf[1] << 8) | (rx_buf[0] & 0xC0));
		data.accel_y = ((rx_buf[3] << 8) | (rx_buf[2] & 0xC0));
		data.accel_z = ((rx_buf[5] << 8) | (rx_buf[4] & 0xC0));

		/* sensitivty 0.5C, center temprature 24C */
		data.temp = (signed char)rx_buf[6] + 24*2;
	} else {
		/* Master mode */
		FIFO_ACCESS_MUTEX_LOCK();
		rc = pdata->read_axis_data(dd->ic_dev, &rx_buf[0], 6);
		FIFO_ACCESS_MUTEX_UNLOCK();
		if (rc) {
			if (retrycount > BMA250_READDATA_RETRY)
				goto report_error;
			else {
				retrycount++;
				msleep(BMA250_BYPASS_STABEL);
				goto read_data_start;
			}
		}
		/* 10bit signed to 16bit signed */
		data.accel_x = ((rx_buf[1] << 8) | (rx_buf[0] & 0xC0));
		data.accel_y = ((rx_buf[3] << 8) | (rx_buf[2] & 0xC0));
		data.accel_z = ((rx_buf[5] << 8) | (rx_buf[4] & 0xC0));
		/* set defaults value. */
		data.temp = 32*2;
	}

	/* sensitivty 256lsb/g for all g-ranges */
	data.accel_x = data.accel_x >> dd->shift;
	data.accel_y = data.accel_y >> dd->shift;
	data.accel_z = data.accel_z >> dd->shift;

	input_report_abs(dd->ip_dev, ABS_X, data.accel_x);
	input_report_abs(dd->ip_dev, ABS_Y, data.accel_y);
	input_report_abs(dd->ip_dev, ABS_Z, data.accel_z);
	input_report_abs(dd->ip_dev, ABS_MISC, data.temp);
	input_sync(dd->ip_dev);
	return rc;

report_error:
	printk(KERN_ERR "%s: Data read error from register.\n", __func__);
	return rc;
}
示例#5
0
static void gs_work_func(struct work_struct *work)
{
	
	int ret,i;
	struct gs_data *gs = container_of(work, struct gs_data, work);
	unsigned char dataX_low = 0;
	unsigned char dataX_high = 0;
	uint16        dataX = 0;
	unsigned char dataY_low = 0;
	unsigned char dataY_high = 0;
	uint16        dataY = 0;
	unsigned char dataZ_low = 0;
	unsigned char dataZ_high = 0;
	uint16        dataZ = 0;
	boolean data_is_err = 0;
	int x,y,z;
      

	uint8_t buf[6];
	uint8_t start_reg;
	struct i2c_msg msg[2];
	int	sesc = accel_delay/1000;
	int nsesc = (accel_delay%1000)*1000000;
	msg[0].addr = gs->client->addr;
	msg[0].flags = 0;
	msg[0].len = 1;
	msg[0].buf = &start_reg;
	start_reg = 0x32;

	msg[1].addr = gs->client->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len = sizeof(buf);
	msg[1].buf = buf;
#if 0
/**************************************************************************
ADI345X#8451849PHIL of PP1 phone  need set  offset, but ADI345B can't set offset value, 
if set the value will work MMITest fail
***************************************************************************/
	 ret = gs_set_offset();
	 if (ret < 0) {
		printk(KERN_ERR "gs_set_offset faild\n");
		/* fail? */
		goto restart_timer;
	}
#endif	 

	 ret =  reg_read(gs, GS_ADI_REG_INT_SOURCE); /* read IRQ STATUS */
	
	if (ret < 0) {
		printk(KERN_ERR "i2c_smbus_read_int status_0X30 failed\n");
		/* fail? */	
		goto restart_timer;
		
	}
	
	if((ret&0x20))//double tap
	{
//		printk(KERN_DEBUG"double tap\n");
		
	}	
	
	else if((ret&0x40))//sigle tap
	{
//		printk(KERN_DEBUG"sigle tap\n");
	}	
	
	else if((ret&0x80))
	{
	//printk(KERN_DEBUG"data ready\n");
		
	    for (i = 0; i < 10; i++) 
	    {
			ret = i2c_transfer(gs->client->adapter, msg, 2);
			if (ret < 0) 
			{
				printk(KERN_ERR "gs_ts_work_func: i2c_transfer failed\n");
				data_is_err = 1;
			}
			else
			{
				data_is_err = 0;
				break;
			}	
					 
		}
		
	
	}
	else
	{
		printk(KERN_ERR"data err\n");
		data_is_err = 1;
		
	} 
	dataX_low = msg[1].buf[0];
	dataX_high = msg[1].buf[1];
	dataY_low = msg[1].buf[2];
	dataY_high = msg[1].buf[3];
	dataZ_low  = msg[1].buf[4];
	dataZ_high = msg[1].buf[5];
	 

	if(!data_is_err)	
	{
	    dataX = ((dataX_high&0x1f) <<8) |dataX_low;
	    dataY = ((dataY_high&0x1f) <<8) |dataY_low;
	    dataZ = ((dataZ_high&0x1f) <<8) |dataZ_low;
		
		
		if(dataX&0x1000)/*负值*/
		{
			 x=dataX -8192;         /*13 bit is sign bit, */  
			 
		}
		else
		{
			x = dataX;
		}
			
		if(dataY&0x1000)/*负值*/
		{
			y=dataY - 8192;   /*13 bit is sign bit, */   
		}
		else
		{
                 	y = dataY;
		}
		
		if(dataZ&0x1000)/*负值*/
		{
			z =dataZ -8192;   /*13 bit is sign bit, */   
		}
		else
		{
		      z = dataZ;
		}

		/* change the x,y,z for u8300 because orientation of accelerometer of u8300 is different.*/
		//if(machine_is_msm7x25_u8300()) 
		{
			int x1,y1,z1;
			x1 = y * (-1);
			y1 = x * (-1);
			z1 = z * (-1);
			
			x = x1;
			y = y1;
			z = z1;
		}
		
		sensor_data[0] = (s16)x;
		sensor_data[1] = (s16)y;		
		sensor_data[2] = (s16)z;
		x = (MG_PER_SAMPLE * (s16)x)/FILTER_SAMPLE_NUMBER;	
		y = (MG_PER_SAMPLE * (s16)y)/FILTER_SAMPLE_NUMBER;
		z = (MG_PER_SAMPLE * (s16)z)/FILTER_SAMPLE_NUMBER;
		x *=(-1);
		input_report_abs(gs->input_dev, ABS_X, x);			
		input_report_abs(gs->input_dev, ABS_Y, y);			
		input_report_abs(gs->input_dev, ABS_Z, z);
		input_sync(gs->input_dev);
	}
	restart_timer:
	
	if (gs->use_irq)
		enable_irq(gs->client->irq);
	else
		hrtimer_start(&gs->timer, ktime_set(sesc, nsesc), HRTIMER_MODE_REL);
}
示例#6
0
static void xpad360_process_packet(struct usb_xpad *xpad,
				   u16 cmd, unsigned char *data)
{
	struct input_dev *dev = xpad->dev;

	/*
	 * Xbox 360 wireless controller will send many key events at
	 * the same time when pairing is done. Ignore them since they
	 * are unnecessary input events.
	 */
	if (xpad->xtype == XTYPE_XBOX360W && data[1] == 0xcc)
		return;

	/* digital pad */
	if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
		input_report_abs(dev, ABS_HAT0X,
				 !!(data[2] & 0x08) - !!(data[2] & 0x04));
		input_report_abs(dev, ABS_HAT0Y,
				 !!(data[2] & 0x02) - !!(data[2] & 0x01));
	} else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
		/* dpad as buttons (right, left, down, up) */
		input_report_key(dev, BTN_LEFT, data[2] & 0x04);
		input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
		input_report_key(dev, BTN_0, data[2] & 0x01);	/* up */
		input_report_key(dev, BTN_1, data[2] & 0x02);	/* down */
	}

	/* start/back buttons */
	input_report_key(dev, BTN_START,  data[2] & 0x10);
	input_report_key(dev, BTN_BACK,   data[2] & 0x20);

	/* stick press left/right */
	input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
	input_report_key(dev, BTN_THUMBR, data[2] & 0x80);

	/* buttons A,B,X,Y,TL,TR and MODE */
	input_report_key(dev, BTN_A,	data[3] & 0x10);
	input_report_key(dev, BTN_B,	data[3] & 0x20);
	input_report_key(dev, BTN_X,	data[3] & 0x40);
	input_report_key(dev, BTN_Y,	data[3] & 0x80);
	input_report_key(dev, BTN_TL,	data[3] & 0x01);
	input_report_key(dev, BTN_TR,	data[3] & 0x02);
	input_report_key(dev, BTN_MODE,	data[3] & 0x04);

	/* left stick */
	input_report_abs(dev, ABS_X,
			 (__s16) le16_to_cpup((__le16 *)(data + 6)));
	input_report_abs(dev, ABS_Y,
			 ~(__s16) le16_to_cpup((__le16 *)(data + 8)));

	/* right stick */
	input_report_abs(dev, ABS_RX,
			 (__s16) le16_to_cpup((__le16 *)(data + 10)));
	input_report_abs(dev, ABS_RY,
			 ~(__s16) le16_to_cpup((__le16 *)(data + 12)));

	/* triggers left/right */
	input_report_abs(dev, ABS_Z, data[4]);
	input_report_abs(dev, ABS_RZ, data[5]);

	input_sync(dev);
}
示例#7
0
文件: hdaps.c 项目: ealize/tp_smapi
/**
 * hdaps_set_power - enable or disable power to the accelerometer.
 * Returns zero on success and negative error code on failure.  Can sleep.
 */
static int hdaps_set_power(int on)
{
	struct thinkpad_ec_row args =
		{ .mask = 0x0003, .val = {0x14, on?0x01:0x00} };
	struct thinkpad_ec_row data = { .mask = 0x8000 };
	int ret = thinkpad_ec_read_row(&args, &data);
	if (ret)
		return ret;
	if (data.val[0xF] != 0x00)
		return -EIO;
	return 0;
}

/**
 * hdaps_set_ec_config - set accelerometer parameters.
 * @ec_rate: embedded controller sampling rate
 * @order: embedded controller running average filter order
 * (Normally we have @ec_rate = sampling_rate * oversampling_ratio.)
 * Returns zero on success and negative error code on failure.  Can sleep.
 */
static int hdaps_set_ec_config(int ec_rate, int order)
{
	struct thinkpad_ec_row args = { .mask = 0x000F,
		.val = {0x10, (u8)ec_rate, (u8)(ec_rate>>8), order} };
	struct thinkpad_ec_row data = { .mask = 0x8000 };
	int ret = thinkpad_ec_read_row(&args, &data);
	printk(KERN_DEBUG "hdaps: setting ec_rate=%d, filter_order=%d\n",
	       ec_rate, order);
	if (ret)
		return ret;
	if (data.val[0xF] == 0x03) {
		printk(KERN_WARNING "hdaps: config param out of range\n");
		return -EINVAL;
	}
	if (data.val[0xF] == 0x06) {
		printk(KERN_WARNING "hdaps: config change already pending\n");
		return -EBUSY;
	}
	if (data.val[0xF] != 0x00) {
		printk(KERN_WARNING "hdaps: config change error, ret=%d\n",
		      data.val[0xF]);
		return -EIO;
	}
	return 0;
}

/**
 * hdaps_get_ec_config - get accelerometer parameters.
 * @ec_rate: embedded controller sampling rate
 * @order: embedded controller running average filter order
 * Returns zero on success and negative error code on failure.  Can sleep.
 */
static int hdaps_get_ec_config(int *ec_rate, int *order)
{
	const struct thinkpad_ec_row args =
		{ .mask = 0x0003, .val = {0x17, 0x82} };
	struct thinkpad_ec_row data = { .mask = 0x801F };
	int ret = thinkpad_ec_read_row(&args, &data);
	if (ret)
		return ret;
	if (data.val[0xF] != 0x00)
		return -EIO;
	if (!(data.val[0x1] & 0x01))
		return -ENXIO; /* accelerometer polling not enabled */
	if (data.val[0x1] & 0x02)
		return -EBUSY; /* config change in progress, retry later */
	*ec_rate = data.val[0x2] | ((int)(data.val[0x3]) << 8);
	*order = data.val[0x4];
	return 0;
}

/**
 * hdaps_get_ec_mode - get EC accelerometer mode
 * Returns zero on success and negative error code on failure.  Can sleep.
 */
static int hdaps_get_ec_mode(u8 *mode)
{
	const struct thinkpad_ec_row args =
		{ .mask = 0x0001, .val = {0x13} };
	struct thinkpad_ec_row data = { .mask = 0x8002 };
	int ret = thinkpad_ec_read_row(&args, &data);
	if (ret)
		return ret;
	if (data.val[0xF] != 0x00) {
		printk(KERN_WARNING
		       "accelerometer not implemented (0x%02x)\n",
		       data.val[0xF]);
		return -EIO;
	}
	*mode = data.val[0x1];
	return 0;
}

/**
 * hdaps_check_ec - checks something about the EC.
 * Follows the clean-room spec for HDAPS; we don't know what it means.
 * Returns zero on success and negative error code on failure.  Can sleep.
 */
static int hdaps_check_ec(void)
{
	const struct thinkpad_ec_row args =
		{ .mask = 0x0003, .val = {0x17, 0x81} };
	struct thinkpad_ec_row data = { .mask = 0x800E };
	int ret = thinkpad_ec_read_row(&args, &data);
	if (ret)
		return  ret;
	if (!((data.val[0x1] == 0x00 && data.val[0x2] == 0x60) || /* cleanroom spec */
	      (data.val[0x1] == 0x01 && data.val[0x2] == 0x00)) || /* seen on T61 */
	    data.val[0x3] != 0x00 || data.val[0xF] != 0x00) {
		printk(KERN_WARNING
		       "hdaps_check_ec: bad response (0x%x,0x%x,0x%x,0x%x)\n",
		       data.val[0x1], data.val[0x2],
		       data.val[0x3], data.val[0xF]);
		return -EIO;
	}
	return 0;
}

/**
 * hdaps_device_init - initialize the accelerometer.
 *
 * Call several embedded controller functions to test and initialize the
 * accelerometer.
 * Returns zero on success and negative error code on failure. Can sleep.
 */
#define FAILED_INIT(msg) printk(KERN_ERR "hdaps init failed at: %s\n", msg)
static int hdaps_device_init(void)
{
	int ret;
	u8 mode;

	ret = thinkpad_ec_lock();
	if (ret)
		return ret;

	if (hdaps_get_ec_mode(&mode))
		{ FAILED_INIT("hdaps_get_ec_mode failed"); goto bad; }

	printk(KERN_DEBUG "hdaps: initial mode latch is 0x%02x\n", mode);
	if (mode == 0x00)
		{ FAILED_INIT("accelerometer not available"); goto bad; }

	if (hdaps_check_ec())
		{ FAILED_INIT("hdaps_check_ec failed"); goto bad; }

	if (hdaps_set_power(1))
		{ FAILED_INIT("hdaps_set_power failed"); goto bad; }

	if (hdaps_set_ec_config(sampling_rate*oversampling_ratio,
				running_avg_filter_order))
		{ FAILED_INIT("hdaps_set_ec_config failed"); goto bad; }

	thinkpad_ec_invalidate();
	udelay(200);

	/* Just prefetch instead of reading, to avoid ~1sec delay on load */
	ret = thinkpad_ec_prefetch_row(&ec_accel_args);
	if (ret)
		{ FAILED_INIT("initial prefetch failed"); goto bad; }
	goto good;
bad:
	thinkpad_ec_invalidate();
	ret = -ENXIO;
good:
	stale_readout = 1;
	thinkpad_ec_unlock();
	return ret;
}

/**
 * hdaps_device_shutdown - power off the accelerometer
 * Returns nonzero on failure. Can sleep.
 */
static int hdaps_device_shutdown(void)
{
	int ret;
	ret = hdaps_set_power(0);
	if (ret) {
		printk(KERN_WARNING "hdaps: cannot power off\n");
		return ret;
	}
	ret = hdaps_set_ec_config(0, 1);
	if (ret)
		printk(KERN_WARNING "hdaps: cannot stop EC sampling\n");
	return ret;
}

/* Device model stuff */

static int hdaps_probe(struct platform_device *dev)
{
	int ret;

	ret = hdaps_device_init();
	if (ret)
		return ret;

	printk(KERN_INFO "hdaps: device successfully initialized.\n");
	return 0;
}

static int hdaps_suspend(struct platform_device *dev, pm_message_t state)
{
	/* Don't do hdaps polls until resume re-initializes the sensor. */
	del_timer_sync(&hdaps_timer);
	hdaps_device_shutdown(); /* ignore errors, effect is negligible */
	return 0;
}

static int hdaps_resume(struct platform_device *dev)
{
	int ret = hdaps_device_init();
	if (ret)
		return ret;

	mutex_lock(&hdaps_users_mtx);
	if (hdaps_users)
		mod_timer(&hdaps_timer, jiffies + HZ/sampling_rate);
	mutex_unlock(&hdaps_users_mtx);
	return 0;
}

static struct platform_driver hdaps_driver = {
	.probe = hdaps_probe,
	.suspend = hdaps_suspend,
	.resume = hdaps_resume,
	.driver	= {
		.name = "hdaps",
		.owner = THIS_MODULE,
	},
};

/**
 * hdaps_calibrate - set our "resting" values.
 * Does its own locking.
 */
static void hdaps_calibrate(void)
{
	needs_calibration = 1;
	hdaps_update();
	/* If that fails, the mousedev poll will take care of things later. */
}

/* Timer handler for updating the input device. Runs in softirq context,
 * so avoid lenghty or blocking operations.
 */
static void hdaps_mousedev_poll(unsigned long unused)
{
	int ret;

	stale_readout = 1;

	/* Cannot sleep.  Try nonblockingly.  If we fail, try again later. */
	if (thinkpad_ec_try_lock())
		goto keep_active;

	ret = __hdaps_update(1); /* fast update, we're in softirq context */
	thinkpad_ec_unlock();
	/* Any of "successful", "not yet ready" and "not prefetched"? */
	if (ret != 0 && ret != -EBUSY && ret != -ENODATA) {
		printk(KERN_ERR
		       "hdaps: poll failed, disabling updates\n");
		return;
	}

keep_active:
	/* Even if we failed now, pos_x,y may have been updated earlier: */
	input_report_abs(hdaps_idev, ABS_X, pos_x - rest_x);
	input_report_abs(hdaps_idev, ABS_Y, pos_y - rest_y);
	input_sync(hdaps_idev);
	input_report_abs(hdaps_idev_raw, ABS_X, pos_x);
	input_report_abs(hdaps_idev_raw, ABS_Y, pos_y);
	input_sync(hdaps_idev_raw);
	mod_timer(&hdaps_timer, jiffies + HZ/sampling_rate);
}


/* Sysfs Files */

static ssize_t hdaps_position_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	int ret = hdaps_update();
	if (ret)
		return ret;
	return sprintf(buf, "(%d,%d)\n", pos_x, pos_y);
}
static ssize_t proximity_enable_store(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t size)
{
	struct cm36686_data *cm36686 = dev_get_drvdata(dev);
	bool new_value;

	if (sysfs_streq(buf, "1"))
		new_value = true;
	else if (sysfs_streq(buf, "0"))
		new_value = false;
	else {
		pr_err("%s: invalid value %d\n", __func__, *buf);
		return -EINVAL;
	}

	mutex_lock(&cm36686->power_lock);
	pr_info("%s, new_value = %d\n", __func__, new_value);
	if (new_value && !(cm36686->power_state & PROXIMITY_ENABLED)) {
		u8 val = 1;
		int i;
	int err = 0;

		cm36686->power_state |= PROXIMITY_ENABLED;

		if (cm36686->pdata->cm36686_led_on) {
			cm36686->pdata->cm36686_led_on(true);
			msleep(20);
		}
#ifdef CM36686_CANCELATION
		/* open cancelation data */
		err = proximity_open_cancelation(cm36686);
		if (err < 0 && err != -ENOENT)
			pr_err("%s: proximity_open_cancelation() failed\n",
				__func__);
#endif
		/* enable settings */
		for (i = 0; i < PS_REG_NUM; i++) {
			cm36686_i2c_write_word(cm36686,
				ps_reg_init_setting[i][REG_ADDR],
				ps_reg_init_setting[i][CMD]);
		}

		val = gpio_get_value(cm36686->pdata->irq);
		/* 0 is close, 1 is far */
		input_report_abs(cm36686->proximity_input_dev,
			ABS_DISTANCE, val);
		input_sync(cm36686->proximity_input_dev);

		enable_irq(cm36686->irq);
		enable_irq_wake(cm36686->irq);
	} else if (!new_value && (cm36686->power_state & PROXIMITY_ENABLED)) {
		cm36686->power_state &= ~PROXIMITY_ENABLED;

		disable_irq_wake(cm36686->irq);
		disable_irq(cm36686->irq);
		/* disable settings */
		cm36686_i2c_write_word(cm36686, REG_PS_CONF1, 0x0001);

		if (cm36686->pdata->cm36686_led_on)
			cm36686->pdata->cm36686_led_on(false);
	}
	mutex_unlock(&cm36686->power_lock);
	return size;
}
示例#9
0
static void ucb1400_ts_event_release(struct input_dev *idev)
{
	input_report_abs(idev, ABS_PRESSURE, 0);
	input_report_key(idev, BTN_TOUCH, 0);
	input_sync(idev);
}
static ssize_t proximity_enable_store(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t size)
{
	struct gp2a_data *gp2a = dev_get_drvdata(dev);
	bool new_value;
	u8 value;
	int ret;
#ifdef GP2AP002X_PROXIMITY_OFFSET
	int err;
#endif

	if (sysfs_streq(buf, "1")) {
		new_value = true;
	} else if (sysfs_streq(buf, "0")) {
		new_value = false;
	} else {
		pr_err("%s: invalid value %d\n", __func__, *buf);
		return -EINVAL;
	}

	mutex_lock(&gp2a->power_lock);
	gp2a_dbgmsg("new_value = %d, old state = %d\n",
		    new_value,
		    (gp2a->power_state & PROXIMITY_ENABLED) ? 1 : 0);
#ifdef ALPS_DEBUG
	pr_info("[TMP] new_value = %d, old state = %d\n",
			new_value,
			(gp2a->power_state & PROXIMITY_ENABLED) ? 1 : 0);
#endif
	if (new_value && !(gp2a->power_state & PROXIMITY_ENABLED)) {
		pr_info("[TMP] %s, %d\n", __func__, __LINE__);
#if defined(CONFIG_MACH_AMAZING_CDMA)
		LED_onoff(1);
#endif
#ifdef GP2AP002X_PROXIMITY_OFFSET
		err = gp2a_cal_mode_read_file(&gp2a->cal_mode);
		if (err < 0 && err != -ENOENT)
			pr_err("%s: cal_mode file read fail\n", __func__);

		pr_info("%s: mode = %02x\n", __func__, gp2a->cal_mode);
		if (gp2a->cal_mode == 2) {
			nondetect = PROX_NONDETECT_MODE2;
			detect = PROX_DETECT_MODE2;
		} else if (gp2a->cal_mode == 1) {
			nondetect = PROX_NONDETECT_MODE1;
			detect = PROX_DETECT_MODE1;
		} else {
			nondetect = PROX_NONDETECT;
			detect = PROX_DETECT;
		}
#endif
		gp2a->val_state = 1;
		input_report_abs(gp2a->proximity_input_dev,
			ABS_DISTANCE,
			gp2a->val_state);
		input_sync(gp2a->proximity_input_dev);

		gp2a->power_state |= PROXIMITY_ENABLED;
		gp2a->pdata->power(true);
		msleep(20);

		value = 0x18;
		gp2a_i2c_write(gp2a, REGS_CON, &value);
#if defined(CONFIG_MACH_KYLE)
		value = 0x00;
#else
		value = 0x08;
#endif
		gp2a_i2c_write(gp2a, REGS_GAIN, &value);
		value = nondetect;
		gp2a_i2c_write(gp2a, REGS_HYS, &value);
		value = 0x04;
		gp2a_i2c_write(gp2a, REGS_CYCLE, &value);

		#if defined(CONFIG_MACH_GEIM)
			enable_irq_wake(gp2a->irq);
		#else
			enable_irq_wake(gp2a->irq);
		#endif
		value = 0x03;
		ret = gp2a_i2c_write(gp2a, REGS_OPMOD, &value);
		pr_info("%s: ret = %d\n", __func__, ret);
		enable_irq(gp2a->irq);
		value = 0x00;
		ret = gp2a_i2c_write(gp2a, REGS_CON, &value);
		pr_info("%s: ret = %d\n", __func__, ret);
	} else if (!new_value && (gp2a->power_state & PROXIMITY_ENABLED)) {
		pr_info("[TMP] %s, %d\n", __func__, __LINE__);
#if defined(CONFIG_MACH_AMAZING_CDMA)
		LED_onoff(0);
#endif
		#if defined(CONFIG_MACH_GEIM)
			disable_irq_wake(gp2a->irq);
		#else
			disable_irq_wake(gp2a->irq);
		#endif
		disable_irq(gp2a->irq);
		value = 0x02;
		gp2a_i2c_write(gp2a, REGS_OPMOD, &value);
		gp2a->power_state &= ~PROXIMITY_ENABLED;
		gp2a->pdata->power(false);
	}
	mutex_unlock(&gp2a->power_lock);
	return size;
}
static int gp2a_i2c_probe(struct i2c_client *client,
			  const struct i2c_device_id *id)
{
	int ret = -ENODEV;
	struct input_dev *input_dev;
	struct gp2a_data *gp2a;
	struct gp2a_platform_data *pdata = client->dev.platform_data;
	pr_info("[TMP] %s, %d\n", __func__, __LINE__);

	nondetect = PROX_NONDETECT;
	detect = PROX_DETECT;
/*#else
	if (board_hw_revision >= 0x07) {
		nondetect = PROX_REV_07_NONDETECT;
		detect = PROX_REV_07_DETECT;
	} else {
		nondetect = PROX_REV_06_NONDETECT;
		detect = PROX_REV_06_DETECT;
	}
#endif*/
	pr_info("%s: %02x %02x\n", __func__, nondetect, detect);
	if (!pdata) {
		pr_err("%s: missing pdata!\n", __func__);
		return ret;
	}

	if (!pdata->power) {
		pr_err("%s: incomplete pdata!\n", __func__);
		return ret;
	}

	/* power on gp2a */
	pdata->power(true);

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		pr_err("%s: i2c functionality check failed!\n", __func__);
		return ret;
	}

	gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL);
	if (!gp2a) {
		pr_err("%s: failed to alloc memory for module data\n",
		       __func__);
		return -ENOMEM;
	}

	gp2a->pdata = pdata;
	gp2a->i2c_client = client;
	i2c_set_clientdata(client, gp2a);

	/* wake lock init */
	wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND,
		       "prx_wake_lock");
	mutex_init(&gp2a->power_lock);

	/* allocate proximity input_device */
	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		goto err_input_allocate_device_proximity;
	}
	input_dev->name = "proximity_sensor";
	ret = input_register_device(input_dev);
	if (ret < 0) {
		pr_err("%s: could not register input device\n",
			__func__);
		input_free_device(input_dev);
		goto err_input_allocate_device_proximity;
	}

	gp2a->proximity_input_dev = input_dev;
	input_set_drvdata(input_dev, gp2a);
	input_set_capability(input_dev, EV_ABS, ABS_DISTANCE);
	input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0);

	ret = sysfs_create_group(&input_dev->dev.kobj,
				 &proximity_attribute_group);

	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_proximity;
	}

	/* the timer just fires off a work queue request.  we need a thread
	   to read the i2c (can be slow and blocking). */
	INIT_WORK(&gp2a->work_prox, gp2a_prox_work_func);
	ret = gp2a_setup_irq(gp2a);

	if (ret) {
		pr_err("%s: could not setup irq\n", __func__);
		goto err_setup_irq;
	}

	ret = sensors_register(gp2a->proximity_dev, gp2a,
		proxi_attrs, "proximity_sensor");
	if (ret < 0) {
		pr_info("%s: could not sensors_register\n", __func__);
		goto exit_gp2a_sensors_register;
	}

#ifdef CONFIG_SENSOR_USE_SYMLINK
	ret =  sensors_initialize_symlink(gp2a->proximity_input_dev);
	if (ret) {
		pr_err("%s: cound not make proximity sensor symlink(%d).\n",
			__func__, ret);
		goto exit_sensors_initialize_symlink;
	}
#endif

	/* set initial proximity value as 1 */
	input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1);
	input_sync(gp2a->proximity_input_dev);

	pr_info("[TMP] %s, %d\n", __func__, __LINE__);

	pdata->power(false);
	goto done;

	/* error, unwind it all */
#ifdef CONFIG_SENSOR_USE_SYMLINK
exit_sensors_initialize_symlink:
#endif
exit_gp2a_sensors_register:
	free_irq(gp2a->irq, gp2a);
	gpio_free(gp2a->pdata->p_out);
err_setup_irq:
	pr_info("err_setup_irq\n");
	sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj,
			   &proximity_attribute_group);
err_sysfs_create_group_proximity:
	pr_info("err_sysfs_create_group_proximity\n");
	input_unregister_device(gp2a->proximity_input_dev);
err_input_allocate_device_proximity:
	pr_info("err_input_allocate_device_proximity\n");
	mutex_destroy(&gp2a->power_lock);
	wake_lock_destroy(&gp2a->prx_wake_lock);
	kfree(gp2a);
done:
	pr_info("done\n");
	return ret;
}
int wacom_i2c_coord(struct wacom_i2c *wac_i2c)
{
	bool prox = false;
	int ret = 0;
	u8 *data;
	int rubber, stylus;
	static u16 x, y, pressure;
	static u16 tmp;
	int rdy = 0;

#ifdef WACOM_IRQ_WORK_AROUND
	cancel_delayed_work(&wac_i2c->pendct_dwork);
#endif

	data = wac_i2c->wac_feature->data;
	ret = i2c_master_recv(wac_i2c->client, data, COM_COORD_NUM);

	if (ret < 0) {
		printk(KERN_ERR "[E-PEN] %s failed to read i2c.L%d\n", __func__,
		       __LINE__);
		return -1;
	}
#if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
	pr_debug("[E-PEN] %x, %x, %x, %x, %x, %x, %x\n",
		 data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
#endif
	if (data[0] & 0x80) {
		/* enable emr device */
		if (!wac_i2c->pen_prox) {

			wac_i2c->pen_prox = 1;

			if (data[0] & 0x40)
				wac_i2c->tool = BTN_TOOL_RUBBER;
			else
				wac_i2c->tool = BTN_TOOL_PEN;
#if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
			pr_debug("[E-PEN] is in(%d)\n", wac_i2c->tool);
#endif
		}

		prox = !!(data[0] & 0x10);
		stylus = !!(data[0] & 0x20);
		rubber = !!(data[0] & 0x40);
		rdy = !!(data[0] & 0x80);

		x = ((u16) data[1] << 8) + (u16) data[2];
		y = ((u16) data[3] << 8) + (u16) data[4];
		pressure = ((u16) data[5] << 8) + (u16) data[6];

#ifdef WACOM_IMPORT_FW_ALGO
		/* Change Position to Active Area */
		if (x <= origin_offset[0])
			x = 0;
		else
			x = x - origin_offset[0];
		if (y <= origin_offset[1])
			y = 0;
		else
			y = y - origin_offset[1];
#ifdef COOR_WORK_AROUND
		wacom_i2c_coord_offset(&x, &y);
		wacom_i2c_coord_average(&x, &y, rdy);
#endif
#endif

		if (wac_i2c->wac_pdata->x_invert)
			x = wac_i2c->wac_feature->x_max - x;
		if (wac_i2c->wac_pdata->y_invert)
			y = wac_i2c->wac_feature->y_max - y;

		if (wac_i2c->wac_pdata->xy_switch) {
			tmp = x;
			x = y;
			y = tmp;
		}
#ifdef COOR_WORK_AROUND
		/* Add offset */
		x = x + tilt_offsetX[user_hand][screen_rotate];
		y = y + tilt_offsetY[user_hand][screen_rotate];
#endif
		if (wacom_i2c_coord_range(&x, &y)) {
			input_report_abs(wac_i2c->input_dev, ABS_X, x);
			input_report_abs(wac_i2c->input_dev, ABS_Y, y);
			input_report_abs(wac_i2c->input_dev,
					 ABS_PRESSURE, pressure);
			input_report_key(wac_i2c->input_dev,
					 BTN_STYLUS, stylus);
			input_report_key(wac_i2c->input_dev, BTN_TOUCH, prox);
			input_report_key(wac_i2c->input_dev, wac_i2c->tool, 1);
			input_sync(wac_i2c->input_dev);

			if (prox && !wac_i2c->pen_pressed) {
#ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK
				set_dvfs_lock(wac_i2c, true);
#endif
#if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
				printk(KERN_DEBUG
				       "[E-PEN] is pressed(%d,%d,%d)(%d)\n",
				       x, y, pressure, wac_i2c->tool);
#else
				printk(KERN_DEBUG "[E-PEN] pressed\n");
#endif

			} else if (!prox && wac_i2c->pen_pressed) {
#ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK
				set_dvfs_lock(wac_i2c, false);
#endif
#if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
				printk(KERN_DEBUG
				       "[E-PEN] is released(%d,%d,%d)(%d)\n",
				       x, y, pressure, wac_i2c->tool);
#else
				printk(KERN_DEBUG "[E-PEN] released\n");
#endif
			}

			wac_i2c->pen_pressed = prox;

			if (stylus && !wac_i2c->side_pressed)
				printk(KERN_DEBUG "[E-PEN] side on\n");
			else if (!stylus && wac_i2c->side_pressed)
				printk(KERN_DEBUG "[E-PEN] side off\n");

			wac_i2c->side_pressed = stylus;
		}
#if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
		else
			printk(KERN_DEBUG "[E-PEN] raw data x=0x%x, y=0x%x\n",
			x, y);
#endif
	} else {

#ifdef WACOM_IRQ_WORK_AROUND
		if (!gpio_get_value(wac_i2c->wac_pdata->gpio_pendct)) {
			x = ((u16) data[1] << 8) + (u16) data[2];
			y = ((u16) data[3] << 8) + (u16) data[4];

			if (data[0] & 0x40)
				wac_i2c->tool = BTN_TOOL_RUBBER;
			else
				wac_i2c->tool = BTN_TOOL_PEN;

			input_report_abs(wac_i2c->input_dev, ABS_X, x);
			input_report_abs(wac_i2c->input_dev, ABS_Y, y);
			input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0);
			input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0);
			input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0);
			input_report_key(wac_i2c->input_dev, wac_i2c->tool, 1);
			input_sync(wac_i2c->input_dev);
		}

		schedule_delayed_work(&wac_i2c->pendct_dwork, HZ / 10);

		return 0;
#else				/* WACOM_IRQ_WORK_AROUND */
#ifdef COOR_WORK_AROUND
		/* enable emr device */
		wacom_i2c_coord_average(0, 0, 0);
#endif

#ifdef WACOM_PDCT_WORK_AROUND
		if (wac_i2c->pen_pdct == PDCT_DETECT_PEN)
			forced_hover(wac_i2c);
		else
#endif
		if (wac_i2c->pen_prox) {
			/* input_report_abs(wac->input_dev,
			   ABS_X, x); */
			/* input_report_abs(wac->input_dev,
			   ABS_Y, y); */

			input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0);
			input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0);
			input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0);
#if defined(WACOM_PDCT_WORK_AROUND)
			input_report_key(wac_i2c->input_dev,
				BTN_TOOL_RUBBER, 0);
			input_report_key(wac_i2c->input_dev, BTN_TOOL_PEN, 0);
#else
			input_report_key(wac_i2c->input_dev, wac_i2c->tool, 0);
#endif
			input_sync(wac_i2c->input_dev);

			printk(KERN_DEBUG "[E-PEN] is out");
		}
		wac_i2c->pen_prox = 0;
		wac_i2c->pen_pressed = 0;
		wac_i2c->side_pressed = 0;

#ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK
		set_dvfs_lock(wac_i2c, false);
#endif
#endif
	}

	return 0;
}
示例#13
0
static void tm1726_send_event(struct tm1726 *tm)
{
	struct input_dev	*input = tm->input;
	u8			i, fingers, finger_state[MAX_FINGERS];
	static int		prev_touch = 0;
	static int		curr_touch = 0;
	int			event = 0;

	finger_state[0] = tm->reg_data[TM_FINGER_STATE1] & 0x03;
	finger_state[1] = (tm->reg_data[TM_FINGER_STATE1] & 0x0c) >> 2;
	finger_state[2] = (tm->reg_data[TM_FINGER_STATE1] & 0x30) >> 4;
	finger_state[3] = (tm->reg_data[TM_FINGER_STATE1] & 0xc0) >> 6;
	finger_state[4] = tm->reg_data[TM_FINGER_STATE2] & 0x03;

	curr_touch = 0;
	for (i = 0; i < MAX_FINGERS; i++) {
		if (finger_state[i] == 1 || finger_state[i] == 2) {
			curr_touch++;
		}
	}

	/* Button Pressed */
	if (!prev_touch && curr_touch) {
		input_report_abs(input, BTN_TOUCH, curr_touch);
		TM1726_DEBUG("Finger Pressed\n");
	}

	/* Button Released */
	if (prev_touch && !curr_touch) {
		event = 1;
		input_report_abs(input, ABS_PRESSURE, 0);
		input_report_abs(input, BTN_TOUCH, 0);
		input_report_abs(input, ABS_MT_TOUCH_MAJOR, 0);
		input_mt_sync(input);
		TM1726_DEBUG("Finger Released\n\n\n");
	}

	fingers = 0;
	for (i = 0; i < MAX_FINGERS; i++) {
		if (finger_state[i] == 1 || finger_state[i] == 2) {
			u8	xh, xl, yh, yl;
			u32	x, y;

			fingers++;

			xh	= tm->reg_data[TM_X1_HIGH + 5 * i];
			xl	= tm->reg_data[TM_XY1_LOW + 5 * i] & 0x0f;
			yh	= tm->reg_data[TM_Y1_HIGH + 5 * i];
			yl	= (tm->reg_data[TM_XY1_LOW + 5 * i] & 0xf0) >> 4;
			x	= (xh << 4) | xl;
			y	= (yh << 4) | yl;
			TM1726_DEBUG("Finger%d Raw: (%d, %d)\n", fingers, x, y);

			if (x < tm->fix.x_min) {
				x = tm->fix.x_min;
			}
			if (x > tm->fix.x_max) {
				x = tm->fix.x_max;
			}
			if (y < tm->fix.y_min) {
				y = tm->fix.y_min;
			}
			if (y > tm->fix.y_max) {
				y = tm->fix.y_max;
			}

			if (tm->fix.x_invert) {
				x = tm->fix.x_max - x + tm->fix.x_min;
			}

			if (tm->fix.y_invert) {
				y = tm->fix.y_max - y + tm->fix.y_min;
			}

			event	= 1;
			if (fingers == 1) {
				input_report_abs(input, ABS_PRESSURE, MAX_Z);
				input_report_abs(input, ABS_X, x);
				input_report_abs(input, ABS_Y, y);
			}

			input_report_abs(input, ABS_MT_TOUCH_MAJOR, MAX_Z);
			input_report_abs(input, ABS_MT_POSITION_X, x);
			input_report_abs(input, ABS_MT_POSITION_Y, y);
			input_mt_sync(input);
			TM1726_DEBUG("Finger%d Calibrated: (%d, %d)\n", fingers, x, y);
		}
	}
示例#14
0
static void hil_dev_handle_ptr_events(struct hil_dev *ptr)
{
	struct input_dev *dev = ptr->dev;
	int idx = ptr->idx4 / 4;
	hil_packet p = ptr->data[idx - 1];
	int i, cnt, laxis;
	bool absdev, ax16;

	if ((p & HIL_CMDCT_POL) != idx - 1) {
//		printk(KERN_WARNING PREFIX
;
		return;
	}

	i = (p & HIL_POL_AXIS_ALT) ? 3 : 0;
	laxis = (p & HIL_POL_NUM_AXES_MASK) + i;

	ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;

	for (cnt = 1; i < laxis; i++) {
		unsigned int lo, hi, val;

		lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK;
		hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0;

		if (absdev) {
			val = lo + (hi << 8);
#ifdef TABLET_AUTOADJUST
			if (val < input_abs_get_min(dev, ABS_X + i))
				input_abs_set_min(dev, ABS_X + i, val);
			if (val > input_abs_get_max(dev, ABS_X + i))
				input_abs_set_max(dev, ABS_X + i, val);
#endif
			if (i % 3)
				val = input_abs_get_max(dev, ABS_X + i) - val;
			input_report_abs(dev, ABS_X + i, val);
		} else {
			val = (int) (((int8_t) lo) | ((int8_t) hi << 8));
			if (i % 3)
				val *= -1;
			input_report_rel(dev, REL_X + i, val);
		}
	}

	while (cnt < idx - 1) {
		unsigned int btn = ptr->data[cnt++];
		int up = btn & 1;

		btn &= 0xfe;
		if (btn == 0x8e)
			continue; /* TODO: proximity == touch? */
		if (btn > 0x8c || btn < 0x80)
			continue;
		btn = (btn - 0x80) >> 1;
		btn = ptr->btnmap[btn];
		input_report_key(dev, btn, !up);
	}

	input_sync(dev);
}
示例#15
0
/*******************************************************	
功能:
	触摸屏工作函数
	由中断触发,接受1组坐标数据,校验后再分析输出
参数:
	ts:	client私有数据结构体
return:
	执行结果码,0表示正常执行
********************************************************/
static void goodix_ts_work_func(struct work_struct *work)
{	
	static uint8_t finger_bit=0;	//last time fingers' state
	struct point_data * p = NULL;
	uint8_t read_position = 0;
	uint8_t point_data[READ_BYTES_NUM]={ 0 };
	uint8_t finger=0;				//record which finger is changed
	uint8_t check_sum = 0;
	int ret = -1; 
	int count = 0;

	struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work);

	if (ts->use_shutdown && gpio_get_value(ts->gpio_shutdown))
		goto NO_ACTION;					//The data is invalid.

	//if i2c-transfer is failed, let it restart less than 10 times. FOR DEBUG.
	/*
	if( ts->retry > 9) {
		if(!ts->use_irq && (ts->timer.state != HRTIMER_STATE_INACTIVE))		
			hrtimer_cancel(&ts->timer);
		dev_info(&(ts->client->dev), "Because of transfer error, %s stop working.\n",s3c_ts_name);
		ts->bad_data = 1;
		return ;
	}
	*/
	ret=i2c_read_bytes(ts->client, point_data, sizeof(point_data));
	if(ret <= 0)	
	{
		dev_dbg(&(ts->client->dev),"I2C transfer error. ERROR Number:%d\n ", ret);
		ts->retry++;
		if(ts->power)
		{
			ts->power(ts, 0);
			ts->power(ts, 1);
		}
		else
		{
			goodix_init_panel(ts);
			msleep(260);
		}
		goto XFER_ERROR;
	}	
	
	//如果能够保证在INT中断后及时的读取坐标数据,可以不进行校验
	if(!ts->use_irq)	
	{
		switch(point_data[1]& 0x1f)
		{
		case 0:
			break;
		case 1:
			for(count=1; count<8; count++)
				check_sum += (int)point_data[count];
			read_position = 8;
			break;
		case 2:
		case 3:
			for(count=1; count<13;count++)
				check_sum += (int)point_data[count];
			read_position = 13;
			break;	
		default:		//(point_data[1]& 0x1f) > 3
			for(count=1; count<34;count++)
				check_sum += (int)point_data[count];
			read_position = 34;
		}
		if(check_sum != point_data[read_position])
			goto XFER_ERROR;
	}
	//The bits indicate which fingers pressed down
	point_data[1]&=0x1f;
	finger = finger_bit^point_data[1];
	if(finger == 0 && point_data[1] == 0)			
		goto NO_ACTION;						//no fingers and no action
	else if(finger == 0)						//the same as last time
		goto BIT_NO_CHANGE;
	
	//check which point(s) DOWN or UP
	analyse_points(&finger_list, finger_bit, finger);

	if(finger_list.head == NULL)
		goto NO_ACTION;
	else
		dev_dbg(&ts->client->dev, "fingers count:%d\n", finger_list.length);

BIT_NO_CHANGE:
	for(p = finger_list.head; p != NULL; p = p->next)
	{	
		if(p->state == FLAG_UP)
		{
			p->x = p->y = 0;
			p->pressure = 0;
			continue;
		}
		
		if(p->id < 3)
			read_position = p->id*5+3;
		else
			read_position = 29;

		
		if(p->id != 3)
		{
			p->x = (unsigned int) (point_data[read_position]<<8) + (unsigned int)( point_data[read_position+1]);
			p->y = (unsigned int)(point_data[read_position+2]<<8) + (unsigned int) (point_data[read_position+3]);
			p->pressure = point_data[read_position+4];
		}
		
		#if MAX_FINGER_NUM > 3
		else 
		{
			p->x = (unsigned int) (point_data[18]<<8) + (unsigned int)( point_data[25]);
			p->y = (unsigned int)(point_data[26]<<8) + (unsigned int) (point_data[27]);
			p->pressure = point_data[28];
		}
		#endif

		// 将触摸屏的坐标映射到LCD坐标上. 触摸屏短边为X轴,LCD坐标一般长边为X轴,可能需要调整原点位置
		p->x = (TOUCH_MAX_WIDTH - p->x)*SCREEN_MAX_WIDTH/TOUCH_MAX_WIDTH;//y
		if (board_version == 0){
			p->y =  p->y*SCREEN_MAX_HEIGHT/TOUCH_MAX_HEIGHT;//x

		} else if (board_version == 1) {
			p->y = (TOUCH_MAX_HEIGHT - p->y)*SCREEN_MAX_HEIGHT/TOUCH_MAX_HEIGHT;//x
		}
		swap(p->x, p->y); 
	}

#ifndef GOODIX_MULTI_TOUCH	
		if(finger_list.head->state == FLAG_DOWN)
		{
			input_report_abs(ts->input_dev, ABS_X, finger_list.head->x);
			input_report_abs(ts->input_dev, ABS_Y, finger_list.head.y);	
		} 
		input_report_abs(ts->input_dev, ABS_PRESSURE, finger_list.head->pressure);
		input_report_key(ts->input_dev, BTN_TOUCH, finger_list.head->state);   
#else

	/* ABS_MT_TOUCH_MAJOR is used as ABS_MT_PRESSURE in android. */
	for(p = finger_list.head; p != NULL; p = p->next)
	{
		if(p->state == FLAG_DOWN)
		{
			input_report_abs(ts->input_dev, ABS_MT_POSITION_X, p->x);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, p->y);
		} 
		//input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, p->id);
		input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, p->pressure);
		input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, p->pressure);
		//printk("ID:%d.\n", p->id);
		input_mt_sync(ts->input_dev);	
	}

#endif
	input_sync(ts->input_dev);

	delete_points(&finger_list);
	finger_bit = point_data[1]&0x1f;	//restore last presse state.

XFER_ERROR:	
NO_ACTION:
	if(ts->use_irq)
		enable_irq(ts->client->irq);

}
示例#16
0
static void xpad360_process_packet(struct usb_xpad *xpad,
				   u16 cmd, unsigned char *data)
{
	struct input_dev *dev = xpad->dev;

	/* digital pad */
	if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
		/* dpad as buttons (left, right, up, down) */
		input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04);
		input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08);
		input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01);
		input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02);
	} else {
		input_report_abs(dev, ABS_HAT0X,
				 !!(data[2] & 0x08) - !!(data[2] & 0x04));
		input_report_abs(dev, ABS_HAT0Y,
				 !!(data[2] & 0x02) - !!(data[2] & 0x01));
	}

	/* start/back buttons */
	input_report_key(dev, BTN_START,  data[2] & 0x10);
	input_report_key(dev, BTN_SELECT, data[2] & 0x20);

	/* stick press left/right */
	input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
	input_report_key(dev, BTN_THUMBR, data[2] & 0x80);

	/* buttons A,B,X,Y,TL,TR and MODE */
	input_report_key(dev, BTN_A,	data[3] & 0x10);
	input_report_key(dev, BTN_B,	data[3] & 0x20);
	input_report_key(dev, BTN_X,	data[3] & 0x40);
	input_report_key(dev, BTN_Y,	data[3] & 0x80);
	input_report_key(dev, BTN_TL,	data[3] & 0x01);
	input_report_key(dev, BTN_TR,	data[3] & 0x02);
	input_report_key(dev, BTN_MODE,	data[3] & 0x04);

	if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
		/* left stick */
		input_report_abs(dev, ABS_X,
				 (__s16) le16_to_cpup((__le16 *)(data + 6)));
		input_report_abs(dev, ABS_Y,
				 ~(__s16) le16_to_cpup((__le16 *)(data + 8)));

		/* right stick */
		input_report_abs(dev, ABS_RX,
				 (__s16) le16_to_cpup((__le16 *)(data + 10)));
		input_report_abs(dev, ABS_RY,
				 ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
	}

	/* triggers left/right */
	if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
		input_report_key(dev, BTN_TL2, data[4]);
		input_report_key(dev, BTN_TR2, data[5]);
	} else {
		input_report_abs(dev, ABS_Z, data[4]);
		input_report_abs(dev, ABS_RZ, data[5]);
	}

	input_sync(dev);
}
示例#17
0
static void change_sensor_delay(struct ssp_data *data,
	int iSensorType, int64_t dNewDelay)
{
	u8 uBuf[2];
	unsigned int uNewEnable = 0;
	int64_t dTempDelay = data->adDelayBuf[iSensorType];

	if (!(atomic_read(&data->aSensorEnable) & (1 << iSensorType))) {
		data->aiCheckStatus[iSensorType] = NO_SENSOR_STATE;
		return;
	}

	data->adDelayBuf[iSensorType] = dNewDelay;

	if (iSensorType == ORIENTATION_SENSOR)
		iSensorType = ACCELEROMETER_SENSOR;

	switch (data->aiCheckStatus[iSensorType]) {
	case ADD_SENSOR_STATE:
		ssp_dbg("[SSP]: %s - add %u, New = %lldns\n",
			 __func__, 1 << iSensorType, dNewDelay);

		uBuf[1] = (u8)get_msdelay(dNewDelay);
		uBuf[0] = (u8)get_delay_cmd(uBuf[1]);

		if (send_instruction(data, ADD_SENSOR, iSensorType, uBuf, 2)
			!= SUCCESS) {
			uNewEnable =
				(unsigned int)atomic_read(&data->aSensorEnable)
				& (~(unsigned int)(1 << iSensorType));
			atomic_set(&data->aSensorEnable, uNewEnable);

			data->aiCheckStatus[iSensorType] = NO_SENSOR_STATE;
			data->uMissSensorCnt++;
			break;
		}

		data->aiCheckStatus[iSensorType] = RUNNING_SENSOR_STATE;

		if (iSensorType == PROXIMITY_SENSOR) {
			proximity_open_lcd_ldi(data);
			proximity_open_calibration(data);

			input_report_abs(data->prox_input_dev, ABS_DISTANCE, 1);
			input_sync(data->prox_input_dev);
		}
		break;
	case RUNNING_SENSOR_STATE:
		if (get_msdelay(dTempDelay)
			== get_msdelay(data->adDelayBuf[iSensorType]))
			break;

		ssp_dbg("[SSP]: %s - Change %u, New = %lldns\n",
			__func__, 1 << iSensorType, dNewDelay);

		uBuf[1] = (u8)get_msdelay(dNewDelay);
		uBuf[0] = (u8)get_delay_cmd(uBuf[1]);
		send_instruction(data, CHANGE_DELAY, iSensorType, uBuf, 2);

		break;
	default:
		break;
	}
}
示例#18
0
/**
 * stkxxx_work() - work queue handler (initiated by the interrupt handler)
 * @work:      work queue to handle
 */
static void stkxxx_work(struct work_struct *work)
{
#ifdef TS_DELAY_WORK
    struct stkxxx *ts = container_of(to_delayed_work(work), struct stkxxx, work);
#else
    struct stkxxx *ts = container_of(work, struct stkxxx, work);
#endif
    struct ts_event *event;
    int i;

    if (stkxxx_get_pendown_state(ts)) {
        if (stkxxx_read_sensor(ts) < 0) {
            printk(KERN_INFO "work read i2c failed\n");
            goto restart;
        }
        event = &ts->event[0];
        if (!ts->pendown) {
            ts->pendown = 1;
            //input_report_key(ts->input, BTN_TOUCH, 1);
            printk(KERN_INFO "DOWN\n");
        }

        for (i=0; i<ts->touching_num; i++) {
            input_report_abs(ts->input, ABS_MT_TRACKING_ID, i);
            #ifdef STKXXX_DEBUG
            printk(KERN_INFO "ABS_MT_TRACKING_ID = %d\n", i);
            #endif
            input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 1);
            #ifdef STKXXX_DEBUG
            printk(KERN_INFO "ABS_MT_TOUCH_MAJOR = %d\n", 1);
            #endif
            input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 0);
            #ifdef STKXXX_DEBUG
            printk(KERN_INFO "ABS_MT_WIDTH_MAJOR = %d\n", 0);
            #endif
            input_report_abs(ts->input, ABS_MT_POSITION_X, event->x);
            #ifdef STKXXX_DEBUG
            printk(KERN_INFO "ABS_MT_POSITION_X = %d\n", event->x);
            #endif
            input_report_abs(ts->input, ABS_MT_POSITION_Y, event->y);
            #ifdef STKXXX_DEBUG
            printk(KERN_INFO "ABS_MT_POSITION_Y = %d\n", event->y);
            #endif
            input_mt_sync(ts->input);
            #ifdef STKXXX_DEBUG
            printk(KERN_INFO "input_mt_sync\n");
            #endif
            event++;
        }
        input_sync(ts->input);
        #ifdef STKXXX_DEBUG
        printk(KERN_INFO "input_sync\n");
        #endif
restart:
#ifdef TS_DELAY_WORK
        schedule_delayed_work(&ts->work, msecs_to_jiffies(TS_POLL_PERIOD));
#else
        hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_MODE_REL);
#endif
    }

    else {
        /* enable IRQ after the pen was lifted */
        if (ts->pendown) {
            ts->pendown = 0;
            input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 0);
            input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 0);
            input_mt_sync(ts->input);
            input_sync(ts->input);
            printk(KERN_INFO "UP\n");
        }
        ts->touching_num = 0;
        ts->pre_touching_num = 0;
        enable_irq(ts->client->irq);
    }
}
static void gt801_ts_work_func(struct work_struct *work)
{
#if  SINGLTOUCH_MODE
  
#else
	int  touch_state_index = 0;
#endif

	unsigned char start_reg = 0x02;
    unsigned char buf[TOUCH_NUMBER*TOUCH_REG_NUM];
	unsigned short x;
	unsigned short y;
    int i,ret;
	int syn_flag = 0;
	int bufLen = TOUCH_NUMBER*TOUCH_REG_NUM;

    struct gt801_ts_data *ts = container_of(work, struct gt801_ts_data, work);
	
	gt801printk("%s\n",__FUNCTION__);
    
	ret=gt801_read_regs(ts->client, start_reg, buf,bufLen);
	if (ret < 0) {
	  	printk("%s:i2c_transfer fail =%d\n",__FUNCTION__,ret);
		if (ts->use_irq) 
   	  		enable_irq(ts->client->irq);
		
		return;
    }
	       
#if  SINGLTOUCH_MODE 
	i = 0;
	if(buf[i+ptpressure] == 0)
	{
		gt801printk(" realse ts_dev->point.x=%d ,ts_dev->point.y=%d \n",ts->point.x,ts->point.y);

		if (touch_state[i] == TOUCH_DOWN)
		{
			input_report_key(ts->input_dev,BTN_TOUCH,0);
			syn_flag = 1;
			touch_state[i] = TOUCH_UP;
			gt801printk("SINGLTOUCH_MODE up\n");
		}
	}
	else
	{
		x = ((( ((unsigned short)buf[i+ptxh] )<< 8) ) | buf[i+ptxl]);
		y= (((((unsigned short)buf[i+ptyh] )<< 8) )| buf[i+ptyl]);	
		
		if (ts->swap_xy)
			swap(x, y);
		
		if (verify_coord(ts,&x,&y))
			goto out;
		
		if (touch_state[i] == TOUCH_UP)
		{
			gt801printk("SINGLTOUCH_MODE down\n");
			input_report_key(ts->input_dev,BTN_TOUCH,1);
			touch_state[i] = TOUCH_DOWN;
		}
		
		gt801printk("input_report_abs(%d/%d)\n",x,y);
		input_report_abs(ts->input_dev,ABS_X,x );
		input_report_abs(ts->input_dev,ABS_Y,y );
		syn_flag = 1;
	}

#else   

    for(i=0; i<bufLen; i+=TOUCH_REG_NUM)
	{
		if(buf[i+ptpressure] == 0){
			gt801printk("%s:buf=%d touch up\n",__FUNCTION__,buf[i+ptpressure]);
			if (touch_state[touch_state_index] == TOUCH_DOWN)
			{
				gt801printk("%s:%d touch up\n",__FUNCTION__,i);
				input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); //Finger Size
				input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); //Touch Size
				input_mt_sync(ts->input_dev);
				syn_flag =1;
				touch_state[touch_state_index] = TOUCH_UP;
			}	  
		}
		else{
			x = ((( ((unsigned short)buf[i+ptxh] )<< 8) ) | buf[i+ptxl]);
			y = (((((unsigned short)buf[i+ptyh] )<< 8) )| buf[i+ptyl]);
			/* adjust the x and y to proper value  added by [email protected]*/
			x = 480-x;
			if(y < 800){
				y = 800-y;
			}

			if (ts->swap_xy){
				swap(x, y);
			}
			
			if (verify_coord(ts,&x,&y));//goto out;
			
			gt801printk("input_report_abs--%d-%d-(%d/%d)\n", i,touch_state_index, x, y);	
			input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1); //Finger Size
			input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
			input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 5); //Touch Size
			input_mt_sync(ts->input_dev);
			syn_flag = 1;
			touch_state[touch_state_index] = TOUCH_DOWN;
		}
		
		touch_state_index++;
    }
	
#endif

	if(syn_flag){
		input_sync(ts->input_dev);
	}

out:
   	if (ts->use_irq) {
   		enable_irq(ts->client->irq);
   	}
	return;
}
static int AMI306_Report_Value(int iEnable)
{
	int controlbuf[AMI306_CB_LENGTH];
	struct ami306_i2c_data *data = i2c_get_clientdata(ami306_i2c_client);
	int report_enable = 0;

	if( !iEnable )
		return -1;

	read_lock(&ami306mid_data.ctrllock);
	memcpy(controlbuf, &ami306mid_data.controldata[0], sizeof(controlbuf));
	read_unlock(&ami306mid_data.ctrllock);			

	if(controlbuf[AMI306_CB_ACTIVESENSORS] & AMIT_BIT_ACCELEROMETER) {
		input_report_abs(data->input_dev, ABS_X, ami306mid_data.na.x);/* x-axis raw acceleration */
		input_report_abs(data->input_dev, ABS_Y, ami306mid_data.na.y);/* y-axis raw acceleration */
		input_report_abs(data->input_dev, ABS_Z, ami306mid_data.na.z);/* z-axis raw acceleration */
		report_enable = 1;
	}

	if(controlbuf[AMI306_CB_ACTIVESENSORS] & AMIT_BIT_MAGNETIC_FIELD) {
		input_report_abs(data->input_dev, ABS_HAT0X, ami306mid_data.nm.x); /* x-axis of raw magnetic vector */
		input_report_abs(data->input_dev, ABS_HAT0Y, ami306mid_data.nm.y); /* y-axis of raw magnetic vector */
		input_report_abs(data->input_dev, ABS_BRAKE, ami306mid_data.nm.z); /* z-axis of raw magnetic vector */
		input_report_abs(data->input_dev, ABS_WHEEL, ami306mid_data.status);/* status of magnetic sensor */
		report_enable = 1;
	}

	if(controlbuf[AMI306_CB_ACTIVESENSORS] & AMIT_BIT_ORIENTATION) {
		input_report_abs(data->input_dev, ABS_RX, ami306mid_data.yaw);	/* yaw */
		input_report_abs(data->input_dev, ABS_RY, ami306mid_data.pitch);/* pitch */
		input_report_abs(data->input_dev, ABS_RZ, ami306mid_data.roll);/* roll */
		input_report_abs(data->input_dev, ABS_RUDDER, ami306mid_data.status);/* status of orientation sensor */
		report_enable = 1;
	}

#if 0
	if(controlbuf[AMI306_CB_ACTIVESENSORS] & AMIT_BIT_GYROSCOPE) {
		input_report_abs(data->input_dev, ABS_HAT1X, ami306mid_data.gyro.x);/* x-axis of gyro sensor */
		input_report_abs(data->input_dev, ABS_HAT1Y, ami306mid_data.gyro.y);/* y-axis of gyro sensor */
		input_report_abs(data->input_dev, ABS_THROTTLE, ami306mid_data.gyro.z);/* z-axis of gyro sensor */
		report_enable = 1;
	}
#endif
		

	if (AMI306_DEBUG_DEV_DEBOUNCE & ami306_debug_mask) {
		AMID("yaw: %d, pitch: %d, roll: %d\n", ami306mid_data.yaw, ami306mid_data.pitch, ami306mid_data.roll);
		AMID("nax: %d, nay: %d, naz: %d\n", ami306mid_data.na.x, ami306mid_data.na.y, ami306mid_data.na.z);
		AMID("nmx: %d, nmy: %d, nmz: %d\n", ami306mid_data.nm.x, ami306mid_data.nm.y, ami306mid_data.nm.z);
		AMID("mag_status: %d\n", ami306mid_data.status);

	}

	if (report_enable)
		input_sync(data->input_dev);

	return 0;
}
示例#21
0
/*
 * This function translates the native event packets to linux input event
 * packets. Some packets coming from serial are not touchscreen related. In
 * this case we send them off to be processed elsewhere.
 */
static void h3600ts_process_packet(struct h3600_dev *ts)
{
    struct input_dev *dev = ts->dev;
    static int touched = 0;
    int key, down = 0;

    switch (ts->event) {
    /*
       Buttons - returned as a single byte
    	7 6 5 4 3 2 1 0
    	S x x x N N N N

       S       switch state ( 0=pressed 1=released)
       x       Unused.
       NNNN    switch number 0-15

       Note: This is true for non interrupt generated key events.
    */
    case KEYBD_ID:
        down = (ts->buf[0] & 0x80) ? 0 : 1;

        switch (ts->buf[0] & 0x7f) {
        case H3600_SCANCODE_RECORD:
            key = KEY_RECORD;
            break;
        case H3600_SCANCODE_CALENDAR:
            key = KEY_PROG1;
            break;
        case H3600_SCANCODE_CONTACTS:
            key = KEY_PROG2;
            break;
        case H3600_SCANCODE_Q:
            key = KEY_Q;
            break;
        case H3600_SCANCODE_START:
            key = KEY_PROG3;
            break;
        case H3600_SCANCODE_UP:
            key = KEY_UP;
            break;
        case H3600_SCANCODE_RIGHT:
            key = KEY_RIGHT;
            break;
        case H3600_SCANCODE_LEFT:
            key = KEY_LEFT;
            break;
        case H3600_SCANCODE_DOWN:
            key = KEY_DOWN;
            break;
        default:
            key = 0;
        }
        if (key)
            input_report_key(dev, key, down);
        break;
    /*
     * Native touchscreen event data is formatted as shown below:-
     *
     *      +-------+-------+-------+-------+
     *      | Xmsb  | Xlsb  | Ymsb  | Ylsb  |
     *      +-------+-------+-------+-------+
     *       byte 0    1       2       3
     */
    case TOUCHS_ID:
        if (!touched) {
            input_report_key(dev, BTN_TOUCH, 1);
            touched = 1;
        }

        if (ts->len) {
            unsigned short x, y;

            x = ts->buf[0];
            x <<= 8;
            x += ts->buf[1];
            y = ts->buf[2];
            y <<= 8;
            y += ts->buf[3];

            input_report_abs(dev, ABS_X, x);
            input_report_abs(dev, ABS_Y, y);
        } else {
            input_report_key(dev, BTN_TOUCH, 0);
            touched = 0;
        }
        break;
    default:
        /* Send a non input event elsewhere */
        break;
    }

    input_sync(dev);
}
示例#22
0
static void gp2a_work_func_light(struct work_struct *work)
{
	struct sensor_data *data = container_of((struct delayed_work *)work,
							struct sensor_data, work);
	
	int adc=0;
	state_type level_state = LIGHT_INIT;
    int lux = 0;
    static int old_lux = 0;

	/* read adc data from s5p110 */
	adc = lightsensor_get_adcvalue();

	if(adc >= 1643)//(adc >= 1050)
	{
		level_state = LIGHT_LEVEL5;
		buffering = 5;
	}

	else if(adc >= 1576 && adc < 1643)//(adc >= 800 && adc < 1050)
	{
		if(buffering == 5)
		{	
			level_state = LIGHT_LEVEL5;
			buffering = 5;
		}
		else if((buffering == 1)||(buffering == 2)||(buffering == 3)||(buffering == 4))
		{
			level_state = LIGHT_LEVEL4;
			buffering = 4;
		}
	}

	else if(adc >= 1159 && adc < 1576)//(adc >= 750 && adc < 800)
	{
		level_state = LIGHT_LEVEL4;
		buffering = 4;
	}

	else if(adc >= 1104 && adc < 1159)//(adc >= 560 && adc < 750)
	{
		if((buffering == 4)||(buffering == 5))
		{	
			level_state = LIGHT_LEVEL4;
			buffering = 4;
		}
		else if((buffering == 1)||(buffering == 2)||(buffering == 3))
		{
			level_state = LIGHT_LEVEL3;
			buffering = 3;
		}
	}
	
	else if(adc >= 462 && adc < 1104)//(adc >= 550 && adc < 560)
	{
		level_state = LIGHT_LEVEL3;
		buffering = 3;
	}

	else if(adc >= 430 && adc < 462)//(adc >= 370 && adc < 550)
	{
		if((buffering == 3)||(buffering == 4)||(buffering == 5))
		{	
			level_state = LIGHT_LEVEL3;
			buffering = 3;
		}
		else if((buffering == 1)||(buffering == 2))
		{
			level_state = LIGHT_LEVEL2;
			buffering = 2;
		}
	}

	else if(adc >= 94 && adc < 430)//(adc >= 270 && adc < 370)
	{
		level_state = LIGHT_LEVEL2;
		buffering = 2;
	}
	
	else if(adc >= 86 && adc < 94)//(adc >= 200 && adc < 270)
	{
		if((buffering == 2)||(buffering == 3)||(buffering == 4)||(buffering == 5))
		{	
			level_state = LIGHT_LEVEL2;
			buffering = 2;
		}
		else if(buffering == 1)
		{
			level_state = LIGHT_LEVEL1;
			buffering = 1;
		}
	}

	else if(adc < 86)//(adc < 200)
	{
		level_state = LIGHT_LEVEL1;
		buffering = 1;
	}

    cur_state = level_state;	

#ifdef MDNIE_TUNINGMODE_FOR_BACKLIGHT
	if(autobrightness_mode)
	{
		if((pre_val!=1)&&(current_gamma_value == 24)&&(level_state == LIGHT_LEVEL5)&&(current_mDNIe_UI == mDNIe_UI_MODE))
			{
			mDNIe_Mode_set_for_backlight(pmDNIe_Gamma_set[1]);
			pre_val = 1;
			gprintk("mDNIe_Mode_set_for_backlight - pmDNIe_Gamma_set[1]\n" );
		}	
	}
#endif

    lux = StateToLux(cur_state);

	data->light_data= cur_adc_value;

    if(data->testmode == 1)
    {
        input_report_abs(this_data, ABS_Y, adc);
    	input_sync(this_data);
    	//gprintk("testmode : adc(%d), lux(%d), cur_state(%d) \n", adc, lux, cur_state);
    }
    else
    {
      if(old_lux != lux)
      {
        old_lux = lux;
      	input_report_abs(this_data, ABS_X, lux);
    	input_sync(this_data);
        gprintk("realmode : adc(%d), lux(%d), cur_state(%d) \n", adc, lux, cur_state);
      }
    }

	schedule_delayed_work(&data->work, msecs_to_jiffies(data->delay));
}
示例#23
0
static void atp_complete(struct urb* urb, struct pt_regs* regs)
{
	int x, y, x_z, y_z, x_f, y_f;
	int retval, i, j;
	struct atp *dev = urb->context;

	switch (urb->status) {
	case 0:
		/* success */
		break;
	case -EOVERFLOW:
		if(!dev->overflowwarn) {
			printk("appletouch: OVERFLOW with data "
				"length %d, actual length is %d\n",
				dev->datalen, dev->urb->actual_length);
			dev->overflowwarn = 1;
		}
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		/* This urb is terminated, clean up */
		dbg("%s - urb shutting down with status: %d",
		    __FUNCTION__, urb->status);
		return;
	default:
		dbg("%s - nonzero urb status received: %d",
		    __FUNCTION__, urb->status);
		goto exit;
	}

	/* drop incomplete datasets */
	if (dev->urb->actual_length != dev->datalen) {
		dprintk("appletouch: incomplete data package"
			" (first byte: %d, length: %d).\n",
			dev->data[0], dev->urb->actual_length);
		goto exit;
	}

	/* reorder the sensors values */
	if (atp_is_geyser_3(dev)) {
		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));

		/*
		 * The values are laid out like this:
		 * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
		 * '-' is an unused value.
		 */

		/* read X values */
		for (i = 0, j = 19; i < 20; i += 2, j += 3) {
			dev->xy_cur[i] = dev->data[j + 1];
			dev->xy_cur[i + 1] = dev->data[j + 2];
		}
		/* read Y values */
		for (i = 0, j = 1; i < 9; i += 2, j += 3) {
			dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
			dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
		}
	} else if (atp_is_geyser_2(dev)) {
		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));

		/*
		 * The values are laid out like this:
		 * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ...
		 * '-' is an unused value.
		 */

		/* read X values */
		for (i = 0, j = 19; i < 20; i += 2, j += 3) {
			dev->xy_cur[i] = dev->data[j];
			dev->xy_cur[i + 1] = dev->data[j + 1];
		}

		/* read Y values */
		for (i = 0, j = 1; i < 9; i += 2, j += 3) {
			dev->xy_cur[ATP_XSENSORS + i] = dev->data[j];
			dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1];
		}
	} else {
		for (i = 0; i < 8; i++) {
			/* X values */
			dev->xy_cur[i     ] = dev->data[5 * i +  2];
			dev->xy_cur[i +  8] = dev->data[5 * i +  4];
			dev->xy_cur[i + 16] = dev->data[5 * i + 42];
			if (i < 2)
				dev->xy_cur[i + 24] = dev->data[5 * i + 44];

			/* Y values */
			dev->xy_cur[i + 26] = dev->data[5 * i +  1];
			dev->xy_cur[i + 34] = dev->data[5 * i +  3];
		}
	}

	dbg_dump("sample", dev->xy_cur);

	if (!dev->valid) {
		/* first sample */
		dev->valid = 1;
		dev->x_old = dev->y_old = -1;
		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));

		if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
			goto exit;

		/* 17" Powerbooks have extra X sensors */
		for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
			if (!dev->xy_cur[i]) continue;

			printk("appletouch: 17\" model detected.\n");
			if(atp_is_geyser_2(dev))
				input_set_abs_params(dev->input, ABS_X, 0,
						     (20 - 1) *
						     ATP_XFACT - 1,
						     ATP_FUZZ, 0);
			else
				input_set_abs_params(dev->input, ABS_X, 0,
						     (ATP_XSENSORS - 1) *
						     ATP_XFACT - 1,
						     ATP_FUZZ, 0);

			break;
		}

		goto exit;
	}

	for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
		/* accumulate the change */
		signed char change = dev->xy_old[i] - dev->xy_cur[i];
		dev->xy_acc[i] -= change;

		/* prevent down drifting */
		if (dev->xy_acc[i] < 0)
			dev->xy_acc[i] = 0;
	}

	memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));

	dbg_dump("accumulator", dev->xy_acc);

	x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
			      ATP_XFACT, &x_z, &x_f);
	y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
			      ATP_YFACT, &y_z, &y_f);

	if (x && y) {
		if (dev->x_old != -1) {
			x = (dev->x_old * 3 + x) >> 2;
			y = (dev->y_old * 3 + y) >> 2;
			dev->x_old = x;
			dev->y_old = y;

			if (debug > 1)
				printk("appletouch: X: %3d Y: %3d "
				       "Xz: %3d Yz: %3d\n",
				       x, y, x_z, y_z);

			input_report_key(dev->input, BTN_TOUCH, 1);
			input_report_abs(dev->input, ABS_X, x);
			input_report_abs(dev->input, ABS_Y, y);
			input_report_abs(dev->input, ABS_PRESSURE,
					 min(ATP_PRESSURE, x_z + y_z));
			atp_report_fingers(dev->input, max(x_f, y_f));
		}
		dev->x_old = x;
		dev->y_old = y;
	}
示例#24
0
static void cypress_ts_work_func(struct work_struct *work)
{
    int ret = 0;
    int retry = 20;
    int finger2=0;
    int x1 = 0, y1 = 0, flick_direction = 0, report_direction = 0, gesture = 0, pressure = 0, pinch_value = 0,x2 = 0, y2 = 0;
    uint8_t buf[15];
    struct cypress_ts_data *ts = container_of(work, struct cypress_ts_data, work);
    //ret = cypress_i2c_read(ts->client, 0x00, buf, 14);
    //ZTE_XUKE_CRDB00517999,BEGIN
    while (retry-- > 0)
    {
    	ret = cypress_i2c_read(ts->client, 0x00, buf, 14);    /* go to sleep */
      //printk("wly2: %d,%d, %x\n", ret, retry,buf[0]); 
	    if (ret >= 0)
    	  break;	
    	msleep(10);
    }
    //ZTE_XUKE_CRDB00517999,END
    //ZTE_WLY_CRDB00512790,BEGIN
    if (ret < 0)
		{
        printk(KERN_ERR "cypress_ts_work_func: cypress_i2c_read failed, go to poweroff.\n");
        gpio_direction_output(GPIO_TOUCH_EN_OUT, 0);
        msleep(200);
        gpio_direction_output(GPIO_TOUCH_EN_OUT, 1);
        msleep(200);
   	}
    buf[14] =0;
    //ZTE_WLY_CRDB00512790,END
    if (0 == firmware_version)firmware_version = buf[12];
		//printk("cypress_ts_work_func,buf[0] =%d\n", buf[0]);
		/*ZTE_TOUCH_WLY_006, @2010-04-14,begin*/
    if(buf[0] == 0x80)
		  cypress_i2c_write(ts->client, 0x0b, 0x80);
    else  
    	pressure = 255;

    x1=buf[2] | (uint16_t)(buf[1] & 0x03) << 8; 
	  y1=buf[4] | (uint16_t)(buf[3] & 0x03) << 8; 
    x2=buf[6] | (uint16_t)(buf[5] & 0x03) << 8; 
    y2=buf[8] | (uint16_t)(buf[7] & 0x03) << 8;
	if(buf[0] == 0x82) 
		finger2=1;

#ifdef TOUCHSCREEN_DUPLICATED_FILTER
	ret = duplicated_filter(ts, x1,y1,x2,y2, finger2, pressure);
	if (ret == 0) 
	{
					/* printk("%s: duplicated_filter\n", __func__); */

#endif

		if (((buf[0] == 0x81)&&(x1 == x2)&&(y1 == y2))||finger2 ||(pressure == 0))
		{
			input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, pressure);
			input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 10);			
			input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x1);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y1);

			input_mt_sync(ts->input_dev);
		}
		if(finger2)
		{
			input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, pressure);
			input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 10);			
			input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x2);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y2);
			input_mt_sync(ts->input_dev);
		}
		input_sync(ts->input_dev);
		
#ifdef TOUCHSCREEN_DUPLICATED_FILTER
	}	
#endif	
		
		/*ZTE_TOUCH_WLY_006, @2010-04-14,end*/
		#ifdef CYPRESS_GESTURE//ZTE_TOUCH_ZT_002
    if(buf[14])
    {
        flick_direction = buf[9];
	 			gesture = buf[13];
	 			cypress_i2c_write(ts->client, 0x0e, 0);
    }
   	// ZTE_PINCH_WLY_001,BEGIN
		//if(( 0x48 == buf[9])||( 0x49 == buf[9]))pinch_value = buf[9];
		if( 0x48 == buf[9])pinch_value = PINCH_VALUE;
		if( 0x49 == buf[9])pinch_value = -PINCH_VALUE;
	  // ZTE_PINCH_WLY_001,END
		/*ZTE_TOUCH_WLY_006, @2010-04-14,begin*/
		//printk("wly : pinch_value= %d, pressure=%d\n", buf[9],pressure);
    report_direction = judge_flick_direction(flick_direction);
    /*input_report_abs(ts->input_dev, EVENT_FLICK, report_direction);
    input_report_abs(ts->input_dev, EVENT_SINGLE_CLICK, (gesture & SINGLE_CLICK));
    input_report_abs(ts->input_dev, EVENT_EARLY_TAP, (gesture & EARLY_TAP) >> 3);
    input_report_abs(ts->input_dev, EVENT_TAP_HOLD, (gesture & TAP_AND_HOLD) >> 1);
    input_report_abs(ts->input_dev, EVENT_PRESS, (gesture & PRESS) >> 5);*/
    input_report_abs(ts->input_dev, EVENT_PINCH, pinch_value);
    input_sync(ts->input_dev);
    
		#endif

    //input_report_key(ts->input_dev, BTN_TOUCH, !!pressure);
    //input_sync(ts->input_dev);
		//ZTE_SET_BIT_WLY_0518,BEGIN
    if (ts->use_irq)
       enable_irq(ts->client->irq);
		//ZTE_SET_BIT_WLY_0518,END

}
示例#25
0
static void ltr558_schedwork(struct work_struct *work){
	int als_ps_status;
	int interrupt, newdata;
	int final_prox_val;
	int final_lux_val;

	als_ps_status = ltr558_i2c_read_reg(LTR558_ALS_PS_STATUS);
	interrupt = als_ps_status & 10;
	newdata   = als_ps_status & 5 ;
	LTRDBG("interrupt [%d]  newdata  [%d]\n", interrupt, newdata);
	switch (interrupt){
		case 2:
			// PS interrupt
			if ((newdata == 1) | (newdata == 5)){
				
				final_prox_val = ltr558_ps_read();
				if(final_prox_val < 0){
					LTRERR("read P-sensor data fail\n");
					goto out;
				}
				
				LTRDBG("final_prox_val [%d]\n", final_prox_val);
				if (final_prox_val >= 0x214){
					P_L_printk("ltr558 OBJECT_IS_DETECTED\n");
					input_report_abs(ltr558_data->ltr558_input,
									ABS_DISTANCE, OBJECT_IS_DETECTED);
					if (ltr558_set_p_range(P_RANGE_2)){
						LTRERR("set P-sensor to range 2 fail\n");
					}	
				}else if (final_prox_val < 0x214){
					P_L_printk("ltr558 OBJECT_IS_NOT_DETECTED\n");
					input_report_abs(ltr558_data->ltr558_input,
									ABS_DISTANCE, OBJECT_IS_NOT_DETECTED);
					if (ltr558_set_p_range(P_RANGE_1)){
						LTRERR("set P-sensor to range 1 fail\n");
					}	
				}
			}
			break;

		case 8:
			// ALS interrupt
			if ((newdata == 4) | (newdata == 5)){
				
				final_lux_val = ltr558_als_read();
				if(final_lux_val < 0){
					LTRERR("read L-sensor data fail\n");
					goto out;
				}
				
				input_report_abs(ltr558_data->ltr558_input, ABS_MISC, final_lux_val);
				LTRDBG("final_lux_val [%d]\n", final_lux_val);
			}
			break;

		case 10:
			// Both interrupt
			if ((newdata == 1) | (newdata == 5)){
				
				final_prox_val = ltr558_ps_read();
				if(final_prox_val < 0){
					LTRERR("read P-sensor data fail\n");
					goto read_als;
				}
				
				LTRDBG("final_prox_val [%d]\n", final_prox_val);
				if (final_prox_val >= 0x214){
					input_report_abs(ltr558_data->ltr558_input,
									ABS_DISTANCE, OBJECT_IS_DETECTED);
					if (ltr558_set_p_range(P_RANGE_2)){
						LTRERR("set P-sensor to range 2 fail\n");
					}	
				}else if (final_prox_val <0x214){
					input_report_abs(ltr558_data->ltr558_input,
									ABS_DISTANCE, OBJECT_IS_NOT_DETECTED);
					if (ltr558_set_p_range(P_RANGE_1)){
						LTRERR("set P-sensor to range 2 fail\n");
					}	
				}
			}
read_als:
			if ((newdata == 4) | (newdata == 5)){
				
				final_lux_val = ltr558_als_read();
				if(final_lux_val < 0){
					LTRERR("read L-sensor data fail\n");
					goto out;
				}
				
				input_report_abs(ltr558_data->ltr558_input, ABS_MISC, final_lux_val);
				LTRDBG("final_lux_val [%d]\n", final_lux_val);
			}
			break;
	}
out:
	input_sync(ltr558_data->ltr558_input);	
	enable_irq(ltr558_data->ltr558_irq);

}
示例#26
0
static int gp2a_i2c_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	int ret = -ENODEV;
	struct input_dev *input_dev;
	struct gp2a_data *gp2a;
	struct gp2a_platform_data *pdata = client->dev.platform_data;

	pr_info("==============================\n");
	pr_info("=========     GP2A     =======\n");
	pr_info("==============================\n");

	if (!pdata) {
		pr_err("%s: missing pdata!\n", __func__);
		return ret;
	}
	/*
	if (!pdata->power || !pdata->light_adc_value) {
		pr_err("%s: incomplete pdata!\n", __func__);
		return ret;
	}
	*/
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		pr_err("%s: i2c functionality check failed!\n", __func__);
		return ret;
	}

	gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL);
	if (!gp2a) {
		pr_err("%s: failed to alloc memory for module data\n",
			__func__);
		return -ENOMEM;
	}

#if defined(CONFIG_OPTICAL_WAKE_ENABLE)
	if (system_rev >= 0x03) {
		pr_info("GP2A Reset GPIO = GPX0(1) (rev%02d)\n", system_rev);
		gp2a->enable_wakeup = true;
	} else {
		pr_info("GP2A Reset GPIO = GPL0(6) (rev%02d)\n", system_rev);
		gp2a->enable_wakeup = false;
	}
#else
	gp2a->enable_wakeup = false;
#endif

	gp2a->pdata = pdata;
	gp2a->i2c_client = client;
	i2c_set_clientdata(client, gp2a);

	/* wake lock init */
	wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND,
			"prx_wake_lock");
	mutex_init(&gp2a->power_mutex);
	mutex_init(&gp2a->adc_mutex);

	ret = gp2a_setup_irq(gp2a);
	if (ret) {
		pr_err("%s: could not setup irq\n", __func__);
		goto err_setup_irq;
	}

	/* allocate proximity input_device */
	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		goto err_input_allocate_device_proximity;
	}

	gp2a->proximity_input_dev = input_dev;
	input_set_drvdata(input_dev, gp2a);
	input_dev->name = "proximity_sensor";
	input_set_capability(input_dev, EV_ABS, ABS_DISTANCE);
	input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0);

	gp2a_dbgmsg("registering proximity input device\n");
	ret = input_register_device(input_dev);
	if (ret < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(input_dev);
		goto err_input_register_device_proximity;
	}

	ret = sysfs_create_group(&input_dev->dev.kobj,
				 &proximity_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_proximity;
	}

	/* hrtimer settings.  we poll for light values using a timer. */
	hrtimer_init(&gp2a->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	gp2a->light_poll_delay =
			ns_to_ktime(LIGHT_TIMER_PERIOD_MS * NSEC_PER_MSEC);
	gp2a->timer.function = gp2a_timer_func;

	/* the timer just fires off a work queue request.  we need a thread
	   to read the i2c (can be slow and blocking). */
	gp2a->wq = create_singlethread_workqueue("gp2a_wq");
	if (!gp2a->wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create workqueue\n", __func__);
		goto err_create_workqueue;
	}

	/* this is the thread function we run on the work queue */
	INIT_WORK(&gp2a->work_light, gp2a_work_func_light);

#ifdef GP2A_MODE_B
	/* this is the thread function we run on the work queue */
	INIT_WORK(&gp2a->work_proximity, gp2a_work_func_proximity);
#endif

	/* allocate lightsensor-level input_device */
	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		ret = -ENOMEM;
		goto err_input_allocate_device_light;
	}

	input_set_drvdata(input_dev, gp2a);
	input_dev->name = "light_sensor";
	input_set_capability(input_dev, EV_ABS, ABS_MISC);
	input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0);

	gp2a_dbgmsg("registering lightsensor-level input device\n");
	ret = input_register_device(input_dev);
	if (ret < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(input_dev);
		goto err_input_register_device_light;
	}

	gp2a->light_input_dev = input_dev;
	ret = sysfs_create_group(&input_dev->dev.kobj,
				&light_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}

	/* alloc platform device for adc client */
	pdev_gp2a_adc = platform_device_alloc("gp2a-adc", -1);
	if (!pdev_gp2a_adc) {
		pr_err("%s: could not allocation pdev_gp2a_adc.\n", __func__);
		ret = -ENOMEM;
		goto err_platform_allocate_device_adc;
	}

	/* Register adc client */
	gp2a->padc = s3c_adc_register(pdev_gp2a_adc, NULL, NULL, 0);

	if (IS_ERR(gp2a->padc)) {
		dev_err(&pdev_gp2a_adc->dev, "cannot register adc\n");
		ret = PTR_ERR(gp2a->padc);
		goto err_platform_register_device_adc;
	}

	/* set sysfs for light sensor */

	ret = misc_register(&light_device);
	if (ret)
		pr_err(KERN_ERR "misc_register failed - light\n");

	gp2a->lightsensor_class = class_create(THIS_MODULE, "lightsensor");
	if (IS_ERR(gp2a->lightsensor_class))
		pr_err("Failed to create class(lightsensor)!\n");

	gp2a->switch_cmd_dev = device_create(gp2a->lightsensor_class,
		NULL, 0, NULL, "switch_cmd");
	if (IS_ERR(gp2a->switch_cmd_dev))
		pr_err("Failed to create device(switch_cmd_dev)!\n");

	if (device_create_file(gp2a->switch_cmd_dev,
		&dev_attr_lightsensor_file_illuminance) < 0)
		pr_err("Failed to create device file(%s)!\n",
			dev_attr_lightsensor_file_illuminance.attr.name);

	dev_set_drvdata(gp2a->switch_cmd_dev, gp2a);

/* new sysfs */
	ret = sensors_register(gp2a->light_dev, gp2a, light_sensor_attrs,
						"light_sensor");
	if (ret) {
		pr_err("%s: cound not register light sensor device(%d).\n",
		__func__, ret);
		goto out_light_sensor_register_failed;
	}

	ret = sensors_register(gp2a->proximity_dev,
			gp2a, proximity_sensor_attrs, "proximity_sensor");
	if (ret) {
		pr_err("%s: cound not register proximity sensor device(%d).\n",
		__func__, ret);
		goto out_proximity_sensor_register_failed;
	}

	/* set initial proximity value as 1 */
	gp2a->prox_value = 1;
	input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1);
	input_sync(gp2a->proximity_input_dev);

	gp2a->adc_total = 0;

	goto done;

	/* error, unwind it all */
out_light_sensor_register_failed:
	sensors_unregister(gp2a->light_dev);
out_proximity_sensor_register_failed:
	sensors_unregister(gp2a->proximity_dev);

err_sysfs_create_group_light:
	input_unregister_device(gp2a->light_input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	destroy_workqueue(gp2a->wq);
err_platform_allocate_device_adc:
	platform_device_unregister(pdev_gp2a_adc);
err_platform_register_device_adc:
	s3c_adc_release(gp2a->padc);
err_create_workqueue:
	sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj,
			&proximity_attribute_group);
err_sysfs_create_group_proximity:
	input_unregister_device(gp2a->proximity_input_dev);
err_input_register_device_proximity:
err_input_allocate_device_proximity:
	free_irq(gp2a->irq, 0);
	gpio_free(gp2a->pdata->p_out);
err_setup_irq:
	mutex_destroy(&gp2a->adc_mutex);
	mutex_destroy(&gp2a->power_mutex);

	wake_lock_destroy(&gp2a->prx_wake_lock);
	kfree(gp2a);
done:
	return ret;
}
示例#27
0
/* report trackpad data as logical trackpad state */
static int report_tp_state(struct bcm5974 *dev, int size)
{
	const struct bcm5974_config *c = &dev->cfg;
	const struct tp_finger *f;
	struct input_dev *input = dev->input;
	int raw_p, raw_w, raw_x, raw_y, raw_n, i;
	int ptest, origin, ibt = 0, nmin = 0, nmax = 0;
	int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;

	if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
		return -EIO;

	/* finger data, le16-aligned */
	f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
	raw_n = (size - c->tp_offset) / SIZEOF_FINGER;

	/* always track the first finger; when detached, start over */
	if (raw_n) {

		/* report raw trackpad data */
		for (i = 0; i < raw_n; i++)
			report_finger_data(input, c, &f[i]);

		raw_p = raw2int(f->force_major);
		raw_w = raw2int(f->size_major);
		raw_x = raw2int(f->abs_x);
		raw_y = raw2int(f->abs_y);

//		dprintk(9,
//			"bcm5974: "
//			"raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
;

		ptest = int2bound(&c->p, raw_p);
		origin = raw2int(f->origin);

		/* while tracking finger still valid, count all fingers */
		if (ptest > PRESSURE_LOW && origin) {
			abs_p = ptest;
			abs_w = int2bound(&c->w, raw_w);
			abs_x = int2bound(&c->x, raw_x - c->x.devmin);
			abs_y = int2bound(&c->y, c->y.devmax - raw_y);
			while (raw_n--) {
				ptest = int2bound(&c->p,
						  raw2int(f->force_major));
				if (ptest > PRESSURE_LOW)
					nmax++;
				if (ptest > PRESSURE_HIGH)
					nmin++;
				f++;
			}
		}
	}

	/* set the integrated button if applicable */
	if (c->tp_type == TYPE2)
		ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);

	if (dev->fingers < nmin)
		dev->fingers = nmin;
	if (dev->fingers > nmax)
		dev->fingers = nmax;

	input_report_key(input, BTN_TOUCH, dev->fingers > 0);
	input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
	input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
	input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3);
	input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3);

	input_report_abs(input, ABS_PRESSURE, abs_p);
	input_report_abs(input, ABS_TOOL_WIDTH, abs_w);

	if (abs_p) {
		input_report_abs(input, ABS_X, abs_x);
		input_report_abs(input, ABS_Y, abs_y);

//		dprintk(8,
//			"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
//			"nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w,
;

	}

	/* type 2 reports button events via ibt only */
	if (c->tp_type == TYPE2)
		input_report_key(input, BTN_LEFT, ibt);

	input_sync(input);

	return 0;
}
示例#28
0
/*
 * URB callback routine.  Called when we get IRQ reports from the
 *  digitizer.
 *
 *  This bridges the USB and input device worlds.  It generates events
 *  on the input device based on the USB reports.
 */
static void gtco_urb_callback(struct urb *urbinfo)
{
	struct gtco *device = urbinfo->context;
	struct input_dev  *inputdev;
	int               rc;
	u32               val = 0;
	s8                valsigned = 0;
	char              le_buffer[2];

	inputdev = device->inputdevice;

	/* Was callback OK? */
	if (urbinfo->status == -ECONNRESET ||
	    urbinfo->status == -ENOENT ||
	    urbinfo->status == -ESHUTDOWN) {

		/* Shutdown is occurring. Return and don't queue up any more */
		return;
	}

	if (urbinfo->status != 0) {
		/*
		 * Some unknown error.  Hopefully temporary. Just go and
		 * requeue an URB
		 */
		goto resubmit;
	}

	/*
	 * Good URB, now process
	 */

	/* PID dependent when we interpret the report */
	if (inputdev->id.product == PID_1000 ||
	    inputdev->id.product == PID_1001 ||
	    inputdev->id.product == PID_1002) {

		/*
		 * Switch on the report ID
		 * Conveniently, the reports have more information, the higher
		 * the report number.  We can just fall through the case
		 * statements if we start with the highest number report
		 */
		switch (device->buffer[0]) {
		case 5:
			/* Pressure is 9 bits */
			val = ((u16)(device->buffer[8]) << 1);
			val |= (u16)(device->buffer[7] >> 7);
			input_report_abs(inputdev, ABS_PRESSURE,
					 device->buffer[8]);

			/* Mask out the Y tilt value used for pressure */
			device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);

			/* Fall thru */
		case 4:
			/* Tilt */

			/* Sign extend these 7 bit numbers.  */
			if (device->buffer[6] & 0x40)
				device->buffer[6] |= 0x80;

			if (device->buffer[7] & 0x40)
				device->buffer[7] |= 0x80;


			valsigned = (device->buffer[6]);
			input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned);

			valsigned = (device->buffer[7]);
			input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned);

			/* Fall thru */
		case 2:
		case 3:
			/* Convert buttons, only 5 bits possible */
			val = (device->buffer[5]) & MASK_BUTTON;

			/* We don't apply any meaning to the bitmask,
			   just report */
			input_event(inputdev, EV_MSC, MSC_SERIAL, val);

			/*  Fall thru */
		case 1:
			/* All reports have X and Y coords in the same place */
			val = get_unaligned_le16(&device->buffer[1]);
			input_report_abs(inputdev, ABS_X, val);

			val = get_unaligned_le16(&device->buffer[3]);
			input_report_abs(inputdev, ABS_Y, val);

			/* Ditto for proximity bit */
			val = device->buffer[5] & MASK_INRANGE ? 1 : 0;
			input_report_abs(inputdev, ABS_DISTANCE, val);

			/* Report 1 is an exception to how we handle buttons */
			/* Buttons are an index, not a bitmask */
			if (device->buffer[0] == 1) {

				/*
				 * Convert buttons, 5 bit index
				 * Report value of index set as one,
				 * the rest as 0
				 */
				val = device->buffer[5] & MASK_BUTTON;
				dbg("======>>>>>>REPORT 1: val 0x%X(%d)",
				    val, val);

				/*
				 * We don't apply any meaning to the button
				 * index, just report it
				 */
				input_event(inputdev, EV_MSC, MSC_SERIAL, val);
			}
			break;

		case 7:
			/* Menu blocks */
			input_event(inputdev, EV_MSC, MSC_SCAN,
				    device->buffer[1]);
			break;
		}
	}

	/* Other pid class */
	if (inputdev->id.product == PID_400 ||
	    inputdev->id.product == PID_401) {

		/* Report 2 */
		if (device->buffer[0] == 2) {
			/* Menu blocks */
			input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]);
		}

		/*  Report 1 */
		if (device->buffer[0] == 1) {
			char buttonbyte;

			/*  IF X max > 64K, we still a bit from the y report */
			if (device->max_X > 0x10000) {

				val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]);
				val |= (u32)(((u8)device->buffer[3] & 0x1) << 16);

				input_report_abs(inputdev, ABS_X, val);

				le_buffer[0]  = (u8)((u8)(device->buffer[3]) >> 1);
				le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7);

				le_buffer[1]  = (u8)(device->buffer[4] >> 1);
				le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);

				val = get_unaligned_le16(le_buffer);
				input_report_abs(inputdev, ABS_Y, val);

				/*
				 * Shift the button byte right by one to
				 * make it look like the standard report
				 */
				buttonbyte = device->buffer[5] >> 1;
			} else {
示例#29
0
static void touch_timer_fire(unsigned long data)
{
	unsigned long data0;
	unsigned long data1;
	int updown;
#ifdef CONFIG_ANDROID
	int x,y;
#endif /* CONFIG_ANDROID */

	data0 = readl(ts_base+S3C_ADCDAT0);
	data1 = readl(ts_base+S3C_ADCDAT1);

	updown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN));

	if (updown) {
		if (ts->count) {

#ifdef CONFIG_TOUCHSCREEN_S3C_DEBUG
			{
				struct timeval tv;
				do_gettimeofday(&tv);
				printk(KERN_INFO "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts->xp, ts->yp);
			}
#endif

#ifdef CONFIG_ANDROID
			x=(int) ts->xp/ts->count;
			y=(int) ts->yp/ts->count;
#if defined(CONFIG_FB_S3C_LTE480WV) || defined(CONFIG_FB_S3C_UTLCD7B) 
			y = 4000 - y;
#endif /* CONFIG_FB_S3C_LTE480WV */
			input_report_abs(ts->dev, ABS_X, x);
			input_report_abs(ts->dev, ABS_Y, y);
			input_report_abs(ts->dev, ABS_Z, 0);
			input_report_key(ts->dev, BTN_TOUCH, 1);
			input_sync(ts->dev);
#else /* CONFIG_ANDROID */
			input_report_abs(ts->dev, ABS_X, ts->xp);
			input_report_abs(ts->dev, ABS_Y, ts->yp);

			input_report_key(ts->dev, BTN_TOUCH, 1);
			input_report_abs(ts->dev, ABS_PRESSURE, 1);
			input_sync(ts->dev);
#endif /* CONFIG_ANDROID */
		}

		ts->xp = 0;
		ts->yp = 0;
		ts->count = 0;

		writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base+S3C_ADCTSC);
		writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base+S3C_ADCCON);
	} else {
		ts->count = 0;
#ifdef CONFIG_ANDROID
		input_report_abs(ts->dev, ABS_X, ts->xp);
		input_report_abs(ts->dev, ABS_Y, ts->yp);
		input_report_abs(ts->dev, ABS_Z, 0);
#endif /* CONFIG_ANDROID */
		input_report_key(ts->dev, BTN_TOUCH, 0);
#ifndef CONFIG_ANDROID
		input_report_abs(ts->dev, ABS_PRESSURE, 0);
#endif /* !CONFIG_ANDROID */
		input_sync(ts->dev);

		writel(WAIT4INT(0), ts_base+S3C_ADCTSC);
	}
}
示例#30
0
static ssize_t
proximity_enable_store(struct device *dev,
			struct device_attribute *attr,
			const char *buf, size_t count)
{
	struct gp2a_data *data = dev_get_drvdata(dev);

	int value = 0;
	char input;
	int err = 0;
	int16_t thrd;
	u8 reg;

	err = kstrtoint(buf, 10, &value);

	if (err) {
		pr_err("%s, kstrtoint failed.", __func__);
		goto done;
	}
	if (value != 0 && value != 1)
		goto done;

	pr_info("%s, %d value = %d\n", __func__, __LINE__, value);

	if (data->proximity_enabled && !value) {	/* Prox power off */
		disable_irq(data->irq);

		proximity_onoff(0, data);
		disable_irq_wake(data->irq);
		//if (data->pdata->led_on)
		//	data->pdata->led_on(false);
	}
	if (!data->proximity_enabled && value) {	/* prox power on */
		//if (data->pdata->led_on)
		//	data->pdata->led_on(true);
		usleep_range(1000, 1100);
		proximity_onoff(1, data);

		err = proximity_open_calibration(data);
		if (err < 0 && err != -ENOENT)
			pr_err("%s: proximity_open_offset() failed\n",
				__func__);
		else {
			thrd = gp2a_reg[3][1]+(data->offset_value);
			THR_REG_LSB(thrd, reg);
			gp2a_i2c_write(data, gp2a_reg[3][0], &reg);
			THR_REG_MSB(thrd, reg);
			gp2a_i2c_write(data, gp2a_reg[4][0], &reg);

			thrd = gp2a_reg[5][1]+(data->offset_value);
			THR_REG_LSB(thrd, reg);
			gp2a_i2c_write(data, gp2a_reg[5][0], &reg);
			THR_REG_MSB(thrd, reg);
			gp2a_i2c_write(data, gp2a_reg[6][0], &reg);
		}

		enable_irq_wake(data->irq);
		msleep(160);

		input = gpio_get_value_cansleep(data->pdata->p_out);
		if (input == 0) {
			input_report_abs(data->proximity_input_dev,
					ABS_DISTANCE, 1);
			input_sync(data->proximity_input_dev);
		}

		enable_irq(data->irq);
	}
	data->proximity_enabled = value;
done:
	return count;
}