.. | .. |
---|
| 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); |
---|