| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * DVB USB library - provides a generic interface for a DVB USB device driver. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) |
|---|
| 7 | 8 | * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 9 | | - * under the terms of the GNU General Public License as published by the Free |
|---|
| 10 | | - * Software Foundation, version 2. |
|---|
| 11 | | - * |
|---|
| 12 | | - * see Documentation/media/dvb-drivers/dvb-usb.rst for more information |
|---|
| 9 | + * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information |
|---|
| 13 | 10 | */ |
|---|
| 14 | 11 | #include "dvb-usb-common.h" |
|---|
| 15 | 12 | |
|---|
| .. | .. |
|---|
| 84 | 81 | |
|---|
| 85 | 82 | ret = dvb_usb_adapter_stream_init(adap); |
|---|
| 86 | 83 | if (ret) |
|---|
| 87 | | - return ret; |
|---|
| 84 | + goto stream_init_err; |
|---|
| 88 | 85 | |
|---|
| 89 | 86 | ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs); |
|---|
| 90 | 87 | if (ret) |
|---|
| .. | .. |
|---|
| 104 | 101 | |
|---|
| 105 | 102 | /* |
|---|
| 106 | 103 | * when reloading the driver w/o replugging the device |
|---|
| 107 | | - * sometimes a timeout occures, this helps |
|---|
| 104 | + * sometimes a timeout occurs, this helps |
|---|
| 108 | 105 | */ |
|---|
| 109 | 106 | if (d->props.generic_bulk_ctrl_endpoint != 0) { |
|---|
| 110 | 107 | usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); |
|---|
| .. | .. |
|---|
| 117 | 114 | dvb_usb_adapter_dvb_exit(adap); |
|---|
| 118 | 115 | dvb_init_err: |
|---|
| 119 | 116 | dvb_usb_adapter_stream_exit(adap); |
|---|
| 117 | +stream_init_err: |
|---|
| 118 | + kfree(adap->priv); |
|---|
| 120 | 119 | return ret; |
|---|
| 121 | 120 | } |
|---|
| 122 | 121 | |
|---|
| .. | .. |
|---|
| 145 | 144 | dvb_usb_i2c_exit(d); |
|---|
| 146 | 145 | deb_info("state should be zero now: %x\n", d->state); |
|---|
| 147 | 146 | d->state = DVB_USB_STATE_INIT; |
|---|
| 147 | + |
|---|
| 148 | + if (d->priv != NULL && d->props.priv_destroy != NULL) |
|---|
| 149 | + d->props.priv_destroy(d); |
|---|
| 150 | + |
|---|
| 148 | 151 | kfree(d->priv); |
|---|
| 149 | 152 | kfree(d); |
|---|
| 150 | 153 | return 0; |
|---|
| .. | .. |
|---|
| 166 | 169 | err("no memory for priv in 'struct dvb_usb_device'"); |
|---|
| 167 | 170 | return -ENOMEM; |
|---|
| 168 | 171 | } |
|---|
| 172 | + |
|---|
| 173 | + if (d->props.priv_init != NULL) { |
|---|
| 174 | + ret = d->props.priv_init(d); |
|---|
| 175 | + if (ret != 0) |
|---|
| 176 | + goto err_priv_init; |
|---|
| 177 | + } |
|---|
| 169 | 178 | } |
|---|
| 170 | 179 | |
|---|
| 171 | 180 | /* check the capabilities and set appropriate variables */ |
|---|
| 172 | 181 | dvb_usb_device_power_ctrl(d, 1); |
|---|
| 173 | 182 | |
|---|
| 174 | | - if ((ret = dvb_usb_i2c_init(d)) || |
|---|
| 175 | | - (ret = dvb_usb_adapter_init(d, adapter_nums))) { |
|---|
| 176 | | - dvb_usb_exit(d); |
|---|
| 177 | | - return ret; |
|---|
| 178 | | - } |
|---|
| 183 | + ret = dvb_usb_i2c_init(d); |
|---|
| 184 | + if (ret) |
|---|
| 185 | + goto err_i2c_init; |
|---|
| 186 | + ret = dvb_usb_adapter_init(d, adapter_nums); |
|---|
| 187 | + if (ret) |
|---|
| 188 | + goto err_adapter_init; |
|---|
| 179 | 189 | |
|---|
| 180 | 190 | if ((ret = dvb_usb_remote_init(d))) |
|---|
| 181 | 191 | err("could not initialize remote control."); |
|---|
| .. | .. |
|---|
| 183 | 193 | dvb_usb_device_power_ctrl(d, 0); |
|---|
| 184 | 194 | |
|---|
| 185 | 195 | return 0; |
|---|
| 196 | + |
|---|
| 197 | +err_adapter_init: |
|---|
| 198 | + dvb_usb_adapter_exit(d); |
|---|
| 199 | + dvb_usb_i2c_exit(d); |
|---|
| 200 | +err_i2c_init: |
|---|
| 201 | + if (d->priv && d->props.priv_destroy) |
|---|
| 202 | + d->props.priv_destroy(d); |
|---|
| 203 | +err_priv_init: |
|---|
| 204 | + kfree(d->priv); |
|---|
| 205 | + d->priv = NULL; |
|---|
| 206 | + return ret; |
|---|
| 186 | 207 | } |
|---|
| 187 | 208 | |
|---|
| 188 | 209 | /* determine the name and the state of the just found USB device */ |
|---|
| 189 | | -static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, struct dvb_usb_device_properties *props, int *cold) |
|---|
| 210 | +static const struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, const struct dvb_usb_device_properties *props, int *cold) |
|---|
| 190 | 211 | { |
|---|
| 191 | 212 | int i, j; |
|---|
| 192 | | - struct dvb_usb_device_description *desc = NULL; |
|---|
| 213 | + const struct dvb_usb_device_description *desc = NULL; |
|---|
| 193 | 214 | |
|---|
| 194 | 215 | *cold = -1; |
|---|
| 195 | 216 | |
|---|
| .. | .. |
|---|
| 244 | 265 | * USB |
|---|
| 245 | 266 | */ |
|---|
| 246 | 267 | int dvb_usb_device_init(struct usb_interface *intf, |
|---|
| 247 | | - struct dvb_usb_device_properties *props, |
|---|
| 268 | + const struct dvb_usb_device_properties *props, |
|---|
| 248 | 269 | struct module *owner, struct dvb_usb_device **du, |
|---|
| 249 | 270 | short *adapter_nums) |
|---|
| 250 | 271 | { |
|---|
| 251 | 272 | struct usb_device *udev = interface_to_usbdev(intf); |
|---|
| 252 | 273 | struct dvb_usb_device *d = NULL; |
|---|
| 253 | | - struct dvb_usb_device_description *desc = NULL; |
|---|
| 274 | + const struct dvb_usb_device_description *desc = NULL; |
|---|
| 254 | 275 | |
|---|
| 255 | 276 | int ret = -ENOMEM, cold = 0; |
|---|
| 256 | 277 | |
|---|
| 257 | 278 | if (du != NULL) |
|---|
| 258 | 279 | *du = NULL; |
|---|
| 259 | 280 | |
|---|
| 260 | | - if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) { |
|---|
| 281 | + d = kzalloc(sizeof(*d), GFP_KERNEL); |
|---|
| 282 | + if (!d) { |
|---|
| 283 | + err("no memory for 'struct dvb_usb_device'"); |
|---|
| 284 | + return -ENOMEM; |
|---|
| 285 | + } |
|---|
| 286 | + |
|---|
| 287 | + memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties)); |
|---|
| 288 | + |
|---|
| 289 | + desc = dvb_usb_find_device(udev, &d->props, &cold); |
|---|
| 290 | + if (!desc) { |
|---|
| 261 | 291 | deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n"); |
|---|
| 262 | | - return -ENODEV; |
|---|
| 292 | + ret = -ENODEV; |
|---|
| 293 | + goto error; |
|---|
| 263 | 294 | } |
|---|
| 264 | 295 | |
|---|
| 265 | 296 | if (cold) { |
|---|
| 266 | 297 | info("found a '%s' in cold state, will try to load a firmware", desc->name); |
|---|
| 267 | 298 | ret = dvb_usb_download_firmware(udev, props); |
|---|
| 268 | 299 | if (!props->no_reconnect || ret != 0) |
|---|
| 269 | | - return ret; |
|---|
| 300 | + goto error; |
|---|
| 270 | 301 | } |
|---|
| 271 | 302 | |
|---|
| 272 | 303 | info("found a '%s' in warm state.", desc->name); |
|---|
| 273 | | - d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); |
|---|
| 274 | | - if (d == NULL) { |
|---|
| 275 | | - err("no memory for 'struct dvb_usb_device'"); |
|---|
| 276 | | - return -ENOMEM; |
|---|
| 277 | | - } |
|---|
| 278 | | - |
|---|
| 279 | 304 | d->udev = udev; |
|---|
| 280 | | - memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties)); |
|---|
| 281 | 305 | d->desc = desc; |
|---|
| 282 | 306 | d->owner = owner; |
|---|
| 283 | 307 | |
|---|
| 284 | 308 | usb_set_intfdata(intf, d); |
|---|
| 285 | 309 | |
|---|
| 286 | | - if (du != NULL) |
|---|
| 310 | + ret = dvb_usb_init(d, adapter_nums); |
|---|
| 311 | + if (ret) { |
|---|
| 312 | + info("%s error while loading driver (%d)", desc->name, ret); |
|---|
| 313 | + goto error; |
|---|
| 314 | + } |
|---|
| 315 | + |
|---|
| 316 | + if (du) |
|---|
| 287 | 317 | *du = d; |
|---|
| 288 | 318 | |
|---|
| 289 | | - ret = dvb_usb_init(d, adapter_nums); |
|---|
| 319 | + info("%s successfully initialized and connected.", desc->name); |
|---|
| 320 | + return 0; |
|---|
| 290 | 321 | |
|---|
| 291 | | - if (ret == 0) |
|---|
| 292 | | - info("%s successfully initialized and connected.", desc->name); |
|---|
| 293 | | - else |
|---|
| 294 | | - info("%s error while loading driver (%d)", desc->name, ret); |
|---|
| 322 | + error: |
|---|
| 323 | + usb_set_intfdata(intf, NULL); |
|---|
| 324 | + kfree(d); |
|---|
| 295 | 325 | return ret; |
|---|
| 296 | 326 | } |
|---|
| 297 | 327 | EXPORT_SYMBOL(dvb_usb_device_init); |
|---|