Thanks for your replies.

David Brownell wrote:
> I'm unclear on why that would be better than for example a usermode
> program to do that using existing usbfs facilities to say to the hub
> driver "please turn that port off".

I just didn't know about USB protocol stack and its feature.

Following your suggestion, what I implemented is here.
I attach user space program.

Your comments are welcome.  BTW, this is quite useful feature for us.


Signed-off-by: NIIBE Yutaka <[EMAIL PROTECTED]>

--- linux-source-2.6.14/include/linux/usbdevice_fs.h~   2005-10-28
09:02:08.000000000 +0900
+++ linux-source-2.6.14/include/linux/usbdevice_fs.h    2006-01-11
20:15:34.000000000 +0900
@@ -123,6 +123,12 @@ struct usbdevfs_hub_portinfo {
        char port [127];        /* e.g. port 3 connects to device 27 */
 };

+struct usbdevfs_hub_portctrl {
+       char cmd;               /* LED or POWER */
+       char port;
+       char value;
+};
+
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
 struct usbdevfs_urb32 {
@@ -165,4 +171,5 @@ struct usbdevfs_urb32 {
 #define USBDEVFS_CLEAR_HALT        _IOR('U', 21, unsigned int)
 #define USBDEVFS_DISCONNECT        _IO('U', 22)
 #define USBDEVFS_CONNECT           _IO('U', 23)
+#define USBDEVFS_HUB_PORTCTRL      _IOW('U', 24, struct
usbdevfs_hub_portctrl)
 #endif /* _LINUX_USBDEVICE_FS_H */
--- linux-source-2.6.14/drivers/usb/core/hub.c~ 2005-10-28
09:02:08.000000000 +0900
+++ linux-source-2.6.14/drivers/usb/core/hub.c  2006-01-11
20:39:52.000000000 +0900
@@ -907,7 +907,33 @@ hub_ioctl(struct usb_interface *intf, un

                return info->nports + 1;
                }
+       case USBDEVFS_HUB_PORTCTRL: {
+               struct usb_hub *hub = usb_get_intfdata (intf);
+               struct usbdevfs_hub_portctrl *ctrl = user_data;

+               if (hdev->devnum <= 0)
+                       return -ENODEV;
+
+               if (ctrl->port < 1 || ctrl->port > hdev->maxchild)
+                       return -EINVAL;
+
+               if (hdev->children[ctrl->port - 1] != NULL)
+                       /* Something connected */
+                       return -EBUSY;
+
+               if (ctrl->cmd == 0)
+                       if (ctrl->value < HUB_LED_AUTO
+                           || ctrl->value > HUB_LED_OFF)
+                               return -EINVAL;
+                       else
+                               set_port_led (hub, ctrl->port, ctrl->value);
+               else
+                       if (ctrl->value)
+                               set_port_feature(hdev, ctrl->port, 
USB_PORT_FEAT_POWER);
+                       else
+                               clear_port_feature(hdev, ctrl->port, 
USB_PORT_FEAT_POWER);
+               return 0;
+       }
        default:
                return -ENOSYS;
        }
/*
 * Copyright (C) 2006 Free Software Initiative of Japan
 *
 * Author: NIIBE Yutaka  <gniibe at fsij.org>
 *
 * This file can be distributed under the terms and conditions of the
 * GNU General Public License version 2 (or later).
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>

#define USBDEVFS_IOCTL             _IOWR('U', 18, struct usbdevfs_ioctl)
#define USBDEVFS_HUB_PORTCTRL      _IOW('U', 24, struct usbdevfs_hub_portctrl)

struct usbdevfs_ioctl {
  int ifno;
  int ioctl_code;
  void *data;
};

struct usbdevfs_hub_portctrl {
  char cmd;
  char port;
  char value;
};

static void
usage (const char *progname)
{
  fprintf (stderr, "Usage: %s PATH [-P PORT] [{-l [VALUE]}|{-p [VALUE]}]\n", progname);
}

#define COMMAND_SET_LED   0
#define COMMAND_SET_POWER 1
#define HUB_LED_GREEN 2

/*
 * HUB-CTRL  -  program to control port power/led of USB hub
 *
 *   $ hub-ctrl /dev/bus/usb/001/002 -P 1 -p            # Power off at port 1
 *   $ hub-ctrl /dev/bus/usb/001/002 -P 1 -p 1          # Power on at port 1
 *   $ hub-ctrl /dev/bus/usb/001/002 -P 2 -l            # LED on at port 1
 *
 * Requirement: USB hub which implements port power control / indicator control
 *              Elecom's U2H-G4S works fine
 *
 */
int
main (int argc, const char *argv[])
{
  int fd;
  struct usbdevfs_ioctl ioctl_data;
  struct usbdevfs_hub_portctrl portctrl_data;
  int i;
  const char *path;
  int port = 1;
  int cmd = COMMAND_SET_POWER;
  int value = 0;

  if (argc < 2)
    {
      usage (argv[0]);
      exit (1);
    }

  path = argv[1];

  for (i = 2; i < argc; i++)
    if (argv[i][0] == '-')
      switch (argv[i][1])
	{
	case 'P':
	  if (++i >= argc)
	    {
	      usage (argv[0]);
	      exit (1);
	    }
	  port = atoi (argv[i]);
	  break;

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

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

	default:
	  usage (argv[0]);
	  exit (1);
	}


  if ((fd = open (path, O_RDWR)) < 0)
    {
      perror ("open");
      exit (1);
    }

  ioctl_data.ifno = 0;
  ioctl_data.ioctl_code = USBDEVFS_HUB_PORTCTRL;
  ioctl_data.data = &portctrl_data;

  portctrl_data.cmd = cmd;
  portctrl_data.port = port;
  portctrl_data.value = value;

  if (ioctl (fd, USBDEVFS_IOCTL, &ioctl_data) < 0)
    {
      perror ("ioctl");
      close (fd);
      exit (1);
    }

  close (fd);
  exit (0);
}

Reply via email to