Compare commits

...

22 Commits

Author SHA1 Message Date
f4660b4366 0.0.3 2017-08-04 15:25:45 -07:00
a4be9f07ea Add robots no index 2017-08-04 15:25:33 -07:00
0c8661808b 0.0.2 2017-08-04 15:16:21 -07:00
b234337dda Update styles 2017-08-04 15:14:24 -07:00
c9cdd3112a 0.0.1 2017-08-04 15:03:26 -07:00
fe7e3a8790 Update to latest pxt-core and pxt-common-packages with codalnext changes 2017-08-04 15:03:14 -07:00
8321c76f4c Use the correct size limit for CRAMFS (10M) 2017-07-27 21:11:23 +01:00
227f9614b0 Strip lego- prefix from files on the brick 2017-07-27 21:10:52 +01:00
de0b5f0d86 Allow writing to currently executing files 2017-07-27 20:42:28 +01:00
abdb21f2a0 Update readme 2017-07-27 14:36:01 +01:00
b16f659ea1 Start user app by invoking .rbf file (via added ioctl on usbdev) 2017-07-27 14:31:23 +01:00
34db42b469 Remove UF2 file repetition 2017-07-27 12:50:12 +01:00
3edceb248d Disable DMA in the MUSB driver 2017-07-27 12:49:34 +01:00
8f9b9a5e4e Use kernel log-level 6 by default 2017-07-27 12:49:19 +01:00
14783eadc2 Workaround UF2 driver problems by repeating the file 3 times 2017-07-26 19:14:12 +01:00
5e7754b436 More info about how images are created 2017-07-26 18:57:46 +01:00
c6b4e506d1 Send restart request to uf2d upon usb disconnect 2017-07-26 18:14:26 +01:00
52ef98e249 Add more logging 2017-07-26 10:43:43 +01:00
9a3eec7d4d dmesg logging 2017-07-25 19:09:32 +01:00
d2f6395443 Cleanup logging; remove excessive flush 2017-07-25 18:37:52 +01:00
7960c9f15e Logging fixes 2017-07-25 15:28:28 +01:00
d84b2b187c Remove unnecessary changes; trim down logging 2017-07-25 15:10:06 +01:00
21 changed files with 453 additions and 167 deletions

View File

@ -11,8 +11,9 @@ they are derived from GPLv2 code).
* the `d_usbdev` uses the composite framework to register an additional mass storage function in addtion
to the pre-existing custom USB HID function
* the `g_mass_storage` module has the following changes:
* a bug fixed, where page-misaligned writes would hang
* additional `/sys/.../lun0/active` entry is added, which allows for signaling drive eject to the host
* `d_usbdev` has an additional `ioctl()` to pretend data came from the USB host - this can be used to direct
the VM to do stuff
### Kernel modifications

View File

@ -1,9 +1,10 @@
#!/bin/sh
set -ex
echo Y > /sys/module/printk/parameters/time
cd /mnt/ramdisk/prjs/ko
echo 3 > /proc/sys/kernel/printk
#echo 3 > /proc/sys/kernel/printk
insmod ./nbd.ko
sleep 1
./uf2d > /tmp/uf2d.log 2> /tmp/uf2derr.log
./uf2d /dev/nbd1 > /tmp/uf2d.log 2> /tmp/uf2derr.log
sleep 1
insmod ./d_usbdev.ko file=/dev/nbd0 HostStr=EV3 SerialStr=0016535543af
insmod ./d_usbdev.ko file=/dev/nbd1 HostStr=EV3 SerialStr=0016535543af

View File

@ -38,11 +38,12 @@
// Keep Eclipse happy
#endif
#if 1
#undef dev_vdbg
#undef dev_dbg
#define dev_vdbg(d, args...) printk(args)
#define dev_dbg(d, args...) printk(args)
#endif
/* big enough to hold our biggest descriptor */
#define USB_BUFSIZ 1024

View File

@ -80,9 +80,6 @@ static void ModuleExit(void);
#include <linux/utsname.h>
#include <linux/device.h>
void myReset(void);
static int dUsbInit(void);
static void dUsbExit(void);
static struct fsg_common *fsg_common;
#include "computil.c" // The composite framework used as utility file
@ -546,12 +543,27 @@ static int Device1Mmap(struct file *filp, struct vm_area_struct *vma)
return (ret);
}
#define FEED_DATA _IOC(_IOC_WRITE, 't', 108, 1024)
static int Device1Ioctl(struct inode *pNode, struct file *File, unsigned int Request, unsigned long Pointer)
{
if (Request != FEED_DATA)
return -EINVAL;
copy_from_user(usb_char_buffer_out,(void*)Pointer,1024);
usb_char_out_length = 1024;
return 0;
}
static const struct file_operations Device1Entries =
{
.owner = THIS_MODULE,
.read = Device1Read,
.write = Device1Write,
.mmap = Device1Mmap
.mmap = Device1Mmap,
.ioctl = Device1Ioctl
};
@ -748,8 +760,3 @@ static int msg_bind(struct usb_composite_dev *cdev)
static int msg_config(struct usb_configuration *c) {
return fsg_add(c->cdev, c, fsg_common);
}
void myReset() {
dUsbExit();
dUsbInit();
}

View File

@ -705,6 +705,8 @@ static int do_read(struct fsg_common *common)
u32 amount_left;
loff_t file_offset, file_offset_tmp;
unsigned int amount;
// partial_page handling causes hangs
// same thing in do_write() --mmoskal
//unsigned int partial_page;
ssize_t nread;
@ -731,6 +733,9 @@ static int do_read(struct fsg_common *common)
/* Carry out the file reads */
amount_left = common->data_size_from_cmnd;
LDBG(curlun, "Uread off=%d cnt=%d\n", (int)lba, amount_left);
if (unlikely(amount_left == 0))
return -EIO; /* No default reply */
@ -879,6 +884,8 @@ static int do_write(struct fsg_common *common)
amount_left_to_req = common->data_size_from_cmnd;
amount_left_to_write = common->data_size_from_cmnd;
LDBG(curlun, "Uwrite off=%d cnt=%d\n", (int)lba, amount_left_to_req);
while (amount_left_to_write > 0) {
/* Queue a request for more data from the host */
@ -2403,7 +2410,28 @@ static void fsg_disable(struct usb_function *f)
fsg->common->prev_fsg = fsg->common->fsg;
fsg->common->fsg = fsg;
fsg->common->new_config = 0;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
DBG(common, "fsg_disable filp=%p\n", fsg->common->luns[0].filp);
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE_DISABLE);
}
static void shutdown_server(void) {
DBG(fsg_common, "shutdown_server filp=%p\n", fsg_common->luns[0].filp);
if (fsg_common->luns[0].filp) {
uint32_t buf[512 / 4];
loff_t file_offset_tmp = 512 * 50000; // make sure we're outside of FS area
int i;
// this should shut down the nbd server, so that the caches are flushed
memset(buf, 0, sizeof(buf));
buf[0] = 0x20da6d81;
buf[1] = 0x747e09d4;
fsg_common->luns[0].filp->f_flags |= O_SYNC;
for (i = 0; i < 2; ++i)
vfs_write(fsg_common->luns[0].filp,
(char*)buf, 512, &file_offset_tmp);
}
}
@ -2525,6 +2553,9 @@ static void handle_exception(struct fsg_common *common)
/* SS_RESET_OCCURRED; */
break;
case FSG_STATE_CONFIG_CHANGE_DISABLE:
shutdown_server();
// fall-through
case FSG_STATE_CONFIG_CHANGE:
rc = do_set_config(common, new_config);
if (common->ep0_req_tag != exception_req_tag)
@ -2651,19 +2682,6 @@ static ssize_t fsg_store_active(struct device *dev, struct device_attribute *att
if (sscanf(buf, "%d", &i) != 1)
return -EINVAL;
/*
if (i == 0) {
dUsbExit();
dUsbInit();
}
else if (i == 1) {
do_set_config(fsg_common, 0);
}
else if (i == 2) {
raise_exception(fsg_common, FSG_STATE_CONFIG_CHANGE);
}
*/
if (isActive() != i) {
if (i == 0) {

View File

@ -334,6 +334,7 @@ enum fsg_state {
FSG_STATE_ABORT_BULK_OUT,
FSG_STATE_RESET,
FSG_STATE_INTERFACE_CHANGE,
FSG_STATE_CONFIG_CHANGE_DISABLE,
FSG_STATE_CONFIG_CHANGE,
FSG_STATE_DISCONNECT,
FSG_STATE_EXIT,
@ -749,13 +750,11 @@ static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
struct rw_semaphore *filesem = dev_get_drvdata(dev);
int rc = 0;
#if 0
if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
LDBG(curlun, "eject attempt prevented\n");
return -EBUSY; /* "Door is locked" */
}
#endif
/* Remove a trailing newline */
if (count > 0 && buf[count-1] == '\n')

View File

@ -734,6 +734,5 @@ int rudolf_add(struct usb_composite_dev *cdev, bool autoresume)
rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
return usb_add_config(cdev, &rudolf_driver);
}

14
brick/scripts/README.md Normal file
View File

@ -0,0 +1,14 @@
# Patched EV3 image
The file `ev3-fs.patch` summarizes the changes done to the original V1.09D image.
You can see some text files are edited, the `d_usbdev.ko` is updated (sources in `../kernel`),
`uf2d` added (sources in `../uf2daemon`), and a stock `nbd.ko` module is added.
Additionally, the `edimax01.ko` is replaced by now much more popular `rtl8192cu.ko` (also stock).
The init script has a hook for running a shell script from `/mnt/ramdisk/`. This can be used
for testing different modules etc.
The kernel command line has been modified to:
* disable DMA for the MUSB driver - otherwise the mass storage device is very unstable
* increase the size of dmesg buffer to 128k

View File

@ -0,0 +1,53 @@
diff -ur orig-ev3/etc/init.d/ev3init.sh dev-ev3/etc/init.d/ev3init.sh
--- orig-ev3/etc/init.d/ev3init.sh 1970-01-01 01:00:00.000000000 +0100
+++ dev-ev3/etc/init.d/ev3init.sh 2017-07-27 12:19:43.195041798 +0100
@@ -1,5 +1,7 @@
#!/bin/sh
+echo Y > /sys/module/printk/parameters/time
+
bluetoothd -n > /dev/null 2>&1 &
echo "Setting up VirtualDrive...";
@@ -60,3 +62,6 @@
sleep 2
hciattach /dev/ttyS2 texas 2000000 "flow" "nosleep" $STRING
sdptool add SP
+
+insmod /lib/modules/2.6.33-rc4/kernel/drivers/net/wireless/rtl8192cu.ko
+. /mnt/ramdisk/rc.local || :
Only in orig-ev3/home/root/lms2012/sys: exit~
diff -ur orig-ev3/home/root/lms2012/sys/init dev-ev3/home/root/lms2012/sys/init
--- orig-ev3/home/root/lms2012/sys/init 1970-01-01 01:00:00.000000000 +0100
+++ dev-ev3/home/root/lms2012/sys/init 2017-07-27 12:23:43.072605126 +0100
@@ -5,13 +5,15 @@
var=$(printf 'HostStr=%s SerialStr=%s' $(cat /home/root/lms2012/sys/settings/BrickName) $(cat /home/root/lms2012/sys/settings/BTser))
echo $var > /home/root/lms2012/sys/settings/UsbInfo.dat
+insmod ${PWD}/mod/nbd.ko
+${PWD}/uf2d
insmod ${PWD}/mod/d_iic.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_uart.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_power.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_pwm.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_ui.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_analog.ko `cat /home/root/lms2012/sys/settings/HwId`
-insmod ${PWD}/mod/d_usbdev.ko `cat /home/root/lms2012/sys/settings/UsbInfo.dat`
+insmod ${PWD}/mod/d_usbdev.ko `cat /home/root/lms2012/sys/settings/UsbInfo.dat` file=/dev/nbd0
insmod ${PWD}/mod/d_usbhost.ko
insmod ${PWD}/mod/d_sound.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_bt.ko `cat /home/root/lms2012/sys/settings/HwId`
@@ -29,6 +31,8 @@
chmod 666 /dev/lms_iic
chmod 666 /dev/lms_bt
+echo 4 > /proc/sys/kernel/printk
+
cd ..
ls -R > /dev/null
cd sys
Binary files orig-ev3/home/root/lms2012/sys/mod/d_usbdev.ko and dev-ev3/home/root/lms2012/sys/mod/d_usbdev.ko differ
Only in dev-ev3/home/root/lms2012/sys/mod: nbd.ko
Only in dev-ev3/home/root/lms2012/sys: uf2d
Only in orig-ev3/lib/modules/2.6.33-rc4/kernel/drivers/net/wireless: edimax01.ko
Only in dev-ev3/lib/modules/2.6.33-rc4/kernel/drivers/net/wireless: rtl8192cu.ko

View File

@ -1,14 +1,36 @@
#!/bin/sh
let fs = require("fs")
// we try to use shorter versions of all parameters for the additional parameters to fit
let bootargs = "mem=${memsize} initrd=${filesysaddr},${filesyssize} root=/dev/ram0 rw rootfstype=cramfs console=${console} ip=${ipaddr} lpj=747520 quiet"
let bootnews = "mem=64M initrd=0xC1180000,10M root=1:0 rw rootfstype=cramfs console=${console} lpj=747520 musb_hdrc.use_dma=0 log_buf_len=128k quiet"
let piggy = true
function build() {
let cr = fs.readFileSync("cram.bin")
if (cr.length > 10878976) {
console.log("too big")
if (bootnews.length > bootargs.length) {
console.log("args too long")
return
}
let img = fs.readFileSync("boot.bin")
while (bootnews.length < bootargs.length)
bootnews += " "
let cr = fs.readFileSync("cram.bin")
if (cr.length > 10485760) {
console.log("too big by " + (cr.length - 10485760))
return
}
let img = fs.readFileSync("EV3 Firmware V1.09D.bin")
for (let i = 0; i < bootnews.length; ++i) {
if (img[0x21DDA + i] != bootargs.charCodeAt(i)) {
console.log("boot args mismatch")
return
}
img[0x21DDA + i] = bootnews.charCodeAt(i)
}
let off = 0x250000
if (img[off] != 0x45 || img[off + 1] != 0x3d) {
console.log("bad magic: " + img[off] + " / " + img[off+1])
@ -17,8 +39,8 @@ function build() {
cr.copy(img, off)
let kern = fs.readFileSync("piggy-patched.gzip")
off = 0x0005540f
let kern = fs.readFileSync(piggy ? "piggy-patched.gzip" : "linux/arch/arm/boot/uImage")
off = piggy ? 0x0005540f : 0x00050000
if (img[off] != kern[0] || img[off+1] != kern[1]) {
console.log("bad kernel magic: " + img[off] + " / " + img[off+1])

View File

@ -1,4 +1,9 @@
#!/bin/sh
# dd if=EV3\ Firmware\ V1.09D.bin of=orig.cram bs=65536 skip=37 count=400
sudo cp linux/pxt/uf2daemon/server dev-ev3/home/root/lms2012/sys/uf2d
sudo cp linux/pxt/kernel/d_usbdev.ko dev-ev3/home/root/lms2012/sys/mod/d_usbdev.ko
sudo chown -R root:root dev-ev3/home/root/lms2012
sudo mkfs.cramfs dev-ev3 cram.bin
node img
ls -l firmware.bin

View File

@ -6,4 +6,5 @@ ev3duder up bin/nbd.ko ../prjs/ko/nbd.ko
ev3duder up ins ../prjs/ko/ins
ev3duder exec 'rm ../prjs/ko/uf2d'
ev3duder up bin/uf2d ../prjs/ko/uf2d
#ev3duder exec 'echo . /mnt/ramdisk/prjs/ko/ins > /mnt/ramdisk/rc.local'

View File

@ -19,6 +19,9 @@
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#define max(a, b) \
({ \
@ -36,7 +39,7 @@
#include "uf2.h"
#define DBG printf
#define DBG LOG
typedef struct {
uint8_t JumpInstruction[3];
@ -332,8 +335,7 @@ void addClusterData(ClusterData *c, FsEntry *e) {
c->myfile = e;
DBG("add cluster: flags=%d size=%d numcl=%d name=%s\n", c->flags, (int)c->st.st_size,
c->numclusters, c->name);
DBG("add cluster: flags=%d size=%d numcl=%d", c->flags, (int)c->st.st_size, c->numclusters);
}
FsEntry *addRootText(const char *filename, const char *contents) {
@ -393,7 +395,7 @@ void setFatNames(FsEntry *dirent) {
}
}
DBG("setname: %s [%s] cl=%s @ %d sz=%d dents=%d\n", p->vfatname, p->fatname,
DBG("setname: %s [%s] cl=%s @ %d sz=%d dents=%d", p->vfatname, p->fatname,
p->data ? p->data->name : "(no data)", p->startCluster, p->size, p->numdirentries);
}
}
@ -528,7 +530,7 @@ void readDirData(uint8_t *dest, FsEntry *dirdata, int blkno) {
if (idx >= 16)
break;
// DBG("dir idx=%d %s\n", idx, e->vfatname);
// DBG("dir idx=%d %s", idx, e->vfatname);
for (int i = 0; i < e->numdirentries; ++i, ++idx) {
if (0 <= idx && idx < 16) {
@ -562,15 +564,15 @@ void readDirData(uint8_t *dest, FsEntry *dirdata, int blkno) {
}
void readBlock(uint8_t *dest, int blkno) {
// DBG("readbl %d\n", blkno);
// DBG("readbl %d", blkno);
int blkno0 = blkno;
for (ClusterData *c = firstCluster; c; c = c->cnext) {
// DBG("off=%d sz=%d\n", blkno, c->numclusters);
// DBG("off=%d sz=%d", blkno, c->numclusters);
if (blkno >= c->numclusters) {
blkno -= c->numclusters;
continue;
}
// DBG("readbl off=%d %p\n", blkno, c);
// DBG("readbl off=%d %p", blkno, c);
if (c->dirdata) {
readDirData(dest, c->dirdata, blkno);
} else if (c->flags & F_TEXT) {
@ -592,6 +594,7 @@ void readBlock(uint8_t *dest, int blkno) {
if (fd >= 0) {
lseek(fd, bl->targetAddr, SEEK_SET);
bl->payloadSize = read(fd, bl->data, 256);
close(fd);
} else {
bl->payloadSize = -1;
}
@ -627,6 +630,48 @@ void read_block(uint32_t block_no, uint8_t *data) {
}
}
char rbfPath[300];
uint8_t stopApp[] = {
0x05, 0x00, // size
0x00, 0x00, // seq. no.
0x3f, 0x3d, // usb magic,
0x02, // req. no.
};
uint8_t runStart[] = {0x00, 0x00, // size
0x00, 0x00, // seq. no.
0x00, 0x00, 0x08, // something
0xC0, 0x08, 0x82, 0x01, 0x00, 0x84};
uint8_t runEnd[] = {0x00, 0x60, 0x64, 0x03, 0x01, 0x60, 0x64, 0x00};
#define FEED_DATA _IOC(_IOC_WRITE, 't', 108, 1024)
void startRbf() {
char buf[1024];
memset(buf, 0, sizeof(buf));
memcpy(buf, stopApp, sizeof(stopApp));
int fd = open("/dev/lms_usbdev", O_RDWR);
ioctl(fd, FEED_DATA, buf);
usleep(500000);
int off = 0;
memcpy(buf + off, runStart, sizeof(runStart));
off += sizeof(runStart);
strcpy(buf + off, rbfPath);
off += strlen(rbfPath);
memcpy(buf + off, runEnd, sizeof(runEnd));
off += sizeof(runEnd);
off -= 2;
buf[0] = off & 0xff;
buf[1] = off >> 8;
ioctl(fd, FEED_DATA, buf);
close(fd);
}
#define MAX_BLOCKS 8000
typedef struct {
uint32_t numBlocks;
@ -634,80 +679,30 @@ typedef struct {
uint8_t writtenMask[MAX_BLOCKS / 8 + 1];
} WriteState;
char elfPath[300];
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);
if (lmsPid) {
DBG("SIGSTOP to lmsPID=%d\n", lmsPid);
kill(lmsPid, SIGSTOP);
} else {
DBG("LMS not found\n");
}
}
void waitAndContinue() {
stopLMS();
for (int fd = 3; fd < 9999; ++fd)
close(fd);
pid_t child = fork();
if (child == 0) {
DBG("start %s\n", elfPath);
execl(elfPath, elfPath, "--msd", (char*) NULL);
exit(128);
}
int status;
waitpid(child, &status, 0);
DBG("re-start LMS\n");
if (lmsPid)
kill(lmsPid, SIGCONT);
exit(0);
}
void restartProgram() {
if (!elfPath[0])
if (!rbfPath[0])
exit(0);
pid_t child = fork();
if (child == 0)
waitAndContinue();
else
exit(0); // causes parent to eject MSD etc
startRbf();
exit(0); // causes parent to eject MSD etc
}
int numWrites = 0;
static WriteState wrState;
void write_block(uint32_t block_no, uint8_t *data) {
WriteState *state = &wrState;
UF2_Block *bl = (void *)data;
if (bl->magicStart0 == 0x20da6d81 && bl->magicStart1 == 0x747e09d4) {
DBG("restart req, #wr=%d", numWrites);
if (numWrites) {
exit(0);
}
return;
}
numWrites++;
if (!is_uf2_block(bl)) {
return;
}
@ -746,15 +741,19 @@ void write_block(uint32_t block_no, uint8_t *data) {
*p = '/';
int fd = open(fn, O_WRONLY | O_CREAT, 0777);
if (fd < 0 && errno == ETXTBSY) {
unlink(fn);
fd = open(fn, O_WRONLY | O_CREAT, 0777);
}
if (fd >= 0) {
ftruncate(fd, bl->fileSize);
lseek(fd, bl->targetAddr, SEEK_SET);
// DBG("write %d bytes at %d to %s\n", bl->payloadSize, bl->targetAddr, fn);
// DBG("write %d bytes at %d to %s", bl->payloadSize, bl->targetAddr, fn);
write(fd, bl->data, bl->payloadSize);
close(fd);
if (strlen(fn) > 4 && !strcmp(fn + strlen(fn) - 4, ".elf")) {
strcpy(elfPath, fn);
if (strlen(fn) > 4 && !strcmp(fn + strlen(fn) - 4, ".rbf")) {
strcpy(rbfPath, fn);
}
}
}
@ -773,6 +772,7 @@ void write_block(uint32_t block_no, uint8_t *data) {
// logval("incr", state->numWritten);
state->writtenMask[pos] |= mask;
state->numWritten++;
DBG("write %d/%d #%d", state->numWritten, state->numBlocks, bl->blockNo);
}
if (state->numWritten >= state->numBlocks) {
restartProgram();

View File

@ -16,27 +16,48 @@
#include <sys/stat.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdarg.h>
#include "uf2.h"
const char *dev_file = "/dev/nbd0";
#define NUM_BLOCKS NUM_FAT_BLOCKS
#define FAIL(args...) \
do { \
fprintf(stderr, args); \
fprintf(stderr, "\n"); \
exit(1); \
} while (0)
#define LOG(args...) \
do { \
fprintf(stderr, args); \
fprintf(stderr, "\n"); \
} while (0)
uint64_t ntohll(uint64_t a) { return ((uint64_t)ntohl(a & 0xffffffff) << 32) | ntohl(a >> 32); }
uint64_t ntohll(uint64_t a) {
return ((uint64_t)ntohl(a & 0xffffffff) << 32) | ntohl(a >> 32);
}
#define htonll ntohll
void mylog(const char *fmt, ...) {
va_list args;
char *p, *p2;
va_start(args, fmt);
vasprintf(&p, fmt, args);
vprintf(fmt, args);
va_end(args);
if (p[0] != '<')
asprintf(&p2, "<6>%s\n", p);
else
asprintf(&p2, "%s\n", p);
int len = strlen(p2);
#ifdef X86
write(2, p2, len);
#else
int fd = open("/dev/kmsg", O_WRONLY);
write(fd, p2, len);
close(fd);
#endif
free(p);
free(p2);
}
void readAll(int fd, void *dst, uint32_t length) {
while (length) {
int curr = read(fd, dst, length);
@ -78,13 +99,10 @@ void startclient() {
exit(0);
}
#define dev_file "/dev/nbd0"
void handleread(int off, int len) {
uint8_t buf[512];
// fprintf(stderr, "read @%d len=%d\n", off, len);
// htonl(EPERM);
reply.error = 0;
LOG("read @%d len=%d", off, len);
reply.error = 0; // htonl(EPERM);
writeAll(sock, &reply, sizeof(struct nbd_reply));
for (int i = 0; i < len; ++i) {
read_block(off + i, buf);
@ -94,7 +112,7 @@ void handleread(int off, int len) {
void handlewrite(int off, int len) {
uint8_t buf[512];
// fprintf(stderr, "write @%d len=%d\n", off, len);
LOG("write @%d len=%d", off, len);
for (int i = 0; i < len; ++i) {
readAll(sock, buf, 512);
write_block(off + i, buf);
@ -133,7 +151,7 @@ void runNBD() {
reply.error = htonl(0);
for (;;) {
nbd_ioctl(BLKFLSBUF, 0); // flush buffers - we don't want the kernel to cache the writes
// nbd_ioctl(BLKFLSBUF, 0); // flush buffers - we don't want the kernel to cache the writes
int nread = read(sock, &request, sizeof(request));
if (nread < 0) {
@ -179,11 +197,14 @@ void enableMSD(int enabled) {
#endif
}
int main() {
int main(int argc, char **argv) {
#ifndef X86
daemon(0, 1);
#endif
if (argc > 1)
dev_file = argv[1];
for (;;) {
pid_t child = fork();
if (child == 0) {

View File

@ -25,8 +25,7 @@ void write_block(uint32_t block_no, uint8_t *data);
#define CONCAT_1(a, b) a##b
#define CONCAT_0(a, b) CONCAT_1(a, b)
#define STATIC_ASSERT(e) \
enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }
#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }
extern const char infoUf2File[];
@ -34,4 +33,14 @@ void readAll(int fd, void *dst, uint32_t length);
STATIC_ASSERT(sizeof(UF2_Block) == 512);
void mylog(const char *fmt, ...);
#define FAIL(args...) \
do { \
mylog("<4>" args); \
exit(1); \
} while (0)
#define LOG mylog
#endif

1
docfiles/robotsmeta.html Normal file
View File

@ -0,0 +1 @@
<meta name="robots" content="noindex">

View File

@ -41,7 +41,8 @@ namespace pxt.editor {
export function deployCoreAsync(resp: pxtc.CompileResult, isCli = false) {
let w: Ev3Wrapper
let filename = resp.downloadFileBaseName
let filename = resp.downloadFileBaseName || "pxt"
filename = filename.replace(/^lego-/, "")
let fspath = "../prjs/BrkProg_SAVE/"

View File

@ -30,7 +30,5 @@
Object = 4,
Function = 5,
}
declare namespace serial {
}
// Auto-generated. Do not edit. Really.

158
libs/base/shims.d.ts vendored Normal file
View File

@ -0,0 +1,158 @@
// Auto-generated. Do not edit.
//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte
declare interface Buffer {
/**
* Write a number in specified format in the buffer.
*/
//% shim=BufferMethods::setNumber
setNumber(format: NumberFormat, offset: int32, value: number): void;
/**
* Read a number in specified format from the buffer.
*/
//% shim=BufferMethods::getNumber
getNumber(format: NumberFormat, offset: int32): number;
/** Returns the length of a Buffer object. */
//% property shim=BufferMethods::length
length: int32;
/**
* Fill (a fragment) of the buffer with given value.
*/
//% offset.defl=0 length.defl=-1 shim=BufferMethods::fill
fill(value: int32, offset?: int32, length?: int32): void;
/**
* Return a copy of a fragment of a buffer.
*/
//% offset.defl=0 length.defl=-1 shim=BufferMethods::slice
slice(offset?: int32, length?: int32): Buffer;
/**
* Shift buffer left in place, with zero padding.
* @param offset number of bytes to shift; use negative value to shift right
* @param start start offset in buffer. Default is 0.
* @param length number of elements in buffer. If negative, length is set as the buffer length minus
* start. eg: -1
*/
//% start.defl=0 length.defl=-1 shim=BufferMethods::shift
shift(offset: int32, start?: int32, length?: int32): void;
/**
* Convert a buffer to its hexadecimal representation.
*/
//% shim=BufferMethods::toHex
toHex(): string;
/**
* Rotate buffer left in place.
* @param offset number of bytes to shift; use negative value to shift right
* @param start start offset in buffer. Default is 0.
* @param length number of elements in buffer. If negative, length is set as the buffer length minus
* start. eg: -1
*/
//% start.defl=0 length.defl=-1 shim=BufferMethods::rotate
rotate(offset: int32, start?: int32, length?: int32): void;
/**
* Write contents of `src` at `dstOffset` in current buffer.
*/
//% shim=BufferMethods::write
write(dstOffset: int32, src: Buffer): void;
}
declare namespace loops {
/**
* Repeats the code forever in the background. On each iteration, allows other codes to run.
* @param body code to execute
*/
//% help=loops/forever weight=100 blockGap=8
//% blockId=forever block="forever" blockAllowMultiple=1 shim=loops::forever
function forever(a: () => void): void;
/**
* Pause for the specified time in milliseconds
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
*/
//% help=loops/pause weight=99
//% async block="pause (ms) %pause"
//% blockId=device_pause shim=loops::pause
function pause(ms: int32): void;
}
declare namespace control {
/**
* Gets the number of milliseconds elapsed since power on.
*/
//% help=control/millis weight=50
//% blockId=control_running_time block="millis (ms)" shim=control::millis
function millis(): int32;
/**
* Run code when a registered event happens.
* @param id the event compoent id
* @param value the event value to match
*/
//% weight=20 blockGap=8 blockId="control_on_event" block="on event|from %src|with value %value"
//% blockExternalInputs=1
//% help="control/on-event" shim=control::onEvent
function onEvent(src: int32, value: int32, handler: () => void): void;
/**
* Reset the device.
*/
//% weight=30 async help=control/reset blockGap=8
//% blockId="control_reset" block="reset" shim=control::reset
function reset(): void;
/**
* Block the current fiber for the given microseconds
* @param micros number of micro-seconds to wait. eg: 4
*/
//% help=control/wait-micros weight=29 async
//% blockId="control_wait_us" block="wait (µs)%micros" shim=control::waitMicros
function waitMicros(micros: int32): void;
/**
* Run other code in the background.
*/
//% help=control/run-in-background blockAllowMultiple=1
//% blockId="control_run_in_background" block="run in background" blockGap=8 shim=control::runInBackground
function runInBackground(a: () => void): void;
/**
* Blocks the calling thread until the specified event is raised.
*/
//% help=control/wait-for-event async
//% blockId=control_wait_for_event block="wait for event|from %src|with value %value" shim=control::waitForEvent
function waitForEvent(src: int32, value: int32): void;
/**
* Derive a unique, consistent serial number of this device from internal data.
*/
//% blockId="control_device_serial_number" block="device serial number" weight=9 shim=control::deviceSerialNumber
function deviceSerialNumber(): int32;
}
declare namespace serial {
/**
* Write some text to the serial port.
*/
//% help=serial/write-string
//% weight=87
//% blockId=serial_writestring block="serial|write string %text" shim=serial::writeString
function writeString(text: string): void;
/**
* Send a buffer across the serial connection.
*/
//% help=serial/write-buffer advanced=true weight=6
//% blockId=serial_writebuffer block="serial|write buffer %buffer" shim=serial::writeBuffer
function writeBuffer(buffer: Buffer): void;
}
// Auto-generated. Do not edit. Really.

View File

@ -1,6 +1,6 @@
{
"name": "pxt-ev3",
"version": "0.0.0",
"version": "0.0.3",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true,
"keywords": [
@ -39,8 +39,8 @@
"semantic-ui-less": "^2.2.4"
},
"dependencies": {
"pxt-common-packages": "0.8.1",
"pxt-core": "1.7.4"
"pxt-common-packages": "0.9.1",
"pxt-core": "1.8.10"
},
"scripts": {
"test": "node node_modules/pxt-core/built/pxt.js travis"

View File

@ -98,12 +98,9 @@ span.blocklyTreeLabel {
}
/* Editor menu toggle */
#menubar .ui.menu .item.editor-menuitem {
#menubar .ui.menu.fixed .item.editor-menuitem .ui.grid {
background: @blue !important;
}
#menubar .ui.menu .item.editor-menuitem .item {
color: white !important;
}
/* Search box */
#blocklySearchArea {
@ -124,11 +121,6 @@ span.blocklyTreeLabel {
#filelist {
background: transparent;
}
div.blocklyTreeRow {
padding-bottom: 2rem !important;
min-height: @blocklyRowHeightMobile;
line-height: @blocklyRowHeightMobile/2;
}
#blocklyTrashIcon {
margin: 0.2rem;
}
@ -136,29 +128,14 @@ span.blocklyTreeLabel {
/* Tablet */
@media only screen and (min-width: @tabletBreakpoint) and (max-width: @largestTabletScreen) {
div.blocklyTreeRow {
padding-left: 0.5rem !important;
min-height: @blocklyRowHeightTablet;
line-height: @blocklyRowHeightTablet/2;
}
}
/* Small Monitor */
@media only screen and (min-width: @computerBreakpoint) and (max-width: @largestSmallMonitor) {
div.blocklyTreeRow {
padding-left: 0.5rem !important;
min-height: @blocklyRowHeightComputer;
line-height: @blocklyRowHeightComputer/2;
}
}
/* Large Monitor */
@media only screen and (min-width: @largeMonitorBreakpoint) {
div.blocklyTreeRow {
padding-left: 0.5rem !important;
min-height: @blocklyRowHeightWide;
line-height: @blocklyRowHeightWide/2;
}
}
/* Mobile, Tablet AND thin screen */
@media only screen and (max-width: @largestTabletScreen) and (max-height: @thinEditorBreakpoint) {