Block LMS while running and implemnet own USB HID handling
This commit is contained in:
		
							
								
								
									
										16
									
								
								aux/pxt.lms
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								aux/pxt.lms
									
									
									
									
									
								
							@@ -3,23 +3,23 @@ vmthread  MAIN
 | 
			
		||||
{
 | 
			
		||||
  DATA8   State
 | 
			
		||||
  DATA32  Status
 | 
			
		||||
  //DATA32  Timer
 | 
			
		||||
  DATA32  Timer
 | 
			
		||||
  DATA16 Serial
 | 
			
		||||
 | 
			
		||||
  UI_WRITE(LED,LED_RED)
 | 
			
		||||
  UI_WRITE(LED,LED_ORANGE)
 | 
			
		||||
  UI_DRAW(TEXT,FG_COLOR,48,62,'Starting...')
 | 
			
		||||
  UI_DRAW(UPDATE)
 | 
			
		||||
  // Make sure VM knows that /tmp/serial.txt is open for writing and can stream the content
 | 
			
		||||
  FILE(OPEN_WRITE, '/tmp/serial.txt', Serial)
 | 
			
		||||
  //FILE(OPEN_WRITE, '/tmp/serial.txt', Serial)
 | 
			
		||||
  // Actual filename is patched-in here
 | 
			
		||||
  SYSTEM('XXXXXXXXX', Status)
 | 
			
		||||
Loop:
 | 
			
		||||
  UI_BUTTON(WAIT_FOR_PRESS)
 | 
			
		||||
  UI_BUTTON(SHORTPRESS,BACK_BUTTON,State)
 | 
			
		||||
  JR_FALSE(State,Loop)
 | 
			
		||||
  //UI_BUTTON(WAIT_FOR_PRESS)
 | 
			
		||||
  //UI_BUTTON(SHORTPRESS,BACK_BUTTON,State)
 | 
			
		||||
  //JR_FALSE(State,Loop)
 | 
			
		||||
  //UI_WRITE(LED,LED_RED)
 | 
			
		||||
  //TIMER_WAIT(1000, Timer)
 | 
			
		||||
  //TIMER_READY(Timer)
 | 
			
		||||
  TIMER_WAIT(100, Timer)
 | 
			
		||||
  TIMER_READY(Timer)
 | 
			
		||||
  UI_DRAW(TEXT,FG_COLOR,48,62,'Bye!')
 | 
			
		||||
  UI_DRAW(UPDATE)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,8 @@ eval("if (typeof process === 'object' && process + '' === '[object process]') px
 | 
			
		||||
namespace pxt.editor {
 | 
			
		||||
    // this comes from aux/pxt.lms
 | 
			
		||||
    const rbfTemplate = `
 | 
			
		||||
4c45474f710000006d000100000000001c000000000000000a000000821b028405018130813e8053
 | 
			
		||||
74617274696e672e2e2e008400c002802f746d702f73657269616c2e74787400486080XX00448303
 | 
			
		||||
83010640414082f5ff8405018130813e80427965210084000a
 | 
			
		||||
4c45474f580000006d000100000000001c000000000000000e000000821b038405018130813e8053
 | 
			
		||||
74617274696e672e2e2e0084006080XX00448581644886488405018130813e80427965210084000a
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
    function hf2Async() {
 | 
			
		||||
@@ -43,6 +42,7 @@ namespace pxt.editor {
 | 
			
		||||
                w = w_
 | 
			
		||||
                if (w.isStreaming)
 | 
			
		||||
                    U.userError("please stop the program first")
 | 
			
		||||
                return w.rmAsync(elfPath)
 | 
			
		||||
            }).then(() => {
 | 
			
		||||
                let f = U.stringToUint8Array(atob(resp.outfiles[pxt.outputName()]))
 | 
			
		||||
                return w.flashAsync(elfPath, f)
 | 
			
		||||
@@ -69,6 +69,7 @@ namespace pxt.editor {
 | 
			
		||||
            deployCoreAsync,
 | 
			
		||||
        };
 | 
			
		||||
        initAsync()
 | 
			
		||||
        /*
 | 
			
		||||
            .then(w => w.streamFileAsync("/tmp/serial.txt", buf => {
 | 
			
		||||
                let str = Util.fromUTF8(Util.uint8ArrayToString(buf))
 | 
			
		||||
                window.postMessage({
 | 
			
		||||
@@ -77,6 +78,7 @@ namespace pxt.editor {
 | 
			
		||||
                    data: str
 | 
			
		||||
                }, "*")
 | 
			
		||||
            }))
 | 
			
		||||
        */
 | 
			
		||||
        return Promise.resolve<pxt.editor.ExtensionResult>(res);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,15 @@ namespace pxt.editor {
 | 
			
		||||
        constructor(public io: pxt.HF2.PacketIO) {
 | 
			
		||||
            io.onData = buf => {
 | 
			
		||||
                buf = buf.slice(0, HF2.read16(buf, 0) + 2)
 | 
			
		||||
                if (HF2.read16(buf, 4) == 0x3d3f) {
 | 
			
		||||
                    let code = HF2.read16(buf, 6)
 | 
			
		||||
                    let payload = buf.slice(8)
 | 
			
		||||
                    if (code == 1)
 | 
			
		||||
                        console.log("Serial: " + U.uint8ArrayToString(payload))
 | 
			
		||||
                    else
 | 
			
		||||
                        console.log("Magic: " + code + ": " + U.toHex(payload))
 | 
			
		||||
                    return
 | 
			
		||||
                }
 | 
			
		||||
                //log("DATA: " + U.toHex(buf))
 | 
			
		||||
                this.msgs.push(buf)
 | 
			
		||||
            }
 | 
			
		||||
@@ -56,8 +65,9 @@ namespace pxt.editor {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        talkAsync(buf: Uint8Array, altResponse = 0) {
 | 
			
		||||
            return this.lock.enqueue("talk", () =>
 | 
			
		||||
                this.io.sendPacketAsync(buf)
 | 
			
		||||
            return this.lock.enqueue("talk", () => {
 | 
			
		||||
                this.msgs.drain()
 | 
			
		||||
                return this.io.sendPacketAsync(buf)
 | 
			
		||||
                    .then(() => this.msgs.shiftAsync(1000))
 | 
			
		||||
                    .then(resp => {
 | 
			
		||||
                        if (resp[2] != buf[2] || resp[3] != buf[3])
 | 
			
		||||
@@ -69,7 +79,8 @@ namespace pxt.editor {
 | 
			
		||||
                                U.userError("cmd error: " + resp[6])
 | 
			
		||||
                        }
 | 
			
		||||
                        return resp
 | 
			
		||||
                    }))
 | 
			
		||||
                    })
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        flashAsync(path: string, file: Uint8Array) {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,11 @@
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
void *operator new(size_t size) {
 | 
			
		||||
    return malloc(size);
 | 
			
		||||
@@ -29,8 +34,6 @@ static int startTime;
 | 
			
		||||
static pthread_mutex_t execMutex;
 | 
			
		||||
static pthread_mutex_t eventMutex;
 | 
			
		||||
static pthread_cond_t newEventBroadcast;
 | 
			
		||||
static FILE *dmesgFile;
 | 
			
		||||
static FILE *serialFile;
 | 
			
		||||
 | 
			
		||||
struct Thread {
 | 
			
		||||
    struct Thread *next;
 | 
			
		||||
@@ -46,6 +49,9 @@ struct Thread {
 | 
			
		||||
 | 
			
		||||
static struct Thread *allThreads;
 | 
			
		||||
static struct Event *eventHead, *eventTail;
 | 
			
		||||
static int usbFD;
 | 
			
		||||
static int dmesgPtr;
 | 
			
		||||
static char dmesgBuf[4096];
 | 
			
		||||
 | 
			
		||||
struct Event {
 | 
			
		||||
    struct Event *next;
 | 
			
		||||
@@ -63,27 +69,43 @@ Event *mkEvent(int source, int value) {
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sendSerial(const char *data, int len) {
 | 
			
		||||
    if (!serialFile) {
 | 
			
		||||
        serialFile = fopen("/tmp/serial.txt", "w");
 | 
			
		||||
        if (!serialFile)
 | 
			
		||||
            serialFile = stderr;
 | 
			
		||||
    }
 | 
			
		||||
#define USB_MAGIC 0x3d3f
 | 
			
		||||
#define USB_SERIAL 1
 | 
			
		||||
 | 
			
		||||
    fwrite(data, 1, len, serialFile);
 | 
			
		||||
    fflush(serialFile);
 | 
			
		||||
    fdatasync(fileno(serialFile));
 | 
			
		||||
struct UsbPacket {
 | 
			
		||||
    uint16_t size;
 | 
			
		||||
    uint16_t msgcount;
 | 
			
		||||
    uint16_t magic;
 | 
			
		||||
    uint16_t code;
 | 
			
		||||
    char buf[1000];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void sendUsb(uint16_t code, const char *data, int len) {
 | 
			
		||||
    if (usbFD == 0)
 | 
			
		||||
        usbFD = open("/dev/lms_usbdev", O_RDWR, 0666);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void target_panic(int error_code) {
 | 
			
		||||
    char buf[50];
 | 
			
		||||
    snprintf(buf, sizeof(buf), "\nPANIC %d\n", error_code);
 | 
			
		||||
    sendSerial(buf, strlen(buf));
 | 
			
		||||
    abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void target_reset() {
 | 
			
		||||
    exit(0);
 | 
			
		||||
    DMESG("PANIC %d", error_code);
 | 
			
		||||
    target_reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void startUser() {
 | 
			
		||||
@@ -294,7 +316,7 @@ static void runPoller(Thread *thr) {
 | 
			
		||||
            prev = curr;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
//    disposeThread(thr);
 | 
			
		||||
    //    disposeThread(thr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//%
 | 
			
		||||
@@ -306,14 +328,76 @@ uint32_t afterProgramPage() {
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
void dumpDmesg() {
 | 
			
		||||
    // TODO
 | 
			
		||||
    sendSerial("\nDMESG:\n", 8);
 | 
			
		||||
    sendSerial(dmesgBuf, dmesgPtr);
 | 
			
		||||
    sendSerial("\n\n", 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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, 1000, "/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
 | 
			
		||||
    */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void target_reset() {
 | 
			
		||||
    if (lmsPid)
 | 
			
		||||
        runLMS();
 | 
			
		||||
    else
 | 
			
		||||
        exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void screen_init();
 | 
			
		||||
void initRuntime() {
 | 
			
		||||
    daemon(1, 1);
 | 
			
		||||
    // daemon(1, 1);
 | 
			
		||||
    startTime = currTime();
 | 
			
		||||
    DMESG("runtime starting...");
 | 
			
		||||
    stopLMS();
 | 
			
		||||
    pthread_t disp;
 | 
			
		||||
    pthread_create(&disp, NULL, evtDispatcher, NULL);
 | 
			
		||||
    pthread_detach(disp);
 | 
			
		||||
@@ -322,21 +406,38 @@ void initRuntime() {
 | 
			
		||||
    startUser();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dmesg(const char *format, ...) {
 | 
			
		||||
    char buf[500];
 | 
			
		||||
static FILE *dmesgFile;
 | 
			
		||||
 | 
			
		||||
void dmesgRaw(const char *buf, uint32_t len) {
 | 
			
		||||
    if (!dmesgFile) {
 | 
			
		||||
        dmesgFile = fopen("/tmp/dmesg.txt", "w");
 | 
			
		||||
        if (!dmesgFile)
 | 
			
		||||
            dmesgFile = stderr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (len > sizeof(dmesgBuf) / 2)
 | 
			
		||||
        return;
 | 
			
		||||
    if (dmesgPtr + len > sizeof(dmesgBuf)) {
 | 
			
		||||
        dmesgPtr = 0;
 | 
			
		||||
    }
 | 
			
		||||
    memcpy(dmesgBuf + dmesgPtr, buf, len);
 | 
			
		||||
    dmesgPtr += len;
 | 
			
		||||
    fwrite(buf, 1, len, dmesgFile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dmesg(const char *format, ...) {
 | 
			
		||||
    char buf[500];
 | 
			
		||||
 | 
			
		||||
    snprintf(buf, sizeof(buf), "[%8d] ", current_time_ms());
 | 
			
		||||
    dmesgRaw(buf, strlen(buf));
 | 
			
		||||
 | 
			
		||||
    va_list arg;
 | 
			
		||||
    va_start(arg, format);
 | 
			
		||||
    vsnprintf(buf, sizeof(buf), format, arg);
 | 
			
		||||
    va_end(arg);
 | 
			
		||||
    dmesgRaw(buf, strlen(buf));
 | 
			
		||||
    dmesgRaw("\n", 1);
 | 
			
		||||
 | 
			
		||||
    fprintf(dmesgFile, "[%8d] %s\n", current_time_ms(), buf);
 | 
			
		||||
    fflush(dmesgFile);
 | 
			
		||||
    fdatasync(fileno(dmesgFile));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user