xref: /linux-6.15/drivers/input/mouse/maplemouse.c (revision dc2f1423)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
203dd5e1bSAdrian McMenamin /*
303dd5e1bSAdrian McMenamin  *	SEGA Dreamcast mouse driver
403dd5e1bSAdrian McMenamin  *	Based on drivers/usb/usbmouse.c
503dd5e1bSAdrian McMenamin  *
66b348085SAdrian McMenamin  *	Copyright (c) Yaegashi Takeshi, 2001
76b348085SAdrian McMenamin  *	Copyright (c) Adrian McMenamin, 2008 - 2009
803dd5e1bSAdrian McMenamin  */
903dd5e1bSAdrian McMenamin 
1003dd5e1bSAdrian McMenamin #include <linux/kernel.h>
1103dd5e1bSAdrian McMenamin #include <linux/slab.h>
1203dd5e1bSAdrian McMenamin #include <linux/input.h>
1303dd5e1bSAdrian McMenamin #include <linux/module.h>
1403dd5e1bSAdrian McMenamin #include <linux/init.h>
1503dd5e1bSAdrian McMenamin #include <linux/timer.h>
1603dd5e1bSAdrian McMenamin #include <linux/maple.h>
1703dd5e1bSAdrian McMenamin 
1803dd5e1bSAdrian McMenamin MODULE_AUTHOR("Adrian McMenamin <[email protected]>");
1903dd5e1bSAdrian McMenamin MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
2003dd5e1bSAdrian McMenamin MODULE_LICENSE("GPL");
2103dd5e1bSAdrian McMenamin 
2203dd5e1bSAdrian McMenamin struct dc_mouse {
2303dd5e1bSAdrian McMenamin 	struct input_dev *dev;
2403dd5e1bSAdrian McMenamin 	struct maple_device *mdev;
2503dd5e1bSAdrian McMenamin };
2603dd5e1bSAdrian McMenamin 
dc_mouse_callback(struct mapleq * mq)2703dd5e1bSAdrian McMenamin static void dc_mouse_callback(struct mapleq *mq)
2803dd5e1bSAdrian McMenamin {
2903dd5e1bSAdrian McMenamin 	int buttons, relx, rely, relz;
3003dd5e1bSAdrian McMenamin 	struct maple_device *mapledev = mq->dev;
3103dd5e1bSAdrian McMenamin 	struct dc_mouse *mse = maple_get_drvdata(mapledev);
3203dd5e1bSAdrian McMenamin 	struct input_dev *dev = mse->dev;
336b348085SAdrian McMenamin 	unsigned char *res = mq->recvbuf->buf;
3403dd5e1bSAdrian McMenamin 
3503dd5e1bSAdrian McMenamin 	buttons = ~res[8];
3603dd5e1bSAdrian McMenamin 	relx = *(unsigned short *)(res + 12) - 512;
3703dd5e1bSAdrian McMenamin 	rely = *(unsigned short *)(res + 14) - 512;
3803dd5e1bSAdrian McMenamin 	relz = *(unsigned short *)(res + 16) - 512;
3903dd5e1bSAdrian McMenamin 
4003dd5e1bSAdrian McMenamin 	input_report_key(dev, BTN_LEFT,   buttons & 4);
4103dd5e1bSAdrian McMenamin 	input_report_key(dev, BTN_MIDDLE, buttons & 9);
4203dd5e1bSAdrian McMenamin 	input_report_key(dev, BTN_RIGHT,  buttons & 2);
4303dd5e1bSAdrian McMenamin 	input_report_rel(dev, REL_X,      relx);
4403dd5e1bSAdrian McMenamin 	input_report_rel(dev, REL_Y,      rely);
4503dd5e1bSAdrian McMenamin 	input_report_rel(dev, REL_WHEEL,  relz);
4603dd5e1bSAdrian McMenamin 	input_sync(dev);
4703dd5e1bSAdrian McMenamin }
4803dd5e1bSAdrian McMenamin 
dc_mouse_open(struct input_dev * dev)4903dd5e1bSAdrian McMenamin static int dc_mouse_open(struct input_dev *dev)
5003dd5e1bSAdrian McMenamin {
516b348085SAdrian McMenamin 	struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev));
5203dd5e1bSAdrian McMenamin 
5303dd5e1bSAdrian McMenamin 	maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50,
5403dd5e1bSAdrian McMenamin 		MAPLE_FUNC_MOUSE);
5503dd5e1bSAdrian McMenamin 
5603dd5e1bSAdrian McMenamin 	return 0;
5703dd5e1bSAdrian McMenamin }
5803dd5e1bSAdrian McMenamin 
dc_mouse_close(struct input_dev * dev)5903dd5e1bSAdrian McMenamin static void dc_mouse_close(struct input_dev *dev)
6003dd5e1bSAdrian McMenamin {
616b348085SAdrian McMenamin 	struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev));
6203dd5e1bSAdrian McMenamin 
6303dd5e1bSAdrian McMenamin 	maple_getcond_callback(mse->mdev, dc_mouse_callback, 0,
6403dd5e1bSAdrian McMenamin 		MAPLE_FUNC_MOUSE);
6503dd5e1bSAdrian McMenamin }
6603dd5e1bSAdrian McMenamin 
676b348085SAdrian McMenamin /* allow the mouse to be used */
probe_maple_mouse(struct device * dev)685298cc4cSBill Pemberton static int probe_maple_mouse(struct device *dev)
6903dd5e1bSAdrian McMenamin {
7003dd5e1bSAdrian McMenamin 	struct maple_device *mdev = to_maple_dev(dev);
7103dd5e1bSAdrian McMenamin 	struct maple_driver *mdrv = to_maple_driver(dev->driver);
726b348085SAdrian McMenamin 	int error;
7303dd5e1bSAdrian McMenamin 	struct input_dev *input_dev;
7403dd5e1bSAdrian McMenamin 	struct dc_mouse *mse;
7503dd5e1bSAdrian McMenamin 
76*dc2f1423SErick Archer 	mse = kzalloc(sizeof(*mse), GFP_KERNEL);
776b348085SAdrian McMenamin 	if (!mse) {
7803dd5e1bSAdrian McMenamin 		error = -ENOMEM;
7903dd5e1bSAdrian McMenamin 		goto fail;
8003dd5e1bSAdrian McMenamin 	}
8103dd5e1bSAdrian McMenamin 
826b348085SAdrian McMenamin 	input_dev = input_allocate_device();
836b348085SAdrian McMenamin 	if (!input_dev) {
846b348085SAdrian McMenamin 		error = -ENOMEM;
856b348085SAdrian McMenamin 		goto fail_nomem;
866b348085SAdrian McMenamin 	}
876b348085SAdrian McMenamin 
8803dd5e1bSAdrian McMenamin 	mse->dev = input_dev;
8903dd5e1bSAdrian McMenamin 	mse->mdev = mdev;
9003dd5e1bSAdrian McMenamin 
9103dd5e1bSAdrian McMenamin 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
9203dd5e1bSAdrian McMenamin 	input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
9303dd5e1bSAdrian McMenamin 		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
9403dd5e1bSAdrian McMenamin 	input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) |
9503dd5e1bSAdrian McMenamin 		BIT_MASK(REL_WHEEL);
9603dd5e1bSAdrian McMenamin 	input_dev->open = dc_mouse_open;
9703dd5e1bSAdrian McMenamin 	input_dev->close = dc_mouse_close;
986b348085SAdrian McMenamin 	input_dev->name = mdev->product_name;
996b348085SAdrian McMenamin 	input_dev->id.bustype = BUS_HOST;
1006b348085SAdrian McMenamin 	error =	input_register_device(input_dev);
1016b348085SAdrian McMenamin 	if (error)
1026b348085SAdrian McMenamin 		goto fail_register;
10303dd5e1bSAdrian McMenamin 
10403dd5e1bSAdrian McMenamin 	mdev->driver = mdrv;
10503dd5e1bSAdrian McMenamin 	maple_set_drvdata(mdev, mse);
10603dd5e1bSAdrian McMenamin 
1076b348085SAdrian McMenamin 	return error;
10803dd5e1bSAdrian McMenamin 
1096b348085SAdrian McMenamin fail_register:
11003dd5e1bSAdrian McMenamin 	input_free_device(input_dev);
1116b348085SAdrian McMenamin fail_nomem:
11203dd5e1bSAdrian McMenamin 	kfree(mse);
1136b348085SAdrian McMenamin fail:
11403dd5e1bSAdrian McMenamin 	return error;
11503dd5e1bSAdrian McMenamin }
11603dd5e1bSAdrian McMenamin 
remove_maple_mouse(struct device * dev)117e2619cf7SBill Pemberton static int remove_maple_mouse(struct device *dev)
11803dd5e1bSAdrian McMenamin {
11903dd5e1bSAdrian McMenamin 	struct maple_device *mdev = to_maple_dev(dev);
12003dd5e1bSAdrian McMenamin 	struct dc_mouse *mse = maple_get_drvdata(mdev);
12103dd5e1bSAdrian McMenamin 
12203dd5e1bSAdrian McMenamin 	mdev->callback = NULL;
12303dd5e1bSAdrian McMenamin 	input_unregister_device(mse->dev);
12403dd5e1bSAdrian McMenamin 	maple_set_drvdata(mdev, NULL);
12503dd5e1bSAdrian McMenamin 	kfree(mse);
12603dd5e1bSAdrian McMenamin 
12703dd5e1bSAdrian McMenamin 	return 0;
12803dd5e1bSAdrian McMenamin }
12903dd5e1bSAdrian McMenamin 
13003dd5e1bSAdrian McMenamin static struct maple_driver dc_mouse_driver = {
13103dd5e1bSAdrian McMenamin 	.function =	MAPLE_FUNC_MOUSE,
13203dd5e1bSAdrian McMenamin 	.drv = {
13303dd5e1bSAdrian McMenamin 		.name = "Dreamcast_mouse",
13403dd5e1bSAdrian McMenamin 		.probe = probe_maple_mouse,
1351cb0aa88SBill Pemberton 		.remove = remove_maple_mouse,
13603dd5e1bSAdrian McMenamin 	},
13703dd5e1bSAdrian McMenamin };
13803dd5e1bSAdrian McMenamin 
dc_mouse_init(void)13903dd5e1bSAdrian McMenamin static int __init dc_mouse_init(void)
14003dd5e1bSAdrian McMenamin {
14103dd5e1bSAdrian McMenamin 	return maple_driver_register(&dc_mouse_driver);
14203dd5e1bSAdrian McMenamin }
14303dd5e1bSAdrian McMenamin 
dc_mouse_exit(void)14403dd5e1bSAdrian McMenamin static void __exit dc_mouse_exit(void)
14503dd5e1bSAdrian McMenamin {
14603dd5e1bSAdrian McMenamin 	maple_driver_unregister(&dc_mouse_driver);
14703dd5e1bSAdrian McMenamin }
14803dd5e1bSAdrian McMenamin 
14903dd5e1bSAdrian McMenamin module_init(dc_mouse_init);
15003dd5e1bSAdrian McMenamin module_exit(dc_mouse_exit);
151