blob: 08a80e8cdb6c6c0aa0f080da54cf5ab49f5796a7 [file] [log] [blame]
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#ifndef _SWDEMUX_INTERNAL_H
#define _SWDEMUX_INTERNAL_H
#include "swdemux.h"
#ifdef __KERNEL__
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include "../dmx_log.h"
#else
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**Double linked list node.*/
struct swdmx_list {
struct swdmx_list *prev; /**< The previous node in the list.*/
struct swdmx_list *next; /**< The next node in the list.*/
};
/**Callback entry.*/
struct swdmx_cb_entry {
struct swdmx_list ln; /**< List node data.*/
void *cb; /**< Callback function.*/
void *data; /**< User defined data.*/
};
/**TS packet parser.*/
struct swdmx_ts_parser {
int packet_size; /**< Packet size.*/
struct swdmx_list cb_list; /**< Callback list.*/
};
/**Demux PID filter.*/
struct swdmx_pid_filter {
struct swdmx_list ln; /**< List node data.*/
u16 pid; /**< PID.*/
struct swdmx_list ts_filter_list; /**< TS filter list.*/
struct swdmx_list sec_filter_list; /**< Section filter list.*/
u8 *sec_data; /**< Section data buffer.*/
int sec_recv; /**< Section data received*/
};
/**Demux.*/
struct swdmx_demux {
struct swdmx_list pid_filter_list; /**< PID filter list.*/
struct swdmx_list ts_filter_list; /**< TS filter list.*/
struct swdmx_list sec_filter_list; /**< Section filter list.*/
};
/**Filter's state.*/
enum swdmx_filter_state {
SWDMX_FILTER_STATE_INIT, /**< Initialized.*/
SWDMX_FILTER_STATE_SET, /**< Parameters has been set.*/
SWDMX_FILTER_STATE_RUN /**< Running.*/
};
/**TS filter.*/
struct swdmx_tsfilter {
struct swdmx_demux *dmx;
/**< The demux contains this filter.*/
struct swdmx_list ln;
/**< List node data.*/
struct swdmx_list pid_ln;
/**< List node used in PID filter.*/
struct swdmx_pid_filter *pid_filter;
/**< The PID filter contains this TS filter.*/
enum swdmx_filter_state state;
/**< State of the filter.*/
struct swdmx_tsfilter_params params;
/**< Parameters.*/
struct swdmx_list cb_list;
/**< Callback list.*/
};
/**Section filter.*/
struct swdmx_secfilter {
struct swdmx_demux *dmx;
/**< The demux contains this filter.*/
struct swdmx_list ln;
/**< List node data.*/
struct swdmx_list pid_ln;
/**< List node used in PID filter.*/
struct swdmx_pid_filter *pid_filter;
/**< The PID filter contains this section filter.*/
enum swdmx_filter_state state;
/**< State of the filter.*/
struct swdmx_secfilter_params params;
/**< Parameters.*/
u8 value[SWDMX_SEC_FILTER_LEN + 2];
/**< Value array.*/
u8 mam[SWDMX_SEC_FILTER_LEN + 2];
/**< Mask & mode array.*/
u8 manm[SWDMX_SEC_FILTER_LEN + 2];
/**< Mask & ~mode array.*/
struct swdmx_list cb_list; /**< Callback list.*/
};
#define SWDMX_ASSERT(a) do {} while (!(a))
#define SWDMX_PTR2SIZE(p) ((size_t)(p))
#define SWDMX_SIZE2PTR(s) ((void *)(size_t)(s))
#define SWDMX_OFFSETOF(s, m)\
SWDMX_PTR2SIZE(&((s *)0)->m)
#define SWDMX_CONTAINEROF(p, s, m)\
((s *)(SWDMX_PTR2SIZE(p) - SWDMX_OFFSETOF(s, m)))
/**
* Output log message.
* \param fmt Output format string.
* \param ... Variable arguments.
*/
/*static inline void
*swdmx_log(const char *fmt, ...)
*{
* va_list ap;
*
* fprintf(stderr, "SWDMX: ");
*
* va_start(ap, fmt);
* vfprintf(stderr, fmt, ap);
* va_end(ap);
*
* fprintf(stderr, "\n");
*}
*/
#define swdmx_log(f, a...) \
dprintk(LOG_DBG, 0, "%s:" f, __func__, ## a)
/**
* Check if the PID is valid.
* \param pid The PID.
* \retval SWDMX_TRUE The PID is valid.
* \retval SWDMX_FALSE The PID is invalid.
*/
static inline u8
swdmx_is_valid_pid(u16 pid)
{
return (pid <= 0x1fff);
}
/**
* Allocate a new memory buffer.
* \param size The size of the buffer.
* \return The new buffer's pointer.
*/
static inline void *
swdmx_malloc(size_t size)
{
return kmalloc(size, GFP_KERNEL);
}
/**
* Free an unused buffer.
* \param ptr The buffer to be freed.
*/
static inline void
swdmx_free(void *ptr)
{
kfree(ptr);
}
/**
* Check if the list is empty.
* \param l The list.
* \retval SWDMX_TRUE The list is empty.
* \retval SWDMX_FALSE The list is not empty.
*/
static inline u8
swdmx_list_is_empty(struct swdmx_list *l)
{
return l->next == l;
}
/**
* Initialize a list node.
* \param n The node to be initialize.
*/
static inline void
swdmx_list_init(struct swdmx_list *n)
{
n->prev = n;
n->next = n;
}
/**
* Append a node to the list.
* \param l The list.
* \param n The node to be added.
*/
static inline void
swdmx_list_append(struct swdmx_list *l, struct swdmx_list *n)
{
n->prev = l->prev;
n->next = l;
l->prev->next = n;
l->prev = n;
}
/**
* Remove a node from the list.
* \param n The node to be removed.
*/
static inline void
swdmx_list_remove(struct swdmx_list *n)
{
n->prev->next = n->next;
n->next->prev = n->prev;
}
/*Traverse the nodes in the list.*/
#define SWDMX_LIST_FOR_EACH(i, l, m)\
for ((i) = SWDMX_CONTAINEROF((l)->next, typeof(*i), m);\
(i) != SWDMX_CONTAINEROF(l, typeof(*i), m);\
(i) = SWDMX_CONTAINEROF((i)->m.next,\
typeof(*i), m))
/*Traverse the nodes in the list safely.*/
#define SWDMX_LIST_FOR_EACH_SAFE(i, n, l, m)\
for ((i) = SWDMX_CONTAINEROF((l)->next, typeof(*i), m),\
(n) = SWDMX_CONTAINEROF((i)->m.next,\
typeof(*i), m);\
(i) != SWDMX_CONTAINEROF(l, typeof(*i), m);\
(i) = (n),\
(n) = SWDMX_CONTAINEROF((i)->m.next,\
typeof(*i), m))
/**
* Add a callback to the list.
* \param l The callback list.
* \param cb The callback function.
* \param data The user defined parameter.
*/
extern void
swdmx_cb_list_add(struct swdmx_list *l, void *cb, void *data);
/**
* Remove a callback from the list.
* \param l The callback list.
* \param cb The callback function to be removed.
* \param data The user defined parameter.
*/
extern void
swdmx_cb_list_remove(struct swdmx_list *l, void *cb, void *data);
/**
* Clear the callback list.
* \param l The callback list to be cleared.
*/
extern void
swdmx_cb_list_clear(struct swdmx_list *l);
/**
* CRC32.
*/
extern u32
swdmx_crc32(const u8 *data, int len);
#ifdef __cplusplus
}
#endif
#endif