237 lines
5.0 KiB
C++
237 lines
5.0 KiB
C++
#include "pxt.h"
|
|
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <pthread.h>
|
|
#include <signal.h>
|
|
#include <dirent.h>
|
|
#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;
|
|
}
|
|
|
|
}
|