usbtree.c (usbview-2.2) | : | usbtree.c (usbview-3.0) | ||
---|---|---|---|---|
// SPDX-License-Identifier: GPL-2.0-only | // SPDX-License-Identifier: GPL-2.0-only | |||
/* | /* | |||
* usbtree.c for USBView - a USB device viewer | * usbtree.c for USBView - a USB device viewer | |||
* Copyright (c) 1999, 2000, 2021 by Greg Kroah-Hartman, <greg@kroah.com> | * Copyright (c) 1999, 2000, 2021-2022 by Greg Kroah-Hartman, <greg@kroah.com> | |||
*/ | */ | |||
#ifdef HAVE_CONFIG_H | #ifdef HAVE_CONFIG_H | |||
#include <config.h> | #include <config.h> | |||
#endif | #endif | |||
#include <stdio.h> | #include <stdio.h> | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#include <string.h> | #include <string.h> | |||
#include <ctype.h> | #include <ctype.h> | |||
#include <sys/stat.h> | #include <sys/stat.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#include <errno.h> | #include <errno.h> | |||
#include <gtk/gtk.h> | #include <gtk/gtk.h> | |||
#include "usbtree.h" | #include "usbtree.h" | |||
#include "usbparse.h" | #include "sysfs.h" | |||
#define MAX_LINE_SIZE 1000 | #define MAX_LINE_SIZE 1000 | |||
static void Init (void) | static void Init (void) | |||
{ | { | |||
GtkTextIter begin; | GtkTextIter begin; | |||
GtkTextIter end; | GtkTextIter end; | |||
/* blow away the tree if there is one */ | /* blow away the tree if there is one */ | |||
if (rootDevice != NULL) { | if (rootDevice != NULL) { | |||
skipping to change at line 44 | skipping to change at line 44 | |||
/* clean out the text box */ | /* clean out the text box */ | |||
gtk_text_buffer_get_start_iter(textDescriptionBuffer,&begin); | gtk_text_buffer_get_start_iter(textDescriptionBuffer,&begin); | |||
gtk_text_buffer_get_end_iter(textDescriptionBuffer,&end); | gtk_text_buffer_get_end_iter(textDescriptionBuffer,&end); | |||
gtk_text_buffer_delete (textDescriptionBuffer, &begin, &end); | gtk_text_buffer_delete (textDescriptionBuffer, &begin, &end); | |||
return; | return; | |||
} | } | |||
static void PopulateListBox (int deviceId) | static void PopulateListBox (int deviceId) | |||
{ | { | |||
Device *device; | struct Device *device; | |||
char *string; | char *string; | |||
char *tempString; | char *tempString; | |||
int configNum; | int configNum; | |||
int interfaceNum; | int interfaceNum; | |||
int endpointNum; | int endpointNum; | |||
int deviceNumber = (deviceId >> 8); | int deviceNumber = (deviceId >> 8); | |||
int busNumber = (deviceId & 0x00ff); | int busNumber = (deviceId & 0x00ff); | |||
GtkTextIter begin; | GtkTextIter begin; | |||
GtkTextIter end; | GtkTextIter end; | |||
skipping to change at line 146 | skipping to change at line 146 | |||
/* add the vendor id, product id, and revision number (if it is there) */ | /* add the vendor id, product id, and revision number (if it is there) */ | |||
if (device->vendorId) { | if (device->vendorId) { | |||
sprintf (string, "\nVendor Id: %.4x\nProduct Id: %.4x\nRevision N umber: %s", | sprintf (string, "\nVendor Id: %.4x\nProduct Id: %.4x\nRevision N umber: %s", | |||
device->vendorId, device->productId, device->revisionNum ber); | device->vendorId, device->productId, device->revisionNum ber); | |||
gtk_text_buffer_insert_at_cursor(textDescriptionBuffer, string,st rlen(string)); | gtk_text_buffer_insert_at_cursor(textDescriptionBuffer, string,st rlen(string)); | |||
} | } | |||
/* display all the info for the configs */ | /* display all the info for the configs */ | |||
for (configNum = 0; configNum < MAX_CONFIGS; ++configNum) { | for (configNum = 0; configNum < MAX_CONFIGS; ++configNum) { | |||
if (device->config[configNum]) { | if (device->config[configNum]) { | |||
DeviceConfig *config = device->config[configNum]; | struct DeviceConfig *config = device->config[configNum]; | |||
/* show this config */ | /* show this config */ | |||
sprintf (string, "\n\nConfig Number: %i\n\tNumber of Inte rfaces: %i\n\t" | sprintf (string, "\n\nConfig Number: %i\n\tNumber of Inte rfaces: %i\n\t" | |||
"Attributes: %.2x\n\tMaxPower Needed: %s", | "Attributes: %.2x\n\tMaxPower Needed: %s", | |||
config->configNumber, config->numInterfaces, | config->configNumber, config->numInterfaces, | |||
config->attributes, config->maxPower); | config->attributes, config->maxPower); | |||
gtk_text_buffer_insert_at_cursor(textDescriptionBuffer, s tring,strlen(string)); | gtk_text_buffer_insert_at_cursor(textDescriptionBuffer, s tring,strlen(string)); | |||
/* show all of the interfaces for this config */ | /* show all of the interfaces for this config */ | |||
for (interfaceNum = 0; interfaceNum < MAX_INTERFACES; ++i nterfaceNum) { | for (interfaceNum = 0; interfaceNum < MAX_INTERFACES; ++i nterfaceNum) { | |||
if (config->interface[interfaceNum]) { | if (config->interface[interfaceNum]) { | |||
DeviceInterface *interface = config->inte rface[interfaceNum]; | struct DeviceInterface *interface = confi g->interface[interfaceNum]; | |||
sprintf (string, "\n\n\tInterface Number: %i", interface->interfaceNumber); | sprintf (string, "\n\n\tInterface Number: %i", interface->interfaceNumber); | |||
gtk_text_buffer_insert_at_cursor(textDesc riptionBuffer, string, strlen(string)); | gtk_text_buffer_insert_at_cursor(textDesc riptionBuffer, string, strlen(string)); | |||
if (interface->name != NULL) { | if (interface->name != NULL) { | |||
sprintf (string, "\n\t\tName: %s" , interface->name); | sprintf (string, "\n\t\tName: %s" , interface->name); | |||
gtk_text_buffer_insert_at_cursor( textDescriptionBuffer, string, strlen(string)); | gtk_text_buffer_insert_at_cursor( textDescriptionBuffer, string, strlen(string)); | |||
} | } | |||
sprintf (string, "\n\t\tAlternate Number: %i\n\t\tClass: %s\n\t\t" | sprintf (string, "\n\t\tAlternate Number: %i\n\t\tClass: %s\n\t\t" | |||
"Sub Class: %.2x\n\t\tProtocol: %.2x\n\t\tNumber of Endpoints: %i", | "Sub Class: %.2x\n\t\tProtocol: %.2x\n\t\tNumber of Endpoints: %i", | |||
interface->alternateNumber, inte rface->class, | interface->alternateNumber, inte rface->class, | |||
interface->subClass, interface-> protocol, interface->numEndpoints); | interface->subClass, interface-> protocol, interface->numEndpoints); | |||
gtk_text_buffer_insert_at_cursor(textDesc riptionBuffer, string, strlen(string)); | gtk_text_buffer_insert_at_cursor(textDesc riptionBuffer, string, strlen(string)); | |||
/* show all of the endpoints for this int erface */ | /* show all of the endpoints for this int erface */ | |||
for (endpointNum = 0; endpointNum < MAX_E NDPOINTS; ++endpointNum) { | for (endpointNum = 0; endpointNum < MAX_E NDPOINTS; ++endpointNum) { | |||
if (interface->endpoint[endpointN um]) { | if (interface->endpoint[endpointN um]) { | |||
DeviceEndpoint *endpoint = interface->endpoint[endpointNum]; | struct DeviceEndpoint *en dpoint = interface->endpoint[endpointNum]; | |||
sprintf (string, "\n\n\t\ t\tEndpoint Address: %.2x\n\t\t\t" | sprintf (string, "\n\n\t\ t\tEndpoint Address: %.2x\n\t\t\t" | |||
"Direction: %s\n \t\t\tAttribute: %i\n\t\t\t" | "Direction: %s\n \t\t\tAttribute: %i\n\t\t\t" | |||
"Type: %s\n\t\t\ tMax Packet Size: %i\n\t\t\tInterval: %s", | "Type: %s\n\t\t\ tMax Packet Size: %i\n\t\t\tInterval: %s", | |||
endpoint->addres s, | endpoint->addres s, | |||
endpoint->in ? " in" : "out", endpoint->attribute, | endpoint->in ? " in" : "out", endpoint->attribute, | |||
endpoint->type, endpoint->maxPacketSize, endpoint->interval); | endpoint->type, endpoint->maxPacketSize, endpoint->interval); | |||
gtk_text_buffer_insert_at _cursor(textDescriptionBuffer, string,strlen(string)); | gtk_text_buffer_insert_at _cursor(textDescriptionBuffer, string,strlen(string)); | |||
} | } | |||
} | } | |||
skipping to change at line 216 | skipping to change at line 216 | |||
gint deviceAddr; | gint deviceAddr; | |||
if (gtk_tree_selection_get_selected (selection, &model, &iter)) { | if (gtk_tree_selection_get_selected (selection, &model, &iter)) { | |||
gtk_tree_model_get (model, &iter, | gtk_tree_model_get (model, &iter, | |||
DEVICE_ADDR_COLUMN, &deviceAddr, | DEVICE_ADDR_COLUMN, &deviceAddr, | |||
-1); | -1); | |||
PopulateListBox (deviceAddr); | PopulateListBox (deviceAddr); | |||
} | } | |||
} | } | |||
static void DisplayDevice (Device *parent, Device *device) | static void DisplayDevice (struct Device *parent, struct Device *device) | |||
{ | { | |||
int i; | int i; | |||
int configNum; | int configNum; | |||
int interfaceNum; | int interfaceNum; | |||
gboolean driverAttached = TRUE; | gboolean driverAttached = TRUE; | |||
gint deviceAddr; | gint deviceAddr; | |||
const gchar *color = "black"; | const gchar *color = "black"; | |||
if (device == NULL) | if (device == NULL) | |||
return; | return; | |||
/* build this node */ | /* build this node */ | |||
deviceAddr = (device->deviceNumber << 8) | device->busNumber; | deviceAddr = (device->deviceNumber << 8) | device->busNumber; | |||
gtk_tree_store_append (treeStore, &device->leaf, | gtk_tree_store_append (treeStore, &device->leaf, | |||
(device->level != 0) ? &parent->leaf : NULL); | (device->level != 0) ? &parent->leaf : NULL); | |||
/* determine if this device has drivers attached to all interfaces */ | /* determine if this device has drivers attached to all interfaces */ | |||
for (configNum = 0; configNum < MAX_CONFIGS; ++configNum) { | for (configNum = 0; configNum < MAX_CONFIGS; ++configNum) { | |||
if (device->config[configNum]) { | if (device->config[configNum]) { | |||
DeviceConfig *config = device->config[configNum]; | struct DeviceConfig *config = device->config[configNum]; | |||
for (interfaceNum = 0; interfaceNum < MAX_INTERFACES; ++i nterfaceNum) { | for (interfaceNum = 0; interfaceNum < MAX_INTERFACES; ++i nterfaceNum) { | |||
if (config->interface[interfaceNum]) { | if (config->interface[interfaceNum]) { | |||
DeviceInterface *interface = config->inte rface[interfaceNum]; | struct DeviceInterface *interface = confi g->interface[interfaceNum]; | |||
if (interface->driverAttached == FALSE) { | if (interface->driverAttached == FALSE) { | |||
driverAttached = FALSE; | driverAttached = FALSE; | |||
break; | break; | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
/* change the color of this leaf if there are no drivers attached to it * / | /* change the color of this leaf if there are no drivers attached to it * / | |||
skipping to change at line 267 | skipping to change at line 267 | |||
-1); | -1); | |||
/* create all of the children's leafs */ | /* create all of the children's leafs */ | |||
for (i = 0; i < MAX_CHILDREN; ++i) { | for (i = 0; i < MAX_CHILDREN; ++i) { | |||
DisplayDevice (device, device->child[i]); | DisplayDevice (device, device->child[i]); | |||
} | } | |||
return; | return; | |||
} | } | |||
#define FILENAME_SIZE 1000; | ||||
gchar devicesFile[1000]; | ||||
static gchar previousDevicesFile[1000]; | ||||
static time_t previousChange; | ||||
const char *verifyMessage = " Verify that you have USB compiled into your ke | ||||
rnel, \n" | ||||
" have the USB core modules loaded, and have the | ||||
\n" | ||||
" usbdevfs filesystem mounted. "; | ||||
static void FileError (void) | ||||
{ | ||||
GtkWidget *dialog; | ||||
dialog = gtk_message_dialog_new ( | ||||
GTK_WINDOW (windowMain), | ||||
GTK_DIALOG_DESTROY_WITH_PARENT, | ||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, | ||||
"Can not open the file %s\n\n%s", | ||||
devicesFile, verifyMessage); | ||||
gtk_dialog_run (GTK_DIALOG (dialog)); | ||||
gtk_widget_destroy (dialog); | ||||
} | ||||
static int FileHasChanged (void) | ||||
{ | ||||
struct stat file_info; | ||||
int result; | ||||
if (strcmp (previousDevicesFile, devicesFile) == 0) { | ||||
/* we've looked at this filename before, so check the file time o | ||||
f the file */ | ||||
result = stat (devicesFile, &file_info); | ||||
if (result) { | ||||
/* something wrong in looking for this file */ | ||||
return 0; | ||||
} | ||||
if (file_info.st_ctime == previousChange) { | ||||
/* no change */ | ||||
return 0; | ||||
} else { | ||||
/* something changed */ | ||||
previousChange = file_info.st_ctime; | ||||
return 1; | ||||
} | ||||
} else { | ||||
/* filenames are different, so save the name for the next time */ | ||||
strcpy (previousDevicesFile, devicesFile); | ||||
return 1; | ||||
} | ||||
} | ||||
void LoadUSBTree (int refresh) | void LoadUSBTree (int refresh) | |||
{ | { | |||
static gboolean signal_connected = FALSE; | static gboolean signal_connected = FALSE; | |||
FILE *usbFile; | ||||
char *dataLine; | ||||
int i; | int i; | |||
/* if refresh is selected, then always do a refresh, otherwise look at th | ||||
e file first */ | ||||
if (!refresh) { | ||||
if (!FileHasChanged()) { | ||||
return; | ||||
} | ||||
} | ||||
usbFile = fopen (devicesFile, "r"); | ||||
if (usbFile == NULL) { | ||||
FileError(); | ||||
return; | ||||
} | ||||
Init(); | Init(); | |||
usb_initialize_list (); | usb_initialize_list (); | |||
dataLine = (char *)g_malloc (MAX_LINE_SIZE); | sysfs_parse(); | |||
/* read and parse lines from the file one by one */ | ||||
while (!feof (usbFile) | ||||
&& fgets (dataLine, MAX_LINE_SIZE-1, usbFile) != NULL | ||||
&& dataLine[strlen(dataLine)-1] == '\n') { | ||||
usb_parse_line (dataLine); | ||||
} | ||||
fclose (usbFile); | ||||
g_free (dataLine); | ||||
usb_name_devices (); | usb_name_devices (); | |||
/* build our tree */ | /* build our tree */ | |||
for (i = 0; i < rootDevice->maxChildren; ++i) { | for (i = 0; i < rootDevice->maxChildren; ++i) { | |||
DisplayDevice (rootDevice, rootDevice->child[i]); | DisplayDevice (rootDevice, rootDevice->child[i]); | |||
} | } | |||
gtk_widget_show (treeUSB); | gtk_widget_show (treeUSB); | |||
gtk_tree_view_expand_all (GTK_TREE_VIEW (treeUSB)); | gtk_tree_view_expand_all (GTK_TREE_VIEW (treeUSB)); | |||
skipping to change at line 377 | skipping to change at line 300 | |||
GtkTreeSelection *select; | GtkTreeSelection *select; | |||
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeUSB)); | select = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeUSB)); | |||
g_signal_connect (G_OBJECT (select), "changed", | g_signal_connect (G_OBJECT (select), "changed", | |||
G_CALLBACK (SelectItem), NULL); | G_CALLBACK (SelectItem), NULL); | |||
signal_connected = TRUE; | signal_connected = TRUE; | |||
} | } | |||
return; | return; | |||
} | } | |||
void initialize_stuff (void) | void initialize_stuff(void) | |||
{ | { | |||
strcpy (devicesFile, "/sys/kernel/debug/usb/devices"); | ||||
memset (&previousDevicesFile[0], 0x00, sizeof(previousDevicesFile)); | ||||
previousChange = 0; | ||||
return; | return; | |||
} | } | |||
End of changes. 15 change blocks. | ||||
96 lines changed or deleted | 11 lines changed or added |