pub mod configure;
use super::{CommandId, Request, SendError};
use crate::architecture::arm::PortType;
use scroll::{Pread, Pwrite, LE};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RW {
R = 1,
W = 0,
}
#[allow(non_snake_case)]
#[derive(Clone, Debug)]
pub struct InnerTransferRequest {
pub APnDP: PortType,
pub RnW: RW,
pub A2: bool,
pub A3: bool,
pub value_match: bool,
pub match_mask: bool,
pub td_timestamp_request: bool,
pub data: Option<u32>,
}
impl InnerTransferRequest {
pub fn new(port: PortType, rw: RW, address: u8, data: Option<u32>) -> Self {
Self {
APnDP: port,
RnW: rw,
A2: (address >> 2) & 0x01 == 1,
A3: (address >> 3) & 0x01 == 1,
value_match: false,
match_mask: false,
td_timestamp_request: false,
data,
}
}
}
#[test]
fn creating_inner_transfer_request() {
let req = InnerTransferRequest::new(PortType::DebugPort, RW::W, 0x8, None);
assert!(req.A3);
assert!(!req.A2);
}
impl InnerTransferRequest {
fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
buffer[0] = (self.APnDP as u8)
| (self.RnW as u8) << 1
| u8::from(self.A2) << 2
| u8::from(self.A3) << 3
| u8::from(self.value_match) << 4
| u8::from(self.match_mask) << 5
| u8::from(self.td_timestamp_request) << 7;
if let Some(data) = self.data {
let data = data.to_le_bytes();
buffer[1..5].copy_from_slice(&data[..]);
Ok(5)
} else {
Ok(1)
}
}
}
#[allow(non_snake_case)]
#[derive(Clone, Debug)]
pub struct InnerTransferResponse {
pub td_timestamp: Option<u32>,
pub data: Option<u32>,
}
impl InnerTransferResponse {
fn from_bytes(
req: &InnerTransferRequest,
ack: Ack,
buffer: &[u8],
) -> Result<(Self, usize), SendError> {
let mut resp = Self {
td_timestamp: None,
data: None,
};
let mut offset = 0;
if let Ack::Ok = ack {
if req.td_timestamp_request {
if buffer.len() < offset + 4 {
return Err(SendError::NotEnoughData);
}
resp.td_timestamp = Some(buffer.pread_with(offset, LE).unwrap());
offset += 4;
}
if req.RnW == RW::R {
if buffer.len() < offset + 4 {
return Err(SendError::NotEnoughData);
}
resp.data = Some(buffer.pread_with(offset, LE).unwrap());
offset += 4;
}
}
Ok((resp, offset))
}
}
#[derive(Debug)]
pub struct TransferRequest {
pub dap_index: u8,
pub transfer_count: u8,
pub transfers: Vec<InnerTransferRequest>,
}
impl TransferRequest {
pub fn new(transfers: &[InnerTransferRequest]) -> Self {
Self {
dap_index: 0,
transfer_count: transfers.len() as u8,
transfers: transfers.into(),
}
}
}
impl Request for TransferRequest {
const COMMAND_ID: CommandId = CommandId::Transfer;
type Response = TransferResponse;
fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
let mut size = 0;
buffer[0] = self.dap_index;
size += 1;
buffer[1] = self.transfer_count;
size += 1;
for transfer in self.transfers.iter() {
size += transfer.to_bytes(&mut buffer[size..])?;
}
Ok(size)
}
fn parse_response(&self, mut buffer: &[u8]) -> Result<Self::Response, SendError> {
if buffer.len() < 2 {
return Err(SendError::NotEnoughData);
}
let transfer_count = buffer[0];
if transfer_count as usize > self.transfers.len() {
tracing::error!("Transfer count larger than requested number of transfers");
return Err(SendError::UnexpectedAnswer);
}
let last_transfer_response = LastTransferResponse {
ack: match buffer[1] & 0x7 {
1 => Ack::Ok,
2 => Ack::Wait,
4 => Ack::Fault,
7 => Ack::NoAck,
_ => Ack::NoAck,
},
protocol_error: buffer[1] & 0x8 > 1,
value_missmatch: buffer[1] & 0x10 > 1,
};
buffer = &buffer[2..];
let mut transfers = Vec::new();
let xfer_count_and_ack = (0..transfer_count).map(|i| {
if i + 1 == transfer_count {
(i as usize, last_transfer_response.ack.clone())
} else {
(i as usize, Ack::Ok)
}
});
for (i, ack) in xfer_count_and_ack {
let req = &self.transfers[i];
let (resp, len) = InnerTransferResponse::from_bytes(req, ack, buffer)?;
transfers.push(resp);
buffer = &buffer[len..];
}
Ok(TransferResponse {
transfer_count,
last_transfer_response,
transfers,
})
}
}
#[allow(clippy::enum_variant_names)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Ack {
Ok = 1,
Wait = 2,
Fault = 4,
NoAck = 7,
}
#[derive(Debug)]
pub struct LastTransferResponse {
pub ack: Ack,
pub protocol_error: bool,
pub value_missmatch: bool,
}
#[derive(Debug)]
pub struct TransferResponse {
pub transfer_count: u8,
pub last_transfer_response: LastTransferResponse,
pub transfers: Vec<InnerTransferResponse>,
}
#[derive(Debug)]
pub(crate) struct TransferBlockRequest {
dap_index: u8,
transfer_count: u16,
transfer_request: InnerTransferBlockRequest,
transfer_data: Vec<u32>,
}
impl Request for TransferBlockRequest {
const COMMAND_ID: CommandId = CommandId::TransferBlock;
type Response = TransferBlockResponse;
fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
let mut size = 0;
buffer[0] = self.dap_index;
size += 1;
buffer
.pwrite_with(self.transfer_count, 1, LE)
.expect("Buffer for CMSIS-DAP command is too small. This is a bug, please report it.");
size += 2;
size += self.transfer_request.to_bytes(buffer, 3)?;
let mut data_offset = 4;
for word in &self.transfer_data {
buffer.pwrite_with(word, data_offset, LE).expect(
"Buffer for CMSIS-DAP command is too small. This is a bug, please report it.",
);
data_offset += 4;
size += 4;
}
Ok(size)
}
fn parse_response(&self, buffer: &[u8]) -> Result<Self::Response, SendError> {
let transfer_count = buffer
.pread_with(0, LE)
.map_err(|_| SendError::NotEnoughData)?;
let transfer_response = buffer
.pread_with(2, LE)
.map_err(|_| SendError::NotEnoughData)?;
let mut data = Vec::with_capacity(transfer_count as usize);
let num_transfers = (buffer.len() - 3) / 4;
tracing::debug!(
"Expected {} responses, got {} responses with data..",
transfer_count,
num_transfers
);
if self.transfer_request.r_n_w == RW::R {
for data_offset in 0..transfer_count as usize {
data.push(
buffer
.pread_with(3 + data_offset * 4, LE)
.map_err(|_| SendError::NotEnoughData)?,
);
}
}
Ok(TransferBlockResponse {
_transfer_count: transfer_count,
transfer_response,
transfer_data: data,
})
}
}
impl TransferBlockRequest {
pub(crate) fn write_request(address: u8, port: PortType, data: Vec<u32>) -> Self {
let inner = InnerTransferBlockRequest {
ap_n_dp: port,
r_n_w: RW::W,
a2: (address >> 2) & 0x01 == 1,
a3: (address >> 3) & 0x01 == 1,
};
TransferBlockRequest {
dap_index: 0,
transfer_count: data.len() as u16,
transfer_request: inner,
transfer_data: data,
}
}
pub(crate) fn read_request(address: u8, port: PortType, read_count: u16) -> Self {
let inner = InnerTransferBlockRequest {
ap_n_dp: port,
r_n_w: RW::R,
a2: (address >> 2) & 0x01 == 1,
a3: (address >> 3) & 0x01 == 1,
};
TransferBlockRequest {
dap_index: 0,
transfer_count: read_count,
transfer_request: inner,
transfer_data: Vec::new(),
}
}
}
#[derive(Debug)]
struct InnerTransferBlockRequest {
ap_n_dp: PortType,
r_n_w: RW,
a2: bool,
a3: bool,
}
impl InnerTransferBlockRequest {
fn to_bytes(&self, buffer: &mut [u8], offset: usize) -> Result<usize, SendError> {
buffer[offset] = (self.ap_n_dp as u8)
| (self.r_n_w as u8) << 1
| u8::from(self.a2) << 2
| u8::from(self.a3) << 3;
Ok(1)
}
}
#[derive(Debug)]
pub(crate) struct TransferBlockResponse {
_transfer_count: u16,
pub transfer_response: u8,
pub transfer_data: Vec<u32>,
}