int usb_install_needs_restart_np(void) { HDEVINFO dev_info; SP_DEVINFO_DATA dev_info_data; int dev_index = 0; SP_DEVINSTALL_PARAMS install_params; int ret = FALSE; dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); dev_info = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT); SetEnvironmentVariable("LIBUSB_NEEDS_REBOOT", "1"); if(dev_info == INVALID_HANDLE_VALUE) { usb_error("usb_install_needs_restart_np(): getting " "device info set failed"); return ret; } while(SetupDiEnumDeviceInfo(dev_info, dev_index, &dev_info_data)) { memset(&install_params, 0, sizeof(SP_PROPCHANGE_PARAMS)); install_params.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if(SetupDiGetDeviceInstallParams(dev_info, &dev_info_data, &install_params)) { if(install_params.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) { usb_message("usb_install_needs_restart_np(): restart needed"); ret = TRUE; } } dev_index++; } SetupDiDestroyDeviceInfoList(dev_info); return ret; }
bool_t usb_service_delete(const char *name) { bool_t ret = FALSE; SC_HANDLE scm = NULL; SC_HANDLE service = NULL; if(!usb_service_load_dll()) { return FALSE; } do { scm = open_sc_manager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); if(!scm) { usb_error("usb_delete_service(): opening service control " "manager failed: %s", usb_win_error_to_string()); break; } service = open_service(scm, name, SERVICE_ALL_ACCESS); if(!service) { ret = TRUE; break; } if(!delete_service(service)) { usb_error("usb_service_delete(): deleting " "service '%s' failed: %s", name, usb_win_error_to_string()); break; } ret = TRUE; } while(0); if(service) { close_service_handle(service); } if(scm) { close_service_handle(scm); } usb_service_free_dll(); return ret; }
bool_t usb_service_load_dll() { if(usb_registry_is_nt()) { advapi32_dll = LoadLibrary("advapi32.dll"); if(!advapi32_dll) { usb_error("usb_service_load_dll(): loading DLL advapi32.dll" "failed"); return FALSE; } open_sc_manager = (open_sc_manager_t) GetProcAddress(advapi32_dll, "OpenSCManagerA"); open_service = (open_service_t) GetProcAddress(advapi32_dll, "OpenServiceA"); change_service_config = (change_service_config_t) GetProcAddress(advapi32_dll, "ChangeServiceConfigA"); close_service_handle = (close_service_handle_t) GetProcAddress(advapi32_dll, "CloseServiceHandle"); create_service = (create_service_t) GetProcAddress(advapi32_dll, "CreateServiceA"); delete_service = (delete_service_t) GetProcAddress(advapi32_dll, "DeleteService"); start_service = (start_service_t) GetProcAddress(advapi32_dll, "StartServiceA"); query_service_status = (query_service_status_t) GetProcAddress(advapi32_dll, "QueryServiceStatus"); control_service = (control_service_t) GetProcAddress(advapi32_dll, "ControlService"); if(!open_sc_manager || !open_service || !change_service_config || !close_service_handle || !create_service || !delete_service || !start_service || !query_service_status || !control_service) { FreeLibrary(advapi32_dll); usb_error("usb_service_load_dll(): loading exported " "functions of advapi32.dll failed"); return FALSE; } } return TRUE; }
// search for a supported joystick bool out_saitek_t::search(void) { int supported_devices [4] = { x52_standard_device1, x52_standard_device2, x52_pro_device, x52_other_device}; #if IBM || LIN // libusb v0.1 usb_bus* bus = 0; struct usb_device* dev = 0; usb_device_descriptor* dsc = 0; debug_out(debug,"out_saitek: libusb v0.1 in use"); usb_init(); debug_out(debug, "out_saitek: probing for a supported joystick"); int busses = usb_find_busses(); int devices = usb_find_devices(); debug_out(debug, "out_saitek: enumerated %d busses and %d devices",busses,devices); // cycle through all the devices looking for a supported joystick for (bus = usb_busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { dsc = &dev->descriptor; if (dsc->idVendor != saitek_vendor) continue; for (int i = 0; i<=3; i++) { debug_out(verbose, "out_saitek: searching for Product ID: 0x%.4X",supported_devices[i]); if (dsc->idProduct == supported_devices[i]) { debug_out(info, "out_saitek: found Saitek X52 Flight Control System (Product ID: 0x%.4X)",supported_devices[i]); a_product = supported_devices[i]; a_joydev = dev; } if (a_joydev) break; } if (a_joydev) break; } if (a_joydev) break; } #else // libusb v1.0 debug_out(debug,"out_saitek: libusb v1.0 in use"); int r = libusb_init(NULL); if (r < 0) { debug_out(err, "out_saitek: failed to initialize libusb: %s",usb_error(r)); return false; } debug_out(debug, "out_saitek: probing for a supported joystick"); for (int i = 0; i<=3; i++) { debug_out(verbose, "out_saitek: searching for Product ID: 0x%.4X",supported_devices[i]); a_joydev = libusb_open_device_with_vid_pid(NULL, saitek_vendor, supported_devices[i]); if (a_joydev != NULL) { debug_out(info, "out_saitek: found Saitek X52 Flight Control System (Product ID: 0x%.4X)",supported_devices[i]); a_product = supported_devices[i]; break; } } #endif if (a_joydev == NULL) { debug_out(err, "out_saitek: cannot find any supported device"); return false; } return true; // joystick found }
// Set the date on the MFD void out_saitek_t::set_date(int year, int month, int day) { if (!a_attached) return; int res; if (a_product == x52_other_device) return; unsigned short datedata = day | (month<<8); unsigned short yeardata = year; res = send_usb(0xC4,datedata); if (res < 0) debug_out(err,"out_saitek: cannot set day to %d and month to %d: %s",day,month,usb_error(res)); res = send_usb(0xC8,yeardata); if (res < 0) debug_out(err,"out_saitek: cannot set year to %d: %s",year,usb_error(res)); }
// Detach from the device bool out_saitek_t::detach(void) { if (!a_attached)return false; debug_out(info, "out_saitek: detaching joystick connection"); print(OFFLINE_MSG); set_time(true, 0, 0); set_date(0, 0, 0); set_display_brightness(0x00); set_led_brightness(0x00); #if IBM || LIN // libusb v0.1 int res = usb_close(a_usbhdl); if (res < 0) debug_out(err,"out_saitek: error while detaching the joystick: %s",usb_error(res)); #else // libusb v1.0 libusb_close(a_joydev); libusb_exit(NULL); #endif debug_out(info,"out_saitek: joystick disconnected cleanly"); return true; }
// clear a given line void out_saitek_t::clear_line(int line) { unsigned char line_clearctl[3] = {0xD9, 0xDA, 0xDC}; int res = send_usb(line_clearctl[line],0x00); if (res < 0) debug_out(err,"out_saitek: cannot clear line %d: %s",line,usb_error(res)); }
// Print the given text on the given line void out_saitek_t::print_line(int line, const char *text, int length) { int res; if (!text) return; debug_out(debug,"out_saitek: printing line %d: '%s'",line,text); unsigned char line_writectl[3] = {0xD1, 0xD2, 0xD4}; clear_line(line); while (length >= 1) { unsigned short charpair; if (length == 1) charpair = (0 << 8) + *text; else charpair = *(unsigned short*) text; res = send_usb(line_writectl[line],charpair); if (res < 0) debug_out(err,"out_saitek: cannot print line %d with text '%s': %s",line,text,usb_error(res)); length -= 2; text += 2; } }
// Set the time on the MFD void out_saitek_t::set_time(bool h24, int hour, int minute) { if (!a_attached) return; unsigned short timedata = minute | (hour<<8) | (h24?0x8000:0); int res = send_usb(0xC0,timedata); if (res < 0) debug_out(err,"out_saitek: cannot set time to %c:%c: %s",hour,minute,usb_error(res)); }
// Turn on a led void out_saitek_t::set_led(int led, int on) { if (!a_attached) return; int res = send_usb(0xB8,on | (led<<8)); if (res < 0) debug_out(err,"out_saitek: cannot set let %d on %d: %s",led,on,usb_error(res)); }
// Set the led brightness void out_saitek_t::set_led_brightness(char brightness) { if (!a_attached) return; int res = 0; bool mfd = false; // Do not turn the lights on for the MFD res = send_usb(mfd?0xB1:0xB2,brightness); if (res < 0) debug_out(err,"out_saitek: error while setting brightness %c on LEDs: %s",brightness,usb_error(res)); }
static int check (int e) { if (e < 0) throw usb_error (libusb_error (e)); return e; }
bool_t usb_service_stop(const char *name) { bool_t ret = FALSE; SC_HANDLE scm = NULL; SC_HANDLE service = NULL; SERVICE_STATUS status; if(!usb_service_load_dll()) { return FALSE; } do { scm = open_sc_manager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); if(!scm) { usb_error("usb_stop_service(): opening service control " "manager failed: %s", usb_win_error_to_string()); break; } service = open_service(scm, name, SERVICE_ALL_ACCESS); if(!service) { ret = TRUE; break; } if(!query_service_status(service, &status)) { usb_error("usb_stop_service(): getting status of " "service '%s' failed: %s", name, usb_win_error_to_string()); break; } if(status.dwCurrentState == SERVICE_STOPPED) { ret = TRUE; break; } if(!control_service(service, SERVICE_CONTROL_STOP, &status)) { usb_error("usb_stop_service(): stopping service '%s' failed: %s", name, usb_win_error_to_string()); break; } do { int wait = 0; if(!query_service_status(service, &status)) { usb_error("usb_stop_service(): getting status of " "service '%s' failed: %s", name, usb_win_error_to_string()); break; } Sleep(500); wait += 500; if(wait > 20000) { usb_error("usb_stop_service(): stopping " "service '%s' failed, timeout", name); ret = FALSE; break; } ret = TRUE; } while(status.dwCurrentState != SERVICE_STOPPED); } while(0); if(service) { close_service_handle(service); } if(scm) { close_service_handle(scm); } usb_service_free_dll(); return ret; }
bool_t usb_service_create(const char *name, const char *display_name, const char *binary_path, unsigned long type, unsigned long start_type) { SC_HANDLE scm = NULL; SC_HANDLE service = NULL; bool_t ret = FALSE; if(!usb_service_load_dll()) { return FALSE; } do { scm = open_sc_manager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); if(!scm) { usb_error("usb_service_create(): opening service control " "manager failed: %s", usb_win_error_to_string()); break; } service = open_service(scm, name, SERVICE_ALL_ACCESS); if(service) { if(!change_service_config(service, type, start_type, SERVICE_ERROR_NORMAL, binary_path, NULL, NULL, NULL, NULL, NULL, display_name)) { usb_error("usb_service_create(): changing config of " "service '%s' failed: %s", name, usb_win_error_to_string()); break; } ret = TRUE; break; } if(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) { service = create_service(scm, name, display_name, GENERIC_EXECUTE, type, start_type, SERVICE_ERROR_NORMAL, binary_path, NULL, NULL, NULL, NULL, NULL); if(!service) { usb_error("usb_service_create(): creating " "service '%s' failed: %s", name, usb_win_error_to_string()); } ret = TRUE; } } while(0); if(service) { close_service_handle(service); } if(scm) { close_service_handle(scm); } usb_service_free_dll(); return ret; }
int usb_install_driver_np(const char *inf_file) { HDEVINFO dev_info; SP_DEVINFO_DATA dev_info_data; INFCONTEXT inf_context; HINF inf_handle; DWORD config_flags, problem, status; BOOL reboot; char inf_path[MAX_PATH]; char id[MAX_PATH]; char tmp_id[MAX_PATH]; char *p; int dev_index; HINSTANCE newdev_dll = NULL; HMODULE setupapi_dll = NULL; update_driver_for_plug_and_play_devices_t UpdateDriverForPlugAndPlayDevices; setup_copy_oem_inf_t SetupCopyOEMInf; newdev_dll = LoadLibrary("newdev.dll"); if(!newdev_dll) { usb_error("usb_install_driver(): loading newdev.dll failed\n"); return -1; } UpdateDriverForPlugAndPlayDevices = (update_driver_for_plug_and_play_devices_t) GetProcAddress(newdev_dll, "UpdateDriverForPlugAndPlayDevicesA"); if(!UpdateDriverForPlugAndPlayDevices) { usb_error("usb_install_driver(): loading newdev.dll failed\n"); return -1; } setupapi_dll = GetModuleHandle("setupapi.dll"); if(!setupapi_dll) { usb_error("usb_install_driver(): loading setupapi.dll failed\n"); return -1; } SetupCopyOEMInf = (setup_copy_oem_inf_t) GetProcAddress(setupapi_dll, "SetupCopyOEMInfA"); if(!SetupCopyOEMInf) { usb_error("usb_install_driver(): loading setupapi.dll failed\n"); return -1; } dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); /* retrieve the full .inf file path */ if(!GetFullPathName(inf_file, MAX_PATH, inf_path, NULL)) { usb_error("usb_install_driver(): .inf file %s not found\n", inf_file); return -1; } /* open the .inf file */ inf_handle = SetupOpenInfFile(inf_path, NULL, INF_STYLE_WIN4, NULL); if(inf_handle == INVALID_HANDLE_VALUE) { usb_error("usb_install_driver(): unable to open .inf file %s\n", inf_file); return -1; } /* find the .inf file's device description section marked "Devices" */ if(!SetupFindFirstLine(inf_handle, "Devices", NULL, &inf_context)) { usb_error("usb_install_driver(): .inf file %s does not contain " "any device descriptions\n", inf_file); SetupCloseInfFile(inf_handle); return -1; } do { /* get the device ID from the .inf file */ if(!SetupGetStringField(&inf_context, 2, id, sizeof(id), NULL)) { continue; } /* convert the string to lowercase */ strlwr(id); reboot = FALSE; /* copy the .inf file to the system directory so that is will be found */ /* when new devices are plugged in */ SetupCopyOEMInf(inf_path, NULL, SPOST_PATH, 0, NULL, 0, NULL, NULL); /* update all connected devices matching this ID, but only if this */ /* driver is better or newer */ UpdateDriverForPlugAndPlayDevices(NULL, id, inf_path, INSTALLFLAG_FORCE, &reboot); /* now search the registry for device nodes representing currently */ /* unattached devices */ /* get all USB device nodes from the registry, present and non-present */ /* devices */ dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES); if(dev_info == INVALID_HANDLE_VALUE) { SetupCloseInfFile(inf_handle); break; } dev_index = 0; /* enumerate the device list to find all attached and unattached */ /* devices */ while(SetupDiEnumDeviceInfo(dev_info, dev_index, &dev_info_data)) { /* get the harware ID from the registry, this is a multi-zero string */ if(SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_HARDWAREID, NULL, (BYTE *)tmp_id, sizeof(tmp_id), NULL)) { /* check all possible IDs contained in that multi-zero string */ for(p = tmp_id; *p; p += (strlen(p) + 1)) { /* convert the string to lowercase */ strlwr(p); /* found a match? */ if(strstr(p, id)) { /* is this device disconnected? */ if(CM_Get_DevNode_Status(&status, &problem, dev_info_data.DevInst, 0) == CR_NO_SUCH_DEVINST) { /* found a device node that represents an unattached */ /* device */ if(SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_CONFIGFLAGS, NULL, (BYTE *)&config_flags, sizeof(config_flags), NULL)) { /* mark the device to be reinstalled the next time it is */ /* plugged in */ config_flags |= CONFIGFLAG_REINSTALL; /* write the property back to the registry */ SetupDiSetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_CONFIGFLAGS, (BYTE *)&config_flags, sizeof(config_flags)); } } /* a match was found, skip the rest */ break; } } } /* check the next device node */ dev_index++; } SetupDiDestroyDeviceInfoList(dev_info); /* get the next device ID from the .inf file */ } while(SetupFindNextLine(&inf_context, &inf_context)); /* we are done, close the .inf file */ SetupCloseInfFile(inf_handle); usb_registry_stop_libusb_devices(); /* stop all libusb devices */ usb_registry_start_libusb_devices(); /* restart all libusb devices */ return 0; }