| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ZIRCON_TOOLS_XDC_SERVER_USB_HANDLER_H_ |
| #define ZIRCON_TOOLS_XDC_SERVER_USB_HANDLER_H_ |
| |
| #include <zircon/types.h> |
| |
| #include <map> |
| #include <set> |
| #include <vector> |
| |
| #include <xdc-server-utils/packet.h> |
| |
| namespace xdc { |
| |
| class UsbHandler { |
| // This is required by the UsbHandler constructor, to stop clients calling it directly. |
| struct ConstructorTag { |
| explicit ConstructorTag() = default; |
| }; |
| |
| public: |
| class Transfer { |
| public: |
| static constexpr const size_t BUFFER_SIZE = 16 * 1024; |
| static constexpr const size_t HEADER_SIZE = sizeof(xdc_packet_header_t); |
| |
| static constexpr const size_t MAX_WRITE_DATA_SIZE = BUFFER_SIZE - HEADER_SIZE; |
| |
| // Create should be called instead. This is public for make_shared. |
| explicit Transfer(ConstructorTag tag) {} |
| |
| // Sets the header of the transfer. |
| // Returns ZX_OK on success, or ZX_ERR_INVALID_ARGS if data_len is larger than |
| // MAX_WRITE_DATA_SIZE. |
| zx_status_t FillHeader(uint32_t stream_id, size_t data_len); |
| |
| // Sets the contents of the transfer. |
| // Returns ZX_OK on success, or ZX_ERR_INVALID_ARGS if data_len is larger than |
| // MAX_WRITE_DATA_SIZE. |
| zx_status_t FillData(uint32_t stream_id, unsigned char* data, size_t data_len); |
| |
| bool SetOffset(int offset); |
| |
| // Returns the data buffer to be populated for a write transfer. |
| unsigned char* write_data_buffer() const { return data_ + HEADER_SIZE; } |
| unsigned char* data() const { return data_; } |
| // The number of bytes to be transferred. |
| int request_length() const { return request_length_; } |
| // The number of bytes successfully transferred. |
| int actual_length() const { return actual_length_; } |
| // Returns where the client has read up to in the data. |
| // An offset equal to actual_length indicates the client has reached the end. |
| int offset() const { return offset_; } |
| |
| private: |
| // Only UsbHandler should create transfers. |
| static std::unique_ptr<Transfer> Create(); |
| |
| // TODO(jocelyndang): this should store a libusb_transfer instead. |
| unsigned char* data_; |
| int request_length_; |
| int actual_length_; |
| |
| int offset_; |
| |
| friend class UsbHandler; |
| }; |
| |
| // Create should be called instead. This is public for make_unique. |
| explicit UsbHandler(ConstructorTag tag) {} |
| |
| static std::unique_ptr<UsbHandler> Create(); |
| |
| // Handles any pending events. |
| // |
| // Parameters: |
| // completed_reads A vector which will be populated with the usb transfers containing data |
| // read from the xdc device. Once the client has finished processing a read, |
| // it should be returned back to the UsbHandler by calling RequeueRead. |
| // |
| // Returns whether the usb handler fds have changed. |
| // If true, the newly added or removed fds should be fetched via GetFdUpdates. |
| bool HandleEvents(std::vector<std::unique_ptr<Transfer>>& completed_reads); |
| |
| // Returns the read transfer back to the UsbHandler to be requeued. |
| void RequeueRead(std::unique_ptr<Transfer> transfer); |
| |
| // Populates added_fds and removed_fds with the fds that have been added |
| // and removed since GetFdUpdates was last called. |
| // |
| // Parameters: |
| // added_fds A map that will be populated with fds to start monitoring and |
| // the corresponding events to monitor for. |
| // removed_fds A set that will be populated with fds to stop monitoring. |
| // The fds will be disjoint from added_fds. |
| void GetFdUpdates(std::map<int, short>& added_fds, std::set<int>& removed_fds); |
| |
| // Returns a write transfer that can be used with QueueWriteTransfer to write |
| // data to the xdc device. May return a nullptr if no transfers are available. |
| std::unique_ptr<Transfer> GetWriteTransfer(); |
| void ReturnWriteTransfer(std::unique_ptr<Transfer>); |
| // Returns a nullptr if the transfer was successfully queued, |
| // otherwise returns the transfer to the client. |
| std::unique_ptr<Transfer> QueueWriteTransfer(std::unique_ptr<Transfer>); |
| |
| // Returns whether the given file descriptor is currently valid for the usb handler. |
| bool IsValidFd(int fd) const { return fds_.count(fd); } |
| |
| bool writable() const { return writable_; } |
| |
| private: |
| // All the libusb fds. |
| std::set<int> fds_; |
| |
| bool writable_; |
| }; |
| |
| } // namespace xdc |
| |
| #endif // ZIRCON_TOOLS_XDC_SERVER_USB_HANDLER_H_ |