void run_js(void *jsargs) { js_call *call_data = (js_call *) jsargs; spidermonkey_drv_t *dd = call_data->driver_data; ErlDrvBinary *args = call_data->args; driver_free(call_data); char *data = args->orig_bytes; char *command = read_command(&data); char *call_id = read_string(&data); char *result = NULL; if (strncmp(command, "ej", 2) == 0) { char *filename = read_string(&data); char *code = read_string(&data); result = sm_eval(dd->vm, filename, code, 1); if (strstr(result, "{\"error\"") != NULL) { send_error_string_response(dd, call_id, result); } else { send_string_response(dd, call_id, result); } driver_free(filename); driver_free(code); driver_free(result); } else if (strncmp(command, "dj", 2) == 0) { char *filename = read_string(&data); char *code = read_string(&data); result = sm_eval(dd->vm, filename, code, 0); if (result == NULL) { send_ok_response(dd, call_id); } else { send_error_string_response(dd, call_id, result); driver_free(result); } driver_free(filename); driver_free(code); } else if (strncmp(command, "sd", 2) == 0) { dd->shutdown = 1; send_ok_response(dd, call_id); } else { unknown_command(dd, call_id); } driver_free(command); driver_free(call_id); driver_binary_dec_refc(args); }
static void process(ErlDrvData handle, ErlIOVec *ev) { spidermonkey_drv_t *dd = (spidermonkey_drv_t *) handle; char *data = ev->binv[1]->orig_bytes; char *command = read_command(&data); if (strncmp(command, "ij", 2) == 0) { char *call_id = read_string(&data); int thread_stack = read_int32(&data); if (thread_stack < 8) { thread_stack = 8; } thread_stack = thread_stack * (1024 * 1024); int heap_size = read_int32(&data) * (1024 * 1024); dd->vm = sm_initialize(thread_stack, heap_size); send_ok_response(dd, call_id); driver_free(call_id); } else { js_call *call_data = (js_call *) driver_alloc(sizeof(js_call)); call_data->driver_data = dd; call_data->args = ev->binv[1]; driver_binary_inc_refc(call_data->args); ErlDrvPort port = dd->port; unsigned long thread_key = (unsigned long) port; driver_async(dd->port, (unsigned int *) &thread_key, (asyncfun) run_js, (void *) call_data, NULL); } driver_free(command); }
static void handle_flush(const char *req, int *req_index) { char dirstr[MAXATOMLEN]; if (ei_decode_atom(req, req_index, dirstr) < 0) { send_error_response("einval"); return; } enum uart_direction direction; if (strcmp(dirstr, "receive") == 0) direction = UART_DIRECTION_RECEIVE; else if (strcmp(dirstr, "transmit") == 0) direction = UART_DIRECTION_TRANSMIT; else if (strcmp(dirstr, "both") == 0) direction = UART_DIRECTION_BOTH; else { send_error_response("einval"); return; } if (!uart_is_open(uart)) { send_error_response("ebadf"); return; } if (uart_flush(uart, direction) >= 0) send_ok_response(); else send_error_response(uart_last_error()); }
static void handle_write_completed(int rc, const uint8_t *data) { free((uint8_t *) data); if (rc == 0) send_ok_response(); else send_error_response(uart_last_error()); }
static void handle_close(const char *req, int *req_index) { (void) req; (void) req_index; if (uart_is_open(uart)) uart_close(uart); send_ok_response(); }
static void handle_drain(const char *req, int *req_index) { (void) req; (void) req_index; if (!uart_is_open(uart)) { send_error_response("ebadf"); return; } if (uart_drain(uart) >= 0) send_ok_response(); else send_error_response(uart_last_error()); }
static void handle_configure(const char *req, int *req_index) { struct uart_config config = current_config; if (parse_option_list(req, req_index, &config) < 0) { send_error_response("einval"); return; } if (uart_configure(uart, &config) >= 0) { current_config = config; send_ok_response(); } else { send_error_response(uart_last_error()); } }
static void handle_set_break(const char *req, int *req_index) { int val; if (ei_decode_boolean(req, req_index, &val) < 0) { send_error_response("einval"); return; } if (!uart_is_open(uart)) { send_error_response("ebadf"); return; } if (uart_set_break(uart, !!val) >= 0) send_ok_response(); else send_error_response(uart_last_error()); }
/* * Handle {name, kv_list} * * name is the serial port name * kv_list a list of configuration values (speed, parity, etc.) */ static void handle_open(const char *req, int *req_index) { int term_type; int term_size; if (ei_decode_tuple_header(req, req_index, &term_size) < 0 || term_size != 2) errx(EXIT_FAILURE, ":open requires a 2-tuple"); char name[32]; long binary_len; if (ei_get_type(req, req_index, &term_type, &term_size) < 0 || term_type != ERL_BINARY_EXT || term_size >= (int) sizeof(name) || ei_decode_binary(req, req_index, name, &binary_len) < 0) { // The name is almost certainly too long, so report that it // doesn't exist. send_error_response("enoent"); return; } name[term_size] = '\0'; struct uart_config config = current_config; if (parse_option_list(req, req_index, &config) < 0) { send_error_response("einval"); return; } // If the uart was already open, close and open it again if (uart_is_open(uart)) uart_close(uart); if (uart_open(uart, name, &config) >= 0) { current_config = config; send_ok_response(); } else { send_error_response(uart_last_error()); } }