blob: 0b69de10a86b9f65ed0d55b74b8f85835845039c [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "usb_utils.h"
#include <stdio.h>
static const char *pid_names[] = {
"Rsvd", // 0000b
"OUT", // 0001b
"ACK", // 0010b
"DATA0", // 0011b
"PING", // 0100b
"SOF", // 0101b
"NYET", // 0110b
"DATA2", // 0111b
"SPLIT", // 1000b
"IN", // 1001b
"NAK", // 1010b
"DATA1", // 1011b
"PRE/ERR", // 1100b
"SETUP", // 1101b
"STALL", // 1110b
"MDATA" // 1111b
};
// Decode a PID and return its textual name, iff valid
const char *decode_pid(uint8_t pid) {
// Valid PIDs are formed from two complementary nibbles
return (((pid ^ 0xf0u) >> 4) ^ (pid & 0xfu)) ? "???" : pid_names[pid & 0xfu];
}
// Dump a sequence of bytes as hexadecimal and AsCII for diagnostic purposes
void dump_bytes(FILE *out, const char *prefix, const uint8_t *data, size_t n,
uint32_t flags) {
static const char hex_digits[] = "0123456789abcdef";
const unsigned ncols = 0x10u;
char buf[ncols * 4u + 2u];
if (!prefix) {
prefix = "";
}
// Note: we have no generic printf functionality and must use LOG_INFO()
while (n > 0u) {
const unsigned chunk = (n > ncols) ? ncols : (unsigned)n;
const uint8_t *row = data;
unsigned idx = 0u;
char *dp = buf;
// Columns of hexadecimal bytes
while (idx < chunk) {
dp[0] = hex_digits[row[idx] >> 4];
dp[1] = hex_digits[row[idx++] & 0xfu];
dp[2] = ' ';
dp += 3;
}
while (idx++ < ncols) {
dp[2] = dp[1] = dp[0] = ' ';
dp += 3;
}
// Printable ASCII characters
for (unsigned idx = 0u; idx < chunk; idx++) {
char ch = row[idx];
*dp++ = (ch < ' ' || ch >= 0x7f) ? '.' : ch;
}
*dp = '\0';
fprintf(out, "%s%s\n", prefix, buf);
data += chunk;
n -= chunk;
}
}
// `extern` declarations to give the inline functions in the
// corresponding header a link location.
extern uint16_t get_le16(const uint8_t *dp);
extern uint32_t get_le32(const uint8_t *dp);
extern uint8_t *set_le16(uint8_t *dp, uint16_t n);
extern uint8_t *set_le32(uint8_t *dp, uint32_t n);