linux/drivers/usb/misc/ehset.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/kernel.h>
   7#include <linux/errno.h>
   8#include <linux/module.h>
   9#include <linux/slab.h>
  10#include <linux/usb.h>
  11#include <linux/usb/ch11.h>
  12
  13#define TEST_SE0_NAK_PID                        0x0101
  14#define TEST_J_PID                              0x0102
  15#define TEST_K_PID                              0x0103
  16#define TEST_PACKET_PID                         0x0104
  17#define TEST_HS_HOST_PORT_SUSPEND_RESUME        0x0106
  18#define TEST_SINGLE_STEP_GET_DEV_DESC           0x0107
  19#define TEST_SINGLE_STEP_SET_FEATURE            0x0108
  20
  21static int ehset_probe(struct usb_interface *intf,
  22                       const struct usb_device_id *id)
  23{
  24        int ret = -EINVAL;
  25        struct usb_device *dev = interface_to_usbdev(intf);
  26        struct usb_device *hub_udev = dev->parent;
  27        struct usb_device_descriptor buf;
  28        u8 portnum = dev->portnum;
  29        u16 test_pid = le16_to_cpu(dev->descriptor.idProduct);
  30
  31        switch (test_pid) {
  32        case TEST_SE0_NAK_PID:
  33                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
  34                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
  35                                           (USB_TEST_SE0_NAK << 8) | portnum,
  36                                           NULL, 0, 1000, GFP_KERNEL);
  37                break;
  38        case TEST_J_PID:
  39                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
  40                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
  41                                           (USB_TEST_J << 8) | portnum, NULL, 0,
  42                                           1000, GFP_KERNEL);
  43                break;
  44        case TEST_K_PID:
  45                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
  46                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
  47                                           (USB_TEST_K << 8) | portnum, NULL, 0,
  48                                           1000, GFP_KERNEL);
  49                break;
  50        case TEST_PACKET_PID:
  51                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
  52                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
  53                                           (USB_TEST_PACKET << 8) | portnum,
  54                                           NULL, 0, 1000, GFP_KERNEL);
  55                break;
  56        case TEST_HS_HOST_PORT_SUSPEND_RESUME:
  57                /* Test: wait for 15secs -> suspend -> 15secs delay -> resume */
  58                msleep(15 * 1000);
  59                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
  60                                           USB_RT_PORT, USB_PORT_FEAT_SUSPEND,
  61                                           portnum, NULL, 0, 1000, GFP_KERNEL);
  62                if (ret < 0)
  63                        break;
  64
  65                msleep(15 * 1000);
  66                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_CLEAR_FEATURE,
  67                                           USB_RT_PORT, USB_PORT_FEAT_SUSPEND,
  68                                           portnum, NULL, 0, 1000, GFP_KERNEL);
  69                break;
  70        case TEST_SINGLE_STEP_GET_DEV_DESC:
  71                /* Test: wait for 15secs -> GetDescriptor request */
  72                msleep(15 * 1000);
  73
  74                ret = usb_control_msg_recv(dev, 0, USB_REQ_GET_DESCRIPTOR,
  75                                           USB_DIR_IN, USB_DT_DEVICE << 8, 0,
  76                                           &buf, USB_DT_DEVICE_SIZE,
  77                                           USB_CTRL_GET_TIMEOUT, GFP_KERNEL);
  78                break;
  79        case TEST_SINGLE_STEP_SET_FEATURE:
  80                /*
  81                 * GetDescriptor SETUP request -> 15secs delay -> IN & STATUS
  82                 *
  83                 * Note, this test is only supported on root hubs since the
  84                 * SetPortFeature handling can only be done inside the HCD's
  85                 * hub_control callback function.
  86                 */
  87                if (hub_udev != dev->bus->root_hub) {
  88                        dev_err(&intf->dev, "SINGLE_STEP_SET_FEATURE test only supported on root hub\n");
  89                        break;
  90                }
  91
  92                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
  93                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
  94                                           (6 << 8) | portnum, NULL, 0,
  95                                           60 * 1000, GFP_KERNEL);
  96
  97                break;
  98        default:
  99                dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n",
 100                        __func__, test_pid);
 101        }
 102
 103        return ret;
 104}
 105
 106static void ehset_disconnect(struct usb_interface *intf)
 107{
 108}
 109
 110static const struct usb_device_id ehset_id_table[] = {
 111        { USB_DEVICE(0x1a0a, TEST_SE0_NAK_PID) },
 112        { USB_DEVICE(0x1a0a, TEST_J_PID) },
 113        { USB_DEVICE(0x1a0a, TEST_K_PID) },
 114        { USB_DEVICE(0x1a0a, TEST_PACKET_PID) },
 115        { USB_DEVICE(0x1a0a, TEST_HS_HOST_PORT_SUSPEND_RESUME) },
 116        { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_GET_DEV_DESC) },
 117        { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_SET_FEATURE) },
 118        { }                     /* Terminating entry */
 119};
 120MODULE_DEVICE_TABLE(usb, ehset_id_table);
 121
 122static struct usb_driver ehset_driver = {
 123        .name =         "usb_ehset_test",
 124        .probe =        ehset_probe,
 125        .disconnect =   ehset_disconnect,
 126        .id_table =     ehset_id_table,
 127};
 128
 129module_usb_driver(ehset_driver);
 130
 131MODULE_DESCRIPTION("USB Driver for EHSET Test Fixture");
 132MODULE_LICENSE("GPL v2");
 133