1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. |
4 | * |
5 | * @File ctimap.c |
6 | * |
7 | * @Brief |
8 | * This file contains the implementation of generic input mapper operations |
9 | * for input mapper management. |
10 | * |
11 | * @Author Liu Chun |
12 | * @Date May 23 2008 |
13 | */ |
14 | |
15 | #include "ctimap.h" |
16 | #include <linux/slab.h> |
17 | |
18 | int input_mapper_add(struct list_head *mappers, struct imapper *entry, |
19 | int (*map_op)(void *, struct imapper *), void *data) |
20 | { |
21 | struct list_head *pos, *pre, *head; |
22 | struct imapper *pre_ent, *pos_ent; |
23 | |
24 | head = mappers; |
25 | |
26 | if (list_empty(head)) { |
27 | entry->next = entry->addr; |
28 | map_op(data, entry); |
29 | list_add(new: &entry->list, head); |
30 | return 0; |
31 | } |
32 | |
33 | list_for_each(pos, head) { |
34 | pos_ent = list_entry(pos, struct imapper, list); |
35 | if (pos_ent->slot > entry->slot) { |
36 | /* found a position in list */ |
37 | break; |
38 | } |
39 | } |
40 | |
41 | if (pos != head) { |
42 | pre = pos->prev; |
43 | if (pre == head) |
44 | pre = head->prev; |
45 | |
46 | __list_add(new: &entry->list, prev: pos->prev, next: pos); |
47 | } else { |
48 | pre = head->prev; |
49 | pos = head->next; |
50 | list_add_tail(new: &entry->list, head); |
51 | } |
52 | |
53 | pre_ent = list_entry(pre, struct imapper, list); |
54 | pos_ent = list_entry(pos, struct imapper, list); |
55 | |
56 | entry->next = pos_ent->addr; |
57 | map_op(data, entry); |
58 | pre_ent->next = entry->addr; |
59 | map_op(data, pre_ent); |
60 | |
61 | return 0; |
62 | } |
63 | |
64 | int input_mapper_delete(struct list_head *mappers, struct imapper *entry, |
65 | int (*map_op)(void *, struct imapper *), void *data) |
66 | { |
67 | struct list_head *next, *pre, *head; |
68 | struct imapper *pre_ent, *next_ent; |
69 | |
70 | head = mappers; |
71 | |
72 | if (list_empty(head)) |
73 | return 0; |
74 | |
75 | pre = (entry->list.prev == head) ? head->prev : entry->list.prev; |
76 | next = (entry->list.next == head) ? head->next : entry->list.next; |
77 | |
78 | if (pre == &entry->list) { |
79 | /* entry is the only one node in mappers list */ |
80 | entry->next = entry->addr = entry->user = entry->slot = 0; |
81 | map_op(data, entry); |
82 | list_del(entry: &entry->list); |
83 | return 0; |
84 | } |
85 | |
86 | pre_ent = list_entry(pre, struct imapper, list); |
87 | next_ent = list_entry(next, struct imapper, list); |
88 | |
89 | pre_ent->next = next_ent->addr; |
90 | map_op(data, pre_ent); |
91 | list_del(entry: &entry->list); |
92 | |
93 | return 0; |
94 | } |
95 | |
96 | void free_input_mapper_list(struct list_head *head) |
97 | { |
98 | struct imapper *entry; |
99 | struct list_head *pos; |
100 | |
101 | while (!list_empty(head)) { |
102 | pos = head->next; |
103 | list_del(entry: pos); |
104 | entry = list_entry(pos, struct imapper, list); |
105 | kfree(objp: entry); |
106 | } |
107 | } |
108 | |
109 | |