root/drivers/media/pci/ttpci/av7110_ca.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. CI_handle
  2. ci_get_data
  3. ci_ll_init
  4. ci_ll_flush
  5. ci_ll_release
  6. ci_ll_reset
  7. ci_ll_write
  8. ci_ll_read
  9. dvb_ca_open
  10. dvb_ca_poll
  11. dvb_ca_ioctl
  12. dvb_ca_write
  13. dvb_ca_read
  14. av7110_ca_register
  15. av7110_ca_unregister
  16. av7110_ca_init
  17. av7110_ca_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * av7110_ca.c: CA and CI stuff
   4  *
   5  * Copyright (C) 1999-2002 Ralph  Metzler
   6  *                       & Marcus Metzler for convergence integrated media GmbH
   7  *
   8  * originally based on code by:
   9  * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
  10  *
  11  * the project's page is at https://linuxtv.org
  12  */
  13 
  14 #include <linux/kernel.h>
  15 #include <linux/types.h>
  16 #include <linux/delay.h>
  17 #include <linux/fs.h>
  18 #include <linux/timer.h>
  19 #include <linux/poll.h>
  20 #include <linux/gfp.h>
  21 
  22 #include "av7110.h"
  23 #include "av7110_hw.h"
  24 #include "av7110_ca.h"
  25 
  26 
  27 void CI_handle(struct av7110 *av7110, u8 *data, u16 len)
  28 {
  29         dprintk(8, "av7110:%p\n",av7110);
  30 
  31         if (len < 3)
  32                 return;
  33         switch (data[0]) {
  34         case CI_MSG_CI_INFO:
  35                 if (data[2] != 1 && data[2] != 2)
  36                         break;
  37                 switch (data[1]) {
  38                 case 0:
  39                         av7110->ci_slot[data[2] - 1].flags = 0;
  40                         break;
  41                 case 1:
  42                         av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_PRESENT;
  43                         break;
  44                 case 2:
  45                         av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_READY;
  46                         break;
  47                 }
  48                 break;
  49         case CI_SWITCH_PRG_REPLY:
  50                 //av7110->ci_stat=data[1];
  51                 break;
  52         default:
  53                 break;
  54         }
  55 }
  56 
  57 
  58 void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len)
  59 {
  60         if (dvb_ringbuffer_free(cibuf) < len + 2)
  61                 return;
  62 
  63         DVB_RINGBUFFER_WRITE_BYTE(cibuf, len >> 8);
  64         DVB_RINGBUFFER_WRITE_BYTE(cibuf, len & 0xff);
  65         dvb_ringbuffer_write(cibuf, data, len);
  66         wake_up_interruptible(&cibuf->queue);
  67 }
  68 
  69 
  70 /******************************************************************************
  71  * CI link layer file ops
  72  ******************************************************************************/
  73 
  74 static int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size)
  75 {
  76         struct dvb_ringbuffer *tab[] = { cirbuf, ciwbuf, NULL }, **p;
  77         void *data;
  78 
  79         for (p = tab; *p; p++) {
  80                 data = vmalloc(size);
  81                 if (!data) {
  82                         while (p-- != tab) {
  83                                 vfree(p[0]->data);
  84                                 p[0]->data = NULL;
  85                         }
  86                         return -ENOMEM;
  87                 }
  88                 dvb_ringbuffer_init(*p, data, size);
  89         }
  90         return 0;
  91 }
  92 
  93 static void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
  94 {
  95         dvb_ringbuffer_flush_spinlock_wakeup(cirbuf);
  96         dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf);
  97 }
  98 
  99 static void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
 100 {
 101         vfree(cirbuf->data);
 102         cirbuf->data = NULL;
 103         vfree(ciwbuf->data);
 104         ciwbuf->data = NULL;
 105 }
 106 
 107 static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file,
 108                        int slots, struct ca_slot_info *slot)
 109 {
 110         int i;
 111         int len = 0;
 112         u8 msg[8] = { 0x00, 0x06, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00 };
 113 
 114         for (i = 0; i < 2; i++) {
 115                 if (slots & (1 << i))
 116                         len += 8;
 117         }
 118 
 119         if (dvb_ringbuffer_free(cibuf) < len)
 120                 return -EBUSY;
 121 
 122         for (i = 0; i < 2; i++) {
 123                 if (slots & (1 << i)) {
 124                         msg[2] = i;
 125                         dvb_ringbuffer_write(cibuf, msg, 8);
 126                         slot[i].flags = 0;
 127                 }
 128         }
 129 
 130         return 0;
 131 }
 132 
 133 static ssize_t ci_ll_write(struct dvb_ringbuffer *cibuf, struct file *file,
 134                            const char __user *buf, size_t count, loff_t *ppos)
 135 {
 136         int free;
 137         int non_blocking = file->f_flags & O_NONBLOCK;
 138         u8 *page = (u8 *)__get_free_page(GFP_USER);
 139         int res;
 140 
 141         if (!page)
 142                 return -ENOMEM;
 143 
 144         res = -EINVAL;
 145         if (count > 2048)
 146                 goto out;
 147 
 148         res = -EFAULT;
 149         if (copy_from_user(page, buf, count))
 150                 goto out;
 151 
 152         free = dvb_ringbuffer_free(cibuf);
 153         if (count + 2 > free) {
 154                 res = -EWOULDBLOCK;
 155                 if (non_blocking)
 156                         goto out;
 157                 res = -ERESTARTSYS;
 158                 if (wait_event_interruptible(cibuf->queue,
 159                                              (dvb_ringbuffer_free(cibuf) >= count + 2)))
 160                         goto out;
 161         }
 162 
 163         DVB_RINGBUFFER_WRITE_BYTE(cibuf, count >> 8);
 164         DVB_RINGBUFFER_WRITE_BYTE(cibuf, count & 0xff);
 165 
 166         res = dvb_ringbuffer_write(cibuf, page, count);
 167 out:
 168         free_page((unsigned long)page);
 169         return res;
 170 }
 171 
 172 static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file,
 173                           char __user *buf, size_t count, loff_t *ppos)
 174 {
 175         int avail;
 176         int non_blocking = file->f_flags & O_NONBLOCK;
 177         ssize_t len;
 178 
 179         if (!cibuf->data || !count)
 180                 return 0;
 181         if (non_blocking && (dvb_ringbuffer_empty(cibuf)))
 182                 return -EWOULDBLOCK;
 183         if (wait_event_interruptible(cibuf->queue,
 184                                      !dvb_ringbuffer_empty(cibuf)))
 185                 return -ERESTARTSYS;
 186         avail = dvb_ringbuffer_avail(cibuf);
 187         if (avail < 4)
 188                 return 0;
 189         len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
 190         len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
 191         if (avail < len + 2 || count < len)
 192                 return -EINVAL;
 193         DVB_RINGBUFFER_SKIP(cibuf, 2);
 194 
 195         return dvb_ringbuffer_read_user(cibuf, buf, len);
 196 }
 197 
 198 static int dvb_ca_open(struct inode *inode, struct file *file)
 199 {
 200         struct dvb_device *dvbdev = file->private_data;
 201         struct av7110 *av7110 = dvbdev->priv;
 202         int err = dvb_generic_open(inode, file);
 203 
 204         dprintk(8, "av7110:%p\n",av7110);
 205 
 206         if (err < 0)
 207                 return err;
 208         ci_ll_flush(&av7110->ci_rbuffer, &av7110->ci_wbuffer);
 209         return 0;
 210 }
 211 
 212 static __poll_t dvb_ca_poll (struct file *file, poll_table *wait)
 213 {
 214         struct dvb_device *dvbdev = file->private_data;
 215         struct av7110 *av7110 = dvbdev->priv;
 216         struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer;
 217         struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer;
 218         __poll_t mask = 0;
 219 
 220         dprintk(8, "av7110:%p\n",av7110);
 221 
 222         poll_wait(file, &rbuf->queue, wait);
 223         poll_wait(file, &wbuf->queue, wait);
 224 
 225         if (!dvb_ringbuffer_empty(rbuf))
 226                 mask |= (EPOLLIN | EPOLLRDNORM);
 227 
 228         if (dvb_ringbuffer_free(wbuf) > 1024)
 229                 mask |= (EPOLLOUT | EPOLLWRNORM);
 230 
 231         return mask;
 232 }
 233 
 234 static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg)
 235 {
 236         struct dvb_device *dvbdev = file->private_data;
 237         struct av7110 *av7110 = dvbdev->priv;
 238         unsigned long arg = (unsigned long) parg;
 239         int ret = 0;
 240 
 241         dprintk(8, "av7110:%p\n",av7110);
 242 
 243         if (mutex_lock_interruptible(&av7110->ioctl_mutex))
 244                 return -ERESTARTSYS;
 245 
 246         switch (cmd) {
 247         case CA_RESET:
 248                 ret = ci_ll_reset(&av7110->ci_wbuffer, file, arg,
 249                                   &av7110->ci_slot[0]);
 250                 break;
 251         case CA_GET_CAP:
 252         {
 253                 struct ca_caps cap;
 254 
 255                 cap.slot_num = 2;
 256                 cap.slot_type = (FW_CI_LL_SUPPORT(av7110->arm_app) ?
 257                                  CA_CI_LINK : CA_CI) | CA_DESCR;
 258                 cap.descr_num = 16;
 259                 cap.descr_type = CA_ECD;
 260                 memcpy(parg, &cap, sizeof(cap));
 261                 break;
 262         }
 263 
 264         case CA_GET_SLOT_INFO:
 265         {
 266                 struct ca_slot_info *info=(struct ca_slot_info *)parg;
 267 
 268                 if (info->num < 0 || info->num > 1) {
 269                         mutex_unlock(&av7110->ioctl_mutex);
 270                         return -EINVAL;
 271                 }
 272                 av7110->ci_slot[info->num].num = info->num;
 273                 av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
 274                                                         CA_CI_LINK : CA_CI;
 275                 memcpy(info, &av7110->ci_slot[info->num], sizeof(struct ca_slot_info));
 276                 break;
 277         }
 278 
 279         case CA_GET_MSG:
 280                 break;
 281 
 282         case CA_SEND_MSG:
 283                 break;
 284 
 285         case CA_GET_DESCR_INFO:
 286         {
 287                 struct ca_descr_info info;
 288 
 289                 info.num = 16;
 290                 info.type = CA_ECD;
 291                 memcpy(parg, &info, sizeof (info));
 292                 break;
 293         }
 294 
 295         case CA_SET_DESCR:
 296         {
 297                 struct ca_descr *descr = (struct ca_descr*) parg;
 298 
 299                 if (descr->index >= 16 || descr->parity > 1) {
 300                         mutex_unlock(&av7110->ioctl_mutex);
 301                         return -EINVAL;
 302                 }
 303                 av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetDescr, 5,
 304                               (descr->index<<8)|descr->parity,
 305                               (descr->cw[0]<<8)|descr->cw[1],
 306                               (descr->cw[2]<<8)|descr->cw[3],
 307                               (descr->cw[4]<<8)|descr->cw[5],
 308                               (descr->cw[6]<<8)|descr->cw[7]);
 309                 break;
 310         }
 311 
 312         default:
 313                 ret = -EINVAL;
 314                 break;
 315         }
 316 
 317         mutex_unlock(&av7110->ioctl_mutex);
 318         return ret;
 319 }
 320 
 321 static ssize_t dvb_ca_write(struct file *file, const char __user *buf,
 322                             size_t count, loff_t *ppos)
 323 {
 324         struct dvb_device *dvbdev = file->private_data;
 325         struct av7110 *av7110 = dvbdev->priv;
 326 
 327         dprintk(8, "av7110:%p\n",av7110);
 328         return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos);
 329 }
 330 
 331 static ssize_t dvb_ca_read(struct file *file, char __user *buf,
 332                            size_t count, loff_t *ppos)
 333 {
 334         struct dvb_device *dvbdev = file->private_data;
 335         struct av7110 *av7110 = dvbdev->priv;
 336 
 337         dprintk(8, "av7110:%p\n",av7110);
 338         return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos);
 339 }
 340 
 341 static const struct file_operations dvb_ca_fops = {
 342         .owner          = THIS_MODULE,
 343         .read           = dvb_ca_read,
 344         .write          = dvb_ca_write,
 345         .unlocked_ioctl = dvb_generic_ioctl,
 346         .open           = dvb_ca_open,
 347         .release        = dvb_generic_release,
 348         .poll           = dvb_ca_poll,
 349         .llseek         = default_llseek,
 350 };
 351 
 352 static struct dvb_device dvbdev_ca = {
 353         .priv           = NULL,
 354         .users          = 1,
 355         .writers        = 1,
 356         .fops           = &dvb_ca_fops,
 357         .kernel_ioctl   = dvb_ca_ioctl,
 358 };
 359 
 360 
 361 int av7110_ca_register(struct av7110 *av7110)
 362 {
 363         return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev,
 364                                    &dvbdev_ca, av7110, DVB_DEVICE_CA, 0);
 365 }
 366 
 367 void av7110_ca_unregister(struct av7110 *av7110)
 368 {
 369         dvb_unregister_device(av7110->ca_dev);
 370 }
 371 
 372 int av7110_ca_init(struct av7110* av7110)
 373 {
 374         return ci_ll_init(&av7110->ci_rbuffer, &av7110->ci_wbuffer, 8192);
 375 }
 376 
 377 void av7110_ca_exit(struct av7110* av7110)
 378 {
 379         ci_ll_release(&av7110->ci_rbuffer, &av7110->ci_wbuffer);
 380 }

/* [<][>][^][v][top][bottom][index][help] */