xref: /aosp_15_r20/external/crosvm/devices/src/pci/pci_address.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Display;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::str::FromStr;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
11*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
12*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserializer;
13*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
14*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serializer;
15*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker /// Identifies a single component of a [`PciAddress`].
18*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq)]
19*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciAddressComponent {
20*bb4ee6a4SAndroid Build Coastguard Worker     Domain,
21*bb4ee6a4SAndroid Build Coastguard Worker     Bus,
22*bb4ee6a4SAndroid Build Coastguard Worker     Device,
23*bb4ee6a4SAndroid Build Coastguard Worker     Function,
24*bb4ee6a4SAndroid Build Coastguard Worker }
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker /// PCI address parsing and conversion errors.
27*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug, PartialEq, Eq)]
28*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
29*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
30*bb4ee6a4SAndroid Build Coastguard Worker     /// The specified component was outside the valid range.
31*bb4ee6a4SAndroid Build Coastguard Worker     #[error("{0:?} out of range")]
32*bb4ee6a4SAndroid Build Coastguard Worker     ComponentOutOfRange(PciAddressComponent),
33*bb4ee6a4SAndroid Build Coastguard Worker     /// The specified component could not be parsed as a hexadecimal number.
34*bb4ee6a4SAndroid Build Coastguard Worker     #[error("{0:?} failed to parse as hex")]
35*bb4ee6a4SAndroid Build Coastguard Worker     InvalidHex(PciAddressComponent),
36*bb4ee6a4SAndroid Build Coastguard Worker     /// The given PCI device path is invalid
37*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Invalid PCI device path")]
38*bb4ee6a4SAndroid Build Coastguard Worker     InvalidHostPath,
39*bb4ee6a4SAndroid Build Coastguard Worker     /// A delimiter (`:` or `.`) between the two specified components was missing or incorrect.
40*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Missing delimiter between {0:?} and {1:?}")]
41*bb4ee6a4SAndroid Build Coastguard Worker     MissingDelimiter(PciAddressComponent, PciAddressComponent),
42*bb4ee6a4SAndroid Build Coastguard Worker     /// The PCI address contained more than the expected number of components.
43*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Too many components in PCI address")]
44*bb4ee6a4SAndroid Build Coastguard Worker     TooManyComponents,
45*bb4ee6a4SAndroid Build Coastguard Worker }
46*bb4ee6a4SAndroid Build Coastguard Worker 
47*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>;
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker /// PCI Device Address, AKA Bus:Device.Function
50*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
51*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciAddress {
52*bb4ee6a4SAndroid Build Coastguard Worker     /// Bus number, in the range `0..=255`.
53*bb4ee6a4SAndroid Build Coastguard Worker     pub bus: u8,
54*bb4ee6a4SAndroid Build Coastguard Worker     /// Device number, in the range `0..=31`.
55*bb4ee6a4SAndroid Build Coastguard Worker     pub dev: u8,
56*bb4ee6a4SAndroid Build Coastguard Worker     /// Function number, in the range `0..=7`.
57*bb4ee6a4SAndroid Build Coastguard Worker     pub func: u8,
58*bb4ee6a4SAndroid Build Coastguard Worker }
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker impl Serialize for PciAddress {
serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> where S: Serializer,61*bb4ee6a4SAndroid Build Coastguard Worker     fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
62*bb4ee6a4SAndroid Build Coastguard Worker     where
63*bb4ee6a4SAndroid Build Coastguard Worker         S: Serializer,
64*bb4ee6a4SAndroid Build Coastguard Worker     {
65*bb4ee6a4SAndroid Build Coastguard Worker         serializer.serialize_str(&self.to_string())
66*bb4ee6a4SAndroid Build Coastguard Worker     }
67*bb4ee6a4SAndroid Build Coastguard Worker }
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> Deserialize<'de> for PciAddress {
deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> where D: Deserializer<'de>,70*bb4ee6a4SAndroid Build Coastguard Worker     fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
71*bb4ee6a4SAndroid Build Coastguard Worker     where
72*bb4ee6a4SAndroid Build Coastguard Worker         D: Deserializer<'de>,
73*bb4ee6a4SAndroid Build Coastguard Worker     {
74*bb4ee6a4SAndroid Build Coastguard Worker         let s = String::deserialize(deserializer)?;
75*bb4ee6a4SAndroid Build Coastguard Worker         FromStr::from_str(&s).map_err(serde::de::Error::custom)
76*bb4ee6a4SAndroid Build Coastguard Worker     }
77*bb4ee6a4SAndroid Build Coastguard Worker }
78*bb4ee6a4SAndroid Build Coastguard Worker 
79*bb4ee6a4SAndroid Build Coastguard Worker /// Convert `PciAddress` to a human-readable string format.
80*bb4ee6a4SAndroid Build Coastguard Worker ///
81*bb4ee6a4SAndroid Build Coastguard Worker /// The display format will always include the domain component, even if it is zero.
82*bb4ee6a4SAndroid Build Coastguard Worker ///
83*bb4ee6a4SAndroid Build Coastguard Worker /// # Example
84*bb4ee6a4SAndroid Build Coastguard Worker ///
85*bb4ee6a4SAndroid Build Coastguard Worker /// ```
86*bb4ee6a4SAndroid Build Coastguard Worker /// use devices::PciAddress;
87*bb4ee6a4SAndroid Build Coastguard Worker ///
88*bb4ee6a4SAndroid Build Coastguard Worker /// let pci_address = PciAddress::new(0x0000, 0x03, 0x14, 0x1)?;
89*bb4ee6a4SAndroid Build Coastguard Worker /// assert_eq!(pci_address.to_string(), "0000:03:14.1");
90*bb4ee6a4SAndroid Build Coastguard Worker /// # Ok::<(), devices::PciAddressError>(())
91*bb4ee6a4SAndroid Build Coastguard Worker /// ```
92*bb4ee6a4SAndroid Build Coastguard Worker impl Display for PciAddress {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result93*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94*bb4ee6a4SAndroid Build Coastguard Worker         let domain = 0;
95*bb4ee6a4SAndroid Build Coastguard Worker         write!(
96*bb4ee6a4SAndroid Build Coastguard Worker             f,
97*bb4ee6a4SAndroid Build Coastguard Worker             "{:04x}:{:02x}:{:02x}.{:0x}",
98*bb4ee6a4SAndroid Build Coastguard Worker             domain, self.bus, self.dev, self.func,
99*bb4ee6a4SAndroid Build Coastguard Worker         )
100*bb4ee6a4SAndroid Build Coastguard Worker     }
101*bb4ee6a4SAndroid Build Coastguard Worker }
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker /// Construct `PciAddress` from string "\[domain:\]bus:device.function".
104*bb4ee6a4SAndroid Build Coastguard Worker /// Each component of the address is unprefixed hexadecimal.
105*bb4ee6a4SAndroid Build Coastguard Worker ///
106*bb4ee6a4SAndroid Build Coastguard Worker /// # Example
107*bb4ee6a4SAndroid Build Coastguard Worker ///
108*bb4ee6a4SAndroid Build Coastguard Worker /// ```
109*bb4ee6a4SAndroid Build Coastguard Worker /// use std::str::FromStr;
110*bb4ee6a4SAndroid Build Coastguard Worker /// use devices::PciAddress;
111*bb4ee6a4SAndroid Build Coastguard Worker ///
112*bb4ee6a4SAndroid Build Coastguard Worker /// let pci_address = PciAddress::from_str("d7:15.4")?;
113*bb4ee6a4SAndroid Build Coastguard Worker /// assert_eq!(pci_address.bus, 0xd7);
114*bb4ee6a4SAndroid Build Coastguard Worker /// assert_eq!(pci_address.dev, 0x15);
115*bb4ee6a4SAndroid Build Coastguard Worker /// assert_eq!(pci_address.func, 0x4);
116*bb4ee6a4SAndroid Build Coastguard Worker /// # Ok::<(), devices::PciAddressError>(())
117*bb4ee6a4SAndroid Build Coastguard Worker /// ```
118*bb4ee6a4SAndroid Build Coastguard Worker impl FromStr for PciAddress {
119*bb4ee6a4SAndroid Build Coastguard Worker     type Err = Error;
120*bb4ee6a4SAndroid Build Coastguard Worker 
from_str(address: &str) -> std::result::Result<Self, Self::Err>121*bb4ee6a4SAndroid Build Coastguard Worker     fn from_str(address: &str) -> std::result::Result<Self, Self::Err> {
122*bb4ee6a4SAndroid Build Coastguard Worker         let (dev_bus_domain, func) = address.rsplit_once('.').ok_or(Error::MissingDelimiter(
123*bb4ee6a4SAndroid Build Coastguard Worker             PciAddressComponent::Device,
124*bb4ee6a4SAndroid Build Coastguard Worker             PciAddressComponent::Function,
125*bb4ee6a4SAndroid Build Coastguard Worker         ))?;
126*bb4ee6a4SAndroid Build Coastguard Worker         let func = u32::from_str_radix(func, 16)
127*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|_| Error::InvalidHex(PciAddressComponent::Function))?;
128*bb4ee6a4SAndroid Build Coastguard Worker 
129*bb4ee6a4SAndroid Build Coastguard Worker         let (bus_domain, dev) = dev_bus_domain
130*bb4ee6a4SAndroid Build Coastguard Worker             .rsplit_once(':')
131*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingDelimiter(
132*bb4ee6a4SAndroid Build Coastguard Worker                 PciAddressComponent::Bus,
133*bb4ee6a4SAndroid Build Coastguard Worker                 PciAddressComponent::Device,
134*bb4ee6a4SAndroid Build Coastguard Worker             ))?;
135*bb4ee6a4SAndroid Build Coastguard Worker         let dev = u32::from_str_radix(dev, 16)
136*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|_| Error::InvalidHex(PciAddressComponent::Device))?;
137*bb4ee6a4SAndroid Build Coastguard Worker 
138*bb4ee6a4SAndroid Build Coastguard Worker         // Domain is optional; if unspecified, the rest of the string is the bus, and domain
139*bb4ee6a4SAndroid Build Coastguard Worker         // defaults to 0.
140*bb4ee6a4SAndroid Build Coastguard Worker         let (domain, bus) = bus_domain.rsplit_once(':').unwrap_or(("0", bus_domain));
141*bb4ee6a4SAndroid Build Coastguard Worker         let bus = u32::from_str_radix(bus, 16)
142*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|_| Error::InvalidHex(PciAddressComponent::Bus))?;
143*bb4ee6a4SAndroid Build Coastguard Worker 
144*bb4ee6a4SAndroid Build Coastguard Worker         if domain.contains(':') {
145*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::TooManyComponents);
146*bb4ee6a4SAndroid Build Coastguard Worker         }
147*bb4ee6a4SAndroid Build Coastguard Worker 
148*bb4ee6a4SAndroid Build Coastguard Worker         let domain = u32::from_str_radix(domain, 16)
149*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|_| Error::InvalidHex(PciAddressComponent::Domain))?;
150*bb4ee6a4SAndroid Build Coastguard Worker 
151*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(domain, bus, dev, func)
152*bb4ee6a4SAndroid Build Coastguard Worker     }
153*bb4ee6a4SAndroid Build Coastguard Worker }
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker impl PciAddress {
156*bb4ee6a4SAndroid Build Coastguard Worker     #[doc(hidden)]
157*bb4ee6a4SAndroid Build Coastguard Worker     const BUS_MASK: u32 = 0x00ff;
158*bb4ee6a4SAndroid Build Coastguard Worker     #[doc(hidden)]
159*bb4ee6a4SAndroid Build Coastguard Worker     const DEVICE_BITS_NUM: usize = 5;
160*bb4ee6a4SAndroid Build Coastguard Worker     #[doc(hidden)]
161*bb4ee6a4SAndroid Build Coastguard Worker     const DEVICE_MASK: u32 = 0x1f;
162*bb4ee6a4SAndroid Build Coastguard Worker     #[doc(hidden)]
163*bb4ee6a4SAndroid Build Coastguard Worker     const FUNCTION_BITS_NUM: usize = 3;
164*bb4ee6a4SAndroid Build Coastguard Worker     #[doc(hidden)]
165*bb4ee6a4SAndroid Build Coastguard Worker     const FUNCTION_MASK: u32 = 0x07;
166*bb4ee6a4SAndroid Build Coastguard Worker     #[doc(hidden)]
167*bb4ee6a4SAndroid Build Coastguard Worker     const REGISTER_OFFSET: usize = 2;
168*bb4ee6a4SAndroid Build Coastguard Worker 
169*bb4ee6a4SAndroid Build Coastguard Worker     /// Construct [`PciAddress`] from separate domain, bus, device, and function numbers.
170*bb4ee6a4SAndroid Build Coastguard Worker     ///
171*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
172*bb4ee6a4SAndroid Build Coastguard Worker     ///
173*bb4ee6a4SAndroid Build Coastguard Worker     /// * `domain` - The PCI domain number. Must be `0` in the current implementation.
174*bb4ee6a4SAndroid Build Coastguard Worker     /// * `bus` - The PCI bus number. Must be in the range `0..=255`.
175*bb4ee6a4SAndroid Build Coastguard Worker     /// * `dev` - The PCI device number. Must be in the range `0..=31`.
176*bb4ee6a4SAndroid Build Coastguard Worker     /// * `func` - The PCI function number. Must be in the range `0..=7`.
177*bb4ee6a4SAndroid Build Coastguard Worker     ///
178*bb4ee6a4SAndroid Build Coastguard Worker     /// # Errors
179*bb4ee6a4SAndroid Build Coastguard Worker     ///
180*bb4ee6a4SAndroid Build Coastguard Worker     /// If any component is out of the valid range, this function will return
181*bb4ee6a4SAndroid Build Coastguard Worker     /// [`Error::ComponentOutOfRange`].
new(domain: u32, bus: u32, dev: u32, func: u32) -> Result<Self>182*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(domain: u32, bus: u32, dev: u32, func: u32) -> Result<Self> {
183*bb4ee6a4SAndroid Build Coastguard Worker         if bus > Self::BUS_MASK {
184*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::ComponentOutOfRange(PciAddressComponent::Bus));
185*bb4ee6a4SAndroid Build Coastguard Worker         }
186*bb4ee6a4SAndroid Build Coastguard Worker 
187*bb4ee6a4SAndroid Build Coastguard Worker         if dev > Self::DEVICE_MASK {
188*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::ComponentOutOfRange(PciAddressComponent::Device));
189*bb4ee6a4SAndroid Build Coastguard Worker         }
190*bb4ee6a4SAndroid Build Coastguard Worker 
191*bb4ee6a4SAndroid Build Coastguard Worker         if func > Self::FUNCTION_MASK {
192*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::ComponentOutOfRange(PciAddressComponent::Function));
193*bb4ee6a4SAndroid Build Coastguard Worker         }
194*bb4ee6a4SAndroid Build Coastguard Worker 
195*bb4ee6a4SAndroid Build Coastguard Worker         // PciAddress does not store domain for now, so disallow anything other than domain 0.
196*bb4ee6a4SAndroid Build Coastguard Worker         if domain > 0 {
197*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::ComponentOutOfRange(PciAddressComponent::Domain));
198*bb4ee6a4SAndroid Build Coastguard Worker         }
199*bb4ee6a4SAndroid Build Coastguard Worker 
200*bb4ee6a4SAndroid Build Coastguard Worker         Ok(PciAddress {
201*bb4ee6a4SAndroid Build Coastguard Worker             bus: bus as u8,
202*bb4ee6a4SAndroid Build Coastguard Worker             dev: dev as u8,
203*bb4ee6a4SAndroid Build Coastguard Worker             func: func as u8,
204*bb4ee6a4SAndroid Build Coastguard Worker         })
205*bb4ee6a4SAndroid Build Coastguard Worker     }
206*bb4ee6a4SAndroid Build Coastguard Worker 
207*bb4ee6a4SAndroid Build Coastguard Worker     /// Decode a [`PciAddress`] and register index from a CONFIG_ADDRESS value.
208*bb4ee6a4SAndroid Build Coastguard Worker     ///
209*bb4ee6a4SAndroid Build Coastguard Worker     /// The configuration address should be in the format used with the PCI CAM or ECAM
210*bb4ee6a4SAndroid Build Coastguard Worker     /// configuration space access mechanisms, with the lowest bits encoding a register index and
211*bb4ee6a4SAndroid Build Coastguard Worker     /// the bits above that encoding the PCI function (3 bits), device (5 bits), and bus (8 bits).
212*bb4ee6a4SAndroid Build Coastguard Worker     /// The low two bits of the configuration address, which are technically part of the register
213*bb4ee6a4SAndroid Build Coastguard Worker     /// number, are ignored, since PCI configuration space accesses must be DWORD (4-byte) aligned.
214*bb4ee6a4SAndroid Build Coastguard Worker     ///
215*bb4ee6a4SAndroid Build Coastguard Worker     /// On success, returns a [`PciAddress`] and the extracted register index in DWORDs.
216*bb4ee6a4SAndroid Build Coastguard Worker     ///
217*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
218*bb4ee6a4SAndroid Build Coastguard Worker     ///
219*bb4ee6a4SAndroid Build Coastguard Worker     /// * `config_address` - The PCI configuration address.
220*bb4ee6a4SAndroid Build Coastguard Worker     /// * `register_bits_num` - The size of the register value in bits.
221*bb4ee6a4SAndroid Build Coastguard Worker     ///
222*bb4ee6a4SAndroid Build Coastguard Worker     /// # Example
223*bb4ee6a4SAndroid Build Coastguard Worker     ///
224*bb4ee6a4SAndroid Build Coastguard Worker     /// ```
225*bb4ee6a4SAndroid Build Coastguard Worker     /// use devices::PciAddress;
226*bb4ee6a4SAndroid Build Coastguard Worker     ///
227*bb4ee6a4SAndroid Build Coastguard Worker     /// let (pci_address, register_index) = PciAddress::from_config_address(0x32a354, 8);
228*bb4ee6a4SAndroid Build Coastguard Worker     /// assert_eq!(pci_address.bus, 0x32);
229*bb4ee6a4SAndroid Build Coastguard Worker     /// assert_eq!(pci_address.dev, 0x14);
230*bb4ee6a4SAndroid Build Coastguard Worker     /// assert_eq!(pci_address.func, 0x3);
231*bb4ee6a4SAndroid Build Coastguard Worker     /// assert_eq!(register_index, 0x15);
232*bb4ee6a4SAndroid Build Coastguard Worker     /// ```
from_config_address(config_address: u32, register_bits_num: usize) -> (Self, usize)233*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_config_address(config_address: u32, register_bits_num: usize) -> (Self, usize) {
234*bb4ee6a4SAndroid Build Coastguard Worker         let bus_offset = register_bits_num + Self::FUNCTION_BITS_NUM + Self::DEVICE_BITS_NUM;
235*bb4ee6a4SAndroid Build Coastguard Worker         let bus = ((config_address >> bus_offset) & Self::BUS_MASK) as u8;
236*bb4ee6a4SAndroid Build Coastguard Worker         let dev_offset = register_bits_num + Self::FUNCTION_BITS_NUM;
237*bb4ee6a4SAndroid Build Coastguard Worker         let dev = ((config_address >> dev_offset) & Self::DEVICE_MASK) as u8;
238*bb4ee6a4SAndroid Build Coastguard Worker         let func = ((config_address >> register_bits_num) & Self::FUNCTION_MASK) as u8;
239*bb4ee6a4SAndroid Build Coastguard Worker         let register_mask: u32 = (1_u32 << (register_bits_num - Self::REGISTER_OFFSET)) - 1;
240*bb4ee6a4SAndroid Build Coastguard Worker         let register = ((config_address >> Self::REGISTER_OFFSET) & register_mask) as usize;
241*bb4ee6a4SAndroid Build Coastguard Worker 
242*bb4ee6a4SAndroid Build Coastguard Worker         (PciAddress { bus, dev, func }, register)
243*bb4ee6a4SAndroid Build Coastguard Worker     }
244*bb4ee6a4SAndroid Build Coastguard Worker 
245*bb4ee6a4SAndroid Build Coastguard Worker     /// Construct [`PciAddress`] from a system PCI path
246*bb4ee6a4SAndroid Build Coastguard Worker     ///
247*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
248*bb4ee6a4SAndroid Build Coastguard Worker     ///
249*bb4ee6a4SAndroid Build Coastguard Worker     /// * `path` - The system PCI path. The file name of this path must be a valid PCI address.
250*bb4ee6a4SAndroid Build Coastguard Worker     ///
251*bb4ee6a4SAndroid Build Coastguard Worker     /// # Errors
252*bb4ee6a4SAndroid Build Coastguard Worker     ///
253*bb4ee6a4SAndroid Build Coastguard Worker     /// If the path given is invalid or filename is an invalid PCI address, this function will
254*bb4ee6a4SAndroid Build Coastguard Worker     /// return error.
from_path(path: &Path) -> Result<Self>255*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_path(path: &Path) -> Result<Self> {
256*bb4ee6a4SAndroid Build Coastguard Worker         let os_str = path.file_name().ok_or(Error::InvalidHostPath)?;
257*bb4ee6a4SAndroid Build Coastguard Worker         let pci_str = os_str.to_str().ok_or(Error::InvalidHostPath)?;
258*bb4ee6a4SAndroid Build Coastguard Worker         PciAddress::from_str(pci_str)
259*bb4ee6a4SAndroid Build Coastguard Worker     }
260*bb4ee6a4SAndroid Build Coastguard Worker 
261*bb4ee6a4SAndroid Build Coastguard Worker     /// Encode [`PciAddress`] into CONFIG_ADDRESS value.
262*bb4ee6a4SAndroid Build Coastguard Worker     ///
263*bb4ee6a4SAndroid Build Coastguard Worker     /// See [`PciAddress::from_config_address()`] for details of the encoding.
264*bb4ee6a4SAndroid Build Coastguard Worker     ///
265*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
266*bb4ee6a4SAndroid Build Coastguard Worker     ///
267*bb4ee6a4SAndroid Build Coastguard Worker     /// * `register` - The register index in DWORDs.
268*bb4ee6a4SAndroid Build Coastguard Worker     /// * `register_bits_num` - The width of the register field, not including the two lowest bits.
269*bb4ee6a4SAndroid Build Coastguard Worker     ///
270*bb4ee6a4SAndroid Build Coastguard Worker     /// # Example
271*bb4ee6a4SAndroid Build Coastguard Worker     ///
272*bb4ee6a4SAndroid Build Coastguard Worker     /// ```
273*bb4ee6a4SAndroid Build Coastguard Worker     /// use devices::PciAddress;
274*bb4ee6a4SAndroid Build Coastguard Worker     ///
275*bb4ee6a4SAndroid Build Coastguard Worker     /// let pci_address = PciAddress::new(0x0000, 0x32, 0x14, 0x3)?;
276*bb4ee6a4SAndroid Build Coastguard Worker     /// let config_address = pci_address.to_config_address(0x15, 8);
277*bb4ee6a4SAndroid Build Coastguard Worker     /// assert_eq!(config_address, 0x32a354);
278*bb4ee6a4SAndroid Build Coastguard Worker     /// # Ok::<(), devices::PciAddressError>(())
279*bb4ee6a4SAndroid Build Coastguard Worker     /// ```
to_config_address(&self, register: usize, register_bits_num: usize) -> u32280*bb4ee6a4SAndroid Build Coastguard Worker     pub fn to_config_address(&self, register: usize, register_bits_num: usize) -> u32 {
281*bb4ee6a4SAndroid Build Coastguard Worker         let bus_offset = register_bits_num + Self::FUNCTION_BITS_NUM + Self::DEVICE_BITS_NUM;
282*bb4ee6a4SAndroid Build Coastguard Worker         let dev_offset = register_bits_num + Self::FUNCTION_BITS_NUM;
283*bb4ee6a4SAndroid Build Coastguard Worker         let register_mask: u32 = (1_u32 << (register_bits_num - Self::REGISTER_OFFSET)) - 1;
284*bb4ee6a4SAndroid Build Coastguard Worker         ((Self::BUS_MASK & self.bus as u32) << bus_offset)
285*bb4ee6a4SAndroid Build Coastguard Worker             | ((Self::DEVICE_MASK & self.dev as u32) << dev_offset)
286*bb4ee6a4SAndroid Build Coastguard Worker             | ((Self::FUNCTION_MASK & self.func as u32) << register_bits_num)
287*bb4ee6a4SAndroid Build Coastguard Worker             | ((register_mask & register as u32) << Self::REGISTER_OFFSET)
288*bb4ee6a4SAndroid Build Coastguard Worker     }
289*bb4ee6a4SAndroid Build Coastguard Worker 
290*bb4ee6a4SAndroid Build Coastguard Worker     /// Convert B:D:F PCI address to unsigned 32 bit integer.
291*bb4ee6a4SAndroid Build Coastguard Worker     ///
292*bb4ee6a4SAndroid Build Coastguard Worker     /// The bus, device, and function numbers are packed into an integer as follows:
293*bb4ee6a4SAndroid Build Coastguard Worker     ///
294*bb4ee6a4SAndroid Build Coastguard Worker     /// | Bits 15-8 | Bits 7-3 | Bits 2-0 |
295*bb4ee6a4SAndroid Build Coastguard Worker     /// |-----------|----------|----------|
296*bb4ee6a4SAndroid Build Coastguard Worker     /// |    Bus    |  Device  | Function |
to_u32(&self) -> u32297*bb4ee6a4SAndroid Build Coastguard Worker     pub fn to_u32(&self) -> u32 {
298*bb4ee6a4SAndroid Build Coastguard Worker         ((Self::BUS_MASK & self.bus as u32) << (Self::FUNCTION_BITS_NUM + Self::DEVICE_BITS_NUM))
299*bb4ee6a4SAndroid Build Coastguard Worker             | ((Self::DEVICE_MASK & self.dev as u32) << Self::FUNCTION_BITS_NUM)
300*bb4ee6a4SAndroid Build Coastguard Worker             | (Self::FUNCTION_MASK & self.func as u32)
301*bb4ee6a4SAndroid Build Coastguard Worker     }
302*bb4ee6a4SAndroid Build Coastguard Worker 
303*bb4ee6a4SAndroid Build Coastguard Worker     /// Convert D:F PCI address to a linux style devfn.
304*bb4ee6a4SAndroid Build Coastguard Worker     ///
305*bb4ee6a4SAndroid Build Coastguard Worker     /// The device and function numbers are packed into an u8 as follows:
306*bb4ee6a4SAndroid Build Coastguard Worker     ///
307*bb4ee6a4SAndroid Build Coastguard Worker     /// | Bits 7-3 | Bits 2-0 |
308*bb4ee6a4SAndroid Build Coastguard Worker     /// |----------|----------|
309*bb4ee6a4SAndroid Build Coastguard Worker     /// |  Device  | Function |
devfn(&self) -> u8310*bb4ee6a4SAndroid Build Coastguard Worker     pub fn devfn(&self) -> u8 {
311*bb4ee6a4SAndroid Build Coastguard Worker         (self.dev << Self::FUNCTION_BITS_NUM) | self.func
312*bb4ee6a4SAndroid Build Coastguard Worker     }
313*bb4ee6a4SAndroid Build Coastguard Worker 
314*bb4ee6a4SAndroid Build Coastguard Worker     /// Convert D:F PCI address to an ACPI _ADR.
315*bb4ee6a4SAndroid Build Coastguard Worker     ///
316*bb4ee6a4SAndroid Build Coastguard Worker     /// The device and function numbers are packed into an u32 as follows:
317*bb4ee6a4SAndroid Build Coastguard Worker     ///
318*bb4ee6a4SAndroid Build Coastguard Worker     /// | Bits 31-16 | Bits 15-0 |
319*bb4ee6a4SAndroid Build Coastguard Worker     /// |------------|-----------|
320*bb4ee6a4SAndroid Build Coastguard Worker     /// |   Device   | Function  |
acpi_adr(&self) -> u32321*bb4ee6a4SAndroid Build Coastguard Worker     pub fn acpi_adr(&self) -> u32 {
322*bb4ee6a4SAndroid Build Coastguard Worker         ((Self::DEVICE_MASK & self.dev as u32) << 16) | (Self::FUNCTION_MASK & self.func as u32)
323*bb4ee6a4SAndroid Build Coastguard Worker     }
324*bb4ee6a4SAndroid Build Coastguard Worker 
325*bb4ee6a4SAndroid Build Coastguard Worker     /// Convert B:D:F PCI address to a PCI PME Requester ID.
326*bb4ee6a4SAndroid Build Coastguard Worker     ///
327*bb4ee6a4SAndroid Build Coastguard Worker     /// The output is identical to `to_u32()` except that only the lower 16 bits are needed
pme_requester_id(&self) -> u16328*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pme_requester_id(&self) -> u16 {
329*bb4ee6a4SAndroid Build Coastguard Worker         self.to_u32() as u16
330*bb4ee6a4SAndroid Build Coastguard Worker     }
331*bb4ee6a4SAndroid Build Coastguard Worker 
332*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if the address points to PCI root host-bridge.
333*bb4ee6a4SAndroid Build Coastguard Worker     ///
334*bb4ee6a4SAndroid Build Coastguard Worker     /// This is true if and only if this is the all-zero address (`00:0.0`).
is_root(&self) -> bool335*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_root(&self) -> bool {
336*bb4ee6a4SAndroid Build Coastguard Worker         matches!(
337*bb4ee6a4SAndroid Build Coastguard Worker             &self,
338*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress {
339*bb4ee6a4SAndroid Build Coastguard Worker                 bus: 0,
340*bb4ee6a4SAndroid Build Coastguard Worker                 dev: 0,
341*bb4ee6a4SAndroid Build Coastguard Worker                 func: 0
342*bb4ee6a4SAndroid Build Coastguard Worker             }
343*bb4ee6a4SAndroid Build Coastguard Worker         )
344*bb4ee6a4SAndroid Build Coastguard Worker     }
345*bb4ee6a4SAndroid Build Coastguard Worker }
346*bb4ee6a4SAndroid Build Coastguard Worker 
347*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
348*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
349*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
350*bb4ee6a4SAndroid Build Coastguard Worker 
351*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string()352*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string() {
353*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
354*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0000:00:00.0").unwrap(),
355*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress {
356*bb4ee6a4SAndroid Build Coastguard Worker                 bus: 0,
357*bb4ee6a4SAndroid Build Coastguard Worker                 dev: 0,
358*bb4ee6a4SAndroid Build Coastguard Worker                 func: 0
359*bb4ee6a4SAndroid Build Coastguard Worker             }
360*bb4ee6a4SAndroid Build Coastguard Worker         );
361*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
362*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("00:00.0").unwrap(),
363*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress {
364*bb4ee6a4SAndroid Build Coastguard Worker                 bus: 0,
365*bb4ee6a4SAndroid Build Coastguard Worker                 dev: 0,
366*bb4ee6a4SAndroid Build Coastguard Worker                 func: 0
367*bb4ee6a4SAndroid Build Coastguard Worker             }
368*bb4ee6a4SAndroid Build Coastguard Worker         );
369*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
370*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("01:02.3").unwrap(),
371*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress {
372*bb4ee6a4SAndroid Build Coastguard Worker                 bus: 1,
373*bb4ee6a4SAndroid Build Coastguard Worker                 dev: 2,
374*bb4ee6a4SAndroid Build Coastguard Worker                 func: 3
375*bb4ee6a4SAndroid Build Coastguard Worker             }
376*bb4ee6a4SAndroid Build Coastguard Worker         );
377*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
378*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("ff:1f.7").unwrap(),
379*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress {
380*bb4ee6a4SAndroid Build Coastguard Worker                 bus: 0xff,
381*bb4ee6a4SAndroid Build Coastguard Worker                 dev: 0x1f,
382*bb4ee6a4SAndroid Build Coastguard Worker                 func: 7,
383*bb4ee6a4SAndroid Build Coastguard Worker             }
384*bb4ee6a4SAndroid Build Coastguard Worker         );
385*bb4ee6a4SAndroid Build Coastguard Worker     }
386*bb4ee6a4SAndroid Build Coastguard Worker 
387*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_missing_func_delim()388*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_missing_func_delim() {
389*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
390*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("1").expect_err("parse should fail"),
391*bb4ee6a4SAndroid Build Coastguard Worker             Error::MissingDelimiter(PciAddressComponent::Device, PciAddressComponent::Function)
392*bb4ee6a4SAndroid Build Coastguard Worker         );
393*bb4ee6a4SAndroid Build Coastguard Worker     }
394*bb4ee6a4SAndroid Build Coastguard Worker 
395*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_missing_dev_delim()396*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_missing_dev_delim() {
397*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
398*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("2.1").expect_err("parse should fail"),
399*bb4ee6a4SAndroid Build Coastguard Worker             Error::MissingDelimiter(PciAddressComponent::Bus, PciAddressComponent::Device)
400*bb4ee6a4SAndroid Build Coastguard Worker         );
401*bb4ee6a4SAndroid Build Coastguard Worker     }
402*bb4ee6a4SAndroid Build Coastguard Worker 
403*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_extra_components()404*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_extra_components() {
405*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
406*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0:0:0:0.0").expect_err("parse should fail"),
407*bb4ee6a4SAndroid Build Coastguard Worker             Error::TooManyComponents
408*bb4ee6a4SAndroid Build Coastguard Worker         );
409*bb4ee6a4SAndroid Build Coastguard Worker     }
410*bb4ee6a4SAndroid Build Coastguard Worker 
411*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_invalid_func_hex()412*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_invalid_func_hex() {
413*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
414*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0000:00:00.g").expect_err("parse should fail"),
415*bb4ee6a4SAndroid Build Coastguard Worker             Error::InvalidHex(PciAddressComponent::Function)
416*bb4ee6a4SAndroid Build Coastguard Worker         );
417*bb4ee6a4SAndroid Build Coastguard Worker     }
418*bb4ee6a4SAndroid Build Coastguard Worker 
419*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_invalid_func_range()420*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_invalid_func_range() {
421*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
422*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0000:00:00.8").expect_err("parse should fail"),
423*bb4ee6a4SAndroid Build Coastguard Worker             Error::ComponentOutOfRange(PciAddressComponent::Function)
424*bb4ee6a4SAndroid Build Coastguard Worker         );
425*bb4ee6a4SAndroid Build Coastguard Worker     }
426*bb4ee6a4SAndroid Build Coastguard Worker 
427*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_invalid_dev_hex()428*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_invalid_dev_hex() {
429*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
430*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0000:00:gg.0").expect_err("parse should fail"),
431*bb4ee6a4SAndroid Build Coastguard Worker             Error::InvalidHex(PciAddressComponent::Device)
432*bb4ee6a4SAndroid Build Coastguard Worker         );
433*bb4ee6a4SAndroid Build Coastguard Worker     }
434*bb4ee6a4SAndroid Build Coastguard Worker 
435*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_invalid_dev_range()436*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_invalid_dev_range() {
437*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
438*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0000:00:20.0").expect_err("parse should fail"),
439*bb4ee6a4SAndroid Build Coastguard Worker             Error::ComponentOutOfRange(PciAddressComponent::Device)
440*bb4ee6a4SAndroid Build Coastguard Worker         );
441*bb4ee6a4SAndroid Build Coastguard Worker     }
442*bb4ee6a4SAndroid Build Coastguard Worker 
443*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_invalid_bus_hex()444*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_invalid_bus_hex() {
445*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
446*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0000:gg:00.0").expect_err("parse should fail"),
447*bb4ee6a4SAndroid Build Coastguard Worker             Error::InvalidHex(PciAddressComponent::Bus)
448*bb4ee6a4SAndroid Build Coastguard Worker         );
449*bb4ee6a4SAndroid Build Coastguard Worker     }
450*bb4ee6a4SAndroid Build Coastguard Worker 
451*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_invalid_bus_range()452*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_invalid_bus_range() {
453*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
454*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0000:100:00.0").expect_err("parse should fail"),
455*bb4ee6a4SAndroid Build Coastguard Worker             Error::ComponentOutOfRange(PciAddressComponent::Bus)
456*bb4ee6a4SAndroid Build Coastguard Worker         );
457*bb4ee6a4SAndroid Build Coastguard Worker     }
458*bb4ee6a4SAndroid Build Coastguard Worker 
459*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_invalid_domain_hex()460*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_invalid_domain_hex() {
461*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
462*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("gggg:00:00.0").expect_err("parse should fail"),
463*bb4ee6a4SAndroid Build Coastguard Worker             Error::InvalidHex(PciAddressComponent::Domain)
464*bb4ee6a4SAndroid Build Coastguard Worker         );
465*bb4ee6a4SAndroid Build Coastguard Worker     }
466*bb4ee6a4SAndroid Build Coastguard Worker 
467*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
from_string_invalid_domain_range()468*bb4ee6a4SAndroid Build Coastguard Worker     fn from_string_invalid_domain_range() {
469*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
470*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::from_str("0001:00:00.0").expect_err("parse should fail"),
471*bb4ee6a4SAndroid Build Coastguard Worker             Error::ComponentOutOfRange(PciAddressComponent::Domain)
472*bb4ee6a4SAndroid Build Coastguard Worker         );
473*bb4ee6a4SAndroid Build Coastguard Worker     }
474*bb4ee6a4SAndroid Build Coastguard Worker 
475*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
format_simple()476*bb4ee6a4SAndroid Build Coastguard Worker     fn format_simple() {
477*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
478*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::new(0, 1, 2, 3).unwrap().to_string(),
479*bb4ee6a4SAndroid Build Coastguard Worker             "0000:01:02.3"
480*bb4ee6a4SAndroid Build Coastguard Worker         );
481*bb4ee6a4SAndroid Build Coastguard Worker     }
482*bb4ee6a4SAndroid Build Coastguard Worker 
483*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
format_max()484*bb4ee6a4SAndroid Build Coastguard Worker     fn format_max() {
485*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
486*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress::new(0, 0xff, 0x1f, 7).unwrap().to_string(),
487*bb4ee6a4SAndroid Build Coastguard Worker             "0000:ff:1f.7"
488*bb4ee6a4SAndroid Build Coastguard Worker         );
489*bb4ee6a4SAndroid Build Coastguard Worker     }
490*bb4ee6a4SAndroid Build Coastguard Worker 
491*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
serialize_json()492*bb4ee6a4SAndroid Build Coastguard Worker     fn serialize_json() {
493*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
494*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::to_string(&PciAddress::new(0, 0xa5, 0x1f, 3).unwrap()).unwrap(),
495*bb4ee6a4SAndroid Build Coastguard Worker             "\"0000:a5:1f.3\""
496*bb4ee6a4SAndroid Build Coastguard Worker         );
497*bb4ee6a4SAndroid Build Coastguard Worker     }
498*bb4ee6a4SAndroid Build Coastguard Worker 
499*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
deserialize_json()500*bb4ee6a4SAndroid Build Coastguard Worker     fn deserialize_json() {
501*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
502*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::from_str::<PciAddress>("\"0000:a5:1f.3\"").unwrap(),
503*bb4ee6a4SAndroid Build Coastguard Worker             PciAddress {
504*bb4ee6a4SAndroid Build Coastguard Worker                 bus: 0xa5,
505*bb4ee6a4SAndroid Build Coastguard Worker                 dev: 0x1f,
506*bb4ee6a4SAndroid Build Coastguard Worker                 func: 3,
507*bb4ee6a4SAndroid Build Coastguard Worker             }
508*bb4ee6a4SAndroid Build Coastguard Worker         );
509*bb4ee6a4SAndroid Build Coastguard Worker     }
510*bb4ee6a4SAndroid Build Coastguard Worker }
511