📄 synth_intr.c
字号:
char filename[BUFSIZE]; const char* path = 0; int i, j; cyg_bool found = false; int to_aux_pipe[2]; int from_aux_pipe[2]; int child; int aux_version;#if 1 // Check for a command line argument -io. Only run the auxiliary if this // argument is provided, i.e. default to traditional behaviour. for (i = 1; i < cyg_hal_sys_argc; i++) { const char* tmp = cyg_hal_sys_argv[i]; if ('-' == *tmp) { // Arguments beyond -- are reserved for use by the application, // and should not be interpreted by the HAL itself or by ecosynth. if (('-' == tmp[1]) && ('\0' == tmp[2])) { break; } tmp++; if ('-' == *tmp) { // Do not distinguish between -io and --io tmp++; } if (('i' == tmp[0]) && ('o' == tmp[1]) && ('\0' == tmp[2])) { found = 1; break; } } } if (!found) { return; }#else // Check for a command line argument -ni or -nio. Always run the // auxiliary unless this argument is given, i.e. default to full // I/O support. for (i = 1; i < cyg_hal_sys_argc; i++) { const char* tmp = cyg_hal_sys_argv[i]; if ('-' == *tmp) { if (('-' == tmp[1]) && ('\0' == tmp[2])) { break; } tmp++; if ('-' == *tmp) { tmp++; } if ('n' == *tmp) { tmp++; if ('i' == *tmp) { tmp++; if ('\0' == *tmp) { found = 1; // -ni or --ni break; } if (('o' == *tmp) && ('\0' == tmp[1])) { found = 1; // -nio or --nio break; } } } } } if (found) { return; }#endif // The auxiliary must be found relative to the current search path, // so look for a PATH= environment variable. for (i = 0; (0 == path) && (0 != cyg_hal_sys_environ[i]); i++) { const char *var = cyg_hal_sys_environ[i]; if (('P' == var[0]) && ('A' == var[1]) && ('T' == var[2]) && ('H' == var[3]) && ('=' == var[4])) { path = var + 5; } } if (0 == path) { // Very unlikely, but just in case. path = ".:/bin:/usr/bin"; } found = 0; while (!found && ('\0' != *path)) { // for every entry in the path char *tmp = AUXILIARY; j = 0; // As a special case, an empty string in the path corresponds to the // current directory. if (':' == *path) { filename[j++] = '.'; path++; } else { while ((j < BUFSIZE) && ('\0' != *path) && (':' != *path)) { filename[j++] = *path++; } // If not at the end of the search path, move on to the next entry. if ('\0' != *path) { while ((':' != *path) && ('\0' != *path)) { path++; } if (':' == *path) { path++; } } } // Now append a directory separator, and then the name of the executable. if (j < BUFSIZE) { filename[j++] = '/'; } while ((j < BUFSIZE) && ('\0' != *tmp)) { filename[j++] = *tmp++; } // If there has been a buffer overflow, skip this entry. if (j == BUFSIZE) { filename[BUFSIZE-1] = '\0'; diag_printf("Warning: buffer limit reached while searching PATH for the I/O auxiliary.\n"); diag_printf(" : skipping current entry.\n"); } else { // filename now contains a possible match for the auxiliary. filename[j++] = '\0'; if (0 == cyg_hal_sys_access(filename, CYG_HAL_SYS_X_OK)) { found = true; } } }#undef BUFSIZE if (!found) { diag_printf("Error: unable to find the I/O auxiliary program on the current search PATH\n"); diag_printf(" : please install the appropriate host-side tools.\n"); cyg_hal_sys_exit(1); } // An apparently valid executable exists (or at the very least it existed...), // so create the pipes that will be used for communication. if ((0 != cyg_hal_sys_pipe(to_aux_pipe)) || (0 != cyg_hal_sys_pipe(from_aux_pipe))) { diag_printf("Error: unable to set up pipes for communicating with the I/O auxiliary.\n"); cyg_hal_sys_exit(1); } // Time to fork(). child = cyg_hal_sys_fork(); if (child < 0) { diag_printf("Error: failed to fork() process for the I/O auxiliary.\n"); cyg_hal_sys_exit(1); } else if (child == 0) { cyg_bool found_dotdot; // There should not be any problems rearranging the file descriptors as desired... cyg_bool unexpected_error = 0; // In the child process. Close unwanted file descriptors, then some dup2'ing, // and execve() the I/O auxiliary. The auxiliary will inherit stdin, // stdout and stderr from the eCos application, so that functions like // printf() work as expected. In addition fd 3 will be the pipe from // the eCos application and fd 4 the pipe to the application. It is possible // that the eCos application was run from some process other than a shell // and hence that file descriptors 3 and 4 are already in use, but that is not // supported. One possible workaround would be to close all file descriptors // >= 3, another would be to munge the argument vector passing the file // descriptors actually being used. unexpected_error |= (0 != cyg_hal_sys_close(to_aux_pipe[1])); unexpected_error |= (0 != cyg_hal_sys_close(from_aux_pipe[0])); if (3 != to_aux_pipe[0]) { if (3 == from_aux_pipe[1]) { // Because to_aux_pipe[] was set up first it should have received file descriptors 3 and 4. diag_printf("Internal error: file descriptors have been allocated in an unusual order.\n"); cyg_hal_sys_exit(1); } else { unexpected_error |= (3 != cyg_hal_sys_dup2(to_aux_pipe[0], 3)); unexpected_error |= (0 != cyg_hal_sys_close(to_aux_pipe[0])); } } if (4 != from_aux_pipe[1]) { unexpected_error |= (4 != cyg_hal_sys_dup2(from_aux_pipe[1], 4)); unexpected_error |= (0 != cyg_hal_sys_close(from_aux_pipe[1])); } if (unexpected_error) { diag_printf("Error: internal error in auxiliary process, failed to manipulate pipes.\n"); cyg_hal_sys_exit(1); } // The arguments passed to the auxiliary are mostly those for // the synthetic target application, except for argv[0] which // is replaced with the auxiliary's pathname. The latter // currently holds at least one ../, and cleaning this up is // useful. // // If the argument vector contains -- then that and subsequent // arguments are not passed to the auxiliary. Instead such // arguments are reserved for use by the application. do { int len; for (len = 0; '\0' != filename[len]; len++) ; found_dotdot = false; for (i = 0; i < (len - 4); i++) { if (('/' == filename[i]) && ('.' == filename[i+1]) && ('.' == filename[i+2]) && ('/' == filename[i+3])) { j = i + 3; for ( --i; (i >= 0) && ('/' != filename[i]); i--) { CYG_EMPTY_STATEMENT; } if (i >= 0) { found_dotdot = true; do { i++; j++; filename[i] = filename[j]; } while ('\0' != filename[i]); } } } } while(found_dotdot); cyg_hal_sys_argv[0] = filename; for (i = 1; i < cyg_hal_sys_argc; i++) { const char* tmp = cyg_hal_sys_argv[i]; if (('-' == tmp[0]) && ('-' == tmp[1]) && ('\0' == tmp[2])) { cyg_hal_sys_argv[i] = (const char*) 0; break; } } cyg_hal_sys_execve(filename, cyg_hal_sys_argv, cyg_hal_sys_environ); // An execute error has occurred. Report this here, then exit. The // parent will detect a close on the pipe without having received // any data, and it will assume that a suitable diagnostic will have // been displayed already. diag_printf("Error: failed to execute the I/O auxiliary.\n"); cyg_hal_sys_exit(1); } else { int rc; char buf[1]; // Still executing the eCos application. // Do some cleaning-up. to_aux = to_aux_pipe[1]; from_aux = from_aux_pipe[0]; if ((0 != cyg_hal_sys_close(to_aux_pipe[0])) || (0 != cyg_hal_sys_close(from_aux_pipe[1]))) { diag_printf("Error: internal error in main process, failed to manipulate pipes.\n"); cyg_hal_sys_exit(1); } // It is now a good idea to block until the auxiliary is // ready, i.e. give it a chance to read in its configuration // files, load appropriate scripts, pop up windows, ... This // may take a couple of seconds or so. Once the auxiliary is // ready it will write a single byte down the pipe. This is // the only time that the auxiliary will write other than when // responding to a request. do { rc = cyg_hal_sys_read(from_aux, buf, 1); } while (-CYG_HAL_SYS_EINTR == rc); if (1 != rc) { // The auxiliary has not started up successfully, so exit // immediately. It should have generated appropriate // diagnostics. cyg_hal_sys_exit(1); } } // At this point the auxiliary is up and running. It should not // generate any interrupts just yet since none of the devices have // been initialized. Remember that the auxiliary is now running, // so that the initialization routines for those devices can // figure out that they should interact with the auxiliary rather // than attempt anything manually. synth_auxiliary_running = true; // Make sure that the auxiliary is the right version. synth_auxiliary_xchgmsg(SYNTH_DEV_AUXILIARY, SYNTH_AUXREQ_GET_VERSION, 0, 0, (const unsigned char*) 0, 0, &aux_version, (unsigned char*) 0, (int*) 0, 0); if (SYNTH_AUXILIARY_PROTOCOL_VERSION != aux_version) { synth_auxiliary_running = false; diag_printf("Error: an incorrect version of the I/O auxiliary is installed\n" " Expected version %d, actual version %d\n" " Installed binary is %s\n", SYNTH_AUXILIARY_PROTOCOL_VERSION, aux_version, filename); cyg_hal_sys_exit(1); }}// Write a request to the I/O auxiliary, and optionally get back a// reply. The dev_id is 0 for messages intended for the auxiliary// itself, for example a device instantiation or a request for the// current interrupt sate. Otherwise it identifies a specific device.// The request code is specific to the device, and the two optional// arguments are specific to the request.voidsynth_auxiliary_xchgmsg(int devid, int reqcode, int arg1, int arg2, const unsigned char* txdata, int txlen, int* result, unsigned char* rxdata, int* actual_rxlen, int rxlen){ unsigned char request[SYNTH_REQUEST_LENGTH]; unsigned char reply[SYNTH_REPLY_LENGTH]; int rc; int reply_rxlen; cyg_bool_t old_isrstate; CYG_ASSERT(devid >= 0, "A valid device id should be supplied"); CYG_ASSERT((0 == txlen) || ((const unsigned char*)0 != txdata), "Data transmits require a transmit buffer"); CYG_ASSERT((0 == rxlen) || ((unsigned char*)0 != rxdata), "Data receives require a receive buffer"); CYG_ASSERT((0 == rxlen) || ((int*)0 != result), "If a reply is expected then space must be allocated"); // I/O interactions with the auxiliary must be atomic: a context switch in // between sending the header and the actual data would be bad. HAL_DISABLE_INTERRUPTS(old_isrstate); // The auxiliary should be running for the duration of this // exchange. However the auxiliary can disappear asynchronously, // so it is not possible for higher-level code to be sure that the // auxiliary is still running. // // If the auxiliary disappears during this call then usually this // will cause a SIGCHILD or SIGPIPE, both of which result in // termination. The exception is when the auxiliary decides to // shut down stdout for some reason without exiting - that has to // be detected in the read loop. if (synth_auxiliary_running) { request[SYNTH_REQUEST_DEVID_OFFSET + 0] = (devid >> 0) & 0x0FF; request[SYNTH_REQUEST_DEVID_OFFSET + 1] = (devid >> 8) & 0x0FF; request[SYNTH_REQUEST_DEVID_OFFSET + 2] = (devid >> 16) & 0x0FF; request[SYNTH_REQUEST_DEVID_OFFSET + 3] = (devid >> 24) & 0x0FF; request[SYNTH_REQUEST_REQUEST_OFFSET + 0] = (reqcode >> 0) & 0x0FF; request[SYNTH_REQUEST_REQUEST_OFFSET + 1] = (reqcode >> 8) & 0x0FF; request[SYNTH_REQUEST_REQUEST_OFFSET + 2] = (reqcode >> 16) & 0x0FF; request[SYNTH_REQUEST_REQUEST_OFFSET + 3] = (reqcode >> 24) & 0x0FF; request[SYNTH_REQUEST_ARG1_OFFSET + 0] = (arg1 >> 0) & 0x0FF; request[SYNTH_REQUEST_ARG1_OFFSET + 1] = (arg1 >> 8) & 0x0FF; request[SYNTH_REQUEST_ARG1_OFFSET + 2] = (arg1 >> 16) & 0x0FF; request[SYNTH_REQUEST_ARG1_OFFSET + 3] = (arg1 >> 24) & 0x0FF; request[SYNTH_REQUEST_ARG2_OFFSET + 0] = (arg2 >> 0) & 0x0FF; request[SYNTH_REQUEST_ARG2_OFFSET + 1] = (arg2 >> 8) & 0x0FF; request[SYNTH_REQUEST_ARG2_OFFSET + 2] = (arg2 >> 16) & 0x0FF; request[SYNTH_REQUEST_ARG2_OFFSET + 3] = (arg2 >> 24) & 0x0FF; request[SYNTH_REQUEST_TXLEN_OFFSET + 0] = (txlen >> 0) & 0x0FF;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -