Commit | Line | Data |
---|---|---|
c79b339f AP |
1 | /* |
2 | * DVB USB library - provides a generic interface for a DVB USB device driver. | |
3 | * | |
4 | * dvb-usb-init.c | |
5 | * | |
6 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
4e60d951 AP |
9 | * under the terms of the GNU General Public License as published by the |
10 | * Free Software Foundation, version 2. | |
c79b339f AP |
11 | * |
12 | * see Documentation/dvb/README.dvb-usb for more information | |
13 | */ | |
14 | #include "dvb_usb_common.h" | |
15 | ||
59784343 AP |
16 | int dvb_usbv2_disable_rc_polling; |
17 | module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644); | |
4e60d951 AP |
18 | MODULE_PARM_DESC(disable_rc_polling, |
19 | "disable remote control polling (default: 0)."); | |
c79b339f | 20 | static int dvb_usb_force_pid_filter_usage; |
4e60d951 AP |
21 | module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, |
22 | int, 0444); | |
23 | MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a" \ | |
24 | " PID filter, if any (default: 0)."); | |
c79b339f | 25 | |
d496eb8a | 26 | static int dvb_usbv2_download_firmware(struct dvb_usb_device *d) |
a0d72d24 AP |
27 | { |
28 | int ret; | |
29 | const struct firmware *fw = NULL; | |
30 | const char *name; | |
31 | ||
32 | /* resolve firmware name */ | |
f093c388 AP |
33 | name = d->props->firmware; |
34 | if (d->props->get_firmware_name) { | |
35 | ret = d->props->get_firmware_name(d, &name); | |
a0d72d24 | 36 | if (ret < 0) |
d496eb8a | 37 | goto err; |
a0d72d24 AP |
38 | } |
39 | ||
f093c388 | 40 | if (!d->props->download_firmware) { |
a0d72d24 AP |
41 | ret = -EINVAL; |
42 | goto err; | |
43 | } | |
44 | ||
45 | ret = request_firmware(&fw, name, &d->udev->dev); | |
46 | if (ret < 0) { | |
23d8e63a AP |
47 | pr_err("%s: did not find the firmware file. (%s) " \ |
48 | "Please see linux/Documentation/dvb/ for " \ | |
65de8f97 | 49 | "more details on firmware-problems. (%d)\n", |
23d8e63a | 50 | KBUILD_MODNAME, name, ret); |
a0d72d24 AP |
51 | goto err; |
52 | } | |
53 | ||
65de8f97 | 54 | pr_info("%s: downloading firmware from file '%s'\n", KBUILD_MODNAME, |
23d8e63a | 55 | name); |
a0d72d24 | 56 | |
f093c388 | 57 | ret = d->props->download_firmware(d, fw); |
a0d72d24 AP |
58 | |
59 | release_firmware(fw); | |
60 | ||
61 | if (ret < 0) | |
62 | goto err; | |
63 | ||
64 | return 0; | |
65 | err: | |
66 | pr_debug("%s: failed=%d\n", __func__, ret); | |
67 | return ret; | |
68 | } | |
69 | ||
d496eb8a | 70 | static int dvb_usbv2_i2c_init(struct dvb_usb_device *d) |
a177c72b | 71 | { |
0fba999f | 72 | int ret; |
a177c72b | 73 | |
f093c388 | 74 | if (!d->props->i2c_algo) { |
0fba999f AP |
75 | ret = 0; |
76 | goto err; | |
77 | } | |
a177c72b AP |
78 | |
79 | strlcpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name)); | |
f093c388 | 80 | d->i2c_adap.algo = d->props->i2c_algo; |
a177c72b AP |
81 | d->i2c_adap.algo_data = NULL; |
82 | d->i2c_adap.dev.parent = &d->udev->dev; | |
83 | ||
84 | i2c_set_adapdata(&d->i2c_adap, d); | |
85 | ||
86 | ret = i2c_add_adapter(&d->i2c_adap); | |
0fba999f AP |
87 | if (ret < 0) { |
88 | pr_err("%s: i2c_add_adapter() failed\n", KBUILD_MODNAME); | |
89 | goto err; | |
90 | } | |
a177c72b AP |
91 | |
92 | d->state |= DVB_USB_STATE_I2C; | |
93 | ||
0fba999f AP |
94 | return 0; |
95 | err: | |
96 | pr_debug("%s: failed=%d\n", __func__, ret); | |
a177c72b AP |
97 | return ret; |
98 | } | |
99 | ||
d496eb8a | 100 | static int dvb_usbv2_i2c_exit(struct dvb_usb_device *d) |
a177c72b AP |
101 | { |
102 | if (d->state & DVB_USB_STATE_I2C) | |
103 | i2c_del_adapter(&d->i2c_adap); | |
0fba999f | 104 | |
a177c72b | 105 | d->state &= ~DVB_USB_STATE_I2C; |
0fba999f | 106 | |
a177c72b AP |
107 | return 0; |
108 | } | |
109 | ||
59784343 | 110 | static int dvb_usbv2_adapter_init(struct dvb_usb_device *d) |
c79b339f AP |
111 | { |
112 | struct dvb_usb_adapter *adap; | |
d496eb8a | 113 | int ret, i, adapter_count; |
c79b339f | 114 | |
5b853004 | 115 | /* resolve adapter count */ |
f093c388 AP |
116 | adapter_count = d->props->num_adapters; |
117 | if (d->props->get_adapter_count) { | |
118 | ret = d->props->get_adapter_count(d); | |
5b853004 AP |
119 | if (ret < 0) |
120 | goto err; | |
121 | ||
122 | adapter_count = ret; | |
123 | } | |
124 | ||
d496eb8a AP |
125 | for (i = 0; i < adapter_count; i++) { |
126 | adap = &d->adapter[i]; | |
c79b339f | 127 | adap->dev = d; |
f093c388 AP |
128 | adap->id = i; |
129 | adap->props = &d->props->adapter[i]; | |
4e60d951 | 130 | |
e46c5b66 AP |
131 | /* speed - when running at FULL speed we need a HW PID filter */ |
132 | if (d->udev->speed == USB_SPEED_FULL && | |
f093c388 | 133 | !(adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) { |
23d8e63a AP |
134 | pr_err("%s: this USB2.0 device cannot be run on a " \ |
135 | "USB1.1 port (it lacks a hardware " \ | |
65de8f97 | 136 | "PID filter)\n", KBUILD_MODNAME); |
d496eb8a AP |
137 | ret = -ENODEV; |
138 | goto err; | |
e46c5b66 | 139 | } else if ((d->udev->speed == USB_SPEED_FULL && |
f093c388 AP |
140 | adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) || |
141 | (adap->props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) { | |
23d8e63a | 142 | pr_info("%s: will use the device's hardware PID " \ |
65de8f97 | 143 | "filter (table count: %d)\n", |
23d8e63a | 144 | KBUILD_MODNAME, |
f093c388 | 145 | adap->props->pid_filter_count); |
e46c5b66 | 146 | adap->pid_filtering = 1; |
f093c388 | 147 | adap->max_feed_count = adap->props->pid_filter_count; |
e46c5b66 | 148 | } else { |
23d8e63a | 149 | pr_info("%s: will pass the complete MPEG2 transport " \ |
65de8f97 | 150 | "stream to the software demuxer\n", |
23d8e63a | 151 | KBUILD_MODNAME); |
e46c5b66 AP |
152 | adap->pid_filtering = 0; |
153 | adap->max_feed_count = 255; | |
154 | } | |
c79b339f | 155 | |
e46c5b66 | 156 | if (!adap->pid_filtering && dvb_usb_force_pid_filter_usage && |
f093c388 | 157 | adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) { |
65de8f97 | 158 | pr_info("%s: pid filter enabled by module option\n", |
23d8e63a | 159 | KBUILD_MODNAME); |
e46c5b66 | 160 | adap->pid_filtering = 1; |
f093c388 | 161 | adap->max_feed_count = adap->props->pid_filter_count; |
c79b339f | 162 | } |
c79b339f | 163 | |
59784343 | 164 | ret = dvb_usbv2_adapter_stream_init(adap); |
4e60d951 | 165 | if (ret) |
d496eb8a | 166 | goto err; |
4e60d951 | 167 | |
59784343 | 168 | ret = dvb_usbv2_adapter_dvb_init(adap); |
4e60d951 | 169 | if (ret) |
d496eb8a | 170 | goto err; |
4e60d951 | 171 | |
59784343 | 172 | ret = dvb_usbv2_adapter_frontend_init(adap); |
4e60d951 | 173 | if (ret) |
d496eb8a | 174 | goto err; |
c79b339f AP |
175 | |
176 | /* use exclusive FE lock if there is multiple shared FEs */ | |
20bb9cc4 | 177 | if (adap->fe[1]) |
c79b339f AP |
178 | adap->dvb_adap.mfe_shared = 1; |
179 | ||
180 | d->num_adapters_initialized++; | |
181 | d->state |= DVB_USB_STATE_DVB; | |
182 | } | |
183 | ||
c79b339f | 184 | return 0; |
5b853004 AP |
185 | err: |
186 | pr_debug("%s: failed=%d\n", __func__, ret); | |
187 | return ret; | |
c79b339f AP |
188 | } |
189 | ||
59784343 | 190 | static int dvb_usbv2_adapter_exit(struct dvb_usb_device *d) |
c79b339f | 191 | { |
d496eb8a | 192 | int i; |
e80e9af3 | 193 | |
d496eb8a AP |
194 | for (i = d->num_adapters_initialized - 1; i >= 0; i--) { |
195 | dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); | |
196 | dvb_usbv2_adapter_dvb_exit(&d->adapter[i]); | |
197 | dvb_usbv2_adapter_stream_exit(&d->adapter[i]); | |
c79b339f | 198 | } |
d496eb8a | 199 | |
c79b339f AP |
200 | d->num_adapters_initialized = 0; |
201 | d->state &= ~DVB_USB_STATE_DVB; | |
d496eb8a | 202 | |
c79b339f AP |
203 | return 0; |
204 | } | |
205 | ||
c79b339f | 206 | /* general initialization functions */ |
59784343 | 207 | static int dvb_usbv2_exit(struct dvb_usb_device *d) |
c79b339f | 208 | { |
19ec2728 | 209 | pr_debug("%s: state before exiting everything: %x\n", __func__, d->state); |
59784343 AP |
210 | dvb_usbv2_remote_exit(d); |
211 | dvb_usbv2_adapter_exit(d); | |
212 | dvb_usbv2_i2c_exit(d); | |
19ec2728 | 213 | pr_debug("%s: state should be zero now: %x\n", __func__, d->state); |
c79b339f AP |
214 | d->state = DVB_USB_STATE_INIT; |
215 | kfree(d->priv); | |
216 | kfree(d); | |
d496eb8a | 217 | |
c79b339f AP |
218 | return 0; |
219 | } | |
220 | ||
59784343 | 221 | static int dvb_usbv2_init(struct dvb_usb_device *d) |
c79b339f AP |
222 | { |
223 | int ret = 0; | |
224 | ||
c79b339f AP |
225 | d->state = DVB_USB_STATE_INIT; |
226 | ||
c79b339f | 227 | /* check the capabilities and set appropriate variables */ |
59784343 | 228 | dvb_usbv2_device_power_ctrl(d, 1); |
c79b339f | 229 | |
f093c388 AP |
230 | if (d->props->read_config) { |
231 | ret = d->props->read_config(d); | |
43402bbd AP |
232 | if (ret < 0) |
233 | goto err; | |
234 | } | |
235 | ||
59784343 | 236 | ret = dvb_usbv2_i2c_init(d); |
d496eb8a AP |
237 | if (ret < 0) |
238 | goto err; | |
4e60d951 | 239 | |
d496eb8a AP |
240 | ret = dvb_usbv2_adapter_init(d); |
241 | if (ret < 0) | |
242 | goto err; | |
c79b339f | 243 | |
f093c388 AP |
244 | if (d->props->init) { |
245 | ret = d->props->init(d); | |
d496eb8a AP |
246 | if (ret < 0) |
247 | goto err; | |
248 | } | |
dc786937 | 249 | |
59784343 | 250 | ret = dvb_usbv2_remote_init(d); |
d496eb8a AP |
251 | if (ret < 0) |
252 | goto err; | |
c79b339f | 253 | |
59784343 | 254 | dvb_usbv2_device_power_ctrl(d, 0); |
c79b339f AP |
255 | |
256 | return 0; | |
43402bbd | 257 | err: |
d496eb8a | 258 | dvb_usbv2_device_power_ctrl(d, 0); |
43402bbd AP |
259 | pr_debug("%s: failed=%d\n", __func__, ret); |
260 | return ret; | |
c79b339f AP |
261 | } |
262 | ||
59784343 | 263 | int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff) |
c79b339f | 264 | { |
d496eb8a AP |
265 | int ret; |
266 | ||
c79b339f AP |
267 | if (onoff) |
268 | d->powered++; | |
269 | else | |
270 | d->powered--; | |
271 | ||
4e60d951 AP |
272 | if (d->powered == 0 || (onoff && d->powered == 1)) { |
273 | /* when switching from 1 to 0 or from 0 to 1 */ | |
d496eb8a | 274 | pr_debug("%s: power control=%d\n", __func__, onoff); |
f093c388 AP |
275 | if (d->props->power_ctrl) { |
276 | ret = d->props->power_ctrl(d, onoff); | |
d496eb8a AP |
277 | goto err; |
278 | } | |
c79b339f | 279 | } |
d496eb8a | 280 | |
c79b339f | 281 | return 0; |
d496eb8a AP |
282 | err: |
283 | pr_debug("%s: failed=%d\n", __func__, ret); | |
284 | return ret; | |
c79b339f AP |
285 | } |
286 | ||
4f208d4e AP |
287 | /* |
288 | * udev, which is used for the firmware downloading, requires we cannot | |
289 | * block during module_init(). module_init() calls USB probe() which | |
290 | * is this routine. Due to that we delay actual operation using workqueue | |
291 | * and return always success here. | |
292 | */ | |
0a867356 | 293 | |
4f208d4e AP |
294 | static void dvb_usbv2_init_work(struct work_struct *work) |
295 | { | |
296 | int ret; | |
297 | struct dvb_usb_device *d = | |
298 | container_of(work, struct dvb_usb_device, probe_work); | |
299 | bool cold = false; | |
496e8278 | 300 | |
3238aafb AP |
301 | d->work_pid = current->pid; |
302 | ||
303 | pr_debug("%s: work_pid=%d\n", __func__, d->work_pid); | |
c79b339f | 304 | |
f093c388 AP |
305 | if (d->props->size_of_priv) { |
306 | d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); | |
4f208d4e AP |
307 | if (!d->priv) { |
308 | pr_err("%s: kzalloc() failed\n", KBUILD_MODNAME); | |
496e8278 | 309 | ret = -ENOMEM; |
4f208d4e | 310 | goto err_usb_driver_release_interface; |
496e8278 AP |
311 | } |
312 | } | |
c79b339f | 313 | |
f093c388 AP |
314 | if (d->props->identify_state) { |
315 | ret = d->props->identify_state(d); | |
496e8278 AP |
316 | if (ret == 0) { |
317 | ; | |
318 | } else if (ret == COLD) { | |
319 | cold = true; | |
320 | ret = 0; | |
321 | } else { | |
4f208d4e | 322 | goto err_usb_driver_release_interface; |
496e8278 | 323 | } |
c79b339f AP |
324 | } |
325 | ||
326 | if (cold) { | |
4f208d4e AP |
327 | pr_info("%s: found a '%s' in cold state\n", |
328 | KBUILD_MODNAME, d->name); | |
59784343 | 329 | ret = dvb_usbv2_download_firmware(d); |
496e8278 AP |
330 | if (ret == 0) { |
331 | ; | |
332 | } else if (ret == RECONNECTS_USB) { | |
333 | ret = 0; | |
4f208d4e | 334 | goto exit_usb_driver_release_interface; |
496e8278 | 335 | } else { |
4f208d4e | 336 | goto err_usb_driver_release_interface; |
496e8278 | 337 | } |
c79b339f AP |
338 | } |
339 | ||
4f208d4e | 340 | pr_info("%s: found a '%s' in warm state\n", KBUILD_MODNAME, d->name); |
c79b339f | 341 | |
59784343 | 342 | ret = dvb_usbv2_init(d); |
4f208d4e AP |
343 | if (ret < 0) |
344 | goto err_usb_driver_release_interface; | |
c79b339f | 345 | |
4f208d4e AP |
346 | pr_info("%s: '%s' successfully initialized and connected\n", |
347 | KBUILD_MODNAME, d->name); | |
21f5a32e AP |
348 | |
349 | return; | |
4f208d4e AP |
350 | err_usb_driver_release_interface: |
351 | pr_info("%s: '%s' error while loading driver (%d)\n", KBUILD_MODNAME, | |
352 | d->name, ret); | |
353 | exit_usb_driver_release_interface: | |
354 | /* it finally calls .disconnect() which frees mem */ | |
355 | usb_driver_release_interface(to_usb_driver(d->intf->dev.driver), | |
356 | d->intf); | |
21f5a32e AP |
357 | pr_debug("%s: failed=%d\n", __func__, ret); |
358 | return; | |
359 | } | |
360 | ||
6b8c8c40 | 361 | int dvb_usbv2_probe(struct usb_interface *intf, |
21f5a32e AP |
362 | const struct usb_device_id *id) |
363 | { | |
364 | int ret; | |
4f208d4e AP |
365 | struct dvb_usb_device *d; |
366 | struct dvb_usb_driver_info *driver_info = | |
367 | (struct dvb_usb_driver_info *) id->driver_info; | |
21f5a32e | 368 | |
36764037 AP |
369 | pr_debug("%s: bInterfaceNumber=%d\n", __func__, |
370 | intf->cur_altsetting->desc.bInterfaceNumber); | |
4f208d4e AP |
371 | |
372 | if (!id->driver_info) { | |
373 | pr_err("%s: driver_info failed\n", KBUILD_MODNAME); | |
374 | ret = -ENODEV; | |
21f5a32e AP |
375 | goto err; |
376 | } | |
377 | ||
4f208d4e AP |
378 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); |
379 | if (!d) { | |
380 | pr_err("%s: kzalloc() failed\n", KBUILD_MODNAME); | |
381 | ret = -ENOMEM; | |
382 | goto err; | |
383 | } | |
21f5a32e | 384 | |
4f208d4e AP |
385 | d->name = driver_info->name; |
386 | d->rc_map = driver_info->rc_map; | |
387 | d->udev = interface_to_usbdev(intf); | |
388 | d->intf = intf; | |
f093c388 | 389 | d->props = driver_info->props; |
36764037 AP |
390 | |
391 | if (d->intf->cur_altsetting->desc.bInterfaceNumber != | |
f093c388 | 392 | d->props->bInterfaceNumber) { |
823eebac | 393 | ret = -ENODEV; |
d496eb8a | 394 | goto err_kfree; |
36764037 AP |
395 | } |
396 | ||
4f208d4e AP |
397 | mutex_init(&d->usb_mutex); |
398 | mutex_init(&d->i2c_mutex); | |
399 | INIT_WORK(&d->probe_work, dvb_usbv2_init_work); | |
400 | usb_set_intfdata(intf, d); | |
401 | ret = schedule_work(&d->probe_work); | |
21f5a32e | 402 | if (ret < 0) { |
4f208d4e | 403 | pr_err("%s: schedule_work() failed\n", KBUILD_MODNAME); |
21f5a32e AP |
404 | goto err_kfree; |
405 | } | |
406 | ||
407 | return 0; | |
408 | err_kfree: | |
4f208d4e | 409 | kfree(d); |
21f5a32e AP |
410 | err: |
411 | pr_debug("%s: failed=%d\n", __func__, ret); | |
412 | return ret; | |
413 | } | |
6b8c8c40 | 414 | EXPORT_SYMBOL(dvb_usbv2_probe); |
21f5a32e | 415 | |
6b8c8c40 | 416 | void dvb_usbv2_disconnect(struct usb_interface *intf) |
c79b339f AP |
417 | { |
418 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
823eebac | 419 | const char *name; |
21f5a32e | 420 | |
3238aafb AP |
421 | pr_debug("%s: pid=%d work_pid=%d\n", __func__, current->pid, |
422 | d->work_pid); | |
4f208d4e | 423 | |
3238aafb AP |
424 | /* ensure initialization work is finished until release resources */ |
425 | if (d->work_pid != current->pid) | |
426 | cancel_work_sync(&d->probe_work); | |
c79b339f | 427 | |
f093c388 AP |
428 | if (d->props->disconnect) |
429 | d->props->disconnect(d); | |
5b6a63cc | 430 | |
823eebac AP |
431 | name = d->name; |
432 | dvb_usbv2_exit(d); | |
4f208d4e AP |
433 | |
434 | pr_info("%s: '%s' successfully deinitialized and disconnected\n", | |
435 | KBUILD_MODNAME, name); | |
c79b339f | 436 | } |
6b8c8c40 | 437 | EXPORT_SYMBOL(dvb_usbv2_disconnect); |
c79b339f | 438 | |
ef81e9eb AP |
439 | int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) |
440 | { | |
441 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
442 | int i; | |
443 | ||
444 | pr_debug("%s:\n", __func__); | |
445 | ||
446 | /* stop remote controller poll */ | |
447 | if (d->rc.query && !d->rc.bulk_mode) | |
448 | cancel_delayed_work_sync(&d->rc_query_work); | |
449 | ||
450 | /* stop streaming */ | |
451 | for (i = d->num_adapters_initialized - 1; i >= 0; i--) { | |
452 | if (d->adapter[i].active_fe != -1) | |
453 | usb_urb_killv2(&d->adapter[i].stream); | |
454 | } | |
455 | ||
456 | return 0; | |
457 | } | |
458 | EXPORT_SYMBOL(dvb_usbv2_suspend); | |
459 | ||
460 | int dvb_usbv2_resume(struct usb_interface *intf) | |
461 | { | |
462 | struct dvb_usb_device *d = usb_get_intfdata(intf); | |
463 | int i; | |
464 | ||
465 | pr_debug("%s:\n", __func__); | |
466 | ||
467 | /* start streaming */ | |
468 | for (i = 0; i < d->num_adapters_initialized; i++) { | |
469 | if (d->adapter[i].active_fe != -1) | |
470 | usb_urb_submitv2(&d->adapter[i].stream, NULL); | |
471 | } | |
472 | ||
473 | /* start remote controller poll */ | |
474 | if (d->rc.query && !d->rc.bulk_mode) | |
475 | schedule_delayed_work(&d->rc_query_work, | |
476 | msecs_to_jiffies(d->rc.interval)); | |
477 | ||
478 | return 0; | |
479 | } | |
480 | EXPORT_SYMBOL(dvb_usbv2_resume); | |
481 | ||
c79b339f AP |
482 | MODULE_VERSION("1.0"); |
483 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | |
484 | MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices"); | |
485 | MODULE_LICENSE("GPL"); |