Commit | Line | Data |
---|---|---|
c79b339f | 1 | /* |
12042b05 | 2 | * DVB USB framework |
c79b339f | 3 | * |
12042b05 AP |
4 | * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> |
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | |
c79b339f | 6 | * |
12042b05 AP |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
c79b339f | 11 | * |
12042b05 AP |
12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
c79b339f | 16 | * |
12042b05 AP |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; if not, write to the Free Software Foundation, Inc., | |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
c79b339f | 20 | */ |
12042b05 | 21 | |
c79b339f AP |
22 | #include "dvb_usb_common.h" |
23 | ||
59784343 AP |
24 | int dvb_usbv2_disable_rc_polling; |
25 | module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644); | |
4e60d951 | 26 | MODULE_PARM_DESC(disable_rc_polling, |
831511bd | 27 | "disable remote control polling (default: 0)"); |
c79b339f | 28 | static int dvb_usb_force_pid_filter_usage; |
4e60d951 AP |
29 | module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, |
30 | int, 0444); | |
6d7cfec4 AP |
31 | MODULE_PARM_DESC(force_pid_filter_usage, |
32 | "force all DVB USB devices to use a PID filter, if any (default: 0)"); | |
c79b339f | 33 | |
6d7cfec4 AP |
34 | static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, |
35 | const char *name) | |
a0d72d24 AP |
36 | { |
37 | int ret; | |
a0921af7 | 38 | const struct firmware *fw; |
d10d1b9a | 39 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
a0d72d24 | 40 | |
f093c388 | 41 | if (!d->props->download_firmware) { |
a0d72d24 AP |
42 | ret = -EINVAL; |
43 | goto err; | |
44 | } | |
45 | ||
46 | ret = request_firmware(&fw, name, &d->udev->dev); | |
47 | if (ret < 0) { | |
6d7cfec4 AP |
48 | dev_err(&d->udev->dev, |
49 | "%s: Did not find the firmware file '%s'. Please see linux/Documentation/dvb/ for more details on firmware-problems. Status %d\n", | |
50 | KBUILD_MODNAME, name, ret); | |
a0d72d24 AP |
51 | goto err; |
52 | } | |
53 | ||
d10d1b9a AP |
54 | dev_info(&d->udev->dev, "%s: downloading firmware from file '%s'\n", |
55 | KBUILD_MODNAME, name); | |
a0d72d24 | 56 | |
f093c388 | 57 | ret = d->props->download_firmware(d, fw); |
a0d72d24 | 58 | release_firmware(fw); |
a0d72d24 AP |
59 | if (ret < 0) |
60 | goto err; | |
61 | ||
c65bcb95 | 62 | return ret; |
a0d72d24 | 63 | err: |
d10d1b9a | 64 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
a0d72d24 AP |
65 | return ret; |
66 | } | |
67 | ||
d496eb8a | 68 | static int dvb_usbv2_i2c_init(struct dvb_usb_device *d) |
a177c72b | 69 | { |
0fba999f | 70 | int ret; |
d10d1b9a | 71 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
d70521a3 AP |
72 | |
73 | if (!d->props->i2c_algo) | |
74 | return 0; | |
a177c72b AP |
75 | |
76 | strlcpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name)); | |
f093c388 | 77 | d->i2c_adap.algo = d->props->i2c_algo; |
a177c72b | 78 | d->i2c_adap.dev.parent = &d->udev->dev; |
a177c72b AP |
79 | i2c_set_adapdata(&d->i2c_adap, d); |
80 | ||
81 | ret = i2c_add_adapter(&d->i2c_adap); | |
0fba999f | 82 | if (ret < 0) { |
d70521a3 | 83 | d->i2c_adap.algo = NULL; |
d10d1b9a AP |
84 | dev_err(&d->udev->dev, "%s: i2c_add_adapter() failed=%d\n", |
85 | KBUILD_MODNAME, ret); | |
0fba999f AP |
86 | goto err; |
87 | } | |
a177c72b | 88 | |
0fba999f AP |
89 | return 0; |
90 | err: | |
d10d1b9a | 91 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
a177c72b AP |
92 | return ret; |
93 | } | |
94 | ||
d496eb8a | 95 | static int dvb_usbv2_i2c_exit(struct dvb_usb_device *d) |
a177c72b | 96 | { |
d10d1b9a | 97 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
0fba999f | 98 | |
d70521a3 AP |
99 | if (d->i2c_adap.algo) |
100 | i2c_del_adapter(&d->i2c_adap); | |
0fba999f | 101 | |
a177c72b AP |
102 | return 0; |
103 | } | |
104 | ||
37b44a0f | 105 | #if IS_ENABLED(CONFIG_RC_CORE) |
877e0aa7 AP |
106 | static void dvb_usb_read_remote_control(struct work_struct *work) |
107 | { | |
108 | struct dvb_usb_device *d = container_of(work, | |
109 | struct dvb_usb_device, rc_query_work.work); | |
110 | int ret; | |
111 | ||
831511bd AP |
112 | /* |
113 | * When the parameter has been set to 1 via sysfs while the | |
114 | * driver was running, or when bulk mode is enabled after IR init. | |
877e0aa7 | 115 | */ |
ac1c86c8 AP |
116 | if (dvb_usbv2_disable_rc_polling || d->rc.bulk_mode) { |
117 | d->rc_polling_active = false; | |
877e0aa7 | 118 | return; |
ac1c86c8 | 119 | } |
877e0aa7 AP |
120 | |
121 | ret = d->rc.query(d); | |
831511bd | 122 | if (ret < 0) { |
d10d1b9a AP |
123 | dev_err(&d->udev->dev, "%s: rc.query() failed=%d\n", |
124 | KBUILD_MODNAME, ret); | |
ac1c86c8 | 125 | d->rc_polling_active = false; |
831511bd AP |
126 | return; /* stop polling */ |
127 | } | |
877e0aa7 AP |
128 | |
129 | schedule_delayed_work(&d->rc_query_work, | |
831511bd | 130 | msecs_to_jiffies(d->rc.interval)); |
877e0aa7 AP |
131 | } |
132 | ||
133 | static int dvb_usbv2_remote_init(struct dvb_usb_device *d) | |
134 | { | |
135 | int ret; | |
136 | struct rc_dev *dev; | |
d10d1b9a | 137 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
ad261839 | 138 | |
877e0aa7 AP |
139 | if (dvb_usbv2_disable_rc_polling || !d->props->get_rc_config) |
140 | return 0; | |
141 | ||
de73beee | 142 | d->rc.map_name = d->rc_map; |
877e0aa7 AP |
143 | ret = d->props->get_rc_config(d, &d->rc); |
144 | if (ret < 0) | |
145 | goto err; | |
146 | ||
de73beee AP |
147 | /* disable rc when there is no keymap defined */ |
148 | if (!d->rc.map_name) | |
149 | return 0; | |
150 | ||
877e0aa7 AP |
151 | dev = rc_allocate_device(); |
152 | if (!dev) { | |
153 | ret = -ENOMEM; | |
154 | goto err; | |
155 | } | |
156 | ||
157 | dev->dev.parent = &d->udev->dev; | |
831511bd | 158 | dev->input_name = d->name; |
877e0aa7 AP |
159 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); |
160 | strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); | |
161 | dev->input_phys = d->rc_phys; | |
162 | usb_to_input_id(d->udev, &dev->input_id); | |
163 | /* TODO: likely RC-core should took const char * */ | |
164 | dev->driver_name = (char *) d->props->driver_name; | |
de73beee | 165 | dev->map_name = d->rc.map_name; |
877e0aa7 | 166 | dev->driver_type = d->rc.driver_type; |
1a1934fa | 167 | rc_set_allowed_protocols(dev, d->rc.allowed_protos); |
877e0aa7 AP |
168 | dev->change_protocol = d->rc.change_protocol; |
169 | dev->priv = d; | |
877e0aa7 AP |
170 | |
171 | ret = rc_register_device(dev); | |
172 | if (ret < 0) { | |
173 | rc_free_device(dev); | |
174 | goto err; | |
175 | } | |
176 | ||
877e0aa7 AP |
177 | d->rc_dev = dev; |
178 | ||
179 | /* start polling if needed */ | |
180 | if (d->rc.query && !d->rc.bulk_mode) { | |
181 | /* initialize a work queue for handling polling */ | |
182 | INIT_DELAYED_WORK(&d->rc_query_work, | |
183 | dvb_usb_read_remote_control); | |
6d7cfec4 AP |
184 | dev_info(&d->udev->dev, |
185 | "%s: schedule remote query interval to %d msecs\n", | |
186 | KBUILD_MODNAME, d->rc.interval); | |
877e0aa7 AP |
187 | schedule_delayed_work(&d->rc_query_work, |
188 | msecs_to_jiffies(d->rc.interval)); | |
ac1c86c8 | 189 | d->rc_polling_active = true; |
877e0aa7 AP |
190 | } |
191 | ||
877e0aa7 AP |
192 | return 0; |
193 | err: | |
d10d1b9a | 194 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
877e0aa7 AP |
195 | return ret; |
196 | } | |
197 | ||
198 | static int dvb_usbv2_remote_exit(struct dvb_usb_device *d) | |
199 | { | |
d10d1b9a | 200 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
ad261839 AP |
201 | |
202 | if (d->rc_dev) { | |
877e0aa7 AP |
203 | cancel_delayed_work_sync(&d->rc_query_work); |
204 | rc_unregister_device(d->rc_dev); | |
ad261839 | 205 | d->rc_dev = NULL; |
877e0aa7 AP |
206 | } |
207 | ||
877e0aa7 AP |
208 | return 0; |
209 | } | |
0c87c66a | 210 | #else |
ef382402 AP |
211 | #define dvb_usbv2_remote_init(args...) 0 |
212 | #define dvb_usbv2_remote_exit(args...) | |
0c87c66a | 213 | #endif |
877e0aa7 | 214 | |
41a0abf7 AP |
215 | static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buf, |
216 | size_t len) | |
217 | { | |
218 | struct dvb_usb_adapter *adap = stream->user_priv; | |
219 | dvb_dmx_swfilter(&adap->demux, buf, len); | |
220 | } | |
221 | ||
222 | static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buf, | |
223 | size_t len) | |
224 | { | |
225 | struct dvb_usb_adapter *adap = stream->user_priv; | |
226 | dvb_dmx_swfilter_204(&adap->demux, buf, len); | |
227 | } | |
228 | ||
229 | static void dvb_usb_data_complete_raw(struct usb_data_stream *stream, u8 *buf, | |
230 | size_t len) | |
231 | { | |
232 | struct dvb_usb_adapter *adap = stream->user_priv; | |
233 | dvb_dmx_swfilter_raw(&adap->demux, buf, len); | |
234 | } | |
235 | ||
691a5502 | 236 | static int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap) |
41a0abf7 | 237 | { |
d10d1b9a AP |
238 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, |
239 | adap->id); | |
41a0abf7 AP |
240 | |
241 | adap->stream.udev = adap_to_d(adap)->udev; | |
242 | adap->stream.user_priv = adap; | |
243 | adap->stream.complete = dvb_usb_data_complete; | |
244 | ||
245 | return usb_urb_initv2(&adap->stream, &adap->props->stream); | |
246 | } | |
247 | ||
691a5502 | 248 | static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap) |
41a0abf7 | 249 | { |
d10d1b9a AP |
250 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, |
251 | adap->id); | |
41a0abf7 | 252 | |
831511bd | 253 | return usb_urb_exitv2(&adap->stream); |
41a0abf7 AP |
254 | } |
255 | ||
bdecbe43 AP |
256 | static int wait_schedule(void *ptr) |
257 | { | |
258 | schedule(); | |
259 | ||
260 | return 0; | |
261 | } | |
262 | ||
96d7ca5e | 263 | static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) |
41a0abf7 AP |
264 | { |
265 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; | |
266 | struct dvb_usb_device *d = adap_to_d(adap); | |
96d7ca5e AP |
267 | int ret = 0; |
268 | struct usb_data_stream_properties stream_props; | |
269 | dev_dbg(&d->udev->dev, | |
270 | "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n", | |
d10d1b9a | 271 | __func__, adap->id, adap->active_fe, dvbdmxfeed->type, |
41a0abf7 | 272 | adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, |
96d7ca5e | 273 | dvbdmxfeed->pid, dvbdmxfeed->index); |
41a0abf7 | 274 | |
96d7ca5e | 275 | /* wait init is done */ |
bdecbe43 AP |
276 | wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule, |
277 | TASK_UNINTERRUPTIBLE); | |
278 | ||
41a0abf7 AP |
279 | if (adap->active_fe == -1) |
280 | return -EINVAL; | |
281 | ||
96d7ca5e AP |
282 | /* skip feed setup if we are already feeding */ |
283 | if (adap->feed_count++ > 0) | |
284 | goto skip_feed_start; | |
285 | ||
286 | /* set 'streaming' status bit */ | |
287 | set_bit(ADAP_STREAMING, &adap->state_bits); | |
288 | ||
289 | /* resolve input and output streaming parameters */ | |
290 | if (d->props->get_stream_config) { | |
291 | memcpy(&stream_props, &adap->props->stream, | |
292 | sizeof(struct usb_data_stream_properties)); | |
293 | ret = d->props->get_stream_config(adap->fe[adap->active_fe], | |
294 | &adap->ts_type, &stream_props); | |
295 | if (ret) | |
296 | dev_err(&d->udev->dev, | |
297 | "%s: get_stream_config() failed=%d\n", | |
298 | KBUILD_MODNAME, ret); | |
299 | } else { | |
300 | stream_props = adap->props->stream; | |
301 | } | |
302 | ||
303 | switch (adap->ts_type) { | |
304 | case DVB_USB_FE_TS_TYPE_204: | |
305 | adap->stream.complete = dvb_usb_data_complete_204; | |
306 | break; | |
307 | case DVB_USB_FE_TS_TYPE_RAW: | |
308 | adap->stream.complete = dvb_usb_data_complete_raw; | |
309 | break; | |
310 | case DVB_USB_FE_TS_TYPE_188: | |
311 | default: | |
312 | adap->stream.complete = dvb_usb_data_complete; | |
313 | break; | |
314 | } | |
315 | ||
316 | /* submit USB streaming packets */ | |
317 | usb_urb_submitv2(&adap->stream, &stream_props); | |
318 | ||
319 | /* enable HW PID filter */ | |
320 | if (adap->pid_filtering && adap->props->pid_filter_ctrl) { | |
321 | ret = adap->props->pid_filter_ctrl(adap, 1); | |
322 | if (ret) | |
323 | dev_err(&d->udev->dev, | |
324 | "%s: pid_filter_ctrl() failed=%d\n", | |
325 | KBUILD_MODNAME, ret); | |
326 | } | |
327 | ||
328 | /* ask device to start streaming */ | |
329 | if (d->props->streaming_ctrl) { | |
330 | ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 1); | |
331 | if (ret) | |
332 | dev_err(&d->udev->dev, | |
333 | "%s: streaming_ctrl() failed=%d\n", | |
334 | KBUILD_MODNAME, ret); | |
41a0abf7 | 335 | } |
96d7ca5e | 336 | skip_feed_start: |
41a0abf7 | 337 | |
96d7ca5e AP |
338 | /* add PID to device HW PID filter */ |
339 | if (adap->pid_filtering && adap->props->pid_filter) { | |
41a0abf7 | 340 | ret = adap->props->pid_filter(adap, dvbdmxfeed->index, |
96d7ca5e AP |
341 | dvbdmxfeed->pid, 1); |
342 | if (ret) | |
2d9e7ea6 AP |
343 | dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n", |
344 | KBUILD_MODNAME, ret); | |
345 | } | |
41a0abf7 | 346 | |
96d7ca5e AP |
347 | if (ret) |
348 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | |
349 | return ret; | |
350 | } | |
41a0abf7 | 351 | |
96d7ca5e AP |
352 | static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) |
353 | { | |
354 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; | |
355 | struct dvb_usb_device *d = adap_to_d(adap); | |
356 | int ret = 0; | |
357 | dev_dbg(&d->udev->dev, | |
358 | "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n", | |
359 | __func__, adap->id, adap->active_fe, dvbdmxfeed->type, | |
360 | adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, | |
361 | dvbdmxfeed->pid, dvbdmxfeed->index); | |
362 | ||
363 | if (adap->active_fe == -1) | |
364 | return -EINVAL; | |
365 | ||
366 | /* remove PID from device HW PID filter */ | |
367 | if (adap->pid_filtering && adap->props->pid_filter) { | |
368 | ret = adap->props->pid_filter(adap, dvbdmxfeed->index, | |
369 | dvbdmxfeed->pid, 0); | |
370 | if (ret) | |
371 | dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n", | |
372 | KBUILD_MODNAME, ret); | |
41a0abf7 AP |
373 | } |
374 | ||
96d7ca5e AP |
375 | /* we cannot stop streaming until last PID is removed */ |
376 | if (--adap->feed_count > 0) | |
377 | goto skip_feed_stop; | |
378 | ||
379 | /* ask device to stop streaming */ | |
380 | if (d->props->streaming_ctrl) { | |
381 | ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 0); | |
382 | if (ret) | |
383 | dev_err(&d->udev->dev, | |
384 | "%s: streaming_ctrl() failed=%d\n", | |
385 | KBUILD_MODNAME, ret); | |
386 | } | |
387 | ||
388 | /* disable HW PID filter */ | |
389 | if (adap->pid_filtering && adap->props->pid_filter_ctrl) { | |
390 | ret = adap->props->pid_filter_ctrl(adap, 0); | |
391 | if (ret) | |
392 | dev_err(&d->udev->dev, | |
393 | "%s: pid_filter_ctrl() failed=%d\n", | |
394 | KBUILD_MODNAME, ret); | |
395 | } | |
396 | ||
397 | /* kill USB streaming packets */ | |
398 | usb_urb_killv2(&adap->stream); | |
399 | ||
400 | /* clear 'streaming' status bit */ | |
bdecbe43 | 401 | clear_bit(ADAP_STREAMING, &adap->state_bits); |
4e857c58 | 402 | smp_mb__after_atomic(); |
bdecbe43 | 403 | wake_up_bit(&adap->state_bits, ADAP_STREAMING); |
96d7ca5e | 404 | skip_feed_stop: |
41a0abf7 | 405 | |
96d7ca5e AP |
406 | if (ret) |
407 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | |
408 | return ret; | |
41a0abf7 AP |
409 | } |
410 | ||
691a5502 | 411 | static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) |
41a0abf7 AP |
412 | { |
413 | int ret; | |
414 | struct dvb_usb_device *d = adap_to_d(adap); | |
d10d1b9a | 415 | dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); |
41a0abf7 AP |
416 | |
417 | ret = dvb_register_adapter(&adap->dvb_adap, d->name, d->props->owner, | |
418 | &d->udev->dev, d->props->adapter_nr); | |
419 | if (ret < 0) { | |
d10d1b9a AP |
420 | dev_dbg(&d->udev->dev, "%s: dvb_register_adapter() failed=%d\n", |
421 | __func__, ret); | |
831511bd | 422 | goto err_dvb_register_adapter; |
41a0abf7 AP |
423 | } |
424 | ||
425 | adap->dvb_adap.priv = adap; | |
426 | ||
427 | if (d->props->read_mac_address) { | |
428 | ret = d->props->read_mac_address(adap, | |
429 | adap->dvb_adap.proposed_mac); | |
430 | if (ret < 0) | |
831511bd | 431 | goto err_dvb_dmx_init; |
41a0abf7 | 432 | |
d10d1b9a AP |
433 | dev_info(&d->udev->dev, "%s: MAC address: %pM\n", |
434 | KBUILD_MODNAME, adap->dvb_adap.proposed_mac); | |
41a0abf7 AP |
435 | } |
436 | ||
437 | adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | |
438 | adap->demux.priv = adap; | |
439 | adap->demux.filternum = 0; | |
831511bd | 440 | adap->demux.filternum = adap->max_feed_count; |
41a0abf7 AP |
441 | adap->demux.feednum = adap->demux.filternum; |
442 | adap->demux.start_feed = dvb_usb_start_feed; | |
443 | adap->demux.stop_feed = dvb_usb_stop_feed; | |
444 | adap->demux.write_to_decoder = NULL; | |
445 | ret = dvb_dmx_init(&adap->demux); | |
446 | if (ret < 0) { | |
d10d1b9a AP |
447 | dev_err(&d->udev->dev, "%s: dvb_dmx_init() failed=%d\n", |
448 | KBUILD_MODNAME, ret); | |
831511bd | 449 | goto err_dvb_dmx_init; |
41a0abf7 AP |
450 | } |
451 | ||
452 | adap->dmxdev.filternum = adap->demux.filternum; | |
453 | adap->dmxdev.demux = &adap->demux.dmx; | |
454 | adap->dmxdev.capabilities = 0; | |
455 | ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap); | |
456 | if (ret < 0) { | |
d10d1b9a AP |
457 | dev_err(&d->udev->dev, "%s: dvb_dmxdev_init() failed=%d\n", |
458 | KBUILD_MODNAME, ret); | |
831511bd | 459 | goto err_dvb_dmxdev_init; |
41a0abf7 AP |
460 | } |
461 | ||
462 | ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); | |
463 | if (ret < 0) { | |
d10d1b9a AP |
464 | dev_err(&d->udev->dev, "%s: dvb_net_init() failed=%d\n", |
465 | KBUILD_MODNAME, ret); | |
831511bd | 466 | goto err_dvb_net_init; |
41a0abf7 AP |
467 | } |
468 | ||
41a0abf7 | 469 | return 0; |
831511bd | 470 | err_dvb_net_init: |
41a0abf7 | 471 | dvb_dmxdev_release(&adap->dmxdev); |
831511bd | 472 | err_dvb_dmxdev_init: |
41a0abf7 | 473 | dvb_dmx_release(&adap->demux); |
831511bd | 474 | err_dvb_dmx_init: |
41a0abf7 | 475 | dvb_unregister_adapter(&adap->dvb_adap); |
831511bd | 476 | err_dvb_register_adapter: |
41a0abf7 AP |
477 | adap->dvb_adap.priv = NULL; |
478 | return ret; | |
479 | } | |
480 | ||
691a5502 | 481 | static int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap) |
41a0abf7 | 482 | { |
d10d1b9a AP |
483 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, |
484 | adap->id); | |
41a0abf7 AP |
485 | |
486 | if (adap->dvb_adap.priv) { | |
487 | dvb_net_release(&adap->dvb_net); | |
488 | adap->demux.dmx.close(&adap->demux.dmx); | |
489 | dvb_dmxdev_release(&adap->dmxdev); | |
490 | dvb_dmx_release(&adap->demux); | |
491 | dvb_unregister_adapter(&adap->dvb_adap); | |
492 | } | |
493 | ||
494 | return 0; | |
495 | } | |
496 | ||
691a5502 | 497 | static int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff) |
41a0abf7 AP |
498 | { |
499 | int ret; | |
500 | ||
501 | if (onoff) | |
502 | d->powered++; | |
503 | else | |
504 | d->powered--; | |
505 | ||
506 | if (d->powered == 0 || (onoff && d->powered == 1)) { | |
507 | /* when switching from 1 to 0 or from 0 to 1 */ | |
d10d1b9a | 508 | dev_dbg(&d->udev->dev, "%s: power=%d\n", __func__, onoff); |
41a0abf7 AP |
509 | if (d->props->power_ctrl) { |
510 | ret = d->props->power_ctrl(d, onoff); | |
18cfe03d AP |
511 | if (ret < 0) |
512 | goto err; | |
41a0abf7 AP |
513 | } |
514 | } | |
515 | ||
516 | return 0; | |
517 | err: | |
d10d1b9a | 518 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
41a0abf7 AP |
519 | return ret; |
520 | } | |
521 | ||
831511bd | 522 | static int dvb_usb_fe_init(struct dvb_frontend *fe) |
41a0abf7 AP |
523 | { |
524 | int ret; | |
525 | struct dvb_usb_adapter *adap = fe->dvb->priv; | |
526 | struct dvb_usb_device *d = adap_to_d(adap); | |
d10d1b9a AP |
527 | dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, |
528 | fe->id); | |
41a0abf7 | 529 | |
06bae122 AP |
530 | if (!adap->suspend_resume_active) { |
531 | adap->active_fe = fe->id; | |
bdecbe43 | 532 | set_bit(ADAP_INIT, &adap->state_bits); |
06bae122 AP |
533 | } |
534 | ||
41a0abf7 AP |
535 | ret = dvb_usbv2_device_power_ctrl(d, 1); |
536 | if (ret < 0) | |
537 | goto err; | |
538 | ||
539 | if (d->props->frontend_ctrl) { | |
540 | ret = d->props->frontend_ctrl(fe, 1); | |
541 | if (ret < 0) | |
542 | goto err; | |
543 | } | |
544 | ||
545 | if (adap->fe_init[fe->id]) { | |
546 | ret = adap->fe_init[fe->id](fe); | |
547 | if (ret < 0) | |
548 | goto err; | |
549 | } | |
41a0abf7 | 550 | err: |
bdecbe43 AP |
551 | if (!adap->suspend_resume_active) { |
552 | clear_bit(ADAP_INIT, &adap->state_bits); | |
4e857c58 | 553 | smp_mb__after_atomic(); |
bdecbe43 AP |
554 | wake_up_bit(&adap->state_bits, ADAP_INIT); |
555 | } | |
0898b954 | 556 | |
06bae122 | 557 | dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret); |
0898b954 AP |
558 | return ret; |
559 | } | |
560 | ||
41a0abf7 AP |
561 | static int dvb_usb_fe_sleep(struct dvb_frontend *fe) |
562 | { | |
563 | int ret; | |
564 | struct dvb_usb_adapter *adap = fe->dvb->priv; | |
565 | struct dvb_usb_device *d = adap_to_d(adap); | |
d10d1b9a AP |
566 | dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, |
567 | fe->id); | |
41a0abf7 | 568 | |
bdecbe43 AP |
569 | if (!adap->suspend_resume_active) { |
570 | set_bit(ADAP_SLEEP, &adap->state_bits); | |
571 | wait_on_bit(&adap->state_bits, ADAP_STREAMING, wait_schedule, | |
572 | TASK_UNINTERRUPTIBLE); | |
573 | } | |
06bae122 | 574 | |
41a0abf7 AP |
575 | if (adap->fe_sleep[fe->id]) { |
576 | ret = adap->fe_sleep[fe->id](fe); | |
577 | if (ret < 0) | |
578 | goto err; | |
579 | } | |
580 | ||
581 | if (d->props->frontend_ctrl) { | |
582 | ret = d->props->frontend_ctrl(fe, 0); | |
583 | if (ret < 0) | |
584 | goto err; | |
585 | } | |
586 | ||
587 | ret = dvb_usbv2_device_power_ctrl(d, 0); | |
588 | if (ret < 0) | |
589 | goto err; | |
41a0abf7 | 590 | err: |
06bae122 AP |
591 | if (!adap->suspend_resume_active) { |
592 | adap->active_fe = -1; | |
bdecbe43 | 593 | clear_bit(ADAP_SLEEP, &adap->state_bits); |
4e857c58 | 594 | smp_mb__after_atomic(); |
bdecbe43 | 595 | wake_up_bit(&adap->state_bits, ADAP_SLEEP); |
06bae122 | 596 | } |
0898b954 | 597 | |
06bae122 | 598 | dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret); |
0898b954 AP |
599 | return ret; |
600 | } | |
601 | ||
691a5502 | 602 | static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) |
41a0abf7 AP |
603 | { |
604 | int ret, i, count_registered = 0; | |
605 | struct dvb_usb_device *d = adap_to_d(adap); | |
d10d1b9a | 606 | dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); |
41a0abf7 AP |
607 | |
608 | memset(adap->fe, 0, sizeof(adap->fe)); | |
609 | adap->active_fe = -1; | |
610 | ||
611 | if (d->props->frontend_attach) { | |
612 | ret = d->props->frontend_attach(adap); | |
613 | if (ret < 0) { | |
6d7cfec4 AP |
614 | dev_dbg(&d->udev->dev, |
615 | "%s: frontend_attach() failed=%d\n", | |
616 | __func__, ret); | |
41a0abf7 AP |
617 | goto err_dvb_frontend_detach; |
618 | } | |
619 | } else { | |
d10d1b9a AP |
620 | dev_dbg(&d->udev->dev, "%s: frontend_attach() do not exists\n", |
621 | __func__); | |
41a0abf7 AP |
622 | ret = 0; |
623 | goto err; | |
624 | } | |
625 | ||
626 | for (i = 0; i < MAX_NO_OF_FE_PER_ADAP && adap->fe[i]; i++) { | |
627 | adap->fe[i]->id = i; | |
41a0abf7 AP |
628 | /* re-assign sleep and wakeup functions */ |
629 | adap->fe_init[i] = adap->fe[i]->ops.init; | |
06bae122 | 630 | adap->fe[i]->ops.init = dvb_usb_fe_init; |
41a0abf7 | 631 | adap->fe_sleep[i] = adap->fe[i]->ops.sleep; |
06bae122 | 632 | adap->fe[i]->ops.sleep = dvb_usb_fe_sleep; |
41a0abf7 AP |
633 | |
634 | ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]); | |
635 | if (ret < 0) { | |
6d7cfec4 AP |
636 | dev_err(&d->udev->dev, |
637 | "%s: frontend%d registration failed\n", | |
638 | KBUILD_MODNAME, i); | |
41a0abf7 AP |
639 | goto err_dvb_unregister_frontend; |
640 | } | |
641 | ||
642 | count_registered++; | |
643 | } | |
644 | ||
645 | if (d->props->tuner_attach) { | |
646 | ret = d->props->tuner_attach(adap); | |
647 | if (ret < 0) { | |
d10d1b9a AP |
648 | dev_dbg(&d->udev->dev, "%s: tuner_attach() failed=%d\n", |
649 | __func__, ret); | |
41a0abf7 AP |
650 | goto err_dvb_unregister_frontend; |
651 | } | |
652 | } | |
653 | ||
654 | return 0; | |
655 | ||
656 | err_dvb_unregister_frontend: | |
657 | for (i = count_registered - 1; i >= 0; i--) | |
658 | dvb_unregister_frontend(adap->fe[i]); | |
659 | ||
660 | err_dvb_frontend_detach: | |
661 | for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { | |
2a858486 | 662 | if (adap->fe[i]) { |
41a0abf7 | 663 | dvb_frontend_detach(adap->fe[i]); |
2a858486 AP |
664 | adap->fe[i] = NULL; |
665 | } | |
41a0abf7 AP |
666 | } |
667 | ||
668 | err: | |
d10d1b9a | 669 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
41a0abf7 AP |
670 | return ret; |
671 | } | |
672 | ||
691a5502 | 673 | static int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) |
41a0abf7 AP |
674 | { |
675 | int i; | |
d10d1b9a AP |
676 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, |
677 | adap->id); | |
41a0abf7 AP |
678 | |
679 | for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { | |
680 | if (adap->fe[i]) { | |
681 | dvb_unregister_frontend(adap->fe[i]); | |
682 | dvb_frontend_detach(adap->fe[i]); | |
683 | } | |
684 | } | |
685 | ||
686 | return 0; | |
687 | } | |
688 | ||
59784343 | 689 | static int dvb_usbv2_adapter_init(struct dvb_usb_device *d) |
c79b339f AP |
690 | { |
691 | struct dvb_usb_adapter *adap; | |
d496eb8a | 692 | int ret, i, adapter_count; |
c79b339f | 693 | |
5b853004 | 694 | /* resolve adapter count */ |
f093c388 AP |
695 | adapter_count = d->props->num_adapters; |
696 | if (d->props->get_adapter_count) { | |
697 | ret = d->props->get_adapter_count(d); | |
5b853004 AP |
698 | if (ret < 0) |
699 | goto err; | |
700 | ||
701 | adapter_count = ret; | |
702 | } | |
703 | ||
d496eb8a AP |
704 | for (i = 0; i < adapter_count; i++) { |
705 | adap = &d->adapter[i]; | |
f093c388 AP |
706 | adap->id = i; |
707 | adap->props = &d->props->adapter[i]; | |
4e60d951 | 708 | |
e46c5b66 AP |
709 | /* speed - when running at FULL speed we need a HW PID filter */ |
710 | if (d->udev->speed == USB_SPEED_FULL && | |
f093c388 | 711 | !(adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) { |
6d7cfec4 AP |
712 | dev_err(&d->udev->dev, |
713 | "%s: this USB2.0 device cannot be run on a USB1.1 port (it lacks a hardware PID filter)\n", | |
d10d1b9a | 714 | KBUILD_MODNAME); |
d496eb8a AP |
715 | ret = -ENODEV; |
716 | goto err; | |
e46c5b66 | 717 | } else if ((d->udev->speed == USB_SPEED_FULL && |
f093c388 AP |
718 | adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) || |
719 | (adap->props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) { | |
6d7cfec4 AP |
720 | dev_info(&d->udev->dev, |
721 | "%s: will use the device's hardware PID filter (table count: %d)\n", | |
722 | KBUILD_MODNAME, | |
f093c388 | 723 | adap->props->pid_filter_count); |
e46c5b66 | 724 | adap->pid_filtering = 1; |
f093c388 | 725 | adap->max_feed_count = adap->props->pid_filter_count; |
e46c5b66 | 726 | } else { |
6d7cfec4 AP |
727 | dev_info(&d->udev->dev, |
728 | "%s: will pass the complete MPEG2 transport stream to the software demuxer\n", | |
729 | KBUILD_MODNAME); | |
e46c5b66 AP |
730 | adap->pid_filtering = 0; |
731 | adap->max_feed_count = 255; | |
732 | } | |
c79b339f | 733 | |
e46c5b66 | 734 | if (!adap->pid_filtering && dvb_usb_force_pid_filter_usage && |
f093c388 | 735 | adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) { |
6d7cfec4 AP |
736 | dev_info(&d->udev->dev, |
737 | "%s: PID filter enabled by module option\n", | |
738 | KBUILD_MODNAME); | |
e46c5b66 | 739 | adap->pid_filtering = 1; |
f093c388 | 740 | adap->max_feed_count = adap->props->pid_filter_count; |
c79b339f | 741 | } |
c79b339f | 742 | |
59784343 | 743 | ret = dvb_usbv2_adapter_stream_init(adap); |
4e60d951 | 744 | if (ret) |
d496eb8a | 745 | goto err; |
4e60d951 | 746 | |
59784343 | 747 | ret = dvb_usbv2_adapter_dvb_init(adap); |
4e60d951 | 748 | if (ret) |
d496eb8a | 749 | goto err; |
4e60d951 | 750 | |
59784343 | 751 | ret = dvb_usbv2_adapter_frontend_init(adap); |
4e60d951 | 752 | if (ret) |
d496eb8a | 753 | goto err; |
c79b339f AP |
754 | |
755 | /* use exclusive FE lock if there is multiple shared FEs */ | |
20bb9cc4 | 756 | if (adap->fe[1]) |
c79b339f | 757 | adap->dvb_adap.mfe_shared = 1; |
c79b339f AP |
758 | } |
759 | ||
c79b339f | 760 | return 0; |
5b853004 | 761 | err: |
d10d1b9a | 762 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
5b853004 | 763 | return ret; |
c79b339f AP |
764 | } |
765 | ||
59784343 | 766 | static int dvb_usbv2_adapter_exit(struct dvb_usb_device *d) |
c79b339f | 767 | { |
d496eb8a | 768 | int i; |
d10d1b9a | 769 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
6e3a5daa AP |
770 | |
771 | for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { | |
b62fd172 AP |
772 | if (d->adapter[i].props) { |
773 | dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); | |
774 | dvb_usbv2_adapter_dvb_exit(&d->adapter[i]); | |
775 | dvb_usbv2_adapter_stream_exit(&d->adapter[i]); | |
776 | } | |
c79b339f | 777 | } |
d496eb8a | 778 | |
c79b339f AP |
779 | return 0; |
780 | } | |
781 | ||
c79b339f | 782 | /* general initialization functions */ |
59784343 | 783 | static int dvb_usbv2_exit(struct dvb_usb_device *d) |
c79b339f | 784 | { |
d10d1b9a | 785 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
d70521a3 | 786 | |
59784343 AP |
787 | dvb_usbv2_remote_exit(d); |
788 | dvb_usbv2_adapter_exit(d); | |
789 | dvb_usbv2_i2c_exit(d); | |
c79b339f AP |
790 | kfree(d->priv); |
791 | kfree(d); | |
d496eb8a | 792 | |
c79b339f AP |
793 | return 0; |
794 | } | |
795 | ||
59784343 | 796 | static int dvb_usbv2_init(struct dvb_usb_device *d) |
c79b339f | 797 | { |
831511bd | 798 | int ret; |
d10d1b9a | 799 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
c79b339f | 800 | |
59784343 | 801 | dvb_usbv2_device_power_ctrl(d, 1); |
c79b339f | 802 | |
f093c388 AP |
803 | if (d->props->read_config) { |
804 | ret = d->props->read_config(d); | |
43402bbd AP |
805 | if (ret < 0) |
806 | goto err; | |
807 | } | |
808 | ||
59784343 | 809 | ret = dvb_usbv2_i2c_init(d); |
d496eb8a AP |
810 | if (ret < 0) |
811 | goto err; | |
4e60d951 | 812 | |
d496eb8a AP |
813 | ret = dvb_usbv2_adapter_init(d); |
814 | if (ret < 0) | |
815 | goto err; | |
c79b339f | 816 | |
f093c388 AP |
817 | if (d->props->init) { |
818 | ret = d->props->init(d); | |
d496eb8a AP |
819 | if (ret < 0) |
820 | goto err; | |
821 | } | |
dc786937 | 822 | |
59784343 | 823 | ret = dvb_usbv2_remote_init(d); |
d496eb8a AP |
824 | if (ret < 0) |
825 | goto err; | |
c79b339f | 826 | |
59784343 | 827 | dvb_usbv2_device_power_ctrl(d, 0); |
c79b339f AP |
828 | |
829 | return 0; | |
43402bbd | 830 | err: |
d496eb8a | 831 | dvb_usbv2_device_power_ctrl(d, 0); |
d10d1b9a | 832 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
43402bbd | 833 | return ret; |
c79b339f AP |
834 | } |
835 | ||
dd0f5e0b AP |
836 | int dvb_usbv2_probe(struct usb_interface *intf, |
837 | const struct usb_device_id *id) | |
4f208d4e AP |
838 | { |
839 | int ret; | |
dd0f5e0b AP |
840 | struct dvb_usb_device *d; |
841 | struct usb_device *udev = interface_to_usbdev(intf); | |
842 | struct dvb_usb_driver_info *driver_info = | |
843 | (struct dvb_usb_driver_info *) id->driver_info; | |
844 | ||
845 | dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, | |
846 | intf->cur_altsetting->desc.bInterfaceNumber); | |
847 | ||
848 | if (!id->driver_info) { | |
849 | dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); | |
850 | ret = -ENODEV; | |
851 | goto err; | |
852 | } | |
853 | ||
854 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); | |
855 | if (!d) { | |
856 | dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | |
857 | ret = -ENOMEM; | |
858 | goto err; | |
859 | } | |
496e8278 | 860 | |
dd0f5e0b AP |
861 | d->name = driver_info->name; |
862 | d->rc_map = driver_info->rc_map; | |
863 | d->udev = udev; | |
864 | d->props = driver_info->props; | |
865 | ||
866 | if (intf->cur_altsetting->desc.bInterfaceNumber != | |
867 | d->props->bInterfaceNumber) { | |
868 | ret = -ENODEV; | |
869 | goto err_free_all; | |
870 | } | |
871 | ||
872 | mutex_init(&d->usb_mutex); | |
873 | mutex_init(&d->i2c_mutex); | |
c79b339f | 874 | |
f093c388 AP |
875 | if (d->props->size_of_priv) { |
876 | d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); | |
4f208d4e | 877 | if (!d->priv) { |
d10d1b9a AP |
878 | dev_err(&d->udev->dev, "%s: kzalloc() failed\n", |
879 | KBUILD_MODNAME); | |
496e8278 | 880 | ret = -ENOMEM; |
dd0f5e0b | 881 | goto err_free_all; |
496e8278 AP |
882 | } |
883 | } | |
c79b339f | 884 | |
f093c388 | 885 | if (d->props->identify_state) { |
a0921af7 AP |
886 | const char *name = NULL; |
887 | ret = d->props->identify_state(d, &name); | |
496e8278 AP |
888 | if (ret == 0) { |
889 | ; | |
890 | } else if (ret == COLD) { | |
6d7cfec4 AP |
891 | dev_info(&d->udev->dev, |
892 | "%s: found a '%s' in cold state\n", | |
893 | KBUILD_MODNAME, d->name); | |
a0921af7 AP |
894 | |
895 | if (!name) | |
896 | name = d->props->firmware; | |
897 | ||
898 | ret = dvb_usbv2_download_firmware(d, name); | |
899 | if (ret == 0) { | |
900 | /* device is warm, continue initialization */ | |
901 | ; | |
902 | } else if (ret == RECONNECTS_USB) { | |
903 | /* | |
904 | * USB core will call disconnect() and then | |
905 | * probe() as device reconnects itself from the | |
906 | * USB bus. disconnect() will release all driver | |
907 | * resources and probe() is called for 'new' | |
908 | * device. As 'new' device is warm we should | |
909 | * never go here again. | |
910 | */ | |
dd0f5e0b | 911 | goto exit; |
a0921af7 | 912 | } else { |
dd0f5e0b | 913 | goto err_free_all; |
a0921af7 | 914 | } |
496e8278 | 915 | } else { |
dd0f5e0b | 916 | goto err_free_all; |
496e8278 | 917 | } |
c79b339f AP |
918 | } |
919 | ||
d10d1b9a AP |
920 | dev_info(&d->udev->dev, "%s: found a '%s' in warm state\n", |
921 | KBUILD_MODNAME, d->name); | |
c79b339f | 922 | |
59784343 | 923 | ret = dvb_usbv2_init(d); |
4f208d4e | 924 | if (ret < 0) |
dd0f5e0b | 925 | goto err_free_all; |
c79b339f | 926 | |
6d7cfec4 AP |
927 | dev_info(&d->udev->dev, |
928 | "%s: '%s' successfully initialized and connected\n", | |
929 | KBUILD_MODNAME, d->name); | |
dd0f5e0b | 930 | exit: |
4f208d4e | 931 | usb_set_intfdata(intf, d); |
21f5a32e AP |
932 | |
933 | return 0; | |
dd0f5e0b AP |
934 | err_free_all: |
935 | dvb_usbv2_exit(d); | |
21f5a32e | 936 | err: |
d10d1b9a | 937 | dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); |
21f5a32e AP |
938 | return ret; |
939 | } | |
6b8c8c40 | 940 | EXPORT_SYMBOL(dvb_usbv2_probe); |
21f5a32e | 941 | |
6b8c8c40 | 942 | void dvb_usbv2_disconnect(struct usb_interface *intf) |
c79b339f AP |
943 | { |
944 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
831511bd | 945 | const char *name = d->name; |
d10d1b9a | 946 | struct device dev = d->udev->dev; |
dd0f5e0b AP |
947 | dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, |
948 | intf->cur_altsetting->desc.bInterfaceNumber); | |
c79b339f | 949 | |
831511bd AP |
950 | if (d->props->exit) |
951 | d->props->exit(d); | |
5b6a63cc | 952 | |
823eebac | 953 | dvb_usbv2_exit(d); |
4f208d4e | 954 | |
d10d1b9a | 955 | dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", |
4f208d4e | 956 | KBUILD_MODNAME, name); |
c79b339f | 957 | } |
6b8c8c40 | 958 | EXPORT_SYMBOL(dvb_usbv2_disconnect); |
c79b339f | 959 | |
ef81e9eb AP |
960 | int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) |
961 | { | |
962 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
15d08836 | 963 | int ret = 0, i, active_fe; |
0898b954 | 964 | struct dvb_frontend *fe; |
d10d1b9a | 965 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
ef81e9eb AP |
966 | |
967 | /* stop remote controller poll */ | |
ac1c86c8 | 968 | if (d->rc_polling_active) |
ef81e9eb AP |
969 | cancel_delayed_work_sync(&d->rc_query_work); |
970 | ||
5cd98320 | 971 | for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { |
0898b954 AP |
972 | active_fe = d->adapter[i].active_fe; |
973 | if (d->adapter[i].dvb_adap.priv && active_fe != -1) { | |
974 | fe = d->adapter[i].fe[active_fe]; | |
06bae122 | 975 | d->adapter[i].suspend_resume_active = true; |
0898b954 AP |
976 | |
977 | if (d->props->streaming_ctrl) | |
978 | d->props->streaming_ctrl(fe, 0); | |
979 | ||
980 | /* stop usb streaming */ | |
ef81e9eb | 981 | usb_urb_killv2(&d->adapter[i].stream); |
0898b954 | 982 | |
15d08836 | 983 | ret = dvb_frontend_suspend(fe); |
0898b954 | 984 | } |
ef81e9eb AP |
985 | } |
986 | ||
15d08836 | 987 | return ret; |
ef81e9eb AP |
988 | } |
989 | EXPORT_SYMBOL(dvb_usbv2_suspend); | |
990 | ||
15d08836 | 991 | static int dvb_usbv2_resume_common(struct dvb_usb_device *d) |
ef81e9eb | 992 | { |
15d08836 | 993 | int ret = 0, i, active_fe; |
0898b954 | 994 | struct dvb_frontend *fe; |
d10d1b9a | 995 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
ef81e9eb | 996 | |
5cd98320 | 997 | for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) { |
0898b954 AP |
998 | active_fe = d->adapter[i].active_fe; |
999 | if (d->adapter[i].dvb_adap.priv && active_fe != -1) { | |
1000 | fe = d->adapter[i].fe[active_fe]; | |
1001 | ||
15d08836 | 1002 | ret = dvb_frontend_resume(fe); |
0898b954 AP |
1003 | |
1004 | /* resume usb streaming */ | |
ef81e9eb | 1005 | usb_urb_submitv2(&d->adapter[i].stream, NULL); |
0898b954 AP |
1006 | |
1007 | if (d->props->streaming_ctrl) | |
1008 | d->props->streaming_ctrl(fe, 1); | |
06bae122 AP |
1009 | |
1010 | d->adapter[i].suspend_resume_active = false; | |
0898b954 | 1011 | } |
ef81e9eb AP |
1012 | } |
1013 | ||
1014 | /* start remote controller poll */ | |
ac1c86c8 | 1015 | if (d->rc_polling_active) |
ef81e9eb AP |
1016 | schedule_delayed_work(&d->rc_query_work, |
1017 | msecs_to_jiffies(d->rc.interval)); | |
1018 | ||
15d08836 AP |
1019 | return ret; |
1020 | } | |
1021 | ||
1022 | int dvb_usbv2_resume(struct usb_interface *intf) | |
1023 | { | |
1024 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
1025 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | |
1026 | ||
1027 | return dvb_usbv2_resume_common(d); | |
ef81e9eb AP |
1028 | } |
1029 | EXPORT_SYMBOL(dvb_usbv2_resume); | |
1030 | ||
15d08836 AP |
1031 | int dvb_usbv2_reset_resume(struct usb_interface *intf) |
1032 | { | |
1033 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
1034 | int ret; | |
1035 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | |
1036 | ||
1037 | dvb_usbv2_device_power_ctrl(d, 1); | |
1038 | ||
1039 | if (d->props->init) | |
1040 | d->props->init(d); | |
1041 | ||
1042 | ret = dvb_usbv2_resume_common(d); | |
1043 | ||
1044 | dvb_usbv2_device_power_ctrl(d, 0); | |
1045 | ||
1046 | return ret; | |
1047 | } | |
1048 | EXPORT_SYMBOL(dvb_usbv2_reset_resume); | |
1049 | ||
12042b05 | 1050 | MODULE_VERSION("2.0"); |
c79b339f | 1051 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); |
12042b05 AP |
1052 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); |
1053 | MODULE_DESCRIPTION("DVB USB common"); | |
c79b339f | 1054 | MODULE_LICENSE("GPL"); |