BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
arduino_i2c_keyboard
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
arduino_i2c_keyboard
Commits
93b0aedf
Commit
93b0aedf
authored
Jul 07, 2018
by
Forest Godfrey
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working evdev and more complete access to the device. Should work with real keypad.
Also fixes a bug causing the device driver to be unable to be unloaded.
parent
39e41950
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
89 additions
and
15 deletions
+89
-15
ai2c_platform_data.h
linux_driver/ai2c_platform_data.h
+1
-0
arduino_i2c.c
linux_driver/arduino_i2c.c
+88
-15
No files found.
linux_driver/ai2c_platform_data.h
View file @
93b0aedf
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
typedef
struct
arduino_i2c_keyboard_platform_data
{
typedef
struct
arduino_i2c_keyboard_platform_data
{
int
gpio_intr_pin
;
int
gpio_intr_pin
;
int
*
keymap
;
int
*
keymap
;
int
numkeys
;
}
arduino_i2c_keyboard_platform_data_t
;
}
arduino_i2c_keyboard_platform_data_t
;
#endif
/* _AI2C_PLATFORM_DATA_H */
#endif
/* _AI2C_PLATFORM_DATA_H */
linux_driver/arduino_i2c.c
View file @
93b0aedf
...
@@ -44,10 +44,29 @@
...
@@ -44,10 +44,29 @@
#define IRQ_GPIO_PIN 9
#define IRQ_GPIO_PIN 9
#define GPIO_IRQ_NAME "ai2c_keyboard_irq"
#define GPIO_IRQ_NAME "ai2c_keyboard_irq"
const
int
default_keymap
[]
=
{
static
int
default_keymap
[]
=
{
0
,
KEY_UP
,
KEY_DOWN
,
KEY_LEFT
,
KEY_RIGHT
,
KEY_A
,
KEY_B
,
BTN_START
,
KEY_SELECT
,
KEY_DISPLAYTOGGLE
,
KEY_1
,
KEY_2
,
KEY_3
,
KEY_4
,
KEY_5
,
KEY_6
,
KEY_7
,
KEY_8
,
KEY_9
};
};
static
int
default_numkeys
=
sizeof
(
default_keymap
)
/
sizeof
(
int
);
static
LIST_HEAD
(
driver_list
);
static
LIST_HEAD
(
driver_list
);
static
DEFINE_MUTEX
(
driver_list_lock
);
static
DEFINE_MUTEX
(
driver_list_lock
);
...
@@ -61,6 +80,7 @@ device_write_register(struct i2c_client *client, uint8_t raddr, uint8_t value) {
...
@@ -61,6 +80,7 @@ device_write_register(struct i2c_client *client, uint8_t raddr, uint8_t value) {
}
}
#if 0
#if 0
/* ifdef'd out to pacify gcc until we need there */
static uint8_t
static uint8_t
device_read_byte(struct i2c_client *client) {
device_read_byte(struct i2c_client *client) {
uint8_t tmp;
uint8_t tmp;
...
@@ -89,16 +109,45 @@ device_read_register(struct i2c_client *client, void *buffer, uint8_t raddr, uin
...
@@ -89,16 +109,45 @@ device_read_register(struct i2c_client *client, void *buffer, uint8_t raddr, uin
static
void
static
void
ai2c_intr
(
struct
work_struct
*
work
)
{
ai2c_intr
(
struct
work_struct
*
work
)
{
int
i
;
uint8_t
key_status
[
6
];
uint16_t
cur
,
down
,
up
;
arduino_i2c_driver_data_t
*
drv_info
=
container_of
(
arduino_i2c_driver_data_t
*
drv_info
=
container_of
(
work
,
arduino_i2c_driver_data_t
,
intr_upper_work
);
work
,
arduino_i2c_driver_data_t
,
intr_upper_work
);
BUG_ON
(
!
drv_info
->
client
);
BUG_ON
(
!
drv_info
->
client
);
dev_info
(
&
drv_info
->
client
->
dev
,
"ai2c_intr: entered
\n
"
);
dev_info
(
&
drv_info
->
client
->
dev
,
"ai2c_intr: entered
\n
"
);
i2c_smbus_write_byte_data
(
drv_info
->
client
,
50
,
48
);
memset
(
key_status
,
0
,
sizeof
(
key_status
));
input_report_key
(
drv_info
->
indev
,
BTN_0
,
1
);
for
(
i
=
0
;
i
<
6
;
i
++
)
{
input_sync
(
drv_info
->
indev
);
device_read_register
(
drv_info
->
client
,
&
(
key_status
[
i
]),
AI2C_REGISTER_KEY_STATUS_LOW
+
i
,
1
);
input_report_key
(
drv_info
->
indev
,
BTN_0
,
0
);
}
cur
=
(
uint16_t
)
key_status
[
0
]
|
((
uint16_t
)
key_status
[
1
]
<<
8
);
down
=
(
uint16_t
)
key_status
[
2
]
|
((
uint16_t
)
key_status
[
3
]
<<
8
);
up
=
(
uint16_t
)
key_status
[
4
]
|
((
uint16_t
)
key_status
[
5
]
<<
8
);
for
(
i
=
0
;
i
<
16
;
i
++
)
{
if
((
down
&
(
1
<<
i
))
&&
(
up
&
(
1
<<
i
)))
{
/* Key went down and up since last check - see what it is currently to decide order */
if
(
cur
&
(
1
<<
i
))
{
/* The button is currently up so it must have gone down first, then up */
input_report_key
(
drv_info
->
indev
,
default_keymap
[
i
],
0
);
input_sync
(
drv_info
->
indev
);
input_report_key
(
drv_info
->
indev
,
default_keymap
[
i
],
1
);
}
else
{
/* Other way agound - up first, then down */
input_report_key
(
drv_info
->
indev
,
default_keymap
[
i
],
1
);
input_sync
(
drv_info
->
indev
);
input_report_key
(
drv_info
->
indev
,
default_keymap
[
i
],
0
);
}
}
else
if
(
down
&
(
1
<<
i
))
{
/* New key down */
input_report_key
(
drv_info
->
indev
,
default_keymap
[
i
],
0
);
}
else
if
(
up
&
(
1
<<
i
))
{
/* New key up */
input_report_key
(
drv_info
->
indev
,
default_keymap
[
i
],
1
);
}
}
/* All events before this happened at the "same" time */
input_sync
(
drv_info
->
indev
);
input_sync
(
drv_info
->
indev
);
return
;
return
;
...
@@ -118,7 +167,7 @@ ai2c_intr_lower(int irq, void *data) {
...
@@ -118,7 +167,7 @@ ai2c_intr_lower(int irq, void *data) {
static
int
static
int
ai2c_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
ai2c_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
int
i
;
int
i
,
keymax
;
int
ret
=
0
;
int
ret
=
0
;
int
flags
=
0
;
int
flags
=
0
;
uint16_t
dev_id
;
uint16_t
dev_id
;
...
@@ -148,6 +197,9 @@ ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
...
@@ -148,6 +197,9 @@ ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
dev_info
(
&
client
->
dev
,
"Device ID: 0x%04x
\n
Device Revision: 0x%02x
\n
Device Firmware Build:
\"
%s
\"\n
"
,
dev_info
(
&
client
->
dev
,
"Device ID: 0x%04x
\n
Device Revision: 0x%02x
\n
Device Firmware Build:
\"
%s
\"\n
"
,
dev_id
,
dev_rev
,
dev_build_str
);
dev_id
,
dev_rev
,
dev_build_str
);
/*
* Allocate/initialize driver data
*/
drv_info
=
(
arduino_i2c_driver_data_t
*
)
kmalloc
(
sizeof
(
arduino_i2c_driver_data_t
),
GFP_KERNEL
);
drv_info
=
(
arduino_i2c_driver_data_t
*
)
kmalloc
(
sizeof
(
arduino_i2c_driver_data_t
),
GFP_KERNEL
);
if
(
!
drv_info
)
{
if
(
!
drv_info
)
{
dev_err
(
&
client
->
dev
,
"Unable to allocate driver memory"
);
dev_err
(
&
client
->
dev
,
"Unable to allocate driver memory"
);
...
@@ -156,6 +208,9 @@ ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
...
@@ -156,6 +208,9 @@ ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
}
}
memset
(
drv_info
,
0
,
sizeof
(
arduino_i2c_driver_data_t
));
memset
(
drv_info
,
0
,
sizeof
(
arduino_i2c_driver_data_t
));
/*
* Get GPIO pin for interrupts
*/
ret
=
gpio_request
(
pdata
->
gpio_intr_pin
,
GPIO_IRQ_NAME
);
ret
=
gpio_request
(
pdata
->
gpio_intr_pin
,
GPIO_IRQ_NAME
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
dev_err
(
&
client
->
dev
,
"ai2c: IRQ pin reservation of %d failed: error %d"
,
pdata
->
gpio_intr_pin
,
ret
);
dev_err
(
&
client
->
dev
,
"ai2c: IRQ pin reservation of %d failed: error %d"
,
pdata
->
gpio_intr_pin
,
ret
);
...
@@ -175,6 +230,9 @@ ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
...
@@ -175,6 +230,9 @@ ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
dev_dbg
(
&
client
->
dev
,
"ai2c: Reserved pin [%d]: irq = %d
\n
"
,
pdata
->
gpio_intr_pin
,
drv_info
->
irq_num
);
dev_dbg
(
&
client
->
dev
,
"ai2c: Reserved pin [%d]: irq = %d
\n
"
,
pdata
->
gpio_intr_pin
,
drv_info
->
irq_num
);
/*
* Register for key press IRQ
*/
flags
|=
IRQF_TRIGGER_FALLING
;
flags
|=
IRQF_TRIGGER_FALLING
;
ret
=
request_irq
(
drv_info
->
irq_num
,
ai2c_intr_lower
,
flags
,
"ai2c_keyboard"
,
drv_info
);
ret
=
request_irq
(
drv_info
->
irq_num
,
ai2c_intr_lower
,
flags
,
"ai2c_keyboard"
,
drv_info
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
...
@@ -189,17 +247,32 @@ ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
...
@@ -189,17 +247,32 @@ ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
goto
out_cleanirq
;
goto
out_cleanirq
;
}
}
/*
* Set up input device
*/
if
(
pdata
->
keymap
)
{
drv_info
->
keymap
=
pdata
->
keymap
;
drv_info
->
numkeys
=
pdata
->
numkeys
;
}
else
{
drv_info
->
keymap
=
default_keymap
;
drv_info
->
numkeys
=
default_numkeys
;
}
drv_info
->
indev
->
name
=
"arduino_i2c"
;
drv_info
->
indev
->
name
=
"arduino_i2c"
;
drv_info
->
indev
->
phys
=
"arduino_i2c/input0"
;
drv_info
->
indev
->
phys
=
"arduino_i2c/input0"
;
drv_info
->
indev
->
dev
.
parent
=
&
client
->
dev
;
drv_info
->
indev
->
dev
.
parent
=
&
client
->
dev
;
drv_info
->
indev
->
id
.
bustype
=
BUS_I2C
;
drv_info
->
indev
->
id
.
bustype
=
BUS_I2C
;
drv_info
->
indev
->
id
.
vendor
=
0x4242
;
drv_info
->
indev
->
id
.
vendor
=
AI2C_ID
;
drv_info
->
indev
->
id
.
product
=
0x4242
;
drv_info
->
indev
->
id
.
product
=
AI2C_ID
;
drv_info
->
indev
->
id
.
version
=
0x0001
;
drv_info
->
indev
->
id
.
version
=
0x0001
;
drv_info
->
indev
->
keycodesize
=
sizeof
(
unsigned
short
);
drv_info
->
indev
->
keycodesize
=
sizeof
(
unsigned
short
);
drv_info
->
indev
->
keycodemax
=
BTN_0
+
1
;
drv_info
->
indev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
);
drv_info
->
indev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
);
drv_info
->
indev
->
keybit
[
BIT_WORD
(
BTN_0
)]
=
BIT_MASK
(
BTN_0
);
keymax
=
-
1
;
for
(
i
=
0
;
i
<
drv_info
->
numkeys
;
i
++
)
{
drv_info
->
indev
->
keybit
[
BIT_WORD
(
drv_info
->
keymap
[
i
])]
|=
BIT_MASK
(
drv_info
->
keymap
[
i
]);
keymax
=
(
drv_info
->
keymap
[
i
]
>
keymax
)
?
drv_info
->
keymap
[
i
]
:
keymax
;
}
drv_info
->
indev
->
keycodemax
=
keymax
+
1
;
ret
=
input_register_device
(
drv_info
->
indev
);
ret
=
input_register_device
(
drv_info
->
indev
);
if
(
ret
)
{
if
(
ret
)
{
dev_err
(
&
client
->
dev
,
"ai2c: unable to register input device: %d"
,
ret
);
dev_err
(
&
client
->
dev
,
"ai2c: unable to register input device: %d"
,
ret
);
...
@@ -225,7 +298,7 @@ out_cleanindev:
...
@@ -225,7 +298,7 @@ out_cleanindev:
out_cleanirq:
out_cleanirq:
free_irq
(
drv_info
->
irq_num
,
drv_info
);
free_irq
(
drv_info
->
irq_num
,
drv_info
);
out_cleanup:
out_cleanup:
gpio_free
(
drv_info
->
irq_
num
);
gpio_free
(
drv_info
->
irq_
pin
);
out_dealloc:
out_dealloc:
kfree
(
drv_info
);
kfree
(
drv_info
);
out:
out:
...
@@ -241,7 +314,7 @@ ai2c_remove(struct i2c_client *client) {
...
@@ -241,7 +314,7 @@ ai2c_remove(struct i2c_client *client) {
flush_work
(
&
drv_info
->
intr_upper_work
);
flush_work
(
&
drv_info
->
intr_upper_work
);
gpio_free
(
drv_info
->
irq_
num
);
gpio_free
(
drv_info
->
irq_
pin
);
dev_set_drvdata
(
&
drv_info
->
client
->
dev
,
NULL
);
dev_set_drvdata
(
&
drv_info
->
client
->
dev
,
NULL
);
...
@@ -273,7 +346,7 @@ static struct i2c_driver ai2c_driver = {
...
@@ -273,7 +346,7 @@ static struct i2c_driver ai2c_driver = {
.
id_table
=
ai2c_id
,
.
id_table
=
ai2c_id
,
};
};
int
static
int
ai2c_init
(
void
)
{
ai2c_init
(
void
)
{
int
ret
;
int
ret
;
printk
(
KERN_INFO
"Arduino I2C Keyboard Starting
\n
"
);
printk
(
KERN_INFO
"Arduino I2C Keyboard Starting
\n
"
);
...
@@ -284,7 +357,7 @@ ai2c_init(void) {
...
@@ -284,7 +357,7 @@ ai2c_init(void) {
return
ret
;
return
ret
;
}
}
void
static
void
ai2c_shutdown
(
void
)
{
ai2c_shutdown
(
void
)
{
printk
(
KERN_INFO
"Arduino I2C Keyboard Shutting Down
\n
"
);
printk
(
KERN_INFO
"Arduino I2C Keyboard Shutting Down
\n
"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment