1/* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16//! IPC service definition. 17 18#![allow(unused_variables)] 19 20mod identity; 21 22use std::ffi::{ c_char, CString }; 23 24use hilog_rust::{ info, error, hilog, HiLogLabel, LogType }; 25use ipc_rust::{ 26 BorrowedMsgParcel, IRemoteBroker, IRemoteObj, MsgParcel, IMsgParcel, 27 RemoteObj, RemoteStub, define_remote_object 28}; 29 30use fusion_data_rust::Intention; 31use fusion_utils_rust::{ call_debug_enter, FusionResult, FusionErrorCode }; 32 33use crate::identity::{ CommonAction, compose_param_id, split_action, split_intention, split_param }; 34 35const LOG_LABEL: HiLogLabel = HiLogLabel { 36 log_type: LogType::LogCore, 37 domain: 0xD002220, 38 tag: "FusionIpcService" 39}; 40 41/// SA ID for "ohos.msdp.Idevicestatus" 42pub const MSDP_DEVICESTATUS_SERVICE_ID: i32 = 2902; 43 44/// Abstration of services. 45/// 46/// By design, for ease of extention, all service implementations are required to 47/// map its functions to this collection of interface, with services identified 48/// by Intentions. 49pub trait IDeviceStatus: IRemoteBroker { 50 /// Enable the service identified by [`intention`]. 51 fn enable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 52 /// Disable the service identified by [`intention`]. 53 fn disable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 54 /// Start the service identified by [`intention`]. 55 fn start(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 56 /// Stop the service identified by [`intention`]. 57 fn stop(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 58 /// Add a watch of state of service, with the service identified by [`intention`], 59 /// the state to watch identified by [`id`], parameters packed in [`data`] parcel. 60 fn add_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 61 /// Remove a watch of state of service. 62 fn remove_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 63 /// Set a parameter of service, with the service identified by [`intention`], 64 /// the parameter identified by [`id`], and values packed in [`data`] parcel. 65 fn set_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 66 /// Get a parameter of service, with the service identified by [`intention`], 67 /// the parameter identified by [`id`]. 68 fn get_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 69 /// Interact with service identified by [`intention`] for general purpose. This interface 70 /// supplements functions of previous intefaces. Functionalities of this interface is 71 /// service spicific. 72 fn control(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>; 73} 74 75fn on_remote_request(stub: &dyn IDeviceStatus, code: u32, data: &BorrowedMsgParcel<'_>, 76 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 77 call_debug_enter!("FusionIpcService::on_remote_request"); 78 let intention = split_intention(code)?; 79 let id = split_param(code); 80 81 match split_action(code)? { 82 CommonAction::Enable => { 83 info!(LOG_LABEL, "Call stub.enable()"); 84 stub.enable(intention, data, reply) 85 } 86 CommonAction::Disable => { 87 info!(LOG_LABEL, "Call stub.disable()"); 88 stub.disable(intention, data, reply) 89 } 90 CommonAction::Start => { 91 info!(LOG_LABEL, "Call stub.start()"); 92 stub.start(intention, data, reply) 93 } 94 CommonAction::Stop => { 95 info!(LOG_LABEL, "Call stub.stop()"); 96 stub.stop(intention, data, reply) 97 } 98 CommonAction::AddWatch => { 99 info!(LOG_LABEL, "Call stub.add_watch()"); 100 stub.add_watch(intention, id, data, reply) 101 } 102 CommonAction::RemoveWatch => { 103 info!(LOG_LABEL, "Call stub.remove_watch()"); 104 stub.remove_watch(intention, id, data, reply) 105 } 106 CommonAction::SetParam => { 107 info!(LOG_LABEL, "Call stub.set_param()"); 108 stub.set_param(intention, id, data, reply) 109 } 110 CommonAction::GetParam => { 111 info!(LOG_LABEL, "Call stub.get_param()"); 112 stub.get_param(intention, id, data, reply) 113 } 114 CommonAction::Control => { 115 info!(LOG_LABEL, "Call stub.control()"); 116 stub.control(intention, id, data, reply) 117 } 118 } 119} 120 121define_remote_object!( 122 IDeviceStatus["ohos.msdp.Idevicestatus"] { 123 stub: FusionIpcStub(on_remote_request), 124 proxy: FusionIpcProxy, 125 } 126); 127 128impl FusionIpcProxy { 129 fn transfer_data(&self, src: &dyn IMsgParcel, target: &mut dyn IMsgParcel) -> FusionResult<()> 130 { 131 call_debug_enter!("FusionIpcProxy::transfer_data"); 132 let data_size = src.get_data_size(); 133 match src.read_buffer(data_size) { 134 Ok(data_vec) => { 135 if target.write_buffer(data_vec.as_slice()) { 136 Ok(()) 137 } else { 138 error!(LOG_LABEL, "write_buffer() failed"); 139 Err(FusionErrorCode::Fail) 140 } 141 } 142 Err(_) => { 143 error!(LOG_LABEL, "read_buffer() failed"); 144 Err(FusionErrorCode::Fail) 145 } 146 } 147 } 148 149 fn send_request(&self, action: CommonAction, intention: Intention, id: u32, 150 data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> 151 { 152 call_debug_enter!("FusionIpcProxy::send_request"); 153 match MsgParcel::new() { 154 Some(mut data_parcel) => { 155 self.transfer_data(data, &mut data_parcel)?; 156 let code = compose_param_id(action, intention, id); 157 let rep = { 158 match self.remote.send_request(code, &data_parcel, false) { 159 Ok(tr) => { 160 tr 161 } 162 Err(_) => { 163 error!(LOG_LABEL, "Failed to send request"); 164 return Err(FusionErrorCode::Fail); 165 } 166 } 167 }; 168 169 self.transfer_data(&rep, reply) 170 } 171 None => { 172 error!(LOG_LABEL, "Can not deref data"); 173 Err(FusionErrorCode::Fail) 174 } 175 } 176 } 177} 178 179impl IDeviceStatus for FusionIpcProxy { 180 fn enable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, 181 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 182 call_debug_enter!("FusionIpcProxy::enable"); 183 self.send_request(CommonAction::Enable, intention, 0u32, data, reply) 184 } 185 186 fn disable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, 187 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 188 call_debug_enter!("FusionIpcProxy::disable"); 189 self.send_request(CommonAction::Disable, intention, 0u32, data, reply) 190 } 191 192 fn start(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, 193 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 194 call_debug_enter!("FusionIpcProxy::start"); 195 self.send_request(CommonAction::Start, intention, 0u32, data, reply) 196 } 197 198 fn stop(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, 199 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 200 call_debug_enter!("FusionIpcProxy::stop"); 201 self.send_request(CommonAction::Stop, intention, 0u32, data, reply) 202 } 203 204 fn add_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, 205 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 206 call_debug_enter!("FusionIpcProxy::add_watch"); 207 self.send_request(CommonAction::AddWatch, intention, id, data, reply) 208 } 209 210 fn remove_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, 211 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 212 call_debug_enter!("FusionIpcProxy::remove_watch"); 213 self.send_request(CommonAction::RemoveWatch, intention, id, data, reply) 214 } 215 216 fn set_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, 217 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 218 call_debug_enter!("FusionIpcProxy::set_param"); 219 self.send_request(CommonAction::SetParam, intention, id, data, reply) 220 } 221 222 fn get_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, 223 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 224 call_debug_enter!("FusionIpcProxy::get_param"); 225 self.send_request(CommonAction::GetParam, intention, id, data, reply) 226 } 227 228 fn control(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, 229 reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> { 230 call_debug_enter!("FusionIpcProxy::control"); 231 self.send_request(CommonAction::Control, intention, id, data, reply) 232 } 233} 234