firedtv-ci.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * FireDTV driver (formerly known as FireSAT)
  3. *
  4. * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
  5. * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. */
  12. #include <linux/dvb/ca.h>
  13. #include <linux/fs.h>
  14. #include <linux/module.h>
  15. #include <dvbdev.h>
  16. #include "avc.h"
  17. #include "firedtv.h"
  18. #include "firedtv-ci.h"
  19. static int fdtv_ca_ready(ANTENNA_INPUT_INFO *info)
  20. {
  21. return info->CaInitializationStatus == 1 &&
  22. info->CaErrorFlag == 0 &&
  23. info->CaDvbFlag == 1 &&
  24. info->CaModulePresentStatus == 1;
  25. }
  26. static int fdtv_get_ca_flags(ANTENNA_INPUT_INFO *info)
  27. {
  28. int flags = 0;
  29. if (info->CaModulePresentStatus == 1)
  30. flags |= CA_CI_MODULE_PRESENT;
  31. if (info->CaInitializationStatus == 1 &&
  32. info->CaErrorFlag == 0 &&
  33. info->CaDvbFlag == 1)
  34. flags |= CA_CI_MODULE_READY;
  35. return flags;
  36. }
  37. static int fdtv_ca_reset(struct firedtv *fdtv)
  38. {
  39. return avc_ca_reset(fdtv) ? -EFAULT : 0;
  40. }
  41. static int fdtv_ca_get_caps(void *arg)
  42. {
  43. struct ca_caps *cap = arg;
  44. cap->slot_num = 1;
  45. cap->slot_type = CA_CI;
  46. cap->descr_num = 1;
  47. cap->descr_type = CA_ECD;
  48. return 0;
  49. }
  50. static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
  51. {
  52. ANTENNA_INPUT_INFO info;
  53. struct ca_slot_info *slot = arg;
  54. if (avc_tuner_status(fdtv, &info))
  55. return -EFAULT;
  56. if (slot->num != 0)
  57. return -EFAULT;
  58. slot->type = CA_CI;
  59. slot->flags = fdtv_get_ca_flags(&info);
  60. return 0;
  61. }
  62. static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
  63. {
  64. struct ca_msg *reply = arg;
  65. return
  66. avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
  67. }
  68. static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
  69. {
  70. struct ca_msg *reply = arg;
  71. return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
  72. }
  73. static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
  74. {
  75. struct ca_msg *reply = arg;
  76. return
  77. avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
  78. }
  79. static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
  80. {
  81. ANTENNA_INPUT_INFO info;
  82. int err;
  83. switch (fdtv->ca_last_command) {
  84. case TAG_APP_INFO_ENQUIRY:
  85. err = fdtv_ca_app_info(fdtv, arg);
  86. break;
  87. case TAG_CA_INFO_ENQUIRY:
  88. err = fdtv_ca_info(fdtv, arg);
  89. break;
  90. default:
  91. if (avc_tuner_status(fdtv, &info))
  92. err = -EFAULT;
  93. else if (info.CaMmi == 1)
  94. err = fdtv_ca_get_mmi(fdtv, arg);
  95. else {
  96. printk(KERN_INFO "%s: Unhandled message 0x%08X\n",
  97. __func__, fdtv->ca_last_command);
  98. err = -EFAULT;
  99. }
  100. }
  101. fdtv->ca_last_command = 0;
  102. return err;
  103. }
  104. static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
  105. {
  106. struct ca_msg *msg = arg;
  107. int data_pos;
  108. int data_length;
  109. int i;
  110. data_pos = 4;
  111. if (msg->msg[3] & 0x80) {
  112. data_length = 0;
  113. for (i = 0; i < (msg->msg[3] & 0x7F); i++)
  114. data_length = (data_length << 8) + msg->msg[data_pos++];
  115. } else {
  116. data_length = msg->msg[3];
  117. }
  118. return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ?
  119. -EFAULT : 0;
  120. }
  121. static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
  122. {
  123. struct ca_msg *msg = arg;
  124. int err;
  125. /* Do we need a semaphore for this? */
  126. fdtv->ca_last_command =
  127. (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
  128. switch (fdtv->ca_last_command) {
  129. case TAG_CA_PMT:
  130. err = fdtv_ca_pmt(fdtv, arg);
  131. break;
  132. case TAG_APP_INFO_ENQUIRY:
  133. /* handled in ca_get_msg */
  134. err = 0;
  135. break;
  136. case TAG_CA_INFO_ENQUIRY:
  137. /* handled in ca_get_msg */
  138. err = 0;
  139. break;
  140. case TAG_ENTER_MENU:
  141. err = avc_ca_enter_menu(fdtv);
  142. break;
  143. default:
  144. printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n",
  145. __func__, fdtv->ca_last_command);
  146. err = -EFAULT;
  147. }
  148. return err;
  149. }
  150. static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
  151. unsigned int cmd, void *arg)
  152. {
  153. struct dvb_device *dvbdev = file->private_data;
  154. struct firedtv *fdtv = dvbdev->priv;
  155. ANTENNA_INPUT_INFO info;
  156. int err;
  157. switch(cmd) {
  158. case CA_RESET:
  159. err = fdtv_ca_reset(fdtv);
  160. break;
  161. case CA_GET_CAP:
  162. err = fdtv_ca_get_caps(arg);
  163. break;
  164. case CA_GET_SLOT_INFO:
  165. err = fdtv_ca_get_slot_info(fdtv, arg);
  166. break;
  167. case CA_GET_MSG:
  168. err = fdtv_ca_get_msg(fdtv, arg);
  169. break;
  170. case CA_SEND_MSG:
  171. err = fdtv_ca_send_msg(fdtv, arg);
  172. break;
  173. default:
  174. printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__,
  175. cmd);
  176. err = -EOPNOTSUPP;
  177. }
  178. /* FIXME Is this necessary? */
  179. avc_tuner_status(fdtv, &info);
  180. return err;
  181. }
  182. static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
  183. {
  184. return POLLIN;
  185. }
  186. static struct file_operations fdtv_ca_fops = {
  187. .owner = THIS_MODULE,
  188. .ioctl = dvb_generic_ioctl,
  189. .open = dvb_generic_open,
  190. .release = dvb_generic_release,
  191. .poll = fdtv_ca_io_poll,
  192. };
  193. static struct dvb_device fdtv_ca = {
  194. .users = 1,
  195. .readers = 1,
  196. .writers = 1,
  197. .fops = &fdtv_ca_fops,
  198. .kernel_ioctl = fdtv_ca_ioctl,
  199. };
  200. int fdtv_ca_register(struct firedtv *fdtv)
  201. {
  202. ANTENNA_INPUT_INFO info;
  203. int err;
  204. if (avc_tuner_status(fdtv, &info))
  205. return -EINVAL;
  206. if (!fdtv_ca_ready(&info))
  207. return -EFAULT;
  208. err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
  209. &fdtv_ca, fdtv, DVB_DEVICE_CA);
  210. if (info.CaApplicationInfo == 0)
  211. printk(KERN_ERR "%s: CaApplicationInfo is not set.\n",
  212. __func__);
  213. if (info.CaDateTimeRequest == 1)
  214. avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
  215. return err;
  216. }
  217. void fdtv_ca_release(struct firedtv *fdtv)
  218. {
  219. if (fdtv->cadev)
  220. dvb_unregister_device(fdtv->cadev);
  221. }