1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 extern "C"
20 {
21 #include <pciaccess.h>
22 } // extern "C"
23 
24 #include <cstdint>
25 
26 namespace host_tool
27 {
28 
29 /**
30  * @class PciAccess
31  * @brief Overridable interface to libpciacess for unit testing
32  */
33 class PciAccess
34 {
35   public:
36     virtual struct pci_device_iterator* pci_id_match_iterator_create(
37         const struct pci_id_match* match) const = 0;
38     virtual void
39         pci_iterator_destroy(struct pci_device_iterator* iter) const = 0;
40     virtual struct pci_device*
41         pci_device_next(struct pci_device_iterator* iter) const = 0;
42     virtual int pci_device_probe(struct pci_device* dev) const = 0;
43     virtual int pci_device_cfg_read_u8(struct pci_device* dev,
44                                        std::uint8_t* data,
45                                        pciaddr_t offset) const = 0;
46     virtual int pci_device_cfg_write_u8(struct pci_device* dev,
47                                         std::uint8_t data,
48                                         pciaddr_t offset) const = 0;
49     virtual int pci_device_map_range(struct pci_device* dev, pciaddr_t base,
50                                      pciaddr_t size, unsigned map_flags,
51                                      void** addr) const = 0;
52     virtual int pci_device_unmap_range(struct pci_device* dev, void* memory,
53                                        pciaddr_t size) const = 0;
54 
55     virtual ~PciAccess() = default;
56 };
57 
58 /**
59  * @class PciAccessImpl
60  * @brief libpciaccess concrete implementation
61  * @details Passes through all calls to the underlying library.
62  */
63 class PciAccessImpl : public PciAccess
64 {
65   public:
66     struct pci_device_iterator* pci_id_match_iterator_create(
67         const struct pci_id_match* match) const override;
68     void pci_iterator_destroy(struct pci_device_iterator* iter) const override;
69     struct pci_device*
70         pci_device_next(struct pci_device_iterator* iter) const override;
71     int pci_device_probe(struct pci_device* dev) const override;
72     int pci_device_cfg_read_u8(struct pci_device* dev, std::uint8_t* data,
73                                pciaddr_t offset) const override;
74     int pci_device_cfg_write_u8(struct pci_device* dev, std::uint8_t data,
75                                 pciaddr_t offset) const override;
76     int pci_device_map_range(struct pci_device* dev, pciaddr_t base,
77                              pciaddr_t size, unsigned map_flags,
78                              void** addr) const override;
79     int pci_device_unmap_range(struct pci_device* dev, void* memory,
80                                pciaddr_t size) const override;
81 
82     static PciAccessImpl& getInstance()
83     {
84         static PciAccessImpl instance;
85         return instance;
86     }
87 
88   private:
89     PciAccessImpl();
90     virtual ~PciAccessImpl();
91 };
92 
93 } // namespace host_tool
94