root/drivers/media/firewire/firedtv-ci.c

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

DEFINITIONS

This source file includes following definitions.
  1. fdtv_ca_ready
  2. fdtv_get_ca_flags
  3. fdtv_ca_get_caps
  4. fdtv_ca_get_slot_info
  5. fdtv_ca_app_info
  6. fdtv_ca_info
  7. fdtv_ca_get_mmi
  8. fdtv_ca_get_msg
  9. fdtv_ca_pmt
  10. fdtv_ca_send_msg
  11. fdtv_ca_ioctl
  12. fdtv_ca_io_poll
  13. fdtv_ca_register
  14. fdtv_ca_release

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * FireDTV driver (formerly known as FireSAT)
   4  *
   5  * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
   6  * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
   7  */
   8 
   9 #include <linux/device.h>
  10 #include <linux/dvb/ca.h>
  11 #include <linux/fs.h>
  12 #include <linux/module.h>
  13 
  14 #include <media/dvbdev.h>
  15 
  16 #include "firedtv.h"
  17 
  18 #define EN50221_TAG_APP_INFO_ENQUIRY    0x9f8020
  19 #define EN50221_TAG_CA_INFO_ENQUIRY     0x9f8030
  20 #define EN50221_TAG_CA_PMT              0x9f8032
  21 #define EN50221_TAG_ENTER_MENU          0x9f8022
  22 
  23 static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
  24 {
  25         return stat->ca_initialization_status   == 1 &&
  26                stat->ca_error_flag              == 0 &&
  27                stat->ca_dvb_flag                == 1 &&
  28                stat->ca_module_present_status   == 1;
  29 }
  30 
  31 static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
  32 {
  33         int flags = 0;
  34 
  35         if (stat->ca_module_present_status == 1)
  36                 flags |= CA_CI_MODULE_PRESENT;
  37         if (stat->ca_initialization_status == 1 &&
  38             stat->ca_error_flag            == 0 &&
  39             stat->ca_dvb_flag              == 1)
  40                 flags |= CA_CI_MODULE_READY;
  41         return flags;
  42 }
  43 
  44 static int fdtv_ca_get_caps(void *arg)
  45 {
  46         struct ca_caps *cap = arg;
  47 
  48         cap->slot_num = 1;
  49         cap->slot_type = CA_CI;
  50         cap->descr_num = 1;
  51         cap->descr_type = CA_ECD;
  52         return 0;
  53 }
  54 
  55 static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
  56 {
  57         struct firedtv_tuner_status stat;
  58         struct ca_slot_info *slot = arg;
  59         int err;
  60 
  61         err = avc_tuner_status(fdtv, &stat);
  62         if (err)
  63                 return err;
  64 
  65         if (slot->num != 0)
  66                 return -EACCES;
  67 
  68         slot->type = CA_CI;
  69         slot->flags = fdtv_get_ca_flags(&stat);
  70         return 0;
  71 }
  72 
  73 static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
  74 {
  75         struct ca_msg *reply = arg;
  76 
  77         return avc_ca_app_info(fdtv, reply->msg, &reply->length);
  78 }
  79 
  80 static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
  81 {
  82         struct ca_msg *reply = arg;
  83 
  84         return avc_ca_info(fdtv, reply->msg, &reply->length);
  85 }
  86 
  87 static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
  88 {
  89         struct ca_msg *reply = arg;
  90 
  91         return avc_ca_get_mmi(fdtv, reply->msg, &reply->length);
  92 }
  93 
  94 static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
  95 {
  96         struct firedtv_tuner_status stat;
  97         int err;
  98 
  99         switch (fdtv->ca_last_command) {
 100         case EN50221_TAG_APP_INFO_ENQUIRY:
 101                 err = fdtv_ca_app_info(fdtv, arg);
 102                 break;
 103         case EN50221_TAG_CA_INFO_ENQUIRY:
 104                 err = fdtv_ca_info(fdtv, arg);
 105                 break;
 106         default:
 107                 err = avc_tuner_status(fdtv, &stat);
 108                 if (err)
 109                         break;
 110                 if (stat.ca_mmi == 1)
 111                         err = fdtv_ca_get_mmi(fdtv, arg);
 112                 else {
 113                         dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
 114                                  fdtv->ca_last_command);
 115                         err = -EACCES;
 116                 }
 117         }
 118         fdtv->ca_last_command = 0;
 119         return err;
 120 }
 121 
 122 static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
 123 {
 124         struct ca_msg *msg = arg;
 125         int data_pos;
 126         int data_length;
 127         int i;
 128 
 129         data_pos = 4;
 130         if (msg->msg[3] & 0x80) {
 131                 data_length = 0;
 132                 for (i = 0; i < (msg->msg[3] & 0x7f); i++)
 133                         data_length = (data_length << 8) + msg->msg[data_pos++];
 134         } else {
 135                 data_length = msg->msg[3];
 136         }
 137 
 138         return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
 139 }
 140 
 141 static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
 142 {
 143         struct ca_msg *msg = arg;
 144         int err;
 145 
 146         /* Do we need a semaphore for this? */
 147         fdtv->ca_last_command =
 148                 (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
 149         switch (fdtv->ca_last_command) {
 150         case EN50221_TAG_CA_PMT:
 151                 err = fdtv_ca_pmt(fdtv, arg);
 152                 break;
 153         case EN50221_TAG_APP_INFO_ENQUIRY:
 154                 /* handled in ca_get_msg */
 155                 err = 0;
 156                 break;
 157         case EN50221_TAG_CA_INFO_ENQUIRY:
 158                 /* handled in ca_get_msg */
 159                 err = 0;
 160                 break;
 161         case EN50221_TAG_ENTER_MENU:
 162                 err = avc_ca_enter_menu(fdtv);
 163                 break;
 164         default:
 165                 dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
 166                         fdtv->ca_last_command);
 167                 err = -EACCES;
 168         }
 169         return err;
 170 }
 171 
 172 static int fdtv_ca_ioctl(struct file *file, unsigned int cmd, void *arg)
 173 {
 174         struct dvb_device *dvbdev = file->private_data;
 175         struct firedtv *fdtv = dvbdev->priv;
 176         struct firedtv_tuner_status stat;
 177         int err;
 178 
 179         switch (cmd) {
 180         case CA_RESET:
 181                 err = avc_ca_reset(fdtv);
 182                 break;
 183         case CA_GET_CAP:
 184                 err = fdtv_ca_get_caps(arg);
 185                 break;
 186         case CA_GET_SLOT_INFO:
 187                 err = fdtv_ca_get_slot_info(fdtv, arg);
 188                 break;
 189         case CA_GET_MSG:
 190                 err = fdtv_ca_get_msg(fdtv, arg);
 191                 break;
 192         case CA_SEND_MSG:
 193                 err = fdtv_ca_send_msg(fdtv, arg);
 194                 break;
 195         default:
 196                 dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
 197                 err = -EOPNOTSUPP;
 198         }
 199 
 200         /* FIXME Is this necessary? */
 201         avc_tuner_status(fdtv, &stat);
 202 
 203         return err;
 204 }
 205 
 206 static __poll_t fdtv_ca_io_poll(struct file *file, poll_table *wait)
 207 {
 208         return EPOLLIN;
 209 }
 210 
 211 static const struct file_operations fdtv_ca_fops = {
 212         .owner          = THIS_MODULE,
 213         .unlocked_ioctl = dvb_generic_ioctl,
 214         .open           = dvb_generic_open,
 215         .release        = dvb_generic_release,
 216         .poll           = fdtv_ca_io_poll,
 217         .llseek         = noop_llseek,
 218 };
 219 
 220 static const struct dvb_device fdtv_ca = {
 221         .users          = 1,
 222         .readers        = 1,
 223         .writers        = 1,
 224         .fops           = &fdtv_ca_fops,
 225         .kernel_ioctl   = fdtv_ca_ioctl,
 226 };
 227 
 228 int fdtv_ca_register(struct firedtv *fdtv)
 229 {
 230         struct firedtv_tuner_status stat;
 231         int err;
 232 
 233         if (avc_tuner_status(fdtv, &stat))
 234                 return -EINVAL;
 235 
 236         if (!fdtv_ca_ready(&stat))
 237                 return -EFAULT;
 238 
 239         err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
 240                                   &fdtv_ca, fdtv, DVB_DEVICE_CA, 0);
 241 
 242         if (stat.ca_application_info == 0)
 243                 dev_err(fdtv->device, "CaApplicationInfo is not set\n");
 244         if (stat.ca_date_time_request == 1)
 245                 avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
 246 
 247         return err;
 248 }
 249 
 250 void fdtv_ca_release(struct firedtv *fdtv)
 251 {
 252         dvb_unregister_device(fdtv->cadev);
 253 }

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