| Adrian McMenamin | 03dd5e1 | 2009-01-29 22:56:08 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  *	SEGA Dreamcast mouse driver | 
 | 3 |  *	Based on drivers/usb/usbmouse.c | 
 | 4 |  * | 
 | 5 |  *	Copyright Yaegashi Takeshi, 2001 | 
 | 6 |  *	Adrian McMenamin, 2008 | 
 | 7 |  */ | 
 | 8 |  | 
 | 9 | #include <linux/kernel.h> | 
 | 10 | #include <linux/slab.h> | 
 | 11 | #include <linux/input.h> | 
 | 12 | #include <linux/module.h> | 
 | 13 | #include <linux/init.h> | 
 | 14 | #include <linux/timer.h> | 
 | 15 | #include <linux/maple.h> | 
 | 16 |  | 
 | 17 | MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>"); | 
 | 18 | MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); | 
 | 19 | MODULE_LICENSE("GPL"); | 
 | 20 |  | 
 | 21 | struct dc_mouse { | 
 | 22 | 	struct input_dev *dev; | 
 | 23 | 	struct maple_device *mdev; | 
 | 24 | }; | 
 | 25 |  | 
 | 26 | static void dc_mouse_callback(struct mapleq *mq) | 
 | 27 | { | 
 | 28 | 	int buttons, relx, rely, relz; | 
 | 29 | 	struct maple_device *mapledev = mq->dev; | 
 | 30 | 	struct dc_mouse *mse = maple_get_drvdata(mapledev); | 
 | 31 | 	struct input_dev *dev = mse->dev; | 
 | 32 | 	unsigned char *res = mq->recvbuf; | 
 | 33 |  | 
 | 34 | 	buttons = ~res[8]; | 
 | 35 | 	relx = *(unsigned short *)(res + 12) - 512; | 
 | 36 | 	rely = *(unsigned short *)(res + 14) - 512; | 
 | 37 | 	relz = *(unsigned short *)(res + 16) - 512; | 
 | 38 |  | 
 | 39 | 	input_report_key(dev, BTN_LEFT,   buttons & 4); | 
 | 40 | 	input_report_key(dev, BTN_MIDDLE, buttons & 9); | 
 | 41 | 	input_report_key(dev, BTN_RIGHT,  buttons & 2); | 
 | 42 | 	input_report_rel(dev, REL_X,      relx); | 
 | 43 | 	input_report_rel(dev, REL_Y,      rely); | 
 | 44 | 	input_report_rel(dev, REL_WHEEL,  relz); | 
 | 45 | 	input_sync(dev); | 
 | 46 | } | 
 | 47 |  | 
 | 48 | static int dc_mouse_open(struct input_dev *dev) | 
 | 49 | { | 
 | 50 | 	struct dc_mouse *mse = dev->dev.platform_data; | 
 | 51 |  | 
 | 52 | 	maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50, | 
 | 53 | 		MAPLE_FUNC_MOUSE); | 
 | 54 |  | 
 | 55 | 	return 0; | 
 | 56 | } | 
 | 57 |  | 
 | 58 | static void dc_mouse_close(struct input_dev *dev) | 
 | 59 | { | 
 | 60 | 	struct dc_mouse *mse = dev->dev.platform_data; | 
 | 61 |  | 
 | 62 | 	maple_getcond_callback(mse->mdev, dc_mouse_callback, 0, | 
 | 63 | 		MAPLE_FUNC_MOUSE); | 
 | 64 | } | 
 | 65 |  | 
 | 66 |  | 
 | 67 | static int __devinit probe_maple_mouse(struct device *dev) | 
 | 68 | { | 
 | 69 | 	struct maple_device *mdev = to_maple_dev(dev); | 
 | 70 | 	struct maple_driver *mdrv = to_maple_driver(dev->driver); | 
 | 71 | 	struct input_dev *input_dev; | 
 | 72 | 	struct dc_mouse *mse; | 
 | 73 | 	int error; | 
 | 74 |  | 
 | 75 | 	mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); | 
 | 76 | 	input_dev = input_allocate_device(); | 
 | 77 |  | 
 | 78 | 	if (!mse || !input_dev) { | 
 | 79 | 		error = -ENOMEM; | 
 | 80 | 		goto fail; | 
 | 81 | 	} | 
 | 82 |  | 
 | 83 | 	mse->dev = input_dev; | 
 | 84 | 	mse->mdev = mdev; | 
 | 85 |  | 
 | 86 | 	input_set_drvdata(input_dev, mse); | 
 | 87 | 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 
 | 88 | 	input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | | 
 | 89 | 		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); | 
 | 90 | 	input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | | 
 | 91 | 		BIT_MASK(REL_WHEEL); | 
 | 92 | 	input_dev->name = mdev->product_name; | 
 | 93 | 	input_dev->id.bustype = BUS_HOST; | 
 | 94 | 	input_dev->open = dc_mouse_open; | 
 | 95 | 	input_dev->close = dc_mouse_close; | 
 | 96 |  | 
 | 97 | 	mdev->driver = mdrv; | 
 | 98 | 	maple_set_drvdata(mdev, mse); | 
 | 99 |  | 
 | 100 | 	error =	input_register_device(input_dev); | 
 | 101 | 	if (error) | 
 | 102 | 		goto fail; | 
 | 103 |  | 
 | 104 | 	return 0; | 
 | 105 |  | 
 | 106 | fail: | 
 | 107 | 	input_free_device(input_dev); | 
 | 108 | 	maple_set_drvdata(mdev, NULL); | 
 | 109 | 	kfree(mse); | 
 | 110 | 	mdev->driver = NULL; | 
 | 111 | 	return error; | 
 | 112 | } | 
 | 113 |  | 
 | 114 | static int __devexit remove_maple_mouse(struct device *dev) | 
 | 115 | { | 
 | 116 | 	struct maple_device *mdev = to_maple_dev(dev); | 
 | 117 | 	struct dc_mouse *mse = maple_get_drvdata(mdev); | 
 | 118 |  | 
 | 119 | 	mdev->callback = NULL; | 
 | 120 | 	input_unregister_device(mse->dev); | 
 | 121 | 	maple_set_drvdata(mdev, NULL); | 
 | 122 | 	kfree(mse); | 
 | 123 |  | 
 | 124 | 	return 0; | 
 | 125 | } | 
 | 126 |  | 
 | 127 | static struct maple_driver dc_mouse_driver = { | 
 | 128 | 	.function =	MAPLE_FUNC_MOUSE, | 
 | 129 | 	.drv = { | 
 | 130 | 		.name = "Dreamcast_mouse", | 
 | 131 | 		.probe = probe_maple_mouse, | 
 | 132 | 		.remove = __devexit_p(remove_maple_mouse), | 
 | 133 | 	}, | 
 | 134 | }; | 
 | 135 |  | 
 | 136 | static int __init dc_mouse_init(void) | 
 | 137 | { | 
 | 138 | 	return maple_driver_register(&dc_mouse_driver); | 
 | 139 | } | 
 | 140 |  | 
 | 141 | static void __exit dc_mouse_exit(void) | 
 | 142 | { | 
 | 143 | 	maple_driver_unregister(&dc_mouse_driver); | 
 | 144 | } | 
 | 145 |  | 
 | 146 | module_init(dc_mouse_init); | 
 | 147 | module_exit(dc_mouse_exit); |