#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <libpcp.h>
#include "tsalarm.h"
#define TSALARM_CONTROL 15
#define TSALARM_CONTROL_R 16
#define TSALARM_CHANNEL_TIMEOUT 20
#define TSALARM_MAX_RETRIES 3
#define TSALARM_SERVICE_NAME "SUNW,sun4v-telco-alarm"
int
tsalarm_get(uint32_t alarm_type, uint32_t *alarm_state)
{
int chnl_fd;
tsalarm_req_t *req_ptr = NULL;
tsalarm_resp_t *resp_ptr = NULL;
pcp_msg_t send_msg;
pcp_msg_t recv_msg;
int rc = TSALARM_SUCCESS;
int retries;
for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) {
if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) {
if (retries == TSALARM_MAX_RETRIES) {
rc = TSALARM_CHANNEL_INIT_FAILURE;
goto cleanup;
}
(void) sleep(TSALARM_CHANNEL_TIMEOUT);
} else
break;
}
req_ptr = malloc(sizeof (tsalarm_req_t));
if (req_ptr == NULL) {
rc = TSALARM_NULL_REQ_DATA;
goto cleanup;
}
req_ptr->alarm_action = TSALARM_STATUS;
req_ptr->alarm_id = alarm_type;
send_msg.msg_type = TSALARM_CONTROL;
send_msg.sub_type = 0;
send_msg.msg_len = sizeof (tsalarm_req_t);
send_msg.msg_data = (uint8_t *)req_ptr;
if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
TSALARM_CHANNEL_TIMEOUT) < 0) {
(void) sleep(TSALARM_CHANNEL_TIMEOUT);
if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
TSALARM_CHANNEL_TIMEOUT) < 0) {
rc = TSALARM_COMM_FAILURE;
goto cleanup;
}
}
if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL)
goto cleanup;
if (recv_msg.msg_type != TSALARM_CONTROL_R) {
rc = TSALARM_UNBOUND_PACKET_RECVD;
goto cleanup;
}
if (resp_ptr->status == TSALARM_ERROR) {
rc = TSALARM_GET_ERROR;
goto cleanup;
}
if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) {
rc = TSALARM_GET_ERROR;
goto cleanup;
}
*alarm_state = resp_ptr->alarm_state;
cleanup:
if (req_ptr != NULL)
free(req_ptr);
if (resp_ptr != NULL)
free(resp_ptr);
(void) pcp_close(chnl_fd);
return (rc);
}
int
tsalarm_set(uint32_t alarm_type, uint32_t alarm_state)
{
int chnl_fd;
tsalarm_req_t *req_ptr = NULL;
tsalarm_resp_t *resp_ptr = NULL;
pcp_msg_t send_msg;
pcp_msg_t recv_msg;
int rc = TSALARM_SUCCESS;
int retries;
for (retries = 1; retries <= TSALARM_MAX_RETRIES; retries++) {
if ((chnl_fd = pcp_init(TSALARM_SERVICE_NAME)) < 0) {
if (retries == TSALARM_MAX_RETRIES) {
rc = TSALARM_CHANNEL_INIT_FAILURE;
goto cleanup;
}
(void) sleep(TSALARM_CHANNEL_TIMEOUT);
} else
break;
}
req_ptr = malloc(sizeof (tsalarm_req_t));
if (req_ptr == NULL) {
rc = TSALARM_NULL_REQ_DATA;
goto cleanup;
}
req_ptr->alarm_id = alarm_type;
if (alarm_state == TSALARM_STATE_ON)
req_ptr->alarm_action = TSALARM_ENABLE;
else if (alarm_state == TSALARM_STATE_OFF)
req_ptr->alarm_action = TSALARM_DISABLE;
send_msg.msg_type = TSALARM_CONTROL;
send_msg.sub_type = 0;
send_msg.msg_len = sizeof (tsalarm_req_t);
send_msg.msg_data = (uint8_t *)req_ptr;
if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
TSALARM_CHANNEL_TIMEOUT) < 0) {
(void) sleep(TSALARM_CHANNEL_TIMEOUT);
if (pcp_send_recv(chnl_fd, &send_msg, &recv_msg,
TSALARM_CHANNEL_TIMEOUT) < 0) {
rc = TSALARM_COMM_FAILURE;
goto cleanup;
}
}
if ((resp_ptr = (tsalarm_resp_t *)recv_msg.msg_data) == NULL)
goto cleanup;
if (recv_msg.msg_type != TSALARM_CONTROL_R) {
rc = TSALARM_UNBOUND_PACKET_RECVD;
goto cleanup;
}
if (resp_ptr->status == TSALARM_ERROR) {
rc = TSALARM_SET_ERROR;
goto cleanup;
}
if ((req_ptr->alarm_action == TSALARM_DISABLE) &&
(resp_ptr->alarm_state != TSALARM_STATE_OFF)) {
rc = TSALARM_SET_ERROR;
goto cleanup;
} else if ((req_ptr->alarm_action == TSALARM_ENABLE) &&
(resp_ptr->alarm_state != TSALARM_STATE_ON)) {
rc = TSALARM_SET_ERROR;
goto cleanup;
} else if (resp_ptr->alarm_state == TSALARM_STATE_UNKNOWN) {
rc = TSALARM_SET_ERROR;
goto cleanup;
}
cleanup:
if (req_ptr != NULL)
free(req_ptr);
if (resp_ptr != NULL)
free(resp_ptr);
(void) pcp_close(chnl_fd);
return (rc);
}