Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Pegasus Mobile Notetaker Pen input tablet driver
0004  *
0005  * Copyright (c) 2016 Martin Kepplinger <martink@posteo.de>
0006  */
0007 
0008 /*
0009  * request packet (control endpoint):
0010  * |-------------------------------------|
0011  * | Report ID | Nr of bytes | command   |
0012  * | (1 byte)  | (1 byte)    | (n bytes) |
0013  * |-------------------------------------|
0014  * | 0x02      | n           |           |
0015  * |-------------------------------------|
0016  *
0017  * data packet after set xy mode command, 0x80 0xb5 0x02 0x01
0018  * and pen is in range:
0019  *
0020  * byte byte name       value (bits)
0021  * --------------------------------------------
0022  * 0    status          0 1 0 0 0 0 X X
0023  * 1    color           0 0 0 0 H 0 S T
0024  * 2    X low
0025  * 3    X high
0026  * 4    Y low
0027  * 5    Y high
0028  *
0029  * X X  battery state:
0030  *  no state reported   0x00
0031  *  battery low     0x01
0032  *  battery good        0x02
0033  *
0034  * H    Hovering
0035  * S    Switch 1 (pen button)
0036  * T    Tip
0037  */
0038 
0039 #include <linux/kernel.h>
0040 #include <linux/module.h>
0041 #include <linux/input.h>
0042 #include <linux/usb/input.h>
0043 #include <linux/slab.h>
0044 #include <linux/workqueue.h>
0045 #include <linux/mutex.h>
0046 
0047 /* USB HID defines */
0048 #define USB_REQ_GET_REPORT      0x01
0049 #define USB_REQ_SET_REPORT      0x09
0050 
0051 #define USB_VENDOR_ID_PEGASUSTECH   0x0e20
0052 #define USB_DEVICE_ID_PEGASUS_NOTETAKER_EN100   0x0101
0053 
0054 /* device specific defines */
0055 #define NOTETAKER_REPORT_ID     0x02
0056 #define NOTETAKER_SET_CMD       0x80
0057 #define NOTETAKER_SET_MODE      0xb5
0058 
0059 #define NOTETAKER_LED_MOUSE     0x02
0060 #define PEN_MODE_XY         0x01
0061 
0062 #define SPECIAL_COMMAND         0x80
0063 #define BUTTON_PRESSED          0xb5
0064 #define COMMAND_VERSION         0xa9
0065 
0066 /* in xy data packet */
0067 #define BATTERY_NO_REPORT       0x40
0068 #define BATTERY_LOW         0x41
0069 #define BATTERY_GOOD            0x42
0070 #define PEN_BUTTON_PRESSED      BIT(1)
0071 #define PEN_TIP             BIT(0)
0072 
0073 struct pegasus {
0074     unsigned char *data;
0075     u8 data_len;
0076     dma_addr_t data_dma;
0077     struct input_dev *dev;
0078     struct usb_device *usbdev;
0079     struct usb_interface *intf;
0080     struct urb *irq;
0081 
0082     /* serialize access to open/suspend */
0083     struct mutex pm_mutex;
0084     bool is_open;
0085 
0086     char name[128];
0087     char phys[64];
0088     struct work_struct init;
0089 };
0090 
0091 static int pegasus_control_msg(struct pegasus *pegasus, u8 *data, int len)
0092 {
0093     const int sizeof_buf = len + 2;
0094     int result;
0095     int error;
0096     u8 *cmd_buf;
0097 
0098     cmd_buf = kmalloc(sizeof_buf, GFP_KERNEL);
0099     if (!cmd_buf)
0100         return -ENOMEM;
0101 
0102     cmd_buf[0] = NOTETAKER_REPORT_ID;
0103     cmd_buf[1] = len;
0104     memcpy(cmd_buf + 2, data, len);
0105 
0106     result = usb_control_msg(pegasus->usbdev,
0107                  usb_sndctrlpipe(pegasus->usbdev, 0),
0108                  USB_REQ_SET_REPORT,
0109                  USB_TYPE_VENDOR | USB_DIR_OUT,
0110                  0, 0, cmd_buf, sizeof_buf,
0111                  USB_CTRL_SET_TIMEOUT);
0112 
0113     kfree(cmd_buf);
0114 
0115     if (unlikely(result != sizeof_buf)) {
0116         error = result < 0 ? result : -EIO;
0117         dev_err(&pegasus->usbdev->dev, "control msg error: %d\n",
0118             error);
0119         return error;
0120     }
0121 
0122     return 0;
0123 }
0124 
0125 static int pegasus_set_mode(struct pegasus *pegasus, u8 mode, u8 led)
0126 {
0127     u8 cmd[] = { NOTETAKER_SET_CMD, NOTETAKER_SET_MODE, led, mode };
0128 
0129     return pegasus_control_msg(pegasus, cmd, sizeof(cmd));
0130 }
0131 
0132 static void pegasus_parse_packet(struct pegasus *pegasus)
0133 {
0134     unsigned char *data = pegasus->data;
0135     struct input_dev *dev = pegasus->dev;
0136     u16 x, y;
0137 
0138     switch (data[0]) {
0139     case SPECIAL_COMMAND:
0140         /* device button pressed */
0141         if (data[1] == BUTTON_PRESSED)
0142             schedule_work(&pegasus->init);
0143 
0144         break;
0145 
0146     /* xy data */
0147     case BATTERY_LOW:
0148         dev_warn_once(&dev->dev, "Pen battery low\n");
0149         fallthrough;
0150 
0151     case BATTERY_NO_REPORT:
0152     case BATTERY_GOOD:
0153         x = le16_to_cpup((__le16 *)&data[2]);
0154         y = le16_to_cpup((__le16 *)&data[4]);
0155 
0156         /* pen-up event */
0157         if (x == 0 && y == 0)
0158             break;
0159 
0160         input_report_key(dev, BTN_TOUCH, data[1] & PEN_TIP);
0161         input_report_key(dev, BTN_RIGHT, data[1] & PEN_BUTTON_PRESSED);
0162         input_report_key(dev, BTN_TOOL_PEN, 1);
0163         input_report_abs(dev, ABS_X, (s16)x);
0164         input_report_abs(dev, ABS_Y, y);
0165 
0166         input_sync(dev);
0167         break;
0168 
0169     default:
0170         dev_warn_once(&pegasus->usbdev->dev,
0171                   "unknown answer from device\n");
0172     }
0173 }
0174 
0175 static void pegasus_irq(struct urb *urb)
0176 {
0177     struct pegasus *pegasus = urb->context;
0178     struct usb_device *dev = pegasus->usbdev;
0179     int retval;
0180 
0181     switch (urb->status) {
0182     case 0:
0183         pegasus_parse_packet(pegasus);
0184         usb_mark_last_busy(pegasus->usbdev);
0185         break;
0186 
0187     case -ECONNRESET:
0188     case -ENOENT:
0189     case -ESHUTDOWN:
0190         dev_err(&dev->dev, "%s - urb shutting down with status: %d",
0191             __func__, urb->status);
0192         return;
0193 
0194     default:
0195         dev_err(&dev->dev, "%s - nonzero urb status received: %d",
0196             __func__, urb->status);
0197         break;
0198     }
0199 
0200     retval = usb_submit_urb(urb, GFP_ATOMIC);
0201     if (retval)
0202         dev_err(&dev->dev, "%s - usb_submit_urb failed with result %d",
0203             __func__, retval);
0204 }
0205 
0206 static void pegasus_init(struct work_struct *work)
0207 {
0208     struct pegasus *pegasus = container_of(work, struct pegasus, init);
0209     int error;
0210 
0211     error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE);
0212     if (error)
0213         dev_err(&pegasus->usbdev->dev, "pegasus_set_mode error: %d\n",
0214             error);
0215 }
0216 
0217 static int pegasus_open(struct input_dev *dev)
0218 {
0219     struct pegasus *pegasus = input_get_drvdata(dev);
0220     int error;
0221 
0222     error = usb_autopm_get_interface(pegasus->intf);
0223     if (error)
0224         return error;
0225 
0226     mutex_lock(&pegasus->pm_mutex);
0227     pegasus->irq->dev = pegasus->usbdev;
0228     if (usb_submit_urb(pegasus->irq, GFP_KERNEL)) {
0229         error = -EIO;
0230         goto err_autopm_put;
0231     }
0232 
0233     error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE);
0234     if (error)
0235         goto err_kill_urb;
0236 
0237     pegasus->is_open = true;
0238     mutex_unlock(&pegasus->pm_mutex);
0239     return 0;
0240 
0241 err_kill_urb:
0242     usb_kill_urb(pegasus->irq);
0243     cancel_work_sync(&pegasus->init);
0244 err_autopm_put:
0245     mutex_unlock(&pegasus->pm_mutex);
0246     usb_autopm_put_interface(pegasus->intf);
0247     return error;
0248 }
0249 
0250 static void pegasus_close(struct input_dev *dev)
0251 {
0252     struct pegasus *pegasus = input_get_drvdata(dev);
0253 
0254     mutex_lock(&pegasus->pm_mutex);
0255     usb_kill_urb(pegasus->irq);
0256     cancel_work_sync(&pegasus->init);
0257     pegasus->is_open = false;
0258     mutex_unlock(&pegasus->pm_mutex);
0259 
0260     usb_autopm_put_interface(pegasus->intf);
0261 }
0262 
0263 static int pegasus_probe(struct usb_interface *intf,
0264              const struct usb_device_id *id)
0265 {
0266     struct usb_device *dev = interface_to_usbdev(intf);
0267     struct usb_endpoint_descriptor *endpoint;
0268     struct pegasus *pegasus;
0269     struct input_dev *input_dev;
0270     int error;
0271     int pipe;
0272 
0273     /* We control interface 0 */
0274     if (intf->cur_altsetting->desc.bInterfaceNumber >= 1)
0275         return -ENODEV;
0276 
0277     /* Sanity check that the device has an endpoint */
0278     if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
0279         dev_err(&intf->dev, "Invalid number of endpoints\n");
0280         return -EINVAL;
0281     }
0282 
0283     endpoint = &intf->cur_altsetting->endpoint[0].desc;
0284 
0285     pegasus = kzalloc(sizeof(*pegasus), GFP_KERNEL);
0286     input_dev = input_allocate_device();
0287     if (!pegasus || !input_dev) {
0288         error = -ENOMEM;
0289         goto err_free_mem;
0290     }
0291 
0292     mutex_init(&pegasus->pm_mutex);
0293 
0294     pegasus->usbdev = dev;
0295     pegasus->dev = input_dev;
0296     pegasus->intf = intf;
0297 
0298     pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
0299     pegasus->data_len = usb_maxpacket(dev, pipe);
0300 
0301     pegasus->data = usb_alloc_coherent(dev, pegasus->data_len, GFP_KERNEL,
0302                        &pegasus->data_dma);
0303     if (!pegasus->data) {
0304         error = -ENOMEM;
0305         goto err_free_mem;
0306     }
0307 
0308     pegasus->irq = usb_alloc_urb(0, GFP_KERNEL);
0309     if (!pegasus->irq) {
0310         error = -ENOMEM;
0311         goto err_free_dma;
0312     }
0313 
0314     usb_fill_int_urb(pegasus->irq, dev, pipe,
0315              pegasus->data, pegasus->data_len,
0316              pegasus_irq, pegasus, endpoint->bInterval);
0317 
0318     pegasus->irq->transfer_dma = pegasus->data_dma;
0319     pegasus->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
0320 
0321     if (dev->manufacturer)
0322         strlcpy(pegasus->name, dev->manufacturer,
0323             sizeof(pegasus->name));
0324 
0325     if (dev->product) {
0326         if (dev->manufacturer)
0327             strlcat(pegasus->name, " ", sizeof(pegasus->name));
0328         strlcat(pegasus->name, dev->product, sizeof(pegasus->name));
0329     }
0330 
0331     if (!strlen(pegasus->name))
0332         snprintf(pegasus->name, sizeof(pegasus->name),
0333              "USB Pegasus Device %04x:%04x",
0334              le16_to_cpu(dev->descriptor.idVendor),
0335              le16_to_cpu(dev->descriptor.idProduct));
0336 
0337     usb_make_path(dev, pegasus->phys, sizeof(pegasus->phys));
0338     strlcat(pegasus->phys, "/input0", sizeof(pegasus->phys));
0339 
0340     INIT_WORK(&pegasus->init, pegasus_init);
0341 
0342     usb_set_intfdata(intf, pegasus);
0343 
0344     input_dev->name = pegasus->name;
0345     input_dev->phys = pegasus->phys;
0346     usb_to_input_id(dev, &input_dev->id);
0347     input_dev->dev.parent = &intf->dev;
0348 
0349     input_set_drvdata(input_dev, pegasus);
0350 
0351     input_dev->open = pegasus_open;
0352     input_dev->close = pegasus_close;
0353 
0354     __set_bit(EV_ABS, input_dev->evbit);
0355     __set_bit(EV_KEY, input_dev->evbit);
0356 
0357     __set_bit(ABS_X, input_dev->absbit);
0358     __set_bit(ABS_Y, input_dev->absbit);
0359 
0360     __set_bit(BTN_TOUCH, input_dev->keybit);
0361     __set_bit(BTN_RIGHT, input_dev->keybit);
0362     __set_bit(BTN_TOOL_PEN, input_dev->keybit);
0363 
0364     __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
0365     __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
0366 
0367     input_set_abs_params(input_dev, ABS_X, -1500, 1500, 8, 0);
0368     input_set_abs_params(input_dev, ABS_Y, 1600, 3000, 8, 0);
0369 
0370     error = input_register_device(pegasus->dev);
0371     if (error)
0372         goto err_free_urb;
0373 
0374     return 0;
0375 
0376 err_free_urb:
0377     usb_free_urb(pegasus->irq);
0378 err_free_dma:
0379     usb_free_coherent(dev, pegasus->data_len,
0380               pegasus->data, pegasus->data_dma);
0381 err_free_mem:
0382     input_free_device(input_dev);
0383     kfree(pegasus);
0384     usb_set_intfdata(intf, NULL);
0385 
0386     return error;
0387 }
0388 
0389 static void pegasus_disconnect(struct usb_interface *intf)
0390 {
0391     struct pegasus *pegasus = usb_get_intfdata(intf);
0392 
0393     input_unregister_device(pegasus->dev);
0394 
0395     usb_free_urb(pegasus->irq);
0396     usb_free_coherent(interface_to_usbdev(intf),
0397               pegasus->data_len, pegasus->data,
0398               pegasus->data_dma);
0399 
0400     kfree(pegasus);
0401     usb_set_intfdata(intf, NULL);
0402 }
0403 
0404 static int pegasus_suspend(struct usb_interface *intf, pm_message_t message)
0405 {
0406     struct pegasus *pegasus = usb_get_intfdata(intf);
0407 
0408     mutex_lock(&pegasus->pm_mutex);
0409     usb_kill_urb(pegasus->irq);
0410     cancel_work_sync(&pegasus->init);
0411     mutex_unlock(&pegasus->pm_mutex);
0412 
0413     return 0;
0414 }
0415 
0416 static int pegasus_resume(struct usb_interface *intf)
0417 {
0418     struct pegasus *pegasus = usb_get_intfdata(intf);
0419     int retval = 0;
0420 
0421     mutex_lock(&pegasus->pm_mutex);
0422     if (pegasus->is_open && usb_submit_urb(pegasus->irq, GFP_NOIO) < 0)
0423         retval = -EIO;
0424     mutex_unlock(&pegasus->pm_mutex);
0425 
0426     return retval;
0427 }
0428 
0429 static int pegasus_reset_resume(struct usb_interface *intf)
0430 {
0431     struct pegasus *pegasus = usb_get_intfdata(intf);
0432     int retval = 0;
0433 
0434     mutex_lock(&pegasus->pm_mutex);
0435     if (pegasus->is_open) {
0436         retval = pegasus_set_mode(pegasus, PEN_MODE_XY,
0437                       NOTETAKER_LED_MOUSE);
0438         if (!retval && usb_submit_urb(pegasus->irq, GFP_NOIO) < 0)
0439             retval = -EIO;
0440     }
0441     mutex_unlock(&pegasus->pm_mutex);
0442 
0443     return retval;
0444 }
0445 
0446 static const struct usb_device_id pegasus_ids[] = {
0447     { USB_DEVICE(USB_VENDOR_ID_PEGASUSTECH,
0448              USB_DEVICE_ID_PEGASUS_NOTETAKER_EN100) },
0449     { }
0450 };
0451 MODULE_DEVICE_TABLE(usb, pegasus_ids);
0452 
0453 static struct usb_driver pegasus_driver = {
0454     .name       = "pegasus_notetaker",
0455     .probe      = pegasus_probe,
0456     .disconnect = pegasus_disconnect,
0457     .suspend    = pegasus_suspend,
0458     .resume     = pegasus_resume,
0459     .reset_resume   = pegasus_reset_resume,
0460     .id_table   = pegasus_ids,
0461     .supports_autosuspend = 1,
0462 };
0463 
0464 module_usb_driver(pegasus_driver);
0465 
0466 MODULE_AUTHOR("Martin Kepplinger <martink@posteo.de>");
0467 MODULE_DESCRIPTION("Pegasus Mobile Notetaker Pen tablet driver");
0468 MODULE_LICENSE("GPL");