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