# 2.1. Digital TV Common functions¶

## 2.1.1. Math functions¶

Provide some commonly-used math functions, usually required in order to estimate signal strength and signal to noise measurements in dB.

unsigned int `intlog2`(u32 value)

computes log2 of a value; the result is shifted left by 24 bits

Parameters

`u32 value`
The value (must be != 0)

Description

to use rational values you can use the following method:

intlog2(value) = intlog2(value * 2^x) - x * 2^24

Some usecase examples:

intlog2(8) will give 3 << 24 = 3 * 2^24

intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24

intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24

Return

log2(value) * 2^24

unsigned int `intlog10`(u32 value)

computes log10 of a value; the result is shifted left by 24 bits

Parameters

`u32 value`
The value (must be != 0)

Description

to use rational values you can use the following method:

intlog10(value) = intlog10(value * 10^x) - x * 2^24

An usecase example:

intlog10(1000) will give 3 << 24 = 3 * 2^24

due to the implementation intlog10(1000) might be not exactly 3 * 2^24

look at intlog2 for similar examples

Return

log10(value) * 2^24

## 2.1.2. DVB devices¶

Those functions are responsible for handling the DVB device nodes.

enum `dvb_device_type`

type of the Digital TV device

Constants

`DVB_DEVICE_SEC`
Digital TV standalone Common Interface (CI)
`DVB_DEVICE_FRONTEND`
Digital TV frontend.
`DVB_DEVICE_DEMUX`
Digital TV demux.
`DVB_DEVICE_DVR`
Digital TV digital video record (DVR).
`DVB_DEVICE_CA`
Digital TV Conditional Access (CA).
`DVB_DEVICE_NET`
Digital TV network.
`DVB_DEVICE_VIDEO`
Digital TV video decoder. Deprecated. Used only on av7110-av.
`DVB_DEVICE_AUDIO`
Digital TV audio decoder. Deprecated. Used only on av7110-av.
`DVB_DEVICE_OSD`
Digital TV On Screen Display (OSD). Deprecated. Used only on av7110.
struct `dvb_adapter`

represents a Digital TV adapter using Linux DVB API

Definition

```struct dvb_adapter {
int num;
const char * name;
u8 proposed_mac;
void * priv;
struct device * device;
struct module * module;
int mfe_shared;
struct dvb_device * mfe_dvbdev;
struct mutex mfe_lock;
#if defined(CONFIG_MEDIA_CONTROLLER_DVB
struct media_device * mdev;
struct media_entity * conn;
#endif
};
```

Members

`num`
`list_head`
`device_list`
List with the DVB devices
`name`
`proposed_mac`
`priv`
private data
`device`
pointer to struct device
`module`
pointer to struct module
`mfe_shared`
mfe shared: indicates mutually exclusive frontends Thie usage of this flag is currently deprecated
`mfe_dvbdev`
Frontend device in use, in the case of MFE
`mfe_lock`
Lock to prevent using the other frontends when MFE is used.
`mdev`
pointer to struct media_device, used when the media controller is used.
`conn`
RF connector. Used only if the device has no separate tuner.
`conn_pads`
pointer to struct media_pad associated with conn;
struct `dvb_device`

represents a DVB device node

Definition

```struct dvb_device {
const struct file_operations * fops;
enum dvb_device_type type;
int minor;
u32 id;
int writers;
int users;
int (* kernel_ioctl) (struct file *file, unsigned int cmd, void *arg);
#if defined(CONFIG_MEDIA_CONTROLLER_DVB
const char * name;
struct media_intf_devnode * intf_devnode;
unsigned tsout_num_entities;
struct media_entity * entity;
struct media_entity * tsout_entity;
#endif
void * priv;
};
```

Members

`list_head`
List head with all DVB devices
`fops`
pointer to struct file_operations
`adapter`
pointer to the adapter that holds this device node
`type`
type of the device, as defined by `enum dvb_device_type`.
`minor`
devnode minor number. Major number is always DVB_MAJOR.
`id`
device ID number, inside the adapter
`readers`
Initialized by the caller. Each call to `open()` in Read Only mode decreases this counter by one.
`writers`
Initialized by the caller. Each call to `open()` in Read/Write mode decreases this counter by one.
`users`
Initialized by the caller. Each call to `open()` in any mode decreases this counter by one.
`wait_queue`
wait queue, used to wait for certain events inside one of the DVB API callers
`kernel_ioctl`
callback function used to handle ioctl calls from userspace.
`name`
Name to be used for the device at the Media Controller
`intf_devnode`
Pointer to media_intf_devnode. Used by the dvbdev core to store the MC device node interface
`tsout_num_entities`
Number of Transport Stream output entities
`entity`
pointer to struct media_entity associated with the device node
`tsout_entity`
array with MC entities associated to each TS output node
`pads`
pointer to struct media_pad associated with entity;
`tsout_pads`
array with the source pads for each tsout_entity
`priv`
private data

Description

This structure is used by the DVB core (frontend, CA, net, demux) in order to create the device nodes. Usually, driver should not initialize this struct diretly.

int `dvb_register_adapter`(struct dvb_adapter * adap, const char * name, struct module * module, struct device * device, short * adapter_nums)

Parameters

`struct dvb_adapter * adap`
`const char * name`
`struct module * module`
initialized with THIS_MODULE at the caller
`struct device * device`
pointer to struct device that corresponds to the device driver
`short * adapter_nums`
Array with a list of the numbers for dvb_register_adapter; to select among them. Typically, initialized with: DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums)
int `dvb_unregister_adapter`(struct dvb_adapter * adap)

Parameters

`struct dvb_adapter * adap`
int `dvb_register_device`(struct dvb_adapter * adap, struct dvb_device ** pdvbdev, const struct dvb_device * template, void * priv, enum dvb_device_type type, int demux_sink_pads)

Registers a new DVB device

Parameters

`struct dvb_adapter * adap`
`struct dvb_device ** pdvbdev`
pointer to the place where the new struct dvb_device will be stored
`const struct dvb_device * template`
Template used to create `pdvbdev`;
`void * priv`
private data
`enum dvb_device_type type`
type of the device, as defined by `enum dvb_device_type`.
`int demux_sink_pads`
Number of demux outputs, to be used to create the TS outputs via the Media Controller.
void `dvb_remove_device`(struct dvb_device * dvbdev)

Remove a registered DVB device

Parameters

`struct dvb_device * dvbdev`
pointer to struct dvb_device

Description

This does not free memory. To do that, call `dvb_free_device()`.

void `dvb_free_device`(struct dvb_device * dvbdev)

Free memory occupied by a DVB device.

Parameters

`struct dvb_device * dvbdev`
pointer to struct dvb_device

Description

Call `dvb_unregister_device()` before calling this function.

void `dvb_unregister_device`(struct dvb_device * dvbdev)

Unregisters a DVB device

Parameters

`struct dvb_device * dvbdev`
pointer to struct dvb_device

Description

This is a combination of `dvb_remove_device()` and `dvb_free_device()`. Using this function is usually a mistake, and is often an indicator for a use-after-free bug (when a userspace process keeps a file handle to a detached device).

int `dvb_create_media_graph`(struct dvb_adapter * adap, bool create_rf_connector)

Creates media graph for the Digital TV part of the device.

Parameters

`struct dvb_adapter * adap`
pointer to `struct dvb_adapter`
`bool create_rf_connector`
if true, it creates the RF connector too

Description

This function checks all DVB-related functions at the media controller entities and creates the needed links for the media graph. It is capable of working with multiple tuners or multiple frontends, but it won’t create links if the device has multiple tuners and multiple frontends or if the device has multiple muxes. In such case, the caller driver should manually create the remaining links.

void `dvb_register_media_controller`(struct dvb_adapter * adap, struct media_device * mdev)

registers a media controller at DVB adapter

Parameters

`struct dvb_adapter * adap`
pointer to `struct dvb_adapter`
`struct media_device * mdev`
pointer to `struct media_device`
struct media_device * `dvb_get_media_controller`(struct dvb_adapter * adap)

gets the associated media controller

Parameters

`struct dvb_adapter * adap`
pointer to `struct dvb_adapter`
int `dvb_generic_open`(struct inode * inode, struct file * file)

Digital TV open function, used by DVB devices

Parameters

`struct inode * inode`
pointer to `struct inode`.
`struct file * file`
pointer to `struct file`.

Description

Checks if a DVB devnode is still valid, and if the permissions are OK and increment negative use count.

int `dvb_generic_release`(struct inode * inode, struct file * file)

Digital TV close function, used by DVB devices

Parameters

`struct inode * inode`
pointer to `struct inode`.
`struct file * file`
pointer to `struct file`.

Description

Checks if a DVB devnode is still valid, and if the permissions are OK and decrement negative use count.

long `dvb_generic_ioctl`(struct file * file, unsigned int cmd, unsigned long arg)

Digital TV close function, used by DVB devices

Parameters

`struct file * file`
pointer to `struct file`.
`unsigned int cmd`
Ioctl name.
`unsigned long arg`
Ioctl argument.

Description

Checks if a DVB devnode and struct dvbdev.kernel_ioctl is still valid. If so, calls `dvb_usercopy()`.

int `dvb_usercopy`(struct file * file, unsigned int cmd, unsigned long arg, int (*func) (struct file *file, unsigned int cmd, void *arg)

copies data from/to userspace memory when an ioctl is issued.

Parameters

`struct file * file`
Pointer to struct `file`.
`unsigned int cmd`
Ioctl name.
`unsigned long arg`
Ioctl argument.
`int (*)(struct file *file, unsigned int cmd, void *arg) func`
function that will actually handle the ioctl

Description

Ancillary function that uses ioctl direction and size to copy from userspace. Then, it calls func, and, if needed, data is copied back to userspace.

`dvb_attach`(FUNCTION, ARGS...)

attaches a DVB frontend into the DVB core.

Parameters

`FUNCTION`
function on a frontend module to be called.
`ARGS...`
FUNCTION arguments.

Description

This ancillary function loads a frontend module in runtime and runs the FUNCTION function there, with ARGS. As it increments symbol usage cont, at unregister, `dvb_detach()` should be called.

`dvb_detach`(FUNC)

detaches a DVB frontend loaded via `dvb_attach()`

Parameters

`FUNC`
attach function

Description

Decrements usage count for a function previously called via `dvb_attach()`.

## 2.1.3. Digital TV Ring buffer¶

Those routines implement ring buffers used to handle digital TV data and copy it from/to userspace.

Note

1. For performance reasons read and write routines don’t check buffer sizes and/or number of bytes free/available. This has to be done before these routines are called. For example:
```/* write @buflen: bytes */
free = dvb_ringbuffer_free(rbuf);
if (free >= buflen)
count = dvb_ringbuffer_write(rbuf, buffer, buflen);
else
/* do something */

/* read min. 1000, max. @bufsize: bytes */
avail = dvb_ringbuffer_avail(rbuf);
if (avail >= 1000)
count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
else
/* do something */
```
1. If there is exactly one reader and one writer, there is no need to lock read or write operations. Two or more readers must be locked against each other. Flushing the buffer counts as a read operation. Resetting the buffer counts as a read and write operation. Two or more writers must be locked against each other.
struct `dvb_ringbuffer`

Describes a ring buffer used at DVB framework

Definition

```struct dvb_ringbuffer {
u8 * data;
ssize_t size;
ssize_t pwrite;
int error;
spinlock_t lock;
};
```

Members

`data`
Area were the ringbuffer data is written
`size`
size of the ringbuffer
`pread`
`pwrite`
next position to write
`error`
used by ringbuffer clients to indicate that an error happened.
`queue`
Wait queue used by ringbuffer clients to indicate when buffer was filled
`lock`
Spinlock used to protect the ringbuffer
void `dvb_ringbuffer_init`(struct dvb_ringbuffer * rbuf, void * data, size_t len)

initialize ring buffer, lock and queue

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer
`void * data`
pointer to the buffer where the data will be stored
`size_t len`
bytes from ring buffer into buf
int `dvb_ringbuffer_empty`(struct dvb_ringbuffer * rbuf)

test whether buffer is empty

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer
ssize_t `dvb_ringbuffer_free`(struct dvb_ringbuffer * rbuf)

returns the number of free bytes in the buffer

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer

Return

number of free bytes in the buffer

ssize_t `dvb_ringbuffer_avail`(struct dvb_ringbuffer * rbuf)

returns the number of bytes waiting in the buffer

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer

Return

number of bytes waiting in the buffer

void `dvb_ringbuffer_reset`(struct dvb_ringbuffer * rbuf)

resets the ringbuffer to initial state

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer

Description

Resets the read and write pointers to zero and flush the buffer.

This counts as a read and write operation

void `dvb_ringbuffer_flush`(struct dvb_ringbuffer * rbuf)

flush buffer

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer
void `dvb_ringbuffer_flush_spinlock_wakeup`(struct dvb_ringbuffer * rbuf)

flush buffer protected by spinlock and wake-up waiting task(s)

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer
`DVB_RINGBUFFER_PEEK`(rbuf, offs)

peek at byte offs in the buffer

Parameters

`rbuf`
pointer to struct dvb_ringbuffer
`offs`
offset inside the ringbuffer
`DVB_RINGBUFFER_SKIP`(rbuf, num)

Parameters

`rbuf`
pointer to struct dvb_ringbuffer
`num`
ssize_t `dvb_ringbuffer_read_user`(struct dvb_ringbuffer * rbuf, u8 __user * buf, size_t len)

Reads a buffer into a user pointer

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer
`u8 __user * buf`
pointer to the buffer where the data will be stored
`size_t len`
bytes from ring buffer into buf

Description

This variant assumes that the buffer is a memory at the userspace. So, it will internally call `copy_to_user()`.

Return

number of bytes transferred or -EFAULT

void `dvb_ringbuffer_read`(struct dvb_ringbuffer * rbuf, u8 * buf, size_t len)

Reads a buffer into a pointer

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer
`u8 * buf`
pointer to the buffer where the data will be stored
`size_t len`
bytes from ring buffer into buf

Description

This variant assumes that the buffer is a memory at the Kernel space

Return

number of bytes transferred or -EFAULT

`DVB_RINGBUFFER_WRITE_BYTE`(rbuf, byte)

write single byte to ring buffer

Parameters

`rbuf`
pointer to struct dvb_ringbuffer
`byte`
byte to write
ssize_t `dvb_ringbuffer_write`(struct dvb_ringbuffer * rbuf, const u8 * buf, size_t len)

Writes a buffer into the ringbuffer

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer
`const u8 * buf`
pointer to the buffer where the data will be read
`size_t len`
bytes from ring buffer into buf

Description

This variant assumes that the buffer is a memory at the Kernel space

Return

number of bytes transferred or -EFAULT

ssize_t `dvb_ringbuffer_write_user`(struct dvb_ringbuffer * rbuf, const u8 __user * buf, size_t len)

Writes a buffer received via a user pointer

Parameters

`struct dvb_ringbuffer * rbuf`
pointer to struct dvb_ringbuffer
`const u8 __user * buf`
pointer to the buffer where the data will be read
`size_t len`
bytes from ring buffer into buf

Description

This variant assumes that the buffer is a memory at the userspace. So, it will internally call `copy_from_user()`.

Return

number of bytes transferred or -EFAULT

ssize_t `dvb_ringbuffer_pkt_write`(struct dvb_ringbuffer * rbuf, u8 * buf, size_t len)

Write a packet into the ringbuffer.

Parameters

`struct dvb_ringbuffer * rbuf`
Ringbuffer to write to.
`u8 * buf`
Buffer to write.
`size_t len`
Length of buffer (currently limited to 65535 bytes max).

Return

Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.

ssize_t `dvb_ringbuffer_pkt_read_user`(struct dvb_ringbuffer * rbuf, size_t idx, int offset, u8 __user * buf, size_t len)

Read from a packet in the ringbuffer.

Parameters

`struct dvb_ringbuffer * rbuf`
Ringbuffer concerned.
`size_t idx`
Packet index as returned by `dvb_ringbuffer_pkt_next()`.
`int offset`
Offset into packet to read from.
`u8 __user * buf`
Destination buffer for data.
`size_t len`
Size of destination buffer.

Return

Number of bytes read, or -EFAULT.

Note

unlike `dvb_ringbuffer_read()`, this does NOT update the read pointer in the ringbuffer. You must use `dvb_ringbuffer_pkt_dispose()` to mark a packet as no longer required.

ssize_t `dvb_ringbuffer_pkt_read`(struct dvb_ringbuffer * rbuf, size_t idx, int offset, u8 * buf, size_t len)

Read from a packet in the ringbuffer.

Parameters

`struct dvb_ringbuffer * rbuf`
Ringbuffer concerned.
`size_t idx`
Packet index as returned by `dvb_ringbuffer_pkt_next()`.
`int offset`
Offset into packet to read from.
`u8 * buf`
Destination buffer for data.
`size_t len`
Size of destination buffer.

Note

unlike `dvb_ringbuffer_read_user()`, this DOES update the read pointer in the ringbuffer.

Return

Number of bytes read, or -EFAULT.

void `dvb_ringbuffer_pkt_dispose`(struct dvb_ringbuffer * rbuf, size_t idx)

Dispose of a packet in the ring buffer.

Parameters

`struct dvb_ringbuffer * rbuf`
Ring buffer concerned.
`size_t idx`
Packet index as returned by `dvb_ringbuffer_pkt_next()`.
ssize_t `dvb_ringbuffer_pkt_next`(struct dvb_ringbuffer * rbuf, size_t idx, size_t * pktlen)

Get the index of the next packet in a ringbuffer.

Parameters

`struct dvb_ringbuffer * rbuf`
Ringbuffer concerned.
`size_t idx`
Previous packet index, or -1 to return the first packet index.
`size_t * pktlen`
On success, will be updated to contain the length of the packet in bytes. returns Packet index (if >=0), or -1 if no packets available.