firesat-ci.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * FireSAT DVB driver
  3. *
  4. * Copyright (c) 2008 Henrik Kurelid <henrik@kurelid.se>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or (at your option) any later version.
  10. */
  11. #include "firesat-ci.h"
  12. #include "firesat.h"
  13. #include "avc_api.h"
  14. #include <linux/dvb/ca.h>
  15. #include <dvbdev.h>
  16. static unsigned int ca_debug = 0;
  17. module_param(ca_debug, int, 0644);
  18. MODULE_PARM_DESC(ca_debug, "debug logging of ca system, default is 0 (no)");
  19. static int firesat_ca_ready(ANTENNA_INPUT_INFO *info)
  20. {
  21. if (ca_debug != 0)
  22. printk("%s: CaMmi=%d, CaInit=%d, CaError=%d, CaDvb=%d, "
  23. "CaModule=%d, CaAppInfo=%d, CaDateTime=%d, "
  24. "CaPmt=%d\n", __func__, info->CaMmi,
  25. info->CaInitializationStatus, info->CaErrorFlag,
  26. info->CaDvbFlag, info->CaModulePresentStatus,
  27. info->CaApplicationInfo,
  28. info->CaDateTimeRequest, info->CaPmtReply);
  29. return info->CaInitializationStatus == 1 &&
  30. info->CaErrorFlag == 0 &&
  31. info->CaDvbFlag == 1 &&
  32. info->CaModulePresentStatus == 1;
  33. }
  34. static int firesat_get_ca_flags(ANTENNA_INPUT_INFO *info)
  35. {
  36. int flags = 0;
  37. if (info->CaModulePresentStatus == 1)
  38. flags |= CA_CI_MODULE_PRESENT;
  39. if (info->CaInitializationStatus == 1 &&
  40. info->CaErrorFlag == 0 &&
  41. info->CaDvbFlag == 1)
  42. flags |= CA_CI_MODULE_READY;
  43. return flags;
  44. }
  45. static int firesat_ca_reset(struct firesat *firesat)
  46. {
  47. if (ca_debug)
  48. printk(KERN_INFO "%s: ioctl CA_RESET\n", __func__);
  49. if (avc_ca_reset(firesat))
  50. return -EFAULT;
  51. return 0;
  52. }
  53. static int firesat_ca_get_caps(struct firesat *firesat, void *arg)
  54. {
  55. struct ca_caps *cap_p = (struct ca_caps*)arg;
  56. int err = 0;
  57. cap_p->slot_num = 1;
  58. cap_p->slot_type = CA_CI;
  59. cap_p->descr_num = 1;
  60. cap_p->descr_type = CA_ECD;
  61. if (ca_debug)
  62. printk(KERN_INFO "%s: ioctl CA_GET_CAP\n", __func__);
  63. return err;
  64. }
  65. static int firesat_ca_get_slot_info(struct firesat *firesat, void *arg)
  66. {
  67. ANTENNA_INPUT_INFO info;
  68. struct ca_slot_info *slot_p = (struct ca_slot_info*)arg;
  69. if (ca_debug)
  70. printk(KERN_INFO "%s: ioctl CA_GET_SLOT_INFO on slot %d.\n",
  71. __func__, slot_p->num);
  72. if (AVCTunerStatus(firesat, &info))
  73. return -EFAULT;
  74. if (slot_p->num == 0) {
  75. slot_p->type = CA_CI;
  76. slot_p->flags = firesat_get_ca_flags(&info);
  77. }
  78. else {
  79. return -EFAULT;
  80. }
  81. return 0;
  82. }
  83. static int firesat_ca_app_info(struct firesat *firesat, void *arg)
  84. {
  85. struct ca_msg *reply_p = (struct ca_msg*)arg;
  86. int i;
  87. if (avc_ca_app_info(firesat, reply_p->msg, &reply_p->length))
  88. return -EFAULT;
  89. if (ca_debug) {
  90. printk(KERN_INFO "%s: Creating TAG_APP_INFO message:",
  91. __func__);
  92. for (i = 0; i < reply_p->length; i++)
  93. printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
  94. printk("\n");
  95. }
  96. return 0;
  97. }
  98. static int firesat_ca_info(struct firesat *firesat, void *arg)
  99. {
  100. struct ca_msg *reply_p = (struct ca_msg*)arg;
  101. int i;
  102. if (avc_ca_info(firesat, reply_p->msg, &reply_p->length))
  103. return -EFAULT;
  104. if (ca_debug) {
  105. printk(KERN_INFO "%s: Creating TAG_CA_INFO message:",
  106. __func__);
  107. for (i = 0; i < reply_p->length; i++)
  108. printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
  109. printk("\n");
  110. }
  111. return 0;
  112. }
  113. static int firesat_ca_get_mmi(struct firesat *firesat, void *arg)
  114. {
  115. struct ca_msg *reply_p = (struct ca_msg*)arg;
  116. int i;
  117. if (avc_ca_get_mmi(firesat, reply_p->msg, &reply_p->length))
  118. return -EFAULT;
  119. if (ca_debug) {
  120. printk(KERN_INFO "%s: Creating MMI reply INFO message:",
  121. __func__);
  122. for (i = 0; i < reply_p->length; i++)
  123. printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
  124. printk("\n");
  125. }
  126. return 0;
  127. }
  128. static int firesat_ca_get_msg(struct firesat *firesat, void *arg)
  129. {
  130. int err;
  131. ANTENNA_INPUT_INFO info;
  132. switch (firesat->ca_last_command) {
  133. case TAG_APP_INFO_ENQUIRY:
  134. err = firesat_ca_app_info(firesat, arg);
  135. break;
  136. case TAG_CA_INFO_ENQUIRY:
  137. err = firesat_ca_info(firesat, arg);
  138. break;
  139. default:
  140. if (AVCTunerStatus(firesat, &info))
  141. err = -EFAULT;
  142. else if (info.CaMmi == 1) {
  143. err = firesat_ca_get_mmi(firesat, arg);
  144. }
  145. else {
  146. printk(KERN_INFO "%s: Unhandled message 0x%08X\n",
  147. __func__, firesat->ca_last_command);
  148. err = -EFAULT;
  149. }
  150. }
  151. firesat->ca_last_command = 0;
  152. return err;
  153. }
  154. static int firesat_ca_pmt(struct firesat *firesat, void *arg)
  155. {
  156. struct ca_msg *msg_p = (struct ca_msg*)arg;
  157. int data_pos;
  158. if (msg_p->msg[3] & 0x80)
  159. data_pos = (msg_p->msg[4] && 0x7F) + 4;
  160. else
  161. data_pos = 4;
  162. if (avc_ca_pmt(firesat, &msg_p->msg[data_pos],
  163. msg_p->length - data_pos))
  164. return -EFAULT;
  165. return 0;
  166. }
  167. static int firesat_ca_send_msg(struct firesat *firesat, void *arg)
  168. {
  169. int err;
  170. struct ca_msg *msg_p = (struct ca_msg*)arg;
  171. // Do we need a semaphore for this?
  172. firesat->ca_last_command =
  173. (msg_p->msg[0] << 16) + (msg_p->msg[1] << 8) + msg_p->msg[2];
  174. switch (firesat->ca_last_command) {
  175. case TAG_CA_PMT:
  176. if (ca_debug != 0)
  177. printk(KERN_INFO "%s: Message received: TAG_CA_PMT\n",
  178. __func__);
  179. err = firesat_ca_pmt(firesat, arg);
  180. break;
  181. case TAG_APP_INFO_ENQUIRY:
  182. // This is all handled in ca_get_msg
  183. if (ca_debug != 0)
  184. printk(KERN_INFO "%s: Message received: "
  185. "TAG_APP_INFO_ENQUIRY\n", __func__);
  186. err = 0;
  187. break;
  188. case TAG_CA_INFO_ENQUIRY:
  189. // This is all handled in ca_get_msg
  190. if (ca_debug != 0)
  191. printk(KERN_INFO "%s: Message received: "
  192. "TAG_CA_APP_INFO_ENQUIRY\n", __func__);
  193. err = 0;
  194. break;
  195. case TAG_ENTER_MENU:
  196. if (ca_debug != 0)
  197. printk(KERN_INFO "%s: Entering CA menu.\n", __func__);
  198. err = avc_ca_enter_menu(firesat);
  199. break;
  200. default:
  201. printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n",
  202. __func__, firesat->ca_last_command);
  203. err = -EFAULT;
  204. }
  205. return err;
  206. }
  207. static int firesat_ca_ioctl(struct inode *inode, struct file *file,
  208. unsigned int cmd, void *arg)
  209. {
  210. struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
  211. struct firesat *firesat = dvbdev->priv;
  212. int err;
  213. ANTENNA_INPUT_INFO info;
  214. switch(cmd) {
  215. case CA_RESET:
  216. err = firesat_ca_reset(firesat);
  217. break;
  218. case CA_GET_CAP:
  219. err = firesat_ca_get_caps(firesat, arg);
  220. break;
  221. case CA_GET_SLOT_INFO:
  222. err = firesat_ca_get_slot_info(firesat, arg);
  223. break;
  224. case CA_GET_MSG:
  225. err = firesat_ca_get_msg(firesat, arg);
  226. break;
  227. case CA_SEND_MSG:
  228. err = firesat_ca_send_msg(firesat, arg);
  229. break;
  230. default:
  231. printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__,
  232. cmd);
  233. err = -EOPNOTSUPP;
  234. }
  235. if (AVCTunerStatus(firesat, &info))
  236. return err;
  237. firesat_ca_ready(&info);
  238. return err;
  239. }
  240. static int firesat_get_date_time_request(struct firesat *firesat)
  241. {
  242. if (ca_debug)
  243. printk(KERN_INFO "%s: Retrieving Time/Date request\n",
  244. __func__);
  245. if (avc_ca_get_time_date(firesat, &firesat->ca_time_interval))
  246. return -EFAULT;
  247. if (ca_debug)
  248. printk(KERN_INFO "%s: Time/Date interval is %d\n",
  249. __func__, firesat->ca_time_interval);
  250. return 0;
  251. }
  252. static int firesat_ca_io_open(struct inode *inode, struct file *file)
  253. {
  254. if (ca_debug != 0)
  255. printk(KERN_INFO "%s\n",__func__);
  256. return dvb_generic_open(inode, file);
  257. }
  258. static int firesat_ca_io_release(struct inode *inode, struct file *file)
  259. {
  260. if (ca_debug != 0)
  261. printk(KERN_INFO "%s\n",__func__);
  262. return dvb_generic_release(inode, file);
  263. }
  264. static unsigned int firesat_ca_io_poll(struct file *file, poll_table *wait)
  265. {
  266. if (ca_debug != 0)
  267. printk(KERN_INFO "%s\n",__func__);
  268. return POLLIN;
  269. }
  270. static struct file_operations firesat_ca_fops = {
  271. .owner = THIS_MODULE,
  272. .read = NULL, // There is no low level read anymore
  273. .write = NULL, // There is no low level write anymore
  274. .ioctl = dvb_generic_ioctl,
  275. .open = firesat_ca_io_open,
  276. .release = firesat_ca_io_release,
  277. .poll = firesat_ca_io_poll,
  278. };
  279. static struct dvb_device firesat_ca = {
  280. .priv = NULL,
  281. .users = 1,
  282. .readers = 1,
  283. .writers = 1,
  284. .fops = &firesat_ca_fops,
  285. .kernel_ioctl = firesat_ca_ioctl,
  286. };
  287. int firesat_ca_init(struct firesat *firesat)
  288. {
  289. int err;
  290. ANTENNA_INPUT_INFO info;
  291. if (AVCTunerStatus(firesat, &info))
  292. return -EINVAL;
  293. if (firesat_ca_ready(&info)) {
  294. err = dvb_register_device(firesat->adapter,
  295. &firesat->cadev,
  296. &firesat_ca, firesat,
  297. DVB_DEVICE_CA);
  298. if (info.CaApplicationInfo == 0)
  299. printk(KERN_ERR "%s: CaApplicationInfo is not set.\n",
  300. __func__);
  301. if (info.CaDateTimeRequest == 1)
  302. firesat_get_date_time_request(firesat);
  303. }
  304. else
  305. err = -EFAULT;
  306. return err;
  307. }
  308. void firesat_ca_release(struct firesat *firesat)
  309. {
  310. if (firesat->cadev)
  311. dvb_unregister_device(firesat->cadev);
  312. }