int svrapp::client_ack(param_list * pl){ log_out(log_debug, "client_ack::json (%s)\n", pl->content); uint cnt_id = 0; char cnt_serial[128] = {0}; if(parse_serial(pl->serial, cnt_id, cnt_serial, sizeof(cnt_serial)) < 0){ log_out(log_error, "client_ack::json invalid serial %s\n", pl->serial); return -1; } std::map<uint, app_connection*>::iterator it = m_cntmap.find(cnt_id); if (it == m_cntmap.end()){ log_out(log_error, "client_ack::client(%u) is off\n", cnt_id); return -1; } cJSON * jserror = cJSON_GetObjectItem(pl->json, "error"); cJSON * jsreason = cJSON_GetObjectItem(pl->json, "reason"); if(!jserror || !jsreason){ log_out(log_error, "client_ack::no error item\n"); return -1; } cJSON_DeleteItemFromObject(pl->jsdata, "device_id"); cJSON_DeleteItemFromObject(pl->jsdata, "company_id"); char * out = cJSON_PrintUnformatted(pl->jsdata); post_ack(it->second, pl->cmd, cnt_serial, jserror->valueint, jsreason->valuestring, out); return 0; }
int svrapp::client_ack(param_list * pl){ log_out(log_debug, "client_ack::json (%s)\n", pl->content); uint realplay_id = 0; char cnt_serial[128] = {0}; if(parse_serial(pl->serial, realplay_id, cnt_serial, sizeof(cnt_serial)) < 0){ log_out(log_error, "client_ack::json invalid serial %s\n", pl->serial); return -1; } std::map<uint, app_connection*>::iterator it = m_cntmap.find(realplay_id); if (it == m_cntmap.end()){ log_out(log_error, "client_ack::client(%u) is off\n", realplay_id); return -1; } cJSON * jserror = cJSON_GetObjectItem(pl->json, "error"); cJSON * jsreason = cJSON_GetObjectItem(pl->json, "reason"); if(!jserror || !jsreason){ log_out(log_error, "client_ack::no error item\n"); return -1; } if(strcmp(pl->cmd, start_realplay_ack) == 0){ start_realplay_ackx(realplay_id, jserror->valueint, it->second); } else if(strcmp(pl->cmd, stop_realplay_ack) == 0){ stop_realplay_ackx(realplay_id, jserror->valueint, it->second); } cJSON_DeleteItemFromObject(pl->jsdata, "device_id"); cJSON_DeleteItemFromObject(pl->jsdata, "company_id"); char * out = cJSON_PrintUnformatted(pl->jsdata); realplay_info * rpif = (realplay_info*)it->second->get_context(); if(rpif){ rpif->post_ack(pl->cmd, cnt_serial, jserror->valueint, jsreason->valuestring, out); } free(out); return 0; }
///@brief Argp Parser Function for example-specific command line options ///@return Zero or error code specifying how to continue static error_t dummy_parse_opt( const int key, ///< [in] Key field from the options vector char *arg, ///< [in,out] Value given as option argument struct argp_state *state) ///< [in,out] Parsing state for use by parser { // Retreive the input argument from argp_parse struct tool_config *tool = state->input; switch (key) { case OPT_SET_SERIAL: if (0 != parse_serial(&tool->overrides, arg)) { argp_error(state, _("Invalid serial number `%s' specified."), arg); } break; default: return ARGP_ERR_UNKNOWN; } return 0; }
int main(int argc, char **argv) { int expected_size = 0; unsigned int transfer_size = 0; enum mode mode = MODE_NONE; struct dfu_status status; libusb_context *ctx; struct dfu_file file; char *end; int final_reset = 0; int detach_unsupported = 0; int ret; int dfuse_device = 0; int fd; const char *dfuse_options = NULL; int detach_delay = 5; uint16_t runtime_vendor; uint16_t runtime_product; memset(&file, 0, sizeof(file)); /* make sure all prints are flushed */ setvbuf(stdout, NULL, _IONBF, 0); while (1) { int c, option_index = 0; c = getopt_long(argc, argv, "hVvlenE:d:p:c:i:a:S:t:U:D:Rs:Z:", opts, &option_index); if (c == -1) break; switch (c) { case 'h': help(); break; case 'V': mode = MODE_VERSION; break; case 'v': verbose++; break; case 'l': mode = MODE_LIST; break; case 'e': mode = MODE_DETACH; match_iface_alt_index = 0; match_iface_index = 0; break; case 'E': detach_delay = atoi(optarg); break; case 'n': detach_unsupported = 1; break; case 'd': parse_vendprod(optarg); break; case 'p': /* Parse device path */ ret = resolve_device_path(optarg); if (ret < 0) errx(EX_SOFTWARE, "Unable to parse '%s'", optarg); if (!ret) errx(EX_SOFTWARE, "Cannot find '%s'", optarg); break; case 'c': /* Configuration */ match_config_index = atoi(optarg); break; case 'i': /* Interface */ match_iface_index = atoi(optarg); break; case 'a': /* Interface Alternate Setting */ match_iface_alt_index = strtoul(optarg, &end, 0); if (*end) { match_iface_alt_name = optarg; match_iface_alt_index = -1; } break; case 'S': parse_serial(optarg); break; case 't': transfer_size = atoi(optarg); break; case 'U': mode = MODE_UPLOAD; file.name = optarg; break; case 'Z': expected_size = atoi(optarg); break; case 'D': mode = MODE_DOWNLOAD; file.name = optarg; break; case 'R': final_reset = 1; break; case 's': dfuse_options = optarg; break; default: help(); break; } } print_version(); if (mode == MODE_VERSION) { exit(0); } if (mode == MODE_NONE) { fprintf(stderr, "You need to specify one of -D or -U\n"); help(); } if (match_config_index == 0) { /* Handle "-c 0" (unconfigured device) as don't care */ match_config_index = -1; } if (mode == MODE_DOWNLOAD) { dfu_load_file(&file, MAYBE_SUFFIX, MAYBE_PREFIX); /* If the user didn't specify product and/or vendor IDs to match, * use any IDs from the file suffix for device matching */ if (match_vendor < 0 && file.idVendor != 0xffff) { match_vendor = file.idVendor; printf("Match vendor ID from file: %04x\n", match_vendor); } if (match_product < 0 && file.idProduct != 0xffff) { match_product = file.idProduct; printf("Match product ID from file: %04x\n", match_product); } } ret = libusb_init(&ctx); if (ret) errx(EX_IOERR, "unable to initialize libusb: %i", ret); if (verbose > 2) { libusb_set_debug(ctx, 255); } probe_devices(ctx); if (mode == MODE_LIST) { list_dfu_interfaces(); exit(0); } if (dfu_root == NULL) { errx(EX_IOERR, "No DFU capable USB device available"); } else if (dfu_root->next != NULL) { /* We cannot safely support more than one DFU capable device * with same vendor/product ID, since during DFU we need to do * a USB bus reset, after which the target device will get a * new address */ errx(EX_IOERR, "More than one DFU capable USB device found! " "Try `--list' and specify the serial number " "or disconnect all but one device\n"); } /* We have exactly one device. Its libusb_device is now in dfu_root->dev */ printf("Opening DFU capable USB device...\n"); ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); if (ret || !dfu_root->dev_handle) errx(EX_IOERR, "Cannot open device"); printf("ID %04x:%04x\n", dfu_root->vendor, dfu_root->product); printf("Run-time device DFU version %04x\n", libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); /* Transition from run-Time mode to DFU mode */ if (!(dfu_root->flags & DFU_IFF_DFU)) { int err; /* In the 'first round' during runtime mode, there can only be one * DFU Interface descriptor according to the DFU Spec. */ /* FIXME: check if the selected device really has only one */ runtime_vendor = dfu_root->vendor; runtime_product = dfu_root->product; printf("Claiming USB DFU Runtime Interface...\n"); if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { errx(EX_IOERR, "Cannot claim interface %d", dfu_root->interface); } if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, 0) < 0) { errx(EX_IOERR, "Cannot set alt interface zero"); } printf("Determining device status: "); err = dfu_get_status(dfu_root, &status); if (err == LIBUSB_ERROR_PIPE) { printf("Device does not implement get_status, assuming appIDLE\n"); status.bStatus = DFU_STATUS_OK; status.bwPollTimeout = 0; status.bState = DFU_STATE_appIDLE; status.iString = 0; } else if (err < 0) { errx(EX_IOERR, "error get_status"); } else { printf("state = %s, status = %d\n", dfu_state_to_string(status.bState), status.bStatus); } milli_sleep(status.bwPollTimeout); switch (status.bState) { case DFU_STATE_appIDLE: case DFU_STATE_appDETACH: if (!detach_unsupported) { printf("Device really in Runtime Mode, send DFU " "detach request...\n"); if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { warnx("error detaching"); } } if (dfu_root->func_dfu.bmAttributes & USB_DFU_WILL_DETACH) { printf("Device will detach and reattach...\n"); } else { printf("Resetting USB...\n"); ret = libusb_reset_device(dfu_root->dev_handle); if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) errx(EX_IOERR, "error resetting " "after detach"); } break; case DFU_STATE_dfuERROR: printf("dfuERROR, clearing status\n"); if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) { errx(EX_IOERR, "error clear_status"); } /* fall through */ default: warnx("WARNING: Runtime device already in DFU state ?!?"); libusb_release_interface(dfu_root->dev_handle, dfu_root->interface); goto dfustate; } libusb_release_interface(dfu_root->dev_handle, dfu_root->interface); libusb_close(dfu_root->dev_handle); dfu_root->dev_handle = NULL; if (mode == MODE_DETACH) { libusb_exit(ctx); exit(0); } /* keeping handles open might prevent re-enumeration */ disconnect_devices(); milli_sleep(detach_delay * 1000); /* Change match vendor and product to impossible values to force * only DFU mode matches in the following probe */ match_vendor = match_product = 0x10000; probe_devices(ctx); if (dfu_root == NULL) { errx(EX_IOERR, "Lost device after RESET?"); } else if (dfu_root->next != NULL) { errx(EX_IOERR, "More than one DFU capable USB device found! " "Try `--list' and specify the serial number " "or disconnect all but one device"); } /* Check for DFU mode device */ if (!(dfu_root->flags | DFU_IFF_DFU)) errx(EX_SOFTWARE, "Device is not in DFU mode"); printf("Opening DFU USB Device...\n"); ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle); if (ret || !dfu_root->dev_handle) { errx(EX_IOERR, "Cannot open device"); } } else { /* we're already in DFU mode, so we can skip the detach/reset * procedure */ /* If a match vendor/product was specified, use that as the runtime * vendor/product, otherwise use the DFU mode vendor/product */ runtime_vendor = match_vendor < 0 ? dfu_root->vendor : match_vendor; runtime_product = match_product < 0 ? dfu_root->product : match_product; } dfustate: #if 0 printf("Setting Configuration %u...\n", dfu_root->configuration); if (libusb_set_configuration(dfu_root->dev_handle, dfu_root->configuration) < 0) { errx(EX_IOERR, "Cannot set configuration"); } #endif printf("Claiming USB DFU Interface...\n"); if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) { errx(EX_IOERR, "Cannot claim interface"); } printf("Setting Alternate Setting #%d ...\n", dfu_root->altsetting); if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, dfu_root->altsetting) < 0) { errx(EX_IOERR, "Cannot set alternate interface"); } status_again: printf("Determining device status: "); if (dfu_get_status(dfu_root, &status ) < 0) { errx(EX_IOERR, "error get_status"); } printf("state = %s, status = %d\n", dfu_state_to_string(status.bState), status.bStatus); milli_sleep(status.bwPollTimeout); switch (status.bState) { case DFU_STATE_appIDLE: case DFU_STATE_appDETACH: errx(EX_IOERR, "Device still in Runtime Mode!"); break; case DFU_STATE_dfuERROR: printf("dfuERROR, clearing status\n"); if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) { errx(EX_IOERR, "error clear_status"); } goto status_again; break; case DFU_STATE_dfuDNLOAD_IDLE: case DFU_STATE_dfuUPLOAD_IDLE: printf("aborting previous incomplete transfer\n"); if (dfu_abort(dfu_root->dev_handle, dfu_root->interface) < 0) { errx(EX_IOERR, "can't send DFU_ABORT"); } goto status_again; break; case DFU_STATE_dfuIDLE: printf("dfuIDLE, continuing\n"); break; default: break; } if (DFU_STATUS_OK != status.bStatus ) { printf("WARNING: DFU Status: '%s'\n", dfu_status_to_string(status.bStatus)); /* Clear our status & try again. */ if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) errx(EX_IOERR, "USB communication error"); if (dfu_get_status(dfu_root, &status) < 0) errx(EX_IOERR, "USB communication error"); if (DFU_STATUS_OK != status.bStatus) errx(EX_SOFTWARE, "Status is not OK: %d", status.bStatus); milli_sleep(status.bwPollTimeout); } printf("DFU mode device DFU version %04x\n", libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion)); if (dfu_root->func_dfu.bcdDFUVersion == libusb_cpu_to_le16(0x11a)) dfuse_device = 1; /* If not overridden by the user */ if (!transfer_size) { transfer_size = libusb_le16_to_cpu( dfu_root->func_dfu.wTransferSize); if (transfer_size) { printf("Device returned transfer size %i\n", transfer_size); } else { errx(EX_IOERR, "Transfer size must be specified"); } } #ifdef HAVE_GETPAGESIZE /* autotools lie when cross-compiling for Windows using mingw32/64 */ #ifndef __MINGW32__ /* limitation of Linux usbdevio */ if ((int)transfer_size > getpagesize()) { transfer_size = getpagesize(); printf("Limited transfer size to %i\n", transfer_size); } #endif /* __MINGW32__ */ #endif /* HAVE_GETPAGESIZE */ if (transfer_size < dfu_root->bMaxPacketSize0) { transfer_size = dfu_root->bMaxPacketSize0; printf("Adjusted transfer size to %i\n", transfer_size); } switch (mode) { case MODE_UPLOAD: /* open for "exclusive" writing */ fd = open(file.name, O_WRONLY | O_BINARY | O_CREAT | O_EXCL | O_TRUNC, 0666); if (fd < 0) err(EX_IOERR, "Cannot open file %s for writing", file.name); if (dfuse_device || dfuse_options) { if (dfuse_do_upload(dfu_root, transfer_size, fd, dfuse_options) < 0) exit(1); } else { if (dfuload_do_upload(dfu_root, transfer_size, expected_size, fd) < 0) { exit(1); } } close(fd); break; case MODE_DOWNLOAD: if (((file.idVendor != 0xffff && file.idVendor != runtime_vendor) || (file.idProduct != 0xffff && file.idProduct != runtime_product)) && ((file.idVendor != 0xffff && file.idVendor != dfu_root->vendor) || (file.idProduct != 0xffff && file.idProduct != dfu_root->product))) { errx(EX_IOERR, "Error: File ID %04x:%04x does " "not match device (%04x:%04x or %04x:%04x)", file.idVendor, file.idProduct, runtime_vendor, runtime_product, dfu_root->vendor, dfu_root->product); } if (dfuse_device || dfuse_options || file.bcdDFU == 0x11a) { if (dfuse_do_dnload(dfu_root, transfer_size, &file, dfuse_options) < 0) exit(1); } else { if (dfuload_do_dnload(dfu_root, transfer_size, &file) < 0) exit(1); } break; case MODE_DETACH: if (detach_unsupported) break; ret = dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000); if (ret < 0) { warnx("can't detach"); } break; default: errx(EX_IOERR, "Unsupported mode: %u", mode); break; } if (final_reset) { if (detach_unsupported) { // STM32 DFU devices dont support DFU_DETACH // Instead, force the device into STATE_DFU_MANIFEST_WAIT_RESET // by sending a download request of size 0 and checking the state if (dfu_download(dfu_root->dev_handle, dfu_root->interface, 0x0, 0x0, NULL)) { warnx("Failure forcing a manifest"); } else { if (dfu_get_status(dfu_root, &status) < 0) { warnx("Unable to check status after manifest"); } else { printf("state = %s, status = %d\n", dfu_state_to_string(status.bState), status.bStatus); if (status.bState != STATE_DFU_MANIFEST) { warnx("Device should be in manifest state"); } } } } else { if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) { /* Even if detach failed, just carry on to leave the device in a known state */ warnx("can't detach"); } } printf("Resetting USB to switch back to runtime mode\n"); ret = libusb_reset_device(dfu_root->dev_handle); if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) { errx(EX_IOERR, "error resetting after download"); } } libusb_close(dfu_root->dev_handle); dfu_root->dev_handle = NULL; libusb_exit(ctx); return (0); }
static int parse_header(void *addr, int len) { struct cb_header *header; unsigned char *ptr = (unsigned char *)addr; int i; for (i = 0; i < len; i += 16, ptr += 16) { header = (struct cb_header *)ptr; if (!strncmp((const char *)header->signature, "LBIO", 4)) break; } /* We walked the entire space and didn't find anything. */ if (i >= len) return -1; if (!header->table_bytes) return 0; /* FIXME: Check the checksum. */ if (ipchksum((uint16_t *) header, sizeof(*header))) return -1; if (ipchksum((uint16_t *) (ptr + sizeof(*header)), header->table_bytes) != header->table_checksum) return -1; /* Now, walk the tables. */ ptr += header->header_bytes; for (i = 0; i < header->table_entries; i++) { struct cb_record *rec = (struct cb_record *)ptr; switch (rec->tag) { case CB_TAG_FORWARD: return parse_header((void *)(unsigned long)((struct cb_forward *)rec)->forward, 1); break; case CB_TAG_MEMORY: parse_memory(ptr); break; case CB_TAG_MAINBOARD: parse_mainboard(ptr); break; case CB_TAG_VERSION: case CB_TAG_EXTRA_VERSION: case CB_TAG_BUILD: case CB_TAG_COMPILE_TIME: case CB_TAG_COMPILE_BY: case CB_TAG_COMPILE_HOST: case CB_TAG_COMPILE_DOMAIN: case CB_TAG_COMPILER: case CB_TAG_LINKER: case CB_TAG_ASSEMBLER: parse_strings(ptr); break; case CB_TAG_SERIAL: parse_serial(ptr); break; case CB_TAG_CONSOLE: parse_console(ptr); break; default: break; } ptr += rec->size; } return 1; }
int main(void) { DDRC = 0x3f; // data direction PORTC = 0x3f; // LEDs and buzzer off // timer 1 ctrl: 7654=0000 (no pins), 32=00 (no irq), 10=00 (ocr1a cmp) TCCR1A = 0; // timer 1 ctrl: 76=00 (no pin), 43=01 (ocr1a cmp), 210=001 (no prescaler) TCCR1B = (1<<WGM12) | (1<<CS10); // timer comparison, less than 150 is too fast for this CPU. 156 = 10/64 ms OCR1A = 156; // enable timer 1 output compare A match TIMSK = 1<<OCIE1A; // uart: U2X=1 and UBRR=0,12 means 9600 baud. With a 1-MHz clock, this is // the highest reliable speed supported by Atmega chips (see spec p. 156). UBRRH = 0; // 9600 baud (if U2X=1) UBRRL = 12; UCSRA = (1<<U2X); // double-speed baudrate set UCSRB = (1<<RXEN) | (1<<TXEN); // enable receiver&transmitter UCSRC = (1<<URSEL) | (3<<UCSZ0); // frame format: 8 data, 1 stop char *p = (char *)action; // clear all actions, dark int i; for (i=0; i < sizeof(action); i++) p[i] = 0; set_default_actions(); // some interesting defaults serial_len = 0; // prime serial command buffer sei(); // enable timer interrupts for (;;) { // event loop if (need_next) { // bit is done, do next recalculate(); need_next = false; } if (UCSRA & (1<<RXC)) { // serial byte received uchar data = UDR; // fetch byte from host if (serial_len == 0) { // first char: if (data != '=' && // = define action data != '+' && // + start action data != '-') // - stop action data = '?'; else serial_buf[serial_len++] = data; } else { // following char: if (data == '\t' || data == ' ') // skip whitespace ; else if (data == '\n' || // newline: parse cmd data == '\r') { serial_buf[serial_len] = 0; parse_serial(); serial_len = 0; } else // other char: store if (serial_len > sizeof(serial_buf)-2) data = '?'; else serial_buf[serial_len++] = data; } while (!(UCSRA & (1<<UDRE))); // wait for tx ready UDR = data; // echo byte } } return 0; }
/** Main program entry point. This routine contains the overall program flow */ int main(void) { initialize(); //Configures Ports, sets default values, etc. //Loop Forever for (;;) { //we add data starting with an '.' to the buffer until we get the newline character. fgets(input, sizeof(input), stdin); //Get the actual input (reads up to and including newline character) cmd = input[1]; //command char is always the first char of the input data after the '.' //Command = 'q' - Query for the current status if (cmd == 'q') { memset(input, 0, sizeof(input)); //Clear previous input fprintf(stdout, ".q%d,%d\n", FIRMWARE_VERSION, NUM_MOTORS); //ACK w/ Firmware Version, # of Motors } //Command = 'l' - Command to Control Debug LED else if (cmd == 'l') { if (input[2] == '1') DEBUG_LED_ON(); //Turn LED On else if (input[2] == '0') DEBUG_LED_OFF(); //Turn LED Off memset(input, 0, sizeof(input)); //Clear previous input fprintf(stdout, ".l%d\n", DEBUG_LED_STATE()); //ACK } //Command = 'v' - Sets all motor speeds //Comma separated entries telling all motors to set certain speeds //Assumes motor IDs are 0 <-> NUM_MOTORS-1 else if (cmd == 'v') { parse_serial(); //Read the input string to an array of values memset(input, 0, sizeof(input)); //Clear previous input //send those speed commands for (int i = 0; i<NUM_MOTORS; i++) { ax12SetRegister2(i, AX_GOAL_SPEED_L, vals[i]); } _delay_ms(25); //Only after we have commanded all the speeds, can we check the status fprintf(stdout, ".v"); //ACK Character //Send ACK Info for (int i = 0; i<NUM_MOTORS; i++) { fprintf(stdout, "%d", ax12GetRegister(i, AX_GOAL_SPEED_L, 2)); //Return velocity setting if (i<NUM_MOTORS-1) fprintf(stdout, ","); //Print delimiter } fprintf(stdout, "\n"); //ACK Newline } //Command = 'c' - Command all the motors to a new position //Comma separated entries telling all motors to move to positions from 0-1023 //Assumes motor IDs are 0 <-> NUM_MOTORS-1 else if (cmd == 'c') { parse_serial(); //Read the input string to an array of positions memset(input, 0, sizeof(input)); //Clear previous input //send those position commands for (int i = 0; i<NUM_MOTORS; i++) { ax12SetRegister2(i, AX_GOAL_POSITION_L, vals[i]); } //Only after we have commanded all the positions, can we check the status fprintf(stdout, ".c"); //ACK Character //Send ACK Info for (int i = 0; i<NUM_MOTORS; i++) { while(ax12GetRegister(i,AX_MOVING,1)); //Wait for this motor to finish moving fprintf(stdout, "%d", ax12GetRegister(i, AX_PRESENT_POSITION_L, 2)); //Return the present position if (i<NUM_MOTORS-1) fprintf(stdout, ","); //Print delimiter } fprintf(stdout, "\n"); //ACK Newline } } }