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

📄 aiptek.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct aiptek *aiptek = dev_get_drvdata(dev);	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, struct device_attribute *attr, char *buf){	/* 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, struct device_attribute *attr, const char *buf, size_t count){	struct aiptek *aiptek = dev_get_drvdata(dev);	/* 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, struct device_attribute *attr, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	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, struct device_attribute *attr, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	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, struct device_attribute *attr, char *buf){	struct aiptek *aiptek = dev_get_drvdata(dev);	return snprintf(buf, PAGE_SIZE, "%04x\n",			aiptek->features.firmwareCode);}static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);static struct attribute *aiptek_attributes[] = {	&dev_attr_size.attr,	&dev_attr_pointer_mode.attr,	&dev_attr_coordinate_mode.attr,	&dev_attr_tool_mode.attr,	&dev_attr_xtilt.attr,	&dev_attr_ytilt.attr,	&dev_attr_jitter.attr,	&dev_attr_delay.attr,	&dev_attr_event_count.attr,	&dev_attr_diagnostic.attr,	&dev_attr_odm_code.attr,	&dev_attr_model_code.attr,	&dev_attr_firmware_code.attr,	&dev_attr_stylus_lower.attr,	&dev_attr_stylus_upper.attr,	&dev_attr_mouse_left.attr,	&dev_attr_mouse_middle.attr,	&dev_attr_mouse_right.attr,	&dev_attr_wheel.attr,	&dev_attr_execute.attr,	NULL};static struct attribute_group aiptek_attribute_group = {	.attrs	= aiptek_attributes,};/*********************************************************************** * 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;	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	};	int err = -ENOMEM;	/* 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;	aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);	inputdev = input_allocate_device();	if (!aiptek || !inputdev) {		warn("aiptek: cannot allocate memory or input device");		goto fail1;        }	aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,					GFP_ATOMIC, &aiptek->data_dma);        if (!aiptek->data) {		warn("aiptek: cannot allocate usb buffer");		goto fail1;	}	aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);	if (!aiptek->urb) {	        warn("aiptek: cannot allocate urb");		goto fail2;	}	aiptek->inputdev = inputdev;	aiptek->usbdev = usbdev;	aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;	aiptek->inDelay = 0;	aiptek->endDelay = 0;	aiptek->previousJitterable = 0;	aiptek->lastMacro = -1;	/* 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	 */	aiptek->newSetting = aiptek->curSetting;	/* 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...	 */	usb_make_path(usbdev, aiptek->features.usbPath,			sizeof(aiptek->features.usbPath));	strlcat(aiptek->features.usbPath, "/input0",		sizeof(aiptek->features.usbPath));	/* Set up client data, pointers to open and close routines	 * for the input device.	 */	inputdev->name = "Aiptek";	inputdev->phys = aiptek->features.usbPath;	usb_to_input_id(usbdev, &inputdev->id);	inputdev->dev.parent = &intf->dev;	input_set_drvdata(inputdev, aiptek);	inputdev->open = aiptek_open;	inputdev->close = aiptek_close;	/* Now program the capacities of the tablet, in terms of being	 * an input device.	 */	for (i = 0; i < ARRAY_SIZE(eventTypes); ++i)	        __set_bit(eventTypes[i], inputdev->evbit);	for (i = 0; i < ARRAY_SIZE(absEvents); ++i)	        __set_bit(absEvents[i], inputdev->absbit);	for (i = 0; i < ARRAY_SIZE(relEvents); ++i)	        __set_bit(relEvents[i], inputdev->relbit);	__set_bit(MSC_SERIAL, inputdev->mscbit);	/* Set up key and button codes */	for (i = 0; i < ARRAY_SIZE(buttonEvents); ++i)		__set_bit(buttonEvents[i], inputdev->keybit);	for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)		__set_bit(macroKeyEvents[i], inputdev->keybit);	/*	 * 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.	 */	input_set_abs_params(inputdev, ABS_X, 0, 2999, 0, 0);	input_set_abs_params(inputdev, ABS_Y, 0, 2249, 0, 0);	input_set_abs_params(inputdev, ABS_PRESSURE, 0, 511, 0, 0);	input_set_abs_params(inputdev, ABS_TILT_X, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);	input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);	input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);	endpoint = &intf->altsetting[0].endpoint[0].desc;	/* Go set up our URB, which is called when the tablet receives	 * input.	 */	usb_fill_int_urb(aiptek->urb,			 aiptek->usbdev,			 usb_rcvintpipe(aiptek->usbdev,					endpoint->bEndpointAddress),			 aiptek->data, 8, aiptek_irq, aiptek,			 endpoint->bInterval);	aiptek->urb->transfer_dma = aiptek->data_dma;	aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;	/* Program the tablet. This sets the tablet up in the mode	 * specified in newSetting, and also queries the tablet's	 * physical capacities.	 *	 * Sanity check: if a tablet doesn't like the slow programmatic	 * delay, we often get sizes of 0x0. Let's use that as an indicator	 * to try faster delays, up to 25 ms. If that logic fails, well, you'll	 * have to explain to us how your tablet thinks it's 0x0, and yet that's	 * not an error :-)	 */	for (i = 0; i < ARRAY_SIZE(speeds); ++i) {		aiptek->curSetting.programmableDelay = speeds[i];		(void)aiptek_program_tablet(aiptek);		if (aiptek->inputdev->absmax[ABS_X] > 0) {			info("input: Aiptek using %d ms programming speed\n",			     aiptek->curSetting.programmableDelay);			break;		}	}	/* Murphy says that some day someone will have a tablet that fails the	   above test. That's you, Frederic Rodrigo */	if (i == ARRAY_SIZE(speeds)) {		info("input: Aiptek tried all speeds, no sane response");		goto fail2;	}	/* Associate this driver's struct with the usb interface.	 */	usb_set_intfdata(intf, aiptek);	/* Set up the sysfs files	 */	err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);	if (err) {		warn("aiptek: cannot create sysfs group err: %d", err);		goto fail3;        }	/* Register the tablet as an Input Device	 */	err = input_register_device(aiptek->inputdev);	if (err) {		warn("aiptek: input_register_device returned err: %d", err);		goto fail4;        }	return 0; fail4:	sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); fail3: usb_free_urb(aiptek->urb); fail2:	usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,			aiptek->data_dma); fail1: usb_set_intfdata(intf, NULL);	input_free_device(inputdev);	kfree(aiptek);	return err;}/*********************************************************************** * Deal with tablet disconnecting from the system. */static void aiptek_disconnect(struct usb_interface *intf){	struct aiptek *aiptek = usb_get_intfdata(intf);	/* Disassociate driver's struct with usb interface	 */	usb_set_intfdata(intf, NULL);	if (aiptek != NULL) {		/* Free & unhook everything from the system.		 */		usb_kill_urb(aiptek->urb);		input_unregister_device(aiptek->inputdev);		sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);		usb_free_urb(aiptek->urb);		usb_buffer_free(interface_to_usbdev(intf),				AIPTEK_PACKET_LENGTH,				aiptek->data, aiptek->data_dma);		kfree(aiptek);	}}static struct usb_driver aiptek_driver = {	.name = "aiptek",	.probe = aiptek_probe,	.disconnect = aiptek_disconnect,	.id_table = aiptek_ids,};static int __init aiptek_init(void){	int result = usb_register(&aiptek_driver);	if (result == 0) {		info(DRIVER_VERSION ": " DRIVER_AUTHOR);		info(DRIVER_DESC);	}	return result;}static void __exit aiptek_exit(void){	usb_deregister(&aiptek_driver);}MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");module_param(programmableDelay, int, 0);MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming");module_param(jitterDelay, int, 0);MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay");module_init(aiptek_init);module_exit(aiptek_exit);

⌨️ 快捷键说明

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