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/slab.h> 25#include <linux/module.h> 26#include <linux/usb.h> 27 28/* Version Information */ 29#define DRIVER_VERSION "v1.1" 30#define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org" 31#define DRIVER_DESC "PlayStation 2 Trance Vibrator driver" 32 33#define TRANCEVIBRATOR_VENDOR_ID 0x0b49 /* ASCII Corporation */ 34#define TRANCEVIBRATOR_PRODUCT_ID 0x064f /* Trance Vibrator */ 35 36static const struct usb_device_id id_table[] = { 37 { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) }, 38 { }, 39}; 40MODULE_DEVICE_TABLE (usb, id_table); 41 42/* Driver-local specific stuff */ 43struct trancevibrator { 44 struct usb_device *udev; 45 unsigned int speed; 46}; 47 48static ssize_t show_speed(struct device *dev, struct device_attribute *attr, 49 char *buf) 50{ 51 struct usb_interface *intf = to_usb_interface(dev); 52 struct trancevibrator *tv = usb_get_intfdata(intf); 53 54 return sprintf(buf, "%d\n", tv->speed); 55} 56 57static ssize_t set_speed(struct device *dev, struct device_attribute *attr, 58 const char *buf, size_t count) 59{ 60 struct usb_interface *intf = to_usb_interface(dev); 61 struct trancevibrator *tv = usb_get_intfdata(intf); 62 int temp, retval, old; 63 64 temp = simple_strtoul(buf, NULL, 10); 65 if (temp > 255) 66 temp = 255; 67 else if (temp < 0) 68 temp = 0; 69 old = tv->speed; 70 tv->speed = temp; 71 72 dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed); 73 74 /* Set speed */ 75 retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0), 76 0x01, /* vendor request: set speed */ 77 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, 78 tv->speed, /* speed value */ 79 0, NULL, 0, USB_CTRL_GET_TIMEOUT); 80 if (retval) { 81 tv->speed = old; 82 dev_dbg(&tv->udev->dev, "retval = %d\n", retval); 83 return retval; 84 } 85 return count; 86} 87 88static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR, show_speed, set_speed); 89 90static int tv_probe(struct usb_interface *interface, 91 const struct usb_device_id *id) 92{ 93 struct usb_device *udev = interface_to_usbdev(interface); 94 struct trancevibrator *dev; 95 int retval; 96 97 dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL); 98 if (dev == NULL) { 99 dev_err(&interface->dev, "Out of memory\n"); 100 retval = -ENOMEM; 101 goto error; 102 } 103 104 dev->udev = usb_get_dev(udev); 105 usb_set_intfdata(interface, dev); 106 retval = device_create_file(&interface->dev, &dev_attr_speed); 107 if (retval) 108 goto error_create_file; 109 110 return 0; 111 112error_create_file: 113 usb_put_dev(udev); 114 usb_set_intfdata(interface, NULL); 115error: 116 kfree(dev); 117 return retval; 118} 119 120static void tv_disconnect(struct usb_interface *interface) 121{ 122 struct trancevibrator *dev; 123 124 dev = usb_get_intfdata (interface); 125 device_remove_file(&interface->dev, &dev_attr_speed); 126 usb_set_intfdata(interface, NULL); 127 usb_put_dev(dev->udev); 128 kfree(dev); 129} 130 131/* USB subsystem object */ 132static struct usb_driver tv_driver = { 133 .name = "trancevibrator", 134 .probe = tv_probe, 135 .disconnect = tv_disconnect, 136 .id_table = id_table, 137}; 138 139module_usb_driver(tv_driver); 140 141MODULE_AUTHOR(DRIVER_AUTHOR); 142MODULE_DESCRIPTION(DRIVER_DESC); 143MODULE_LICENSE("GPL"); 144