0001
0002
0003
0004
0005
0006 #include <linux/kernel.h>
0007 #include <linux/errno.h>
0008 #include <linux/module.h>
0009 #include <linux/slab.h>
0010 #include <linux/usb.h>
0011 #include <linux/usb/ch11.h>
0012
0013 #define TEST_SE0_NAK_PID 0x0101
0014 #define TEST_J_PID 0x0102
0015 #define TEST_K_PID 0x0103
0016 #define TEST_PACKET_PID 0x0104
0017 #define TEST_HS_HOST_PORT_SUSPEND_RESUME 0x0106
0018 #define TEST_SINGLE_STEP_GET_DEV_DESC 0x0107
0019 #define TEST_SINGLE_STEP_SET_FEATURE 0x0108
0020
0021 extern const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
0022 const struct usb_device_id *id);
0023
0024
0025
0026
0027
0028 static const struct usb_device_id ehset_hub_list[] = {
0029 { USB_DEVICE(0x0424, 0x4502) },
0030 { USB_DEVICE(0x0424, 0x4913) },
0031 { USB_DEVICE(0x0451, 0x8027) },
0032 { }
0033 };
0034
0035 static int ehset_prepare_port_for_testing(struct usb_device *hub_udev, u16 portnum)
0036 {
0037 int ret = 0;
0038
0039
0040
0041
0042
0043
0044
0045
0046 if (usb_device_match_id(hub_udev, ehset_hub_list)) {
0047 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_CLEAR_FEATURE,
0048 USB_RT_PORT, USB_PORT_FEAT_ENABLE,
0049 portnum, NULL, 0, 1000, GFP_KERNEL);
0050
0051
0052
0053
0054 msleep(100);
0055 } else {
0056
0057
0058
0059
0060 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
0061 USB_RT_PORT, USB_PORT_FEAT_SUSPEND,
0062 portnum, NULL, 0, 1000, GFP_KERNEL);
0063 }
0064 return ret;
0065 }
0066
0067 static int ehset_probe(struct usb_interface *intf,
0068 const struct usb_device_id *id)
0069 {
0070 int ret = -EINVAL;
0071 struct usb_device *dev = interface_to_usbdev(intf);
0072 struct usb_device *hub_udev = dev->parent;
0073 struct usb_device_descriptor buf;
0074 u8 portnum = dev->portnum;
0075 u16 test_pid = le16_to_cpu(dev->descriptor.idProduct);
0076
0077 switch (test_pid) {
0078 case TEST_SE0_NAK_PID:
0079 ret = ehset_prepare_port_for_testing(hub_udev, portnum);
0080 if (!ret)
0081 break;
0082 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
0083 USB_RT_PORT, USB_PORT_FEAT_TEST,
0084 (USB_TEST_SE0_NAK << 8) | portnum,
0085 NULL, 0, 1000, GFP_KERNEL);
0086 break;
0087 case TEST_J_PID:
0088 ret = ehset_prepare_port_for_testing(hub_udev, portnum);
0089 if (!ret)
0090 break;
0091 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
0092 USB_RT_PORT, USB_PORT_FEAT_TEST,
0093 (USB_TEST_J << 8) | portnum, NULL, 0,
0094 1000, GFP_KERNEL);
0095 break;
0096 case TEST_K_PID:
0097 ret = ehset_prepare_port_for_testing(hub_udev, portnum);
0098 if (!ret)
0099 break;
0100 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
0101 USB_RT_PORT, USB_PORT_FEAT_TEST,
0102 (USB_TEST_K << 8) | portnum, NULL, 0,
0103 1000, GFP_KERNEL);
0104 break;
0105 case TEST_PACKET_PID:
0106 ret = ehset_prepare_port_for_testing(hub_udev, portnum);
0107 if (!ret)
0108 break;
0109 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
0110 USB_RT_PORT, USB_PORT_FEAT_TEST,
0111 (USB_TEST_PACKET << 8) | portnum,
0112 NULL, 0, 1000, GFP_KERNEL);
0113 break;
0114 case TEST_HS_HOST_PORT_SUSPEND_RESUME:
0115
0116 msleep(15 * 1000);
0117 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
0118 USB_RT_PORT, USB_PORT_FEAT_SUSPEND,
0119 portnum, NULL, 0, 1000, GFP_KERNEL);
0120 if (ret < 0)
0121 break;
0122
0123 msleep(15 * 1000);
0124 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_CLEAR_FEATURE,
0125 USB_RT_PORT, USB_PORT_FEAT_SUSPEND,
0126 portnum, NULL, 0, 1000, GFP_KERNEL);
0127 break;
0128 case TEST_SINGLE_STEP_GET_DEV_DESC:
0129
0130 msleep(15 * 1000);
0131
0132 ret = usb_control_msg_recv(dev, 0, USB_REQ_GET_DESCRIPTOR,
0133 USB_DIR_IN, USB_DT_DEVICE << 8, 0,
0134 &buf, USB_DT_DEVICE_SIZE,
0135 USB_CTRL_GET_TIMEOUT, GFP_KERNEL);
0136 break;
0137 case TEST_SINGLE_STEP_SET_FEATURE:
0138
0139
0140
0141
0142
0143
0144
0145 if (hub_udev != dev->bus->root_hub) {
0146 dev_err(&intf->dev, "SINGLE_STEP_SET_FEATURE test only supported on root hub\n");
0147 break;
0148 }
0149
0150 ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
0151 USB_RT_PORT, USB_PORT_FEAT_TEST,
0152 (6 << 8) | portnum, NULL, 0,
0153 60 * 1000, GFP_KERNEL);
0154
0155 break;
0156 default:
0157 dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n",
0158 __func__, test_pid);
0159 }
0160
0161 return ret;
0162 }
0163
0164 static void ehset_disconnect(struct usb_interface *intf)
0165 {
0166 }
0167
0168 static const struct usb_device_id ehset_id_table[] = {
0169 { USB_DEVICE(0x1a0a, TEST_SE0_NAK_PID) },
0170 { USB_DEVICE(0x1a0a, TEST_J_PID) },
0171 { USB_DEVICE(0x1a0a, TEST_K_PID) },
0172 { USB_DEVICE(0x1a0a, TEST_PACKET_PID) },
0173 { USB_DEVICE(0x1a0a, TEST_HS_HOST_PORT_SUSPEND_RESUME) },
0174 { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_GET_DEV_DESC) },
0175 { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_SET_FEATURE) },
0176 { }
0177 };
0178 MODULE_DEVICE_TABLE(usb, ehset_id_table);
0179
0180 static struct usb_driver ehset_driver = {
0181 .name = "usb_ehset_test",
0182 .probe = ehset_probe,
0183 .disconnect = ehset_disconnect,
0184 .id_table = ehset_id_table,
0185 };
0186
0187 module_usb_driver(ehset_driver);
0188
0189 MODULE_DESCRIPTION("USB Driver for EHSET Test Fixture");
0190 MODULE_LICENSE("GPL v2");