162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 1999-2002 Vojtech Pavlik 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#ifndef _GAMEPORT_H 662306a36Sopenharmony_ci#define _GAMEPORT_H 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci#include <linux/list.h> 1062306a36Sopenharmony_ci#include <linux/mutex.h> 1162306a36Sopenharmony_ci#include <linux/device.h> 1262306a36Sopenharmony_ci#include <linux/timer.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <uapi/linux/gameport.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct gameport { 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci void *port_data; /* Private pointer for gameport drivers */ 1962306a36Sopenharmony_ci char name[32]; 2062306a36Sopenharmony_ci char phys[32]; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci int io; 2362306a36Sopenharmony_ci int speed; 2462306a36Sopenharmony_ci int fuzz; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci void (*trigger)(struct gameport *); 2762306a36Sopenharmony_ci unsigned char (*read)(struct gameport *); 2862306a36Sopenharmony_ci int (*cooked_read)(struct gameport *, int *, int *); 2962306a36Sopenharmony_ci int (*calibrate)(struct gameport *, int *, int *); 3062306a36Sopenharmony_ci int (*open)(struct gameport *, int); 3162306a36Sopenharmony_ci void (*close)(struct gameport *); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci struct timer_list poll_timer; 3462306a36Sopenharmony_ci unsigned int poll_interval; /* in msecs */ 3562306a36Sopenharmony_ci spinlock_t timer_lock; 3662306a36Sopenharmony_ci unsigned int poll_cnt; 3762306a36Sopenharmony_ci void (*poll_handler)(struct gameport *); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci struct gameport *parent, *child; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci struct gameport_driver *drv; 4262306a36Sopenharmony_ci struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci struct device dev; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci struct list_head node; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci#define to_gameport_port(d) container_of(d, struct gameport, dev) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistruct gameport_driver { 5162306a36Sopenharmony_ci const char *description; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci int (*connect)(struct gameport *, struct gameport_driver *drv); 5462306a36Sopenharmony_ci int (*reconnect)(struct gameport *); 5562306a36Sopenharmony_ci void (*disconnect)(struct gameport *); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci struct device_driver driver; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci bool ignore; 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci#define to_gameport_driver(d) container_of(d, struct gameport_driver, driver) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciint gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode); 6462306a36Sopenharmony_civoid gameport_close(struct gameport *gameport); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#if IS_REACHABLE(CONFIG_GAMEPORT) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_civoid __gameport_register_port(struct gameport *gameport, struct module *owner); 6962306a36Sopenharmony_ci/* use a define to avoid include chaining to get THIS_MODULE */ 7062306a36Sopenharmony_ci#define gameport_register_port(gameport) \ 7162306a36Sopenharmony_ci __gameport_register_port(gameport, THIS_MODULE) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_civoid gameport_unregister_port(struct gameport *gameport); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci__printf(2, 3) 7662306a36Sopenharmony_civoid gameport_set_phys(struct gameport *gameport, const char *fmt, ...); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#else 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic inline void gameport_register_port(struct gameport *gameport) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci return; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic inline void gameport_unregister_port(struct gameport *gameport) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci return; 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic inline __printf(2, 3) 9162306a36Sopenharmony_civoid gameport_set_phys(struct gameport *gameport, const char *fmt, ...) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci return; 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#endif 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic inline struct gameport *gameport_allocate_port(void) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci struct gameport *gameport = kzalloc(sizeof(struct gameport), GFP_KERNEL); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci return gameport; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic inline void gameport_free_port(struct gameport *gameport) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci kfree(gameport); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic inline void gameport_set_name(struct gameport *gameport, const char *name) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci strscpy(gameport->name, name, sizeof(gameport->name)); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * Use the following functions to manipulate gameport's per-port 11762306a36Sopenharmony_ci * driver-specific data. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_cistatic inline void *gameport_get_drvdata(struct gameport *gameport) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci return dev_get_drvdata(&gameport->dev); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic inline void gameport_set_drvdata(struct gameport *gameport, void *data) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci dev_set_drvdata(&gameport->dev, data); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* 13062306a36Sopenharmony_ci * Use the following functions to pin gameport's driver in process context 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_cistatic inline int gameport_pin_driver(struct gameport *gameport) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci return mutex_lock_interruptible(&gameport->drv_mutex); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic inline void gameport_unpin_driver(struct gameport *gameport) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci mutex_unlock(&gameport->drv_mutex); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ciint __must_check __gameport_register_driver(struct gameport_driver *drv, 14362306a36Sopenharmony_ci struct module *owner, const char *mod_name); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* use a define to avoid include chaining to get THIS_MODULE & friends */ 14662306a36Sopenharmony_ci#define gameport_register_driver(drv) \ 14762306a36Sopenharmony_ci __gameport_register_driver(drv, THIS_MODULE, KBUILD_MODNAME) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_civoid gameport_unregister_driver(struct gameport_driver *drv); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci/** 15262306a36Sopenharmony_ci * module_gameport_driver() - Helper macro for registering a gameport driver 15362306a36Sopenharmony_ci * @__gameport_driver: gameport_driver struct 15462306a36Sopenharmony_ci * 15562306a36Sopenharmony_ci * Helper macro for gameport drivers which do not do anything special in 15662306a36Sopenharmony_ci * module init/exit. This eliminates a lot of boilerplate. Each module may 15762306a36Sopenharmony_ci * only use this macro once, and calling it replaces module_init() and 15862306a36Sopenharmony_ci * module_exit(). 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_ci#define module_gameport_driver(__gameport_driver) \ 16162306a36Sopenharmony_ci module_driver(__gameport_driver, gameport_register_driver, \ 16262306a36Sopenharmony_ci gameport_unregister_driver) 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic inline void gameport_trigger(struct gameport *gameport) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci gameport->trigger(gameport); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic inline unsigned char gameport_read(struct gameport *gameport) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci return gameport->read(gameport); 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic inline int gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci if (gameport->cooked_read) 17862306a36Sopenharmony_ci return gameport->cooked_read(gameport, axes, buttons); 17962306a36Sopenharmony_ci else 18062306a36Sopenharmony_ci return -1; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic inline int gameport_calibrate(struct gameport *gameport, int *axes, int *max) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci if (gameport->calibrate) 18662306a36Sopenharmony_ci return gameport->calibrate(gameport, axes, max); 18762306a36Sopenharmony_ci else 18862306a36Sopenharmony_ci return -1; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic inline int gameport_time(struct gameport *gameport, int time) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci return (time * gameport->speed) / 1000; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic inline void gameport_set_poll_handler(struct gameport *gameport, void (*handler)(struct gameport *)) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci gameport->poll_handler = handler; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic inline void gameport_set_poll_interval(struct gameport *gameport, unsigned int msecs) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci gameport->poll_interval = msecs; 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_civoid gameport_start_polling(struct gameport *gameport); 20762306a36Sopenharmony_civoid gameport_stop_polling(struct gameport *gameport); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#endif 210