1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <ddk/device.h>
8 #include <ddk/protocol/test.h>
9 #include <ddktl/device.h>
10 #include <ddktl/protocol/ethernet.h>
11 #include <ddktl/protocol/test.h>
12 #include <zircon/compiler.h>
13 #include <zircon/types.h>
14 #include <zircon/device/ethertap.h>
15 #include <lib/zx/socket.h>
16 #include <fbl/mutex.h>
17 #include <fbl/unique_ptr.h>
18 #include <threads.h>
19 
20 namespace eth {
21 
22 class TapCtl : public ddk::Device<TapCtl, ddk::Ioctlable> {
23   public:
24     TapCtl(zx_device_t* device);
25 
26     void DdkRelease();
27     zx_status_t DdkIoctl(uint32_t op, const void* in_buf, size_t in_len, void* out_buf,
28                          size_t out_len, size_t* out_actual);
29 };
30 
31 class TapDevice : public ddk::Device<TapDevice, ddk::Unbindable>,
32                   public ddk::EthmacProtocol<TapDevice, ddk::base_protocol> {
33   public:
34     TapDevice(zx_device_t* device, const ethertap_ioctl_config* config, zx::socket data);
35 
36     void DdkRelease();
37     void DdkUnbind();
38 
39     zx_status_t EthmacQuery(uint32_t options, ethmac_info_t* info);
40     void EthmacStop();
41     zx_status_t EthmacStart(const ethmac_ifc_t* ifc);
42     zx_status_t EthmacQueueTx(uint32_t options, ethmac_netbuf_t* netbuf);
43     zx_status_t EthmacSetParam(uint32_t param, int32_t value, const void* data,
44                                   size_t data_size);
45     // No DMA capability, so return invalid handle for get_bti
46     void EthmacGetBti(zx::bti* bti);
47     int Thread();
48 
49   private:
50     zx_status_t UpdateLinkStatus(zx_signals_t observed);
51     zx_status_t Recv(uint8_t* buffer, uint32_t capacity);
52 
53     // ethertap options
54     uint32_t options_ = 0;
55 
56     // ethermac fields
57     uint32_t features_ = 0;
58     uint32_t mtu_ = 0;
59     uint8_t mac_[6] = {};
60 
61     fbl::Mutex lock_;
62     bool dead_ = false;
63     ddk::EthmacIfcClient ethmac_client_ __TA_GUARDED(lock_);
64 
65     // Only accessed from Thread, so not locked.
66     bool online_ = false;
67     zx::socket data_;
68 
69     thrd_t thread_;
70 };
71 
72 }  // namespace eth
73