xref: /openbmc/linux/sound/pci/ctxfi/ctimap.c (revision 022dacdd)
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(&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(&entry->list, pos->prev, pos);
47 	} else {
48 		pre = head->prev;
49 		pos = head->next;
50 		list_add_tail(&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->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->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(pos);
104 		entry = list_entry(pos, struct imapper, list);
105 		kfree(entry);
106 	}
107 }
108 
109