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