18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * @File ctimap.c 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * @Brief 88c2ecf20Sopenharmony_ci * This file contains the implementation of generic input mapper operations 98c2ecf20Sopenharmony_ci * for input mapper management. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * @Author Liu Chun 128c2ecf20Sopenharmony_ci * @Date May 23 2008 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "ctimap.h" 168c2ecf20Sopenharmony_ci#include <linux/slab.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ciint input_mapper_add(struct list_head *mappers, struct imapper *entry, 198c2ecf20Sopenharmony_ci int (*map_op)(void *, struct imapper *), void *data) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci struct list_head *pos, *pre, *head; 228c2ecf20Sopenharmony_ci struct imapper *pre_ent, *pos_ent; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci head = mappers; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci if (list_empty(head)) { 278c2ecf20Sopenharmony_ci entry->next = entry->addr; 288c2ecf20Sopenharmony_ci map_op(data, entry); 298c2ecf20Sopenharmony_ci list_add(&entry->list, head); 308c2ecf20Sopenharmony_ci return 0; 318c2ecf20Sopenharmony_ci } 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci list_for_each(pos, head) { 348c2ecf20Sopenharmony_ci pos_ent = list_entry(pos, struct imapper, list); 358c2ecf20Sopenharmony_ci if (pos_ent->slot > entry->slot) { 368c2ecf20Sopenharmony_ci /* found a position in list */ 378c2ecf20Sopenharmony_ci break; 388c2ecf20Sopenharmony_ci } 398c2ecf20Sopenharmony_ci } 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (pos != head) { 428c2ecf20Sopenharmony_ci pre = pos->prev; 438c2ecf20Sopenharmony_ci if (pre == head) 448c2ecf20Sopenharmony_ci pre = head->prev; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci __list_add(&entry->list, pos->prev, pos); 478c2ecf20Sopenharmony_ci } else { 488c2ecf20Sopenharmony_ci pre = head->prev; 498c2ecf20Sopenharmony_ci pos = head->next; 508c2ecf20Sopenharmony_ci list_add_tail(&entry->list, head); 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci pre_ent = list_entry(pre, struct imapper, list); 548c2ecf20Sopenharmony_ci pos_ent = list_entry(pos, struct imapper, list); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci entry->next = pos_ent->addr; 578c2ecf20Sopenharmony_ci map_op(data, entry); 588c2ecf20Sopenharmony_ci pre_ent->next = entry->addr; 598c2ecf20Sopenharmony_ci map_op(data, pre_ent); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciint input_mapper_delete(struct list_head *mappers, struct imapper *entry, 658c2ecf20Sopenharmony_ci int (*map_op)(void *, struct imapper *), void *data) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci struct list_head *next, *pre, *head; 688c2ecf20Sopenharmony_ci struct imapper *pre_ent, *next_ent; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci head = mappers; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (list_empty(head)) 738c2ecf20Sopenharmony_ci return 0; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci pre = (entry->list.prev == head) ? head->prev : entry->list.prev; 768c2ecf20Sopenharmony_ci next = (entry->list.next == head) ? head->next : entry->list.next; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (pre == &entry->list) { 798c2ecf20Sopenharmony_ci /* entry is the only one node in mappers list */ 808c2ecf20Sopenharmony_ci entry->next = entry->addr = entry->user = entry->slot = 0; 818c2ecf20Sopenharmony_ci map_op(data, entry); 828c2ecf20Sopenharmony_ci list_del(&entry->list); 838c2ecf20Sopenharmony_ci return 0; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci pre_ent = list_entry(pre, struct imapper, list); 878c2ecf20Sopenharmony_ci next_ent = list_entry(next, struct imapper, list); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci pre_ent->next = next_ent->addr; 908c2ecf20Sopenharmony_ci map_op(data, pre_ent); 918c2ecf20Sopenharmony_ci list_del(&entry->list); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return 0; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_civoid free_input_mapper_list(struct list_head *head) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci struct imapper *entry; 998c2ecf20Sopenharmony_ci struct list_head *pos; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci while (!list_empty(head)) { 1028c2ecf20Sopenharmony_ci pos = head->next; 1038c2ecf20Sopenharmony_ci list_del(pos); 1048c2ecf20Sopenharmony_ci entry = list_entry(pos, struct imapper, list); 1058c2ecf20Sopenharmony_ci kfree(entry); 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 109