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 <xdc-server-utils/packet.h> 8 #include <zircon/types.h> 9 10 #include <map> 11 #include <set> 12 #include <vector> 13 14 namespace xdc { 15 16 class UsbHandler { 17 // This is required by the UsbHandler constructor, to stop clients calling it directly. 18 struct ConstructorTag { 19 explicit ConstructorTag() = default; 20 }; 21 22 public: 23 class Transfer { 24 public: 25 static constexpr const size_t BUFFER_SIZE = 16 * 1024; 26 static constexpr const size_t HEADER_SIZE = sizeof(xdc_packet_header_t); 27 28 static constexpr const size_t MAX_WRITE_DATA_SIZE = BUFFER_SIZE - HEADER_SIZE; 29 30 // Create should be called instead. This is public for make_shared. Transfer(ConstructorTag tag)31 explicit Transfer(ConstructorTag tag) {} 32 33 // Sets the header of the transfer. 34 // Returns ZX_OK on success, or ZX_ERR_INVALID_ARGS if data_len is larger than 35 // MAX_WRITE_DATA_SIZE. 36 zx_status_t FillHeader(uint32_t stream_id, size_t data_len); 37 38 // Sets the contents of the transfer. 39 // Returns ZX_OK on success, or ZX_ERR_INVALID_ARGS if data_len is larger than 40 // MAX_WRITE_DATA_SIZE. 41 zx_status_t FillData(uint32_t stream_id, unsigned char* data, size_t data_len); 42 43 bool SetOffset(int offset); 44 45 // Returns the data buffer to be populated for a write transfer. write_data_buffer()46 unsigned char* write_data_buffer() const { return data_ + HEADER_SIZE; } data()47 unsigned char* data() const { return data_; } 48 // The number of bytes to be transferred. request_length()49 int request_length() const { return request_length_; } 50 // The number of bytes successfully transferred. actual_length()51 int actual_length() const { return actual_length_; } 52 // Returns where the client has read up to in the data. 53 // An offset equal to actual_length indicates the client has reached the end. offset()54 int offset() const { return offset_; } 55 56 private: 57 // Only UsbHandler should create transfers. 58 static std::unique_ptr<Transfer> Create(); 59 60 // TODO(jocelyndang): this should store a libusb_transfer instead. 61 unsigned char* data_; 62 int request_length_; 63 int actual_length_; 64 65 int offset_; 66 67 friend class UsbHandler; 68 }; 69 70 // Create should be called instead. This is public for make_unique. UsbHandler(ConstructorTag tag)71 explicit UsbHandler(ConstructorTag tag) {} 72 73 static std::unique_ptr<UsbHandler> Create(); 74 75 // Handles any pending events. 76 // 77 // Parameters: 78 // completed_reads A vector which will be populated with the usb transfers containing data 79 // read from the xdc device. Once the client has finished processing a read, 80 // it should be returned back to the UsbHandler by calling RequeueRead. 81 // 82 // Returns whether the usb handler fds have changed. 83 // If true, the newly added or removed fds should be fetched via GetFdUpdates. 84 bool HandleEvents(std::vector<std::unique_ptr<Transfer>>& completed_reads); 85 86 // Returns the read transfer back to the UsbHandler to be requeued. 87 void RequeueRead(std::unique_ptr<Transfer> transfer); 88 89 // Populates added_fds and removed_fds with the fds that have been added 90 // and removed since GetFdUpdates was last called. 91 // 92 // Parameters: 93 // added_fds A map that will be populated with fds to start monitoring and 94 // the corresponding events to monitor for. 95 // removed_fds A set that will be populated with fds to stop monitoring. 96 // The fds will be disjoint from added_fds. 97 void GetFdUpdates(std::map<int, short>& added_fds, std::set<int>& removed_fds); 98 99 // Returns a write transfer that can be used with QueueWriteTransfer to write 100 // data to the xdc device. May return a nullptr if no transfers are available. 101 std::unique_ptr<Transfer> GetWriteTransfer(); 102 void ReturnWriteTransfer(std::unique_ptr<Transfer>); 103 // Returns a nullptr if the transfer was successfully queued, 104 // otherwise returns the transfer to the client. 105 std::unique_ptr<Transfer> QueueWriteTransfer(std::unique_ptr<Transfer>); 106 107 // Returns whether the given file descriptor is currently valid for the usb handler. IsValidFd(int fd)108 bool IsValidFd(int fd) const { return fds_.count(fd); } 109 writable()110 bool writable() const { return writable_; } 111 112 private: 113 // All the libusb fds. 114 std::set<int> fds_; 115 116 bool writable_; 117 }; 118 119 } // namespace xdc 120