blob: 4fd357eb1547c0de234bc8f2558220ac9d9ddc7a [file] [log] [blame]
/*
* Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*============================================================================
FILE: host_diag_log.c
OVERVIEW: This source file contains definitions for WLAN UTIL diag APIs
DEPENDENCIES:
============================================================================*/
#include "cdf_types.h"
#include "i_host_diag_core_log.h"
#include "host_diag_core_event.h"
#include "wlan_nlink_common.h"
#include "cds_sched.h"
#include "wlan_ptt_sock_svc.h"
#include "wlan_nlink_srv.h"
#include "cds_api.h"
#define PTT_MSG_DIAG_CMDS_TYPE (0x5050)
#define DIAG_TYPE_LOGS (1)
#define DIAG_TYPE_EVENTS (2)
#define DIAG_SWAP16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8))
typedef struct event_report_s {
uint32_t diag_type;
uint16_t event_id;
uint16_t length;
} event_report_t;
/**---------------------------------------------------------------------------
\brief host_diag_log_set_code() -
This function sets the logging code in the given log record.
\param - ptr - Pointer to the log header type.
- code - log code.
\return - None
--------------------------------------------------------------------------*/
void host_diag_log_set_code(void *ptr, uint16_t code)
{
if (ptr) {
/* All log packets are required to start with 'log_header_type' */
((log_hdr_type *) ptr)->code = code;
}
}
/**---------------------------------------------------------------------------
\brief host_diag_log_set_length() -
This function sets the length field in the given log record.
\param - ptr - Pointer to the log header type.
- length - log length.
\return - None
--------------------------------------------------------------------------*/
void host_diag_log_set_length(void *ptr, uint16_t length)
{
if (ptr) {
/* All log packets are required to start with 'log_header_type' */
((log_hdr_type *) ptr)->len = (uint16_t) length;
}
}
/**---------------------------------------------------------------------------
\brief host_diag_log_submit() -
This function sends the log data to the ptt socket app only if it is registered with the driver.
\param - ptr - Pointer to the log header type.
\return - None
--------------------------------------------------------------------------*/
void host_diag_log_submit(void *plog_hdr_ptr)
{
log_hdr_type *pHdr = (log_hdr_type *) plog_hdr_ptr;
tAniHdr *wmsg = NULL;
uint8_t *pBuf;
uint16_t data_len;
uint16_t total_len;
if (cds_is_load_unload_in_progress()) {
CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
"%s: Unloading/Loading in Progress. Ignore!!!",
__func__);
return;
}
if (nl_srv_is_initialized() != 0)
return;
if (cds_is_multicast_logging()) {
data_len = pHdr->len;
total_len = sizeof(tAniHdr) + sizeof(uint32_t) + data_len;
pBuf = (uint8_t *) cdf_mem_malloc(total_len);
if (!pBuf) {
CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
"cdf_mem_malloc failed");
return;
}
cdf_mem_zero((void *)pBuf, total_len);
wmsg = (tAniHdr *) pBuf;
wmsg->type = PTT_MSG_DIAG_CMDS_TYPE;
wmsg->length = total_len;
wmsg->length = DIAG_SWAP16(wmsg->length);
pBuf += sizeof(tAniHdr);
/* Diag Type events or log */
*(uint32_t *) pBuf = DIAG_TYPE_LOGS;
pBuf += sizeof(uint32_t);
memcpy(pBuf, pHdr, data_len);
ptt_sock_send_msg_to_app (wmsg, 0, ANI_NL_MSG_PUMAC,
INVALID_PID);
cdf_mem_free((void *)wmsg);
}
return;
}
/**
* host_diag_log_wlock() - This function is used to send wake lock diag events
* @reason: Reason why the wakelock was taken or released
* @wake_lock_name: Function in which the wakelock was taken or released
* @timeout: Timeout value in case of timed wakelocks
* @status: Status field indicating whether the wake lock was taken/released
*
* This function is used to send wake lock diag events to user space
*
* Return: None
*
*/
void host_diag_log_wlock(uint32_t reason, const char *wake_lock_name,
uint32_t timeout, uint32_t status)
{
WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
struct host_event_wlan_wake_lock);
if ((nl_srv_is_initialized() != 0) ||
(cds_is_wakelock_enabled() == false))
return;
wlan_diag_event.status = status;
wlan_diag_event.reason = reason;
wlan_diag_event.timeout = timeout;
wlan_diag_event.name_len = strlen(wake_lock_name);
strlcpy(&wlan_diag_event.name[0],
wake_lock_name,
wlan_diag_event.name_len+1);
WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_WAKE_LOCK);
}
/**---------------------------------------------------------------------------
\brief host_diag_event_report_payload() -
This function sends the event data to the ptt socket app only if it is
registered with the driver.
\param - ptr - Pointer to the log header type.
\return - None
--------------------------------------------------------------------------*/
void host_diag_event_report_payload(uint16_t event_Id, uint16_t length,
void *pPayload)
{
tAniHdr *wmsg = NULL;
uint8_t *pBuf;
event_report_t *pEvent_report;
uint16_t total_len;
if (cds_is_load_unload_in_progress()) {
CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO,
"%s: Unloading/Loading in Progress. Ignore!!!",
__func__);
return;
}
if (nl_srv_is_initialized() != 0)
return;
if (cds_is_multicast_logging()) {
total_len = sizeof(tAniHdr) + sizeof(event_report_t) + length;
pBuf = (uint8_t *) cdf_mem_malloc(total_len);
if (!pBuf) {
CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
"cdf_mem_malloc failed");
return;
}
wmsg = (tAniHdr *) pBuf;
wmsg->type = PTT_MSG_DIAG_CMDS_TYPE;
wmsg->length = total_len;
wmsg->length = DIAG_SWAP16(wmsg->length);
pBuf += sizeof(tAniHdr);
pEvent_report = (event_report_t *) pBuf;
pEvent_report->diag_type = DIAG_TYPE_EVENTS;
pEvent_report->event_id = event_Id;
pEvent_report->length = length;
pBuf += sizeof(event_report_t);
memcpy(pBuf, pPayload, length);
if (ptt_sock_send_msg_to_app
(wmsg, 0, ANI_NL_MSG_PUMAC, INVALID_PID) < 0) {
CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
"Ptt Socket error sending message to the app!!");
cdf_mem_free((void *)wmsg);
return;
}
cdf_mem_free((void *)wmsg);
}
return;
}