1 // Copyright 2018 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 <fbl/unique_fd.h> 8 #include <map> 9 #include <poll.h> 10 #include <set> 11 #include <vector> 12 13 #include "usb-handler.h" 14 15 namespace xdc { 16 17 class Client { 18 public: Client(int fd)19 explicit Client(int fd) 20 : fd_(fd) {} 21 22 void SetStreamId(uint32_t stream_id); 23 void SetConnected(bool connected); 24 // Returns whether the set of client events we are polling for has changed. 25 bool UpdatePollState(bool usb_writable); 26 27 // Queues a completed read transfer to be written to the client. 28 void AddCompletedRead(std::unique_ptr<UsbHandler::Transfer> transfer); 29 // Writes data from completed read transfers to the client until there are 30 // no transfers left, or the client is currently unavailable to accept data. 31 void ProcessCompletedReads(const std::unique_ptr<UsbHandler>& usb_handler); 32 // Writes data read from the client to the usb handler. 33 zx_status_t ProcessWrites(const std::unique_ptr<UsbHandler>& usb_handler); 34 // Returns any unused transfers to the usb handler. 35 void ReturnTransfers(const std::unique_ptr<UsbHandler>& usb_handler); 36 fd()37 int fd() const { return fd_.get(); } 38 // Returns the set of client events we should poll for. events()39 short events() const { return events_; } registered()40 bool registered() const { return registered_; } stream_id()41 uint32_t stream_id() const { return stream_id_; } connected()42 bool connected() const { return connected_; } 43 // Returns true if we have read data from the client not yet sent to the usb handler. has_write_data()44 bool has_write_data() const { return pending_write_ && pending_write_->request_length() > 0; } 45 46 private: 47 fbl::unique_fd fd_; 48 49 short events_ = 0; 50 51 // Whether the client has registered a stream id. 52 bool registered_ = false; 53 uint32_t stream_id_ = 0; 54 // True if the client has registered a stream id, 55 // and that stream id is also registered on the xdc device side. 56 bool connected_ = false; 57 58 std::vector<std::unique_ptr<UsbHandler::Transfer>> completed_reads_; 59 // Data read from the client, to be sent to the usb handler. 60 std::unique_ptr<UsbHandler::Transfer> pending_write_; 61 }; 62 63 class XdcServer { 64 // This is required by the XdcServer constructor, to stop clients calling it directly. 65 struct ConstructorTag { 66 explicit ConstructorTag() = default; 67 }; 68 69 public: 70 // Create should be called instead. This is public for make_unique. XdcServer(ConstructorTag tag)71 XdcServer(ConstructorTag tag) {} 72 73 static std::unique_ptr<XdcServer> Create(); 74 void Run(); 75 76 private: 77 bool Init(); 78 79 void UpdateClientPollEvents(); 80 81 // Updates poll_fds_ with any newly added or removed usb handler fds. 82 void UpdateUsbHandlerFds(); 83 84 // Processes new client connections on the server socket. 85 void ClientConnect(); 86 87 // Returns whether registration succeeded. 88 bool RegisterStream(std::shared_ptr<Client> client); 89 90 // Returns the client registered to the given stream id, or nullptr if none was found. 91 std::shared_ptr<Client> GetClient(uint32_t stream_id); 92 93 void UsbReadComplete(std::unique_ptr<UsbHandler::Transfer> transfer); 94 // Parses the control message from the given transfer buffer. 95 void HandleCtrlMsg(unsigned char* transfer_buf, int transfer_len); 96 97 // Sends a control message the to the xdc device with whether a stream has gone on / offline. 98 // If the message cannot currently be sent, it is queued to be retried later. 99 void NotifyStreamState(uint32_t stream_id, bool online); 100 bool SendCtrlMsg(xdc_msg_t& msg); 101 void SendQueuedCtrlMsgs(); 102 103 std::unique_ptr<UsbHandler> usb_handler_; 104 105 // Server socket we receive client connections on. 106 fbl::unique_fd socket_fd_; 107 // File lock acquired to ensure we don't unlink the socket of a running xdc server instance. 108 fbl::unique_fd socket_lock_fd_; 109 110 // Maps from client socket file descriptor to client. 111 std::map<int, std::shared_ptr<Client>> clients_; 112 113 // File descriptors we are currently polling on. 114 std::vector<pollfd> poll_fds_; 115 116 // Stream ids registered on the xdc device side. 117 std::set<uint32_t> dev_stream_ids_; 118 119 std::vector<xdc_msg_t> queued_ctrl_msgs_; 120 121 xdc_packet_state_t read_packet_state_; 122 }; 123 124 } // namespace xdc 125