mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
An common module used for all of module communication.
The module encapsule a group of notification, used for decoupling between modules, for example, the touchscreen driver are coupling fingerprint and display driver in the bring-up phase, the dependencies between modules need to fixed to avoid proceeding blocked, This module is middle layer, it change a direct dependece into an indirect dependence. Change-Id: I905ab2e3e4de32be9a2d2a9346d3153bb3690241 Reviewed-on: https://gerrit.mot.com/1756389 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jianqi Yang <yangj@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
f155ee5a66
commit
a22d4e065e
5 changed files with 289 additions and 0 deletions
12
drivers/mmi_relay/Android.mk
Normal file
12
drivers/mmi_relay/Android.mk
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
DLKM_DIR := motorola/kernel/modules
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := mmi_relay.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
ifeq ($(DLKM_INSTALL_TO_VENDOR_OUT),true)
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/
|
||||
else
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
endif
|
||||
include $(DLKM_DIR)/AndroidKernelModule.mk
|
||||
5
drivers/mmi_relay/Kbuild
Normal file
5
drivers/mmi_relay/Kbuild
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# add -Wall to try to catch everything we can.
|
||||
EXTRA_CFLAGS += -Wall
|
||||
EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include
|
||||
|
||||
obj-m += mmi_relay.o
|
||||
10
drivers/mmi_relay/Makefile
Normal file
10
drivers/mmi_relay/Makefile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
|
||||
234
drivers/mmi_relay/mmi_relay.c
Normal file
234
drivers/mmi_relay/mmi_relay.c
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mmi_relay.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
typedef struct _relay_node {
|
||||
struct list_head list;
|
||||
union {
|
||||
struct atomic_notifier_head atomic_head;
|
||||
struct blocking_notifier_head blocking_head;
|
||||
};
|
||||
int id;
|
||||
notifier_t type;
|
||||
notifier_d dev;
|
||||
}relay_node;
|
||||
|
||||
struct mmi_relay_dev {
|
||||
struct platform_device *pdev;
|
||||
struct mutex lock;
|
||||
relay_node nodes[NUM_TYPES][NUM_DEVS];
|
||||
unsigned notifier_nums;
|
||||
};
|
||||
static struct mmi_relay_dev* relay_dev;
|
||||
|
||||
/*
|
||||
* Informs the registered notifiers about an event
|
||||
* @type: notification type: atomic blocking
|
||||
* @dev: notification sender
|
||||
* @val: value passed to notifier function
|
||||
*/
|
||||
|
||||
int relay_notifier_fire(notifier_t type, notifier_d dev, unsigned long val, void *v)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(!relay_dev) {
|
||||
pr_err("Device is not initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(type >= NUM_TYPES || dev >= NUM_DEVS) {
|
||||
pr_err("Relay error type or dev\n");
|
||||
return -EPERM;
|
||||
}
|
||||
switch(type) {
|
||||
case ATOMIC:
|
||||
{
|
||||
struct atomic_notifier_head* h = &relay_dev->nodes[type][dev].atomic_head;
|
||||
ret = atomic_notifier_call_chain(h, val, v);
|
||||
break;
|
||||
}
|
||||
case BLOCKING:
|
||||
{
|
||||
struct blocking_notifier_head* h = &relay_dev->nodes[type][dev].blocking_head;
|
||||
ret = blocking_notifier_call_chain(h, val, v);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BUG_ON(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(relay_notifier_fire);
|
||||
|
||||
/**
|
||||
* Register an atomic or blocking notify to receive notifications from dev.
|
||||
* @dev: notification sender
|
||||
*/
|
||||
int relay_register_action(notifier_t type, notifier_d dev, struct notifier_block * nb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(!relay_dev) {
|
||||
pr_err("Device is not initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(type >= NUM_TYPES || dev >= NUM_DEVS) {
|
||||
pr_err("Relay error type or dev\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
mutex_lock(&relay_dev->lock);
|
||||
switch(type) {
|
||||
case ATOMIC:
|
||||
{
|
||||
struct atomic_notifier_head* h = &relay_dev->nodes[type][dev].atomic_head;
|
||||
ret = atomic_notifier_chain_register(h, nb);
|
||||
if (!ret)
|
||||
relay_notifier_fire(ATOMIC, MMI_RELAY, RELAY_NOTIFY_REGISTER, NULL);
|
||||
break;
|
||||
}
|
||||
case BLOCKING:
|
||||
{
|
||||
struct blocking_notifier_head* h = &relay_dev->nodes[type][dev].blocking_head;
|
||||
ret = blocking_notifier_chain_register(h, nb);
|
||||
if (!ret)
|
||||
relay_notifier_fire(BLOCKING, MMI_RELAY, RELAY_NOTIFY_REGISTER, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BUG_ON(1);
|
||||
}
|
||||
mutex_unlock(&relay_dev->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(relay_register_action);
|
||||
|
||||
int relay_unregister_action(notifier_t type, notifier_d dev, struct notifier_block *nb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(!relay_dev) {
|
||||
pr_err("Device is not initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(type >= NUM_TYPES || dev >= NUM_DEVS) {
|
||||
pr_err("Relay error type or dev\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
mutex_lock(&relay_dev->lock);
|
||||
switch(type) {
|
||||
case ATOMIC:
|
||||
{
|
||||
struct atomic_notifier_head* h = &relay_dev->nodes[type][dev].atomic_head;
|
||||
ret = atomic_notifier_chain_unregister(h, nb);
|
||||
if (!ret)
|
||||
relay_notifier_fire(ATOMIC, MMI_RELAY, RELAY_NOTIFY_UNREGISTER, NULL);
|
||||
break;
|
||||
}
|
||||
case BLOCKING:
|
||||
{
|
||||
struct blocking_notifier_head* h = &relay_dev->nodes[type][dev].blocking_head;
|
||||
ret = blocking_notifier_chain_unregister(h, nb);
|
||||
if (!ret)
|
||||
relay_notifier_fire(BLOCKING, MMI_RELAY, RELAY_NOTIFY_UNREGISTER, NULL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BUG_ON(1);
|
||||
}
|
||||
mutex_unlock(&relay_dev->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(relay_unregister_action);
|
||||
|
||||
static int mmi_relay_probe(struct platform_device *pdev)
|
||||
{
|
||||
notifier_t i;
|
||||
notifier_d j;
|
||||
|
||||
relay_dev = kzalloc(sizeof(struct mmi_relay_dev), GFP_KERNEL);
|
||||
if (!relay_dev) {
|
||||
pr_err("Failed to allocate memory for relay_dev\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
relay_dev->pdev = pdev;
|
||||
relay_dev->notifier_nums = NUM_DEVS * NUM_TYPES;
|
||||
|
||||
mutex_init(&relay_dev->lock);
|
||||
|
||||
for(i = (notifier_t)0; i < NUM_TYPES; i++) {
|
||||
for(j = (notifier_d)0; j < NUM_DEVS; j++) {
|
||||
relay_dev->nodes[i][j].type = i;
|
||||
relay_dev->nodes[i][j].dev= j;
|
||||
relay_dev->nodes[i][j].id = i << 16 | j;
|
||||
INIT_LIST_HEAD(&relay_dev->nodes[i][j].list);
|
||||
|
||||
if(i == ATOMIC) {
|
||||
ATOMIC_INIT_NOTIFIER_HEAD(&relay_dev->nodes[i][j].atomic_head);
|
||||
} else {
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&relay_dev->nodes[i][j].blocking_head);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmi_relay_remove(struct platform_device *pdev)
|
||||
{
|
||||
kfree(relay_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id mmi_relay_mt[] = {
|
||||
{.compatible = "mmi,sys-relay"},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mmi_relay_mt);
|
||||
|
||||
static struct platform_driver mmi_relay_driver = {
|
||||
.probe = mmi_relay_probe,
|
||||
.remove = mmi_relay_remove,
|
||||
.driver = {
|
||||
.name = "mmi_relay",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = mmi_relay_mt,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init mmi_relay_init(void)
|
||||
{
|
||||
return platform_driver_register(&mmi_relay_driver);
|
||||
}
|
||||
|
||||
static void __exit mmi_relay_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mmi_relay_driver);
|
||||
}
|
||||
|
||||
module_init(mmi_relay_init);
|
||||
module_exit(mmi_relay_exit);
|
||||
|
||||
MODULE_ALIAS("platform:mmi_relay");
|
||||
MODULE_AUTHOR("Motorola Mobility LLC");
|
||||
MODULE_DESCRIPTION("Motorola Mobility Module Conmmunication Relay");
|
||||
MODULE_LICENSE("GPL");
|
||||
28
include/linux/mmi_relay.h
Normal file
28
include/linux/mmi_relay.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef __MMI_RELAY_H__
|
||||
#define __MMI_RELAY_H__
|
||||
|
||||
#include <linux/notifier.h>
|
||||
|
||||
typedef enum notifier_type {
|
||||
ATOMIC,
|
||||
BLOCKING,
|
||||
NUM_TYPES,
|
||||
}notifier_t;
|
||||
|
||||
typedef enum notifier_dev {
|
||||
LCD,
|
||||
FPS,
|
||||
MMI_RELAY,
|
||||
NUM_DEVS,
|
||||
}notifier_d;
|
||||
|
||||
enum mmi_relay_event {
|
||||
RELAY_NOTIFY_REGISTER,
|
||||
RELAY_NOTIFY_UNREGISTER,
|
||||
};
|
||||
|
||||
extern int relay_notifier_fire(notifier_t type, notifier_d dev, unsigned long val, void *v);
|
||||
extern int relay_register_action(notifier_t type, notifier_d dev, struct notifier_block * nb);
|
||||
extern int relay_unregister_action(notifier_t type, notifier_d dev, struct notifier_block * nb);
|
||||
|
||||
#endif
|
||||
Loading…
Reference in a new issue