⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aiptek.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	default:		s = "unknown";		break;	}	return snprintf(buf, PAGE_SIZE, "%s\n", s);}static ssize_tstore_tabletMouseMiddle(struct device *dev, const char *buf, size_t count){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	if (strcmp(buf, "left") == 0) {		aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON;	} else if (strcmp(buf, "middle") == 0) {		aiptek->newSetting.mouseButtonMiddle =		    AIPTEK_MOUSE_MIDDLE_BUTTON;	} else if (strcmp(buf, "right") == 0) {		aiptek->newSetting.mouseButtonMiddle =		    AIPTEK_MOUSE_RIGHT_BUTTON;	}	return count;}static DEVICE_ATTR(mouse_middle,		   S_IRUGO | S_IWUGO,		   show_tabletMouseMiddle, store_tabletMouseMiddle);/*********************************************************************** * support routines for the 'mouse_right' file. Note that this file * both displays current setting and allows for setting changing. */static ssize_t show_tabletMouseRight(struct device *dev, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	char *s;	if (aiptek == NULL)		return 0;	switch (aiptek->curSetting.mouseButtonRight) {	case AIPTEK_MOUSE_LEFT_BUTTON:		s = "left";		break;	case AIPTEK_MOUSE_MIDDLE_BUTTON:		s = "middle";		break;	case AIPTEK_MOUSE_RIGHT_BUTTON:		s = "right";		break;	default:		s = "unknown";		break;	}	return snprintf(buf, PAGE_SIZE, "%s\n", s);}static ssize_tstore_tabletMouseRight(struct device *dev, const char *buf, size_t count){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	if (strcmp(buf, "left") == 0) {		aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON;	} else if (strcmp(buf, "middle") == 0) {		aiptek->newSetting.mouseButtonRight =		    AIPTEK_MOUSE_MIDDLE_BUTTON;	} else if (strcmp(buf, "right") == 0) {		aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON;	}	return count;}static DEVICE_ATTR(mouse_right,		   S_IRUGO | S_IWUGO,		   show_tabletMouseRight, store_tabletMouseRight);/*********************************************************************** * support routines for the 'wheel' file. Note that this file * both displays current setting and allows for setting changing. */static ssize_t show_tabletWheel(struct device *dev, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {		return snprintf(buf, PAGE_SIZE, "disable\n");	} else {		return snprintf(buf, PAGE_SIZE, "%d\n",				aiptek->curSetting.wheel);	}}static ssize_tstore_tabletWheel(struct device *dev, const char *buf, size_t count){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);	return count;}static DEVICE_ATTR(wheel,		   S_IRUGO | S_IWUGO, show_tabletWheel, store_tabletWheel);/*********************************************************************** * support routines for the 'execute' file. Note that this file * both displays current setting and allows for setting changing. */static ssize_t show_tabletExecute(struct device *dev, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	/* There is nothing useful to display, so a one-line manual	 * is in order...	 */	return snprintf(buf, PAGE_SIZE,			"Write anything to this file to program your tablet.\n");}static ssize_tstore_tabletExecute(struct device *dev, const char *buf, size_t count){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	/* We do not care what you write to this file. Merely the action	 * of writing to this file triggers a tablet reprogramming.	 */	memcpy(&aiptek->curSetting, &aiptek->newSetting,	       sizeof(struct aiptek_settings));	if (aiptek_program_tablet(aiptek) < 0)		return -EIO;	return count;}static DEVICE_ATTR(execute,		   S_IRUGO | S_IWUGO, show_tabletExecute, store_tabletExecute);/*********************************************************************** * support routines for the 'odm_code' file. Note that this file * only displays current setting. */static ssize_t show_tabletODMCode(struct device *dev, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode);}static DEVICE_ATTR(odm_code, S_IRUGO, show_tabletODMCode, NULL);/*********************************************************************** * support routines for the 'model_code' file. Note that this file * only displays current setting. */static ssize_t show_tabletModelCode(struct device *dev, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode);}static DEVICE_ATTR(model_code, S_IRUGO, show_tabletModelCode, NULL);/*********************************************************************** * support routines for the 'firmware_code' file. Note that this file * only displays current setting. */static ssize_t show_firmwareCode(struct device *dev, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	if (aiptek == NULL)		return 0;	return snprintf(buf, PAGE_SIZE, "%04x\n",			aiptek->features.firmwareCode);}static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);/*********************************************************************** * This routine removes all existing sysfs files managed by this device * driver. */static void aiptek_delete_files(struct device *dev){	device_remove_file(dev, &dev_attr_size);	device_remove_file(dev, &dev_attr_product_id);	device_remove_file(dev, &dev_attr_vendor_id);	device_remove_file(dev, &dev_attr_vendor);	device_remove_file(dev, &dev_attr_product);	device_remove_file(dev, &dev_attr_pointer_mode);	device_remove_file(dev, &dev_attr_coordinate_mode);	device_remove_file(dev, &dev_attr_tool_mode);	device_remove_file(dev, &dev_attr_xtilt);	device_remove_file(dev, &dev_attr_ytilt);	device_remove_file(dev, &dev_attr_jitter);	device_remove_file(dev, &dev_attr_delay);	device_remove_file(dev, &dev_attr_input_path);	device_remove_file(dev, &dev_attr_event_count);	device_remove_file(dev, &dev_attr_diagnostic);	device_remove_file(dev, &dev_attr_odm_code);	device_remove_file(dev, &dev_attr_model_code);	device_remove_file(dev, &dev_attr_firmware_code);	device_remove_file(dev, &dev_attr_stylus_lower);	device_remove_file(dev, &dev_attr_stylus_upper);	device_remove_file(dev, &dev_attr_mouse_left);	device_remove_file(dev, &dev_attr_mouse_middle);	device_remove_file(dev, &dev_attr_mouse_right);	device_remove_file(dev, &dev_attr_wheel);	device_remove_file(dev, &dev_attr_execute);}/*********************************************************************** * This routine creates the sysfs files managed by this device * driver. */static int aiptek_add_files(struct device *dev){	int ret;	if ((ret = device_create_file(dev, &dev_attr_size)) ||	    (ret = device_create_file(dev, &dev_attr_product_id)) ||	    (ret = device_create_file(dev, &dev_attr_vendor_id)) ||	    (ret = device_create_file(dev, &dev_attr_vendor)) ||	    (ret = device_create_file(dev, &dev_attr_product)) ||	    (ret = device_create_file(dev, &dev_attr_pointer_mode)) ||	    (ret = device_create_file(dev, &dev_attr_coordinate_mode)) ||	    (ret = device_create_file(dev, &dev_attr_tool_mode)) ||	    (ret = device_create_file(dev, &dev_attr_xtilt)) ||	    (ret = device_create_file(dev, &dev_attr_ytilt)) ||	    (ret = device_create_file(dev, &dev_attr_jitter)) ||	    (ret = device_create_file(dev, &dev_attr_delay)) ||	    (ret = device_create_file(dev, &dev_attr_input_path)) ||	    (ret = device_create_file(dev, &dev_attr_event_count)) ||	    (ret = device_create_file(dev, &dev_attr_diagnostic)) ||	    (ret = device_create_file(dev, &dev_attr_odm_code)) ||	    (ret = device_create_file(dev, &dev_attr_model_code)) ||	    (ret = device_create_file(dev, &dev_attr_firmware_code)) ||	    (ret = device_create_file(dev, &dev_attr_stylus_lower)) ||	    (ret = device_create_file(dev, &dev_attr_stylus_upper)) ||	    (ret = device_create_file(dev, &dev_attr_mouse_left)) ||	    (ret = device_create_file(dev, &dev_attr_mouse_middle)) ||	    (ret = device_create_file(dev, &dev_attr_mouse_right)) ||	    (ret = device_create_file(dev, &dev_attr_wheel)) ||	    (ret = device_create_file(dev, &dev_attr_execute))) {		err("aiptek: killing own sysfs device files\n");		aiptek_delete_files(dev);	}	return ret;}/*********************************************************************** * This routine is called when a tablet has been identified. It basically * sets up the tablet and the driver's internal structures. */static intaiptek_probe(struct usb_interface *intf, const struct usb_device_id *id){	struct usb_device *usbdev = interface_to_usbdev(intf);	struct usb_endpoint_descriptor *endpoint;	struct aiptek *aiptek;	struct input_dev *inputdev;	struct input_handle *inputhandle;	struct list_head *node, *next;	char path[64 + 1];	int i;	int speeds[] = { 0,		AIPTEK_PROGRAMMABLE_DELAY_50,		AIPTEK_PROGRAMMABLE_DELAY_400,		AIPTEK_PROGRAMMABLE_DELAY_25,		AIPTEK_PROGRAMMABLE_DELAY_100,		AIPTEK_PROGRAMMABLE_DELAY_200,		AIPTEK_PROGRAMMABLE_DELAY_300	};	/* programmableDelay is where the command-line specified	 * delay is kept. We make it the first element of speeds[],	 * so therefore, your override speed is tried first, then the	 * remainder. Note that the default value of 400ms will be tried	 * if you do not specify any command line parameter.	 */	speeds[0] = programmableDelay;	if ((aiptek = kmalloc(sizeof(struct aiptek), GFP_KERNEL)) == NULL)		return -ENOMEM;	memset(aiptek, 0, sizeof(struct aiptek));	aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,					SLAB_ATOMIC, &aiptek->data_dma);	if (aiptek->data == NULL) {		kfree(aiptek);		return -ENOMEM;	}	aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);	if (aiptek->urb == NULL) {		usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,				aiptek->data_dma);		kfree(aiptek);		return -ENOMEM;	}	/* Set up the curSettings struct. Said struct contains the current	 * programmable parameters. The newSetting struct contains changes	 * the user makes to the settings via the sysfs interface. Those	 * changes are not "committed" to curSettings until the user	 * writes to the sysfs/.../execute file.	 */	aiptek->curSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE;	aiptek->curSetting.coordinateMode = AIPTEK_COORDINATE_ABSOLUTE_MODE;	aiptek->curSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE;	aiptek->curSetting.xTilt = AIPTEK_TILT_DISABLE;	aiptek->curSetting.yTilt = AIPTEK_TILT_DISABLE;	aiptek->curSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON;	aiptek->curSetting.mouseButtonMiddle = AIPTEK_MOUSE_MIDDLE_BUTTON;	aiptek->curSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON;	aiptek->curSetting.stylusButtonUpper = AIPTEK_STYLUS_UPPER_BUTTON;	aiptek->curSetting.stylusButtonLower = AIPTEK_STYLUS_LOWER_BUTTON;	aiptek->curSetting.jitterDelay = jitterDelay;	aiptek->curSetting.programmableDelay = programmableDelay;	/* Both structs should have equivalent settings	 */	memcpy(&aiptek->newSetting, &aiptek->curSetting,	       sizeof(struct aiptek_settings));	/* Now program the capacities of the tablet, in terms of being	 * an input device.	 */	aiptek->inputdev.evbit[0] |= BIT(EV_KEY)	    | BIT(EV_ABS)	    | BIT(EV_REL)	    | BIT(EV_MSC);	aiptek->inputdev.absbit[0] |=	    (BIT(ABS_X) |	     BIT(ABS_Y) |	     BIT(ABS_PRESSURE) |	     BIT(ABS_TILT_X) |	     BIT(ABS_TILT_Y) | BIT(ABS_WHEEL) | BIT(ABS_MISC));	aiptek->inputdev.relbit[0] |=	    (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));	aiptek->inputdev.keybit[LONG(BTN_LEFT)] |=	    (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));	aiptek->inputdev.keybit[LONG(BTN_DIGI)] |=	    (BIT(BTN_TOOL_PEN) |	     BIT(BTN_TOOL_RUBBER) |	     BIT(BTN_TOOL_PENCIL) |	     BIT(BTN_TOOL_AIRBRUSH) |	     BIT(BTN_TOOL_BRUSH) |	     BIT(BTN_TOOL_MOUSE) |	     BIT(BTN_TOOL_LENS) |	     BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));	aiptek->inputdev.mscbit[0] = BIT(MSC_SERIAL);	/* Programming the tablet macro keys needs to be done with a for loop	 * as the keycodes are discontiguous.	 */	for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i)		set_bit(macroKeyEvents[i], aiptek->inputdev.keybit);	/* Set up client data, pointers to open and close routines	 * for the input device.	 */	aiptek->inputdev.private = aiptek;	aiptek->inputdev.open = aiptek_open;	aiptek->inputdev.close = aiptek_close;	/* Determine the usb devices' physical path.	 * Asketh not why we always pretend we're using "../input0",	 * but I suspect this will have to be refactored one	 * day if a single USB device can be a keyboard & a mouse	 * & a tablet, and the inputX number actually will tell	 * us something...	 */	if (usb_make_path(usbdev, path, 64) > 0)		sprintf(aiptek->features.usbPath, "%s/input0", path);	/* Program the input device coordinate capacities. We do not yet	 * know what maximum X, Y, and Z values are, so we're putting fake	 * values in. Later, we'll ask the tablet to put in the correct	 * values.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -