Beispiel #1
0
/* return: -1 on error, 0 on success, 1 on disconnect.  */
static int hub_port_wait_reset(struct usb_device *hub, int port,
                               struct usb_device *dev, unsigned int delay)
{
    int delay_time, ret;
    u16 portstatus;
    u16 portchange;

    for (delay_time = 0;
            delay_time < HUB_RESET_TIMEOUT;
            delay_time += delay) {
        /* wait to give the device a chance to reset */
        wait_ms(delay);

        /* read and decode port status */
        ret = hub_port_status(hub, port, &portstatus, &portchange);
        if (ret < 0) {
            return -1;
        }

        /* Device went away? */
        if (!(portstatus & USB_PORT_STAT_CONNECTION))
            return 1;

        /* bomb out completely if something weird happened */
        if ((portchange & USB_PORT_STAT_C_CONNECTION))
            return -1;

        /* if we`ve finished resetting, then break out of the loop */
        if (!(portstatus & USB_PORT_STAT_RESET) &&
                (portstatus & USB_PORT_STAT_ENABLE)) {
            if (portstatus & USB_PORT_STAT_HIGH_SPEED)
                dev->speed = USB_SPEED_HIGH;
            else if (portstatus & USB_PORT_STAT_LOW_SPEED)
                dev->speed = USB_SPEED_LOW;
            else
                dev->speed = USB_SPEED_FULL;
            return 0;
        }

        /* switch to the long delay after two short delay failures */
        if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
            delay = HUB_LONG_RESET_TIME;

        dev_dbg (hubdev (hub),
                 "port %d not reset yet, waiting %dms\n",
                 port + 1, delay);
    }

    return -1;
}
Beispiel #2
0
static int list_ports(struct state *st) {
	struct libusb_device **devs;
	struct libusb_device *dev;
	int current;
	int hub_number;
	int unknown_hub_number = 0;
	int ret = 0;

	if (libusb_get_device_list(st->ctx, &devs) < 0){
		perror ("failed to access USB");
		return 0;
	}

	for (current=0; (dev = devs[current]) != NULL; current++) {
		struct libusb_device_descriptor device_desc;
		struct libusb_config_descriptor *config_desc;
		libusb_device_handle *uh;
		uint16_t dev_vid, dev_pid;

		ret = libusb_get_device_descriptor(dev, &device_desc);
		if (ret)
			goto err;

		ret = libusb_get_active_config_descriptor(dev, &config_desc);

		dev_vid = libusb_le16_to_cpu(device_desc.idVendor);
		dev_pid = libusb_le16_to_cpu(device_desc.idProduct);

		if (libusb_open(dev, &uh) != 0 )
			continue;

		if (dev_vid == 0x05e3 && dev_pid == 0x0614) {
			hub_number = get_hub_number(dev);
			if (hub_number == 1)
				printf("Upstream hub - ");
			else if (hub_number == 2)
				printf("Downstream hub - ");
			else
				printf("Unknown hub %d - ", (++unknown_hub_number));
			hub_port_status(uh, hub_number - 1);
		}

		libusb_free_config_descriptor(config_desc);
		libusb_close(uh);
	}
err:
	libusb_free_device_list(devs, 1);

	return ret;
}
Beispiel #3
0
/* return: -1 on error, 0 on success, 1 on disconnect.  */
static int hub_port_debounce(struct usb_device *hub, int port)
{
    int ret;
    int delay_time, stable_count;
    u16 portchange, portstatus;
    unsigned connection;

    connection = 0;
    stable_count = 0;
    for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; delay_time += HUB_DEBOUNCE_STEP) {
        wait_ms(HUB_DEBOUNCE_STEP);

        ret = hub_port_status(hub, port, &portstatus, &portchange);
        if (ret < 0)
            return -1;

        if ((portstatus & USB_PORT_STAT_CONNECTION) == connection) {
            if (connection) {
                if (++stable_count == HUB_DEBOUNCE_STABLE)
                    break;
            }
        } else {
            stable_count = 0;
        }
        connection = portstatus & USB_PORT_STAT_CONNECTION;

        if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
            clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION);
        }
    }

    /* XXX Replace this with dbg() when 2.6 is about to ship. */
    dev_dbg (hubdev (hub),
             "debounce: port %d: delay %dms stable %d status 0x%x\n",
             port + 1, delay_time, stable_count, portstatus);

    return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
}
Beispiel #4
0
int
main (int argc, const char *argv[])
{
	int busnum = 0, devnum = 0;
	int cmd = COMMAND_SET_NONE;
	int port = 1;
	int value = 0;
	int request, feature, index;
	int result = 0;
	int listing = 0;
	int verbose = 0;
	int hub = -1;
	libusb_device_handle *uh = NULL;
	int i;

	if (argc == 1)
		listing = 1;

	for (i = 1; i < argc; i++)
		if (argv[i][0] == '-')
			switch (argv[i][1])
		{
			case 'h':
				if (++i >= argc || busnum > 0 || devnum > 0)
					exit_with_usage (argv[0]);
				hub = atoi (argv[i]);
				break;

			case 'b':
				if (++i >= argc || hub >= 0)
					exit_with_usage (argv[0]);
				busnum = atoi (argv[i]);
				break;

			case 'd':
				if (++i >= argc || hub >= 0)
					exit_with_usage (argv[0]);
				devnum = atoi (argv[i]);
				break;

			case 'P':
				if (++i >= argc)
					exit_with_usage (argv[0]);
				port = atoi (argv[i]);
				break;

			case 'l':
				if (cmd != COMMAND_SET_NONE)
					exit_with_usage (argv[0]);
				if (++i < argc)
					value = atoi (argv[i]);
				else
					value = HUB_LED_GREEN;
				cmd = COMMAND_SET_LED;
				break;

			case 'p':
				if (cmd != COMMAND_SET_NONE)
					exit_with_usage (argv[0]);
				if (++i < argc)
					value = atoi (argv[i]);
				else
					value= 0;
				cmd = COMMAND_SET_POWER;
				break;

			case 'v':
				verbose = 1;
				if (argc == 2)
					listing = 1;
				break;

			default:
				exit_with_usage (argv[0]);
		}
		else
			exit_with_usage (argv[0]);

	if ((busnum > 0 && devnum <= 0) || (busnum <= 0 && devnum > 0))
		/* BUS is specified, but DEV is'nt, or ... */
		exit_with_usage (argv[0]);

	/* Default is the hub #0 */
	if (hub < 0 && busnum == 0)
		hub = 0;

	/* Default is POWER */
	if (cmd == COMMAND_SET_NONE)
		cmd = COMMAND_SET_POWER;

	libusb_init ( &ctx );
	libusb_set_debug( ctx, 3 );

	if (usb_find_hubs (listing, verbose, busnum, devnum, hub) <= 0)
	{
		fprintf (stderr, "No hubs found.\n");
		libusb_exit( ctx );
		exit (1);
	}

	if (listing){
		libusb_exit( ctx );
		exit (0);
	}

	if (hub < 0)
		hub = get_hub (busnum, devnum);

	if (hub >= 0 && hub < number_of_hubs_with_feature){
		if ( libusb_open (hubs[hub].dev, &uh ) || uh == NULL)
		{
			fprintf (stderr, "Device not found.\n");
			result = 1;
		}
		else
		{
			if (cmd == COMMAND_SET_POWER){
				if (value){
					request = LIBUSB_REQUEST_SET_FEATURE;
					feature = USB_PORT_FEAT_POWER;
					index = port;
				}else{
					request = LIBUSB_REQUEST_CLEAR_FEATURE;
					feature = USB_PORT_FEAT_POWER;
					index = port;
				}
			}else{
				request = LIBUSB_REQUEST_SET_FEATURE;
				feature = USB_PORT_FEAT_INDICATOR;
				index = (value << 8) | port;
			}

			if (verbose)
				printf ("Send control message (REQUEST=%d, FEATURE=%d, INDEX=%d)\n",
				request, feature, index);
/*
			if(libusb_detach_kernel_driver( uh, 0 ))
				perror("libusb_detach_kernel_driver");
			if(libusb_claim_interface( uh, 0 ))
				perror("libusb_claim_interface");
*/
			if (libusb_control_transfer (uh, USB_RT_PORT, request, feature, index,
				NULL, 0, CTRL_TIMEOUT) < 0)
			{
				perror ("failed to control.\n");
				result = 1;
			}

			if (verbose)
				hub_port_status (uh, hubs[hub].nport, hubs[hub].usb3);
/*
			libusb_release_interface( uh,0 );
			libusb_attach_kernel_driver( uh, 0); 
*/

			libusb_close (uh);
		}
	}
	libusb_exit( ctx );
	exit (result);
}
Beispiel #5
0
static int
usb_find_hubs (int listing, int verbose, int busnum, int devnum, int hub)
{

	struct libusb_device **devs;
	struct libusb_device *dev;
	int i = 0;
	int r;
	number_of_hubs_with_feature = 0;

	if (libusb_get_device_list( ctx, &devs ) < 0){
		perror ("failed to access USB");
		return 0;
	}

	while ( (dev = devs[i++]) != NULL) {
		struct libusb_device_descriptor desc;
		unsigned short dev_vid, dev_pid, dev_bcd;

		r = libusb_get_device_descriptor(dev, &desc);
		if (r < 0) {
			continue;
		}
		dev_vid = libusb_le16_to_cpu(desc.idVendor);
		dev_pid = libusb_le16_to_cpu(desc.idProduct);
		dev_bcd = libusb_le16_to_cpu(desc.bcdUSB);
		//wmlog_msg(1, "Bus %03d Device %03d: ID %04x:%04x", libusb_get_bus_number(dev), libusb_get_device_address(dev), dev_vid, dev_pid);

		libusb_device_handle *uh;
		int print = 0;
		int usb3 = (dev_bcd >= 0x0300);

		//printf("found dev %d\n", dev->descriptor.bDeviceClass);
		if (desc.bDeviceClass != LIBUSB_CLASS_HUB)
			continue;


		if (listing
			|| (verbose ))
			//		  && ((atoi (bus->dirname) == busnum && dev->devnum == devnum)
			//		      || hub == number_of_hubs_with_feature)))
			print = 1;

		if( libusb_open (dev, &uh) != 0 )
			continue;

/*		if(libusb_detach_kernel_driver( uh, 0 ))
			perror("libusb_detach_kernel_driver");

		if(libusb_claim_interface( uh, 0 ))
			perror("libusb_claim_interface");*/

		if ( uh != NULL )
		{	    

			if (print)
				printf ("Hub #%d at \tBUS:DEV\t\t%03d:%03d\n\t\tUSB VEND:PROD: \t%04x:%04x\n",
				number_of_hubs_with_feature,
				libusb_get_bus_number( dev ), 
				libusb_get_device_address( dev ),
				dev_vid, dev_pid
				);

			char buf[ sizeof(struct usb_hub_descriptor) + 2*4 ];
			int len;
			int nport;
			struct usb_hub_descriptor *uhd = (struct usb_hub_descriptor *)buf;

			if ( (len = libusb_control_transfer ( uh,
				LIBUSB_ENDPOINT_IN | USB_RT_HUB,
				LIBUSB_REQUEST_GET_DESCRIPTOR,
				(usb3 ? LIBUSB_DT_SUPERSPEED_HUB : LIBUSB_DT_HUB)<<8, 0,
				buf, (int)sizeof ( buf ),
				CTRL_TIMEOUT ) )
//			if( libusb_get_descriptor( uh, LIBUSB_DT_HUB, 0, buf, sizeof(buf) )
			    >(int)sizeof (struct usb_hub_descriptor) )
			{
				if (!(!(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND)
					&& (uhd->wHubCharacteristics[0] & HUB_CHAR_LPSM) >= 2)){

						switch ((uhd->wHubCharacteristics[0] & HUB_CHAR_LPSM))
						{
						case 0:
							if (print)
								fprintf (stderr, " INFO: ganged switching.\n");
							break;
						case 1:
							if (print)
								fprintf (stderr, " INFO: individual power switching.\n");
							break;
						case 2:
						case 3:
							if (print)
								fprintf (stderr, " WARN: No power switching.\n");
							break;
						}

						if (print
							&& !(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND))
							fprintf (stderr, " WARN: Port indicators are NOT supported.\n");
				}
			}
			else
			{
				perror ("Can't get hub descriptor.");
				printf( "%d\n",len );
			}

			if( len > 0 )
			{
				nport = buf[2];
				hubs[number_of_hubs_with_feature].busnum = libusb_get_bus_number( dev );
				hubs[number_of_hubs_with_feature].devnum = libusb_get_device_address( dev );
				hubs[number_of_hubs_with_feature].dev = dev;
				hubs[number_of_hubs_with_feature].indicator_support =
					(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND)? 1 : 0;
				hubs[number_of_hubs_with_feature].nport = nport;
				hubs[number_of_hubs_with_feature].usb3 = usb3;

				number_of_hubs_with_feature++;

				if (verbose)
					hub_port_status (uh, nport, usb3);
			}
/*
			libusb_release_interface( uh,0 );
			libusb_attach_kernel_driver( uh, 0); */

			libusb_close (uh);
		}
	}
	libusb_free_device_list( devs, 1 );


	return number_of_hubs_with_feature;
}
Beispiel #6
0
static int
usb_find_hubs (int listing, int verbose, int busnum, int devnum, int hub)
{
  struct usb_bus *busses;
  struct usb_bus *bus;

  number_of_hubs_with_feature = 0;
  busses = usb_get_busses();
  if (busses == NULL)
    {
      perror ("failed to access USB");
      return -1;
    }

  for (bus = busses; bus; bus = bus->next)
    {
      struct usb_device *dev;

      for (dev = bus->devices; dev; dev = dev->next)
	{
	  usb_dev_handle *uh;
	  int print = 0;

	  if (dev->descriptor.bDeviceClass != USB_CLASS_HUB)
	    continue;

	  if (listing
	      || (verbose
		  && ((atoi (bus->dirname) == busnum && dev->devnum == devnum)
		      || hub == number_of_hubs_with_feature)))
	    print = 1;

	  uh = usb_open (dev);

	  if (uh != NULL)
	    {
	      char buf[1024];
	      int len;
	      int nport;
	      struct usb_hub_descriptor *uhd = (struct usb_hub_descriptor *)buf;
	      if ((len = usb_control_msg (uh, USB_DIR_IN | USB_RT_HUB,
					  USB_REQ_GET_DESCRIPTOR,
					  USB_DT_HUB << 8, 0, 
					  buf, sizeof (buf), CTRL_TIMEOUT))
		  > sizeof (struct usb_hub_descriptor))
		{
		  if (!(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND)
		      && (uhd->wHubCharacteristics[0] & HUB_CHAR_LPSM) >= 2)
		    continue;

		  if (print)
		    printf ("Hub #%d at %s:%03d\n",
			    number_of_hubs_with_feature,
			    bus->dirname, dev->devnum);

		  switch ((uhd->wHubCharacteristics[0] & HUB_CHAR_LPSM))
		    {
		    case 0:
		      if (print)
			fprintf (stderr, " INFO: ganged switching.\n");
		      break;
		    case 1:
		      if (print)
			fprintf (stderr, " INFO: individual power switching.\n");
		      break;
		    case 2:
		    case 3:
		      if (print)
			fprintf (stderr, " WARN: No power switching.\n");
		      break;
		    }

		  if (print
		      && !(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND))
		    fprintf (stderr, " WARN: Port indicators are NOT supported.\n");
		}
	      else
		{
		  perror ("Can't get hub descriptor");
		  usb_close (uh);
		  continue;
		}

	      nport = buf[2];
	      hubs[number_of_hubs_with_feature].busnum = atoi (bus->dirname);
	      hubs[number_of_hubs_with_feature].devnum = dev->devnum;
	      hubs[number_of_hubs_with_feature].dev = dev;
	      hubs[number_of_hubs_with_feature].indicator_support =
		(uhd->wHubCharacteristics[0] & HUB_CHAR_PORTIND)? 1 : 0;
	      hubs[number_of_hubs_with_feature].nport = nport;

	      number_of_hubs_with_feature++;

	      if (verbose)
		hub_port_status (uh, nport);

	      usb_close (uh);
	    }
	}
    }

  return number_of_hubs_with_feature;
}
int usb_hub_port1_power_ctr(int value)
//main (int argc, const char *argv[])
{
  int busnum = 0, devnum = 0;
  int cmd = COMMAND_SET_NONE;
  int port = 1;
  //int value = 0;
  int request, feature, index;
  int result = 0;
  int listing = 0;
  int verbose = 0;
  int hub = -1;
  usb_dev_handle *uh = NULL;

  int i;




#if 0
  if (argc == 1)
    listing = 1;

  for (i = 1; i < argc; i++)
    if (argv[i][0] == '-')
      switch (argv[i][1])
	{
	case 'h':
	  if (++i >= argc || busnum > 0 || devnum > 0)
	    exit_with_usage (argv[0]);
	  hub = atoi (argv[i]);
	  break;

	case 'b':
	  if (++i >= argc || hub >= 0)
	    exit_with_usage (argv[0]);
	  busnum = atoi (argv[i]);
	  break;

	case 'd':
	  if (++i >= argc || hub >= 0)
	    exit_with_usage (argv[0]);
	  devnum = atoi (argv[i]);
	  break;

	case 'P':
	  if (++i >= argc)
	    exit_with_usage (argv[0]);
	  port = atoi (argv[i]);
	  break;

	case 'l':
	  if (cmd != COMMAND_SET_NONE)
	    exit_with_usage (argv[0]);
	  if (++i < argc)
	    value = atoi (argv[i]);
	  else
	    value = HUB_LED_GREEN;
	  cmd = COMMAND_SET_LED;
	  break;

	case 'p':
	  if (cmd != COMMAND_SET_NONE)
	    exit_with_usage (argv[0]);
	  if (++i < argc)
	    value = atoi (argv[i]);
	  else
	    value= 0;
	  cmd = COMMAND_SET_POWER;
	  break;

	case 'v':
	  verbose = 1;
	  if (argc == 2)
	    listing = 1;
	  break;

	default:
	  exit_with_usage (argv[0]);
	}
    else
      exit_with_usage (argv[0]);



  if ((busnum > 0 && devnum <= 0) || (busnum <= 0 && devnum > 0))
    /* BUS is specified, but DEV is'nt, or ... */
    exit_with_usage (argv[0]);
#else
    listing = 1;
    int return_busnum, return_devnum ;
    int *p_return_busnum = & return_busnum ;
    int *p_return_devnum = & return_devnum ;

#endif


  /* Default is the hub #0 */
  if (hub < 0 && busnum == 0)
    hub = 0;

  /* Default is POWER */
  if (cmd == COMMAND_SET_NONE)
    cmd = COMMAND_SET_POWER;

  usb_init ();
  usb_find_busses ();
  usb_find_devices ();


  if (
  usb_find_hubs (
  p_return_busnum,p_return_devnum     
    ,listing, verbose, busnum, devnum, hub) 
  //usb_find_hubs (listing, verbose, busnum, devnum, hub) 
    <= 0)
    {
  fprintf (stderr, "No hubs found.\n");
  exit (1);
    }
  else
    {
      //printf ("Hub %d:%d\n",return_busnum,return_devnum);
  busnum=return_busnum;
  devnum=return_devnum;
    }

#if 0
  if (listing)
    exit (0);
#endif

  if (hub < 0)
    hub = get_hub (busnum, devnum);

  if (hub >= 0 && hub < number_of_hubs_with_feature)
    uh = usb_open (hubs[hub].dev);

  if (uh == NULL)
    {
      fprintf (stderr, "Device not found.\n");
      result = 1;
    }
  else
    {
      if (cmd == COMMAND_SET_POWER)
	if (value)
	  {
	    request = USB_REQ_SET_FEATURE;
	    feature = USB_PORT_FEAT_POWER;
	    index = port;
	  }
	else
	  {
	    request = USB_REQ_CLEAR_FEATURE;
	    feature = USB_PORT_FEAT_POWER;
	    index = port;
	  }
      else
	{
	  request = USB_REQ_SET_FEATURE;
	  feature = USB_PORT_FEAT_INDICATOR;
	  index = (value << 8) | port;
	}

      if (verbose)
	printf ("Send control message (REQUEST=%d, FEATURE=%d, INDEX=%d)\n",
		request, feature, index);

      if (usb_control_msg (uh, USB_RT_PORT, request, feature, index,
			   NULL, 0, CTRL_TIMEOUT) < 0)
	{
	  perror ("failed to control.\n");
	  result = 1;
	}

      if (verbose)
	hub_port_status (uh, hubs[hub].nport);

      usb_close (uh);
    }

  //exit (result);
  return (result);
}
Beispiel #8
0
static void hub_events(void)
{
    unsigned long flags;
    struct list_head *tmp;
    struct usb_device *dev;
    struct usb_hub *hub;
    u16 hubstatus;
    u16 hubchange;
    u16 portstatus;
    u16 portchange;
    int i, ret;
    int m=0;
    /*
     *  We restart the list every time to avoid a deadlock with
     * deleting hubs downstream from this one. This should be
     * safe since we delete the hub from the event list.
     * Not the most efficient, but avoids deadlocks.
     */

    while (m<5) {
        m++;
        spin_lock_irqsave(&hub_event_lock, flags);

        if (list_empty(&hub_event_list))
            break;

        /* Grab the next entry from the beginning of the list */
        tmp = hub_event_list.next;

        hub = list_entry(tmp, struct usb_hub, event_list);
        dev = interface_to_usbdev(hub->intf);

        list_del_init(tmp);

        if (unlikely(down_trylock(&hub->khubd_sem)))
            BUG();	/* never blocks, we were on list */

        spin_unlock_irqrestore(&hub_event_lock, flags);

        if (hub->error) {
            dev_dbg (&hub->intf->dev, "resetting for error %d\n",
                     hub->error);

            if (hub_reset(hub)) {
                dev_dbg (&hub->intf->dev,
                         "can't reset; disconnecting\n");
                up(&hub->khubd_sem);
                hub_start_disconnect(dev);
                continue;
            }

            hub->nerrors = 0;
            hub->error = 0;
        }

        for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
            ret = hub_port_status(dev, i, &portstatus, &portchange);
            if (ret < 0) {
                continue;
            }

            if (portchange & USB_PORT_STAT_C_CONNECTION) {
                hub_port_connect_change(hub, i, portstatus, portchange);
            } else if (portchange & USB_PORT_STAT_C_ENABLE) {
                dev_dbg (hubdev (dev),
                         "port %d enable change, status %x\n",
                         i + 1, portstatus);
                clear_port_feature(dev,
                                   i + 1, USB_PORT_FEAT_C_ENABLE);

                /*
                 * EM interference sometimes causes badly
                 * shielded USB devices to be shutdown by
                 * the hub, this hack enables them again.
                 * Works at least with mouse driver.
                 */
                if (!(portstatus & USB_PORT_STAT_ENABLE)
                        && (portstatus & USB_PORT_STAT_CONNECTION)
                        && (dev->children[i])) {
                    dev_err (&hub->intf->dev,
                             "port %i "
                             "disabled by hub (EMI?), "
                             "re-enabling...",
                             i + 1);
                    hub_port_connect_change(hub,
                                            i, portstatus, portchange);
                }
            }

            if (portchange & USB_PORT_STAT_C_SUSPEND) {
                dev_dbg (&hub->intf->dev,
                         "suspend change on port %d\n",
                         i + 1);
                clear_port_feature(dev,
                                   i + 1,  USB_PORT_FEAT_C_SUSPEND);
            }

            if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
                dev_err (&hub->intf->dev,
                         "over-current change on port %d\n",
                         i + 1);
                clear_port_feature(dev,
                                   i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
                hub_power_on(hub);
            }

            if (portchange & USB_PORT_STAT_C_RESET) {
                dev_dbg (&hub->intf->dev,
                         "reset change on port %d\n",
                         i + 1);
                clear_port_feature(dev,
                                   i + 1, USB_PORT_FEAT_C_RESET);
            }
        } /* end for i */

        /* deal with hub status changes */
        if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)
            dev_err (&hub->intf->dev, "get_hub_status failed\n");
        else {
            if (hubchange & HUB_CHANGE_LOCAL_POWER) {
                dev_dbg (&hub->intf->dev, "power change\n");
                clear_hub_feature(dev, C_HUB_LOCAL_POWER);
            }
            if (hubchange & HUB_CHANGE_OVERCURRENT) {
                dev_dbg (&hub->intf->dev, "overcurrent change\n");
                wait_ms(500);	/* Cool down */
                clear_hub_feature(dev, C_HUB_OVER_CURRENT);
                hub_power_on(hub);
            }
        }
        up(&hub->khubd_sem);
    } /* end while (1) */

    spin_unlock_irqrestore(&hub_event_lock, flags);
}
Beispiel #9
0
/* After USB port reset, treat device number 0 as an USB hub. Assign it with
 * a device number hub_addr. Then apply enable and reset on downstream port.
 */
 static int dbgp_hub_enable(struct ehci_dbg_port *ehci_debug, unsigned char hub_addr,
	unsigned char port)
{
	char status[8];
	int ret, loop;

	/* Assign a devicenumber for the hub. */
	ret = dbgp_control_msg(ehci_debug, 0,
		USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
		USB_REQ_SET_ADDRESS, hub_addr, 0, NULL, 0);
	if (ret < 0)
		goto err;

	/* Enter configured state on hub. */
	ret = dbgp_control_msg(ehci_debug, hub_addr,
		USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
		USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0);
	if (ret < 0)
		goto err;

	/* Set PORT_POWER, poll for PORT_CONNECTION. */
	ret = dbgp_control_msg(ehci_debug, hub_addr,
		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
		USB_REQ_SET_FEATURE, USB_HUB_PORT_POWER, port, NULL, 0);
	if (ret < 0)
		goto err;

	loop = 100;
	do {
		dbgp_mdelay(10);
		ret = dbgp_control_msg(ehci_debug, hub_addr,
			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER,
			USB_REQ_GET_STATUS, 0, port, status, 4);
		if (ret < 0)
			goto err;
		if (hub_port_status(status, USB_HUB_PORT_CONNECTION))
			break;
	} while (--loop);
	if (! loop)
		goto err;

	ret = dbgp_control_msg(ehci_debug, hub_addr,
		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
		USB_REQ_CLEAR_FEATURE, USB_HUB_C_PORT_CONNECTION, port, NULL, 0);
	if (ret < 0)
		goto err;


	/* Set PORT_RESET, poll for C_PORT_RESET. */
	ret = dbgp_control_msg(ehci_debug, hub_addr,
		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
		USB_REQ_SET_FEATURE, USB_HUB_PORT_RESET, port, NULL, 0);
	if (ret < 0)
		goto err;

	loop = 100;
	do {
		dbgp_mdelay(10);
		ret = dbgp_control_msg(ehci_debug, hub_addr,
			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER,
			USB_REQ_GET_STATUS, 0, port, status, 4);
		if (ret < 0)
			goto err;
		if (hub_port_status(status, USB_HUB_C_PORT_RESET))
			break;
	} while (--loop);
	if (! loop)
		goto err;

	ret = dbgp_control_msg(ehci_debug, hub_addr,
		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER,
		USB_REQ_CLEAR_FEATURE, USB_HUB_C_PORT_RESET, port, NULL, 0);
	if (ret < 0)
		goto err;

	if (hub_port_status(status, USB_HUB_PORT_ENABLED))
		return 0;
err:
	return -1;
}