mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 00:51:29 +00:00
Previously the Producer and Consumer interfaces tracked the Consumer and Producer respectively at the other end of the queue that they interacted with. This was done to avoid modifying the queue implementation, but resulted in a rougher interface that required additional initialization steps and prevented alternative configurations; many producers and one consumer for example. This commit uses the new queue policies to track this information. The new direct policy behaves as the old producer and consumers did. Now the producers and consumers are just named references to the queue that they work on and a convenient location for a notification callback when the queue is updated in a way that is relevent to the producer or consumer. All users of Producer and Consumer have been updated including the stream adaptors which are in use by the echo test code and the mcdp28x0 driver. Use of the stream adaptors has also been simplified. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=make buildall -j Manual testing of Ryu (P5) and discovery board echo task Change-Id: I704be6378a31b4e20f5063295eff9943e4900409 Reviewed-on: https://chromium-review.googlesource.com/271792 Reviewed-by: Anton Staaf <robotboy@chromium.org> Commit-Queue: Anton Staaf <robotboy@chromium.org> Trybot-Ready: Anton Staaf <robotboy@chromium.org> Tested-by: Anton Staaf <robotboy@chromium.org>
224 lines
5.0 KiB
C
224 lines
5.0 KiB
C
/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*
|
|
* Megachips DisplayPort to HDMI protocol converter / level shifter driver.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "console.h"
|
|
#include "common.h"
|
|
#include "ec_commands.h"
|
|
#include "mcdp28x0.h"
|
|
#include "stream_adaptor.h"
|
|
#include "timer.h"
|
|
#include "usart-stm32f0.h"
|
|
#include "util.h"
|
|
|
|
#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
|
|
|
|
static uint8_t mcdp_inbuf[MCDP_INBUF_MAX];
|
|
|
|
#undef MCDP_DEBUG
|
|
|
|
#ifdef MCDP_DEBUG
|
|
static inline void print_buffer(uint8_t *buf, int cnt)
|
|
{
|
|
int i;
|
|
CPRINTF("buf:");
|
|
for (i = 0; i < cnt; i++) {
|
|
if (i && !(i % 4))
|
|
CPRINTF("\n ");
|
|
CPRINTF("[%02d]0x%02x ", i, buf[i]);
|
|
}
|
|
CPRINTF("\n");
|
|
}
|
|
#else
|
|
static inline void print_buffer(uint8_t *buf, int cnt) {}
|
|
#endif
|
|
|
|
struct usart_config const usart_mcdp;
|
|
|
|
IO_STREAM_CONFIG(usart_mcdp, MCDP_INBUF_MAX, MCDP_OUTBUF_MAX, NULL, NULL);
|
|
|
|
USART_CONFIG(usart_mcdp,
|
|
CONFIG_MCDP28X0,
|
|
115200,
|
|
usart_mcdp_rx_queue,
|
|
usart_mcdp_tx_queue);
|
|
|
|
/**
|
|
* Compute checksum.
|
|
*
|
|
* @seed initial value of checksum.
|
|
* @msg message bytes to compute checksum on.
|
|
* @cnt count of message bytes.
|
|
* @return partial checksum.
|
|
*/
|
|
static uint8_t compute_checksum(uint8_t seed, const uint8_t *msg, int cnt)
|
|
{
|
|
int i;
|
|
uint8_t chksum = seed;
|
|
|
|
for (i = 0; i < cnt; i++)
|
|
chksum += msg[i];
|
|
return ~chksum + 1;
|
|
}
|
|
|
|
/**
|
|
* transmit message over serial
|
|
*
|
|
* Packet consists of:
|
|
* msg[0] == length of entire packet
|
|
* msg[1] == 1st message byte (typically command)
|
|
* msg[cnt+1] == last message byte
|
|
* msg[cnt+2] == checksum
|
|
*
|
|
* @msg message bytes
|
|
* @cnt count of message bytes
|
|
* @return zero if success, error code otherwise
|
|
*/
|
|
static int tx_serial(const uint8_t *msg, int cnt)
|
|
{
|
|
uint8_t out = cnt + 2;
|
|
/* 1st byte (not in msg) is always cnt + 2, so seed chksum with that */
|
|
uint8_t chksum = compute_checksum(cnt + 2, msg, cnt);
|
|
|
|
if (out_stream_write(&usart_mcdp_out.out, &out, 1) != 1)
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
if (out_stream_write(&usart_mcdp_out.out, msg, cnt) != cnt)
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
if (out_stream_write(&usart_mcdp_out.out, &chksum, 1) != 1)
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* receive message over serial
|
|
*
|
|
* While definitive documentation is lacking its believed the following receive
|
|
* packet is always true.
|
|
*
|
|
* Packet consists of:
|
|
* msg[0] == length of entire packet
|
|
* msg[1] == 1st message byte (typically command)
|
|
* msg[cnt+2] == last message byte
|
|
* msg[cnt+3] == checksum
|
|
*
|
|
* @msg pointer to buffer to read message into
|
|
* @cnt count of message bytes
|
|
* @return zero if success, error code otherwise
|
|
*/
|
|
static int rx_serial(uint8_t *msg, int cnt)
|
|
{
|
|
size_t read;
|
|
int retry = 2;
|
|
|
|
read = in_stream_read(&usart_mcdp_in.in, msg, cnt);
|
|
while ((read < cnt) && retry) {
|
|
usleep(100*MSEC);
|
|
read += in_stream_read(&usart_mcdp_in.in, msg + read,
|
|
cnt - read);
|
|
retry--;
|
|
}
|
|
|
|
print_buffer(msg, cnt);
|
|
|
|
/* Some response sizes are dynamic so shrink cnt accordingly. */
|
|
if (cnt > msg[0])
|
|
cnt = msg[0];
|
|
|
|
if (msg[cnt-1] != compute_checksum(0, msg, cnt-1))
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
return !(read == cnt);
|
|
}
|
|
|
|
void mcdp_enable(void)
|
|
{
|
|
usart_init(&usart_mcdp);
|
|
}
|
|
|
|
void mcdp_disable(void)
|
|
{
|
|
usart_shutdown(&usart_mcdp);
|
|
}
|
|
|
|
int mcdp_get_info(struct mcdp_info *info)
|
|
{
|
|
const uint8_t msg[2] = {MCDP_CMD_GETINFO, 0x00}; /* cmd + msg type */
|
|
|
|
if (tx_serial(msg, sizeof(msg)))
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
if (rx_serial(mcdp_inbuf, MCDP_RSP_LEN(MCDP_LEN_GETINFO)))
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
memcpy(info, &mcdp_inbuf[2], MCDP_LEN_GETINFO);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
#ifdef CONFIG_CMD_MCDP
|
|
static int mcdp_get_dev_id(char *dev, uint8_t dev_id, int dev_cnt)
|
|
{
|
|
uint8_t msg[2];
|
|
msg[0] = MCDP_CMD_GETDEVID;
|
|
msg[1] = dev_id;
|
|
|
|
if (tx_serial(msg, sizeof(msg)))
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
if (rx_serial(mcdp_inbuf, sizeof(mcdp_inbuf)))
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
memcpy(dev, &mcdp_inbuf[2], mcdp_inbuf[0] - 3);
|
|
dev[mcdp_inbuf[0] - 3] = '\0';
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
int command_mcdp(int argc, char **argv)
|
|
{
|
|
int rv = EC_SUCCESS;
|
|
char *e;
|
|
|
|
if (argc < 2)
|
|
return EC_ERROR_PARAM_COUNT;
|
|
|
|
mcdp_enable();
|
|
if (!strncasecmp(argv[1], "info", 4)) {
|
|
struct mcdp_info info;
|
|
rv = mcdp_get_info(&info);
|
|
if (!rv)
|
|
ccprintf("family:%04x chipid:%04x irom:%d.%d.%d "
|
|
"fw:%d.%d.%d\n",
|
|
MCDP_FAMILY(info.family),
|
|
MCDP_CHIPID(info.chipid),
|
|
info.irom.major, info.irom.minor,
|
|
info.irom.build,
|
|
info.fw.major, info.fw.minor, info.fw.build);
|
|
} else if (!strncasecmp(argv[1], "devid", 4)) {
|
|
uint8_t dev_id = strtoi(argv[2], &e, 10);
|
|
char dev[32];
|
|
if (*e)
|
|
rv = EC_ERROR_PARAM2;
|
|
else
|
|
rv = mcdp_get_dev_id(dev, dev_id, 32);
|
|
if (!rv)
|
|
ccprintf("devid[%d] = %s\n", dev_id, dev);
|
|
} else {
|
|
rv = EC_ERROR_PARAM1;
|
|
}
|
|
|
|
mcdp_disable();
|
|
return rv;
|
|
}
|
|
DECLARE_CONSOLE_COMMAND(mcdp, command_mcdp,
|
|
"info|devid <id>",
|
|
"USB PD",
|
|
NULL);
|
|
#endif /* CONFIG_CMD_MCDP */
|