#include #include #include #include #include #include #include #include #include #include #include #include #define DRS232TEST 0 struct log_info_cat osmo_rs232_test_cat[] = { [DRS232TEST] = { .name = "DRS232TEST", .description = "rs232 test", .color = "\033[1;35m", .enabled = 1, .loglevel = LOGL_DEBUG, }, }; const struct log_info osmo_rs232_test_log_info = { .filter_fn = NULL, .cat = osmo_rs232_test_cat, .num_cat = ARRAY_SIZE(osmo_rs232_test_cat), }; static struct osmo_rs232 *r; void sighandler(int foo) { LOGP(DRS232TEST, LOGL_NOTICE, "closing rs232.\n"); osmo_rs232_close(r); osmo_rs232_destroy(r); exit(EXIT_SUCCESS); } static int read_cb(struct osmo_rs232 *r) { struct msgb *msg; LOGP(DRS232TEST, LOGL_DEBUG, "received data from rs232\n"); msg = msgb_alloc(1024, "rs232/test"); if (msg == NULL) { LOGP(DRS232TEST, LOGL_ERROR, "cannot allocate message\n"); return 0; } if (osmo_rs232_read(r, msg) < 0) { LOGP(DRS232TEST, LOGL_ERROR, "cannot receive message\n"); return 0; } LOGP(DRS232TEST, LOGL_DEBUG, "received %d bytes\n", msg->len); printf("received %d bytes ", msg->len); int i; printf("("); for (i=0; ilen; i++) printf("\\x%.2x", 0xff & msg->data[i]); printf(") %s\n", msg->data); msgb_free(msg); return 0; } static void *tall_test; /* u-blox6_ReceiverDescriptionProtocolSpec_(GPS.G6-SW-10018).pdf */ /* See Sect 23. */ struct ubx_hdr { uint8_t sync_char1; /* 0xb5 */ uint8_t sync_char2; /* 0x62 */ uint8_t class; uint8_t id; } __attribute__((packed)); static void ubx_header(struct msgb *msg, uint8_t class, uint8_t id) { /* See Sect. 31.24 */ struct ubx_hdr ubxhdr = { .sync_char1 = 0xb5, .sync_char2 = 0x62, .class = class, .id = id, }; memcpy(msg->data, &ubxhdr, sizeof(struct ubx_hdr)); msgb_put(msg, sizeof(struct ubx_hdr)); } /* See Sect 26. */ static void ubx_checksum(struct msgb *msg, uint8_t *ck) { struct ubx_hdr *ubxhdr = (struct ubx_hdr *)msg->data; /* skip sync chars in checksum calculation. */ uint8_t *buf = ((uint8_t *)ubxhdr) + 2; int i; memset(ck, 0, sizeof(uint16_t)); for (i=0; ilen-2; i++) { ck[0] += buf[i]; ck[1] += ck[0]; } } # if OSMO_IS_LITTLE_ENDIAN # define utohl(x) (x) # define utohs(x) (x) # define htoul(x) (x) # define htous(x) (x) # else # if OSMO_IS_BIG_ENDIAN # define utohl(x) __bswap_32 (x) # define utohs(x) __bswap_16 (x) # define htoul(x) __bswap_32 (x) # define htous(x) __bswap_16 (x) # endif # endif static void ubx_payload_start(struct msgb *msg) { uint16_t len = 0; /* make room for payload length. */ memcpy(msg->data + msg->len, &len, sizeof(len)); msgb_put(msg, sizeof(len)); } static void ubx_payload_put_u8(struct msgb *msg, uint8_t data) { memcpy(msg->data + msg->len, &data, sizeof(data)); msgb_put(msg, sizeof(data)); } static void ubx_payload_put_le16(struct msgb *msg, uint16_t data) { uint16_t le_data = htous(data); memcpy(msg->data + msg->len, &le_data, sizeof(data)); msgb_put(msg, sizeof(data)); } static void ubx_payload_put_le32(struct msgb *msg, uint32_t data) { uint32_t le_data = htoul(data); memcpy(msg->data + msg->len, &le_data, sizeof(data)); msgb_put(msg, sizeof(data)); } static void ubx_payload_stop(struct msgb *msg) { uint16_t *length = (uint16_t *) &(msg->data[4]); uint8_t checksum[2]; /* length does not includes the header, ID, length. * note that checksum has not been yet added. */ *length = htous(msg->len - 6); ubx_checksum(msg, checksum); memcpy(msg->data + msg->len, checksum, sizeof(checksum)); msgb_put(msg, sizeof(checksum)); } static void cfg_prt(void) { struct msgb *msg; msg = msgb_alloc(512, "CFG-PRT for USB"); if (msg == NULL) exit(EXIT_FAILURE); ubx_header(msg, 0x06, 0x00); /* CFG-PRT */ ubx_payload_start(msg); ubx_payload_put_u8(msg, 0x03); /* Port ID is (=3 USB). */ ubx_payload_put_u8(msg, 0x00); /* Reserved. */ ubx_payload_put_le16(msg, 0x0000); /* TX ready. */ ubx_payload_put_le32(msg, 0x00000000); /* Reserved. */ ubx_payload_put_le32(msg, 0x00000000); /* Reserved. */ ubx_payload_put_le16(msg, 0x0003); /* InProtoMask (NMEA+UBX). */ ubx_payload_put_le16(msg, 0x0001); /* OutProtoMask (UBX). */ ubx_payload_put_le16(msg, 0x0000); /* Flags. */ ubx_payload_put_le16(msg, 0x0000); /* Reserved. */ ubx_payload_stop(msg); int i; for (i=0; ilen; i++) printf("\\x%.2x", 0xff & msg->data[i]); printf("\n"); if (osmo_rs232_write(r, msg) < 0) { LOGP(DRS232TEST, LOGL_ERROR, "cannot write to rs232\n"); exit(EXIT_FAILURE); } } static int nmea_checksum(char *nmea_cmd, uint8_t *checksum) { int i, ret = 0; uint8_t from, to; char *start, *end; /* find starting $ */ start = strtok(nmea_cmd, "$"); if (start == NULL) return -1; from = start - nmea_cmd; end = strtok(start+1, "*"); if (end == NULL) return -1; to = end - nmea_cmd; ret = (uint8_t)nmea_cmd[0]; for (i=from+1; idata, nmea_cmd, strlen(nmea_cmd)); msgb_put(msg, strlen(nmea_cmd)); if (osmo_rs232_write(r, msg) < 0) { LOGP(DRS232TEST, LOGL_ERROR, "cannot write to rs232\n"); exit(EXIT_FAILURE); } } static void cfg_tp5(void) { struct msgb *msg; msg = msgb_alloc(512, "CFG-TP5 for USB"); if (msg == NULL) exit(EXIT_FAILURE); ubx_header(msg, 0x06, 0x31); /* CFG-TP5 */ ubx_payload_start(msg); ubx_payload_put_u8(msg, 0x01); /* TIMEPULSE2 (=1) */ ubx_payload_put_u8(msg, 0x00); /* Reserved. */ ubx_payload_put_le16(msg, 0x0000); /* Reserved. */ ubx_payload_put_le16(msg, 0); /* Antenna Delay (ns) */ ubx_payload_put_le16(msg, 0); /* RF Group Delay (ns) */ ubx_payload_put_le32(msg, 8192000); /* freqPeriod (Hz/us) */ ubx_payload_put_le32(msg, 8192000); /* freqPeriodLoc (Hz/us) */ ubx_payload_put_le32(msg, 0x80000000); /* pulseLenRation: 1/2^-32 (us() */ ubx_payload_put_le32(msg, 0x80000000); /* pulseLenRationLock: 1/2^-32 (us() */ ubx_payload_put_le32(msg, 0); /* userConfigDelay (ns) */ ubx_payload_put_le32(msg, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); /* flags: bits 0, 1 and 3. */ ubx_payload_stop(msg); int i; for (i=0; ilen; i++) printf("\\x%.2x", 0xff & msg->data[i]); printf("\n"); if (osmo_rs232_write(r, msg) < 0) { LOGP(DRS232TEST, LOGL_ERROR, "cannot write to rs232\n"); exit(EXIT_FAILURE); } } static int kbd_cb(struct osmo_fd *fd, unsigned int what) { char buf[1024]; int ret, val; ret = read(STDIN_FILENO, buf, sizeof(buf)); if (ret < 0) { LOGP(DRS232TEST, LOGL_ERROR, "cannot write to read from " "keyboard\n"); exit(EXIT_FAILURE); } val = atoi(buf); switch(val) { case 1: printf("sending command PUBX to switch to UBX mode\n"); send_pubx(); break; case 2: printf("sending command TP5\n"); cfg_tp5(); break; case 3: printf("sending command CFG-PRT\n"); cfg_prt(); break; default: printf("wrong option: select 1, 2 or 3\n"); break; } return 0; } int main(void) { struct osmo_fd *kbd_ofd; int rc; tall_test = talloc_named_const(NULL, 1, "osmo_rs232_test"); msgb_talloc_ctx_init(tall_test, 0); osmo_init_logging2(tall_test, &osmo_rs232_test_log_info); log_set_log_level(osmo_stderr_target, LOGL_NOTICE); r = osmo_rs232_create(tall_test); if (r == NULL) { LOGP(DRS232TEST, LOGL_ERROR, "cannot create rs232 object\n"); exit(EXIT_FAILURE); } osmo_rs232_set_serial_port(r, "/dev/ttyACM0"); osmo_rs232_set_baudrate(r, 9600); osmo_rs232_set_delay_us(r, 3330); osmo_rs232_set_read_cb(r, read_cb); if (osmo_rs232_open(r) < 0) { LOGP(DRS232TEST, LOGL_ERROR, "cannot open rs232\n"); exit(EXIT_FAILURE); } LOGP(DRS232TEST, LOGL_NOTICE, "Entering main loop\n"); kbd_ofd = talloc_zero(tall_test, struct osmo_fd); if (!kbd_ofd) { LOGP(DRS232TEST, LOGL_ERROR, "OOM\n"); exit(EXIT_FAILURE); } osmo_fd_setup(kbd_ofd, STDIN_FILENO, OSMO_FD_READ, kbd_cb, NULL, 0); rc = osmo_fd_register(kbd_ofd); if (rc < 0) { LOGP(DRS232TEST, LOGL_ERROR, "FD Register\n"); exit(EXIT_FAILURE); } while(1) { osmo_select_main(0); } }