^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Pegasus Mobile Notetaker Pen input tablet driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2016 Martin Kepplinger <martink@posteo.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * request packet (control endpoint):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * |-------------------------------------|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * | Report ID | Nr of bytes | command |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * | (1 byte) | (1 byte) | (n bytes) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * |-------------------------------------|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * | 0x02 | n | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * |-------------------------------------|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * data packet after set xy mode command, 0x80 0xb5 0x02 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * and pen is in range:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * byte byte name value (bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * --------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * 0 status 0 1 0 0 0 0 X X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 1 color 0 0 0 0 H 0 S T
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 2 X low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 3 X high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * 4 Y low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 5 Y high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * X X battery state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * no state reported 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * battery low 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * battery good 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * H Hovering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * S Switch 1 (pen button)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * T Tip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/usb/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* USB HID defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define USB_REQ_GET_REPORT 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define USB_REQ_SET_REPORT 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define USB_VENDOR_ID_PEGASUSTECH 0x0e20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define USB_DEVICE_ID_PEGASUS_NOTETAKER_EN100 0x0101
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* device specific defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define NOTETAKER_REPORT_ID 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define NOTETAKER_SET_CMD 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define NOTETAKER_SET_MODE 0xb5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define NOTETAKER_LED_MOUSE 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define PEN_MODE_XY 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define SPECIAL_COMMAND 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define BUTTON_PRESSED 0xb5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define COMMAND_VERSION 0xa9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* in xy data packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define BATTERY_NO_REPORT 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define BATTERY_LOW 0x41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define BATTERY_GOOD 0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define PEN_BUTTON_PRESSED BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define PEN_TIP BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct pegasus {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u8 data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) dma_addr_t data_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct input_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct usb_device *usbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct usb_interface *intf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct urb *irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* serialize access to open/suspend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct mutex pm_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) bool is_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) char name[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) char phys[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct work_struct init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int pegasus_control_msg(struct pegasus *pegasus, u8 *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) const int sizeof_buf = len + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u8 *cmd_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) cmd_buf = kmalloc(sizeof_buf, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!cmd_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) cmd_buf[0] = NOTETAKER_REPORT_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) cmd_buf[1] = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) memcpy(cmd_buf + 2, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) result = usb_control_msg(pegasus->usbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) usb_sndctrlpipe(pegasus->usbdev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) USB_REQ_SET_REPORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) USB_TYPE_VENDOR | USB_DIR_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 0, 0, cmd_buf, sizeof_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) USB_CTRL_SET_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) kfree(cmd_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (unlikely(result != sizeof_buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) error = result < 0 ? result : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) dev_err(&pegasus->usbdev->dev, "control msg error: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int pegasus_set_mode(struct pegasus *pegasus, u8 mode, u8 led)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u8 cmd[] = { NOTETAKER_SET_CMD, NOTETAKER_SET_MODE, led, mode };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return pegasus_control_msg(pegasus, cmd, sizeof(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void pegasus_parse_packet(struct pegasus *pegasus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned char *data = pegasus->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct input_dev *dev = pegasus->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u16 x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) switch (data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) case SPECIAL_COMMAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* device button pressed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (data[1] == BUTTON_PRESSED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) schedule_work(&pegasus->init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* xy data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) case BATTERY_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev_warn_once(&dev->dev, "Pen battery low\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) case BATTERY_NO_REPORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case BATTERY_GOOD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) x = le16_to_cpup((__le16 *)&data[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) y = le16_to_cpup((__le16 *)&data[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* pen-up event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (x == 0 && y == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) input_report_key(dev, BTN_TOUCH, data[1] & PEN_TIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) input_report_key(dev, BTN_RIGHT, data[1] & PEN_BUTTON_PRESSED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) input_report_key(dev, BTN_TOOL_PEN, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) input_report_abs(dev, ABS_X, (s16)x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) input_report_abs(dev, ABS_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) dev_warn_once(&pegasus->usbdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) "unknown answer from device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void pegasus_irq(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct pegasus *pegasus = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct usb_device *dev = pegasus->usbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) switch (urb->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) pegasus_parse_packet(pegasus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) usb_mark_last_busy(pegasus->usbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) dev_err(&dev->dev, "%s - urb shutting down with status: %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) __func__, urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dev_err(&dev->dev, "%s - nonzero urb status received: %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) __func__, urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) retval = usb_submit_urb(urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) dev_err(&dev->dev, "%s - usb_submit_urb failed with result %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void pegasus_init(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct pegasus *pegasus = container_of(work, struct pegasus, init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) dev_err(&pegasus->usbdev->dev, "pegasus_set_mode error: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int pegasus_open(struct input_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct pegasus *pegasus = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) error = usb_autopm_get_interface(pegasus->intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) mutex_lock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) pegasus->irq->dev = pegasus->usbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (usb_submit_urb(pegasus->irq, GFP_KERNEL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto err_autopm_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) goto err_kill_urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) pegasus->is_open = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) mutex_unlock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) err_kill_urb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) usb_kill_urb(pegasus->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) cancel_work_sync(&pegasus->init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) err_autopm_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) mutex_unlock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) usb_autopm_put_interface(pegasus->intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static void pegasus_close(struct input_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct pegasus *pegasus = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mutex_lock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) usb_kill_urb(pegasus->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) cancel_work_sync(&pegasus->init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) pegasus->is_open = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) mutex_unlock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) usb_autopm_put_interface(pegasus->intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static int pegasus_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct usb_device *dev = interface_to_usbdev(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct usb_endpoint_descriptor *endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct pegasus *pegasus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* We control interface 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (intf->cur_altsetting->desc.bInterfaceNumber >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* Sanity check that the device has an endpoint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) dev_err(&intf->dev, "Invalid number of endpoints\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) endpoint = &intf->cur_altsetting->endpoint[0].desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) pegasus = kzalloc(sizeof(*pegasus), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!pegasus || !input_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) goto err_free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) mutex_init(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) pegasus->usbdev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) pegasus->dev = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) pegasus->intf = intf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) pegasus->data_len = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) pegasus->data = usb_alloc_coherent(dev, pegasus->data_len, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) &pegasus->data_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (!pegasus->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) goto err_free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) pegasus->irq = usb_alloc_urb(0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (!pegasus->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) goto err_free_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) usb_fill_int_urb(pegasus->irq, dev, pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) pegasus->data, pegasus->data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) pegasus_irq, pegasus, endpoint->bInterval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) pegasus->irq->transfer_dma = pegasus->data_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) pegasus->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (dev->manufacturer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) strlcpy(pegasus->name, dev->manufacturer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) sizeof(pegasus->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (dev->product) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (dev->manufacturer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) strlcat(pegasus->name, " ", sizeof(pegasus->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) strlcat(pegasus->name, dev->product, sizeof(pegasus->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (!strlen(pegasus->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) snprintf(pegasus->name, sizeof(pegasus->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) "USB Pegasus Device %04x:%04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) le16_to_cpu(dev->descriptor.idVendor),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) le16_to_cpu(dev->descriptor.idProduct));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) usb_make_path(dev, pegasus->phys, sizeof(pegasus->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) strlcat(pegasus->phys, "/input0", sizeof(pegasus->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) INIT_WORK(&pegasus->init, pegasus_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) usb_set_intfdata(intf, pegasus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) input_dev->name = pegasus->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) input_dev->phys = pegasus->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) usb_to_input_id(dev, &input_dev->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) input_dev->dev.parent = &intf->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) input_set_drvdata(input_dev, pegasus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) input_dev->open = pegasus_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) input_dev->close = pegasus_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) __set_bit(EV_ABS, input_dev->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) __set_bit(EV_KEY, input_dev->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) __set_bit(ABS_X, input_dev->absbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) __set_bit(ABS_Y, input_dev->absbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) __set_bit(BTN_TOUCH, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) __set_bit(BTN_RIGHT, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) __set_bit(BTN_TOOL_PEN, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) input_set_abs_params(input_dev, ABS_X, -1500, 1500, 8, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) input_set_abs_params(input_dev, ABS_Y, 1600, 3000, 8, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) error = input_register_device(pegasus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) goto err_free_urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) err_free_urb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) usb_free_urb(pegasus->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) err_free_dma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) usb_free_coherent(dev, pegasus->data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) pegasus->data, pegasus->data_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) err_free_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) input_free_device(input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) kfree(pegasus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) usb_set_intfdata(intf, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void pegasus_disconnect(struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct pegasus *pegasus = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) input_unregister_device(pegasus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) usb_free_urb(pegasus->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) usb_free_coherent(interface_to_usbdev(intf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) pegasus->data_len, pegasus->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) pegasus->data_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) kfree(pegasus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) usb_set_intfdata(intf, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int pegasus_suspend(struct usb_interface *intf, pm_message_t message)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct pegasus *pegasus = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) mutex_lock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) usb_kill_urb(pegasus->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) cancel_work_sync(&pegasus->init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) mutex_unlock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static int pegasus_resume(struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct pegasus *pegasus = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) mutex_lock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (pegasus->is_open && usb_submit_urb(pegasus->irq, GFP_NOIO) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) retval = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mutex_unlock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static int pegasus_reset_resume(struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct pegasus *pegasus = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) mutex_lock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (pegasus->is_open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) retval = pegasus_set_mode(pegasus, PEN_MODE_XY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) NOTETAKER_LED_MOUSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (!retval && usb_submit_urb(pegasus->irq, GFP_NOIO) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) retval = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) mutex_unlock(&pegasus->pm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static const struct usb_device_id pegasus_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) { USB_DEVICE(USB_VENDOR_ID_PEGASUSTECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) USB_DEVICE_ID_PEGASUS_NOTETAKER_EN100) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) MODULE_DEVICE_TABLE(usb, pegasus_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static struct usb_driver pegasus_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .name = "pegasus_notetaker",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) .probe = pegasus_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .disconnect = pegasus_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .suspend = pegasus_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) .resume = pegasus_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .reset_resume = pegasus_reset_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .id_table = pegasus_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .supports_autosuspend = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) module_usb_driver(pegasus_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) MODULE_AUTHOR("Martin Kepplinger <martink@posteo.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) MODULE_DESCRIPTION("Pegasus Mobile Notetaker Pen tablet driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) MODULE_LICENSE("GPL");