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