summaryrefslogtreecommitdiff
path: root/drivers/android/rust_binder.rs
blob: d059077238ce54d4b944334ec1f6adddb71df553 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// SPDX-License-Identifier: GPL-2.0

//! Binder -- the Android IPC mechanism.
//!
//! TODO: This module is a work in progress.

use kernel::{
    io_buffer::IoBufferWriter,
    linked_list::{GetLinks, GetLinksWrapped, Links},
    miscdev::Registration,
    prelude::*,
    str::CStr,
    sync::Ref,
    user_ptr::UserSlicePtrWriter,
};

mod allocation;
mod context;
mod defs;
mod node;
mod process;
mod range_alloc;
mod thread;
mod transaction;

use {context::Context, thread::Thread};

module! {
    type: BinderModule,
    name: b"rust_binder",
    author: b"Wedson Almeida Filho",
    description: b"Android Binder",
    license: b"GPL",
}

enum Either<L, R> {
    Left(L),
    Right(R),
}

trait DeliverToRead {
    /// Performs work. Returns true if remaining work items in the queue should be processed
    /// immediately, or false if it should return to caller before processing additional work
    /// items.
    fn do_work(self: Ref<Self>, thread: &Thread, writer: &mut UserSlicePtrWriter) -> Result<bool>;

    /// Cancels the given work item. This is called instead of [`DeliverToRead::do_work`] when work
    /// won't be delivered.
    fn cancel(self: Ref<Self>) {}

    /// Returns the linked list links for the work item.
    fn get_links(&self) -> &Links<dyn DeliverToRead>;
}

struct DeliverToReadListAdapter {}

impl GetLinks for DeliverToReadListAdapter {
    type EntryType = dyn DeliverToRead;

    fn get_links(data: &Self::EntryType) -> &Links<Self::EntryType> {
        data.get_links()
    }
}

impl GetLinksWrapped for DeliverToReadListAdapter {
    type Wrapped = Ref<dyn DeliverToRead>;
}

struct DeliverCode {
    code: u32,
    links: Links<dyn DeliverToRead>,
}

impl DeliverCode {
    fn new(code: u32) -> Self {
        Self {
            code,
            links: Links::new(),
        }
    }
}

impl DeliverToRead for DeliverCode {
    fn do_work(self: Ref<Self>, _thread: &Thread, writer: &mut UserSlicePtrWriter) -> Result<bool> {
        writer.write(&self.code)?;
        Ok(true)
    }

    fn get_links(&self) -> &Links<dyn DeliverToRead> {
        &self.links
    }
}

const fn ptr_align(value: usize) -> usize {
    let size = core::mem::size_of::<usize>() - 1;
    (value + size) & !size
}

unsafe impl Sync for BinderModule {}

struct BinderModule {
    _reg: Pin<Box<Registration<process::Process>>>,
}

impl kernel::Module for BinderModule {
    fn init(name: &'static CStr, _module: &'static kernel::ThisModule) -> Result<Self> {
        let ctx = Context::new()?;
        let reg = Registration::new_pinned(fmt!("{name}"), ctx)?;
        Ok(Self { _reg: reg })
    }
}