linux/drivers/usb/misc/trancevibrator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * PlayStation 2 Trance Vibrator driver
   4 *
   5 * Copyright (C) 2006 Sam Hocevar <sam@zoy.org>
   6 */
   7
   8/* Standard include files */
   9#include <linux/kernel.h>
  10#include <linux/errno.h>
  11#include <linux/slab.h>
  12#include <linux/module.h>
  13#include <linux/usb.h>
  14
  15#define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org"
  16#define DRIVER_DESC "PlayStation 2 Trance Vibrator driver"
  17
  18#define TRANCEVIBRATOR_VENDOR_ID        0x0b49  /* ASCII Corporation */
  19#define TRANCEVIBRATOR_PRODUCT_ID       0x064f  /* Trance Vibrator */
  20
  21static const struct usb_device_id id_table[] = {
  22        { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) },
  23        { },
  24};
  25MODULE_DEVICE_TABLE (usb, id_table);
  26
  27/* Driver-local specific stuff */
  28struct trancevibrator {
  29        struct usb_device *udev;
  30        unsigned int speed;
  31};
  32
  33static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
  34                          char *buf)
  35{
  36        struct usb_interface *intf = to_usb_interface(dev);
  37        struct trancevibrator *tv = usb_get_intfdata(intf);
  38
  39        return sprintf(buf, "%d\n", tv->speed);
  40}
  41
  42static ssize_t speed_store(struct device *dev, struct device_attribute *attr,
  43                         const char *buf, size_t count)
  44{
  45        struct usb_interface *intf = to_usb_interface(dev);
  46        struct trancevibrator *tv = usb_get_intfdata(intf);
  47        int temp, retval, old;
  48
  49        retval = kstrtoint(buf, 10, &temp);
  50        if (retval)
  51                return retval;
  52        if (temp > 255)
  53                temp = 255;
  54        else if (temp < 0)
  55                temp = 0;
  56        old = tv->speed;
  57        tv->speed = temp;
  58
  59        dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed);
  60
  61        /* Set speed */
  62        retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
  63                                 0x01, /* vendor request: set speed */
  64                                 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  65                                 tv->speed, /* speed value */
  66                                 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
  67        if (retval) {
  68                tv->speed = old;
  69                dev_dbg(&tv->udev->dev, "retval = %d\n", retval);
  70                return retval;
  71        }
  72        return count;
  73}
  74static DEVICE_ATTR_RW(speed);
  75
  76static struct attribute *tv_attrs[] = {
  77        &dev_attr_speed.attr,
  78        NULL,
  79};
  80ATTRIBUTE_GROUPS(tv);
  81
  82static int tv_probe(struct usb_interface *interface,
  83                    const struct usb_device_id *id)
  84{
  85        struct usb_device *udev = interface_to_usbdev(interface);
  86        struct trancevibrator *dev;
  87        int retval;
  88
  89        dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL);
  90        if (!dev) {
  91                retval = -ENOMEM;
  92                goto error;
  93        }
  94
  95        dev->udev = usb_get_dev(udev);
  96        usb_set_intfdata(interface, dev);
  97
  98        return 0;
  99
 100error:
 101        kfree(dev);
 102        return retval;
 103}
 104
 105static void tv_disconnect(struct usb_interface *interface)
 106{
 107        struct trancevibrator *dev;
 108
 109        dev = usb_get_intfdata (interface);
 110        usb_set_intfdata(interface, NULL);
 111        usb_put_dev(dev->udev);
 112        kfree(dev);
 113}
 114
 115/* USB subsystem object */
 116static struct usb_driver tv_driver = {
 117        .name =         "trancevibrator",
 118        .probe =        tv_probe,
 119        .disconnect =   tv_disconnect,
 120        .id_table =     id_table,
 121        .dev_groups =   tv_groups,
 122};
 123
 124module_usb_driver(tv_driver);
 125
 126MODULE_AUTHOR(DRIVER_AUTHOR);
 127MODULE_DESCRIPTION(DRIVER_DESC);
 128MODULE_LICENSE("GPL");
 129