예제 #1
0
static int ntrig_usbhid_input_mapping(	struct hid_device*	hdev, 
					struct hid_input*	hi,
					struct hid_field*	field, 
					struct hid_usage*	usage,
					unsigned long**		bit, 
					int*			max)
{
	struct ntrig_usbhid_data* nd = hid_get_drvdata(hdev);
	
	switch (usage->hid & HID_USAGE_PAGE) {
	case HID_UP_GENDESK:
		switch (usage->hid) {
		case HID_GD_X:
			hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_X);
			input_set_abs_params(hi->input, ABS_X, field->logical_minimum, field->logical_maximum, 0, 0);
			nd->ntrig_dispatcher->logical_min_x	= field->logical_minimum;
			nd->ntrig_dispatcher->logical_max_x	= field->logical_maximum;
			ntrig_dbg("%s ABX_X_MIN=%d ABX_X_MAX=%d\n", __FUNCTION__, field->logical_minimum, field->logical_maximum);
			return 1;
		case HID_GD_Y:
			hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_Y);
			nd->ntrig_dispatcher->logical_min_y	= field->logical_minimum;
			nd->ntrig_dispatcher->logical_max_y	= field->logical_maximum;
			input_set_abs_params(hi->input, ABS_Y, field->logical_minimum, field->logical_maximum, 0, 0);
			ntrig_dbg("%s ABX_Y_MIN=%d ABX_Y_MAX=%d\n", __FUNCTION__, field->logical_minimum, field->logical_maximum);
			return 1;
		}
		return 0;

	case HID_UP_DIGITIZER:
		switch (usage->hid) {
		/* we do not want to map these for now */
		case HID_DG_INVERT: /* Not support by pen */
		case HID_DG_ERASER: /* Not support by pen */

		case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */
		case HID_DG_INPUTMODE:
		case HID_DG_DEVICEINDEX:
		case HID_DG_CONTACTMAX:
			return -1;
                /*case HID_DG_TIPSWITCH:
                        hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
                        return 1;*/
		/* width/height mapped on TouchMajor/TouchMinor/Orientation */
		case HID_DG_WIDTH:
			hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR);
			return 1;
		case HID_DG_HEIGHT:
			hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR);
			hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TRACKING_ID);
			return 1;
		}
		return 0;

	case 0xff000000:
		/* we do not want to map these: no input-oriented meaning */
		return -1;
	}
	return 0;
}
예제 #2
0
int NTRIGWriteSensor (void *dev, uint8_t cmd, const char *in_buf, short msg_len)
{
	int retval; // holds the number of bytes written/read or <0 if failed, so no need for the above check	

	ntrig_dbg( "inside %s cmd = %d\n", __FUNCTION__, cmd);
	
	if (!dev) {
		ntrig_dbg("%s: wrong paramas\n", __FUNCTION__);
		return DTRG_FAILED;
	}

	// Get battery status from SW var, not from device
	if (cmd == REPORTID_GET_PEN_BATTRY_STATUS) {
		next_read_sensor_command = REPORTID_GET_PEN_BATTRY_STATUS;	
//		ntrig_dbg("%s: REPORTID_GET_PEN_BATTRY_STATUS: next command = %d \n", __FUNCTION__, next_read_sensor_command);
		return 1;
	}

	retval = ntrig_usbhid_send_report((struct hid_device *)dev, cmd, in_buf, msg_len);

	ntrig_dbg( "Leaving %s , count = %d, msg_len = %d\n", __FUNCTION__, retval, msg_len);

	if(retval < 0) {
		/* failed */
		return retval;
	}

	return msg_len + 1; // add 1 for command
}
예제 #3
0
/** 
 * Read sensor configuration response from HID device. 
 * Return number of bytes read or fail.
 */
int NTRIGReadSensor (void *dev, char *buf, size_t count)
{
	int size = hid_touch_ep_msg[HID_REPLY_SIZE];
	struct ntrig_usbhid_data* nd = hid_get_drvdata((struct hid_device *)dev);

	ntrig_dbg( "usbhid: inside %s out_buf size = %d \n", __FUNCTION__, (int)sizeof(buf));
	// Get battery status from SW var, not from device
	if (next_read_sensor_command == REPORTID_GET_PEN_BATTRY_STATUS) {
		buf[0] = (char) nd->battery_status;
//		ntrig_dbg("%s: REPORTID_GET_PEN_BATTRY_STATUS: status = %d \n", __FUNCTION__, buf[0]);
		next_read_sensor_command = -1;	
		return 1;
	}
	
	/* size of input buffer (coming from sysfs show function) is PAGE_SIZE (4096 bytes)
	   so it's very unlikely we'll have memory overwriting. 
	   Therefore there's no need to check the buf size before writing to it
	*/
	if (count < size) {	// buffer too small
		ntrig_dbg( "usbhid: Leaving %s, count (%d)< size(%d)\n", __FUNCTION__, (int)count, size);
		return -1;
	}

	memcpy(buf, &hid_touch_ep_msg[HID_REPLY_DATA], size);
	ntrig_dbg( "usbhid: Leaving %s \n", __FUNCTION__);

	return size;
}
예제 #4
0
/*
 * This function is used to configure N-trig firmware
 * The first command we need to send to firmware is change
 * to Multi-touch Mode we don't receive a reply
 * Endpoint 2 - Touch/Pen events
 */
static int ntrig_usbhid_send_report(struct hid_device *hdev, uint8_t request_report, const char *in_buf, short msg_len)
{
	struct hid_report *report;
	struct list_head *report_list =
			&hdev->report_enum[HID_FEATURE_REPORT].report_list;

	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
        struct usb_device *dev = interface_to_usbdev(intf);
        __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
        int ret = DTRG_FAILED;

	ntrig_dbg( "inside %s \n", __FUNCTION__);
	
	report = list_first_entry(report_list, struct hid_report, list);
	if (report->maxfield < 1)
		return -ENODEV;

	list_for_each_entry(report,
			    report_list, list) {
		if (report->maxfield < 1) {
		      ntrig_dbg("no fields in the report\n");
		      continue;
		}
		if (request_report == report->id) {
			int bufsize = (msg_len < HID_CLASS_TOUCH_EP_LEN) ? HID_CLASS_TOUCH_EP_LEN : msg_len;
		    char *buf = kmalloc(bufsize, GFP_KERNEL);
		    if (!buf)
			return -ENOMEM;
		    if (!msg_len) { // msg_len == 0 ==> get report
			    ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
		                         HID_REQ_GET_REPORT,
		                         USB_DIR_IN | USB_TYPE_CLASS |
		                         USB_RECIP_INTERFACE,
		                         (0x03 << 8) | request_report, ifnum, buf, report->size,
		                         USB_CTRL_GET_TIMEOUT);
			    hid_touch_ep_msg[HID_REPLY_SIZE] = ret;
			    if (ret >= 0) // success
			    	memcpy(&hid_touch_ep_msg[HID_REPLY_DATA], buf, ret);
		    }
		    else { // msg_len > 0 ==> set report
			    if (!in_buf) {
				kfree(buf);
				return -ENOMEM;
			    }
		    	    memcpy(buf, in_buf, msg_len); 
			    ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
					HID_REQ_SET_REPORT ,
                                 	USB_DIR_OUT | USB_TYPE_CLASS |
                                 	USB_RECIP_INTERFACE,		                        
					(0x03 << 8) | request_report, ifnum, buf, msg_len,
		                        USB_CTRL_SET_TIMEOUT);
 		    }
		    kfree(buf);
		}
	}
	return ret;
}
예제 #5
0
int get_virtual_keys(char *buf) {
#ifdef VIRTUAL_KEYS_SUPPORTED
	char tmp_buf[1024];
#endif
	ntrig_dbg("ntrig-sysfs-dispatcher: inside %s\n", __FUNCTION__);
#ifdef VIRTUAL_KEYS_SUPPORTED
snprintf(tmp_buf, PAGE_SIZE, "%s\n", virtual_keys_attr_buf);
ntrig_dbg("ntrig-sysfs-dispatcher: inside %s, keys=%s\n", __FUNCTION__,tmp_buf);
	return snprintf(buf, PAGE_SIZE, "%s\n", virtual_keys_attr_buf);
#else
	return 0;
#endif
}
예제 #6
0
static void ntrig_usbhid_remove(struct hid_device *hdev)
{
	struct ntrig_usbhid_data*	nd;

	ntrig_dbg("Entering %s\n", __FUNCTION__);
	hid_hw_stop(hdev);

	nd = hid_get_drvdata(hdev);
	UnregNtrigDispatcher(nd->ntrig_dispatcher, nd->sensor_id, TYPE_BUS_USB_HID, hdev->uniq);	
	remove_device(&nd->ntrig_dispatcher);		
	kfree(nd);

	ntrig_dbg("%s all resource released\n", __FUNCTION__);
}
예제 #7
0
static ssize_t get_counters_show(struct kobject *kobj, struct kobj_attribute *attr,
			char *buf)
{	
	int i, res;
	ntrig_counter *counters_list;
	int length;
	
	ntrig_dbg( "inside %s\n", __FUNCTION__);
	
	if(read_get_counters == NULL)
	{
		printk(KERN_DEBUG "in %s  read_get_counters is NULL\n", __FUNCTION__);
		return -1;
	}
	res = 0;
	
	read_get_counters(&counters_list, &length);
	
	for(i=0;i<length;++i)
	{
		res += snprintf(buf+res,PAGE_SIZE-res,"%s \t %d\n",counters_list[i].name, counters_list[i].count);
	}
	
	return res;
}
예제 #8
0
/*
 * This function used to configure N-trig firmware
 * The first command we need to send to firmware is change
 * to Multi-touch Mode we don't receive a reply
 * Endpoint 1 NCP 
 */
static int ntrig_usbhid_send_ncp_report(struct hid_device *hdev, const unsigned char *ncp_cmd)
{
	struct hid_report *report;
	struct list_head *report_list =
			&hdev->report_enum[HID_FEATURE_REPORT].report_list;

	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
        struct usb_device *dev = interface_to_usbdev(intf);
        __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
        int ret;
	
	ntrig_dbg( "inside %s \n", __FUNCTION__);
	ntrig_dbg("%s: ncp_cmd[0]=%0X ncp_cmd[1]=%0X\n", __FUNCTION__, ncp_cmd[0], ncp_cmd[1]);
	report = list_first_entry(report_list, struct hid_report, list);
	if (report->maxfield < 1)
		return -ENODEV;
	list_for_each_entry(report,
			    report_list, list) {
		if (report->maxfield < 1) {
		      ntrig_dbg("no fields in the report\n");
		      continue;
		}
		/*
		* Bytes Needed From User
		* 0 - Length Of Message
		* 1 - Reprot ID
		* .. - Data
		*/
		/* ntrig_dbg("%s: checking report id %d for candidate %d\n", __FUNCTION__, report->id, ncp_cmd[1]); */
		if (ncp_cmd[HID_NCP_CMD_DATA] == report->id) {
		    char *buf = kmalloc(ncp_cmd[HID_NCP_CMD_LEN], GFP_KERNEL);
		    if (!buf)
			return -ENOMEM;
		    memcpy(buf, &ncp_cmd[HID_NCP_CMD_DATA], ncp_cmd[HID_NCP_CMD_LEN]); 
		    ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 HID_REQ_SET_REPORT ,
                                 USB_DIR_OUT | USB_TYPE_CLASS |
                                 USB_RECIP_INTERFACE,
                                 ( 0x03 << 8) | ncp_cmd[HID_NCP_CMD_DATA], ifnum, buf, ncp_cmd[HID_NCP_CMD_LEN],
                                 USB_CTRL_SET_TIMEOUT);

		    kfree(buf);
		}
	}
	return 0;
}
예제 #9
0
/*
 * Release sysfs files 
 */
static void ntrig_board_properties_release(void)
{
	ntrig_dbg( "inside %s\n", __FUNCTION__);	

	if (board_properties_kobj == NULL) {
		ntrig_dbg( "inside %s , kobj==NULL \n", __FUNCTION__);
		return;
	}

	/* remove file virtualkeys.<device> under folder /sys/board_properties */
	sysfs_remove_file(board_properties_kobj, ntrig_properties_attrs);

	/* remove folder /sys/board_properties (this function also handle reference count and memroy free) */
	kobject_put(board_properties_kobj);
	board_properties_kobj = NULL;
	ntrig_dbg( "inside %s After call to kobject_put\n", __FUNCTION__);	
}
예제 #10
0
void multi_touch_session_end(struct ntrig_usbhid_data* nd)
{	
	clear_input_buffer(nd);	
	nd->message.type	 			= MSG_FINGER_PARSE;
	nd->message.msg.fingers_event.num_of_fingers 	= 0;
	nd->message.msg.fingers_event.frame_index	= nd->frame_index;
	nd->message.msg.fingers_event.sensor_id 	= nd->sensor_id;	
	if (WriteHIDNTRIG(&nd->message) != DTRG_NO_ERROR)
		ntrig_dbg("FAILED to end MULTI-TOUCH session\n");
}
예제 #11
0
/*
 * This function sends the DRIVER_ALIVE message to the touch screen upon waking
 * up after a device sleep.
 */
static int ntrig_usbhid_reset_resume(struct hid_device *hdev)
{
	int ret;
	ntrig_dbg( "inside %s \n", __FUNCTION__);
	ret = ntrig_usbhid_send_report(hdev, REPORTID_DRIVER_ALIVE, NULL, 0);
	if (ret < 0) {
		dev_err(&hdev->dev, "%s: send REPORTID_DRIVER_ALIVE failed, error code=%d\n", __FUNCTION__, ret);
	}
	return 0;
}
예제 #12
0
/** 
 * Write NCP msg to HID device. 
 * Return success or fail.
 */
int NTRIGWriteNCP (void *dev, const char *buf, short msg_len)
{
	int count = 0;
	struct hid_device *hdev = dev;

	ntrig_dbg( "inside %s \n", __FUNCTION__);
	ntrig_dbg("%s: buf[0]=%0X buf[1]=%0X\n", __FUNCTION__, buf[0], buf[1]);
	
	if ((!dev) || (!buf) || (msg_len == 0)) {
		ntrig_dbg("%s: wrong paramas\n", __FUNCTION__);
		return DTRG_FAILED;
	}

	//This version don't support bytes received from shell (ascii)
	ntrig_usbhid_send_ncp_report(hdev, buf);

	ntrig_dbg( "Leaving %s , count = %d\n", __FUNCTION__, count);	
	return count;
}
예제 #13
0
void send_multi_touch(struct ntrig_usbhid_data* nd)
{
	/* lets verify that buffer is used for multi-touch data */
	if( MSG_FINGER_PARSE == nd->message.type) {
		nd->message.msg.fingers_event.num_of_fingers = nd->contact_count;
		/* add frame index, when  sending all fingers data */		
		nd->message.msg.fingers_event.frame_index = nd->frame_index;
		nd->message.msg.fingers_event.sensor_id   = nd->sensor_id;	
		if (WriteHIDNTRIG(&nd->message) != DTRG_NO_ERROR) 
			ntrig_dbg("FAILED to send MULTI-TOUCH\n");
	}
}
예제 #14
0
static ssize_t config_dispatcher_store(struct kobject *kobj, struct kobj_attribute *attr,
			 const char *buf, size_t count)
{
	int retval = 0;
	unsigned char val;

	//sscanf(buf, "%cu", &val);
	val = *buf;
	if (strcmp(attr->attr.name, "tracklib_status") == 0) {
		ntrig_dbg("ntrig-sysfs-dispatcher: inside %s , CONFIG_TRACKLIB, data = %d\n", __FUNCTION__, val);
		retval = write_config_dispatcher(&val, CONFIG_TRACKLIB);	
	}
	else if (strcmp(attr->attr.name, "pen_status") == 0) {	
		ntrig_dbg("ntrig-sysfs-dispatcher: inside %s , CONFIG_PEN, data = %d \n", __FUNCTION__, val);
		retval = write_config_dispatcher(&val, CONFIG_PEN);	
	}
	else if (strcmp(attr->attr.name, "bus_interface") == 0) {
		ntrig_dbg("ntrig-sysfs-dispatcher: inside %s , CONFIG_BUS_INTERFACE, data = %d \n", __FUNCTION__, val);
		retval = write_config_dispatcher(&val, CONFIG_BUS_INTERFACE);	
	}
	else if (strcmp(attr->attr.name, "touch_screen_border") == 0) {
		ntrig_dbg("ntrig-sysfs-dispatcher: inside %s , CONFIG_TOUCH_SCREEN_BORDER, data = %d \n", __FUNCTION__, (int)val);
		retval = write_config_dispatcher(&val, CONFIG_TOUCH_SCREEN_BORDER);
	}
	else if (strcmp(attr->attr.name, "debug_print") == 0) {
		ntrig_dbg("ntrig-sysfs-dispatcher: inside %s , CONFIG_DEBUG_PRINT, data = %d \n", __FUNCTION__, (int)val);
		retval = write_config_dispatcher(&val, CONFIG_DEBUG_PRINT);
	}
	else {
		ntrig_dbg("ntrig-sysfs-dispatcher: inside %s , ubknown configuration \n", __FUNCTION__);
		retval = DTRG_FAILED;
	}

	return retval;
}
예제 #15
0
/*
 * Dispatcher configuration files
 */
static ssize_t config_dispatcher_show(struct kobject *kobj, struct kobj_attribute *attr,
			char *buf)
{
	int retval = 0;

	if (strcmp(attr->attr.name, "tracklib_status") == 0) {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , CONFIG_TRACKLIB \n", __FUNCTION__);
		retval = read_config_dispatcher(buf, CONFIG_TRACKLIB);	
	}
	else if (strcmp(attr->attr.name, "pen_status") == 0) {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , CONFIG_PEN \n", __FUNCTION__);
		retval = read_config_dispatcher(buf, CONFIG_PEN);	
	}
	else if (strcmp(attr->attr.name, "ntrig_virtual_keys_show") == 0) {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , CONFIG_VIRTUAL_KEYS \n", __FUNCTION__);
		retval = get_virtual_keys(buf);		// Virtual keys are held locally in this file
	}
	else if (strcmp(attr->attr.name, "num_sensors") == 0) {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , CONFIG_NUM_SENSORS \n", __FUNCTION__);
		retval = read_config_dispatcher(buf, CONFIG_NUM_SENSORS);	
	}
	else if (strcmp(attr->attr.name, "touch_screen_border") == 0) {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , CONFIG_TOUCH_SCREEN_BORDER \n", __FUNCTION__);
		retval = read_config_dispatcher(buf, CONFIG_TOUCH_SCREEN_BORDER);
	}
	else if (strcmp(attr->attr.name, "driver_version") == 0) {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , CONFIG_DRIVER_VERSION \n", __FUNCTION__);
		retval = read_config_dispatcher(buf, CONFIG_DRIVER_VERSION);
	}
	else if (strcmp(attr->attr.name, "debug_print") == 0) {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , CONFIG_DEBUG_PRINT \n", __FUNCTION__);
		retval = read_config_dispatcher(buf, CONFIG_DEBUG_PRINT);
	}
	else if (strcmp(attr->attr.name, "bus_interface") == 0) {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , CONFIG_BUS_INTERFACE \n", __FUNCTION__);
		retval = read_config_dispatcher(buf, CONFIG_BUS_INTERFACE);	
	}
	else {
		ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , ubknown configuration \n", __FUNCTION__);
		retval = DTRG_FAILED;
	}

	return retval;
}
예제 #16
0
static ssize_t config_sensor_store(struct kobject *kobj, struct kobj_attribute *attr,
			 const char *buf, size_t count)
{
	int retval;
	ntrig_dbg("ntrig-sysfs-dispathcer: inside %s , data = %d \n", __FUNCTION__, buf[1]);

	retval = write_config_sensor((void *) buf, count);

	if (retval)	
		return count;
	else
		return retval;
}
예제 #17
0
/** 
 * Read NCP msg from HID device. 
 * Return number of bytes read or fail.
 */
int NTRIGReadNCP (void *dev, char *buf, size_t count)
{
	int size = sizeof(ntrig_usbhid_ncp_t);

	ntrig_dbg( "usbhid: inside %s \n", __FUNCTION__);
	
	/* allocated buffer too small */
	if (count < size)
		return DTRG_FAILED;

	/* buf is allocated by dispatcher, therefore no need to call copy_to_user */
	memcpy(buf, &ncp, size);
	return size;
}
예제 #18
0
void send_pen(struct ntrig_usbhid_data* nd)
{
	clear_input_buffer(nd);		
	nd->message.type			= MSG_PEN_EVENTS;
	nd->message.msg.pen_event.x_coord	= nd->x;
	nd->message.msg.pen_event.y_coord	= nd->y;
	nd->message.msg.pen_event.pressure	= nd->pressure;
	nd->message.msg.pen_event.btn_code	= nd->btn_pressed;
	nd->message.msg.pen_event.btn_removed	= nd->btn_removed;
	nd->message.msg.pen_event.sensor_id 	= nd->sensor_id;	
	nd->message.msg.pen_event.battery_status = nd->battery_status;
	
	if (WriteHIDNTRIG(&nd->message) != DTRG_NO_ERROR)
		ntrig_dbg("FAILED to send PEN\n");
}
예제 #19
0
static ssize_t reset_counters_store(struct kobject *kobj, struct kobj_attribute *attr,
			 const char *buf, size_t count)
{
	int ret = 1;
	if(buf[0]=='0')
	{
		if(write_reset_counters != NULL)
		{
			write_reset_counters();
		}
	}
	else
	{
		ntrig_dbg("Inside %s: RESET_COUNTERS - wrong data=%d, only valid data is 0\n", __FUNCTION__, *buf);
	}
	return ret;
}
예제 #20
0
int ntrig_dispathcer_sysfs_init(void)
{
	int retval;

	ntrig_dbg( "inside %s\n", __FUNCTION__);

	dispatcher_kobj = kobject_create_and_add("ntrig", NULL);
	if (!dispatcher_kobj) {
		ntrig_dbg( "inside %s\n failed to create dispatcher_kobj", __FUNCTION__);
		return -ENOMEM;
	}
	/* Create the files associated with this kobject */
	retval = sysfs_create_group(dispatcher_kobj, &attr_group);
	if (retval) {
		ntrig_dbg( "inside %s\n failed to create sysfs_group", __FUNCTION__);
		kobject_put(dispatcher_kobj);
	}

#ifdef VIRTUAL_KEYS_SUPPORTED
	ntrig_create_virtualkeys_file();
#endif

	ntrig_dbg("ntrig-dispatcher-sysfs inside %s \n", __FUNCTION__);

	if(setup_config_dispatcher(&read_config_dispatcher, &write_config_dispatcher)){
		ntrig_dbg("ntrig-dispatcher-sysfs inside %s cannot setup_get_bus_interface\n", __FUNCTION__);
	}
	if(setup_config_sensor(&read_config_sensor, &write_config_sensor)){
		ntrig_dbg("ntrig-dispatcher-sysfs inside %s cannot setup_config_sensor\n", __FUNCTION__);
	}
	if(setup_get_bus_interface(&read_get_bus_interface, &write_get_bus_interface)){
		ntrig_dbg("ntrig-dispatcher-sysfs inside %s cannot setup_get_bus_interface\n", __FUNCTION__);
	}
	if(setup_config_counters(&read_get_counters, &write_reset_counters)){
		ntrig_dbg("ntrig-dispatcher-sysfs inside %s cannot setup_get_counters\n", __FUNCTION__);
	}
	
	return retval;
}
예제 #21
0
/**
 * build an NCP/DFU command. The command code will determine how to build
 * the SPI header. The command data will be copied after the header 
 * Buffer must be large enough to hold maximum possible raw 
 * command (560 bytes for DFU) 
 */
void build_ncp_dfu_cmd(u8 cmd, const char* buf, short msg_len, char* out_buf)
{
	int i;
	u8 len;
	struct _ntrig_low_bus_msg* msg = (struct _ntrig_low_bus_msg*)out_buf;
	char* data;
	u32 sum;

	/* set the common fields: preamble, filter pattern */
	msg->preamble = LOWMSG_PREAMBLE;
	for(i=0; i<4; i++) {
		msg->pattern[i] = FILTER_PATTERN[i];
	}
	msg->msg.type = LOWMSG_TYPE_COMMAND;
	msg->msg.flags = 0;
	/* fill specific requests */
	switch(cmd) {
	case LOWMSG_REQUEST_GO_TO_BOOTLOADER:
		/* go to bootloader: we add request type (0x40) and 2 index bytes */
		data = &msg->msg.data[0];
		msg->msg.length = msg_len + 1 + 2 + offsetof(struct _ntrig_low_msg, data);
		msg->msg.channel = LOWMSG_CHANNEL_CONTROL;
		msg->msg.function = LOWMSG_FUNCTION_GO_TO_BOOTLOADER;
		*data++ = 0x40; /* request type */
		memcpy(data, buf, msg_len);
		/* fix message for SPI: it passes 0x0100 instead of 0x0101, which justs resets the fw, and not jump to boot loader
		   TODO check why it works in USB even though it's the wrong value according to spec */
		data[1] = data[2] = 0x01;
		data += msg_len;
		*data++ = 0;
		*data++ = 0;
		break;
	case LOWMSG_REQUEST_DEBUG_AGENT:
		data = &msg->msg.data[0];
		/* ignore BULK_DATA prefix - should not be sent */		
		msg_len -= BULK_DATA;
		buf += BULK_DATA;
		msg->msg.length = msg_len + offsetof(struct _ntrig_low_msg, data);
		msg->msg.channel = LOWMSG_CHANNEL_DEBUG;
		msg->msg.function = LOWMSG_FUNCTION_DEBUG_TYPE_A;
		memcpy(data, buf, msg_len);
		data += msg_len;
		// checksum
		for (i = 0, sum = 0; i < msg->msg.length; i++)
			sum += (u32)((unsigned char *)&msg->msg)[i];
		memcpy(data, &sum, sizeof(sum));
		break;
	case SPI_ENABLED_COMMAND:
		/* arbitrary SPI command, see header file defining this constant */
		data = &msg->msg.data[0];
		msg->msg.length = msg_len - SPI_ENABLED_COMMAND_HEADER_LENGTH + offsetof(struct _ntrig_low_msg, data);
		msg->msg.channel = buf[1];
		msg->msg.function = buf[2];
		memcpy(data, &buf[SPI_ENABLED_COMMAND_HEADER_LENGTH], msg_len);
		break;		
	case LOWMSG_REQUEST_NCP_DFU:
		/* a standard NCP/DFU command. Copy buffer as is */
		data = &msg->msg.data[0];
		msg->msg.length = msg_len + offsetof(struct _ntrig_low_msg, data);
		msg->msg.channel = LOWMSG_CHANNEL_MAINT;
		msg->msg.function = LOWMSG_FUNCTION_NCP;
		memcpy(data, buf, msg_len);
		break;
	default:
		ntrig_dbg("%s: unknown request %d\n", __FUNCTION__, cmd);
	}
}
예제 #22
0
void ntrig_dispathcer_sysfs_exit(void)
{
	ntrig_dbg( "inside %s\n", __FUNCTION__);
	dispatcher_files_release();
}
void config_multi_touch(struct _ntrig_bus_device *dev,
	struct input_dev *input_device)
{
	int i;
	__u16 min_x = dev->logical_min_x;
	__u16 max_x = dev->logical_max_x;
	__u16 min_y = dev->logical_min_y;
	__u16 max_y = dev->logical_max_y;
#ifdef ROTATE_ANDROID
	//__u16 tmp;
#endif

	__set_bit(EV_ABS, input_device->evbit);

	__set_bit(ABS_MT_POSITION_X, input_device->absbit);
	__set_bit(ABS_MT_POSITION_Y, input_device->absbit);
	__set_bit(ABS_MT_WIDTH_MAJOR, input_device->absbit);
#ifdef MT_REPORT_TYPE_B
	__set_bit(ABS_MT_WIDTH_MINOR, input_device->absbit);
	__set_bit(ABS_MT_PRESSURE, input_device->absbit);
#ifndef DISABLE_TOOL_TYPE
	__set_bit(ABS_MT_TOOL_TYPE, input_device->absbit);
#endif /*DISABLE_TOOL_TYPE*/
#else
	__set_bit(ABS_MT_TOUCH_MAJOR, input_device->absbit);
#endif
	/**
	 *   [48/0x30] - ABS_MT_TOUCH_MAJOR  0 .. 40
	 *   [50/0x32] - ABS_MT_WIDTH_MAJOR  0 .. 8000
	 *   [53/0x35] - ABS_MT_POSITION_X   0 .. 1023
	 *   [54/0x36] - ABS_MT_POSITION_Y   0.. 599
	 *   ABS_MT_POSITION_Y =
	 */
	ntrig_dbg_lvl(NTRIG_DEBUG_LEVEL_ONCE,
		"inside %s before VIRTUAL_KEYS_SUPPORTED\n", __func__);

	if (virtual_keys_supported()) {
		ntrig_dbg("inside %s with VIRTUAL_KEYS_SUPPORTED1\n", __func__);

		__set_bit(EV_KEY, input_device->evbit);
		for (i = 0; i < get_virtual_keys_num(); i++)
			__set_bit(get_virt_keys_scan_code(i),
				input_device->keybit);

		min_x += get_touch_screen_border_left();
		max_x -= get_touch_screen_border_right();
		min_y += get_touch_screen_border_down();
		max_y -= get_touch_screen_border_up();
		ntrig_dbg("inside %s with VIRTUAL_KEYS_SUPPORTED2\n", __func__);
	} else {
		ntrig_dbg("inside %s with VIRTUAL_KEYS_SUPPORTED undefined\n",
			__func__);
	}

#ifdef ROTATE_ANDROID
	/* Exchange the x/y boundaries to make the rotation code simpler */
	exchange(&min_x, &min_y);
	exchange(&max_x, &max_y);
#endif
	input_set_abs_params(input_device, ABS_MT_POSITION_X,
		min_x, max_x, 0, 0);
	input_set_abs_params(input_device, ABS_MT_POSITION_Y,
		min_y, max_y, 0, 0);
	input_set_abs_params(input_device, ABS_MT_WIDTH_MAJOR, 0,
		ABS_MT_WIDTH_MAX, 0, 0);
	input_set_abs_params(input_device, ABS_MT_WIDTH_MINOR, 0,
		ABS_MT_WIDTH_MAX, 0, 0);
#ifdef MT_REPORT_TYPE_B
	input_set_abs_params(input_device, ABS_MT_PRESSURE, 1, 255, 0, 0);
#ifndef DISABLE_TOOL_TYPE
	input_set_abs_params(input_device, ABS_MT_TOOL_TYPE, 0, 1, 0, 0);
#endif /*DISABLE_TOOL_TYPE*/
#else
	input_set_abs_params(input_device, ABS_MT_TOUCH_MAJOR, 0,
		ABS_MT_TOUCH_MAJOR_MAX, 0, 0);
#endif
	/** ABS_MT_ORIENTATION: we use 0 or 1 values, we only detect
	 *  90 degree rotation (by looking at the maximum of dx and
	 *  dy reported by sensor */
	input_set_abs_params(input_device, ABS_MT_ORIENTATION, 0, 1, 0, 0);
	input_set_abs_params(input_device, ABS_MT_TRACKING_ID, 0,
		ABS_MT_TRACKING_ID_MAX, 0, 0);

	ntrig_dbg("inside %s after VIRTUAL_KEYS_SUPPORTED\n", __func__);
}
예제 #24
0
/**
 * process the data in the state machine. 
 * Call set_low_msg_sm_data_packet before. 
 * Returns 0 if all data from packet was processed, 1 if there 
 * is more data to process. 
 * After each call, you need to call has_complete_low_message to 
 * check if there is a ready message to process 
 */
int process_low_sm_data_packet(struct _ntrig_low_sm_info* info)
{
	info->gotDataLinkMsg = 0;
	while(info->amountProcessed < info->dataLen) {
		u8 b = *info->data;
		info->data++;
		info->amountProcessed++;
		//ntrig_dbg("%s: got %d state %d substate %d\n", __FUNCTION__, b, info->state, info->substate);
		switch(info->state) {
		case STATE_IDLE:
			/* in idle state, just count the number of successive 0xFF bytes in order to detect a valid preamble.
			   a valid preamble has 4 or more 0xFF bytes */
			if(b == 0xFF) {
				if(info->substate < 4) {
					info->substate++;
				}
			} else if(b == FILTER_PATTERN[0]) {
				if(info->substate >= 4) {
					/* start verifying signature (filter pattern) */
					info->state = STATE_VERIFY_SIG;
					info->substate = 1;
				} else {
					/* start of filter pattern but not enough preamble bytes */
					info->substate = 0;
				}
			} else {
				info->substate = 0;
			}
			break;
		case STATE_VERIFY_SIG:
			/* verify the filter pattern, in order to know if we have a valid message following */
			if(b == FILTER_PATTERN[info->substate]) {
				info->substate++;
				if(info->substate == 4) {
					/* we have a valid filter pattern, next we can read the type field */
					info->state = STATE_TYPE;
				}
			} else {
				/* invalid filter pattern, back to idle */
				info->state = STATE_IDLE;
				info->substate = (b == 0xFF) ? 1 : 0;
			}
			break;
		case STATE_TYPE:
			/* read the type */
			info->lmsg.type = b;
			info->state = STATE_LENGTH;
			info->substate = 0;
			break;
		case STATE_LENGTH:
			/* read the length (2 bytes) */
			if(info->substate == 0) {
				/* read first byte */
				info->lmsg.length = b;
				info->substate++;
			} else {
				/* read second byte */
				info->lmsg.length = info->lmsg.length | (b << 8);
				if(info->lmsg.length > MAX_TRACKED_PACKET_SIZE) {
					/* the packet is too large, we assume it is corrupted. Go back to idle */
					ntrig_err("%s: Message too large - length=%d (> max SPI packet size)\n", 
						__FUNCTION__, info->lmsg.length);
					info->state = STATE_IDLE;
				} else {
					info->state = STATE_FLAGS;
				}
			}
			break;
		case STATE_FLAGS:
			/* read the flags */
			info->lmsg.flags = b;
			if(info->lmsg.length < 2) {
				/* invalid message - it must contain at least channel and function, ignore it */
				ntrig_dbg("%s: invalid message, length (%d) is too short\n", __FUNCTION__, info->lmsg.length);
				info->state = STATE_IDLE;
				info->substate = 0;
			}
			info->state = STATE_MSG;
			info->substate = 4; /* already read type + length + flags */
			break;
		case STATE_MSG:
			/* reading the rest of the message */
			if(info->substate >= 6) {
				info->lmsg.data[info->substate - 6] = b;
			} else if(info->substate == 4) {
				info->lmsg.channel = b;
			} else if(info->substate == 5) {
				info->lmsg.function = b;
			}
			info->substate++;
			if(info->substate >= info->lmsg.length) {
				/* we have a complete data link message */
				info->gotDataLinkMsg = 1;
				/* reset state for next iteration */
				info->state = STATE_IDLE;
				info->substate = 0;
				goto after_loop;
			}
			break;
		}
	}
after_loop:
	/* return if we have more data to process or not */
	return (info->amountProcessed < info->dataLen);
}
예제 #25
0
static int ntrig_usbhid_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	char				phys_path[256];
	int 				ret;
	struct ntrig_usbhid_data*	nd;
	struct usb_interface*		intf;
	struct usb_device* 		dev;
	struct usb_host_interface*	interface;
	struct usb_endpoint_descriptor*	endpoint;
	struct _ntrig_dev_ncp_func	ncp_func;
	struct _ntrig_dev_hid_func	hid_func;


	intf 	 = to_usb_interface(hdev->dev.parent);
	dev	 = interface_to_usbdev(intf);
	interface= intf->cur_altsetting;
	endpoint = &interface->endpoint[0].desc;
	nd = kmalloc(sizeof(struct ntrig_usbhid_data), GFP_KERNEL);
	if (!nd) {
		dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
		return -ENOMEM;
	} 
	if(DTRG_NO_ERROR != allocate_device(&nd->ntrig_dispatcher)){
		dev_err(&hdev->dev, "cannot allocate N-Trig dispatcher\n");
		return DTRG_FAILED;
	}

	hid_set_drvdata(hdev, nd);
	ret = hid_parse(hdev);
	if (ret) {
		dev_err(&hdev->dev, "parse failed, error code=%d\n", ret);
		goto err_free;
	}

	if (NCP_EP_ADDRESS == endpoint->bEndpointAddress) {
		ret = hid_hw_start(hdev, ~HID_QUIRK_MULTI_INPUT);
		if (ret) {
			dev_err(&hdev->dev, "hw start failed NCP, error code=%d\n", ret);
			goto err_free;
		}

		/* register device in the dispatcher - set device and function pointers for ncp
		set sensor id in the device data structure */	  
	// NOTE: registration of ncp_read, ncp_write & dev is linked. 
	//  It's the resposibility of this function to set these parameters together
		ncp_func.dev = (void *) hdev;
		ncp_func.read = NTRIGReadNCP;
		ncp_func.write = NTRIGWriteNCP;
		nd->sensor_id = RegNtrigDispatcher(TYPE_BUS_USB_HID, hdev->uniq, &ncp_func, NULL);
		// TODO: define behavior in case of fail
		if (nd->sensor_id == DTRG_FAILED) {
			ntrig_dbg("%s: Cannot register device to dispatcher\n", __FUNCTION__);
			goto err_free;
		}
		ntrig_dbg("%s NCP dev registered with dispatcher, bus_id = %s, sensor_id = %d\n", __FUNCTION__, hdev->uniq, nd->sensor_id);
		return 0;
	}

	else {
		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
		if (ret) {
			dev_err(&hdev->dev, "hw start failed TOUCH, error code=%d\n", ret);
			goto err_free;
		}
		ret = ntrig_usbhid_send_report(hdev, REPORTID_DRIVER_ALIVE, NULL, 0);
		if (ret < 0) {
			dev_err(&hdev->dev, "send set feature failed, error code=%d\n", ret);
			goto err_free;
		}

		/* register device in the dispatcher - no need to set device and function pointers for touch events
		   set sensor id in the device data structure */	  
	// NOTE: registration of ncp_read, ncp_write & dev is linked. 
	//  It's the resposibility of this function to set these parameters together
		hid_func.dev = (void *)hdev;
		hid_func.read = NTRIGReadSensor;
		hid_func.write = NTRIGWriteSensor;
		nd->sensor_id = RegNtrigDispatcher(TYPE_BUS_USB_HID, hdev->uniq, NULL, &hid_func); 
		// TODO: define behavior in case of fail
		if (nd->sensor_id == DTRG_FAILED) {
			ntrig_dbg("%s: Cannot register device to dispatcher\n", __FUNCTION__);
			goto err_free;
		}
		ntrig_dbg("%s HID dev registered with dispatcher, bus_id = %s, sensor_id = %d\n", __FUNCTION__, hdev->uniq, nd->sensor_id);
	}
	/**
	 * Create additional single touch queue
         */

	usb_make_path(dev, phys_path, sizeof(phys_path));
	strlcat(phys_path, "/input0", sizeof(phys_path));
	
	nd->ntrig_dispatcher->phys = phys_path;
	nd->ntrig_dispatcher->name = "USBHID";
	nd->ntrig_dispatcher->pressure_min= 0;
	nd->ntrig_dispatcher->pressure_max= 0xFF;
	create_single_touch(nd->ntrig_dispatcher, nd->sensor_id);
	create_multi_touch (nd->ntrig_dispatcher, nd->sensor_id);

	nd->battery_status = PEN_BUTTON_BATTERY_NOT_AVAILABLE;

	ntrig_dbg("Iside %s, bus_id = %d, name = %s, phys = %s, uniq = %s\n", __FUNCTION__, hdev->bus, hdev->name, hdev->phys, hdev->uniq );

	ntrig_dbg("End of %s\n", __FUNCTION__);
	return DTRG_NO_ERROR;
err_free:
	ntrig_dbg("Error End of %s\n", __FUNCTION__);
	remove_device(&nd->ntrig_dispatcher);	
	kfree(nd);
	return DTRG_FAILED;
}
예제 #26
0
/*
 * this function is called upon all reports
 * so that we can filter contact point information,
 * decide whether we are in multi or single touch mode
 * and call input_mt_sync after each point if necessary
 */
static int ntrig_usbhid_event(struct hid_device *hid, struct hid_field *field,
			struct hid_usage *usage, __s32 value)
{
	struct usb_interface*		intf	 = to_usb_interface(hid->dev.parent);
	struct usb_host_interface*	interface= intf->cur_altsetting;
	struct usb_endpoint_descriptor*	endpoint = &interface->endpoint[0].desc;
	__s32				btn	 = BTN_UNPRESSED;	
	static __u16 ncp_report_counter = 0;

	/* ntrig_dbg("%s: us=%4X, ap=%4X, ep=%4X, cl=%4X val=%4X\n ", 
			  __FUNCTION__, usage->hid, field->application, endpoint->bEndpointAddress, hid->claimed, value); */
	if ( NCP_EP_ADDRESS == endpoint->bEndpointAddress ) {
	    switch (ncp_report_counter) {
		case NCP_HEADER: 
		  /* We Do Nothing with this, because each report as a diffrent start address */
		  break; 
		case NCP_HOSTADD_LSB: 
		  ncp.host_address = value;
		  break;
		case NCP_HOSTADD_MSB:
		  ncp.host_address |= value << 8;
		  break;
		case NCP_MSG_LEN_LSB: 
		  ncp.msg_length = value;
		  break;
		case NCP_MSG_LEN_MSB: 
		  ncp.msg_length |= value << 8;
		  break;
		case NCP_MSG_TYPE: 
		  ncp.msg_type = value;
		case NCP_CODE: 
		  ncp.msg_group_code = value;
		  break;
		case NCP_GROUP: 
		  ncp.msg_group_code |= value << 8;
		  break;
		case NCP_RTN_CODE_1:
		case NCP_RTN_CODE_2:
		case NCP_RTN_CODE_3:
		case NCP_RTN_CODE_4:
		    ncp.return_code[ncp_report_counter - 8] = value;
		    break;
		case NCP_RESERVED_LSB:
		    ncp.reserved = value;
		    break;
		case NCP_RESERVED_MSB:
		    ncp.reserved |= value << 8;
		    break;  
		default:
		    ncp.payload[ncp_report_counter -14] = value;
		  break;
	    }
	    if (++ncp_report_counter == field->report_count)
		ncp_report_counter = 0;
	    return 1;
	}
	if (hid->claimed & HID_CLAIMED_INPUT) {
	    struct ntrig_usbhid_data*	nd	= hid_get_drvdata(hid);
	    struct input_dev*		input	= field->hidinput->input;

	    /* We attach multi touch to dispatcher if there is no multi touch queue*/
	    if(!check_multi_touch(nd->sensor_id)) {
		ntrig_dbg("%s Attach Multi Touch device to dispatcher\n", __FUNCTION__);
		attach_multi_touch(nd->sensor_id, input);
	    }	

	    /* We attach multi touch to dispatcher if there is no single touch queue */
	    if(!check_single_touch(nd->sensor_id)) {
		ntrig_dbg("%s Attach Single Touch device to dispatcher\n", __FUNCTION__);
		attach_single_touch(nd->sensor_id, input);
	    }	

	    switch (usage->hid) {
		case HID_GD_X:
		/* ntrig_dbg("%s: HID_GD_X=%d\n", __FUNCTION__, value); */
		nd->x = value;
		break;
	    case HID_GD_Y:
		/* ntrig_dbg("%s: HID_GD_Y=%d\n", __FUNCTION__, value); */
		nd->y = value;
		break;
	    }
	    if (field->application == HID_DG_PEN) {
		switch (usage->hid) {
			case HID_DG_INRANGE:
//	ntrig_dbg("%s: HID_DG_PEN: HID_DG_INRANGE=%x, value %d\n", __FUNCTION__, usage->hid, value);
				nd->events = value;
				break;
			case HID_DG_TIPSWITCH:
//	ntrig_dbg("%s: HID_DG_PEN: HID_DG_TIPSWITCH=%x, value %d\n", __FUNCTION__, usage->hid, value);
				nd->events |= (value << 1);
				break;
			case HID_DG_BARRELSWITCH:
//	ntrig_dbg("%s: HID_DG_PEN: HID_DG_BARRELSWITCH=%x, value %d\n", __FUNCTION__, usage->hid, value);
				nd->events |= (value << 2);
				break;
			case HID_DG_INVERT:
//	ntrig_dbg("%s: HID_DG_PEN: HID_DG_INVERT=%x, value %d\n", __FUNCTION__, usage->hid, value);
				nd->events |= (value << 3);
				break;
			case HID_DG_ERASER:
//	ntrig_dbg("%s: HID_DG_PEN: HID_DG_ERASER=%x, value %d\n", __FUNCTION__, usage->hid, value);
				nd->events |= (value << 4);
				break;
			case HID_DG_TIPPRESSURE:
//	ntrig_dbg("%s: HID_DG_PEN: HID_DG_TIPPRESSURE=%x, value %d\n", __FUNCTION__, usage->hid, value);
				nd->pressure = value;
				btn = (int) nd->events;
				/* process button information and send to dispatcher if required */			
				set_button(nd, btn); 
				/* send pen data to dispatcher */ 
				send_pen  (nd);	   
				/* print button and pen data */
//				ntrig_dbg("Privet X=%d Y=%d Button=%d Pressure=%d\n", 
//					nd->x, 
//					nd->y, 
//					nd->btn_pressed, 
//					nd->pressure);
				break;
#if 0
			case PEN_BATTERY_STATUS:
//	ntrig_dbg("%s: HID_DG_PEN: PEN_BATTERY_STATUS=%x, value %d\n", __FUNCTION__, usage->hid, value);
				if (nd->events & 0x01)	// TIPSWITCH == true --> pen is touching the screen --> battery_status value is valid
					nd->battery_status = value;
				else			// TIPSWITCH == false --> pen is not touching the screen --> battery_status value is not valid
					nd->battery_status = PEN_BUTTON_BATTERY_NOT_AVAILABLE;
	ntrig_dbg("%s: HID_DG_PEN: PEN_BATTERY_STATUS=%x, value %d, batter_status = %d, \n", __FUNCTION__, usage->hid, value, nd->battery_status);
				break;
#endif
			default:
//				ntrig_dbg("%s: HID_DG_PEN: default=%x, value %d\n", __FUNCTION__, usage->hid, value);
				break;
		}
	   } else { /* MultiTouch Report */
			switch (usage->hid) {
			case HID_DG_CONTACTCOUNT:
				nd->contact_count = value;
				/* end of report (this field always comes last) - send to dispatcher*/
				send_multi_touch(nd);
				break;
			case MTM_FRAME_INDEX: /* Index 1 */
//				ntrig_dbg("%s: MultiTouch Report: MTM_FRAME_INDEX=%x, value %d\n", __FUNCTION__, usage->hid, value);
				nd->frame_index = value;
				break;
			case HID_DG_TIPSWITCH:	/* FALLTHRU */
			case HID_DG_INRANGE:	/* FALLTHRU */
			case HID_DG_CONFIDENCE: /* Not Relevant-Index 2 - 4 */
				break;
			case HID_DG_CONTACTID: /* Index 5 */
				nd->finger_id = value;
				break;
			case HID_DG_WIDTH:/* Index 6 - 7*/
				nd->dx = value;
				break;
			case HID_DG_HEIGHT:/* Index 8 - 9 */
				nd->dy = value;
				/* Start The Sequence of MSC bytes */
				nd->msc_cnt = 0;
				break;
			case MTM_PROPRIETARY:/* Index 10 - 14 */
//				ntrig_dbg("%s: MultiTouch Report: v=%x, value %d\n", __FUNCTION__, usage->hid, value);
				nd->msc_cnt++;
//				ntrig_dbg("%s: MTM_PROPRIETARY msc_cnt=%d val=%d\n", __FUNCTION__, nd->msc_cnt, value);
				switch (nd->msc_cnt) {
				case REPORT_GENERIC1:
					nd->generic_byte = value;
					break;
				case REPORT_MT:
					nd->blob_id = value;
					break;
				case REPORT_PALM:
					nd->isPalm = value;
					break;
				case REPORT_GENERIC2:
					/* end of single finger part of report */
					 /* process multi touch finger data */
					process_multi_touch_finger(nd);
					/* Print finger data */						
					ntrig_dbg("Frame=%x Finger=%d X=%d Y=%d DX=%d DY=%d FirstOccur=%d Palm=%d Press=%d Blob=%d\n",
							nd->frame_index, 
							nd->finger_id, 
							nd->x,
							nd->y, 
							nd->dx, 
							nd->dy,
							nd->generic_byte, 
							nd->isPalm, 
							nd->pressure,
							nd->blob_id);
					break;
				}
				break;
			}
		}
	}
	/* we have handled the hidinput part, now remains hiddev */
	if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event)
		hid->hiddev_hid_event(hid, field, usage, value);
	return 1;
}
예제 #27
0
/*
 * Create folder "board_properties" under sysfs, 
 * and create file virtualskeys.<dev-name> under this folder
 */
static void ntrig_create_virtualkeys_file(void)
{
	int retval;
	int i;
	char tmpbuf[CHARS_PER_NUMBER*6+sizeof(char)*7];

	ntrig_dbg( "inside %s\n", __FUNCTION__);	
	
	/* At this stage we support a sinlge device for virtual keys. Hence leaving this function
	   if file for this device is already created.
	   If we support more devices in the future - this is the place to create a new file. */	
	if (board_properties_kobj) {
		ntrig_dbg( "inside %s - virtualkey file for the device alreay created !\n", __FUNCTION__);
		return;	
	}
	
	/* 1. Create folder "board_properties" under "sys" */
	/* allocate the memory for the whole object */
	board_properties_kobj = kobject_create_and_add("board_properties", NULL);
	ntrig_dbg( "inside %s\n", __FUNCTION__);	

	if (!board_properties_kobj) {
		ntrig_dbg( "inside %s - kobject_create_and_add FAILED\n", __FUNCTION__);	
		return;
	}

	/*
	 * We are always responsible for sending the uevent that the kobject
	 * was added to the system.
	 */
	kobject_uevent(board_properties_kobj, KOBJ_ADD);

	/* 2. Create virtual keys file name */
	sprintf(virtual_keys_file_name, "%s%s",VIRTUAL_KEYS_FILE_PREFIX, NTRIG_DEVICE_NAME);
	ntrig_properties_attrs->name = virtual_keys_file_name;

	/* 3. create file "virtualkeys" under folder "board_properties"  */
	/* create the file "virtualkeys.<ntrig-dev-name>" under "board_properties" folder */
	retval = sysfs_create_file(board_properties_kobj, ntrig_properties_attrs);

	if (retval != EOK) {
		ntrig_dbg( "inside %s - sysfs_create_file FAILED\n", __FUNCTION__);	

		/* remove properties_kobj */
		kobject_put(board_properties_kobj);
		return;
	}

	/* 3. Write Virtual keys definitions into the file */
	/* There is no actual writing to file system.
 	   Instead, we create a char buffer containing the data entered by the user,
	   in the format expected by the reading module. 
	   The buffer is global to this source file, so it can be accessed by the "show" function. */
	
	/* see expected format of the buffer in function readVirtualKeys in file KeyInputQueue.java */
	/* Data for all keys is written into the same buffer. */
	/* Format of data for each key is: scan-kode:center-x:center-y:width:hight\n */

	virtual_keys_attr_buf[0] = '\0';
	/* a tmp buffer to contain data of one key in string format */ 
	for (i=0; i<VIRTUAL_KEYS_NUM; i++) {
		
		sprintf(tmpbuf, "0x01:%d:%d:%d:%d:%d:", 
			_ntrig_virt_keys[i].scan_code,
			_ntrig_virt_keys[i].center_x,
			_ntrig_virt_keys[i].center_y,
			_ntrig_virt_keys[i].width,
			_ntrig_virt_keys[i].height);

		strcat(virtual_keys_attr_buf, tmpbuf);		
	}

	/* remove last ':' */
	virtual_keys_attr_buf[strlen(virtual_keys_attr_buf)-1] = 0;
		
	ntrig_dbg( "inside %s - attributes = %s, len = %d\n", __FUNCTION__, virtual_keys_attr_buf, strlen(virtual_keys_attr_buf) );
}	
예제 #28
0
/*
 * Read (show) data from the sysfs file
 */
static ssize_t ntrig_virtual_keys_show(struct kobject *kobj,
		struct kobj_attribute *attr, char *buf)
{
	ntrig_dbg( "inside %s - attributes = %s\n", __FUNCTION__, virtual_keys_attr_buf );	
	return snprintf(buf, PAGE_SIZE, "%s\n", virtual_keys_attr_buf);
}