Re: PROBLEM : Device Re-enumeration not happening after reset

"Jithu Joseph" <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
Dear Alan, Oliver and others,

Thanks really for pointing out, "Reenumeration after a reset wasn't
implemented in 2.4!  It's present only in the 2.6 kernel".

Yesterday i compared my 2.4.27 with 2.6.22  and found out that the
re-enumerate stuff as mentioned by Oliver is missing in 2.4.27's
usb_reset_device () function.

Are you aware of any functions in 2.4 kernel which can be used within
a kernel level usb client driver which will trigger a re-enumeration
of the device. Then i can issue that call after the reset call .
[Since i am working with an embedded board - i am not in a position to
port the kernel to a 2.6 version] . Even some calls to re-enumerate
the entire usb tree should do -as this is my only device.

I assume that if there is no way to trigger a renumeration from within
the kernel level driver then i will have to make some changes to
hub.c's usb_reset_device () , - or are there any easier or simpler
ways to attain my objective. Replugging the device is not an option
for me.

Perhaps i can attempt something like - instead of trying to load a
different DFU driver after the reset - i can bring  DFU logic within
this driver, issue a reset - then set configuration etc and proceed
with the download


Being relatively new to kernel development and being my first post to
the group - i am really bowled over by your responses and supporting
nature  - Once again a big thanks - frankly i never expected a
response.

Thanks and Regards
Jithu Joseph



// I am just copying the 2.4.27's hub.c's usb_reset_device () device -
just in case some of you might want to take a quick glance

int usb_reset_device(struct usb_device *dev)
{
	struct usb_device *parent = dev->parent;
	struct usb_device_descriptor *descriptor;
	int i, ret, port = -1;

	if (!parent) {
		err("attempting to reset root hub!");
		return -EINVAL;
	}

	for (i = 0; i < parent->maxchild; i++)
		if (parent->children[i] == dev) {
			port = i;
			break;
		}

	if (port < 0)
		return -ENOENT;

	down(&usb_address0_sem);

	/* Send a reset to the device */
	if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) {
		usb_hub_port_disable(parent, port);
		up(&usb_address0_sem);
		return(-ENODEV);
	}

	/* Reprogram the Address */
	ret = usb_set_address(dev);
	if (ret < 0) {
		err("USB device not accepting new address (error=%d)", ret);
		usb_hub_port_disable(parent, port);
		up(&usb_address0_sem);
		return ret;
	}

	/* Let the SET_ADDRESS settle */
	wait_ms(10);

	up(&usb_address0_sem);

	/*
	 * Now we fetch the configuration descriptors for the device and
	 * see if anything has changed. If it has, we dump the current
	 * parsed descriptors and reparse from scratch. Then we leave
	 * the device alone for the caller to finish setting up.
	 *
	 * If nothing changed, we reprogram the configuration and then
	 * the alternate settings.
	 */
	descriptor = kmalloc(sizeof *descriptor, GFP_NOIO);
	if (!descriptor) {
		return -ENOMEM;
	}
	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor,
			sizeof(*descriptor));
	if (ret < 0) {
		kfree(descriptor);
		return ret;
	}

	le16_to_cpus(&descriptor->bcdUSB);
	le16_to_cpus(&descriptor->idVendor);
	le16_to_cpus(&descriptor->idProduct);
	le16_to_cpus(&descriptor->bcdDevice);

	if (memcmp(&dev->descriptor, descriptor, sizeof(*descriptor))) {
		kfree(descriptor);
		usb_destroy_configuration(dev);

		ret = usb_get_device_descriptor(dev);
		if (ret < sizeof(dev->descriptor)) {
			if (ret < 0)
				err("unable to get device descriptor (error=%d)", ret);
			else
				err("USB device descriptor short read (expected %Zi, got %i)",
sizeof(dev->descriptor), ret);

			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
			dev->devnum = -1;
			return -EIO;
		}

		ret = usb_get_configuration(dev);
		if (ret < 0) {
			err("unable to get configuration (error=%d)", ret);
			usb_destroy_configuration(dev);
			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
			dev->devnum = -1;
			return 1;
		}

		dev->actconfig = dev->config;
		usb_set_maxpacket(dev);

		return 1;
	}

	kfree(descriptor);

	ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
	if (ret < 0) {
		err("failed to set active configuration (error=%d)", ret);
		return ret;
	}

	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
		struct usb_interface *intf = &dev->actconfig->interface[i];
		struct usb_interface_descriptor *as = &intf->altsetting[intf->act_altsetting];

		ret = usb_set_interface(dev, as->bInterfaceNumber, as->bAlternateSetting);
		if (ret < 0) {
			err("failed to set active alternate setting for interface %d
(error=%d)", i, ret);
			return ret;
		}
	}

	return 0;
}


On 10/28/07, Oliver Neukum <[email protected]> wrote:
> Am Sonntag 28 Oktober 2007 schrieb Alan Stern:
> > You missed a critical piece of information: Jithu is using a 2.4
> > kernel.
>
> <censored> :-(
>
>         Regards
>                 Oliver
>
>

// - my initial post

> Dear All,
>
> I am trying to implement a firmware upgrade for my usb smart card
> reader. (device firmware update procedure : I issue a switch to DFU
> control message and issue a usb_reset which makes the device
> re-enumerate as a DFU device with different VID/PID, after which I
> proceed with the f/w download)
>
> I am having a kernel level usb driver for my device (USB Smart card
> reader). When a user level  application triggers a firm ware update :
> 1.  i get the control in my kernel driver.
> 2.  I send the switch to DFU control message to my device  (which is
> ack ed by the device)
> 3.  i issue a reset using usb_reset_device (defined in hub.c)
>
> The problem i am facing is that after issuing the  "usb_reset_device
> (struct usb_device *dev) ", though i am able to see a reset in the
> CATC( USB protocol Analyzer) , the disconnect of the current usb
> client driver  is not getting called  and also the probe of the DFU
> driver is not getting called (the driver has support for both the
> VIDs/PIDs)
>
> Am i missing something - should i somehow notify the subystem to
> reenumerate the port or am i using the wrong call to reset
>
> At the CATC level i am seeing a reset, and the same address is

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.