usbtest.c 5.39 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/* usbtest.c - test module for USB */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2008  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <grub/types.h>
#include <grub/misc.h>
22
#include <grub/charset.h>
23 24 25 26
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/usb.h>
27
#include <grub/command.h>
28
#include <grub/i18n.h>
29

30 31
GRUB_MOD_LICENSE ("GPLv3+");

32 33
static const char *usb_classes[] =
  {
34
    "Unknown",
35 36 37
    "Audio",
    "Communication Interface",
    "HID",
38
    "Unknown",
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
    "Physical",
    "Image",
    "Printer",
    "Mass Storage",
    "Hub",
    "Data Interface",
    "Smart Card",
    "Content Security",
    "Video"
  };

static const char *usb_endp_type[] =
  {
    "Control",
    "Isochronous",
    "Bulk",
    "Interrupt"
  };

58
static const char *usb_devspeed[] =
59 60 61 62 63 64 65
  {
    "",
    "Low",
    "Full",
    "High"
  };

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
static grub_usb_err_t
grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid,
		     char **string)
{
  struct grub_usb_desc_str descstr;
  struct grub_usb_desc_str *descstrp;
  grub_usb_err_t err;

  /* Only get the length.  */
  err = grub_usb_control_msg (dev, 1 << 7,
			      0x06, (3 << 8) | index,
			      langid, 1, (char *) &descstr);
  if (err)
    return err;

  descstrp = grub_malloc (descstr.length);
  if (! descstrp)
    return GRUB_USB_ERR_INTERNAL;
  err = grub_usb_control_msg (dev, 1 << 7,
			      0x06, (3 << 8) | index,
			      langid, descstr.length, (char *) descstrp);

88 89 90 91 92 93 94 95 96 97
  if (descstrp->length == 0)
    {
      grub_free (descstrp);
      *string = grub_strdup ("");
      if (! *string)
	return GRUB_USB_ERR_INTERNAL;
      return GRUB_USB_ERR_NONE;
    }

  *string = grub_malloc (descstr.length * 2 + 1);
98 99 100 101 102 103
  if (! *string)
    {
      grub_free (descstrp);
      return GRUB_USB_ERR_INTERNAL;
    }

104 105
  *grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str,
		       descstrp->length / 2 - 1) = 0;
106 107 108 109 110
  grub_free (descstrp);

  return GRUB_USB_ERR_NONE;
}

111 112 113
static void
usb_print_str (const char *description, grub_usb_device_t dev, int idx)
{
114
  char *name = NULL;
115
  grub_usb_err_t err;
116 117 118 119 120
  /* XXX: LANGID  */

  if (! idx)
    return;

121 122 123 124 125 126 127 128
  err = grub_usb_get_string (dev, idx, 0x0409, &name);
  if (err)
    grub_printf ("Error %d retrieving %s\n", err, description);
  else
    {
      grub_printf ("%s: `%s'\n", description, name);
      grub_free (name);
    }
129 130 131
}

static int
132
usb_iterate (grub_usb_device_t dev, void *data __attribute__ ((unused)))
133 134 135 136 137 138 139 140 141
{
  struct grub_usb_desc_device *descdev;
  int i;

  descdev = &dev->descdev;

  usb_print_str ("Product", dev, descdev->strprod);
  usb_print_str ("Vendor", dev, descdev->strvendor);
  usb_print_str ("Serial", dev, descdev->strserial);
142

143 144 145 146
  grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
	       descdev->class, descdev->class < ARRAY_SIZE (usb_classes)
	       ? usb_classes[descdev->class] : "Unknown",
	       descdev->subclass, descdev->protocol);
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
  grub_printf ("USB version %d.%d, VendorID: 0x%02x, ProductID: 0x%02x, #conf: %d\n",
	       descdev->usbrel >> 8, (descdev->usbrel >> 4) & 0x0F,
	       descdev->vendorid, descdev->prodid, descdev->configcnt);

  grub_printf ("%s speed device\n", usb_devspeed[dev->speed]);

  for (i = 0; i < descdev->configcnt; i++)
    {
      struct grub_usb_desc_config *config;

      config = dev->config[i].descconf;
      usb_print_str ("Configuration:", dev, config->strconfig);
    }

  for (i = 0; i < dev->config[0].descconf->numif; i++)
    {
      int j;
      struct grub_usb_desc_if *interf;
      interf = dev->config[0].interf[i].descif;

      grub_printf ("Interface #%d: #Endpoints: %d   ",
		   i, interf->endpointcnt);
169 170 171 172
      grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
		   interf->class, interf->class < ARRAY_SIZE (usb_classes)
		   ? usb_classes[interf->class] : "Unknown",
		   interf->subclass, interf->protocol);
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

      usb_print_str ("Interface", dev, interf->strif);

      for (j = 0; j < interf->endpointcnt; j++)
	{
	  struct grub_usb_desc_endp *endp;
	  endp = &dev->config[0].interf[i].descendp[j];

	  grub_printf ("Endpoint #%d: %s, max packed size: %d, transfer type: %s, latency: %d\n",
		       endp->endp_addr & 15,
		       (endp->endp_addr & 128) ? "IN" : "OUT",
		       endp->maxpacket, usb_endp_type[endp->attrib & 3],
		       endp->interval);
	}
    }

  grub_printf("\n");

  return 0;
}

static grub_err_t
195
grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)),
196 197 198
		  int argc __attribute__ ((unused)),
		  char **args __attribute__ ((unused)))
{
199
  grub_usb_poll_devices (1);
200

201
  grub_printf ("USB devices:\n\n");
202
  grub_usb_iterate (usb_iterate, NULL);
203 204 205 206

  return 0;
}

207 208
static grub_command_t cmd;

209 210
GRUB_MOD_INIT(usbtest)
{
211
  cmd = grub_register_command ("usb", grub_cmd_usbtest,
212
			       0, N_("Test USB support."));
213 214 215 216
}

GRUB_MOD_FINI(usbtest)
{
217
  grub_unregister_command (cmd);
218
}