Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
e97f4677
K
Kernel
项目概览
openeuler
/
Kernel
大约 1 年 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e97f4677
编写于
12月 04, 2009
作者:
M
Mauro Carvalho Chehab
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
V4L/DVB (13542): ir-keytable: Allow dynamic table change
Signed-off-by:
N
Mauro Carvalho Chehab
<
mchehab@redhat.com
>
上级
92fda216
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
197 addition
and
10 deletion
+197
-10
drivers/media/common/ir-keytable.c
drivers/media/common/ir-keytable.c
+197
-10
未找到文件。
drivers/media/common/ir-keytable.c
浏览文件 @
e97f4677
...
...
@@ -8,6 +8,7 @@
#include <media/ir-common.h>
#define IR_TAB_MIN_SIZE 32
#define IR_TAB_MAX_SIZE 1024
/**
* ir_seek_table() - returns the element order on the table
...
...
@@ -121,7 +122,154 @@ static int ir_getkeycode(struct input_dev *dev,
return
0
;
}
return
-
EINVAL
;
/*
* Scancode not found and table can't be expanded
*/
if
(
elem
<
0
&&
rc_tab
->
size
==
IR_TAB_MAX_SIZE
)
return
-
EINVAL
;
/*
* If is there extra space, returns KEY_RESERVED,
* otherwise, input core won't let ir_setkeycode to work
*/
*
keycode
=
KEY_RESERVED
;
return
0
;
}
/**
* ir_is_resize_needed() - Check if the table needs rezise
* @table: keycode table that may need to resize
* @n_elems: minimum number of entries to store keycodes
*
* Considering that kmalloc uses power of two storage areas, this
* routine detects if the real alloced size will change. If not, it
* just returns without doing nothing. Otherwise, it will extend or
* reduce the table size to meet the new needs.
*
* It returns 0 if no resize is needed, 1 otherwise.
*/
static
int
ir_is_resize_needed
(
struct
ir_scancode_table
*
table
,
int
n_elems
)
{
int
cur_size
=
ir_roundup_tablesize
(
table
->
size
);
int
new_size
=
ir_roundup_tablesize
(
n_elems
);
if
(
cur_size
==
new_size
)
return
0
;
/* Resize is needed */
return
1
;
}
/**
* ir_delete_key() - remove a keycode from the table
* @rc_tab: keycode table
* @elem: element to be removed
*
*/
static
void
ir_delete_key
(
struct
ir_scancode_table
*
rc_tab
,
int
elem
)
{
unsigned
long
flags
=
0
;
int
newsize
=
rc_tab
->
size
-
1
;
int
resize
=
ir_is_resize_needed
(
rc_tab
,
newsize
);
struct
ir_scancode
*
oldkeymap
=
rc_tab
->
scan
;
struct
ir_scancode
*
newkeymap
;
if
(
resize
)
{
newkeymap
=
kzalloc
(
ir_roundup_tablesize
(
newsize
)
*
sizeof
(
*
newkeymap
),
GFP_ATOMIC
);
/* There's no memory for resize. Keep the old table */
if
(
!
newkeymap
)
resize
=
0
;
}
if
(
!
resize
)
{
newkeymap
=
oldkeymap
;
/* We'll modify the live table. Lock it */
spin_lock_irqsave
(
&
rc_tab
->
lock
,
flags
);
}
/*
* Copy the elements before the one that will be deleted
* if (!resize), both oldkeymap and newkeymap points
* to the same place, so, there's no need to copy
*/
if
(
resize
&&
elem
>
0
)
memcpy
(
newkeymap
,
oldkeymap
,
elem
*
sizeof
(
*
newkeymap
));
/*
* Copy the other elements overwriting the element to be removed
* This operation applies to both resize and non-resize case
*/
if
(
elem
<
newsize
)
memcpy
(
&
newkeymap
[
elem
],
&
oldkeymap
[
elem
+
1
],
(
newsize
-
elem
)
*
sizeof
(
*
newkeymap
));
if
(
resize
)
{
/*
* As the copy happened to a temporary table, only here
* it needs to lock while replacing the table pointers
* to use the new table
*/
spin_lock_irqsave
(
&
rc_tab
->
lock
,
flags
);
rc_tab
->
size
=
newsize
;
rc_tab
->
scan
=
newkeymap
;
spin_unlock_irqrestore
(
&
rc_tab
->
lock
,
flags
);
/* Frees the old keytable */
kfree
(
oldkeymap
);
}
else
{
rc_tab
->
size
=
newsize
;
spin_unlock_irqrestore
(
&
rc_tab
->
lock
,
flags
);
}
}
/**
* ir_insert_key() - insert a keycode at the table
* @rc_tab: keycode table
* @scancode: the desired scancode
* @keycode: the keycode to be retorned.
*
*/
static
int
ir_insert_key
(
struct
ir_scancode_table
*
rc_tab
,
int
scancode
,
int
keycode
)
{
unsigned
long
flags
;
int
elem
=
rc_tab
->
size
;
int
newsize
=
rc_tab
->
size
+
1
;
int
resize
=
ir_is_resize_needed
(
rc_tab
,
newsize
);
struct
ir_scancode
*
oldkeymap
=
rc_tab
->
scan
;
struct
ir_scancode
*
newkeymap
;
if
(
resize
)
{
newkeymap
=
kzalloc
(
ir_roundup_tablesize
(
newsize
)
*
sizeof
(
*
newkeymap
),
GFP_ATOMIC
);
if
(
!
newkeymap
)
return
-
ENOMEM
;
memcpy
(
newkeymap
,
oldkeymap
,
rc_tab
->
size
*
sizeof
(
*
newkeymap
));
}
else
newkeymap
=
oldkeymap
;
/* Stores the new code at the table */
IR_dprintk
(
1
,
"#%d: New scan 0x%04x with key 0x%04x
\n
"
,
rc_tab
->
size
,
scancode
,
keycode
);
spin_lock_irqsave
(
&
rc_tab
->
lock
,
flags
);
rc_tab
->
size
=
newsize
;
if
(
resize
)
{
rc_tab
->
scan
=
newkeymap
;
kfree
(
oldkeymap
);
}
newkeymap
[
elem
].
scancode
=
scancode
;
newkeymap
[
elem
].
keycode
=
keycode
;
spin_unlock_irqrestore
(
&
rc_tab
->
lock
,
flags
);
return
0
;
}
/**
...
...
@@ -142,20 +290,59 @@ static int ir_setkeycode(struct input_dev *dev,
struct
ir_scancode
*
keymap
=
rc_tab
->
scan
;
unsigned
long
flags
;
/* Search if it is replacing an existing keycode */
/*
* Handle keycode table deletions
*
* If userspace is adding a KEY_UNKNOWN or KEY_RESERVED,
* deal as a trial to remove an existing scancode attribution
* if table become too big, reduce it to save space
*/
if
(
keycode
==
KEY_UNKNOWN
||
keycode
==
KEY_RESERVED
)
{
rc
=
ir_seek_table
(
rc_tab
,
scancode
);
if
(
rc
<
0
)
return
0
;
IR_dprintk
(
1
,
"#%d: Deleting scan 0x%04x
\n
"
,
rc
,
scancode
);
clear_bit
(
keymap
[
rc
].
keycode
,
dev
->
keybit
);
ir_delete_key
(
rc_tab
,
rc
);
return
0
;
}
/*
* Handle keycode replacements
*
* If the scancode exists, just replace by the new value
*/
rc
=
ir_seek_table
(
rc_tab
,
scancode
);
if
(
rc
<
0
)
return
rc
;
if
(
rc
>=
0
)
{
IR_dprintk
(
1
,
"#%d: Replacing scan 0x%04x with key 0x%04x
\n
"
,
rc
,
scancode
,
keycode
);
IR_dprintk
(
1
,
"#%d: Replacing scan 0x%04x with key 0x%04x
\n
"
,
rc
,
scancode
,
keycode
);
clear_bit
(
keymap
[
rc
].
keycode
,
dev
->
keybit
);
clear_bit
(
keymap
[
rc
].
keycode
,
dev
->
keybit
);
spin_lock_irqsave
(
&
rc_tab
->
lock
,
flags
);
keymap
[
rc
].
keycode
=
keycode
;
spin_unlock_irqrestore
(
&
rc_tab
->
lock
,
flags
);
spin_lock_irqsave
(
&
rc_tab
->
lock
,
flags
);
keymap
[
rc
].
keycode
=
keycode
;
spin_unlock_irqrestore
(
&
rc_tab
->
lock
,
flags
);
set_bit
(
keycode
,
dev
->
keybit
);
return
0
;
}
/*
* Handle new scancode inserts
*
* reallocate table if needed and insert a new keycode
*/
/* Avoid growing the table indefinitely */
if
(
rc_tab
->
size
+
1
>
IR_TAB_MAX_SIZE
)
return
-
EINVAL
;
rc
=
ir_insert_key
(
rc_tab
,
scancode
,
keycode
);
if
(
rc
<
0
)
return
rc
;
set_bit
(
keycode
,
dev
->
keybit
);
return
0
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录