linux/drivers/usb/misc/trancevibrator.c
<<
>>
Prefs
   1/*
   2 * PlayStation 2 Trance Vibrator driver
   3 *
   4 * Copyright (C) 2006 Sam Hocevar <sam@zoy.org>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20
  21/* Standard include files */
  22#include <linux/kernel.h>
  23#include <linux/errno.h>
  24#include <linux/init.h>
  25#include <linux/slab.h>
  26#include <linux/module.h>
  27#include <linux/usb.h>
  28
  29/* Version Information */
  30#define DRIVER_VERSION "v1.1"
  31#define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org"
  32#define DRIVER_DESC "PlayStation 2 Trance Vibrator driver"
  33
  34#define TRANCEVIBRATOR_VENDOR_ID        0x0b49  /* ASCII Corporation */
  35#define TRANCEVIBRATOR_PRODUCT_ID       0x064f  /* Trance Vibrator */
  36
  37static const struct usb_device_id id_table[] = {
  38        { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) },
  39        { },
  40};
  41MODULE_DEVICE_TABLE (usb, id_table);
  42
  43/* Driver-local specific stuff */
  44struct trancevibrator {
  45        struct usb_device *udev;
  46        unsigned int speed;
  47};
  48
  49static ssize_t show_speed(struct device *dev, struct device_attribute *attr,
  50                          char *buf)
  51{
  52        struct usb_interface *intf = to_usb_interface(dev);
  53        struct trancevibrator *tv = usb_get_intfdata(intf);
  54
  55        return sprintf(buf, "%d\n", tv->speed);
  56}
  57
  58static ssize_t set_speed(struct device *dev, struct device_attribute *attr,
  59                         const char *buf, size_t count)
  60{
  61        struct usb_interface *intf = to_usb_interface(dev);
  62        struct trancevibrator *tv = usb_get_intfdata(intf);
  63        int temp, retval, old;
  64
  65        temp = simple_strtoul(buf, NULL, 10);
  66        if (temp > 255)
  67                temp = 255;
  68        else if (temp < 0)
  69                temp = 0;
  70        old = tv->speed;
  71        tv->speed = temp;
  72
  73        dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed);
  74
  75        /* Set speed */
  76        retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
  77                                 0x01, /* vendor request: set speed */
  78                                 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
  79                                 tv->speed, /* speed value */
  80                                 0, NULL, 0, USB_CTRL_GET_TIMEOUT);
  81        if (retval) {
  82                tv->speed = old;
  83                dev_dbg(&tv->udev->dev, "retval = %d\n", retval);
  84                return retval;
  85        }
  86        return count;
  87}
  88
  89static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR, show_speed, set_speed);
  90
  91static int tv_probe(struct usb_interface *interface,
  92                    const struct usb_device_id *id)
  93{
  94        struct usb_device *udev = interface_to_usbdev(interface);
  95        struct trancevibrator *dev;
  96        int retval;
  97
  98        dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL);
  99        if (dev == NULL) {
 100                dev_err(&interface->dev, "Out of memory\n");
 101                retval = -ENOMEM;
 102                goto error;
 103        }
 104
 105        dev->udev = usb_get_dev(udev);
 106        usb_set_intfdata(interface, dev);
 107        retval = device_create_file(&interface->dev, &dev_attr_speed);
 108        if (retval)
 109                goto error_create_file;
 110
 111        return 0;
 112
 113error_create_file:
 114        usb_put_dev(udev);
 115        usb_set_intfdata(interface, NULL);
 116error:
 117        kfree(dev);
 118        return retval;
 119}
 120
 121static void tv_disconnect(struct usb_interface *interface)
 122{
 123        struct trancevibrator *dev;
 124
 125        dev = usb_get_intfdata (interface);
 126        device_remove_file(&interface->dev, &dev_attr_speed);
 127        usb_set_intfdata(interface, NULL);
 128        usb_put_dev(dev->udev);
 129        kfree(dev);
 130}
 131
 132/* USB subsystem object */
 133static struct usb_driver tv_driver = {
 134        .name =         "trancevibrator",
 135        .probe =        tv_probe,
 136        .disconnect =   tv_disconnect,
 137        .id_table =     id_table,
 138};
 139
 140static int __init tv_init(void)
 141{
 142        int retval = usb_register(&tv_driver);
 143        if (retval) {
 144                err("usb_register failed. Error number %d", retval);
 145                return retval;
 146        }
 147
 148        printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
 149               DRIVER_DESC "\n");
 150        return 0;
 151}
 152
 153static void __exit tv_exit(void)
 154{
 155        usb_deregister(&tv_driver);
 156}
 157
 158module_init (tv_init);
 159module_exit (tv_exit);
 160
 161MODULE_AUTHOR(DRIVER_AUTHOR);
 162MODULE_DESCRIPTION(DRIVER_DESC);
 163MODULE_LICENSE("GPL");
 164