diff --git a/ddbridge/dvb_netstream.c b/ddbridge/dvb_netstream.c new file mode 100644 index 0000000..f49fc96 --- /dev/null +++ b/ddbridge/dvb_netstream.c @@ -0,0 +1,259 @@ +/* + * dvb_netstream.c: support for DVB to network streaming hardware + * + * Copyright (C) 2012-2013 Marcus and Ralph Metzler + * for Digital Devices GmbH + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include "dvb_netstream.h" + +static ssize_t ns_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + pr_info("%s\n", __func__); + return 0; +} + +static ssize_t ns_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + pr_info("%s\n", __func__); + return 0; +} + +static unsigned int ns_poll(struct file *file, poll_table *wait) +{ + pr_info("%s\n", __func__); + return 0; +} + +static int ns_stop(struct dvbnss *nss) +{ + struct dvb_netstream *ns = nss->ns; + + mutex_lock(&ns->mutex); + if (nss->running && ns->stop) { + ns->stop(nss); + nss->running = 0; + } + mutex_unlock(&ns->mutex); + return 0; +} + +static int ns_release(struct inode *inode, struct file *file) +{ + struct dvbnss *nss = file->private_data; + struct dvb_netstream *ns = nss->ns; + + ns_stop(nss); + if (ns->free) + ns->free(nss); + mutex_lock(&ns->mutex); + list_del(&nss->nssl); + mutex_unlock(&ns->mutex); + vfree(nss); + return 0; +} + +static int ns_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_netstream *ns = dvbdev->priv; + struct dvbnss *nss; + + nss = vmalloc(sizeof(*nss)); + if (!nss) + return -ENOMEM; + nss->ns = ns; + if (ns->alloc && ns->alloc(nss) < 0) { + vfree(nss); + return -EBUSY; + } + file->private_data = nss; + nss->running = 0; + mutex_lock(&ns->mutex); + list_add(&nss->nssl, &ns->nssl); + mutex_unlock(&ns->mutex); + return 0; +} + +static int set_net(struct dvbnss *nss, struct dvb_ns_params *p) +{ + return 0; +} + +static int do_ioctl(struct file *file, unsigned int cmd, void *parg) +{ + struct dvbnss *nss = file->private_data; + struct dvb_netstream *ns = nss->ns; + /*unsigned long arg = (unsigned long) parg;*/ + int ret = 0; + + switch (cmd) { + case NS_SET_RTCP_MSG: + { + struct dvb_ns_rtcp *rtcpm = parg; + + if (ns->set_rtcp_msg) + ret = ns->set_rtcp_msg(nss, rtcpm->msg, rtcpm->len); + break; + } + + case NS_SET_NET: + memcpy(&nss->params, parg, sizeof(nss->params)); + if (ns->set_net) + ret = ns->set_net(nss); + else + ret = set_net(nss, (struct dvb_ns_params *) parg); + break; + + case NS_START: + mutex_lock(&ns->mutex); + if (nss->running) { + ret = -EBUSY; + } else if (ns->start) { + ret = ns->start(nss); + nss->running = 1; + } + mutex_unlock(&ns->mutex); + break; + + case NS_STOP: + ns_stop(nss); + break; + + case NS_SET_PACKETS: + { + struct dvb_ns_packet *packet = parg; + + if (ns->set_ts_packets) + ret = ns->set_ts_packets(nss, packet->buf, + packet->count * 188); + break; + } + + case NS_INSERT_PACKETS: + { + u8 count = *(u8 *) parg; + + if (ns->insert_ts_packets) + ret = ns->insert_ts_packets(nss, count); + break; + } + + case NS_SET_PID: + { + u16 pid = *(u16 *) parg; + u16 byte = (pid & 0x1fff) >> 3; + u8 bit = 1 << (pid & 7); + + if (pid & 0x2000) { + if (pid & 0x8000) + memset(nss->pids, 0xff, 0x400); + else + memset(nss->pids, 0x00, 0x400); + } else { + if (pid & 0x8000) + nss->pids[byte] |= bit; + else + nss->pids[byte] &= ~bit; + } + if (ns->set_pid) + ret = ns->set_pid(nss, pid); + break; + } + + case NS_SET_PIDS: + ret = copy_from_user(nss->pids, *(u8 **) parg, 0x400); + if (ret < 0) + return ret; + if (ns->set_pids) + ret = ns->set_pids(nss); + break; + + case NS_SET_CI: + { + u8 ci = *(u8 *) parg; + + if (nss->running) + ret = -EBUSY; + else if (ns->set_ci) + ret = ns->set_ci(nss, ci); + break; + } + + default: + ret = -EINVAL; + break; + } + return ret; +} + +static long ns_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return dvb_usercopy(file, cmd, arg, do_ioctl); +} + +static const struct file_operations ns_fops = { + .owner = THIS_MODULE, + .read = ns_read, + .write = ns_write, + .open = ns_open, + .release = ns_release, + .poll = ns_poll, + .mmap = 0, + .unlocked_ioctl = ns_ioctl, +}; + +static struct dvb_device ns_dev = { + .priv = 0, + .readers = 1, + .writers = 1, + .users = 1, + .fops = &ns_fops, +}; + + +int dvb_netstream_init(struct dvb_adapter *dvb_adapter, + struct dvb_netstream *ns) +{ + mutex_init(&ns->mutex); + spin_lock_init(&ns->lock); + ns->exit = 0; + dvb_register_device(dvb_adapter, &ns->dvbdev, &ns_dev, ns, + DVB_DEVICE_NS, 0); + INIT_LIST_HEAD(&ns->nssl); + return 0; +} +//EXPORT_SYMBOL(dvb_netstream_init); + +void dvb_netstream_release(struct dvb_netstream *ns) +{ + ns->exit = 1; + if (ns->dvbdev->users > 1) { + wait_event(ns->dvbdev->wait_queue, + ns->dvbdev->users == 1); + } + dvb_unregister_device(ns->dvbdev); +} +//EXPORT_SYMBOL(dvb_netstream_release); diff --git a/ddbridge/dvb_netstream.h b/ddbridge/dvb_netstream.h new file mode 100644 index 0000000..a40f1f1 --- /dev/null +++ b/ddbridge/dvb_netstream.h @@ -0,0 +1,93 @@ +/* + * dvb_netstream.c: support for DVB to network streaming hardware + * + * Copyright (C) 2012-2013 Marcus and Ralph Metzler + * for Digital Devices GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef _DVB_NETSTREAM_H_ +#define _DVB_NETSTREAM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dvbdev.h" + +#define DVBNS_MAXPIDS 32 + +struct dvbnss { + struct dvb_netstream *ns; + void *priv; + + u8 pids[1024]; + u8 packet[1328]; + u32 pp; + + struct socket *sock; + struct sockaddr_in sadr; + u32 sn; + + struct dvb_ns_params params; + + struct list_head nssl; + int running; +}; + +#define MAX_DVBNSS 32 + +struct dvb_netstream { + void *priv; + + struct mutex mutex; + spinlock_t lock; + struct dvb_device *dvbdev; + int exit; + + struct list_head nssl; + + int (*set_net)(struct dvbnss *); + int (*set_pid)(struct dvbnss *, u16); + int (*set_pids)(struct dvbnss *); + int (*set_ci)(struct dvbnss *, u8); + int (*set_rtcp_msg)(struct dvbnss *, u8 *, u32); + int (*set_ts_packets)(struct dvbnss *, u8 *, u32); + int (*insert_ts_packets)(struct dvbnss *, u8); + int (*start)(struct dvbnss *); + int (*stop)(struct dvbnss *); + int (*alloc)(struct dvbnss *); + void (*free)(struct dvbnss *); +}; + + +void dvb_netstream_release(struct dvb_netstream *); +int dvb_netstream_init(struct dvb_adapter *, struct dvb_netstream *); + + +#endif