blob: 0681e2346e3703f0482591b981f5d6e058545ffc [file] [log] [blame]
#include "libpldm/transport.h"
#include "base.h"
#include "libpldm/requester/pldm.h"
#include "transport.h"
#ifdef PLDM_HAS_POLL
#include <poll.h>
#endif
#include <stdlib.h>
#include <unistd.h>
#ifndef PLDM_HAS_POLL
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
static inline int poll(struct pollfd *fds __attribute__((unused)),
int nfds __attribute__((unused)),
int timeout __attribute__((unused)))
{
return 0;
}
#endif
pldm_requester_rc_t pldm_transport_poll(struct pldm_transport *transport,
int timeout)
{
struct pollfd pollfd;
int rc = 0;
if (!transport) {
return PLDM_REQUESTER_INVALID_SETUP;
}
if (!transport->init_pollfd) {
return PLDM_REQUESTER_SUCCESS;
}
transport->init_pollfd(transport, &pollfd);
rc = poll(&pollfd, 1, timeout);
if (rc < 0) {
return PLDM_REQUESTER_POLL_FAIL;
}
return PLDM_REQUESTER_SUCCESS;
}
pldm_requester_rc_t pldm_transport_send_msg(struct pldm_transport *transport,
pldm_tid_t tid,
const void *pldm_req_msg,
size_t req_msg_len)
{
if (!transport || !pldm_req_msg) {
return PLDM_REQUESTER_INVALID_SETUP;
}
if (req_msg_len < sizeof(struct pldm_msg_hdr)) {
return PLDM_REQUESTER_NOT_REQ_MSG;
}
const struct pldm_msg_hdr *hdr = pldm_req_msg;
if (!hdr->request) {
return PLDM_REQUESTER_NOT_REQ_MSG;
}
return transport->send(transport, tid, pldm_req_msg, req_msg_len);
}
pldm_requester_rc_t pldm_transport_recv_msg(struct pldm_transport *transport,
pldm_tid_t tid,
void **pldm_resp_msg,
size_t *resp_msg_len)
{
if (!transport || !resp_msg_len) {
return PLDM_REQUESTER_INVALID_SETUP;
}
pldm_requester_rc_t rc =
transport->recv(transport, tid, pldm_resp_msg, resp_msg_len);
if (rc != PLDM_REQUESTER_SUCCESS) {
return rc;
}
struct pldm_msg_hdr *hdr = *pldm_resp_msg;
if (hdr->request || hdr->datagram) {
free(*pldm_resp_msg);
*pldm_resp_msg = NULL;
return PLDM_REQUESTER_NOT_RESP_MSG;
}
uint8_t pldm_rc = 0;
if (*resp_msg_len < (sizeof(struct pldm_msg_hdr) + sizeof(pldm_rc))) {
free(*pldm_resp_msg);
*pldm_resp_msg = NULL;
return PLDM_REQUESTER_RESP_MSG_TOO_SMALL;
}
return PLDM_REQUESTER_SUCCESS;
}
pldm_requester_rc_t
pldm_transport_send_recv_msg(struct pldm_transport *transport, pldm_tid_t tid,
const void *pldm_req_msg, size_t req_msg_len,
void **pldm_resp_msg, size_t *resp_msg_len)
{
if (!resp_msg_len) {
return PLDM_REQUESTER_INVALID_SETUP;
}
pldm_requester_rc_t rc =
pldm_transport_send_msg(transport, tid, pldm_req_msg, req_msg_len);
if (rc != PLDM_REQUESTER_SUCCESS) {
return rc;
}
while (1) {
rc = pldm_transport_poll(transport, -1);
if (rc != PLDM_REQUESTER_SUCCESS) {
break;
}
rc = pldm_transport_recv_msg(transport, tid, pldm_resp_msg,
resp_msg_len);
if (rc == PLDM_REQUESTER_SUCCESS) {
break;
}
}
return rc;
}