xref: /linux/rust/kernel/serdev.rs (revision 59e6295fac26b8e85c1ea859cdd89fa1e47519d7)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Abstractions for the serial device bus.
4 //!
5 //! C header: [`include/linux/serdev.h`](srctree/include/linux/serdev.h)
6 
7 use crate::{
8     acpi,
9     device,
10     driver,
11     error::{
12         from_result,
13         to_result,
14         VTABLE_DEFAULT_ERROR, //
15     },
16     new_mutex,
17     of,
18     prelude::*,
19     sync::{
20         aref::AlwaysRefCounted,
21         Mutex, //
22     },
23     time::Jiffies,
24     types::{
25         Opaque,
26         ScopeGuard, //
27     }, //
28 };
29 
30 use core::{
31     cell::UnsafeCell,
32     marker::PhantomData,
33     mem::{offset_of, MaybeUninit},
34     ptr::NonNull, //
35 };
36 
37 /// Parity bit to use with a serial device.
38 #[repr(u32)]
39 pub enum Parity {
40     /// No parity bit.
41     None = bindings::serdev_parity_SERDEV_PARITY_NONE,
42     /// Even partiy.
43     Even = bindings::serdev_parity_SERDEV_PARITY_EVEN,
44     /// Odd parity.
45     Odd = bindings::serdev_parity_SERDEV_PARITY_ODD,
46 }
47 
48 /// An adapter for the registration of serial device bus device drivers.
49 pub struct Adapter<T: Driver>(T);
50 
51 // SAFETY:
52 // - `bindings::serdev_device_driver` is a C type declared as `repr(C)`.
53 // - `PrivateData<'bound, T>` is the type of the driver's device private data.
54 // - `struct serdev_device_driver` embeds a `struct device_driver`.
55 // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
56 unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> {
57     type DriverType = bindings::serdev_device_driver;
58     type DriverData<'bound> = PrivateData<'bound, T>;
59     const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
60 }
61 
62 // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
63 // a preceding call to `register` has been successful.
64 unsafe impl<T: Driver> driver::RegistrationOps for Adapter<T> {
65     unsafe fn register(
66         sdrv: &Opaque<Self::DriverType>,
67         name: &'static CStr,
68         module: &'static ThisModule,
69     ) -> Result {
70         let of_table = match T::OF_ID_TABLE {
71             Some(table) => table.as_ptr(),
72             None => core::ptr::null(),
73         };
74 
75         let acpi_table = match T::ACPI_ID_TABLE {
76             Some(table) => table.as_ptr(),
77             None => core::ptr::null(),
78         };
79 
80         // SAFETY: It's safe to set the fields of `struct serdev_device_driver` on initialization.
81         unsafe {
82             (*sdrv.get()).driver.name = name.as_char_ptr();
83             (*sdrv.get()).probe = Some(Self::probe_callback);
84             (*sdrv.get()).remove = Some(Self::remove_callback);
85             (*sdrv.get()).driver.of_match_table = of_table;
86             (*sdrv.get()).driver.acpi_match_table = acpi_table;
87         }
88 
89         // SAFETY: `sdrv` is guaranteed to be a valid `DriverType`.
90         to_result(unsafe { bindings::__serdev_device_driver_register(sdrv.get(), module.as_ptr()) })
91     }
92 
93     unsafe fn unregister(sdrv: &Opaque<Self::DriverType>) {
94         // SAFETY: `sdrv` is guaranteed to be a valid `DriverType`.
95         unsafe { bindings::serdev_device_driver_unregister(sdrv.get()) };
96     }
97 }
98 
99 #[doc(hidden)]
100 #[pin_data(PinnedDrop)]
101 pub struct PrivateData<'bound, T: Driver> {
102     sdev: &'bound Device<device::Bound>,
103     #[pin]
104     driver: UnsafeCell<MaybeUninit<T::Data<'bound>>>,
105     open: UnsafeCell<bool>,
106     /// Whether `receive_buf_callback` is allowed to call `Driver::receive`.
107     ///
108     /// If locked, the receive_buf_callback will be blocked on data reception.
109     /// This is the case while the driver is being probed or while [`PrivateData`] is being dropped.
110     /// This is necessary, because we need to open the serdev device before the driver has been
111     /// probed in order to allow it to be configured, which allows `receive_buf_callback` to be
112     /// called. Thus we need to block data until probe completes and the driver data becomes
113     /// initialized.
114     ///
115     /// If unlocked and true, the receive_buf_callback will forward the data to
116     /// `Driver::receive`. This is the normal state of operation.
117     ///
118     /// If unlocked and false, the receive_buf_callback will throw away the data.
119     /// This is only the case, if the serdev device is open and
120     /// - the driver returned an error in probe
121     /// or
122     /// - the driver data already has been dropped, because it was unbound.
123     #[pin]
124     active: Mutex<bool>,
125 }
126 
127 #[pinned_drop]
128 impl<T: Driver> PinnedDrop for PrivateData<'_, T> {
129     fn drop(self: Pin<&mut Self>) {
130         let mut active = self.active.lock();
131         if *active {
132             // SAFETY:
133             // - We have exclusive access to `self.driver`.
134             // - `self.driver` is guaranteed to be initialized.
135             unsafe { (*self.driver.get()).assume_init_drop() };
136             *active = false;
137         }
138         drop(active);
139 
140         // SAFETY: We have exclusive access to `self.open`.
141         if unsafe { *self.open.get() } {
142             // SAFETY: `self.sdev.as_raw()` is guaranteed to be a pointer to a valid
143             // `struct serdev_device`.
144             unsafe { bindings::serdev_device_close(self.sdev.as_raw()) };
145         }
146     }
147 }
148 
149 impl<T: Driver> Adapter<T> {
150     const OPS: &'static bindings::serdev_device_ops = &bindings::serdev_device_ops {
151         receive_buf: if T::HAS_RECEIVE {
152             Some(Self::receive_buf_callback)
153         } else {
154             None
155         },
156         write_wakeup: Some(bindings::serdev_device_write_wakeup),
157     };
158 
159     extern "C" fn probe_callback(sdev: *mut bindings::serdev_device) -> kernel::ffi::c_int {
160         // SAFETY: The serial device bus only ever calls the probe callback with a valid pointer to
161         // a `struct serdev_device`.
162         //
163         // INVARIANT: `sdev` is valid for the duration of `probe_callback()`.
164         let sdev = unsafe { &*sdev.cast::<Device<device::CoreInternal<'_>>>() };
165         // SAFETY: `sdev` matched data is of type `Self::IdInfo`.
166         let info = unsafe { <Self as driver::Adapter>::id_info(sdev.as_ref()) };
167 
168         from_result(|| {
169             sdev.as_ref().set_drvdata(try_pin_init!(PrivateData::<T> {
170                 sdev: &**sdev,
171                 driver: MaybeUninit::<T::Data<'_>>::zeroed().into(),
172                 open: false.into(),
173                 active <- new_mutex!(false),
174             }))?;
175             // SAFETY: We just set drvdata to `PrivateData<'_, T>`.
176             let private_data = unsafe { sdev.as_ref().drvdata_borrow::<PrivateData<'_, T>>() };
177             let private_data = ScopeGuard::new_with_data(private_data, |_| {
178                 // SAFETY: We just set drvdata to `PrivateData<'_, T>`.
179                 drop(unsafe { sdev.as_ref().drvdata_obtain::<PrivateData<'_, T>>() });
180             });
181             let mut active = private_data.active.lock();
182 
183             // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer to `serdev_device`.
184             unsafe { bindings::serdev_device_set_client_ops(sdev.as_raw(), Self::OPS) };
185 
186             // SAFETY: The serial device bus only ever calls the probe callback with a valid pointer
187             // to a `serdev_device`.
188             to_result(unsafe { bindings::serdev_device_open(sdev.as_raw()) })?;
189 
190             // SAFETY: We have exclusive access to `private_data.open`.
191             unsafe { *private_data.open.get() = true };
192 
193             let data = T::probe(sdev, info);
194 
195             // SAFETY: We have exclusive access to `private_data.driver`.
196             let driver = unsafe { &mut *private_data.driver.get() };
197             // SAFETY:
198             // - `driver.as_mut_ptr()` is a valid pointer to uninitialized data.
199             // - `private_data.driver` is pinned.
200             let result = unsafe { pin_init::raw_try_init(driver.as_mut_ptr(), data) };
201 
202             *active = result.is_ok();
203 
204             drop(active);
205 
206             result.map(|()| {
207                 private_data.dismiss();
208                 0
209             })
210         })
211     }
212 
213     extern "C" fn remove_callback(sdev: *mut bindings::serdev_device) {
214         // SAFETY: The serial device bus only ever calls the remove callback with a valid pointer
215         // to a `struct serdev_device`.
216         //
217         // INVARIANT: `sdev` is valid for the duration of `remove_callback()`.
218         let sdev = unsafe { &*sdev.cast::<Device<device::CoreInternal<'_>>>() };
219 
220         // SAFETY: `remove_callback` is only ever called after a successful call to
221         // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
222         // and stored a `Pin<KBox<PrivateData<'_, T>>>`.
223         let private_data = unsafe { sdev.as_ref().drvdata_borrow::<PrivateData<'_, T>>() };
224 
225         // SAFETY: No one has exclusive access to `private_data.driver`.
226         let data = unsafe { &*private_data.driver.get() };
227         // SAFETY:
228         // - `private_data.driver` is pinned.
229         // - `remove_callback` is only ever called after a successful call to `probe_callback`,
230         //   hence it's guaranteed that `private_data.driver` was initialized.
231         let data_pinned = unsafe { Pin::new_unchecked(data.assume_init_ref()) };
232 
233         T::unbind(sdev, data_pinned);
234     }
235 
236     extern "C" fn receive_buf_callback(
237         sdev: *mut bindings::serdev_device,
238         buf: *const u8,
239         length: usize,
240     ) -> usize {
241         // SAFETY: The serial device bus only ever calls the receive buf callback with a valid
242         // pointer to a `struct serdev_device`.
243         //
244         // INVARIANT: `sdev` is valid for the duration of `receive_buf_callback()`.
245         let sdev = unsafe { &*sdev.cast::<Device<device::BoundInternal>>() };
246 
247         // SAFETY: `receive_buf_callback` is only ever called after a successful call to
248         // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
249         // and stored a `Pin<KBox<PrivateData<'_, T>>>`.
250         let private_data = unsafe { sdev.as_ref().drvdata_borrow::<PrivateData<'_, T>>() };
251         let active = private_data.active.lock();
252 
253         if !*active {
254             return length;
255         }
256 
257         // SAFETY: No one has exclusive access to `private_data.driver`.
258         let data = unsafe { &*private_data.driver.get() };
259         // SAFETY:
260         // - `private_data.driver` is pinned.
261         // - `receive_buf_callback` is only ever called after a successful call to `probe_callback`,
262         //   hence it's guaranteed that `private_data.driver` was initialized.
263         let data_pinned = unsafe { Pin::new_unchecked(data.assume_init_ref()) };
264 
265         // SAFETY: `buf` is guaranteed to be non-null and has the size of `length`.
266         let buf = unsafe { core::slice::from_raw_parts(buf, length) };
267 
268         T::receive(sdev, data_pinned, buf)
269     }
270 }
271 
272 impl<T: Driver> driver::Adapter for Adapter<T> {
273     type IdInfo = T::IdInfo;
274 
275     fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> {
276         T::OF_ID_TABLE
277     }
278 
279     fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>> {
280         T::ACPI_ID_TABLE
281     }
282 }
283 
284 /// Declares a kernel module that exposes a single serial device bus device driver.
285 ///
286 /// # Examples
287 ///
288 /// ```ignore
289 /// kernel::module_serdev_device_driver! {
290 ///     type: MyDriver,
291 ///     name: "Module name",
292 ///     authors: ["Author name"],
293 ///     description: "Description",
294 ///     license: "GPL v2",
295 /// }
296 /// ```
297 #[macro_export]
298 macro_rules! module_serdev_device_driver {
299     ($($f:tt)*) => {
300         $crate::module_driver!(<T>, $crate::serdev::Adapter<T>, { $($f)* });
301     };
302 }
303 
304 /// The serial device bus device driver trait.
305 ///
306 /// Drivers must implement this trait in order to get a serial device bus device driver registered.
307 ///
308 /// # Examples
309 ///
310 ///```
311 /// # use kernel::{
312 ///     acpi,
313 ///     bindings,
314 ///     device::{
315 ///         Bound,
316 ///         Core, //
317 ///     },
318 ///     of,
319 ///     serdev, //
320 /// };
321 ///
322 /// struct MyDriver;
323 ///
324 /// kernel::of_device_table!(
325 ///     OF_TABLE,
326 ///     <MyDriver as serdev::Driver>::IdInfo,
327 ///     [
328 ///         (of::DeviceId::new(c"test,device"), ())
329 ///     ]
330 /// );
331 ///
332 /// kernel::acpi_device_table!(
333 ///     ACPI_TABLE,
334 ///     <MyDriver as serdev::Driver>::IdInfo,
335 ///     [
336 ///         (acpi::DeviceId::new(c"LNUXBEEF"), ())
337 ///     ]
338 /// );
339 ///
340 /// #[vtable]
341 /// impl serdev::Driver for MyDriver {
342 ///     type IdInfo = ();
343 ///     type Data<'bound> = Self;
344 ///     const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
345 ///     const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
346 ///
347 ///     fn probe<'bound>(
348 ///         sdev: &'bound serdev::Device<Core<'_>>,
349 ///         _id_info: Option<&'bound Self::IdInfo>,
350 ///     ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
351 ///         sdev.set_baudrate(115200);
352 ///         sdev.write_all(b"Hello\n", 0)?;
353 ///         Ok(MyDriver)
354 ///     }
355 /// }
356 ///```
357 #[vtable]
358 pub trait Driver {
359     /// The type holding driver private data about each device id supported by the driver.
360     // TODO: Use associated_type_defaults once stabilized:
361     //
362     // ```
363     // type IdInfo: 'static = ();
364     // ```
365     type IdInfo: 'static;
366 
367     /// The type of the driver's bus device private data.
368     type Data<'bound>: Send + Sync + 'bound;
369 
370     /// The table of OF device ids supported by the driver.
371     const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
372 
373     /// The table of ACPI device ids supported by the driver.
374     const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None;
375 
376     /// Serial device bus device driver probe.
377     ///
378     /// Called when a new serial device bus device is added or discovered.
379     /// Implementers should attempt to initialize the device here.
380     fn probe<'bound>(
381         sdev: &'bound Device<device::Core<'_>>,
382         id_info: Option<&'bound Self::IdInfo>,
383     ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
384 
385     /// Serial device bus device driver unbind.
386     ///
387     /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback
388     /// is optional.
389     ///
390     /// This callback serves as a place for drivers to perform teardown operations that require a
391     /// `&Device<Core>` or `&Device<Bound>` reference. For instance.
392     ///
393     /// Otherwise, release operations for driver resources should be performed in `Drop`.
394     fn unbind<'bound>(sdev: &'bound Device<device::Core<'_>>, this: Pin<&Self::Data<'bound>>) {
395         let _ = (sdev, this);
396     }
397 
398     /// Serial device bus device data receive callback.
399     ///
400     /// Called when data got received from device.
401     ///
402     /// Returns the number of bytes accepted.
403     fn receive<'bound>(
404         sdev: &'bound Device<device::Bound>,
405         this: Pin<&Self::Data<'bound>>,
406         data: &[u8],
407     ) -> usize {
408         let _ = (sdev, this, data);
409         build_error!(VTABLE_DEFAULT_ERROR)
410     }
411 }
412 
413 /// The serial device bus device representation.
414 ///
415 /// This structure represents the Rust abstraction for a C `struct serdev_device`. The
416 /// implementation abstracts the usage of an already existing C `struct serdev_device` within Rust
417 /// code that we get passed from the C side.
418 ///
419 /// # Invariants
420 ///
421 /// A [`Device`] instance represents a valid `struct serdev_device` created by the C portion of
422 /// the kernel.
423 #[repr(transparent)]
424 pub struct Device<Ctx: device::DeviceContext = device::Normal>(
425     Opaque<bindings::serdev_device>,
426     PhantomData<Ctx>,
427 );
428 
429 impl<Ctx: device::DeviceContext> Device<Ctx> {
430     #[inline]
431     fn as_raw(&self) -> *mut bindings::serdev_device {
432         self.0.get()
433     }
434 }
435 
436 impl Device<device::Bound> {
437     /// Set the baudrate in bits per second.
438     ///
439     /// Common baudrates are 115200, 9600, 19200, 57600, 4800.
440     ///
441     /// Use [`Device::write_flush`] before calling this if you have written data prior to this call.
442     #[inline]
443     pub fn set_baudrate(&self, speed: u32) -> Result<(), u32> {
444         // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
445         let ret = unsafe { bindings::serdev_device_set_baudrate(self.as_raw(), speed) };
446         if ret == speed {
447             Ok(())
448         } else {
449             Err(ret)
450         }
451     }
452 
453     /// Set if flow control should be enabled.
454     ///
455     /// Use [`Device::write_flush`] before calling this if you have written data prior to this call.
456     #[inline]
457     pub fn set_flow_control(&self, enable: bool) {
458         // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
459         unsafe { bindings::serdev_device_set_flow_control(self.as_raw(), enable) };
460     }
461 
462     /// Set parity to use.
463     ///
464     /// Use [`Device::write_flush`] before calling this if you have written data prior to this call.
465     #[inline]
466     pub fn set_parity(&self, parity: Parity) -> Result {
467         // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
468         to_result(unsafe { bindings::serdev_device_set_parity(self.as_raw(), parity as u32) })
469     }
470 
471     /// Write data to the serial device until the controller has accepted all the data or has
472     /// been interrupted by a timeout or signal.
473     ///
474     /// Note that any accepted data has only been buffered by the controller. Use
475     /// [`Device::wait_until_sent`] to make sure the controller write buffer has actually been
476     /// emptied.
477     ///
478     /// Use a timeout of 0 to wait indefinitely.
479     ///
480     /// Returns the number of bytes written (less than `data.len()` if interrupted).
481     /// [`kernel::error::code::ETIMEDOUT`] or [`kernel::error::code::ERESTARTSYS`] if interrupted
482     /// before any bytes were written. [`kernel::error::code::EINVAL`] if `data.len() > i32::MAX`.
483     #[inline]
484     pub fn write_all(&self, data: &[u8], timeout: Jiffies) -> Result<usize> {
485         if data.len() > i32::MAX as usize {
486             return Err(EINVAL);
487         }
488 
489         // SAFETY:
490         // - `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
491         // - `data.as_ptr()` is guaranteed to be a valid array pointer with the size of
492         //   `data.len()`.
493         let ret = unsafe {
494             bindings::serdev_device_write(
495                 self.as_raw(),
496                 data.as_ptr(),
497                 data.len(),
498                 isize::try_from(timeout).unwrap_or_default(),
499             )
500         };
501         // CAST: negative return values are guaranteed to be between `-MAX_ERRNO` and `-1`,
502         // which always fit into a `i32`.
503         to_result(ret as i32).map(|()| ret.unsigned_abs())
504     }
505 
506     /// Write data to the serial device.
507     ///
508     /// If you want to write until the controller has accepted all the data, use
509     /// [`Device::write_all`].
510     ///
511     /// Note that any accepted data has only been buffered by the controller. Use
512     /// [`Device::wait_until_sent`] to make sure the controller write buffer has actually been
513     /// emptied.
514     ///
515     /// Returns the number of bytes written (less than `data.len()` if not enough room in the
516     /// write buffer).
517     #[inline]
518     pub fn write(&self, data: &[u8]) -> Result<u32> {
519         if data.len() > i32::MAX as usize {
520             return Err(EINVAL);
521         }
522 
523         // SAFETY:
524         // - `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
525         // - `data.as_ptr()` is guaranteed to be a valid array pointer with the size of
526         //   `data.len()`.
527         let ret =
528             unsafe { bindings::serdev_device_write_buf(self.as_raw(), data.as_ptr(), data.len()) };
529 
530         to_result(ret as i32).map(|()| ret.unsigned_abs())
531     }
532 
533     /// Send data to the serial device immediately.
534     ///
535     /// Note that this doesn't guarantee that the data has been transmitted.
536     /// Use [`Device::wait_until_sent`] for this purpose.
537     #[inline]
538     pub fn write_flush(&self) {
539         // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
540         unsafe { bindings::serdev_device_write_flush(self.as_raw()) };
541     }
542 
543     /// Wait for the data to be sent.
544     ///
545     /// After this function, the write buffer of the controller should be empty or the timeout
546     /// elapsed.
547     ///
548     /// Use a timeout of 0 to wait indefinitely.
549     #[inline]
550     pub fn wait_until_sent(&self, timeout: Jiffies) {
551         // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
552         unsafe {
553             bindings::serdev_device_wait_until_sent(
554                 self.as_raw(),
555                 isize::try_from(timeout).unwrap_or_default(),
556             )
557         };
558     }
559 }
560 
561 // SAFETY: `serdev::Device` is a transparent wrapper of `struct serdev_device`.
562 // The offset is guaranteed to point to a valid device field inside `serdev::Device`.
563 unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx> {
564     const OFFSET: usize = offset_of!(bindings::serdev_device, dev);
565 }
566 
567 // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
568 // argument.
569 kernel::impl_device_context_deref!(unsafe { Device });
570 kernel::impl_device_context_into_aref!(Device);
571 
572 // SAFETY: Instances of `Device` are always reference-counted.
573 unsafe impl AlwaysRefCounted for Device {
574     fn inc_ref(&self) {
575         self.as_ref().inc_ref();
576     }
577 
578     unsafe fn dec_ref(obj: NonNull<Self>) {
579         // SAFETY: The safety requirements guarantee that the refcount is non-zero.
580         unsafe { bindings::serdev_device_put(obj.cast().as_ptr()) }
581     }
582 }
583 
584 impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
585     fn as_ref(&self) -> &device::Device<Ctx> {
586         // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
587         // `struct serdev_device`.
588         let dev = unsafe { &raw mut (*self.as_raw()).dev };
589 
590         // SAFETY: `dev` points to a valid `struct device`.
591         unsafe { device::Device::from_raw(dev) }
592     }
593 }
594 
595 // SAFETY: A `Device` is always reference-counted and can be released from any thread.
596 unsafe impl Send for Device {}
597 
598 // SAFETY: `Device` can be shared among threads because all methods of `Device`
599 // (i.e. `Device<Normal>) are thread safe.
600 unsafe impl Sync for Device {}
601 
602 // SAFETY: Same as `Device<Normal>` -- the underlying `struct serdev_device` is the same;
603 // `Bound` is a zero-sized type-state marker that does not affect thread safety.
604 unsafe impl Sync for Device<device::Bound> {}
605