/*-
* Copyright (c) 1999-2003 MAEKAWA Masahide <gehenna@daemon-systems.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: main.c,v 1.15 2003/01/11 14:46:36 maekawa Exp $
*/
#include <sys/ioctl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <dev/usb/usb.h>
#include "main.h"
int indexes = 0, langid = 0, verbose_level = 0, fd;
static void error(const char *, ...);
static void verbose(int, const char *, ...);
extern struct devinfo usbdev;
extern int level;
int
main(int argc, char *argv[])
{
usb_device_descriptor_t ddesc;
struct usb_config_desc cdesc;
struct usb_full_desc fdesc;
struct usb_string_desc sdesc;
const char *device_name = NULL;
uint8_t *buffer;
int n, i;
if (argc > 1)
device_name = argv[1];
#ifdef _PATH_DEV_UGEN
else
device_name = _PATH_DEV_UGEN;
#endif /* _PATH_DEV_UGEN */
if (device_name == NULL) {
error("not specified ugen device node");
exit(EXIT_FAILURE);
}
if ((fd = open(device_name, O_RDWR, 0)) < 0) {
error("%s", device_name);
exit(EXIT_FAILURE);
}
if (ioctl(fd, USB_GET_DEVICE_DESC, &ddesc) != 0) {
error("ioctl USB_GET_DEVICE_DESC");
close(fd);
exit(EXIT_FAILURE);
}
dump_device(&ddesc);
for (i = 0 ; i < ddesc.bNumConfigurations ; i++) {
cdesc.ucd_config_index = i;
if (ioctl(fd, USB_GET_CONFIG_DESC, &cdesc) != 0) {
error("ioctl USB_GET_CONFIG_DESC");
close(fd);
exit(EXIT_FAILURE);
}
fdesc.ufd_config_index = i;
fdesc.ufd_size = UGETW(cdesc.ucd_desc.wTotalLength);
if ((fdesc.ufd_data = malloc(fdesc.ufd_size)) == NULL) {
error("config %d", i);
close(fd);
exit(EXIT_FAILURE);
}
if (ioctl(fd, USB_GET_FULL_DESC, &fdesc) != 0) {
error("ioctl USB_GET_FULL_DESC");
free(fdesc.ufd_data);
close(fd);
exit(EXIT_FAILURE);
}
verbose(-1, "Configuration %d:", i);
dump_full(&fdesc);
free(fdesc.ufd_data);
}
if (indexes != 0) {
memset(&sdesc, 0, sizeof(sdesc));
if (ioctl(fd, USB_GET_STRING_DESC, &sdesc) != 0) {
error("ioctl USB_GET_STRING_DESC");
close(fd);
exit(EXIT_FAILURE);
}
dump_string(&sdesc.usd_desc, 0);
buffer = (uint8_t *)&sdesc.usd_desc.bString;
n = (sdesc.usd_desc.bLength - 2) / 2;
for (i = 0 ; i < n ; i++) {
langid = UGETW(&buffer[i*2]);
if (langid == 0x0409)
break;
}
if (langid == 0x0409) {
sdesc.usd_language_id = langid;
for (i = 1 ; i <= indexes ; i++) {
sdesc.usd_string_index = i;
if (ioctl(fd, USB_GET_STRING_DESC,
&sdesc) != 0) {
error("ioctl USB_GET_STRING_DESC");
close(fd);
exit(EXIT_FAILURE);
}
dump_string(&sdesc.usd_desc, i);
}
}
}
close(fd);
exit(EXIT_SUCCESS);
}
int
usb_get_descriptor(int addr, uint8_t vh, uint8_t vl, uint8_t idx, void *buffer,
size_t bufsize)
{
struct usb_ctl_request ctlreq;
ctlreq.ucr_addr = addr;
ctlreq.ucr_request.bmRequestType = UT_READ_INTERFACE;
ctlreq.ucr_request.bRequest = UR_GET_DESCRIPTOR;
USETW2(ctlreq.ucr_request.wValue, vh, vl);
USETW(ctlreq.ucr_request.wIndex, idx);
USETW(ctlreq.ucr_request.wLength, bufsize);
ctlreq.ucr_data = buffer;
ctlreq.ucr_flags = 0;
ctlreq.ucr_actlen = 0;
if (ioctl(fd, USB_DO_REQUEST, &ctlreq) != 0)
return (0);
if ((size_t)ctlreq.ucr_actlen != bufsize)
return (0);
return (1);
}
void
bprintf(uint8_t *buffer, size_t bufsize)
{
int i, bitlen;
bitlen = bufsize * 8;
for (i = 0 ; i < bitlen ; i++)
printf("%d", BIT(buffer[i / 8], 7 - (i % 8), 1));
}
void
iprintf(const char *fmt, ...)
{
va_list ap;
int i;
for (i = 0 ; i < level ; i++)
printf("\t");
va_start(ap, fmt);
vfprintf(stdout, fmt, ap);
va_end(ap);
}
static void
error(const char *fmt, ...)
{
va_list ap;
int sv_errno = errno;
fflush(stdout);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, ": %s\n", strerror(sv_errno));
}
static void
verbose(int val, const char *fmt, ...)
{
va_list ap;
if (verbose_level < val)
return;
va_start(ap, fmt);
vfprintf(stdout, fmt, ap);
va_end(ap);
fprintf(stdout, "\n");
}
syntax highlighted by Code2HTML, v. 0.9.1