summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/dvb/dvb-usb/dvb_usb.h11
-rw-r--r--drivers/media/dvb/dvb-usb/dvb_usb_common.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb_usb_firmware.c16
-rw-r--r--drivers/media/dvb/dvb-usb/dvb_usb_init.c86
4 files changed, 72 insertions, 43 deletions
diff --git a/drivers/media/dvb/dvb-usb/dvb_usb.h b/drivers/media/dvb/dvb-usb/dvb_usb.h
index 101191e7366..e3d55525dec 100644
--- a/drivers/media/dvb/dvb-usb/dvb_usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb_usb.h
@@ -275,9 +275,10 @@ struct dvb_usb_device_properties {
#define CYPRESS_AN2235 2
#define CYPRESS_FX2 3
int usb_ctrl;
- int (*download_firmware) (struct usb_device *, const struct firmware *);
+
+#define RECONNECTS_USB 1
+ int (*download_firmware) (struct dvb_usb_device *, const struct firmware *);
const char *firmware;
- int no_reconnect;
int size_of_priv;
@@ -286,8 +287,10 @@ struct dvb_usb_device_properties {
int (*power_ctrl) (struct dvb_usb_device *, int);
int (*read_mac_address) (struct dvb_usb_device *, u8 []);
- int (*identify_state) (struct usb_device *, struct dvb_usb_device_properties *,
- struct dvb_usb_device_description **, int *);
+
+#define WARM 0
+#define COLD 1
+ int (*identify_state) (struct dvb_usb_device *);
int (*init) (struct dvb_usb_device *);
struct {
diff --git a/drivers/media/dvb/dvb-usb/dvb_usb_common.h b/drivers/media/dvb/dvb-usb/dvb_usb_common.h
index 24341bde02d..dd275cdc108 100644
--- a/drivers/media/dvb/dvb-usb/dvb_usb_common.h
+++ b/drivers/media/dvb/dvb-usb/dvb_usb_common.h
@@ -25,7 +25,7 @@ extern int dvb_usb_disable_rc_polling;
#define deb_uxfer(args...) dprintk(dvb_usb_debug,0x100,args)
/* commonly used methods */
-extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_device_properties *);
+extern int dvb_usb_download_firmware(struct dvb_usb_device *);
extern int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff);
diff --git a/drivers/media/dvb/dvb-usb/dvb_usb_firmware.c b/drivers/media/dvb/dvb-usb/dvb_usb_firmware.c
index 20f2ed782dd..dd9f8220ade 100644
--- a/drivers/media/dvb/dvb-usb/dvb_usb_firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb_usb_firmware.c
@@ -75,29 +75,29 @@ int usbv2_cypress_load_firmware(struct usb_device *udev, const struct firmware *
}
EXPORT_SYMBOL(usbv2_cypress_load_firmware);
-int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_device_properties *props)
+int dvb_usb_download_firmware(struct dvb_usb_device *d)
{
int ret;
const struct firmware *fw = NULL;
- if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) {
+ if ((ret = request_firmware(&fw, d->props.firmware, &d->udev->dev)) != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
- props->firmware,ret);
+ d->props.firmware,ret);
return ret;
}
- info("downloading firmware from file '%s'",props->firmware);
+ info("downloading firmware from file '%s'", d->props.firmware);
- switch (props->usb_ctrl) {
+ switch (d->props.usb_ctrl) {
case CYPRESS_AN2135:
case CYPRESS_AN2235:
case CYPRESS_FX2:
- ret = usbv2_cypress_load_firmware(udev, fw, props->usb_ctrl);
+ ret = usbv2_cypress_load_firmware(d->udev, fw, d->props.usb_ctrl);
break;
case DEVICE_SPECIFIC:
- if (props->download_firmware)
- ret = props->download_firmware(udev,fw);
+ if (d->props.download_firmware)
+ ret = d->props.download_firmware(d, fw);
else {
err("BUG: driver didn't specified a download_firmware-callback, although it claims to have a DEVICE_SPECIFIC one.");
ret = -EINVAL;
diff --git a/drivers/media/dvb/dvb-usb/dvb_usb_init.c b/drivers/media/dvb/dvb-usb/dvb_usb_init.c
index 662c25840f3..9c03a3266be 100644
--- a/drivers/media/dvb/dvb-usb/dvb_usb_init.c
+++ b/drivers/media/dvb/dvb-usb/dvb_usb_init.c
@@ -147,14 +147,6 @@ static int dvb_usb_init(struct dvb_usb_device *d)
d->state = DVB_USB_STATE_INIT;
- if (d->props.size_of_priv > 0) {
- d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL);
- if (d->priv == NULL) {
- err("no memory for priv in 'struct dvb_usb_device'");
- return -ENOMEM;
- }
- }
-
/* check the capabilities and set appropriate variables */
dvb_usb_device_power_ctrl(d, 1);
@@ -175,12 +167,12 @@ static int dvb_usb_init(struct dvb_usb_device *d)
}
/* determine the name and the state of the just found USB device */
-static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, struct dvb_usb_device_properties *props, int *cold)
+static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, struct dvb_usb_device_properties *props, bool *cold)
{
int i, j;
struct dvb_usb_device_description *desc = NULL;
- *cold = -1;
+ *cold = true;
for (i = 0; i < props->num_device_descs; i++) {
@@ -188,7 +180,7 @@ static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device
deb_info("check for cold %x %x\n", props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
- *cold = 1;
+ *cold = true;
desc = &props->devices[i];
break;
}
@@ -201,16 +193,13 @@ static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device
deb_info("check for warm %x %x\n", props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
- *cold = 0;
+ *cold = false;
desc = &props->devices[i];
break;
}
}
}
- if (desc != NULL && props->identify_state != NULL)
- props->identify_state(udev, props, &desc, cold);
-
return desc;
}
@@ -233,38 +222,68 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
* USB
*/
int dvb_usbv2_device_init(struct usb_interface *intf,
- const struct usb_device_id *id)
+ const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct dvb_usb_device *d = NULL;
struct dvb_usb_device_description *desc = NULL;
struct dvb_usb_device_properties *props =
(struct dvb_usb_device_properties *) id->driver_info;
+ int ret = -ENOMEM;
+ bool cold;
+
+ d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
+ if (d == NULL) {
+ err("no memory for 'struct dvb_usb_device'");
+ return -ENOMEM;
+ }
+
+ d->udev = udev;
+ memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
- int ret = -ENOMEM, cold = 0;
+ if (d->props.size_of_priv > 0) {
+ d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL);
+ if (d->priv == NULL) {
+ err("no memory for priv in 'struct dvb_usb_device'");
+ ret = -ENOMEM;
+ goto err_kfree;
+ }
+ }
if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) {
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_kfree;
+ }
+
+ d->desc = desc;
+
+ if (d->props.identify_state) {
+ ret = d->props.identify_state(d);
+ if (ret == 0) {
+ ;
+ } else if (ret == COLD) {
+ cold = true;
+ ret = 0;
+ } else {
+ goto err_kfree;
+ }
}
if (cold) {
info("found a '%s' in cold state, will try to load a firmware", desc->name);
- ret = dvb_usb_download_firmware(udev, props);
- if (!props->no_reconnect || ret != 0)
- return ret;
+ ret = dvb_usb_download_firmware(d);
+ if (ret == 0) {
+ ;
+ } else if (ret == RECONNECTS_USB) {
+ ret = 0;
+ goto err_kfree;
+ } else {
+ goto err_kfree;
+ }
}
info("found a '%s' in warm state.", desc->name);
- d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
- if (d == NULL) {
- err("no memory for 'struct dvb_usb_device'");
- return -ENOMEM;
- }
-
- d->udev = udev;
- memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
- d->desc = desc;
usb_set_intfdata(intf, d);
@@ -274,6 +293,13 @@ int dvb_usbv2_device_init(struct usb_interface *intf,
info("%s successfully initialized and connected.", desc->name);
else
info("%s error while loading driver (%d)", desc->name, ret);
+
+ return 0;
+
+err_kfree:
+ kfree(d->priv);
+ kfree(d);
+
return ret;
}
EXPORT_SYMBOL(dvb_usbv2_device_init);