1#![deny(unsafe_op_in_unsafe_fn, missing_docs)]
7
8mod wire;
9
10use fuchsia_sync::{Mutex, MutexGuard};
11use std::marker::PhantomData;
12use std::num::NonZero;
13use std::pin::Pin;
14use std::ptr::NonNull;
15use std::task::{Context, Poll};
16
17use fidl_next::{Chunk, HasExecutor};
18use zx::{HandleBased, Status};
19
20use fdf_channel::arena::{Arena, ArenaBox};
21use fdf_channel::channel::Channel;
22use fdf_channel::futures::ReadMessageState;
23use fdf_channel::message::Message;
24use fdf_core::dispatcher::{CurrentDispatcher, OnDispatcher};
25use fdf_core::handle::{DriverHandle, MixedHandle, MixedHandleType};
26
27pub use self::wire::*;
28
29#[derive(Debug, PartialEq)]
32pub struct DriverChannel<D = CurrentDispatcher> {
33 dispatcher: D,
34 channel: Channel<[Chunk]>,
35}
36
37impl<D> DriverChannel<D> {
38 pub fn new_with_dispatcher(dispatcher: D, channel: Channel<[Chunk]>) -> Self {
41 Self { dispatcher, channel }
42 }
43
44 pub fn create_with_dispatchers(dispatcher1: D, dispatcher2: D) -> (Self, Self) {
47 let (channel1, channel2) = Channel::create();
48 (
49 Self { dispatcher: dispatcher1, channel: channel1 },
50 Self { dispatcher: dispatcher2, channel: channel2 },
51 )
52 }
53
54 pub fn create_with_dispatcher(dispatcher: D) -> (Self, Self)
57 where
58 D: Clone,
59 {
60 Self::create_with_dispatchers(dispatcher.clone(), dispatcher)
61 }
62
63 pub fn receive_from_token_with_dispatcher(
66 dispatcher: D,
67 token: zx::Channel,
68 ) -> Result<DriverChannel<D>, Status> {
69 let mut handle = 0;
70 Status::ok(unsafe { fdf_sys::fdf_token_receive(token.into_raw(), &mut handle) })?;
71 let handle = NonZero::new(handle).ok_or(Status::BAD_HANDLE)?;
72 let channel = unsafe { Channel::from_driver_handle(DriverHandle::new_unchecked(handle)) };
73 Ok(DriverChannel::new_with_dispatcher(dispatcher, channel))
74 }
75
76 pub fn into_channel(self) -> Channel<[Chunk]> {
78 self.channel
79 }
80
81 pub fn into_driver_handle(self) -> DriverHandle {
83 self.channel.into_driver_handle()
84 }
85}
86
87impl DriverChannel<CurrentDispatcher> {
88 pub fn new(channel: Channel<[Chunk]>) -> Self {
91 Self::new_with_dispatcher(CurrentDispatcher, channel)
92 }
93
94 pub fn create() -> (Self, Self) {
97 Self::create_with_dispatcher(CurrentDispatcher)
98 }
99
100 pub fn receive_from_token(token: zx::Channel) -> Result<DriverChannel, Status> {
103 Self::receive_from_token_with_dispatcher(CurrentDispatcher, token)
104 }
105}
106
107impl fidl_next::InstanceFromServiceTransport<zx::Channel> for DriverChannel<CurrentDispatcher> {
108 fn from_service_transport(handle: zx::Channel) -> Self {
109 DriverChannel::receive_from_token(handle).unwrap()
110 }
111}
112
113pub fn create_channel_with_dispatchers<P, D>(
116 client_dispatcher: D,
117 server_dispatcher: D,
118) -> (fidl_next::ClientEnd<P, DriverChannel<D>>, fidl_next::ServerEnd<P, DriverChannel<D>>) {
119 let (client_channel, server_channel) =
120 DriverChannel::create_with_dispatchers(client_dispatcher, server_dispatcher);
121 (
122 fidl_next::ClientEnd::from_untyped(client_channel),
123 fidl_next::ServerEnd::from_untyped(server_channel),
124 )
125}
126
127pub fn create_channel_with_dispatcher<P, D: Clone>(
130 dispatcher: D,
131) -> (fidl_next::ClientEnd<P, DriverChannel<D>>, fidl_next::ServerEnd<P, DriverChannel<D>>) {
132 create_channel_with_dispatchers(dispatcher.clone(), dispatcher)
133}
134
135pub fn create_channel<P>()
138-> (fidl_next::ClientEnd<P, DriverChannel>, fidl_next::ServerEnd<P, DriverChannel>) {
139 create_channel_with_dispatcher(CurrentDispatcher)
140}
141
142pub struct SendBuffer {
144 handles: Vec<Option<MixedHandle>>,
145 data: Vec<Chunk>,
146}
147
148impl SendBuffer {
149 fn new() -> Self {
150 Self { handles: Vec::new(), data: Vec::new() }
151 }
152}
153
154impl fidl_next::Encoder for SendBuffer {
155 #[inline]
156 fn bytes_written(&self) -> usize {
157 fidl_next::Encoder::bytes_written(&self.data)
158 }
159
160 #[inline]
161 fn write(&mut self, bytes: &[u8]) {
162 fidl_next::Encoder::write(&mut self.data, bytes)
163 }
164
165 #[inline]
166 fn rewrite(&mut self, pos: usize, bytes: &[u8]) {
167 fidl_next::Encoder::rewrite(&mut self.data, pos, bytes)
168 }
169
170 fn write_zeroes(&mut self, len: usize) {
171 fidl_next::Encoder::write_zeroes(&mut self.data, len);
172 }
173}
174
175impl fidl_next::encoder::InternalHandleEncoder for SendBuffer {
176 #[inline]
177 fn __internal_handle_count(&self) -> usize {
178 self.handles.len()
179 }
180}
181
182impl fidl_next::fuchsia::HandleEncoder for SendBuffer {
183 fn push_handle(&mut self, handle: zx::NullableHandle) -> Result<(), fidl_next::EncodeError> {
184 if let Some(handle) = MixedHandle::from_zircon_handle(handle) {
185 if handle.is_driver() {
186 return Err(fidl_next::EncodeError::ExpectedZirconHandle);
187 }
188 self.handles.push(Some(handle));
189 } else {
190 self.handles.push(None);
191 }
192 Ok(())
193 }
194
195 unsafe fn push_raw_driver_handle(&mut self, handle: u32) -> Result<(), fidl_next::EncodeError> {
196 if let Some(handle) = NonZero::new(handle) {
197 let handle = unsafe { MixedHandle::from_raw(handle) };
200 if !handle.is_driver() {
201 return Err(fidl_next::EncodeError::ExpectedDriverHandle);
202 }
203 self.handles.push(Some(handle));
204 } else {
205 self.handles.push(None);
206 }
207 Ok(())
208 }
209
210 fn handles_pushed(&self) -> usize {
211 self.handles.len()
212 }
213}
214
215#[doc(hidden)] pub struct RecvBuffer {
217 buffer: Option<Message<[Chunk]>>,
218 data_offset: usize,
219 handle_offset: usize,
220}
221
222impl RecvBuffer {
223 fn next_handle(&self) -> Result<&MixedHandle, fidl_next::DecodeError> {
224 let Some(buffer) = &self.buffer else {
225 return Err(fidl_next::DecodeError::InsufficientHandles);
226 };
227
228 let Some(handles) = buffer.handles() else {
229 return Err(fidl_next::DecodeError::InsufficientHandles);
230 };
231 if handles.len() < self.handle_offset + 1 {
232 return Err(fidl_next::DecodeError::InsufficientHandles);
233 }
234 handles[self.handle_offset].as_ref().ok_or(fidl_next::DecodeError::RequiredHandleAbsent)
235 }
236}
237
238unsafe impl fidl_next::Decoder for RecvBuffer {
243 fn take_chunks_raw(&mut self, count: usize) -> Result<NonNull<Chunk>, fidl_next::DecodeError> {
246 let Some(buffer) = &mut self.buffer else {
247 return Err(fidl_next::DecodeError::InsufficientData);
248 };
249
250 let Some(data) = buffer.data_mut() else {
251 return Err(fidl_next::DecodeError::InsufficientData);
252 };
253 if data.len() < self.data_offset + count {
254 return Err(fidl_next::DecodeError::InsufficientData);
255 }
256 let pos = self.data_offset;
257 self.data_offset += count;
258 Ok(unsafe { NonNull::new_unchecked((data[pos..(pos + count)]).as_mut_ptr()) })
259 }
260
261 fn commit(&mut self) {
262 if let Some(handles) = self.buffer.as_mut().and_then(Message::handles_mut) {
263 for handle in handles.iter_mut().take(self.handle_offset) {
264 core::mem::forget(handle.take());
265 }
266 }
267 }
268
269 fn finish(&self) -> Result<(), fidl_next::DecodeError> {
270 if let Some(buffer) = &self.buffer {
271 let data_len = buffer.data().unwrap_or(&[]).len();
272 if self.data_offset != data_len {
273 return Err(fidl_next::DecodeError::ExtraBytes {
274 num_extra: data_len - self.data_offset,
275 });
276 }
277 let handle_len = buffer.handles().unwrap_or(&[]).len();
278 if self.handle_offset != handle_len {
279 return Err(fidl_next::DecodeError::ExtraHandles {
280 num_extra: handle_len - self.handle_offset,
281 });
282 }
283 }
284
285 Ok(())
286 }
287}
288
289impl fidl_next::decoder::InternalHandleDecoder for RecvBuffer {
290 fn __internal_take_handles(&mut self, count: usize) -> Result<(), fidl_next::DecodeError> {
291 let Some(handles) = self.buffer.as_mut().and_then(Message::handles_mut) else {
292 return Err(fidl_next::DecodeError::InsufficientHandles);
293 };
294 if handles.len() < self.handle_offset + count {
295 return Err(fidl_next::DecodeError::InsufficientHandles);
296 }
297 let pos = self.handle_offset;
298 self.handle_offset = pos + count;
299 Ok(())
300 }
301
302 fn __internal_handles_remaining(&self) -> usize {
303 self.buffer
304 .as_ref()
305 .map(|buffer| buffer.handles().unwrap_or(&[]).len() - self.handle_offset)
306 .unwrap_or(0)
307 }
308}
309
310impl fidl_next::fuchsia::HandleDecoder for RecvBuffer {
311 fn take_raw_handle(&mut self) -> Result<zx::sys::zx_handle_t, fidl_next::DecodeError> {
312 let result = {
313 let handle = self.next_handle()?.resolve_ref();
314 let MixedHandleType::Zircon(handle) = handle else {
315 return Err(fidl_next::DecodeError::ExpectedZirconHandle);
316 };
317 handle.raw_handle()
318 };
319 let pos = self.handle_offset;
320 self.handle_offset = pos + 1;
321 Ok(result)
322 }
323
324 fn take_raw_driver_handle(&mut self) -> Result<u32, fidl_next::DecodeError> {
325 let result = {
326 let handle = self.next_handle()?.resolve_ref();
327 let MixedHandleType::Driver(handle) = handle else {
328 return Err(fidl_next::DecodeError::ExpectedDriverHandle);
329 };
330 unsafe { handle.get_raw().get() }
331 };
332 let pos = self.handle_offset;
333 self.handle_offset = pos + 1;
334 Ok(result)
335 }
336
337 fn handles_remaining(&mut self) -> usize {
338 fidl_next::decoder::InternalHandleDecoder::__internal_handles_remaining(self)
339 }
340}
341
342pub struct DriverRecvState(ReadMessageState);
344
345pub struct Shared<D> {
347 channel: Mutex<DriverChannel<D>>,
348}
349
350impl<D> Shared<D> {
351 fn new(channel: Mutex<DriverChannel<D>>) -> Self {
352 Self { channel }
353 }
354
355 fn get_locked(&self) -> MutexGuard<'_, DriverChannel<D>> {
356 self.channel.lock()
357 }
358}
359
360pub struct Exclusive {
362 _phantom: PhantomData<()>,
363}
364
365impl<D: OnDispatcher> fidl_next::Transport for DriverChannel<D> {
366 type Error = Status;
367
368 fn split(self) -> (Self::Shared, Self::Exclusive) {
369 (Shared::new(Mutex::new(self)), Exclusive { _phantom: PhantomData })
370 }
371
372 type Shared = Shared<D>;
373
374 type SendBuffer = SendBuffer;
375
376 type SendFutureState = SendBuffer;
377
378 fn acquire(_shared: &Self::Shared) -> Self::SendBuffer {
379 SendBuffer::new()
380 }
381
382 type Exclusive = Exclusive;
383
384 type RecvFutureState = DriverRecvState;
385
386 type RecvBuffer = RecvBuffer;
387
388 fn begin_send(_shared: &Self::Shared, buffer: Self::SendBuffer) -> Self::SendFutureState {
389 buffer
390 }
391
392 fn poll_send(
393 mut buffer: Pin<&mut Self::SendFutureState>,
394 _cx: &mut Context<'_>,
395 shared: &Self::Shared,
396 ) -> Poll<Result<(), Option<Self::Error>>> {
397 let arena = Arena::new();
398 let message = Message::new_with(arena, |arena| {
399 let data = arena.insert_slice(&buffer.data);
400 let handles = buffer.handles.split_off(0);
401 let handles = arena.insert_from_iter(handles);
402 (Some(data), Some(handles))
403 });
404 let result = match shared.get_locked().channel.write(message) {
405 Ok(()) => Ok(()),
406 Err(Status::PEER_CLOSED) => Err(None),
407 Err(e) => Err(Some(e)),
408 };
409 Poll::Ready(result)
410 }
411
412 fn begin_recv(
413 shared: &Self::Shared,
414 _exclusive: &mut Self::Exclusive,
415 ) -> Self::RecvFutureState {
416 let state =
419 unsafe { ReadMessageState::register_read_wait(&mut shared.get_locked().channel) };
420 DriverRecvState(state)
421 }
422
423 fn poll_recv(
424 mut future: Pin<&mut Self::RecvFutureState>,
425 cx: &mut Context<'_>,
426 shared: &Self::Shared,
427 _exclusive: &mut Self::Exclusive,
428 ) -> Poll<Result<Self::RecvBuffer, Option<Self::Error>>> {
429 use std::task::Poll::*;
430 match future.as_mut().0.poll_with_dispatcher(cx, shared.get_locked().dispatcher.clone()) {
431 Ready(Ok(maybe_buffer)) => {
432 let buffer = maybe_buffer.map(|buffer| {
433 buffer.map_data(|_, data| {
434 let bytes = data.len();
435 assert_eq!(
436 0,
437 bytes % size_of::<Chunk>(),
438 "Received driver channel buffer was not a multiple of {} bytes",
439 size_of::<Chunk>()
440 );
441 unsafe {
445 let ptr = ArenaBox::into_ptr(data).cast();
446 ArenaBox::new(NonNull::slice_from_raw_parts(
447 ptr,
448 bytes / size_of::<Chunk>(),
449 ))
450 }
451 })
452 });
453
454 Ready(Ok(RecvBuffer { buffer, data_offset: 0, handle_offset: 0 }))
455 }
456 Ready(Err(err)) => {
457 if err == Status::PEER_CLOSED {
458 Ready(Err(None))
459 } else {
460 Ready(Err(Some(err)))
461 }
462 }
463 Pending => Pending,
464 }
465 }
466}
467
468impl<D> fidl_next::RunsTransport<DriverChannel<D>> for fidl_next::fuchsia_async::FuchsiaAsync {}
469
470impl<D: OnDispatcher + 'static> HasExecutor for DriverChannel<D> {
471 type Executor = fidl_next::fuchsia_async::FuchsiaAsync;
472
473 fn executor(&self) -> Self::Executor {
474 fidl_next::fuchsia_async::FuchsiaAsync
475 }
476}
477
478#[cfg(test)]
479mod test {
480 use fidl_next::{ClientDispatcher, ClientEnd, Responder, ServerDispatcher, ServerEnd};
487 use fidl_next_fuchsia_examples_gizmo::device::{GetEvent, GetHardwareId};
488 use fidl_next_fuchsia_examples_gizmo::{Device, DeviceClientHandler, DeviceServerHandler};
489 use fuchsia_async::OnSignals;
490 use zx::{AsHandleRef, Event, Signals};
491
492 use super::*;
493 use fdf_core::dispatcher::{CurrentDispatcher, OnDispatcher};
494 use fdf_env::test::spawn_in_driver;
495
496 struct DeviceServer;
497 impl DeviceServerHandler<DriverChannel> for DeviceServer {
498 async fn get_hardware_id(&mut self, responder: Responder<GetHardwareId, DriverChannel>) {
499 responder.respond(4004u32).await.unwrap();
500 }
501
502 async fn get_event(&mut self, responder: Responder<GetEvent, DriverChannel>) {
503 let event = Event::create();
504 event.signal_handle(Signals::empty(), Signals::USER_0).unwrap();
505 responder.respond(event).await.unwrap();
506 }
507 }
508
509 struct DeviceClient;
510 impl DeviceClientHandler<DriverChannel> for DeviceClient {}
511
512 #[test]
513 fn driver_fidl_server() {
514 spawn_in_driver("driver fidl server", async {
515 let (server_chan, client_chan) = Channel::<[Chunk]>::create();
516 let client_end: ClientEnd<Device, _> =
517 ClientEnd::<Device, _>::from_untyped(DriverChannel::new(client_chan));
518 let server_end: ServerEnd<Device, _> =
519 ServerEnd::from_untyped(DriverChannel::new(server_chan));
520 let client_dispatcher = ClientDispatcher::new(client_end);
521 let server_dispatcher = ServerDispatcher::new(server_end);
522 let client = client_dispatcher.client();
523
524 CurrentDispatcher
525 .spawn(async {
526 server_dispatcher.run(DeviceServer).await.unwrap();
527 println!("server task finished");
528 })
529 .unwrap();
530 CurrentDispatcher
531 .spawn(async {
532 client_dispatcher.run(DeviceClient).await.unwrap();
533 println!("client task finished");
534 })
535 .unwrap();
536
537 {
538 let res = client.get_hardware_id().await.unwrap();
539 let hardware_id = res.unwrap();
540 assert_eq!(hardware_id.response, 4004);
541 }
542
543 {
544 let res = client.get_event().await.unwrap();
545
546 let mut executor = fuchsia_async::LocalExecutor::default();
548 let signalled = executor
549 .run_singlethreaded(OnSignals::new(res.event, Signals::USER_0))
550 .unwrap();
551 assert_eq!(Signals::USER_0, signalled);
552 }
553 });
554 }
555}