1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/slab.h>
23#include <linux/module.h>
24#include <linux/mm.h>
25#include <linux/kref.h>
26#include <linux/uaccess.h>
27#include <linux/usb.h>
28
29
30#include "as102_drv.h"
31#include "as102_fw.h"
32#include "dvbdev.h"
33
34int as102_debug;
35module_param_named(debug, as102_debug, int, 0644);
36MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)");
37
38int dual_tuner;
39module_param_named(dual_tuner, dual_tuner, int, 0644);
40MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)");
41
42static int fw_upload = 1;
43module_param_named(fw_upload, fw_upload, int, 0644);
44MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)");
45
46static int pid_filtering;
47module_param_named(pid_filtering, pid_filtering, int, 0644);
48MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)");
49
50static int ts_auto_disable;
51module_param_named(ts_auto_disable, ts_auto_disable, int, 0644);
52MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)");
53
54int elna_enable = 1;
55module_param_named(elna_enable, elna_enable, int, 0644);
56MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
57
58DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
59
60static void as102_stop_stream(struct as102_dev_t *dev)
61{
62 struct as10x_bus_adapter_t *bus_adap;
63
64 if (dev != NULL)
65 bus_adap = &dev->bus_adap;
66 else
67 return;
68
69 if (bus_adap->ops->stop_stream != NULL)
70 bus_adap->ops->stop_stream(dev);
71
72 if (ts_auto_disable) {
73 if (mutex_lock_interruptible(&dev->bus_adap.lock))
74 return;
75
76 if (as10x_cmd_stop_streaming(bus_adap) < 0)
77 dprintk(debug, "as10x_cmd_stop_streaming failed\n");
78
79 mutex_unlock(&dev->bus_adap.lock);
80 }
81}
82
83static int as102_start_stream(struct as102_dev_t *dev)
84{
85 struct as10x_bus_adapter_t *bus_adap;
86 int ret = -EFAULT;
87
88 if (dev != NULL)
89 bus_adap = &dev->bus_adap;
90 else
91 return ret;
92
93 if (bus_adap->ops->start_stream != NULL)
94 ret = bus_adap->ops->start_stream(dev);
95
96 if (ts_auto_disable) {
97 if (mutex_lock_interruptible(&dev->bus_adap.lock))
98 return -EFAULT;
99
100 ret = as10x_cmd_start_streaming(bus_adap);
101
102 mutex_unlock(&dev->bus_adap.lock);
103 }
104
105 return ret;
106}
107
108static int as10x_pid_filter(struct as102_dev_t *dev,
109 int index, u16 pid, int onoff) {
110
111 struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap;
112 int ret = -EFAULT;
113
114 if (mutex_lock_interruptible(&dev->bus_adap.lock)) {
115 dprintk(debug, "mutex_lock_interruptible(lock) failed !\n");
116 return -EBUSY;
117 }
118
119 switch (onoff) {
120 case 0:
121 ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
122 dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
123 index, pid, ret);
124 break;
125 case 1:
126 {
127 struct as10x_ts_filter filter;
128
129 filter.type = TS_PID_TYPE_TS;
130 filter.idx = 0xFF;
131 filter.pid = pid;
132
133 ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
134 dprintk(debug,
135 "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
136 index, filter.idx, filter.pid, ret);
137 break;
138 }
139 }
140
141 mutex_unlock(&dev->bus_adap.lock);
142 return ret;
143}
144
145static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
146{
147 int ret = 0;
148 struct dvb_demux *demux = dvbdmxfeed->demux;
149 struct as102_dev_t *as102_dev = demux->priv;
150
151 if (mutex_lock_interruptible(&as102_dev->sem))
152 return -ERESTARTSYS;
153
154 if (pid_filtering)
155 as10x_pid_filter(as102_dev, dvbdmxfeed->index,
156 dvbdmxfeed->pid, 1);
157
158 if (as102_dev->streaming++ == 0)
159 ret = as102_start_stream(as102_dev);
160
161 mutex_unlock(&as102_dev->sem);
162 return ret;
163}
164
165static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
166{
167 struct dvb_demux *demux = dvbdmxfeed->demux;
168 struct as102_dev_t *as102_dev = demux->priv;
169
170 if (mutex_lock_interruptible(&as102_dev->sem))
171 return -ERESTARTSYS;
172
173 if (--as102_dev->streaming == 0)
174 as102_stop_stream(as102_dev);
175
176 if (pid_filtering)
177 as10x_pid_filter(as102_dev, dvbdmxfeed->index,
178 dvbdmxfeed->pid, 0);
179
180 mutex_unlock(&as102_dev->sem);
181 return 0;
182}
183
184int as102_dvb_register(struct as102_dev_t *as102_dev)
185{
186 struct device *dev = &as102_dev->bus_adap.usb_dev->dev;
187 int ret;
188
189 ret = dvb_register_adapter(&as102_dev->dvb_adap,
190 as102_dev->name, THIS_MODULE,
191 dev, adapter_nr);
192 if (ret < 0) {
193 dev_err(dev, "%s: dvb_register_adapter() failed: %d\n",
194 __func__, ret);
195 return ret;
196 }
197
198 as102_dev->dvb_dmx.priv = as102_dev;
199 as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256;
200 as102_dev->dvb_dmx.feednum = 256;
201 as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed;
202 as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed;
203
204 as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING |
205 DMX_SECTION_FILTERING;
206
207 as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum;
208 as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx;
209 as102_dev->dvb_dmxdev.capabilities = 0;
210
211 ret = dvb_dmx_init(&as102_dev->dvb_dmx);
212 if (ret < 0) {
213 dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret);
214 goto edmxinit;
215 }
216
217 ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
218 if (ret < 0) {
219 dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n",
220 __func__, ret);
221 goto edmxdinit;
222 }
223
224 ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe);
225 if (ret < 0) {
226 dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d",
227 __func__, ret);
228 goto efereg;
229 }
230
231
232 mutex_init(&as102_dev->bus_adap.lock);
233
234
235 mutex_init(&as102_dev->sem);
236
237
238
239
240
241 if (fw_upload)
242 try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
243 "firmware_class");
244
245 pr_info("Registered device %s", as102_dev->name);
246 return 0;
247
248efereg:
249 dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
250edmxdinit:
251 dvb_dmx_release(&as102_dev->dvb_dmx);
252edmxinit:
253 dvb_unregister_adapter(&as102_dev->dvb_adap);
254 return ret;
255}
256
257void as102_dvb_unregister(struct as102_dev_t *as102_dev)
258{
259
260 as102_dvb_unregister_fe(&as102_dev->dvb_fe);
261
262
263 dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
264 dvb_dmx_release(&as102_dev->dvb_dmx);
265
266
267 dvb_unregister_adapter(&as102_dev->dvb_adap);
268
269 pr_info("Unregistered device %s", as102_dev->name);
270}
271
272module_usb_driver(as102_usb_driver);
273
274
275MODULE_DESCRIPTION(DRIVER_FULL_NAME);
276MODULE_LICENSE("GPL");
277MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
278