-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
452 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#include "usb/classdriver/cdc.hpp" | ||
|
||
#include <algorithm> | ||
#include <cstdlib> | ||
#include <iterator> | ||
|
||
#include "logger.hpp" | ||
#include "usb/device.hpp" | ||
|
||
namespace usb::cdc { | ||
CDCDriver::CDCDriver(Device* dev, const InterfaceDescriptor* if_comm, | ||
const InterfaceDescriptor* if_data) : ClassDriver{dev} { | ||
} | ||
|
||
Error CDCDriver::Initialize() { | ||
return MAKE_ERROR(Error::kNotImplemented); | ||
} | ||
|
||
Error CDCDriver::SetEndpoint(const std::vector<EndpointConfig>& configs) { | ||
for (const auto& config : configs) { | ||
if (config.ep_type == EndpointType::kInterrupt && config.ep_id.IsIn()) { | ||
ep_interrupt_in_ = config.ep_id; | ||
} else if (config.ep_type == EndpointType::kBulk && config.ep_id.IsIn()) { | ||
ep_bulk_in_ = config.ep_id; | ||
} else if (config.ep_type == EndpointType::kBulk && !config.ep_id.IsIn()) { | ||
ep_bulk_out_ = config.ep_id; | ||
} | ||
} | ||
return MAKE_ERROR(Error::kSuccess); | ||
} | ||
|
||
Error CDCDriver::OnEndpointsConfigured() { | ||
return MAKE_ERROR(Error::kSuccess); | ||
} | ||
|
||
Error CDCDriver::OnControlCompleted(EndpointID ep_id, SetupData setup_data, | ||
const void* buf, int len) { | ||
return MAKE_ERROR(Error::kNotImplemented); | ||
} | ||
|
||
Error CDCDriver::OnNormalCompleted(EndpointID ep_id, const void* buf, int len) { | ||
Log(kDebug, "CDCDriver::OnNormalCompleted: buf='%.*s'\n", len, buf); | ||
auto buf8 = reinterpret_cast<const uint8_t*>(buf); | ||
if (ep_id == ep_bulk_in_) { | ||
std::copy_n(buf8, len, std::back_inserter(receive_buf_)); | ||
} else if (ep_id == ep_bulk_out_) { | ||
} else { | ||
return MAKE_ERROR(Error::kEndpointNotInCharge); | ||
} | ||
delete[] buf8; | ||
return MAKE_ERROR(Error::kSuccess); | ||
} | ||
|
||
Error CDCDriver::SendSerial(const void* buf, int len) { | ||
uint8_t* buf_out = new uint8_t[len]; | ||
memcpy(buf_out, buf, len); | ||
if (auto err = ParentDevice()->NormalOut(ep_bulk_out_, buf_out, len)) { | ||
Log(kError, "%s:%d: NormalOut failed: %s\n", err.File(), err.Line(), err.Name()); | ||
return err; | ||
} | ||
|
||
uint8_t* buf_in = new uint8_t[8]; | ||
if (auto err = ParentDevice()->NormalIn(ep_bulk_in_, buf_in, 8)) { | ||
Log(kError, "%s:%d: NormalIn failed: %s\n", err.File(), err.Line(), err.Name()); | ||
return err; | ||
} | ||
return MAKE_ERROR(Error::kSuccess); | ||
} | ||
|
||
int CDCDriver::ReceiveSerial(void* buf, int len) { | ||
const auto recv_len = std::min(len, static_cast<int>(receive_buf_.size())); | ||
auto buf8 = reinterpret_cast<uint8_t*>(buf); | ||
for (int i = 0; i < recv_len; ++i) { | ||
buf8[i] = receive_buf_.front(); | ||
receive_buf_.pop_front(); | ||
} | ||
return recv_len; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/** | ||
* @file usb/classdriver/cdc.hpp | ||
* | ||
* CDC class drivers. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <deque> | ||
|
||
#include "usb/classdriver/base.hpp" | ||
#include "usb/descriptor.hpp" | ||
|
||
namespace usb::cdc { | ||
enum class DescriptorSubType : uint8_t { | ||
kHeader = 0, | ||
kCM = 1, // Call Management | ||
kACM = 2, // Abstract Control Management | ||
kUnion = 6, | ||
}; | ||
|
||
struct FunctionalDescriptor { | ||
static const uint8_t kType = 36; // CS_INTERFACE | ||
|
||
uint8_t length; // offset 0 | ||
uint8_t descriptor_type; // offset 1 | ||
DescriptorSubType descriptor_subtype; // offset 2 | ||
} __attribute__((packed)); | ||
|
||
struct HeaderDescriptor : public FunctionalDescriptor { | ||
static const auto kSubType = DescriptorSubType::kHeader; | ||
|
||
uint16_t cdc; | ||
} __attribute__((packed)); | ||
|
||
struct CMDescriptor : public FunctionalDescriptor { | ||
static const auto kSubType = DescriptorSubType::kCM; | ||
|
||
union { | ||
uint8_t data; | ||
struct { | ||
uint8_t handle_call_management : 1; | ||
uint8_t data_interface_usable : 1; | ||
uint8_t : 6; | ||
} __attribute__((packed)) bits; | ||
} capabilities; | ||
uint8_t data_interface; | ||
} __attribute__((packed)); | ||
|
||
struct ACMDescriptor : public FunctionalDescriptor { | ||
static const auto kSubType = DescriptorSubType::kACM; | ||
|
||
union { | ||
uint8_t data; | ||
struct { | ||
uint8_t comm_feature : 1; | ||
uint8_t hw_handshake : 1; | ||
uint8_t send_break : 1; | ||
uint8_t conn_notification : 1; | ||
uint8_t : 4; | ||
} __attribute__((packed)) bits; | ||
} capabilities; | ||
} __attribute__((packed)); | ||
|
||
struct UnionDescriptor : public FunctionalDescriptor { | ||
static const auto kSubType = DescriptorSubType::kUnion; | ||
|
||
uint8_t control_interface; | ||
uint8_t SubordinateInterface(size_t index) const { | ||
return reinterpret_cast<const uint8_t*>(this)[index + 4]; | ||
} | ||
} __attribute__((packed)); | ||
|
||
template <class T> | ||
const T* FuncDescDynamicCast(const uint8_t* desc_data) { | ||
if (desc_data[1] == T::kType && | ||
desc_data[2] == static_cast<uint8_t>(T::kSubType)) { | ||
return reinterpret_cast<const T*>(desc_data); | ||
} | ||
return nullptr; | ||
} | ||
|
||
template <class T> | ||
T* FuncDescDynamicCast(uint8_t* desc_data) { | ||
if (FuncDescDynamicCast<const T>(desc_data)) { | ||
return reinterpret_cast<T*>(desc_data); | ||
} | ||
return nullptr; | ||
} | ||
|
||
class CDCDriver : public ClassDriver { | ||
public: | ||
CDCDriver(Device* dev, const InterfaceDescriptor* if_comm, | ||
const InterfaceDescriptor* if_data); | ||
|
||
Error Initialize() override; | ||
Error SetEndpoint(const std::vector<EndpointConfig>& configs) override; | ||
Error OnEndpointsConfigured() override; | ||
Error OnControlCompleted(EndpointID ep_id, SetupData setup_data, | ||
const void* buf, int len) override; | ||
Error OnNormalCompleted(EndpointID ep_id, const void* buf, int len) override; | ||
|
||
Error SendSerial(const void* buf, int len); | ||
int ReceiveSerial(void* buf, int len); | ||
|
||
private: | ||
EndpointID ep_interrupt_in_, ep_bulk_in_, ep_bulk_out_; | ||
std::deque<uint8_t> receive_buf_; | ||
}; | ||
|
||
inline CDCDriver* driver = nullptr; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.