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