| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- /*
- * util functions for various ?zap implementations
- *
- * Copyright (C) 2001 Johannes Stezenbach (js@convergence.de)
- * for convergence integrated media
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <string.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <errno.h>
- #include <stdint.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <linux/dvb/frontend.h>
- #include <linux/dvb/dmx.h>
- int set_pesfilter(int dmxfd, int pid, int pes_type, int dvr)
- {
- struct dmx_pes_filter_params pesfilter;
- /* ignore this pid to allow radio services */
- if (pid < 0 || pid >= 0x1fff || (pid == 0 && pes_type != DMX_PES_OTHER))
- return 0;
- if (dvr) {
- int buffersize = 64 * 1024;
- if (ioctl(dmxfd, DMX_SET_BUFFER_SIZE, buffersize) == -1)
- perror("DMX_SET_BUFFER_SIZE failed");
- }
- pesfilter.pid = pid;
- pesfilter.input = DMX_IN_FRONTEND;
- pesfilter.output = dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER;
- pesfilter.pes_type = pes_type;
- pesfilter.flags = DMX_IMMEDIATE_START;
- if (ioctl(dmxfd, DMX_SET_PES_FILTER, &pesfilter) == -1) {
- fprintf(stderr, "DMX_SET_PES_FILTER failed "
- "(PID = 0x%04x): %d %m\n", pid, errno);
- return -1;
- }
- return 0;
- }
- int get_pmt_pid(char *dmxdev, int sid)
- {
- int patfd, count;
- int pmt_pid = 0;
- int patread = 0;
- int section_length;
- unsigned char buft[4096];
- unsigned char *buf = buft;
- struct dmx_sct_filter_params f;
- memset(&f, 0, sizeof(f));
- f.pid = 0;
- f.filter.filter[0] = 0x00;
- f.filter.mask[0] = 0xff;
- f.timeout = 0;
- f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;
- if ((patfd = open(dmxdev, O_RDWR)) < 0) {
- perror("openening pat demux failed");
- return -1;
- }
- if (ioctl(patfd, DMX_SET_FILTER, &f) == -1) {
- perror("ioctl DMX_SET_FILTER failed");
- close(patfd);
- return -1;
- }
- while (!patread) {
- if (((count = read(patfd, buf, sizeof(buft))) < 0) && errno == EOVERFLOW)
- count = read(patfd, buf, sizeof(buft));
- if (count < 0) {
- perror("read_sections: read error");
- close(patfd);
- return -1;
- }
- section_length = ((buf[1] & 0x0f) << 8) | buf[2];
- if (count != section_length + 3)
- continue;
- buf += 8;
- section_length -= 8;
- patread = 1; /* assumes one section contains the whole pat */
- while (section_length > 0) {
- int service_id = (buf[0] << 8) | buf[1];
- if (service_id == sid) {
- pmt_pid = ((buf[2] & 0x1f) << 8) | buf[3];
- section_length = 0;
- }
- buf += 4;
- section_length -= 4;
- }
- }
- close(patfd);
- return pmt_pid;
- }
- char *type_str[] = {
- "QPSK",
- "QAM",
- "OFDM",
- "ATSC",
- };
- /* to be used with v3 drivers */
- int check_frontend_v3(int fd, enum fe_type type)
- {
- struct dvb_frontend_info info;
- int ret;
- ret = ioctl(fd, FE_GET_INFO, &info);
- if (ret < 0) {
- perror("ioctl FE_GET_INFO failed");
- close(fd);
- ret = -1;
- goto exit;
- }
- if (info.type != type) {
- fprintf(stderr, "Not a valid %s device!\n", type_str[type]);
- close(fd);
- ret = -EINVAL;
- goto exit;
- }
- exit:
- return ret;
- }
- char *del_str[] = {
- "UNDEFINED",
- "DVB-C (A)",
- "DVB-C (B)",
- "DVB-T",
- "DSS",
- "DVB-S",
- "DVB-S2",
- "DVB-H",
- "ISDB-T",
- "ISDB-S",
- "ISDB-C",
- "ATSC",
- "ATSC-M/H",
- "DTMB",
- "CMMB",
- "DAB",
- "DVB-T2",
- "TURBO",
- "QAM (C)",
- };
- static int map_delivery_mode(fe_type_t *type, enum fe_delivery_system delsys)
- {
- switch (delsys) {
- case SYS_DSS:
- case SYS_DVBS:
- case SYS_DVBS2:
- case SYS_TURBO:
- *type = FE_QPSK;
- break;
- case SYS_DVBT:
- case SYS_DVBT2:
- case SYS_DVBH:
- case SYS_ISDBT:
- *type = FE_OFDM;
- break;
- case SYS_DVBC_ANNEX_A:
- case SYS_DVBC_ANNEX_C:
- *type = FE_QAM;
- break;
- case SYS_ATSC:
- case SYS_DVBC_ANNEX_B:
- *type = FE_ATSC;
- break;
- default:
- fprintf(stderr, "Delivery system unsupported, please report to linux-media ML\n");
- return -1;
- }
- return 0;
- }
- int get_property(int fd, uint32_t pcmd, uint32_t *len, uint8_t *data)
- {
- struct dtv_property p, *b;
- struct dtv_properties cmd;
- int ret;
- p.cmd = pcmd;
- cmd.num = 1;
- cmd.props = &p;
- b = &p;
- ret = ioctl(fd, FE_GET_PROPERTY, &cmd);
- if (ret < 0) {
- fprintf(stderr, "FE_SET_PROPERTY returned %d\n", ret);
- return -1;
- }
- memcpy(len, &b->u.buffer.len, sizeof (uint32_t));
- memcpy(data, b->u.buffer.data, *len);
- return 0;
- }
- int set_property(int fd, uint32_t cmd, uint32_t data)
- {
- struct dtv_property p, *b;
- struct dtv_properties c;
- int ret;
- p.cmd = cmd;
- c.num = 1;
- c.props = &p;
- b = &p;
- b->u.data = data;
- ret = ioctl(fd, FE_SET_PROPERTY, &c);
- if (ret < 0) {
- fprintf(stderr, "FE_SET_PROPERTY returned %d\n", ret);
- return -1;
- }
- return 0;
- }
- int dvbfe_get_delsys(int fd, fe_delivery_system_t *delsys)
- {
- uint32_t len;
- /* Buggy API design */
- return get_property(fd, DTV_DELIVERY_SYSTEM, &len, (uint8_t *)delsys);
- }
- int dvbfe_set_delsys(int fd, enum fe_delivery_system delsys)
- {
- return set_property(fd, DTV_DELIVERY_SYSTEM, delsys);
- }
- int dvbfe_enum_delsys(int fd, uint32_t *len, uint8_t *data)
- {
- return get_property(fd, DTV_ENUM_DELSYS, len, data);
- }
- int dvbfe_get_version(int fd, int *major, int *minor)
- {
- struct dtv_property p, *b;
- struct dtv_properties cmd;
- int ret;
- p.cmd = DTV_API_VERSION;
- cmd.num = 1;
- cmd.props = &p;
- b = &p;
- ret = ioctl(fd, FE_GET_PROPERTY, &cmd);
- if (ret < 0) {
- fprintf(stderr, "FE_GET_PROPERTY failed, ret=%d\n", ret);
- return -1;
- }
- *major = (b->u.data >> 8) & 0xff;
- *minor = b->u.data & 0xff;
- return 0;
- }
- int check_frontend_multi(int fd, enum fe_type type, uint32_t *mstd)
- {
- int ret;
- enum fe_type delmode;
- unsigned int i, valid_delsys = 0;
- uint32_t len;
- uint8_t data[32];
- ret = dvbfe_enum_delsys(fd, &len, data);
- if (ret) {
- fprintf(stderr, "enum_delsys failed, ret=%d\n", ret);
- ret = -EIO;
- goto exit;
- }
- fprintf(stderr, "\t FE_CAN { ");
- for (i = 0; i < len; i++) {
- if (i < len - 1)
- fprintf(stderr, "%s + ", del_str[data[i]]);
- else
- fprintf(stderr, "%s", del_str[data[i]]);
- }
- fprintf(stderr, " }\n");
- /* check whether frontend can support our delivery */
- for (i = 0; i < len; i++) {
- map_delivery_mode(&delmode, data[i]);
- if (type == delmode) {
- valid_delsys = 1;
- ret = 0;
- break;
- }
- }
- if (!valid_delsys) {
- fprintf(stderr, "Not a valid %s device!\n", type_str[type]);
- ret = -EINVAL;
- goto exit;
- }
- *mstd = len; /* mstd has supported delsys count */
- exit:
- return ret;
- }
- int check_frontend(int fd, enum fe_type type, uint32_t *mstd)
- {
- int major, minor, ret;
- ret = dvbfe_get_version(fd, &major, &minor);
- if (ret)
- goto exit;
- fprintf(stderr, "Version: %d.%d ", major, minor);
- if ((major == 5) && (minor > 8)) {
- ret = check_frontend_multi(fd, type, mstd);
- if (ret)
- goto exit;
- } else {
- ret = check_frontend_v3(fd, type);
- if (ret)
- goto exit;
- }
- exit:
- return ret;
- }
|