firedtv-dvb.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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/bitops.h>
  13. #include <linux/device.h>
  14. #include <linux/errno.h>
  15. #include <linux/kernel.h>
  16. #include <linux/mod_devicetable.h>
  17. #include <linux/module.h>
  18. #include <linux/mutex.h>
  19. #include <linux/slab.h>
  20. #include <linux/string.h>
  21. #include <linux/types.h>
  22. #include <linux/wait.h>
  23. #include <linux/workqueue.h>
  24. #include <dmxdev.h>
  25. #include <dvb_demux.h>
  26. #include <dvbdev.h>
  27. #include <dvb_frontend.h>
  28. #include "firedtv.h"
  29. static int alloc_channel(struct firedtv *fdtv)
  30. {
  31. int i;
  32. for (i = 0; i < 16; i++)
  33. if (!__test_and_set_bit(i, &fdtv->channel_active))
  34. break;
  35. return i;
  36. }
  37. static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
  38. {
  39. int i, n;
  40. for (i = 0, n = 0; i < 16; i++)
  41. if (test_bit(i, &fdtv->channel_active))
  42. pid[n++] = fdtv->channel_pid[i];
  43. *pidc = n;
  44. }
  45. static inline void dealloc_channel(struct firedtv *fdtv, int i)
  46. {
  47. __clear_bit(i, &fdtv->channel_active);
  48. }
  49. int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
  50. {
  51. struct firedtv *fdtv = dvbdmxfeed->demux->priv;
  52. int pidc, c, ret;
  53. u16 pids[16];
  54. switch (dvbdmxfeed->type) {
  55. case DMX_TYPE_TS:
  56. case DMX_TYPE_SEC:
  57. break;
  58. default:
  59. dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
  60. dvbdmxfeed->type);
  61. return -EINVAL;
  62. }
  63. if (mutex_lock_interruptible(&fdtv->demux_mutex))
  64. return -EINTR;
  65. if (dvbdmxfeed->type == DMX_TYPE_TS) {
  66. switch (dvbdmxfeed->pes_type) {
  67. case DMX_TS_PES_VIDEO:
  68. case DMX_TS_PES_AUDIO:
  69. case DMX_TS_PES_TELETEXT:
  70. case DMX_TS_PES_PCR:
  71. case DMX_TS_PES_OTHER:
  72. c = alloc_channel(fdtv);
  73. break;
  74. default:
  75. dev_err(fdtv->device,
  76. "can't start dmx feed: invalid pes type %u\n",
  77. dvbdmxfeed->pes_type);
  78. ret = -EINVAL;
  79. goto out;
  80. }
  81. } else {
  82. c = alloc_channel(fdtv);
  83. }
  84. if (c > 15) {
  85. dev_err(fdtv->device, "can't start dmx feed: busy\n");
  86. ret = -EBUSY;
  87. goto out;
  88. }
  89. dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
  90. fdtv->channel_pid[c] = dvbdmxfeed->pid;
  91. collect_channels(fdtv, &pidc, pids);
  92. if (dvbdmxfeed->pid == 8192) {
  93. ret = avc_tuner_get_ts(fdtv);
  94. if (ret) {
  95. dealloc_channel(fdtv, c);
  96. dev_err(fdtv->device, "can't get TS\n");
  97. goto out;
  98. }
  99. } else {
  100. ret = avc_tuner_set_pids(fdtv, pidc, pids);
  101. if (ret) {
  102. dealloc_channel(fdtv, c);
  103. dev_err(fdtv->device, "can't set PIDs\n");
  104. goto out;
  105. }
  106. }
  107. out:
  108. mutex_unlock(&fdtv->demux_mutex);
  109. return ret;
  110. }
  111. int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
  112. {
  113. struct dvb_demux *demux = dvbdmxfeed->demux;
  114. struct firedtv *fdtv = demux->priv;
  115. int pidc, c, ret;
  116. u16 pids[16];
  117. if (dvbdmxfeed->type == DMX_TYPE_TS &&
  118. !((dvbdmxfeed->ts_type & TS_PACKET) &&
  119. (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
  120. if (dvbdmxfeed->ts_type & TS_DECODER) {
  121. if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
  122. !demux->pesfilter[dvbdmxfeed->pes_type])
  123. return -EINVAL;
  124. demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
  125. demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
  126. }
  127. if (!(dvbdmxfeed->ts_type & TS_DECODER &&
  128. dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
  129. return 0;
  130. }
  131. if (mutex_lock_interruptible(&fdtv->demux_mutex))
  132. return -EINTR;
  133. c = (unsigned long)dvbdmxfeed->priv;
  134. dealloc_channel(fdtv, c);
  135. collect_channels(fdtv, &pidc, pids);
  136. ret = avc_tuner_set_pids(fdtv, pidc, pids);
  137. mutex_unlock(&fdtv->demux_mutex);
  138. return ret;
  139. }
  140. DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  141. int fdtv_dvb_register(struct firedtv *fdtv)
  142. {
  143. int err;
  144. err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
  145. THIS_MODULE, fdtv->device, adapter_nr);
  146. if (err < 0)
  147. goto fail_log;
  148. /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
  149. fdtv->demux.dmx.capabilities = 0;
  150. fdtv->demux.priv = fdtv;
  151. fdtv->demux.filternum = 16;
  152. fdtv->demux.feednum = 16;
  153. fdtv->demux.start_feed = fdtv_start_feed;
  154. fdtv->demux.stop_feed = fdtv_stop_feed;
  155. fdtv->demux.write_to_decoder = NULL;
  156. err = dvb_dmx_init(&fdtv->demux);
  157. if (err)
  158. goto fail_unreg_adapter;
  159. fdtv->dmxdev.filternum = 16;
  160. fdtv->dmxdev.demux = &fdtv->demux.dmx;
  161. fdtv->dmxdev.capabilities = 0;
  162. err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
  163. if (err)
  164. goto fail_dmx_release;
  165. fdtv->frontend.source = DMX_FRONTEND_0;
  166. err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
  167. if (err)
  168. goto fail_dmxdev_release;
  169. err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
  170. &fdtv->frontend);
  171. if (err)
  172. goto fail_rem_frontend;
  173. dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
  174. fdtv_frontend_init(fdtv);
  175. err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
  176. if (err)
  177. goto fail_net_release;
  178. err = fdtv_ca_register(fdtv);
  179. if (err)
  180. dev_info(fdtv->device,
  181. "Conditional Access Module not enabled\n");
  182. return 0;
  183. fail_net_release:
  184. dvb_net_release(&fdtv->dvbnet);
  185. fdtv->demux.dmx.close(&fdtv->demux.dmx);
  186. fail_rem_frontend:
  187. fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
  188. fail_dmxdev_release:
  189. dvb_dmxdev_release(&fdtv->dmxdev);
  190. fail_dmx_release:
  191. dvb_dmx_release(&fdtv->demux);
  192. fail_unreg_adapter:
  193. dvb_unregister_adapter(&fdtv->adapter);
  194. fail_log:
  195. dev_err(fdtv->device, "DVB initialization failed\n");
  196. return err;
  197. }
  198. void fdtv_dvb_unregister(struct firedtv *fdtv)
  199. {
  200. fdtv_ca_release(fdtv);
  201. dvb_unregister_frontend(&fdtv->fe);
  202. dvb_net_release(&fdtv->dvbnet);
  203. fdtv->demux.dmx.close(&fdtv->demux.dmx);
  204. fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
  205. dvb_dmxdev_release(&fdtv->dmxdev);
  206. dvb_dmx_release(&fdtv->demux);
  207. dvb_unregister_adapter(&fdtv->adapter);
  208. }
  209. const char *fdtv_model_names[] = {
  210. [FIREDTV_UNKNOWN] = "unknown type",
  211. [FIREDTV_DVB_S] = "FireDTV S/CI",
  212. [FIREDTV_DVB_C] = "FireDTV C/CI",
  213. [FIREDTV_DVB_T] = "FireDTV T/CI",
  214. [FIREDTV_DVB_S2] = "FireDTV S2 ",
  215. };
  216. struct firedtv *fdtv_alloc(struct device *dev,
  217. const struct firedtv_backend *backend,
  218. const char *name, size_t name_len)
  219. {
  220. struct firedtv *fdtv;
  221. int i;
  222. fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
  223. if (!fdtv)
  224. return NULL;
  225. dev_set_drvdata(dev, fdtv);
  226. fdtv->device = dev;
  227. fdtv->isochannel = -1;
  228. fdtv->voltage = 0xff;
  229. fdtv->tone = 0xff;
  230. fdtv->backend = backend;
  231. mutex_init(&fdtv->avc_mutex);
  232. init_waitqueue_head(&fdtv->avc_wait);
  233. fdtv->avc_reply_received = true;
  234. mutex_init(&fdtv->demux_mutex);
  235. INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
  236. for (i = ARRAY_SIZE(fdtv_model_names); --i; )
  237. if (strlen(fdtv_model_names[i]) <= name_len &&
  238. strncmp(name, fdtv_model_names[i], name_len) == 0)
  239. break;
  240. fdtv->type = i;
  241. return fdtv;
  242. }
  243. #define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
  244. IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
  245. #define DIGITAL_EVERYWHERE_OUI 0x001287
  246. #define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
  247. #define AVC_SW_VERSION_ENTRY 0x010001
  248. const struct ieee1394_device_id fdtv_id_table[] = {
  249. {
  250. /* FloppyDTV S/CI and FloppyDTV S2 */
  251. .match_flags = MATCH_FLAGS,
  252. .vendor_id = DIGITAL_EVERYWHERE_OUI,
  253. .model_id = 0x000024,
  254. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
  255. .version = AVC_SW_VERSION_ENTRY,
  256. }, {
  257. /* FloppyDTV T/CI */
  258. .match_flags = MATCH_FLAGS,
  259. .vendor_id = DIGITAL_EVERYWHERE_OUI,
  260. .model_id = 0x000025,
  261. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
  262. .version = AVC_SW_VERSION_ENTRY,
  263. }, {
  264. /* FloppyDTV C/CI */
  265. .match_flags = MATCH_FLAGS,
  266. .vendor_id = DIGITAL_EVERYWHERE_OUI,
  267. .model_id = 0x000026,
  268. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
  269. .version = AVC_SW_VERSION_ENTRY,
  270. }, {
  271. /* FireDTV S/CI and FloppyDTV S2 */
  272. .match_flags = MATCH_FLAGS,
  273. .vendor_id = DIGITAL_EVERYWHERE_OUI,
  274. .model_id = 0x000034,
  275. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
  276. .version = AVC_SW_VERSION_ENTRY,
  277. }, {
  278. /* FireDTV T/CI */
  279. .match_flags = MATCH_FLAGS,
  280. .vendor_id = DIGITAL_EVERYWHERE_OUI,
  281. .model_id = 0x000035,
  282. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
  283. .version = AVC_SW_VERSION_ENTRY,
  284. }, {
  285. /* FireDTV C/CI */
  286. .match_flags = MATCH_FLAGS,
  287. .vendor_id = DIGITAL_EVERYWHERE_OUI,
  288. .model_id = 0x000036,
  289. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
  290. .version = AVC_SW_VERSION_ENTRY,
  291. }, {}
  292. };
  293. MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
  294. static int __init fdtv_init(void)
  295. {
  296. int ret;
  297. ret = fdtv_fw_init();
  298. if (ret < 0)
  299. return ret;
  300. ret = fdtv_1394_init();
  301. if (ret < 0)
  302. fdtv_fw_exit();
  303. return ret;
  304. }
  305. static void __exit fdtv_exit(void)
  306. {
  307. fdtv_1394_exit();
  308. fdtv_fw_exit();
  309. }
  310. module_init(fdtv_init);
  311. module_exit(fdtv_exit);
  312. MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
  313. MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
  314. MODULE_DESCRIPTION("FireDTV DVB Driver");
  315. MODULE_LICENSE("GPL");
  316. MODULE_SUPPORTED_DEVICE("FireDTV DVB");