#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/workqueue.h>
#define DRIVER_DESC …
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…);
MODULE_LICENSE(…) …;
static int bell_volume = …;
module_param(bell_volume, int, 0);
MODULE_PARM_DESC(…) …;
static int keyclick_volume = …;
module_param(keyclick_volume, int, 0);
MODULE_PARM_DESC(…) …;
static int ctrlclick_volume = …;
module_param(ctrlclick_volume, int, 0);
MODULE_PARM_DESC(…) …;
static int lk201_compose_is_alt;
module_param(lk201_compose_is_alt, int, 0);
MODULE_PARM_DESC(…) …;
#undef LKKBD_DEBUG
#ifdef LKKBD_DEBUG
#define DBG …
#else
#define DBG(x...) …
#endif
#define LK_LED_WAIT …
#define LK_LED_COMPOSE …
#define LK_LED_SHIFTLOCK …
#define LK_LED_SCROLLLOCK …
#define LK_CMD_LED_ON …
#define LK_CMD_LED_OFF …
#define LK_MODE_DOWN …
#define LK_MODE_AUTODOWN …
#define LK_MODE_UPDOWN …
#define LK_CMD_SET_MODE(mode, div) …
#define LK_CMD_ENABLE_KEYCLICK …
#define LK_CMD_DISABLE_KEYCLICK …
#define LK_CMD_DISABLE_BELL …
#define LK_CMD_SOUND_BELL …
#define LK_CMD_ENABLE_BELL …
#define LK_CMD_DISABLE_CTRCLICK …
#define LK_CMD_ENABLE_CTRCLICK …
#define LK_CMD_SET_DEFAULTS …
#define LK_CMD_POWERCYCLE_RESET …
#define LK_CMD_ENABLE_LK401 …
#define LK_CMD_REQUEST_ID …
#define LK_STUCK_KEY …
#define LK_SELFTEST_FAILED …
#define LK_ALL_KEYS_UP …
#define LK_METRONOME …
#define LK_OUTPUT_ERROR …
#define LK_INPUT_ERROR …
#define LK_KBD_LOCKED …
#define LK_KBD_TEST_MODE_ACK …
#define LK_PREFIX_KEY_DOWN …
#define LK_MODE_CHANGE_ACK …
#define LK_RESPONSE_RESERVED …
#define LK_NUM_KEYCODES …
#define LK_NUM_IGNORE_BYTES …
static unsigned short lkkbd_keycode[LK_NUM_KEYCODES] = …;
#define CHECK_LED(LK, VAR_ON, VAR_OFF, LED, BITS) …
struct lkkbd { … };
#ifdef LKKBD_DEBUG
static struct {
unsigned char value;
unsigned char *name;
} lk_response[] = {
#define RESPONSE …
RESPONSE(LK_STUCK_KEY),
RESPONSE(LK_SELFTEST_FAILED),
RESPONSE(LK_ALL_KEYS_UP),
RESPONSE(LK_METRONOME),
RESPONSE(LK_OUTPUT_ERROR),
RESPONSE(LK_INPUT_ERROR),
RESPONSE(LK_KBD_LOCKED),
RESPONSE(LK_KBD_TEST_MODE_ACK),
RESPONSE(LK_PREFIX_KEY_DOWN),
RESPONSE(LK_MODE_CHANGE_ACK),
RESPONSE(LK_RESPONSE_RESERVED),
#undef RESPONSE
};
static unsigned char *response_name(unsigned char value)
{
int i;
for (i = 0; i < ARRAY_SIZE(lk_response); i++)
if (lk_response[i].value == value)
return lk_response[i].name;
return "<unknown>";
}
#endif
static unsigned char volume_to_hw(int volume_percent)
{ … }
static void lkkbd_detection_done(struct lkkbd *lk)
{ … }
static irqreturn_t lkkbd_interrupt(struct serio *serio,
unsigned char data, unsigned int flags)
{ … }
static void lkkbd_toggle_leds(struct lkkbd *lk)
{ … }
static void lkkbd_toggle_keyclick(struct lkkbd *lk, bool on)
{ … }
static int lkkbd_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{ … }
static void lkkbd_reinit(struct work_struct *work)
{ … }
static int lkkbd_connect(struct serio *serio, struct serio_driver *drv)
{ … }
static void lkkbd_disconnect(struct serio *serio)
{ … }
static const struct serio_device_id lkkbd_serio_ids[] = …;
MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);
static struct serio_driver lkkbd_drv = …;
module_serio_driver(…) …;