| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * dvb_frontend.c: DVB frontend tuning interface/thread |
|---|
| 3 | | - * |
|---|
| 4 | 4 | * |
|---|
| 5 | 5 | * Copyright (C) 1999-2001 Ralph Metzler |
|---|
| 6 | 6 | * Marcus Metzler |
|---|
| .. | .. |
|---|
| 8 | 8 | * for convergence integrated media GmbH |
|---|
| 9 | 9 | * |
|---|
| 10 | 10 | * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup) |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or |
|---|
| 13 | | - * modify it under the terms of the GNU General Public License |
|---|
| 14 | | - * as published by the Free Software Foundation; either version 2 |
|---|
| 15 | | - * of the License, or (at your option) any later version. |
|---|
| 16 | | - * |
|---|
| 17 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 18 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 19 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 20 | | - * GNU General Public License for more details. |
|---|
| 21 | | - * To obtain the license, point your browser to |
|---|
| 22 | | - * http://www.gnu.org/copyleft/gpl.html |
|---|
| 23 | 11 | */ |
|---|
| 24 | 12 | |
|---|
| 25 | 13 | /* Enables DVBv3 compatibility bits at the headers */ |
|---|
| .. | .. |
|---|
| 147 | 135 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
|---|
| 148 | 136 | |
|---|
| 149 | 137 | if (fepriv) |
|---|
| 150 | | - dvb_free_device(fepriv->dvbdev); |
|---|
| 138 | + dvb_device_put(fepriv->dvbdev); |
|---|
| 151 | 139 | |
|---|
| 152 | 140 | dvb_frontend_invoke_release(fe, fe->ops.release); |
|---|
| 153 | 141 | |
|---|
| .. | .. |
|---|
| 304 | 292 | } |
|---|
| 305 | 293 | |
|---|
| 306 | 294 | if (events->eventw == events->eventr) { |
|---|
| 307 | | - int ret; |
|---|
| 295 | + struct wait_queue_entry wait; |
|---|
| 296 | + int ret = 0; |
|---|
| 308 | 297 | |
|---|
| 309 | 298 | if (flags & O_NONBLOCK) |
|---|
| 310 | 299 | return -EWOULDBLOCK; |
|---|
| 311 | 300 | |
|---|
| 312 | | - ret = wait_event_interruptible(events->wait_queue, |
|---|
| 313 | | - dvb_frontend_test_event(fepriv, events)); |
|---|
| 314 | | - |
|---|
| 301 | + init_waitqueue_entry(&wait, current); |
|---|
| 302 | + add_wait_queue(&events->wait_queue, &wait); |
|---|
| 303 | + while (!dvb_frontend_test_event(fepriv, events)) { |
|---|
| 304 | + wait_woken(&wait, TASK_INTERRUPTIBLE, 0); |
|---|
| 305 | + if (signal_pending(current)) { |
|---|
| 306 | + ret = -ERESTARTSYS; |
|---|
| 307 | + break; |
|---|
| 308 | + } |
|---|
| 309 | + } |
|---|
| 310 | + remove_wait_queue(&events->wait_queue, &wait); |
|---|
| 315 | 311 | if (ret < 0) |
|---|
| 316 | 312 | return ret; |
|---|
| 317 | 313 | } |
|---|
| .. | .. |
|---|
| 919 | 915 | dev_warn(fe->dvb->device, |
|---|
| 920 | 916 | "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", |
|---|
| 921 | 917 | fe->dvb->num, fe->id); |
|---|
| 918 | + |
|---|
| 919 | + dev_dbg(fe->dvb->device, "frequency interval: tuner: %u...%u, frontend: %u...%u", |
|---|
| 920 | + tuner_min, tuner_max, frontend_min, frontend_max); |
|---|
| 922 | 921 | |
|---|
| 923 | 922 | /* If the standard is for satellite, convert frequencies to kHz */ |
|---|
| 924 | 923 | switch (c->delivery_system) { |
|---|
| .. | .. |
|---|
| 1596 | 1595 | * |
|---|
| 1597 | 1596 | * Provides emulation for delivery systems that are compatible with the old |
|---|
| 1598 | 1597 | * DVBv3 call. Among its usages, it provices support for ISDB-T, and allows |
|---|
| 1599 | | - * using a DVB-S2 only frontend just like it were a DVB-S, if the frontent |
|---|
| 1598 | + * using a DVB-S2 only frontend just like it were a DVB-S, if the frontend |
|---|
| 1600 | 1599 | * parameters are compatible with DVB-S spec. |
|---|
| 1601 | 1600 | */ |
|---|
| 1602 | 1601 | static int emulate_delivery_system(struct dvb_frontend *fe, u32 delsys) |
|---|
| .. | .. |
|---|
| 2323 | 2322 | return 0; |
|---|
| 2324 | 2323 | } |
|---|
| 2325 | 2324 | |
|---|
| 2325 | +static int dvb_get_property(struct dvb_frontend *fe, struct file *file, |
|---|
| 2326 | + struct dtv_properties *tvps) |
|---|
| 2327 | +{ |
|---|
| 2328 | + struct dvb_frontend_private *fepriv = fe->frontend_priv; |
|---|
| 2329 | + struct dtv_property *tvp = NULL; |
|---|
| 2330 | + struct dtv_frontend_properties getp; |
|---|
| 2331 | + int i, err; |
|---|
| 2332 | + |
|---|
| 2333 | + memcpy(&getp, &fe->dtv_property_cache, sizeof(getp)); |
|---|
| 2334 | + |
|---|
| 2335 | + dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", |
|---|
| 2336 | + __func__, tvps->num); |
|---|
| 2337 | + dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", |
|---|
| 2338 | + __func__, tvps->props); |
|---|
| 2339 | + |
|---|
| 2340 | + /* |
|---|
| 2341 | + * Put an arbitrary limit on the number of messages that can |
|---|
| 2342 | + * be sent at once |
|---|
| 2343 | + */ |
|---|
| 2344 | + if (!tvps->num || tvps->num > DTV_IOCTL_MAX_MSGS) |
|---|
| 2345 | + return -EINVAL; |
|---|
| 2346 | + |
|---|
| 2347 | + tvp = memdup_user((void __user *)tvps->props, tvps->num * sizeof(*tvp)); |
|---|
| 2348 | + if (IS_ERR(tvp)) |
|---|
| 2349 | + return PTR_ERR(tvp); |
|---|
| 2350 | + |
|---|
| 2351 | + /* |
|---|
| 2352 | + * Let's use our own copy of property cache, in order to |
|---|
| 2353 | + * avoid mangling with DTV zigzag logic, as drivers might |
|---|
| 2354 | + * return crap, if they don't check if the data is available |
|---|
| 2355 | + * before updating the properties cache. |
|---|
| 2356 | + */ |
|---|
| 2357 | + if (fepriv->state != FESTATE_IDLE) { |
|---|
| 2358 | + err = dtv_get_frontend(fe, &getp, NULL); |
|---|
| 2359 | + if (err < 0) |
|---|
| 2360 | + goto out; |
|---|
| 2361 | + } |
|---|
| 2362 | + for (i = 0; i < tvps->num; i++) { |
|---|
| 2363 | + err = dtv_property_process_get(fe, &getp, |
|---|
| 2364 | + tvp + i, file); |
|---|
| 2365 | + if (err < 0) |
|---|
| 2366 | + goto out; |
|---|
| 2367 | + } |
|---|
| 2368 | + |
|---|
| 2369 | + if (copy_to_user((void __user *)tvps->props, tvp, |
|---|
| 2370 | + tvps->num * sizeof(struct dtv_property))) { |
|---|
| 2371 | + err = -EFAULT; |
|---|
| 2372 | + goto out; |
|---|
| 2373 | + } |
|---|
| 2374 | + |
|---|
| 2375 | + err = 0; |
|---|
| 2376 | +out: |
|---|
| 2377 | + kfree(tvp); |
|---|
| 2378 | + return err; |
|---|
| 2379 | +} |
|---|
| 2380 | + |
|---|
| 2381 | +static int dvb_get_frontend(struct dvb_frontend *fe, |
|---|
| 2382 | + struct dvb_frontend_parameters *p_out) |
|---|
| 2383 | +{ |
|---|
| 2384 | + struct dtv_frontend_properties getp; |
|---|
| 2385 | + |
|---|
| 2386 | + /* |
|---|
| 2387 | + * Let's use our own copy of property cache, in order to |
|---|
| 2388 | + * avoid mangling with DTV zigzag logic, as drivers might |
|---|
| 2389 | + * return crap, if they don't check if the data is available |
|---|
| 2390 | + * before updating the properties cache. |
|---|
| 2391 | + */ |
|---|
| 2392 | + memcpy(&getp, &fe->dtv_property_cache, sizeof(getp)); |
|---|
| 2393 | + |
|---|
| 2394 | + return dtv_get_frontend(fe, &getp, p_out); |
|---|
| 2395 | +} |
|---|
| 2396 | + |
|---|
| 2326 | 2397 | static int dvb_frontend_handle_ioctl(struct file *file, |
|---|
| 2327 | 2398 | unsigned int cmd, void *parg) |
|---|
| 2328 | 2399 | { |
|---|
| .. | .. |
|---|
| 2368 | 2439 | err = 0; |
|---|
| 2369 | 2440 | break; |
|---|
| 2370 | 2441 | } |
|---|
| 2371 | | - case FE_GET_PROPERTY: { |
|---|
| 2372 | | - struct dtv_properties *tvps = parg; |
|---|
| 2373 | | - struct dtv_property *tvp = NULL; |
|---|
| 2374 | | - struct dtv_frontend_properties getp = fe->dtv_property_cache; |
|---|
| 2375 | | - |
|---|
| 2376 | | - dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", |
|---|
| 2377 | | - __func__, tvps->num); |
|---|
| 2378 | | - dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", |
|---|
| 2379 | | - __func__, tvps->props); |
|---|
| 2380 | | - |
|---|
| 2381 | | - /* |
|---|
| 2382 | | - * Put an arbitrary limit on the number of messages that can |
|---|
| 2383 | | - * be sent at once |
|---|
| 2384 | | - */ |
|---|
| 2385 | | - if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS)) |
|---|
| 2386 | | - return -EINVAL; |
|---|
| 2387 | | - |
|---|
| 2388 | | - tvp = memdup_user((void __user *)tvps->props, tvps->num * sizeof(*tvp)); |
|---|
| 2389 | | - if (IS_ERR(tvp)) |
|---|
| 2390 | | - return PTR_ERR(tvp); |
|---|
| 2391 | | - |
|---|
| 2392 | | - /* |
|---|
| 2393 | | - * Let's use our own copy of property cache, in order to |
|---|
| 2394 | | - * avoid mangling with DTV zigzag logic, as drivers might |
|---|
| 2395 | | - * return crap, if they don't check if the data is available |
|---|
| 2396 | | - * before updating the properties cache. |
|---|
| 2397 | | - */ |
|---|
| 2398 | | - if (fepriv->state != FESTATE_IDLE) { |
|---|
| 2399 | | - err = dtv_get_frontend(fe, &getp, NULL); |
|---|
| 2400 | | - if (err < 0) { |
|---|
| 2401 | | - kfree(tvp); |
|---|
| 2402 | | - return err; |
|---|
| 2403 | | - } |
|---|
| 2404 | | - } |
|---|
| 2405 | | - for (i = 0; i < tvps->num; i++) { |
|---|
| 2406 | | - err = dtv_property_process_get(fe, &getp, |
|---|
| 2407 | | - tvp + i, file); |
|---|
| 2408 | | - if (err < 0) { |
|---|
| 2409 | | - kfree(tvp); |
|---|
| 2410 | | - return err; |
|---|
| 2411 | | - } |
|---|
| 2412 | | - } |
|---|
| 2413 | | - |
|---|
| 2414 | | - if (copy_to_user((void __user *)tvps->props, tvp, |
|---|
| 2415 | | - tvps->num * sizeof(struct dtv_property))) { |
|---|
| 2416 | | - kfree(tvp); |
|---|
| 2417 | | - return -EFAULT; |
|---|
| 2418 | | - } |
|---|
| 2419 | | - kfree(tvp); |
|---|
| 2420 | | - err = 0; |
|---|
| 2442 | + case FE_GET_PROPERTY: |
|---|
| 2443 | + err = dvb_get_property(fe, file, parg); |
|---|
| 2421 | 2444 | break; |
|---|
| 2422 | | - } |
|---|
| 2423 | 2445 | |
|---|
| 2424 | 2446 | case FE_GET_INFO: { |
|---|
| 2425 | 2447 | struct dvb_frontend_info *info = parg; |
|---|
| 2426 | 2448 | memset(info, 0, sizeof(*info)); |
|---|
| 2427 | 2449 | |
|---|
| 2428 | | - strcpy(info->name, fe->ops.info.name); |
|---|
| 2450 | + strscpy(info->name, fe->ops.info.name, sizeof(info->name)); |
|---|
| 2429 | 2451 | info->symbol_rate_min = fe->ops.info.symbol_rate_min; |
|---|
| 2430 | 2452 | info->symbol_rate_max = fe->ops.info.symbol_rate_max; |
|---|
| 2431 | 2453 | info->symbol_rate_tolerance = fe->ops.info.symbol_rate_tolerance; |
|---|
| .. | .. |
|---|
| 2557 | 2579 | fepriv->tune_mode_flags = (unsigned long)parg; |
|---|
| 2558 | 2580 | err = 0; |
|---|
| 2559 | 2581 | break; |
|---|
| 2560 | | - |
|---|
| 2561 | 2582 | /* DEPRECATED dish control ioctls */ |
|---|
| 2562 | 2583 | |
|---|
| 2563 | 2584 | case FE_DISHNETWORK_SEND_LEGACY_CMD: |
|---|
| .. | .. |
|---|
| 2590 | 2611 | u8 last = 1; |
|---|
| 2591 | 2612 | |
|---|
| 2592 | 2613 | if (dvb_frontend_debug) |
|---|
| 2593 | | - dprintk("%s switch command: 0x%04lx\n", |
|---|
| 2594 | | - __func__, swcmd); |
|---|
| 2614 | + dprintk("switch command: 0x%04lx\n", |
|---|
| 2615 | + swcmd); |
|---|
| 2595 | 2616 | nexttime = ktime_get_boottime(); |
|---|
| 2596 | 2617 | if (dvb_frontend_debug) |
|---|
| 2597 | 2618 | tv[0] = nexttime; |
|---|
| .. | .. |
|---|
| 2614 | 2635 | dvb_frontend_sleep_until(&nexttime, 8000); |
|---|
| 2615 | 2636 | } |
|---|
| 2616 | 2637 | if (dvb_frontend_debug) { |
|---|
| 2617 | | - dprintk("%s(%d): switch delay (should be 32k followed by all 8k)\n", |
|---|
| 2618 | | - __func__, fe->dvb->num); |
|---|
| 2638 | + dprintk("(adapter %d): switch delay (should be 32k followed by all 8k)\n", |
|---|
| 2639 | + fe->dvb->num); |
|---|
| 2619 | 2640 | for (i = 1; i < 10; i++) |
|---|
| 2620 | 2641 | pr_info("%d: %d\n", i, |
|---|
| 2621 | 2642 | (int)ktime_us_delta(tv[i], tv[i - 1])); |
|---|
| .. | .. |
|---|
| 2676 | 2697 | break; |
|---|
| 2677 | 2698 | err = dtv_set_frontend(fe); |
|---|
| 2678 | 2699 | break; |
|---|
| 2700 | + |
|---|
| 2679 | 2701 | case FE_GET_EVENT: |
|---|
| 2680 | 2702 | err = dvb_frontend_get_event(fe, parg, file->f_flags); |
|---|
| 2681 | 2703 | break; |
|---|
| 2682 | 2704 | |
|---|
| 2683 | | - case FE_GET_FRONTEND: { |
|---|
| 2684 | | - struct dtv_frontend_properties getp = fe->dtv_property_cache; |
|---|
| 2685 | | - |
|---|
| 2686 | | - /* |
|---|
| 2687 | | - * Let's use our own copy of property cache, in order to |
|---|
| 2688 | | - * avoid mangling with DTV zigzag logic, as drivers might |
|---|
| 2689 | | - * return crap, if they don't check if the data is available |
|---|
| 2690 | | - * before updating the properties cache. |
|---|
| 2691 | | - */ |
|---|
| 2692 | | - err = dtv_get_frontend(fe, &getp, parg); |
|---|
| 2705 | + case FE_GET_FRONTEND: |
|---|
| 2706 | + err = dvb_get_frontend(fe, parg); |
|---|
| 2693 | 2707 | break; |
|---|
| 2694 | | - } |
|---|
| 2695 | 2708 | |
|---|
| 2696 | 2709 | default: |
|---|
| 2697 | 2710 | return -ENOTSUPP; |
|---|
| .. | .. |
|---|
| 2956 | 2969 | .name = fe->ops.info.name, |
|---|
| 2957 | 2970 | #endif |
|---|
| 2958 | 2971 | }; |
|---|
| 2972 | + int ret; |
|---|
| 2959 | 2973 | |
|---|
| 2960 | 2974 | dev_dbg(dvb->device, "%s:\n", __func__); |
|---|
| 2961 | 2975 | |
|---|
| .. | .. |
|---|
| 2989 | 3003 | "DVB: registering adapter %i frontend %i (%s)...\n", |
|---|
| 2990 | 3004 | fe->dvb->num, fe->id, fe->ops.info.name); |
|---|
| 2991 | 3005 | |
|---|
| 2992 | | - dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template, |
|---|
| 3006 | + ret = dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template, |
|---|
| 2993 | 3007 | fe, DVB_DEVICE_FRONTEND, 0); |
|---|
| 3008 | + if (ret) { |
|---|
| 3009 | + dvb_frontend_put(fe); |
|---|
| 3010 | + mutex_unlock(&frontend_mutex); |
|---|
| 3011 | + return ret; |
|---|
| 3012 | + } |
|---|
| 2994 | 3013 | |
|---|
| 2995 | 3014 | /* |
|---|
| 2996 | 3015 | * Initialize the cache to the proper values according with the |
|---|