2019-05-19 15:08:20 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2009-01-30 09:56:08 +03:00
/*
* SEGA Dreamcast mouse driver
* Based on drivers / usb / usbmouse . c
*
2009-04-26 00:43:18 +04:00
* Copyright ( c ) Yaegashi Takeshi , 2001
* Copyright ( c ) Adrian McMenamin , 2008 - 2009
2009-01-30 09:56:08 +03:00
*/
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/input.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/timer.h>
# include <linux/maple.h>
MODULE_AUTHOR ( " Adrian McMenamin <adrian@mcmen.demon.co.uk> " ) ;
MODULE_DESCRIPTION ( " SEGA Dreamcast mouse driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
struct dc_mouse {
struct input_dev * dev ;
struct maple_device * mdev ;
} ;
static void dc_mouse_callback ( struct mapleq * mq )
{
int buttons , relx , rely , relz ;
struct maple_device * mapledev = mq - > dev ;
struct dc_mouse * mse = maple_get_drvdata ( mapledev ) ;
struct input_dev * dev = mse - > dev ;
2009-04-26 00:43:18 +04:00
unsigned char * res = mq - > recvbuf - > buf ;
2009-01-30 09:56:08 +03:00
buttons = ~ res [ 8 ] ;
relx = * ( unsigned short * ) ( res + 12 ) - 512 ;
rely = * ( unsigned short * ) ( res + 14 ) - 512 ;
relz = * ( unsigned short * ) ( res + 16 ) - 512 ;
input_report_key ( dev , BTN_LEFT , buttons & 4 ) ;
input_report_key ( dev , BTN_MIDDLE , buttons & 9 ) ;
input_report_key ( dev , BTN_RIGHT , buttons & 2 ) ;
input_report_rel ( dev , REL_X , relx ) ;
input_report_rel ( dev , REL_Y , rely ) ;
input_report_rel ( dev , REL_WHEEL , relz ) ;
input_sync ( dev ) ;
}
static int dc_mouse_open ( struct input_dev * dev )
{
2009-04-26 00:43:18 +04:00
struct dc_mouse * mse = maple_get_drvdata ( to_maple_dev ( & dev - > dev ) ) ;
2009-01-30 09:56:08 +03:00
maple_getcond_callback ( mse - > mdev , dc_mouse_callback , HZ / 50 ,
MAPLE_FUNC_MOUSE ) ;
return 0 ;
}
static void dc_mouse_close ( struct input_dev * dev )
{
2009-04-26 00:43:18 +04:00
struct dc_mouse * mse = maple_get_drvdata ( to_maple_dev ( & dev - > dev ) ) ;
2009-01-30 09:56:08 +03:00
maple_getcond_callback ( mse - > mdev , dc_mouse_callback , 0 ,
MAPLE_FUNC_MOUSE ) ;
}
2009-04-26 00:43:18 +04:00
/* allow the mouse to be used */
2012-11-24 09:38:25 +04:00
static int probe_maple_mouse ( struct device * dev )
2009-01-30 09:56:08 +03:00
{
struct maple_device * mdev = to_maple_dev ( dev ) ;
struct maple_driver * mdrv = to_maple_driver ( dev - > driver ) ;
2009-04-26 00:43:18 +04:00
int error ;
2009-01-30 09:56:08 +03:00
struct input_dev * input_dev ;
struct dc_mouse * mse ;
mse = kzalloc ( sizeof ( struct dc_mouse ) , GFP_KERNEL ) ;
2009-04-26 00:43:18 +04:00
if ( ! mse ) {
2009-01-30 09:56:08 +03:00
error = - ENOMEM ;
goto fail ;
}
2009-04-26 00:43:18 +04:00
input_dev = input_allocate_device ( ) ;
if ( ! input_dev ) {
error = - ENOMEM ;
goto fail_nomem ;
}
2009-01-30 09:56:08 +03:00
mse - > dev = input_dev ;
mse - > mdev = mdev ;
input_dev - > evbit [ 0 ] = BIT_MASK ( EV_KEY ) | BIT_MASK ( EV_REL ) ;
input_dev - > keybit [ BIT_WORD ( BTN_MOUSE ) ] = BIT_MASK ( BTN_LEFT ) |
BIT_MASK ( BTN_RIGHT ) | BIT_MASK ( BTN_MIDDLE ) ;
input_dev - > relbit [ 0 ] = BIT_MASK ( REL_X ) | BIT_MASK ( REL_Y ) |
BIT_MASK ( REL_WHEEL ) ;
input_dev - > open = dc_mouse_open ;
input_dev - > close = dc_mouse_close ;
2009-04-26 00:43:18 +04:00
input_dev - > name = mdev - > product_name ;
input_dev - > id . bustype = BUS_HOST ;
error = input_register_device ( input_dev ) ;
if ( error )
goto fail_register ;
2009-01-30 09:56:08 +03:00
mdev - > driver = mdrv ;
maple_set_drvdata ( mdev , mse ) ;
2009-04-26 00:43:18 +04:00
return error ;
2009-01-30 09:56:08 +03:00
2009-04-26 00:43:18 +04:00
fail_register :
2009-01-30 09:56:08 +03:00
input_free_device ( input_dev ) ;
2009-04-26 00:43:18 +04:00
fail_nomem :
2009-01-30 09:56:08 +03:00
kfree ( mse ) ;
2009-04-26 00:43:18 +04:00
fail :
2009-01-30 09:56:08 +03:00
return error ;
}
2012-11-24 09:50:47 +04:00
static int remove_maple_mouse ( struct device * dev )
2009-01-30 09:56:08 +03:00
{
struct maple_device * mdev = to_maple_dev ( dev ) ;
struct dc_mouse * mse = maple_get_drvdata ( mdev ) ;
mdev - > callback = NULL ;
input_unregister_device ( mse - > dev ) ;
maple_set_drvdata ( mdev , NULL ) ;
kfree ( mse ) ;
return 0 ;
}
static struct maple_driver dc_mouse_driver = {
. function = MAPLE_FUNC_MOUSE ,
. drv = {
. name = " Dreamcast_mouse " ,
. probe = probe_maple_mouse ,
2012-11-24 09:27:39 +04:00
. remove = remove_maple_mouse ,
2009-01-30 09:56:08 +03:00
} ,
} ;
static int __init dc_mouse_init ( void )
{
return maple_driver_register ( & dc_mouse_driver ) ;
}
static void __exit dc_mouse_exit ( void )
{
maple_driver_unregister ( & dc_mouse_driver ) ;
}
module_init ( dc_mouse_init ) ;
module_exit ( dc_mouse_exit ) ;