~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to bus/usb/usbhub.c

Tags: upstream-1.99~20101122
ImportĀ upstreamĀ versionĀ 1.99~20101122

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* usb.c - USB Hub Support.  */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2008  Free Software Foundation, Inc.
5
 
 *
6
 
 *  GRUB is free software: you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation, either version 3 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  GRUB is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <grub/dl.h>
21
 
#include <grub/mm.h>
22
 
#include <grub/usb.h>
23
 
#include <grub/misc.h>
24
 
 
25
 
/* USB Supports 127 devices, with device 0 as special case.  */
26
 
static struct grub_usb_device *grub_usb_devs[128];
27
 
 
28
 
/* Add a device that currently has device number 0 and resides on
29
 
   CONTROLLER, the Hub reported that the device speed is SPEED.  */
30
 
static grub_usb_device_t
31
 
grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed)
32
 
{
33
 
  grub_usb_device_t dev;
34
 
  int i;
35
 
 
36
 
  dev = grub_zalloc (sizeof (struct grub_usb_device));
37
 
  if (! dev)
38
 
    return NULL;
39
 
 
40
 
  dev->controller = *controller;
41
 
  dev->speed = speed;
42
 
 
43
 
  grub_usb_device_initialize (dev);
44
 
 
45
 
  /* Assign a new address to the device.  */
46
 
  for (i = 1; i < 128; i++)
47
 
    {
48
 
      if (! grub_usb_devs[i])
49
 
        break;
50
 
    }
51
 
  if (i == 128)
52
 
    {
53
 
      grub_error (GRUB_ERR_IO, "can't assign address to USB device");
54
 
      return NULL;
55
 
    }
56
 
 
57
 
  grub_usb_control_msg (dev,
58
 
                        (GRUB_USB_REQTYPE_OUT
59
 
                         | GRUB_USB_REQTYPE_STANDARD
60
 
                         | GRUB_USB_REQTYPE_TARGET_DEV),
61
 
                        GRUB_USB_REQ_SET_ADDRESS,
62
 
                        i, 0, 0, NULL);
63
 
 
64
 
  dev->addr = i;
65
 
  dev->initialized = 1;
66
 
  grub_usb_devs[i] = dev;
67
 
 
68
 
  return dev;
69
 
}
70
 
 
71
 
 
72
 
static grub_err_t
73
 
grub_usb_add_hub (grub_usb_device_t dev)
74
 
{
75
 
  struct grub_usb_usb_hubdesc hubdesc;
76
 
  grub_err_t err;
77
 
  int i;
78
 
 
79
 
  grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
80
 
                              | GRUB_USB_REQTYPE_CLASS
81
 
                              | GRUB_USB_REQTYPE_TARGET_DEV),
82
 
                        GRUB_USB_REQ_GET_DESCRIPTOR,
83
 
                        (GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
84
 
                        0, sizeof (hubdesc), (char *) &hubdesc);
85
 
 
86
 
  /* Iterate over the Hub ports.  */
87
 
  for (i = 1; i <= hubdesc.portcnt; i++)
88
 
    {
89
 
      grub_uint32_t status;
90
 
 
91
 
      /* Get the port status.  */
92
 
      err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
93
 
                                        | GRUB_USB_REQTYPE_CLASS
94
 
                                        | GRUB_USB_REQTYPE_TARGET_OTHER),
95
 
                                  GRUB_USB_REQ_HUB_GET_PORT_STATUS,
96
 
                                  0, i, sizeof (status), (char *) &status);
97
 
 
98
 
      /* Just ignore the device if the Hub does not report the
99
 
         status.  */
100
 
      if (err)
101
 
        continue;
102
 
 
103
 
      /* If connected, reset and enable the port.  */
104
 
      if (status & GRUB_USB_HUB_STATUS_CONNECTED)
105
 
        {
106
 
          grub_usb_speed_t speed;
107
 
 
108
 
          /* Determine the device speed.  */
109
 
          if (status & GRUB_USB_HUB_STATUS_LOWSPEED)
110
 
            speed = GRUB_USB_SPEED_LOW;
111
 
          else
112
 
            {
113
 
              if (status & GRUB_USB_HUB_STATUS_HIGHSPEED)
114
 
                speed = GRUB_USB_SPEED_HIGH;
115
 
              else
116
 
                speed = GRUB_USB_SPEED_FULL;
117
 
            }
118
 
 
119
 
          /* A device is actually connected to this port, not enable
120
 
             the port.  XXX: Why 0x03?  According to some docs it
121
 
             should be 0x0.  Check the specification!  */
122
 
          err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
123
 
                                            | GRUB_USB_REQTYPE_CLASS
124
 
                                            | GRUB_USB_REQTYPE_TARGET_OTHER),
125
 
                                      0x3, 0x4, i, 0, 0);
126
 
 
127
 
          /* If the Hub does not cooperate for this port, just skip
128
 
             the port.  */
129
 
          if (err)
130
 
            continue;
131
 
 
132
 
          /* Add the device and assign a device address to it.  */
133
 
          grub_usb_hub_add_dev (&dev->controller, speed);
134
 
        }
135
 
    }
136
 
 
137
 
  return GRUB_ERR_NONE;
138
 
}
139
 
 
140
 
grub_usb_err_t
141
 
grub_usb_root_hub (grub_usb_controller_t controller)
142
 
{
143
 
  grub_err_t err;
144
 
  int ports;
145
 
  int i;
146
 
 
147
 
  /* Query the number of ports the root Hub has.  */
148
 
  ports = controller->dev->hubports (controller);
149
 
 
150
 
  for (i = 0; i < ports; i++)
151
 
    {
152
 
      grub_usb_speed_t speed = controller->dev->detect_dev (controller, i);
153
 
 
154
 
      if (speed != GRUB_USB_SPEED_NONE)
155
 
        {
156
 
          grub_usb_device_t dev;
157
 
 
158
 
          /* Enable the port.  */
159
 
          err = controller->dev->portstatus (controller, i, 1);
160
 
          if (err)
161
 
            continue;
162
 
 
163
 
          /* Enable the port and create a device.  */
164
 
          dev = grub_usb_hub_add_dev (controller, speed);
165
 
          if (! dev)
166
 
            continue;
167
 
 
168
 
          /* If the device is a Hub, scan it for more devices.  */
169
 
          if (dev->descdev.class == 0x09)
170
 
            grub_usb_add_hub (dev);
171
 
        }
172
 
    }
173
 
 
174
 
  return GRUB_USB_ERR_NONE;
175
 
}
176
 
 
177
 
int
178
 
grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
179
 
{
180
 
  int i;
181
 
 
182
 
  for (i = 0; i < 128; i++)
183
 
    {
184
 
      if (grub_usb_devs[i])
185
 
        {
186
 
          if (hook (grub_usb_devs[i]))
187
 
              return 1;
188
 
        }
189
 
    }
190
 
 
191
 
  return 0;
192
 
}