~mil/ppbbq10

d9d0bdff46d93eaf6948b6de41882387e28f5dca — Miles Alan 9 months ago d1a6589
Stylistic updates - alphabetize fns/defs, func decls on nl, etc.
1 files changed, 217 insertions(+), 210 deletions(-)

M ppbbq10.c
M ppbbq10.c => ppbbq10.c +217 -210
@@ 11,47 11,61 @@
#include <linux/slab.h>
#include <linux/types.h>

//#define DEBUG

#define REG_VER		0x01
#define REG_CFG		0x02
#define REG_INT		0x03
#define REG_KEY		0x04
#define REG_BKL		0x05
#define REG_DEB		0x06
#define REG_FRQ		0x07
#define REG_RST		0x08
#define REG_FIF		0x09

#define WRITE_MASK	BIT(7)

#define CFG_USE_MODS		BIT(7)
#define CFG_REPORT_MODS		BIT(6)
#define CFG_PANIC_INT		BIT(5)
#define CFG_KEY_INT			BIT(4)
#define CFG_NUMLOCK_INT		BIT(3)
/* defines */
#define CFG_CAPSLOCK_INT	BIT(2)
#define CFG_KEY_INT	BIT(4)
#define CFG_NUMLOCK_INT	BIT(3)
#define CFG_OVERFLOW_INT	BIT(1)
#define CFG_OVERFLOW_ON		BIT(0)

#define INT_PANIC		BIT(4)
#define INT_KEY			BIT(3)
#define INT_NUMLOCK		BIT(2)
#define CFG_OVERFLOW_ON	BIT(0)
#define CFG_PANIC_INT	BIT(5)
#define CFG_REPORT_MODS	BIT(6)
#define CFG_USE_MODS	BIT(7)
#define INT_CAPSLOCK	BIT(1)
#define INT_KEY	BIT(3)
#define INT_NUMLOCK	BIT(2)
#define INT_OVERFLOW	BIT(0)

#define _KEY_NUMLOCK	BIT(6)
#define _KEY_CAPSLOCK	BIT(5)
#define INT_PANIC	BIT(4)
#define KEY_COUNT_MASK	0x1F

#define NUM_KEYCODES	256
#define REG_BKL	0x05
#define REG_CFG	0x02
#define REG_DEB	0x06
#define REG_FIF	0x09
#define REG_FRQ	0x07
#define REG_INT	0x03
#define REG_KEY	0x04
#define REG_RST	0x08
#define REG_VER	0x01
#define STATE_HOLD	2
#define STATE_IDLE	0
#define STATE_PRESS	1
#define STATE_RELEASE	3
#define STATE_HOLD		2
#define STATE_PRESS		1
#define STATE_IDLE		0
#define WRITE_MASK	BIT(7)
#define _KEY_CAPSLOCK	BIT(5)
#define _KEY_NUMLOCK	BIT(6)
//#define DEBUG

#define NUM_KEYCODES	256
/* structs */
struct ppbbq10_data {
	unsigned short keymap_norm[NUM_KEYCODES];
	struct i2c_client *client;
	struct input_dev *input;
};

static unsigned short keycodes[NUM_KEYCODES] = {
/* function declarations */
static int ppbbq10_backlight_update_status(struct backlight_device *bd);
static void __exit ppbbq10_exit(void);
static int __init ppbbq10_init(void);
static irqreturn_t ppbbq10_irq_handler(int irq, void *dev_id);
static int ppbbq10_probe(struct i2c_client *client, const struct i2c_device_id *id);
static void ppbbq10_read_fifo(struct ppbbq10_data *drv_data);
static int ppbbq10_read_reg(struct ppbbq10_data *drv_data, u8 reg, u8 *buf, u8 len);
static void ppbbq10_update_locks(struct ppbbq10_data *drv_data);
static int ppbbq10_write_data(struct ppbbq10_data *drv_data, u8 reg, const u8 *buf, u8 len);
static int ppbbq10_write_reg(struct ppbbq10_data *drv_data, u8 reg);

/* variables */
static unsigned short keymap_norm[NUM_KEYCODES] = {
	[0x01] = KEY_UP,
	[0x02] = KEY_DOWN,
	[0x03] = KEY_LEFT,


@@ 59,11 73,9 @@ static unsigned short keycodes[NUM_KEYCODES] = {
	[0x05] = KEY_ENTER,
	[0x06] = KEY_MENU,
	[0x07] = KEY_BACK,

	[17] = KEY_LEFTALT,
	[18] = KEY_LEFTSHIFT,
	[19] = KEY_LEFTCTRL,

	['A'] = KEY_A,
	['B'] = KEY_B,
	['C'] = KEY_C,


@@ 90,166 102,63 @@ static unsigned short keycodes[NUM_KEYCODES] = {
	['X'] = KEY_X,
	['Y'] = KEY_Y,
	['Z'] = KEY_Z,

	[' '] = KEY_SPACE,
	['~'] = KEY_0,
	['$'] = KEY_GRAVE,

	['\b'] = KEY_BACKSPACE,
	['\n'] = KEY_ENTER,
};

struct ppbbq10_data {
	unsigned short keycode[NUM_KEYCODES];
	struct i2c_client *client;
	struct input_dev *input;
};

static struct i2c_adapter *adapter;
static struct i2c_client *client;
static struct i2c_board_info ppbbq10_i2c_board_info[] __initdata = {
	{ I2C_BOARD_INFO("ppbbq10", 0x1f), /*.irq = gpio_to_irq(11)*/ }
};
static const struct i2c_device_id ppbbq10_id[] = {
	{ "ppbbq10", 0, }
static const struct backlight_ops backlight_ops = {
	.options		= BL_CORE_SUSPENDRESUME,
	.update_status	= ppbbq10_backlight_update_status,
};
static const struct i2c_device_id ppbbq10_id[] = { { "ppbbq10", 0, } };
static struct i2c_adapter *adapter;
static struct i2c_client *client;
static struct backlight_properties backlight_props = {
	.type			= BACKLIGHT_PLATFORM,
	.max_brightness = 255,
	.brightness		= 127,
};


static int ppbbq10_write_reg(struct ppbbq10_data *drv_data, u8 reg)
/* function implementations */
static int
ppbbq10_backlight_update_status(struct backlight_device *bd)
{
	struct i2c_client *client = drv_data->client;
	int error;

	struct i2c_msg msgs[] = {
		{ .addr = client->addr, .flags = I2C_M_STOP, .len = sizeof(u8), .buf = &reg, },
	};

	error = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (error != ARRAY_SIZE(msgs)) {
		dev_err(&client->dev, "%s failed, reg: %d, error: %d\n",
		__func__, reg, error);

		return error;
	}
	const struct backlight_properties *p = &bd->props;
	const u8 intensity = (p->power == FB_BLANK_UNBLANK) ? p->brightness : 0;
	struct ppbbq10_data *drv_data = dev_get_drvdata(&bd->dev);

	return 0;
	return ppbbq10_write_data(drv_data, REG_BKL, &intensity, sizeof(intensity));
}

static int ppbbq10_write_data(struct ppbbq10_data *drv_data, u8 reg, const u8 *buf, u8 len)
static void __exit
ppbbq10_exit(void)
{
	struct i2c_client *client = drv_data->client;
	int error;

	reg |= 0x80;

	struct i2c_msg msgs[] = {
		{ .addr = client->addr, .flags = 0, .len = sizeof(u8), .buf = &reg, },
		{ .addr = client->addr, .flags = 0, .len = len, .buf = (u8*)buf, },
	};

	error = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (error != ARRAY_SIZE(msgs)) {
		dev_err(&client->dev, "%s failed, reg: %d, error: %d\n",
			__func__, reg, error);

		return error;
	}

	return 0;
	printk(KERN_INFO "Unregister ppbbq10 kernel module.\n");
	i2c_unregister_device(client);
	/*i2c_del_driver(&ppbbq10_driver);*/
}

static int ppbbq10_read_reg(struct ppbbq10_data *drv_data, u8 reg, u8 *buf, u8 len)
static int __init
ppbbq10_init(void)
{
	struct i2c_client *client = drv_data->client;
	int error;

	struct i2c_msg msgs[] = {
		{ .addr = client->addr, .flags = client->flags, .len = sizeof(u8), .buf = &reg, },
		{ .addr = client->addr, .flags = client->flags | I2C_M_RD, .len = len, .buf = buf }
	};

	error = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (error != ARRAY_SIZE(msgs)) {
		dev_err(&client->dev, "%s failed, reg: %d, error: %d\n",
			__func__, reg, error);

		return error;
	adapter = i2c_get_adapter(3);
	printk(KERN_INFO "Initialize ppbq10 kernel module.\n");
	if (!adapter) {
		printk(KERN_INFO "Error acquiring i2c adapter 3.\n");
		return -1;
	}

	client = i2c_new_client_device(adapter, ppbbq10_i2c_board_info);
	//client->irq = gpio_to_irq(2);
	return 0;
}

static void ppbbq10_update_locks(struct ppbbq10_data *drv_data)
{
	struct input_dev *input = drv_data->input;
	struct i2c_client *client = drv_data->client;
	u8 data;
	int error;

	error = ppbbq10_read_reg(drv_data, REG_KEY, &data, sizeof(u8));
	if (error < 0) {
		dev_err(&client->dev, "%s failed to read REG_KEY, error: %d\n",
			__func__, error);
		return;
	}

	pr_warn("%s status: 0x%02X\n", __func__, data);

	//input_report_key(input, KEY_NUMLOCK, data & _KEY_NUMLOCK);
	//input_report_key(input, KEY_CAPSLOCK, data & _KEY_CAPSLOCK);

	input_sync(input);
}

static void ppbbq10_read_fifo(struct ppbbq10_data *drv_data)
{
	struct input_dev *input = drv_data->input;
	struct i2c_client *client = drv_data->client;
	unsigned int keycode;
	u8 data[2];
	u8 count;
	int error;

	error = ppbbq10_read_reg(drv_data, REG_KEY, data, sizeof(u8));
	if (error < 0) {
		dev_err(&client->dev, "%s failed to read REG_KEY, error: %d\n",
			__func__, error);
		return;
	}

	pr_debug("%s status: 0x%02X\n", __func__, data[0]);

	count = (data[0] & KEY_COUNT_MASK);

	while (count > 0) {
		error = ppbbq10_read_reg(drv_data, REG_FIF, data, sizeof(u8) * 2);
		if (error < 0) {
			dev_err(&client->dev, "%s failed to read REG_FIF, error: %d\n",
				__func__, error);
			return;
		}

		pr_debug("%s key %d/%c, state: %d\n",
			__func__, data[1], data[1], data[0]);

		count -= 1;

		if (data[0] == STATE_PRESS || data[0] == STATE_RELEASE) {
			input_event(input, EV_MSC, MSC_SCAN, data[1]);

			keycode = drv_data->keycode[data[1]];
			if (keycode == KEY_UNKNOWN) {
				pr_warn("%s code 0x%02X UNKNOWN\n", __func__, data[1]);
			} else {
				input_report_key(input, keycode, data[0] == STATE_PRESS);
			}
		}
	}

	input_sync(input);
}

static irqreturn_t ppbbq10_irq_handler(int irq, void *dev_id)
static irqreturn_t
ppbbq10_irq_handler(int irq, void *dev_id)
{
	struct ppbbq10_data *drv_data = dev_id;
	struct i2c_client *client = drv_data->client;


@@ 288,27 197,8 @@ static irqreturn_t ppbbq10_irq_handler(int irq, void *dev_id)
	return IRQ_HANDLED;
}

static int ppbbq10_backlight_update_status(struct backlight_device *bd)
{
	const struct backlight_properties *p = &bd->props;
	const u8 intensity = (p->power == FB_BLANK_UNBLANK) ? p->brightness : 0;
	struct ppbbq10_data *drv_data = dev_get_drvdata(&bd->dev);

	return ppbbq10_write_data(drv_data, REG_BKL, &intensity, sizeof(intensity));
}

static const struct backlight_ops backlight_ops = {
	.options		= BL_CORE_SUSPENDRESUME,
	.update_status	= ppbbq10_backlight_update_status,
};

static struct backlight_properties backlight_props = {
	.type			= BACKLIGHT_PLATFORM,
	.max_brightness = 255,
	.brightness		= 127,
};

static int ppbbq10_probe(struct i2c_client *client, const struct i2c_device_id *id)
static int
ppbbq10_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	struct device *dev = &client->dev;
	struct ppbbq10_data *drv_data;


@@ 323,7 213,7 @@ static int ppbbq10_probe(struct i2c_client *client, const struct i2c_device_id *
		return -ENOMEM;

	drv_data->client = client;
	memcpy(drv_data->keycode, keycodes, sizeof(drv_data->keycode));
	memcpy(drv_data->keymap_norm, keymap_norm, sizeof(drv_data->keymap_norm));

	error = ppbbq10_write_reg(drv_data, REG_RST);
	if (error)


@@ 365,12 255,12 @@ static int ppbbq10_probe(struct i2c_client *client, const struct i2c_device_id *
	input->id.vendor  = 0x0001;
	input->id.product = 0x0001;
	input->id.version = 0x0001;
	input->keycode = drv_data->keycode;
	input->keycodesize = sizeof(drv_data->keycode[0]);
	input->keycodemax = ARRAY_SIZE(drv_data->keycode);
	input->keycode= drv_data->keymap_norm;
	input->keycodesize = sizeof(drv_data->keymap_norm[0]);
	input->keycodemax = ARRAY_SIZE(drv_data->keymap_norm);

	for (i = 0; i < NUM_KEYCODES; i++)
		__set_bit(drv_data->keycode[i], input->keybit);
		__set_bit(drv_data->keymap_norm[i], input->keybit);

	__clear_bit(KEY_RESERVED, input->keybit);



@@ 397,27 287,144 @@ static int ppbbq10_probe(struct i2c_client *client, const struct i2c_device_id *
	return 0;
}

static int __init ppbbq10_init(void)
static void
ppbbq10_read_fifo(struct ppbbq10_data *drv_data)
{
	adapter = i2c_get_adapter(3);
	printk(KERN_INFO "Initialize ppbq10 kernel module.\n");
	if (!adapter) {
		printk(KERN_INFO "Error acquiring i2c adapter 3.\n");
		return -1;
	struct input_dev *input = drv_data->input;
	struct i2c_client *client = drv_data->client;
	unsigned int keycode;
	u8 data[2];
	u8 count;
	int error;

	error = ppbbq10_read_reg(drv_data, REG_KEY, data, sizeof(u8));
	if (error < 0) {
		dev_err(&client->dev, "%s failed to read REG_KEY, error: %d\n",
			__func__, error);
		return;
	}
	client = i2c_new_client_device(adapter, ppbbq10_i2c_board_info);
	//client->irq = gpio_to_irq(2);

	pr_debug("%s status: 0x%02X\n", __func__, data[0]);

	count = (data[0] & KEY_COUNT_MASK);

	while (count > 0) {
		error = ppbbq10_read_reg(drv_data, REG_FIF, data, sizeof(u8) * 2);
		if (error < 0) {
			dev_err(&client->dev, "%s failed to read REG_FIF, error: %d\n",
				__func__, error);
			return;
		}

		pr_debug("%s key %d/%c, state: %d\n",
			__func__, data[1], data[1], data[0]);

		count -= 1;

		if (data[0] == STATE_PRESS || data[0] == STATE_RELEASE) {
			input_event(input, EV_MSC, MSC_SCAN, data[1]);

			keycode = drv_data->keymap_norm[data[1]];
			if (keycode == KEY_UNKNOWN) {
				pr_warn("%s code 0x%02X UNKNOWN\n", __func__, data[1]);
			} else {
				input_report_key(input, keycode, data[0] == STATE_PRESS);
			}
		}
	}

	input_sync(input);
}

static int
ppbbq10_read_reg(struct ppbbq10_data *drv_data, u8 reg, u8 *buf, u8 len)
{
	struct i2c_client *client = drv_data->client;
	int error;

	struct i2c_msg msgs[] = {
		{ .addr = client->addr, .flags = client->flags, .len = sizeof(u8), .buf = &reg, },
		{ .addr = client->addr, .flags = client->flags | I2C_M_RD, .len = len, .buf = buf }
	};

	error = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (error != ARRAY_SIZE(msgs)) {
		dev_err(&client->dev, "%s failed, reg: %d, error: %d\n",
			__func__, reg, error);

		return error;
	}

	return 0;
}

static void
ppbbq10_update_locks(struct ppbbq10_data *drv_data)
{
	struct input_dev *input = drv_data->input;
	struct i2c_client *client = drv_data->client;
	u8 data;
	int error;

	error = ppbbq10_read_reg(drv_data, REG_KEY, &data, sizeof(u8));
	if (error < 0) {
		dev_err(&client->dev, "%s failed to read REG_KEY, error: %d\n",
			__func__, error);
		return;
	}

	pr_warn("%s status: 0x%02X\n", __func__, data);

	//input_report_key(input, KEY_NUMLOCK, data & _KEY_NUMLOCK);
	//input_report_key(input, KEY_CAPSLOCK, data & _KEY_CAPSLOCK);

	input_sync(input);
}

static void __exit ppbbq10_exit(void)
static int
ppbbq10_write_reg(struct ppbbq10_data *drv_data, u8 reg)
{
	printk(KERN_INFO "Unregister ppbbq10 kernel module.\n");
	i2c_unregister_device(client);
	/*i2c_del_driver(&ppbbq10_driver);*/
	struct i2c_client *client = drv_data->client;
	int error;

	struct i2c_msg msgs[] = {
		{ .addr = client->addr, .flags = I2C_M_STOP, .len = sizeof(u8), .buf = &reg, },
	};

	error = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (error != ARRAY_SIZE(msgs)) {
		dev_err(&client->dev, "%s failed, reg: %d, error: %d\n",
		__func__, reg, error);

		return error;
	}

	return 0;
}

static int
ppbbq10_write_data(struct ppbbq10_data *drv_data, u8 reg, const u8 *buf, u8 len)
{
	struct i2c_client *client = drv_data->client;
	int error;

	reg |= 0x80;

	struct i2c_msg msgs[] = {
		{ .addr = client->addr, .flags = 0, .len = sizeof(u8), .buf = &reg, },
		{ .addr = client->addr, .flags = 0, .len = len, .buf = (u8*)buf, },
	};

	error = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (error != ARRAY_SIZE(msgs)) {
		dev_err(&client->dev, "%s failed, reg: %d, error: %d\n",
			__func__, reg, error);

		return error;
	}

	return 0;
}

module_init(ppbbq10_init);
module_exit(ppbbq10_exit);