/** * Forks and runs the given application, waits for a maximum of timeout seconds for process to finish. * * @param argv The arguments values, the first one is the application path or name */ void bb_run_fork_wait(char** argv, int timeout) { check_handler(); // Fork and attempt to run given application pid_t ret = fork(); if (ret == 0) { // Fork went ok, child process replace bb_run_exec(argv); } else { if (ret > 0) { // Fork went ok, parent process continues bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], ret); pidlist_add(ret); //sleep until process finishes or timeout reached int i = 0; while (bb_is_running(ret) && ((i < timeout) || (timeout == 0)) && dowait) { usleep(1000000); i++; } //make a single attempt to kill the process if timed out, without waiting if (bb_is_running(ret)) { bb_stop(ret); } } else { // Fork failed bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]); return; } } return; }
uint8_t bb_i2c_read( uint8_t addr, uint8_t *buf, uint8_t len ) { uint8_t rc = 0; bb_start(); bb_out( addr | 0x01 ); // address + R if ( get_ack() ) { while ( len > 0 ) { *buf++ = bb_in(); len--; if ( len > 0 ) { send_ack(); } else { send_nak(); } } } else { rc = 1; } bb_stop(); return rc; }
uint8_t bb_i2c_write( uint8_t addr, uint8_t *buf, uint8_t len ) { uint8_t rc = 0; bb_start(); bb_out( addr ); // address + W if ( get_ack() ) { while ( len > 0 ) { bb_out( *buf++ ); if ( get_ack() == 0 ) { rc = 1; break; } len--; } } else { rc = 1; } bb_stop(); return rc; }
/** * Start the X server by fork-exec, turn card on and load driver if needed. * If after this method finishes X is running, it was successfull. * If it somehow fails, X should not be running after this method finishes. */ void start_secondary(void) { char driver[BUFFER_SIZE] = {0}; /* enable card if the switcher is available */ if (switcher) { if (switch_on() != SWITCH_ON) { set_bb_error("Could not enable discrete graphics card"); return; } if (pci_config_restore(pci_bus_id_discrete, &pci_config_state_discrete)) { bb_log(LOG_WARNING, "Could not restore PCI configuration space: %s\n", strerror(errno)); } } //if runmode is BB_RUN_EXIT, do not start X, we are shutting down. if (bb_status.runmode == BB_RUN_EXIT) { return; } if (pci_get_driver(driver, pci_bus_id_discrete, sizeof driver)) { /* if the loaded driver does not equal the driver from config, unload it */ if (strcasecmp(bb_config.driver, driver)) { if (!module_unload(driver)) { /* driver failed to unload, aborting */ return; } } } /* load the driver if none was loaded or if the loaded driver did not match * the configured one */ if (strcasecmp(bb_config.driver, driver)) { char *module_name = bb_config.module_name; char *driver_name = bb_config.driver; if (!module_load(module_name, driver_name)) { set_bb_error("Could not load GPU driver"); return; } } //no problems, start X if not started yet if (!bb_is_running(bb_status.x_pid)) { char pci_id[12]; static char *x_conf_file; snprintf(pci_id, 12, "PCI:%02x:%02x:%o", pci_bus_id_discrete->bus, pci_bus_id_discrete->slot, pci_bus_id_discrete->func); if (!x_conf_file) { x_conf_file = xorg_path_w_driver(bb_config.x_conf_file, bb_config.driver); } bb_log(LOG_INFO, "Starting X server on display %s.\n", bb_config.x_display); char *x_argv[] = { XORG_BINARY, bb_config.x_display, "-config", x_conf_file, "-sharevts", "-nolisten", "tcp", "-noreset", "-verbose", "3", "-isolateDevice", pci_id, "-modulepath", bb_config.mod_path, NULL }; if (!*bb_config.mod_path) { x_argv[12] = 0; //remove -modulepath if not set } //close any previous pipe, if it (still) exists if (bb_status.x_pipe[0] != -1){close(bb_status.x_pipe[0]); bb_status.x_pipe[0] = -1;} if (bb_status.x_pipe[1] != -1){close(bb_status.x_pipe[1]); bb_status.x_pipe[1] = -1;} //create a new pipe if (pipe2(bb_status.x_pipe, O_NONBLOCK)){ set_bb_error("Could not create output pipe for X"); return; } bb_status.x_pid = bb_run_fork_ld_redirect(x_argv, bb_config.ld_path, bb_status.x_pipe[1]); //close the end of the pipe that is not ours if (bb_status.x_pipe[1] != -1){close(bb_status.x_pipe[1]); bb_status.x_pipe[1] = -1;} } //check if X is available, for maximum 10 seconds. time_t xtimer = time(0); Display * xdisp = 0; while ((time(0) - xtimer <= 10) && bb_is_running(bb_status.x_pid)) { xdisp = XOpenDisplay(bb_config.x_display); if (xdisp != 0) { break; } check_xorg_pipe();//make sure Xorg errors come in smoothly usleep(100000); //don't retry too fast } check_xorg_pipe();//make sure Xorg errors come in smoothly //check if X is available if (xdisp == 0) { //X not available /// \todo Maybe check X exit status and/or messages? if (bb_is_running(bb_status.x_pid)) { //X active, but not accepting connections set_bb_error("X unresponsive after 10 seconds - aborting"); bb_stop(bb_status.x_pid); } else { //X terminated itself set_bb_error("X did not start properly"); } } else { //X accepted the connetion - we assume it works XCloseDisplay(xdisp); //close connection to X again bb_log(LOG_INFO, "X successfully started in %i seconds\n", time(0) - xtimer); //reset errors, if any set_bb_error(0); } }//start_secondary