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/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 36 static struct usb_device_id id_table [] = { 37 { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) }, 38 { }, 39 }; 40 MODULE_DEVICE_TABLE (usb, id_table); 41 42 /* Driver-local specific stuff */ 43 struct trancevibrator { 44 struct usb_device *udev; 45 unsigned int speed; 46 }; 47 48 static 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 57 static 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; 63 64 temp = simple_strtoul(buf, NULL, 10); 65 if (temp > 255) 66 temp = 255; 67 else if (temp < 0) 68 temp = 0; 69 tv->speed = temp; 70 71 dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed); 72 73 /* Set speed */ 74 retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0), 75 0x01, /* vendor request: set speed */ 76 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, 77 tv->speed, /* speed value */ 78 0, NULL, 0, USB_CTRL_GET_TIMEOUT); 79 if (retval) { 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_IWUGO | S_IRUGO, 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 == NULL) { 97 dev_err(&interface->dev, "Out of memory\n"); 98 retval = -ENOMEM; 99 goto error; 100 } 101 102 dev->udev = usb_get_dev(udev); 103 usb_set_intfdata(interface, dev); 104 retval = device_create_file(&interface->dev, &dev_attr_speed); 105 if (retval) 106 goto error_create_file; 107 108 return 0; 109 110 error_create_file: 111 usb_put_dev(udev); 112 usb_set_intfdata(interface, NULL); 113 error: 114 kfree(dev); 115 return retval; 116 } 117 118 static void tv_disconnect(struct usb_interface *interface) 119 { 120 struct trancevibrator *dev; 121 122 dev = usb_get_intfdata (interface); 123 device_remove_file(&interface->dev, &dev_attr_speed); 124 usb_set_intfdata(interface, NULL); 125 usb_put_dev(dev->udev); 126 kfree(dev); 127 } 128 129 /* USB subsystem object */ 130 static struct usb_driver tv_driver = { 131 .name = "trancevibrator", 132 .probe = tv_probe, 133 .disconnect = tv_disconnect, 134 .id_table = id_table, 135 }; 136 137 static int __init tv_init(void) 138 { 139 int retval = usb_register(&tv_driver); 140 if (retval) { 141 err("usb_register failed. Error number %d", retval); 142 return retval; 143 } 144 145 info(DRIVER_VERSION ":" DRIVER_DESC); 146 return 0; 147 } 148 149 static void __exit tv_exit(void) 150 { 151 usb_deregister(&tv_driver); 152 } 153 154 module_init (tv_init); 155 module_exit (tv_exit); 156 157 MODULE_AUTHOR(DRIVER_AUTHOR); 158 MODULE_DESCRIPTION(DRIVER_DESC); 159 MODULE_LICENSE("GPL"); 160