⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 synth_intr.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -