#include "pxt.h" #include #include #include #include #include #include #include #include #include #include "ev3const.h" namespace pxt { static int usbFD; #define USB_MAGIC 0x3d3f #define USB_SERIAL 1 #define USB_RESTART 2 #define USB_DMESG 3 struct UsbPacket { uint16_t size; uint16_t msgcount; uint16_t magic; uint16_t code; char buf[1024 - 8]; }; void *usbThread(void *) { UsbPacket pkt; UsbPacket resp; while (true) { int len = read(usbFD, &pkt, sizeof(pkt)); if (len <= 4) { sleep_core_us(20000); continue; } resp.msgcount = pkt.msgcount; if (pkt.magic == USB_MAGIC) { if (pkt.code == USB_RESTART) { target_reset(); } else if (pkt.code == USB_DMESG) { dumpDmesg(); } /* resp.magic = pkt.magic; resp.code = pkt.code; resp.size = 8; write(usbFD, &resp, sizeof(resp)); */ } else { resp.magic = 0xffff; resp.size = 4; write(usbFD, &resp, sizeof(resp)); } sleep_core_us(1000); } } static void startUsb() { usbFD = open("/dev/lms_usbdev", O_RDWR, 0666); pthread_t pid; pthread_create(&pid, NULL, usbThread, NULL); pthread_detach(pid); } static void *exitThread(void *) { int fd = open("/dev/lms_ui", O_RDWR, 0666); if (fd < 0) return 0; uint8_t *data = (uint8_t *)mmap(NULL, NUM_BUTTONS, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { close(fd); return 0; } for (;;) { if (data[5]) target_reset(); sleep_core_us(50000); } } static void startExitThread() { pthread_t pid; pthread_create(&pid, NULL, exitThread, NULL); pthread_detach(pid); } void sendUsb(uint16_t code, const char *data, int len) { while (len > 0) { int sz = len; if (sz > 1000) sz = 1000; UsbPacket pkt = {(uint16_t)(6 + sz), 0, USB_MAGIC, code, {}}; memcpy(pkt.buf, data, sz); write(usbFD, &pkt, sizeof(pkt)); len -= sz; data += sz; } } void sendSerial(const char *data, int len) { sendUsb(USB_SERIAL, data, len); } int lmsPid; void stopLMS() { struct dirent *ent; DIR *dir; dir = opendir("/proc"); if (dir == NULL) return; while ((ent = readdir(dir)) != NULL) { int pid = atoi(ent->d_name); if (!pid) continue; char namebuf[100]; snprintf(namebuf, 100, "/proc/%d/cmdline", pid); FILE *f = fopen(namebuf, "r"); if (f) { fread(namebuf, 1, 99, f); if (strcmp(namebuf, "./lms2012") == 0) { lmsPid = pid; } fclose(f); if (lmsPid) break; } } closedir(dir); lmsPid = 0; // disable SIGSTOP for now - rethink if problems with I2C (runs on a thread) if (lmsPid) { DMESG("SIGSTOP to lmsPID=%d", lmsPid); if (kill(lmsPid, SIGSTOP)) DMESG("SIGSTOP failed"); } } void runLMS() { DMESG("re-starting LMS2012"); kill(lmsPid, SIGCONT); sleep_core_us(200000); exit(0); /* chdir("/home/root/lms2012/sys"); for (int fd = 3; fd < 9999; ++fd) close(fd); execl("lms2012", "./lms2012"); exit(100); // should not be reached */ } void stopMotors() { uint8_t cmd[3] = {opOutputStop, 0x0F, 0}; int fd = open("/dev/lms_pwm", O_RDWR); write(fd, cmd, 3); close(fd); } void stopProgram() { uint8_t cmd[1] = {opOutputProgramStop}; int fd = open("/dev/lms_pwm", O_RDWR); write(fd, cmd, 1); close(fd); } extern "C" void target_reset() { tryLockUser(); stopMotors(); stopProgram(); if (lmsPid) runLMS(); else exit(0); } void target_exit() { target_reset(); } void target_startup() { stopLMS(); startUsb(); startExitThread(); } void initKeys() {} static const char *progPath = "/mnt/ramdisk/prjs/BrkProg_SAVE"; // These are disabled except when building File_manager.pdf // % void deletePrjFile(String filename) { const char *d = filename->getUTF8Data(); if (strlen(d) > 500 || strchr(d, '/')) return; char buf[1024]; snprintf(buf, sizeof(buf), "%s/%s", progPath, d); unlink(buf); } // % RefCollection *listPrjFiles() { auto res = Array_::mk(); registerGCObj(res); auto dp = opendir(progPath); for (;;) { dirent *ep = dp ? readdir(dp) : NULL; if (!ep) break; if (ep->d_name[0] == '.') continue; auto str = mkString(ep->d_name, -1); registerGCObj(str); res->head.push((TValue)str); unregisterGCObj(str); } if (dp) closedir(dp); unregisterGCObj(res); return res; } }