firesat_dvb.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #include <linux/init.h>
  2. #include <linux/slab.h>
  3. #include <linux/wait.h>
  4. #include <linux/module.h>
  5. #include <linux/delay.h>
  6. #include <linux/time.h>
  7. #include <linux/errno.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/semaphore.h>
  10. #include <ieee1394_hotplug.h>
  11. #include <nodemgr.h>
  12. #include <highlevel.h>
  13. #include <ohci1394.h>
  14. #include <hosts.h>
  15. #include <dvbdev.h>
  16. #include "firesat.h"
  17. #include "avc_api.h"
  18. #include "cmp.h"
  19. #include "firesat-rc.h"
  20. #include "firesat-ci.h"
  21. DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  22. static struct firesat_channel *firesat_channel_allocate(struct firesat *firesat)
  23. {
  24. int k;
  25. printk(KERN_INFO "%s\n", __func__);
  26. if (down_interruptible(&firesat->demux_sem))
  27. return NULL;
  28. for (k = 0; k < 16; k++) {
  29. printk(KERN_INFO "%s: channel %d: active = %d, pid = 0x%x\n",__func__,k,firesat->channel[k].active,firesat->channel[k].pid);
  30. if (firesat->channel[k].active == 0) {
  31. firesat->channel[k].active = 1;
  32. up(&firesat->demux_sem);
  33. return &firesat->channel[k];
  34. }
  35. }
  36. up(&firesat->demux_sem);
  37. return NULL; // no more channels available
  38. }
  39. static int firesat_channel_collect(struct firesat *firesat, int *pidc, u16 pid[])
  40. {
  41. int k, l = 0;
  42. if (down_interruptible(&firesat->demux_sem))
  43. return -EINTR;
  44. for (k = 0; k < 16; k++)
  45. if (firesat->channel[k].active == 1)
  46. pid[l++] = firesat->channel[k].pid;
  47. up(&firesat->demux_sem);
  48. *pidc = l;
  49. return 0;
  50. }
  51. static int firesat_channel_release(struct firesat *firesat,
  52. struct firesat_channel *channel)
  53. {
  54. if (down_interruptible(&firesat->demux_sem))
  55. return -EINTR;
  56. channel->active = 0;
  57. up(&firesat->demux_sem);
  58. return 0;
  59. }
  60. int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed)
  61. {
  62. struct firesat *firesat = (struct firesat*)dvbdmxfeed->demux->priv;
  63. struct firesat_channel *channel;
  64. int pidc,k;
  65. u16 pids[16];
  66. printk(KERN_INFO "%s (pid %u)\n",__func__,dvbdmxfeed->pid);
  67. switch (dvbdmxfeed->type) {
  68. case DMX_TYPE_TS:
  69. case DMX_TYPE_SEC:
  70. break;
  71. default:
  72. printk("%s: invalid type %u\n",__func__,dvbdmxfeed->type);
  73. return -EINVAL;
  74. }
  75. if (dvbdmxfeed->type == DMX_TYPE_TS) {
  76. switch (dvbdmxfeed->pes_type) {
  77. case DMX_TS_PES_VIDEO:
  78. case DMX_TS_PES_AUDIO:
  79. case DMX_TS_PES_TELETEXT:
  80. case DMX_TS_PES_PCR:
  81. case DMX_TS_PES_OTHER:
  82. //Dirty fix to keep firesat->channel pid-list up to date
  83. for(k=0;k<16;k++){
  84. if(firesat->channel[k].active == 0)
  85. firesat->channel[k].pid =
  86. dvbdmxfeed->pid;
  87. break;
  88. }
  89. channel = firesat_channel_allocate(firesat);
  90. break;
  91. default:
  92. printk("%s: invalid pes type %u\n",__func__, dvbdmxfeed->pes_type);
  93. return -EINVAL;
  94. }
  95. } else {
  96. channel = firesat_channel_allocate(firesat);
  97. }
  98. if (!channel) {
  99. printk("%s: busy!\n", __func__);
  100. return -EBUSY;
  101. }
  102. dvbdmxfeed->priv = channel;
  103. channel->dvbdmxfeed = dvbdmxfeed;
  104. channel->pid = dvbdmxfeed->pid;
  105. channel->type = dvbdmxfeed->type;
  106. channel->firesat = firesat;
  107. if (firesat_channel_collect(firesat, &pidc, pids)) {
  108. firesat_channel_release(firesat, channel);
  109. return -EINTR;
  110. }
  111. if(dvbdmxfeed->pid == 8192) {
  112. if((k=AVCTuner_GetTS(firesat))) {
  113. firesat_channel_release(firesat, channel);
  114. printk("%s: AVCTuner_GetTS failed with error %d\n",
  115. __func__,k);
  116. return k;
  117. }
  118. }
  119. else {
  120. if((k=AVCTuner_SetPIDs(firesat, pidc, pids))) {
  121. firesat_channel_release(firesat, channel);
  122. printk("%s: AVCTuner_SetPIDs failed with error %d\n",
  123. __func__,k);
  124. return k;
  125. }
  126. }
  127. return 0;
  128. }
  129. int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
  130. {
  131. struct dvb_demux *demux = dvbdmxfeed->demux;
  132. struct firesat *firesat = (struct firesat*)demux->priv;
  133. int k, l = 0;
  134. u16 pids[16];
  135. printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
  136. if (dvbdmxfeed->type == DMX_TYPE_TS && !((dvbdmxfeed->ts_type & TS_PACKET) &&
  137. (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
  138. if (dvbdmxfeed->ts_type & TS_DECODER) {
  139. if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
  140. !demux->pesfilter[dvbdmxfeed->pes_type])
  141. return -EINVAL;
  142. demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
  143. demux->pesfilter[dvbdmxfeed->pes_type] = 0;
  144. }
  145. if (!(dvbdmxfeed->ts_type & TS_DECODER &&
  146. dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
  147. return 0;
  148. }
  149. if (down_interruptible(&firesat->demux_sem))
  150. return -EINTR;
  151. // list except channel to be removed
  152. for (k = 0; k < 16; k++)
  153. if (firesat->channel[k].active == 1)
  154. if (&firesat->channel[k] !=
  155. (struct firesat_channel *)dvbdmxfeed->priv)
  156. pids[l++] = firesat->channel[k].pid;
  157. else
  158. firesat->channel[k].active = 0;
  159. if ((k = AVCTuner_SetPIDs(firesat, l, pids))) {
  160. up(&firesat->demux_sem);
  161. return k;
  162. }
  163. ((struct firesat_channel *)dvbdmxfeed->priv)->active = 0;
  164. up(&firesat->demux_sem);
  165. return 0;
  166. }
  167. int firesat_dvbdev_init(struct firesat *firesat,
  168. struct device *dev,
  169. struct dvb_frontend *fe)
  170. {
  171. int result;
  172. firesat->has_ci = 1; // TEMP workaround
  173. #if 0
  174. switch (firesat->type) {
  175. case FireSAT_DVB_S:
  176. firesat->model_name = "FireSAT DVB-S";
  177. firesat->frontend_info = &firesat_S_frontend_info;
  178. break;
  179. case FireSAT_DVB_C:
  180. firesat->model_name = "FireSAT DVB-C";
  181. firesat->frontend_info = &firesat_C_frontend_info;
  182. break;
  183. case FireSAT_DVB_T:
  184. firesat->model_name = "FireSAT DVB-T";
  185. firesat->frontend_info = &firesat_T_frontend_info;
  186. break;
  187. default:
  188. printk("%s: unknown model type 0x%x on subunit %d!\n",
  189. __func__, firesat->type,subunit);
  190. firesat->model_name = "Unknown";
  191. firesat->frontend_info = NULL;
  192. }
  193. #endif
  194. /* // ------- CRAP -----------
  195. if (!firesat->frontend_info) {
  196. spin_lock_irqsave(&firesat_list_lock, flags);
  197. list_del(&firesat->list);
  198. spin_unlock_irqrestore(&firesat_list_lock, flags);
  199. kfree(firesat);
  200. continue;
  201. }
  202. */
  203. //initialising firesat->adapter before calling dvb_register_adapter
  204. if (!(firesat->adapter = kmalloc(sizeof (struct dvb_adapter), GFP_KERNEL))) {
  205. printk("%s: couldn't allocate memory.\n", __func__);
  206. kfree(firesat->adapter);
  207. kfree(firesat);
  208. return -ENOMEM;
  209. }
  210. if ((result = dvb_register_adapter(firesat->adapter,
  211. firesat->model_name,
  212. THIS_MODULE,
  213. dev, adapter_nr)) < 0) {
  214. printk("%s: dvb_register_adapter failed: error %d\n", __func__, result);
  215. #if 0
  216. /* ### cleanup */
  217. spin_lock_irqsave(&firesat_list_lock, flags);
  218. list_del(&firesat->list);
  219. spin_unlock_irqrestore(&firesat_list_lock, flags);
  220. #endif
  221. kfree(firesat);
  222. return result;
  223. }
  224. firesat->demux.dmx.capabilities = 0/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/;
  225. firesat->demux.priv = (void *)firesat;
  226. firesat->demux.filternum = 16;
  227. firesat->demux.feednum = 16;
  228. firesat->demux.start_feed = firesat_start_feed;
  229. firesat->demux.stop_feed = firesat_stop_feed;
  230. firesat->demux.write_to_decoder = NULL;
  231. if ((result = dvb_dmx_init(&firesat->demux)) < 0) {
  232. printk("%s: dvb_dmx_init failed: error %d\n", __func__,
  233. result);
  234. dvb_unregister_adapter(firesat->adapter);
  235. return result;
  236. }
  237. firesat->dmxdev.filternum = 16;
  238. firesat->dmxdev.demux = &firesat->demux.dmx;
  239. firesat->dmxdev.capabilities = 0;
  240. if ((result = dvb_dmxdev_init(&firesat->dmxdev, firesat->adapter)) < 0) {
  241. printk("%s: dvb_dmxdev_init failed: error %d\n",
  242. __func__, result);
  243. dvb_dmx_release(&firesat->demux);
  244. dvb_unregister_adapter(firesat->adapter);
  245. return result;
  246. }
  247. firesat->frontend.source = DMX_FRONTEND_0;
  248. if ((result = firesat->demux.dmx.add_frontend(&firesat->demux.dmx,
  249. &firesat->frontend)) < 0) {
  250. printk("%s: dvb_dmx_init failed: error %d\n", __func__,
  251. result);
  252. dvb_dmxdev_release(&firesat->dmxdev);
  253. dvb_dmx_release(&firesat->demux);
  254. dvb_unregister_adapter(firesat->adapter);
  255. return result;
  256. }
  257. if ((result = firesat->demux.dmx.connect_frontend(&firesat->demux.dmx,
  258. &firesat->frontend)) < 0) {
  259. printk("%s: dvb_dmx_init failed: error %d\n", __func__,
  260. result);
  261. firesat->demux.dmx.remove_frontend(&firesat->demux.dmx, &firesat->frontend);
  262. dvb_dmxdev_release(&firesat->dmxdev);
  263. dvb_dmx_release(&firesat->demux);
  264. dvb_unregister_adapter(firesat->adapter);
  265. return result;
  266. }
  267. dvb_net_init(firesat->adapter, &firesat->dvbnet, &firesat->demux.dmx);
  268. // fe->ops = firesat_ops;
  269. // fe->dvb = firesat->adapter;
  270. firesat_frontend_attach(firesat, fe);
  271. fe->sec_priv = firesat; //IMPORTANT, functions depend on this!!!
  272. if ((result= dvb_register_frontend(firesat->adapter, fe)) < 0) {
  273. printk("%s: dvb_register_frontend_new failed: error %d\n", __func__, result);
  274. /* ### cleanup */
  275. return result;
  276. }
  277. if (firesat->has_ci)
  278. firesat_ca_init(firesat);
  279. return 0;
  280. }