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 | ||
68126673 | 24 | static int dvb_usbv2_disable_rc_polling; |
59784343 | 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; |
c5540fbb | 167 | dev->allowed_protocols = 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 | ||
96d7ca5e | 256 | static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) |
41a0abf7 AP |
257 | { |
258 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; | |
259 | struct dvb_usb_device *d = adap_to_d(adap); | |
96d7ca5e AP |
260 | int ret = 0; |
261 | struct usb_data_stream_properties stream_props; | |
262 | dev_dbg(&d->udev->dev, | |
263 | "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n", | |
d10d1b9a | 264 | __func__, adap->id, adap->active_fe, dvbdmxfeed->type, |
41a0abf7 | 265 | adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, |
96d7ca5e | 266 | dvbdmxfeed->pid, dvbdmxfeed->index); |
41a0abf7 | 267 | |
96d7ca5e | 268 | /* wait init is done */ |
74316201 | 269 | wait_on_bit(&adap->state_bits, ADAP_INIT, TASK_UNINTERRUPTIBLE); |
bdecbe43 | 270 | |
41a0abf7 AP |
271 | if (adap->active_fe == -1) |
272 | return -EINVAL; | |
273 | ||
96d7ca5e AP |
274 | /* skip feed setup if we are already feeding */ |
275 | if (adap->feed_count++ > 0) | |
276 | goto skip_feed_start; | |
277 | ||
278 | /* set 'streaming' status bit */ | |
279 | set_bit(ADAP_STREAMING, &adap->state_bits); | |
280 | ||
281 | /* resolve input and output streaming parameters */ | |
282 | if (d->props->get_stream_config) { | |
283 | memcpy(&stream_props, &adap->props->stream, | |
284 | sizeof(struct usb_data_stream_properties)); | |
285 | ret = d->props->get_stream_config(adap->fe[adap->active_fe], | |
286 | &adap->ts_type, &stream_props); | |
287 | if (ret) | |
288 | dev_err(&d->udev->dev, | |
289 | "%s: get_stream_config() failed=%d\n", | |
290 | KBUILD_MODNAME, ret); | |
291 | } else { | |
292 | stream_props = adap->props->stream; | |
293 | } | |
294 | ||
295 | switch (adap->ts_type) { | |
296 | case DVB_USB_FE_TS_TYPE_204: | |
297 | adap->stream.complete = dvb_usb_data_complete_204; | |
298 | break; | |
299 | case DVB_USB_FE_TS_TYPE_RAW: | |
300 | adap->stream.complete = dvb_usb_data_complete_raw; | |
301 | break; | |
302 | case DVB_USB_FE_TS_TYPE_188: | |
303 | default: | |
304 | adap->stream.complete = dvb_usb_data_complete; | |
305 | break; | |
306 | } | |
307 | ||
308 | /* submit USB streaming packets */ | |
309 | usb_urb_submitv2(&adap->stream, &stream_props); | |
310 | ||
311 | /* enable HW PID filter */ | |
312 | if (adap->pid_filtering && adap->props->pid_filter_ctrl) { | |
313 | ret = adap->props->pid_filter_ctrl(adap, 1); | |
314 | if (ret) | |
315 | dev_err(&d->udev->dev, | |
316 | "%s: pid_filter_ctrl() failed=%d\n", | |
317 | KBUILD_MODNAME, ret); | |
318 | } | |
319 | ||
320 | /* ask device to start streaming */ | |
321 | if (d->props->streaming_ctrl) { | |
322 | ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 1); | |
323 | if (ret) | |
324 | dev_err(&d->udev->dev, | |
325 | "%s: streaming_ctrl() failed=%d\n", | |
326 | KBUILD_MODNAME, ret); | |
41a0abf7 | 327 | } |
96d7ca5e | 328 | skip_feed_start: |
41a0abf7 | 329 | |
96d7ca5e AP |
330 | /* add PID to device HW PID filter */ |
331 | if (adap->pid_filtering && adap->props->pid_filter) { | |
41a0abf7 | 332 | ret = adap->props->pid_filter(adap, dvbdmxfeed->index, |
96d7ca5e AP |
333 | dvbdmxfeed->pid, 1); |
334 | if (ret) | |
2d9e7ea6 AP |
335 | dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n", |
336 | KBUILD_MODNAME, ret); | |
337 | } | |
41a0abf7 | 338 | |
96d7ca5e AP |
339 | if (ret) |
340 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | |
341 | return ret; | |
342 | } | |
41a0abf7 | 343 | |
96d7ca5e AP |
344 | static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) |
345 | { | |
346 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; | |
347 | struct dvb_usb_device *d = adap_to_d(adap); | |
348 | int ret = 0; | |
349 | dev_dbg(&d->udev->dev, | |
350 | "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n", | |
351 | __func__, adap->id, adap->active_fe, dvbdmxfeed->type, | |
352 | adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, | |
353 | dvbdmxfeed->pid, dvbdmxfeed->index); | |
354 | ||
355 | if (adap->active_fe == -1) | |
356 | return -EINVAL; | |
357 | ||
358 | /* remove PID from device HW PID filter */ | |
359 | if (adap->pid_filtering && adap->props->pid_filter) { | |
360 | ret = adap->props->pid_filter(adap, dvbdmxfeed->index, | |
361 | dvbdmxfeed->pid, 0); | |
362 | if (ret) | |
363 | dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n", | |
364 | KBUILD_MODNAME, ret); | |
41a0abf7 AP |
365 | } |
366 | ||
96d7ca5e AP |
367 | /* we cannot stop streaming until last PID is removed */ |
368 | if (--adap->feed_count > 0) | |
369 | goto skip_feed_stop; | |
370 | ||
371 | /* ask device to stop streaming */ | |
372 | if (d->props->streaming_ctrl) { | |
373 | ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 0); | |
374 | if (ret) | |
375 | dev_err(&d->udev->dev, | |
376 | "%s: streaming_ctrl() failed=%d\n", | |
377 | KBUILD_MODNAME, ret); | |
378 | } | |
379 | ||
380 | /* disable HW PID filter */ | |
381 | if (adap->pid_filtering && adap->props->pid_filter_ctrl) { | |
382 | ret = adap->props->pid_filter_ctrl(adap, 0); | |
383 | if (ret) | |
384 | dev_err(&d->udev->dev, | |
385 | "%s: pid_filter_ctrl() failed=%d\n", | |
386 | KBUILD_MODNAME, ret); | |
387 | } | |
388 | ||
389 | /* kill USB streaming packets */ | |
390 | usb_urb_killv2(&adap->stream); | |
391 | ||
392 | /* clear 'streaming' status bit */ | |
bdecbe43 | 393 | clear_bit(ADAP_STREAMING, &adap->state_bits); |
4e857c58 | 394 | smp_mb__after_atomic(); |
bdecbe43 | 395 | wake_up_bit(&adap->state_bits, ADAP_STREAMING); |
96d7ca5e | 396 | skip_feed_stop: |
41a0abf7 | 397 | |
96d7ca5e AP |
398 | if (ret) |
399 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | |
400 | return ret; | |
41a0abf7 AP |
401 | } |
402 | ||
691a5502 | 403 | static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) |
41a0abf7 AP |
404 | { |
405 | int ret; | |
406 | struct dvb_usb_device *d = adap_to_d(adap); | |
d10d1b9a | 407 | dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); |
41a0abf7 AP |
408 | |
409 | ret = dvb_register_adapter(&adap->dvb_adap, d->name, d->props->owner, | |
410 | &d->udev->dev, d->props->adapter_nr); | |
411 | if (ret < 0) { | |
d10d1b9a AP |
412 | dev_dbg(&d->udev->dev, "%s: dvb_register_adapter() failed=%d\n", |
413 | __func__, ret); | |
831511bd | 414 | goto err_dvb_register_adapter; |
41a0abf7 AP |
415 | } |
416 | ||
417 | adap->dvb_adap.priv = adap; | |
418 | ||
419 | if (d->props->read_mac_address) { | |
420 | ret = d->props->read_mac_address(adap, | |
421 | adap->dvb_adap.proposed_mac); | |
422 | if (ret < 0) | |
831511bd | 423 | goto err_dvb_dmx_init; |
41a0abf7 | 424 | |
d10d1b9a AP |
425 | dev_info(&d->udev->dev, "%s: MAC address: %pM\n", |
426 | KBUILD_MODNAME, adap->dvb_adap.proposed_mac); | |
41a0abf7 AP |
427 | } |
428 | ||
429 | adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | |
430 | adap->demux.priv = adap; | |
431 | adap->demux.filternum = 0; | |
831511bd | 432 | adap->demux.filternum = adap->max_feed_count; |
41a0abf7 AP |
433 | adap->demux.feednum = adap->demux.filternum; |
434 | adap->demux.start_feed = dvb_usb_start_feed; | |
435 | adap->demux.stop_feed = dvb_usb_stop_feed; | |
436 | adap->demux.write_to_decoder = NULL; | |
437 | ret = dvb_dmx_init(&adap->demux); | |
438 | if (ret < 0) { | |
d10d1b9a AP |
439 | dev_err(&d->udev->dev, "%s: dvb_dmx_init() failed=%d\n", |
440 | KBUILD_MODNAME, ret); | |
831511bd | 441 | goto err_dvb_dmx_init; |
41a0abf7 AP |
442 | } |
443 | ||
444 | adap->dmxdev.filternum = adap->demux.filternum; | |
445 | adap->dmxdev.demux = &adap->demux.dmx; | |
446 | adap->dmxdev.capabilities = 0; | |
447 | ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap); | |
448 | if (ret < 0) { | |
d10d1b9a AP |
449 | dev_err(&d->udev->dev, "%s: dvb_dmxdev_init() failed=%d\n", |
450 | KBUILD_MODNAME, ret); | |
831511bd | 451 | goto err_dvb_dmxdev_init; |
41a0abf7 AP |
452 | } |
453 | ||
454 | ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); | |
455 | if (ret < 0) { | |
d10d1b9a AP |
456 | dev_err(&d->udev->dev, "%s: dvb_net_init() failed=%d\n", |
457 | KBUILD_MODNAME, ret); | |
831511bd | 458 | goto err_dvb_net_init; |
41a0abf7 AP |
459 | } |
460 | ||
41a0abf7 | 461 | return 0; |
831511bd | 462 | err_dvb_net_init: |
41a0abf7 | 463 | dvb_dmxdev_release(&adap->dmxdev); |
831511bd | 464 | err_dvb_dmxdev_init: |
41a0abf7 | 465 | dvb_dmx_release(&adap->demux); |
831511bd | 466 | err_dvb_dmx_init: |
41a0abf7 | 467 | dvb_unregister_adapter(&adap->dvb_adap); |
831511bd | 468 | err_dvb_register_adapter: |
41a0abf7 AP |
469 | adap->dvb_adap.priv = NULL; |
470 | return ret; | |
471 | } | |
472 | ||
691a5502 | 473 | static int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap) |
41a0abf7 | 474 | { |
d10d1b9a AP |
475 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, |
476 | adap->id); | |
41a0abf7 AP |
477 | |
478 | if (adap->dvb_adap.priv) { | |
479 | dvb_net_release(&adap->dvb_net); | |
480 | adap->demux.dmx.close(&adap->demux.dmx); | |
481 | dvb_dmxdev_release(&adap->dmxdev); | |
482 | dvb_dmx_release(&adap->demux); | |
483 | dvb_unregister_adapter(&adap->dvb_adap); | |
484 | } | |
485 | ||
486 | return 0; | |
487 | } | |
488 | ||
691a5502 | 489 | static int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff) |
41a0abf7 AP |
490 | { |
491 | int ret; | |
492 | ||
493 | if (onoff) | |
494 | d->powered++; | |
495 | else | |
496 | d->powered--; | |
497 | ||
498 | if (d->powered == 0 || (onoff && d->powered == 1)) { | |
499 | /* when switching from 1 to 0 or from 0 to 1 */ | |
d10d1b9a | 500 | dev_dbg(&d->udev->dev, "%s: power=%d\n", __func__, onoff); |
41a0abf7 AP |
501 | if (d->props->power_ctrl) { |
502 | ret = d->props->power_ctrl(d, onoff); | |
18cfe03d AP |
503 | if (ret < 0) |
504 | goto err; | |
41a0abf7 AP |
505 | } |
506 | } | |
507 | ||
508 | return 0; | |
509 | err: | |
d10d1b9a | 510 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
41a0abf7 AP |
511 | return ret; |
512 | } | |
513 | ||
831511bd | 514 | static int dvb_usb_fe_init(struct dvb_frontend *fe) |
41a0abf7 AP |
515 | { |
516 | int ret; | |
517 | struct dvb_usb_adapter *adap = fe->dvb->priv; | |
518 | struct dvb_usb_device *d = adap_to_d(adap); | |
d10d1b9a AP |
519 | dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, |
520 | fe->id); | |
41a0abf7 | 521 | |
06bae122 AP |
522 | if (!adap->suspend_resume_active) { |
523 | adap->active_fe = fe->id; | |
bdecbe43 | 524 | set_bit(ADAP_INIT, &adap->state_bits); |
06bae122 AP |
525 | } |
526 | ||
41a0abf7 AP |
527 | ret = dvb_usbv2_device_power_ctrl(d, 1); |
528 | if (ret < 0) | |
529 | goto err; | |
530 | ||
531 | if (d->props->frontend_ctrl) { | |
532 | ret = d->props->frontend_ctrl(fe, 1); | |
533 | if (ret < 0) | |
534 | goto err; | |
535 | } | |
536 | ||
537 | if (adap->fe_init[fe->id]) { | |
538 | ret = adap->fe_init[fe->id](fe); | |
539 | if (ret < 0) | |
540 | goto err; | |
541 | } | |
41a0abf7 | 542 | err: |
bdecbe43 AP |
543 | if (!adap->suspend_resume_active) { |
544 | clear_bit(ADAP_INIT, &adap->state_bits); | |
4e857c58 | 545 | smp_mb__after_atomic(); |
bdecbe43 AP |
546 | wake_up_bit(&adap->state_bits, ADAP_INIT); |
547 | } | |
0898b954 | 548 | |
06bae122 | 549 | dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret); |
0898b954 AP |
550 | return ret; |
551 | } | |
552 | ||
41a0abf7 AP |
553 | static int dvb_usb_fe_sleep(struct dvb_frontend *fe) |
554 | { | |
555 | int ret; | |
556 | struct dvb_usb_adapter *adap = fe->dvb->priv; | |
557 | struct dvb_usb_device *d = adap_to_d(adap); | |
d10d1b9a AP |
558 | dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, |
559 | fe->id); | |
41a0abf7 | 560 | |
bdecbe43 AP |
561 | if (!adap->suspend_resume_active) { |
562 | set_bit(ADAP_SLEEP, &adap->state_bits); | |
74316201 | 563 | wait_on_bit(&adap->state_bits, ADAP_STREAMING, |
bdecbe43 AP |
564 | TASK_UNINTERRUPTIBLE); |
565 | } | |
06bae122 | 566 | |
41a0abf7 AP |
567 | if (adap->fe_sleep[fe->id]) { |
568 | ret = adap->fe_sleep[fe->id](fe); | |
569 | if (ret < 0) | |
570 | goto err; | |
571 | } | |
572 | ||
573 | if (d->props->frontend_ctrl) { | |
574 | ret = d->props->frontend_ctrl(fe, 0); | |
575 | if (ret < 0) | |
576 | goto err; | |
577 | } | |
578 | ||
579 | ret = dvb_usbv2_device_power_ctrl(d, 0); | |
580 | if (ret < 0) | |
581 | goto err; | |
41a0abf7 | 582 | err: |
06bae122 AP |
583 | if (!adap->suspend_resume_active) { |
584 | adap->active_fe = -1; | |
bdecbe43 | 585 | clear_bit(ADAP_SLEEP, &adap->state_bits); |
4e857c58 | 586 | smp_mb__after_atomic(); |
bdecbe43 | 587 | wake_up_bit(&adap->state_bits, ADAP_SLEEP); |
06bae122 | 588 | } |
0898b954 | 589 | |
06bae122 | 590 | dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret); |
0898b954 AP |
591 | return ret; |
592 | } | |
593 | ||
691a5502 | 594 | static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) |
41a0abf7 AP |
595 | { |
596 | int ret, i, count_registered = 0; | |
597 | struct dvb_usb_device *d = adap_to_d(adap); | |
d10d1b9a | 598 | dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); |
41a0abf7 AP |
599 | |
600 | memset(adap->fe, 0, sizeof(adap->fe)); | |
601 | adap->active_fe = -1; | |
602 | ||
603 | if (d->props->frontend_attach) { | |
604 | ret = d->props->frontend_attach(adap); | |
605 | if (ret < 0) { | |
6d7cfec4 AP |
606 | dev_dbg(&d->udev->dev, |
607 | "%s: frontend_attach() failed=%d\n", | |
608 | __func__, ret); | |
41a0abf7 AP |
609 | goto err_dvb_frontend_detach; |
610 | } | |
611 | } else { | |
d10d1b9a AP |
612 | dev_dbg(&d->udev->dev, "%s: frontend_attach() do not exists\n", |
613 | __func__); | |
41a0abf7 AP |
614 | ret = 0; |
615 | goto err; | |
616 | } | |
617 | ||
618 | for (i = 0; i < MAX_NO_OF_FE_PER_ADAP && adap->fe[i]; i++) { | |
619 | adap->fe[i]->id = i; | |
41a0abf7 AP |
620 | /* re-assign sleep and wakeup functions */ |
621 | adap->fe_init[i] = adap->fe[i]->ops.init; | |
06bae122 | 622 | adap->fe[i]->ops.init = dvb_usb_fe_init; |
41a0abf7 | 623 | adap->fe_sleep[i] = adap->fe[i]->ops.sleep; |
06bae122 | 624 | adap->fe[i]->ops.sleep = dvb_usb_fe_sleep; |
41a0abf7 AP |
625 | |
626 | ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]); | |
627 | if (ret < 0) { | |
6d7cfec4 AP |
628 | dev_err(&d->udev->dev, |
629 | "%s: frontend%d registration failed\n", | |
630 | KBUILD_MODNAME, i); | |
41a0abf7 AP |
631 | goto err_dvb_unregister_frontend; |
632 | } | |
633 | ||
634 | count_registered++; | |
635 | } | |
636 | ||
637 | if (d->props->tuner_attach) { | |
638 | ret = d->props->tuner_attach(adap); | |
639 | if (ret < 0) { | |
d10d1b9a AP |
640 | dev_dbg(&d->udev->dev, "%s: tuner_attach() failed=%d\n", |
641 | __func__, ret); | |
41a0abf7 AP |
642 | goto err_dvb_unregister_frontend; |
643 | } | |
644 | } | |
645 | ||
646 | return 0; | |
647 | ||
648 | err_dvb_unregister_frontend: | |
649 | for (i = count_registered - 1; i >= 0; i--) | |
650 | dvb_unregister_frontend(adap->fe[i]); | |
651 | ||
652 | err_dvb_frontend_detach: | |
653 | for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { | |
2a858486 | 654 | if (adap->fe[i]) { |
41a0abf7 | 655 | dvb_frontend_detach(adap->fe[i]); |
2a858486 AP |
656 | adap->fe[i] = NULL; |
657 | } | |
41a0abf7 AP |
658 | } |
659 | ||
660 | err: | |
d10d1b9a | 661 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
41a0abf7 AP |
662 | return ret; |
663 | } | |
664 | ||
691a5502 | 665 | static int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) |
41a0abf7 | 666 | { |
ca42129f AP |
667 | int ret, i; |
668 | struct dvb_usb_device *d = adap_to_d(adap); | |
669 | ||
670 | dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); | |
41a0abf7 AP |
671 | |
672 | for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { | |
673 | if (adap->fe[i]) { | |
674 | dvb_unregister_frontend(adap->fe[i]); | |
675 | dvb_frontend_detach(adap->fe[i]); | |
676 | } | |
677 | } | |
678 | ||
1066d77f AP |
679 | if (d->props->tuner_detach) { |
680 | ret = d->props->tuner_detach(adap); | |
681 | if (ret < 0) { | |
682 | dev_dbg(&d->udev->dev, "%s: tuner_detach() failed=%d\n", | |
683 | __func__, ret); | |
684 | } | |
685 | } | |
686 | ||
ca42129f AP |
687 | if (d->props->frontend_detach) { |
688 | ret = d->props->frontend_detach(adap); | |
689 | if (ret < 0) { | |
690 | dev_dbg(&d->udev->dev, | |
691 | "%s: frontend_detach() failed=%d\n", | |
692 | __func__, ret); | |
693 | } | |
694 | } | |
695 | ||
41a0abf7 AP |
696 | return 0; |
697 | } | |
698 | ||
59784343 | 699 | static int dvb_usbv2_adapter_init(struct dvb_usb_device *d) |
c79b339f AP |
700 | { |
701 | struct dvb_usb_adapter *adap; | |
d496eb8a | 702 | int ret, i, adapter_count; |
c79b339f | 703 | |
5b853004 | 704 | /* resolve adapter count */ |
f093c388 AP |
705 | adapter_count = d->props->num_adapters; |
706 | if (d->props->get_adapter_count) { | |
707 | ret = d->props->get_adapter_count(d); | |
5b853004 AP |
708 | if (ret < 0) |
709 | goto err; | |
710 | ||
711 | adapter_count = ret; | |
712 | } | |
713 | ||
d496eb8a AP |
714 | for (i = 0; i < adapter_count; i++) { |
715 | adap = &d->adapter[i]; | |
f093c388 AP |
716 | adap->id = i; |
717 | adap->props = &d->props->adapter[i]; | |
4e60d951 | 718 | |
e46c5b66 AP |
719 | /* speed - when running at FULL speed we need a HW PID filter */ |
720 | if (d->udev->speed == USB_SPEED_FULL && | |
f093c388 | 721 | !(adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) { |
6d7cfec4 AP |
722 | dev_err(&d->udev->dev, |
723 | "%s: this USB2.0 device cannot be run on a USB1.1 port (it lacks a hardware PID filter)\n", | |
d10d1b9a | 724 | KBUILD_MODNAME); |
d496eb8a AP |
725 | ret = -ENODEV; |
726 | goto err; | |
e46c5b66 | 727 | } else if ((d->udev->speed == USB_SPEED_FULL && |
f093c388 AP |
728 | adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) || |
729 | (adap->props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) { | |
6d7cfec4 AP |
730 | dev_info(&d->udev->dev, |
731 | "%s: will use the device's hardware PID filter (table count: %d)\n", | |
732 | KBUILD_MODNAME, | |
f093c388 | 733 | adap->props->pid_filter_count); |
e46c5b66 | 734 | adap->pid_filtering = 1; |
f093c388 | 735 | adap->max_feed_count = adap->props->pid_filter_count; |
e46c5b66 | 736 | } else { |
6d7cfec4 AP |
737 | dev_info(&d->udev->dev, |
738 | "%s: will pass the complete MPEG2 transport stream to the software demuxer\n", | |
739 | KBUILD_MODNAME); | |
e46c5b66 AP |
740 | adap->pid_filtering = 0; |
741 | adap->max_feed_count = 255; | |
742 | } | |
c79b339f | 743 | |
e46c5b66 | 744 | if (!adap->pid_filtering && dvb_usb_force_pid_filter_usage && |
f093c388 | 745 | adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) { |
6d7cfec4 AP |
746 | dev_info(&d->udev->dev, |
747 | "%s: PID filter enabled by module option\n", | |
748 | KBUILD_MODNAME); | |
e46c5b66 | 749 | adap->pid_filtering = 1; |
f093c388 | 750 | adap->max_feed_count = adap->props->pid_filter_count; |
c79b339f | 751 | } |
c79b339f | 752 | |
59784343 | 753 | ret = dvb_usbv2_adapter_stream_init(adap); |
4e60d951 | 754 | if (ret) |
d496eb8a | 755 | goto err; |
4e60d951 | 756 | |
59784343 | 757 | ret = dvb_usbv2_adapter_dvb_init(adap); |
4e60d951 | 758 | if (ret) |
d496eb8a | 759 | goto err; |
4e60d951 | 760 | |
59784343 | 761 | ret = dvb_usbv2_adapter_frontend_init(adap); |
4e60d951 | 762 | if (ret) |
d496eb8a | 763 | goto err; |
c79b339f AP |
764 | |
765 | /* use exclusive FE lock if there is multiple shared FEs */ | |
20bb9cc4 | 766 | if (adap->fe[1]) |
c79b339f | 767 | adap->dvb_adap.mfe_shared = 1; |
c79b339f AP |
768 | } |
769 | ||
c79b339f | 770 | return 0; |
5b853004 | 771 | err: |
d10d1b9a | 772 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
5b853004 | 773 | return ret; |
c79b339f AP |
774 | } |
775 | ||
59784343 | 776 | static int dvb_usbv2_adapter_exit(struct dvb_usb_device *d) |
c79b339f | 777 | { |
d496eb8a | 778 | int i; |
d10d1b9a | 779 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
6e3a5daa AP |
780 | |
781 | for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { | |
b62fd172 | 782 | if (d->adapter[i].props) { |
b62fd172 AP |
783 | dvb_usbv2_adapter_dvb_exit(&d->adapter[i]); |
784 | dvb_usbv2_adapter_stream_exit(&d->adapter[i]); | |
7a0af6ed | 785 | dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); |
b62fd172 | 786 | } |
c79b339f | 787 | } |
d496eb8a | 788 | |
c79b339f AP |
789 | return 0; |
790 | } | |
791 | ||
c79b339f | 792 | /* general initialization functions */ |
59784343 | 793 | static int dvb_usbv2_exit(struct dvb_usb_device *d) |
c79b339f | 794 | { |
d10d1b9a | 795 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
d70521a3 | 796 | |
59784343 AP |
797 | dvb_usbv2_remote_exit(d); |
798 | dvb_usbv2_adapter_exit(d); | |
799 | dvb_usbv2_i2c_exit(d); | |
c79b339f AP |
800 | kfree(d->priv); |
801 | kfree(d); | |
d496eb8a | 802 | |
c79b339f AP |
803 | return 0; |
804 | } | |
805 | ||
59784343 | 806 | static int dvb_usbv2_init(struct dvb_usb_device *d) |
c79b339f | 807 | { |
831511bd | 808 | int ret; |
d10d1b9a | 809 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
c79b339f | 810 | |
59784343 | 811 | dvb_usbv2_device_power_ctrl(d, 1); |
c79b339f | 812 | |
f093c388 AP |
813 | if (d->props->read_config) { |
814 | ret = d->props->read_config(d); | |
43402bbd AP |
815 | if (ret < 0) |
816 | goto err; | |
817 | } | |
818 | ||
59784343 | 819 | ret = dvb_usbv2_i2c_init(d); |
d496eb8a AP |
820 | if (ret < 0) |
821 | goto err; | |
4e60d951 | 822 | |
d496eb8a AP |
823 | ret = dvb_usbv2_adapter_init(d); |
824 | if (ret < 0) | |
825 | goto err; | |
c79b339f | 826 | |
f093c388 AP |
827 | if (d->props->init) { |
828 | ret = d->props->init(d); | |
d496eb8a AP |
829 | if (ret < 0) |
830 | goto err; | |
831 | } | |
dc786937 | 832 | |
59784343 | 833 | ret = dvb_usbv2_remote_init(d); |
d496eb8a AP |
834 | if (ret < 0) |
835 | goto err; | |
c79b339f | 836 | |
59784343 | 837 | dvb_usbv2_device_power_ctrl(d, 0); |
c79b339f AP |
838 | |
839 | return 0; | |
43402bbd | 840 | err: |
d496eb8a | 841 | dvb_usbv2_device_power_ctrl(d, 0); |
d10d1b9a | 842 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
43402bbd | 843 | return ret; |
c79b339f AP |
844 | } |
845 | ||
dd0f5e0b AP |
846 | int dvb_usbv2_probe(struct usb_interface *intf, |
847 | const struct usb_device_id *id) | |
4f208d4e AP |
848 | { |
849 | int ret; | |
dd0f5e0b AP |
850 | struct dvb_usb_device *d; |
851 | struct usb_device *udev = interface_to_usbdev(intf); | |
852 | struct dvb_usb_driver_info *driver_info = | |
853 | (struct dvb_usb_driver_info *) id->driver_info; | |
854 | ||
855 | dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, | |
856 | intf->cur_altsetting->desc.bInterfaceNumber); | |
857 | ||
858 | if (!id->driver_info) { | |
859 | dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); | |
860 | ret = -ENODEV; | |
861 | goto err; | |
862 | } | |
863 | ||
864 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); | |
865 | if (!d) { | |
866 | dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | |
867 | ret = -ENOMEM; | |
868 | goto err; | |
869 | } | |
496e8278 | 870 | |
dd0f5e0b AP |
871 | d->name = driver_info->name; |
872 | d->rc_map = driver_info->rc_map; | |
873 | d->udev = udev; | |
874 | d->props = driver_info->props; | |
875 | ||
876 | if (intf->cur_altsetting->desc.bInterfaceNumber != | |
877 | d->props->bInterfaceNumber) { | |
878 | ret = -ENODEV; | |
879 | goto err_free_all; | |
880 | } | |
881 | ||
882 | mutex_init(&d->usb_mutex); | |
883 | mutex_init(&d->i2c_mutex); | |
c79b339f | 884 | |
f093c388 AP |
885 | if (d->props->size_of_priv) { |
886 | d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); | |
4f208d4e | 887 | if (!d->priv) { |
d10d1b9a AP |
888 | dev_err(&d->udev->dev, "%s: kzalloc() failed\n", |
889 | KBUILD_MODNAME); | |
496e8278 | 890 | ret = -ENOMEM; |
dd0f5e0b | 891 | goto err_free_all; |
496e8278 AP |
892 | } |
893 | } | |
c79b339f | 894 | |
f093c388 | 895 | if (d->props->identify_state) { |
a0921af7 AP |
896 | const char *name = NULL; |
897 | ret = d->props->identify_state(d, &name); | |
496e8278 AP |
898 | if (ret == 0) { |
899 | ; | |
900 | } else if (ret == COLD) { | |
6d7cfec4 AP |
901 | dev_info(&d->udev->dev, |
902 | "%s: found a '%s' in cold state\n", | |
903 | KBUILD_MODNAME, d->name); | |
a0921af7 AP |
904 | |
905 | if (!name) | |
906 | name = d->props->firmware; | |
907 | ||
908 | ret = dvb_usbv2_download_firmware(d, name); | |
909 | if (ret == 0) { | |
910 | /* device is warm, continue initialization */ | |
911 | ; | |
912 | } else if (ret == RECONNECTS_USB) { | |
913 | /* | |
914 | * USB core will call disconnect() and then | |
915 | * probe() as device reconnects itself from the | |
916 | * USB bus. disconnect() will release all driver | |
917 | * resources and probe() is called for 'new' | |
918 | * device. As 'new' device is warm we should | |
919 | * never go here again. | |
920 | */ | |
dd0f5e0b | 921 | goto exit; |
a0921af7 | 922 | } else { |
dd0f5e0b | 923 | goto err_free_all; |
a0921af7 | 924 | } |
496e8278 | 925 | } else { |
dd0f5e0b | 926 | goto err_free_all; |
496e8278 | 927 | } |
c79b339f AP |
928 | } |
929 | ||
d10d1b9a AP |
930 | dev_info(&d->udev->dev, "%s: found a '%s' in warm state\n", |
931 | KBUILD_MODNAME, d->name); | |
c79b339f | 932 | |
59784343 | 933 | ret = dvb_usbv2_init(d); |
4f208d4e | 934 | if (ret < 0) |
dd0f5e0b | 935 | goto err_free_all; |
c79b339f | 936 | |
6d7cfec4 AP |
937 | dev_info(&d->udev->dev, |
938 | "%s: '%s' successfully initialized and connected\n", | |
939 | KBUILD_MODNAME, d->name); | |
dd0f5e0b | 940 | exit: |
4f208d4e | 941 | usb_set_intfdata(intf, d); |
21f5a32e AP |
942 | |
943 | return 0; | |
dd0f5e0b AP |
944 | err_free_all: |
945 | dvb_usbv2_exit(d); | |
21f5a32e | 946 | err: |
d10d1b9a | 947 | dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); |
21f5a32e AP |
948 | return ret; |
949 | } | |
6b8c8c40 | 950 | EXPORT_SYMBOL(dvb_usbv2_probe); |
21f5a32e | 951 | |
6b8c8c40 | 952 | void dvb_usbv2_disconnect(struct usb_interface *intf) |
c79b339f AP |
953 | { |
954 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
831511bd | 955 | const char *name = d->name; |
d10d1b9a | 956 | struct device dev = d->udev->dev; |
dd0f5e0b AP |
957 | dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, |
958 | intf->cur_altsetting->desc.bInterfaceNumber); | |
c79b339f | 959 | |
831511bd AP |
960 | if (d->props->exit) |
961 | d->props->exit(d); | |
5b6a63cc | 962 | |
823eebac | 963 | dvb_usbv2_exit(d); |
4f208d4e | 964 | |
d10d1b9a | 965 | dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", |
4f208d4e | 966 | KBUILD_MODNAME, name); |
c79b339f | 967 | } |
6b8c8c40 | 968 | EXPORT_SYMBOL(dvb_usbv2_disconnect); |
c79b339f | 969 | |
ef81e9eb AP |
970 | int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) |
971 | { | |
972 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
15d08836 | 973 | int ret = 0, i, active_fe; |
0898b954 | 974 | struct dvb_frontend *fe; |
d10d1b9a | 975 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
ef81e9eb AP |
976 | |
977 | /* stop remote controller poll */ | |
ac1c86c8 | 978 | if (d->rc_polling_active) |
ef81e9eb AP |
979 | cancel_delayed_work_sync(&d->rc_query_work); |
980 | ||
5cd98320 | 981 | for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { |
0898b954 AP |
982 | active_fe = d->adapter[i].active_fe; |
983 | if (d->adapter[i].dvb_adap.priv && active_fe != -1) { | |
984 | fe = d->adapter[i].fe[active_fe]; | |
06bae122 | 985 | d->adapter[i].suspend_resume_active = true; |
0898b954 AP |
986 | |
987 | if (d->props->streaming_ctrl) | |
988 | d->props->streaming_ctrl(fe, 0); | |
989 | ||
990 | /* stop usb streaming */ | |
ef81e9eb | 991 | usb_urb_killv2(&d->adapter[i].stream); |
0898b954 | 992 | |
15d08836 | 993 | ret = dvb_frontend_suspend(fe); |
0898b954 | 994 | } |
ef81e9eb AP |
995 | } |
996 | ||
15d08836 | 997 | return ret; |
ef81e9eb AP |
998 | } |
999 | EXPORT_SYMBOL(dvb_usbv2_suspend); | |
1000 | ||
15d08836 | 1001 | static int dvb_usbv2_resume_common(struct dvb_usb_device *d) |
ef81e9eb | 1002 | { |
15d08836 | 1003 | int ret = 0, i, active_fe; |
0898b954 | 1004 | struct dvb_frontend *fe; |
d10d1b9a | 1005 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
ef81e9eb | 1006 | |
5cd98320 | 1007 | for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) { |
0898b954 AP |
1008 | active_fe = d->adapter[i].active_fe; |
1009 | if (d->adapter[i].dvb_adap.priv && active_fe != -1) { | |
1010 | fe = d->adapter[i].fe[active_fe]; | |
1011 | ||
15d08836 | 1012 | ret = dvb_frontend_resume(fe); |
0898b954 AP |
1013 | |
1014 | /* resume usb streaming */ | |
ef81e9eb | 1015 | usb_urb_submitv2(&d->adapter[i].stream, NULL); |
0898b954 AP |
1016 | |
1017 | if (d->props->streaming_ctrl) | |
1018 | d->props->streaming_ctrl(fe, 1); | |
06bae122 AP |
1019 | |
1020 | d->adapter[i].suspend_resume_active = false; | |
0898b954 | 1021 | } |
ef81e9eb AP |
1022 | } |
1023 | ||
1024 | /* start remote controller poll */ | |
ac1c86c8 | 1025 | if (d->rc_polling_active) |
ef81e9eb AP |
1026 | schedule_delayed_work(&d->rc_query_work, |
1027 | msecs_to_jiffies(d->rc.interval)); | |
1028 | ||
15d08836 AP |
1029 | return ret; |
1030 | } | |
1031 | ||
1032 | int dvb_usbv2_resume(struct usb_interface *intf) | |
1033 | { | |
1034 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
1035 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | |
1036 | ||
1037 | return dvb_usbv2_resume_common(d); | |
ef81e9eb AP |
1038 | } |
1039 | EXPORT_SYMBOL(dvb_usbv2_resume); | |
1040 | ||
15d08836 AP |
1041 | int dvb_usbv2_reset_resume(struct usb_interface *intf) |
1042 | { | |
1043 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
1044 | int ret; | |
1045 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | |
1046 | ||
1047 | dvb_usbv2_device_power_ctrl(d, 1); | |
1048 | ||
1049 | if (d->props->init) | |
1050 | d->props->init(d); | |
1051 | ||
1052 | ret = dvb_usbv2_resume_common(d); | |
1053 | ||
1054 | dvb_usbv2_device_power_ctrl(d, 0); | |
1055 | ||
1056 | return ret; | |
1057 | } | |
1058 | EXPORT_SYMBOL(dvb_usbv2_reset_resume); | |
1059 | ||
12042b05 | 1060 | MODULE_VERSION("2.0"); |
c79b339f | 1061 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); |
12042b05 AP |
1062 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); |
1063 | MODULE_DESCRIPTION("DVB USB common"); | |
c79b339f | 1064 | MODULE_LICENSE("GPL"); |