📄 aiptek.c
字号:
usb_kill_urb(aiptek->urb);}/*********************************************************************** * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, * where they were known as usb_set_report and usb_get_report. */static intaiptek_set_report(struct aiptek *aiptek, unsigned char report_type, unsigned char report_id, void *buffer, int size){ return usb_control_msg(aiptek->usbdev, usb_sndctrlpipe(aiptek->usbdev, 0), USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, (report_type << 8) + report_id, aiptek->ifnum, buffer, size, 5000);}static intaiptek_get_report(struct aiptek *aiptek, unsigned char report_type, unsigned char report_id, void *buffer, int size){ return usb_control_msg(aiptek->usbdev, usb_rcvctrlpipe(aiptek->usbdev, 0), USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, (report_type << 8) + report_id, aiptek->ifnum, buffer, size, 5000);}/*********************************************************************** * Send a command to the tablet. */static intaiptek_command(struct aiptek *aiptek, unsigned char command, unsigned char data){ const int sizeof_buf = 3 * sizeof(u8); int ret; u8 *buf; buf = kmalloc(sizeof_buf, GFP_KERNEL); if (!buf) return -ENOMEM; buf[0] = 2; buf[1] = command; buf[2] = data; if ((ret = aiptek_set_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { dbg("aiptek_program: failed, tried to send: 0x%02x 0x%02x", command, data); } kfree(buf); return ret < 0 ? ret : 0;}/*********************************************************************** * Retrieve information from the tablet. Querying info is defined as first * sending the {command,data} sequence as a command, followed by a wait * (aka, "programmaticDelay") and then a "read" request. */static intaiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data){ const int sizeof_buf = 3 * sizeof(u8); int ret; u8 *buf; buf = kmalloc(sizeof_buf, GFP_KERNEL); if (!buf) return -ENOMEM; buf[0] = 2; buf[1] = command; buf[2] = data; if (aiptek_command(aiptek, command, data) != 0) { kfree(buf); return -EIO; } msleep(aiptek->curSetting.programmableDelay); if ((ret = aiptek_get_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { dbg("aiptek_query failed: returned 0x%02x 0x%02x 0x%02x", buf[0], buf[1], buf[2]); ret = -EIO; } else { ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1))); } kfree(buf); return ret;}/*********************************************************************** * Program the tablet into either absolute or relative mode. * We also get information about the tablet's size. */static int aiptek_program_tablet(struct aiptek *aiptek){ int ret; /* Execute Resolution500LPI */ if ((ret = aiptek_command(aiptek, 0x18, 0x04)) < 0) return ret; /* Query getModelCode */ if ((ret = aiptek_query(aiptek, 0x02, 0x00)) < 0) return ret; aiptek->features.modelCode = ret & 0xff; /* Query getODMCode */ if ((ret = aiptek_query(aiptek, 0x03, 0x00)) < 0) return ret; aiptek->features.odmCode = ret; /* Query getFirmwareCode */ if ((ret = aiptek_query(aiptek, 0x04, 0x00)) < 0) return ret; aiptek->features.firmwareCode = ret; /* Query getXextension */ if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0) return ret; aiptek->inputdev->absmin[ABS_X] = 0; aiptek->inputdev->absmax[ABS_X] = ret - 1; /* Query getYextension */ if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0) return ret; aiptek->inputdev->absmin[ABS_Y] = 0; aiptek->inputdev->absmax[ABS_Y] = ret - 1; /* Query getPressureLevels */ if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0) return ret; aiptek->inputdev->absmin[ABS_PRESSURE] = 0; aiptek->inputdev->absmax[ABS_PRESSURE] = ret - 1; /* Depending on whether we are in absolute or relative mode, we will * do a switchToTablet(absolute) or switchToMouse(relative) command. */ if (aiptek->curSetting.coordinateMode == AIPTEK_COORDINATE_ABSOLUTE_MODE) { /* Execute switchToTablet */ if ((ret = aiptek_command(aiptek, 0x10, 0x01)) < 0) { return ret; } } else { /* Execute switchToMouse */ if ((ret = aiptek_command(aiptek, 0x10, 0x00)) < 0) { return ret; } } /* Enable the macro keys */ if ((ret = aiptek_command(aiptek, 0x11, 0x02)) < 0) return ret;#if 0 /* Execute FilterOn */ if ((ret = aiptek_command(aiptek, 0x17, 0x00)) < 0) return ret;#endif /* Execute AutoGainOn */ if ((ret = aiptek_command(aiptek, 0x12, 0xff)) < 0) return ret; /* Reset the eventCount, so we track events from last (re)programming */ aiptek->diagnostic = AIPTEK_DIAGNOSTIC_NA; aiptek->eventCount = 0; return 0;}/*********************************************************************** * Sysfs functions. Sysfs prefers that individually-tunable parameters * exist in their separate pseudo-files. Summary data that is immutable * may exist in a singular file so long as you don't define a writeable * interface. *//*********************************************************************** * support the 'size' file -- display support */static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr, char *buf){ struct aiptek *aiptek = dev_get_drvdata(dev); if (aiptek == NULL) return 0; return snprintf(buf, PAGE_SIZE, "%dx%d\n", aiptek->inputdev->absmax[ABS_X] + 1, aiptek->inputdev->absmax[ABS_Y] + 1);}/* These structs define the sysfs files, param #1 is the name of the * file, param 2 is the file permissions, param 3 & 4 are to the * output generator and input parser routines. Absence of a routine is * permitted -- it only means can't either 'cat' the file, or send data * to it. */static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL);/*********************************************************************** * support routines for the 'product_id' file */static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf){ struct aiptek *aiptek = dev_get_drvdata(dev); if (aiptek == NULL) return 0; return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.product);}static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);/*********************************************************************** * support routines for the 'vendor_id' file */static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf){ struct aiptek *aiptek = dev_get_drvdata(dev); if (aiptek == NULL) return 0; return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);}static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);/*********************************************************************** * support routines for the 'vendor' file */static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf){ struct aiptek *aiptek = dev_get_drvdata(dev); int retval; if (aiptek == NULL) return 0; retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer); return retval;}static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL);/*********************************************************************** * support routines for the 'product' file */static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf){ struct aiptek *aiptek = dev_get_drvdata(dev); int retval; if (aiptek == NULL) return 0; retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product); return retval;}static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL);/*********************************************************************** * support routines for the 'pointer_mode' file. Note that this file * both displays current setting and allows reprogramming. */static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf){ struct aiptek *aiptek = dev_get_drvdata(dev); char *s; if (aiptek == NULL) return 0; switch (aiptek->curSetting.pointerMode) { case AIPTEK_POINTER_ONLY_STYLUS_MODE: s = "stylus"; break; case AIPTEK_POINTER_ONLY_MOUSE_MODE: s = "mouse"; break; case AIPTEK_POINTER_EITHER_MODE: s = "either"; break; default: s = "unknown"; break; } return snprintf(buf, PAGE_SIZE, "%s\n", s);}static ssize_tstore_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct aiptek *aiptek = dev_get_drvdata(dev); if (aiptek == NULL) return 0; if (strcmp(buf, "stylus") == 0) { aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_STYLUS_MODE; } else if (strcmp(buf, "mouse") == 0) { aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE; } else if (strcmp(buf, "either") == 0) { aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE; } return count;}static DEVICE_ATTR(pointer_mode, S_IRUGO | S_IWUGO, show_tabletPointerMode, store_tabletPointerMode);/*********************************************************************** * support routines for the 'coordinate_mode' file. Note that this file * both displays current setting and allows reprogramming. */static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf){ struct aiptek *aiptek = dev_get_drvdata(dev); char *s; if (aiptek == NULL) return 0; switch (aiptek->curSetting.coordinateMode) { case AIPTEK_COORDINATE_ABSOLUTE_MODE: s = "absolute"; break; case AIPTEK_COORDINATE_RELATIVE_MODE: s = "relative"; break; default: s = "unknown"; break; } return snprintf(buf, PAGE_SIZE, "%s\n", s);}static ssize_tstore_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct aiptek *aiptek = dev_get_drvdata(dev); if (aiptek == NULL) return 0; if (strcmp(buf, "absolute") == 0) { aiptek->newSetting.pointerMode = AIPTEK_COORDINATE_ABSOLUTE_MODE; } else if (strcmp(buf, "relative") == 0) { aiptek->newSetting.pointerMode = AIPTEK_COORDINATE_RELATIVE_MODE; } return count;}static DEVICE_ATTR(coordinate_mode, S_IRUGO | S_IWUGO, show_tabletCoordinateMode, store_tabletCoordinateMode);/*********************************************************************** * support routines for the 'tool_mode' file. Note that this file * both displays current setting and allows reprogramming. */static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf){ struct aiptek *aiptek = dev_get_drvdata(dev); char *s; if (aiptek == NULL) return 0; switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) { case AIPTEK_TOOL_BUTTON_MOUSE_MODE: s = "mouse"; break; case AIPTEK_TOOL_BUTTON_ERASER_MODE: s = "eraser"; break; case AIPTEK_TOOL_BUTTON_PENCIL_MODE: s = "pencil"; break; case AIPTEK_TOOL_BUTTON_PEN_MODE: s = "pen"; break; case AIPTEK_TOOL_BUTTON_BRUSH_MODE: s = "brush"; break; case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE: s = "airbrush"; break; case AIPTEK_TOOL_BUTTON_LENS_MODE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -