/* libusb-win32, Generic Windows USB Library * Copyright (c) 2002-2004 Stephan Meyer * Copyright (c) 2000-2004 Johannes Erdfelt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __GNUC__ #ifndef WINVER #define WINVER 0x0500 #endif #endif #define INITGUID #include #include #include #include #include "lusb0_usb.h" #define LIBUSB_WINDOW_CLASS "LIBUSB_WINDOW_CLASS" #define LIBUSB_BUTTON_HEIGHT 30 #define LIBUSB_BUTTON_WIDTH 70 #define LIBUSB_BORDER 10 DEFINE_GUID(GUID_DEVINTERFACE_USB_HUB, 0xf18a0e88, 0xc30c, 0x11d0, 0x88, \ 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8); DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, \ 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); #define EDIT_BUF_INCREMENT 1024 enum { ID_EXIT = 100, ID_REFRESH, ID_EDIT }; static char *edit_buffer = NULL; static int edit_buffer_size = 0; static int edit_buffer_pos = 0; static HWND main_win; static HWND exit_button; static HWND refresh_button; static HWND edit_box; static HDEVNOTIFY notification_handle_hub, notification_handle_dev; LRESULT CALLBACK win_proc(HWND handle, UINT message, WPARAM w_param, LPARAM l_param); static void on_size(int width, int height); static void on_refresh(void); static void edit_printf_init(void); static void edit_printf_free(void); static void edit_printf(const char *s, ...); static void print_configuration(struct usb_config_descriptor *config); static void print_interface(struct usb_interface *interface); static void print_altsetting(struct usb_interface_descriptor *interface); static void print_endpoint(struct usb_endpoint_descriptor *endpoint); static void print_device_descriptor(struct usb_device_descriptor *desc, int indent); int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmd_line, int cmd_show) { MSG msg; WNDCLASSEX win_class; DEV_BROADCAST_DEVICEINTERFACE dev_if; LoadLibrary("comctl32.dll"); win_class.cbSize = sizeof(WNDCLASSEX); win_class.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS ; win_class.lpfnWndProc = win_proc; win_class.cbClsExtra = 0; win_class.cbWndExtra = 0; win_class.hInstance = instance; win_class.hIcon = NULL; win_class.hCursor = LoadCursor(NULL, IDC_ARROW); win_class.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); win_class.lpszMenuName = NULL; win_class.lpszClassName = LIBUSB_WINDOW_CLASS; win_class.hIconSm = NULL; RegisterClassEx(&win_class); main_win = CreateWindowEx(WS_EX_APPWINDOW| WS_EX_CONTROLPARENT, LIBUSB_WINDOW_CLASS, "TestLibUsb - Windows Version", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_DLGFRAME, CW_USEDEFAULT, 0, 500, 500, NULL, NULL, instance, NULL); if (!main_win) { return FALSE; } exit_button = CreateWindow("BUTTON", "Exit", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 10, 10, LIBUSB_BUTTON_WIDTH, LIBUSB_BUTTON_HEIGHT, main_win, (HMENU) ID_EXIT, instance, NULL); refresh_button = CreateWindow("BUTTON", "Refresh", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 10, 100, LIBUSB_BUTTON_WIDTH, LIBUSB_BUTTON_HEIGHT, main_win, (HMENU) ID_REFRESH, instance, NULL); edit_box = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, main_win, (HMENU) ID_EDIT, instance, NULL); SendMessage(edit_box, WM_SETFONT, (WPARAM) CreateFont(13, 8, 0, 0, 400, 0, 0, 0, 0, 1, 2, 1, 49, "Courier"), 0); ShowWindow(main_win, cmd_show); UpdateWindow(main_win); BringWindowToTop(main_win); usb_set_debug(4); usb_init(); usb_find_busses(); on_refresh(); dev_if.dbcc_size = sizeof(dev_if); dev_if.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_HUB; notification_handle_hub = RegisterDeviceNotification(main_win, &dev_if, 0); dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; notification_handle_dev = RegisterDeviceNotification(main_win, &dev_if, 0); while (GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } DestroyWindow(main_win); UnregisterClass(LIBUSB_WINDOW_CLASS, instance); return 0; } LRESULT CALLBACK win_proc(HWND win, UINT message, WPARAM w_param, LPARAM l_param) { DEV_BROADCAST_HDR *hdr = (DEV_BROADCAST_HDR *) l_param; switch (message) { case WM_DESTROY: if (notification_handle_hub) UnregisterDeviceNotification(notification_handle_hub); if (notification_handle_dev) UnregisterDeviceNotification(notification_handle_dev); PostQuitMessage(0); break; case WM_SIZE: on_size(LOWORD(l_param), HIWORD(l_param)); break; case WM_COMMAND: switch (LOWORD(w_param)) { case ID_EXIT: PostQuitMessage(0); break; case ID_REFRESH: on_refresh(); break; default: return DefWindowProc(win, message, w_param, l_param ); } break; case WM_DEVICECHANGE: switch (w_param) { case DBT_DEVICEREMOVECOMPLETE: if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) on_refresh(); break; case DBT_DEVICEARRIVAL: if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) on_refresh(); break; default: ; } break; default: return DefWindowProc(win, message, w_param, l_param); } return 0; } static void on_size(int width, int height) { int _width, _height, _x, _y; _width = LIBUSB_BUTTON_WIDTH; _height = LIBUSB_BUTTON_HEIGHT; _x = width - LIBUSB_BORDER - LIBUSB_BUTTON_WIDTH; _y = height - LIBUSB_BORDER - LIBUSB_BUTTON_HEIGHT; SetWindowPos(exit_button, HWND_TOP, _x, _y, _width, _height, SWP_SHOWWINDOW); _x -= LIBUSB_BUTTON_WIDTH + LIBUSB_BORDER; SetWindowPos(refresh_button, HWND_TOP, _x, _y, _width, _height, SWP_SHOWWINDOW); _width = width - 2 * LIBUSB_BORDER; _height = height - 4 * LIBUSB_BORDER - LIBUSB_BUTTON_HEIGHT; _y = LIBUSB_BORDER; _x = LIBUSB_BORDER; SetWindowPos(edit_box, HWND_TOP, _x, _y, _width, _height, SWP_SHOWWINDOW); } static void on_refresh(void) { struct usb_bus *bus; struct usb_device *dev; const struct usb_version *version; edit_printf_init(); usb_find_devices(); version = usb_get_version(); if (version) { edit_printf("DLL version:\t%d.%d.%d.%d\r\n", version->dll.major, version->dll.minor, version->dll.micro, version->dll.nano); edit_printf("Driver version:\t%d.%d.%d.%d\r\n\r\n", version->driver.major, version->driver.minor, version->driver.micro, version->driver.nano); } edit_printf("bus/device idVendor/idProduct\r\n"); for (bus = usb_get_busses(); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { int ret, i; char string[256]; usb_dev_handle *udev; edit_printf("%s/%s %04X/%04X\r\n", bus->dirname, dev->filename, dev->descriptor.idVendor, dev->descriptor.idProduct); udev = usb_open(dev); if (udev) { if (dev->descriptor.iManufacturer) { ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, string, sizeof(string)); if (ret > 0) edit_printf("- Manufacturer : %s\r\n", string); else edit_printf("- Unable to fetch manufacturer string\r\n"); } if (dev->descriptor.iProduct) { ret = usb_get_string_simple(udev, dev->descriptor.iProduct, string, sizeof(string)); if (ret > 0) edit_printf("- Product : %s\r\n", string); else edit_printf("- Unable to fetch product string\r\n"); } if (dev->descriptor.iSerialNumber) { ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string, sizeof(string)); if (ret > 0) edit_printf("- Serial Number: %s\r\n", string); else edit_printf("- Unable to fetch serial number string\r\n"); } usb_close (udev); } print_device_descriptor(&dev->descriptor,0); if (!dev->config) { edit_printf(" Couldn't retrieve descriptors\r\n"); continue; } for (i = 0; i < dev->descriptor.bNumConfigurations; i++) print_configuration(&dev->config[i]); } } SendMessage(edit_box, WM_SETTEXT, 0, (LPARAM) edit_buffer); edit_printf_free(); } static void edit_printf_init(void) { if (edit_buffer) { free(edit_buffer); } edit_buffer = malloc(EDIT_BUF_INCREMENT); if (edit_buffer) { edit_buffer_size = EDIT_BUF_INCREMENT; } edit_buffer_size = 0; edit_buffer_pos = 0; } static void edit_printf_free(void) { if (edit_buffer) { free(edit_buffer); } edit_buffer = NULL; edit_buffer_size = 0; edit_buffer_pos = 0; } static void edit_printf(const char *s, ...) { va_list args; va_start(args, s); if (edit_buffer_size - edit_buffer_pos < EDIT_BUF_INCREMENT) { char *tmp = realloc(edit_buffer, edit_buffer_size + EDIT_BUF_INCREMENT); if (tmp) { edit_buffer = tmp; edit_buffer_size += EDIT_BUF_INCREMENT; } else { return; } } edit_buffer_pos += vsnprintf(edit_buffer + edit_buffer_pos, EDIT_BUF_INCREMENT - 1, s, args); va_end(args); } static void print_endpoint(struct usb_endpoint_descriptor *endpoint) { edit_printf(" bEndpointAddress: %02xh\r\n", endpoint->bEndpointAddress); edit_printf(" bmAttributes: %02xh\r\n", endpoint->bmAttributes); edit_printf(" wMaxPacketSize: %d\r\n", endpoint->wMaxPacketSize); edit_printf(" bInterval: %d\r\n", endpoint->bInterval); edit_printf(" bRefresh: %d\r\n", endpoint->bRefresh); edit_printf(" bSynchAddress: %d\r\n", endpoint->bSynchAddress); } static void print_altsetting(struct usb_interface_descriptor *interface) { int i; edit_printf(" bInterfaceNumber: %d\r\n", interface->bInterfaceNumber); edit_printf(" bAlternateSetting: %d\r\n", interface->bAlternateSetting); edit_printf(" bNumEndpoints: %d\r\n", interface->bNumEndpoints); edit_printf(" bInterfaceClass: %d\r\n", interface->bInterfaceClass); edit_printf(" bInterfaceSubClass: %d\r\n", interface->bInterfaceSubClass); edit_printf(" bInterfaceProtocol: %d\r\n", interface->bInterfaceProtocol); edit_printf(" iInterface: %d\r\n", interface->iInterface); for (i = 0; i < interface->bNumEndpoints; i++) print_endpoint(&interface->endpoint[i]); } static void print_interface(struct usb_interface *interface) { int i; for (i = 0; i < interface->num_altsetting; i++) print_altsetting(&interface->altsetting[i]); } static void print_configuration(struct usb_config_descriptor *config) { int i; edit_printf(" wTotalLength: %d\r\n", config->wTotalLength); edit_printf(" bNumInterfaces: %d\r\n", config->bNumInterfaces); edit_printf(" bConfigurationValue: %d\r\n", config->bConfigurationValue); edit_printf(" iConfiguration: %d\r\n", config->iConfiguration); edit_printf(" bmAttributes: %02xh\r\n", config->bmAttributes); edit_printf(" MaxPower: %d\r\n", config->MaxPower); for (i = 0; i < config->bNumInterfaces; i++) print_interface(&config->interface[i]); } static void print_device_descriptor(struct usb_device_descriptor *desc, int indent) { edit_printf("%.*sbLength: %u\r\n", indent, " ", desc->bLength); edit_printf("%.*sbDescriptorType: %02Xh\r\n", indent, " ", desc->bDescriptorType); edit_printf("%.*sbcdUSB: %04Xh\r\n", indent, " ", desc->bcdUSB); edit_printf("%.*sbDeviceClass: %02Xh\r\n", indent, " ", desc->bDeviceClass); edit_printf("%.*sbDeviceSubClass: %02Xh\r\n", indent, " ", desc->bDeviceSubClass); edit_printf("%.*sbDeviceProtocol: %02Xh\r\n", indent, " ", desc->bDeviceProtocol); edit_printf("%.*sbMaxPacketSize0: %02Xh\r\n", indent, " ", desc->bMaxPacketSize0); edit_printf("%.*sidVendor: %04Xh\r\n", indent, " ", desc->idVendor); edit_printf("%.*sidProduct: %04Xh\r\n", indent, " ", desc->idProduct); edit_printf("%.*sbcdDevice: %04Xh\r\n", indent, " ", desc->bcdDevice); edit_printf("%.*siManufacturer: %u\r\n", indent, " ", desc->iManufacturer); edit_printf("%.*siProduct: %u\r\n", indent, " ", desc->iProduct); edit_printf("%.*siSerialNumber: %u\r\n", indent, " ", desc->iSerialNumber); edit_printf("%.*sbNumConfigurations: %u\r\n", indent, " ", desc->bNumConfigurations); }