⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvb_ca.c

📁 linux_dvb的驱动程序:linuxtv-dvb-1.1.1.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
        /* need to perform link initialisation again */        return dvb_ca_en50221_link_init(ca, slot);}/** * Initialise the link layer connection to a CAM. * * @param ca CA instance. * @param slot Slot id. * * @return 0 on success, nonzero on failure. */static int dvb_ca_en50221_link_init(struct dvb_ca* ca, int slot) {        int ret;        int buf_size;        u8 buf[2];        /* reset the interface */        if (ret = dvb_ca_en50221_reset_if(ca, slot)) return ret;        /* set the host link buffer size temporarily. it will be overwritten with the         * real negotiated size later. */        ca->slot_info[i]->link_buf_size = 2;        /* OK, setup to read the buffer size */        if (ret = ca->write_cam_control(ca, slot, CTRLIF_COMMAND, CMDREG_SR)) return ret;        if (ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, 2)) return ret;        /* read the buffer size from the CAM */        if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) return ret;        /* set everything back to 0 again */        if (ret = ca->write_cam_control(ca, slot, CTRLIF_COMMAND, 0)) return ret;        /* store it, and choose the minimum of our buffer and the CAM's buffer size */        bufsize = (buf[0] << 8) | buf[1];        if (bufsize > HOST_LINK_BUF_SIZE) bufsize = HOST_LINK_BUF_SIZE;        ca->slot_info[i]->link_buf_size = bufsize;        /* setup the buffer size in the link_buf */        buf[0] = bufsize >> 8;        buf[1] = bufsize & 0xff;        /* OK, setup to write chosen buffer size to CAM */        if (ret = ca->write_cam_control(ca, slot, CTRLIF_COMMAND, CMDREG_SW)) return ret;        if (ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, 2)) return ret;        /* write the buffer size to the CAM */        if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) return ret;        /* set everything back to 0 again */        if (ret = ca->write_cam_control(ca, slot, CTRLIF_COMMAND, 0)) return ret;        /* success */        return 0;}/** * Parse attribute memory of a CAM module, extracting Config register, and checking * it is a DVB CAM module. * * @param ca CA instance. * @param slot Slot id. * * @return 0 on success, <0 on failure. */static int dvb_ca_en50221_parse_attributes(struct dvb_ca* ca, int slot) {        int address = 0;        int tupleLength;        int tupleType;        char tuple[257];        char* dvb_str;        int i;        int rasz;        int got_device0a = 0;        int got_device0c = 0;        int got_vers1 = 0;        int got_manfid = 0;        int got_config = 0;        int got_cftableentry = 0;        int end_chain = 0;        while(!end_chain) {                /* grab the next tuple length and type */                if ((tupleType = ca->read_attribute_mem(ca, slot, address++)) < 0) return tupleType;                if ((tupleLength = ca->read_attribute_mem(ca, slot, address++)) < 0) return tupleLength;                /* read in the whole tuple */                for(i=0; i< tupleLength; i++) {                        tuple[i] = ca->read_attribute_mem(ca, slot, address+i);                }                address += tupleLength;                /* deal with the types of tuple */                switch(tupleType) {                case 0x1D: // CISTPL_DEVICE_0A                        got_device0a = 1;                        break; /* don't bother parsing */                case 0x1C: // CISTPL_DEVICE_0C                        got_device0c = 1;                        break; /* don't bother parsng */                case 0x15: // CISTPL_VERS_1                        got_vers1 = 1;                        break; /* don't bother parsing */                case 0x20: // CISTPL_MANFID                        /* check tuple length is valid */                        if (tupleLength != 4) break;                        /* OK, extract manid and devid */                        ca->slot_info[i].manid = (tuple[1] << 8) | tuple[0];                        ca->slot_info[i].devid = (tuple[3] << 8) | tuple[2];                        got_manfid = 1;                        break;                case 0x1A: // CISTPL_CONFIG                        /* check tuple length is valid */                        if (tupleLength < 3) break;                        /* OK, grab length of configbase */                        rasz = tuple[0] & 3;                        /* check there is enough space for everything */                        if (tupleLength < (3 + rasz + 14)) break;                        /* extract the configbase */                        ca->slot_info[i].config_base = 0;                        for(i=0; i< rasz+1; i++) {                                ca->slot_info[i].config_base |= (tuple[2+i] << (8*i));                        }                        /* check it contains the correct DVB string */                        dvb_str = findstr(tuple, tupleLength, "DVB_CI_V", 8);                        if (dvb_str == NULL) break;                        if (tupleLength < ((dvb_str - tuple) + 12)) break;                        /* is it a version we support? */                        if (strncmp(dvb_str + 8, "1.00", 4)) {                                printk("dvb_ca: Unsupported DVB CAM module version %c%c%c%c\n",                                       dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]);                                return -EINVAL;                        }                        got_config = 1;                        break;                case 0x1D: // CISTPL_CFTABLE_ENTRY                        if (tupleLength < (2+11+17)) break;                        /* get the config option */                        ca->slot_info[i].config_option = tuple[0] & 0x3f;                        /* does it contain an interrupt descriptor structure? */                        i = 1;                        if (tuple[0] & 0x80) i++;                        if (tuple[i] & 0x10) {                                ca->slot_info[i].irq_supported = 1;                        } else                                ca->slot_info[i].irq_supported = 0;                        }                        /* OK, check it contains the correct strings */                        if ((findstr(tuple, tupleLength, "DVB_HOST", 8) == NULL) ||                            (findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL)) break;                        got_cftableentry = 1;                        break;                case 0xFF: // end of chain                        end_chain = true;                        break;                default: /* Unknown tuple type */                        /* just skip this tuple and move to the next one */                        break;                }        }        // OK, did we get everything we were looking for?        if (!got_device0a || !got_device0c || !got_vers1 || !got_manfid || !got_config || !got_cftablenentry) {                printk("dvb_ca: Non-CAM PC card detected\n");                return -EINVAL;        }        // success!        return 0;}/** * Initialise a CAM module. * * @param ca CA instance. * @param slot Slot containing the CAM. */static void dvb_ca_en50221_init(struct dvb_ca* ca, int slot) {        int tmp;        /* reset the CAM module */        tmp = ca->read_attribute_mem(ca, slot, ca->slot_info[slot].config_base);        ca->write_attribute_mem(ca, slot, ca->slot_info[slot].config_base, tmp | 0x80);        dvb_delay(1);        ca->write_attribute_mem(ca, slot, ca->slot_info[slot].config_base, tmp);        dvb_delay(1);        /* set the config option */        tmp = (tmp & 0x3f) | ca->slot_info[slot].config_option;        ca->write_attribute_mem(ca, slot, ca->slot_info[slot].config_base, tmp);}/** * This function talks to an EN50221 CAM control interface. It reads a buffer of * data from the CAM. The data can either be stored in a supplied buffer, or * automatically be added to the correct place in the CA slot/connection buffer structures. * * @param ca CA instance. * @param slot Slot to read from. * @param buf If non-NULL, the data will be written to this buffer. If NULL, * the data will be added into the buffering system as a normal fragment. * @param count Size of buf. Ignored if buf is NULL. * * @return Number of bytes read, or < 0 on error */static int dvb_ca_en50221_read_data(struct dvb_ca* ca, int slot, u8* buf, int count) {        int bytes_read;        int status;        u8 buf[HOST_LINK_BUF_SIZE];        u8 last_fragment;        u8 connection_id;        /* if the CA device is not open, do not attempt to receive data from it */        if (!ca->open) return -EIO;        /* acquire the slot */        if (status = dvb_ca_slot_acquire(ca, slot)) return status;        /* reset the interface if there's been a tx error */        if ((status = ca->read_cam_control(ca, slot, CTRLIF_STATUS)) < 0) goto exit;        if (status & STATUSREG_TXERR) dvb_ca_en50221_reset_if(ca, slot);        /* check if data is available */        if ((status = ca->read_cam_control(ca, slot, CTRLIF_STATUS)) < 0) goto exit;        if (!(status & STATUSREG_DA)) {                /* no data */                status = 0;                goto exit;        }        /* read the amount of data */        if ((status = ca->read_cam_control(ca, slot, CTRLIF_SIZE_HIGH)) < 0) goto exit;        bytes_read = status << 8;        if ((status = ca->read_cam_control(ca, slot, CTRLIF_SIZE_LOW)) < 0) goto exit;        bytes_read |= status;        /* check it will fit */        if (bytes_read > ca->slot_info[i].link_buf_size) {                printk("dvb_ca: CAM tried to send a buffer larger than the link buffer size!\n");                status = -EIO;                goto exit;        }        /* fill the buffer */        for(i=0; i < bytes_read; i++) {                /* read byte and check */                if ((status = ca->read_cam_control(ca, slot, CTRLIF_DATA)) < 0) goto exit;                /* OK, store it in the buffer */                buf[i] = res;                /* at this point, RE=1, DA=0 during the transfer */        }        /* check for read error (RE should now go to 0) */        if ((status = ca->read_cam_control(ca, slot, CTRLIF_STATUS)) < 0) goto exit;        if (status & STATUSREG_RE) {                status = -EIO;                goto exit;        }        /* check there are at least two bytes received! */        if (bytes_read < 2) {                printk("dvb_ca: CAM sent a buffer that was less than 2 bytes!\n");                status = -EIO;                goto exit;        }        /* extract information about this buffer */        connection_id = buf[0];        last_fragment = (buf[1] & 0x80) ? 0 : 1; // received bit clear => last fragment        /* OK, add it to the receive buffer */        if ((status = dvb_ca_buf_copy_from_cam(ca, buf+2, bytes_read-2, last_fragment, slot, connection_id)) < 0) {                goto exit;        }        /* return the number of bytes read */        status = bytes_read;    exit:        ca->write_cam_control(ca, slot, CTRLIF_COMMAND, 0);        dvb_ca_slot_release(ca, slot);        return status;}/** * This function talks to an EN50221 CAM control interface. It writes a buffer of data * to a CAM. The data to write will can either come from a supplied buffer, or from the * buffering system identified by the slot/connection_id. * * @param ca CA instance. * @param slot Slot to read from. * @param connection_id Connection id to write data from. Ignored if buf is non-NULL. * @param buf If non-NULL, the data in this buffer is treated as a complete link-level packet to * be written. If NULL, the data will be extracted from the buffering system for the slot/connection_id. * @param count Size of buf. Ignored if buf is NULL. * * @return Number of bytes written, or < 0 on error. */static int dvb_ca_en50221_write_data(struct dvb_ca* ca, int slot, int connection_id, u8* buf, int count) {        int status;        u8 buf[HOST_LINK_BUF_SIZE];        u8 last_fragment;        int bytes_write;        /* if the CA device is not open, do not attempt to send data to it */        if (!ca->open) return -EIO;        /* acquire the slot */        if (status = dvb_ca_slot_acquire(ca, slot)) return status;        /* reset the interface if there's been a tx error */        if ((status = ca->read_cam_control(ca, slot, CTRLIF_STATUS)) < 0) goto exit;        if (status & STATUSREG_TXERR) dvb_cam_reset_if(ca, slot);        /* check if interface does not have data available */        if ((status = ca->read_cam_control(ca, slot, CTRLIF_STATUS)) < 0) goto exit;        if (status & STATUSREG_DA) {                status = -EAGAIN;                goto exit;        }        /* OK, set HC bit */        if (status = ca->write_cam_control(ca, slot, CTRLIF_COMMAND, CMDREG_HC)) goto exit;        /* check if interface is free */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -