Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/a3f/ev3duder
Browse files Browse the repository at this point in the history
Conflicts:
	src/main.c
  • Loading branch information
a3f committed Jun 8, 2015
2 parents ee64e79 + 6826c04 commit b83a9f8
Show file tree
Hide file tree
Showing 13 changed files with 383 additions and 67 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,6 @@ Temporary Items
ev3duder
#doxygen
doc
#vim
*.swp
*.swo
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ OBJDIR = build

#LIBS = -lpsapi

SRCS = src/main.c src/cmd_defaults.c src/exec.c src/test.c src/up.c src/ls.c src/rm.c src/mkdir.c
SRCS = src/main.c src/cmd_defaults.c src/run.c src/test.c src/up.c src/ls.c src/rm.c src/mkdir.c src/mkrbf.c src/dl.c

# TODO: Apple's ld doesn't support interleaving -Bstatic
LIBS = -Llib/ -lhidapi
Expand Down
116 changes: 68 additions & 48 deletions src/btunix.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,68 +8,88 @@
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>

#include <signal.h>
#include <setjmp.h>
#include <sys/time.h>

#include "defs.h"
#define BT "/dev/cu.EV3-SerialPort"
// ^ TODO: add ability to find differently named EV3's
static void handle_sigint(int signo);
void *bt_open()
{
signal(SIGINT, handle_sigint);
int *fd = malloc(sizeof(int));
*fd = open(BT, O_RDWR | O_NONBLOCK);
fprintf(stderr, "bt_open reporting. fd = %d ",*fd);
return fd;
// signal(SIGINT, handle_sigint);
int *fd = malloc(sizeof(int));
*fd = open(BT, O_RDWR);
return *fd != -1 ? fd : NULL;
}

int bt_write(void* fd_, const u8* buf, size_t count)
{
size_t sent;
int fd = *(int*)fd_;
for (size_t ret = sent = 0; sent < count; sent += ret)
{
//ssize_t ret = write(fd, buf+sent, count-sent);
ssize_t ret = write(fd, buf, count);
if (ret < 0)
{
// set some error msg
break;
}
}
return sent;
size_t sent;
int fd = *(int*)fd_;
buf++;count--; // omit HID report number
for (ssize_t ret = sent = 0; sent < count; sent += ret)
{
ret = write(fd, buf, count-sent);
if (ret == -1)
{
// set some error msg
break;
}
}
return sent;
}
int bt_read(void* fd_, u8* buf, size_t count, int milliseconds)
static jmp_buf env;
static void handle_alarm(int sig)
{
int fd = *(int*)fd_;
if(0 && milliseconds > -1)
{
struct termios termios;
tcgetattr(fd, &termios);
termios.c_lflag &= ~ICANON;
termios.c_cc[VTIME] = milliseconds / 100;
tcsetattr(fd, TCSANOW, &termios);
}// else blocking wait

size_t recvd;
for (size_t ret = recvd = 0; recvd < count; recvd += ret)
{
ssize_t ret = read(fd, buf+recvd, count-recvd);
if (ret < 0)
{
// set some error msg maybe save errno in static field
break;
}
}
return recvd;
(void)sig; longjmp(env, 1);
}
int bt_read(void* fd_, u8* buf, size_t count, int milliseconds)
{ // goto <3
(void)count;
(void)milliseconds;
int fd = *(int*)fd_;
size_t recvd =0;
size_t packet_len = 2;
signal(SIGALRM, handle_alarm);
struct itimerval timer;
milliseconds = 1;
if (milliseconds != -1)
{
timer.it_value.tv_sec = milliseconds / 1000;
timer.it_value.tv_usec = milliseconds % 1000 * 1000;
}
if (setjmp(env) == 0)
{
again:
for (ssize_t ret=recvd; recvd < packet_len; recvd += ret)
{
if (milliseconds != -1) {
setitimer(ITIMER_REAL, &timer, NULL);
ret = read(fd, buf+recvd, packet_len-recvd);
alarm(0);
}else
ret = read(fd, buf+recvd, packet_len-recvd);
if (ret == -1)
{
perror("read failed");
return -1;
}
// bug one should handle disconnects during transfer. if this happens read keeps returning zeros
}
if (recvd == 2)
{
packet_len += buf[0] | (buf[1] << 8);
if (packet_len > 2*count) //TODO: remove 2*
return -1;
goto again;
}
}
return recvd;

}
const wchar_t *bt_error(void* fd_) { (void)fd_; return L"Errors not implemented yet";}
static void handle_sigint(int signo)
{
switch(signo)
{
case SIGINT:
exit(1);
}
}

9 changes: 9 additions & 0 deletions src/cmd_defaults.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,18 @@ CONTINUE_DOWNLOAD_INIT = { .hidLayer = 0x00, .replyType = 0x01, .cmd = 0x93};
const CONTINUE_DOWNLOAD_REPLY
CONTINUE_DOWNLOAD_REPLY_SUCCESS = {.packetLen = 6, .type = 0x03, .cmd = 0x93, .ret = 0x08};

const BEGIN_UPLOAD
BEGIN_UPLOAD_INIT = { .hidLayer = 0x00, .replyType = 0x01, .cmd = 0x94 };

const CONTINUE_UPLOAD
CONTINUE_UPLOAD_INIT = { .hidLayer = 0x00, .replyType = 0x01, .cmd = 0x95};

const LIST_FILES
LIST_FILES_INIT = {.hidLayer = 0x00, .replyType = 0x01, .cmd = 0x99 };

const CONTINUE_LIST_FILES
CONTINUE_LIST_FILES_INIT = {.hidLayer =0x00, .packetLen =7, .replyType = 0x01, .cmd = 0x9A};

const BEGIN_GETFILE
BEGIN_GETFILE_INIT = {.hidLayer =0x00, .replyType = 0x01, .cmd = 0x96 };

Expand Down
114 changes: 114 additions & 0 deletions src/dl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ev3_io.h"

#include "defs.h"
#include "systemcmd.h"
#include "error.h"
#include "funcs.h"

#define CHUNK_SIZE 1000 // EV3's HID driver doesn't do packets > 1024B
int dl( const char *path, FILE *fp)
{
int res;
size_t path_sz = strlen(path) + 1;
if (!fp)
fp = fopen(strrchr(path, '/') + 1, "w");

//TODO: read in chunks, whatif long isnt big enough
BEGIN_UPLOAD *bu = packet_alloc(BEGIN_UPLOAD, path_sz);
memcpy(bu->fileName, path, path_sz);
bu->maxBytes = CHUNK_SIZE;

print_bytes(bu, bu->packetLen + PREFIX_SIZE);
res = ev3_write(handle, (u8 *)bu, bu->packetLen + PREFIX_SIZE);
if (res < 0)
{
errmsg = "Unable to write BEGIN_UPLOAD.";
hiderr = ev3_error(handle);
return ERR_HID;
}
fputs("Checking reply: \n", stderr);
size_t file_chunksz = sizeof(BEGIN_UPLOAD_REPLY) + bu->maxBytes;
void *file_chunk = malloc(file_chunksz);
BEGIN_UPLOAD_REPLY *burep = file_chunk;

res = ev3_read_timeout(handle, (u8 *)burep, file_chunksz, TIMEOUT);
if (res <= 0)
{
errmsg = "Unable to read BEGIN_UPLOAD";
hiderr = ev3_error(handle);
return ERR_HID;
}

if (burep->type == VM_ERROR)
{
if (burep->ret < ARRAY_SIZE(ev3_error_msgs))
hiderr = ev3_error_msgs[burep->ret];
else
hiderr = L"ERROR_OUT_OF_BOUNDS";
fputs("Operation failed.\nlast_reply=", stderr);
print_bytes(burep, burep->packetLen);


errmsg = "`BEGIN_UPLOAD` was denied.";
return ERR_VM;
}
fwrite(burep->bytes, CHUNK_SIZE, 1, fp);

size_t read_so_far = burep->packetLen + 2 - offsetof(BEGIN_UPLOAD_REPLY, bytes);
size_t total = burep->fileSize;
free(burep);

CONTINUE_UPLOAD cu = CONTINUE_UPLOAD_INIT;
cu.fileHandle =burep->fileHandle;
cu.maxBytes = CHUNK_SIZE + sizeof(BEGIN_UPLOAD_REPLY) - sizeof(CONTINUE_UPLOAD_REPLY);
// fprintf(stderr, "read %zu from total %zu bytes.\n", read_so_far, total);
CONTINUE_UPLOAD_REPLY *curep = file_chunk;
int ret = curep->ret;
while(ret != END_OF_FILE)
{
res = ev3_write(handle, (u8*)&cu, sizeof cu);
if (res < 0)
{
errmsg = "Unable to write BEGIN_UPLOAD";
hiderr = ev3_error(handle);
return ERR_HID;
}

res = ev3_read_timeout(handle, (u8 *)curep, file_chunksz, TIMEOUT);
if (res <= 0)
{
errmsg = "Unable to read BEGIN_UPLOAD_REPLY";
hiderr = ev3_error(handle);
return ERR_HID;
}
if (curep->type == VM_ERROR)
{
if (curep->ret < ARRAY_SIZE(ev3_error_msgs))
hiderr = ev3_error_msgs[curep->ret];
else
hiderr = L"ERROR_OUT_OF_BOUNDS";
fputs("Operation failed.\nlast_reply=", stderr);
print_bytes(curep, curep->packetLen);


errmsg = "`BEGIN_UPLOAD` was denied.";
return ERR_VM;
}
fwrite(burep->bytes, cu.maxBytes, 1, fp);
cu.fileHandle = curep->fileHandle;
size_t read_so_far = curep->packetLen + 2 - offsetof(CONTINUE_UPLOAD_REPLY, bytes);
fflush(stdout);
fprintf(stderr, "read %zu from total %zu bytes.\n", read_so_far, file_chunksz);
ret = curep->ret;
}

errmsg = "`BEGIN_UPLOAD` was successful.";
return ERR_UNK;

}


7 changes: 4 additions & 3 deletions src/funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ extern int up(FILE* loc, const char *rem);
extern int dl(const char *rem, FILE* loc);
//! print HID information, beep and exit
extern int test(void);
//! execute remote .rbf file \p rem via VM
extern int exec(const char *rem);
//! run remote .rbf file \p rem via VM
extern int run(const char *rem);
//! list contents of remote directory \p rem
extern int ls(const char *rem);
//! remove remote file or directory \p rem
extern int rm(const char *rem);
//! create directory \p rem on remote system
extern int mkdir(const char *rem);

//! fill \p *buf with a rbf file executing \p cmd
extern size_t mkrbf(char **buf, const char *cmd);
#endif

60 changes: 57 additions & 3 deletions src/ls.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
* @bug Doesn't handle replies over 1000 byte in length.
* implementation of \p CONTINUTE_LIST_FILES would be required
*/
#define MAX_READ 1024
int ls(const char *path)
{
int res;
size_t path_sz = strlen(path) + 1;
LIST_FILES *list = packet_alloc(LIST_FILES, path_sz);
list->maxBytes = 0xffff;
list->maxBytes = MAX_READ;
memcpy(list->path, path, path_sz);

print_bytes(list, list->packetLen + PREFIX_SIZE);
Expand Down Expand Up @@ -60,8 +61,61 @@ int ls(const char *path)
errmsg = "`LIST_FILES` was denied.";
return ERR_VM;
}
puts(listrep->list);
//README: it's assumed that the folder structure fits into ONE HID packet. if not additional code for handling CONTINUTE_LIST_FILES is required
fputs(listrep->list, stdout);
//
// From the LEGO docs: - LIST_FILES should work as long as list does not exceed 1014 bytes. CONTINUE_LISTFILES has NOT been implemented yet.
#if !LEGO_FIXED_CONTINUE_LIST_FILES

#else
size_t read_so_far = listrep->packetLen + 2 - offsetof(LIST_FILES_REPLY, list);
size_t total = listrep->listSize;
CONTINUE_LIST_FILES listcon = CONTINUE_LIST_FILES_INIT;
listcon.handle =listrep->handle;
listcon.listSize = 100;
// fprintf(stderr, "read %zu from total %zu bytes.\n", read_so_far, total);
size_t listconrep_sz = sizeof(CONTINUE_LIST_FILES_REPLY) + MAX_READ;
CONTINUE_LIST_FILES_REPLY *listconrep = malloc(listconrep_sz);
int ret = listconrep->ret;
while(ret != END_OF_FILE)
{
CONTINUE_LIST_FILES_REPLY *listconrep = malloc(listconrep_sz);
res = ev3_write(handle, (u8*)&listcon, sizeof listcon);
if (res < 0)
{
errmsg = "Unable to write LIST_FILES";
hiderr = ev3_error(handle);
return ERR_HID;
}

res = ev3_read_timeout(handle, (u8 *)listconrep, listconrep_sz, TIMEOUT);
if (res <= 0)
{
errmsg = "Unable to read LIST_FILES_REPLY";
hiderr = ev3_error(handle);
return ERR_HID;
}
if (listconrep->type == VM_ERROR)
{
if (listconrep->ret < ARRAY_SIZE(ev3_error_msgs))
hiderr = ev3_error_msgs[listconrep->ret];
else
hiderr = L"ERROR_OUT_OF_BOUNDS";
fputs("Operation failed.\nlast_reply=", stderr);
print_bytes(listconrep, listconrep->packetLen);


errmsg = "`LIST_FILES` was denied.";
return ERR_VM;
}
fprintf(stdout, "%s", listconrep->list);
listcon.handle = listconrep->handle;
listcon.listSize = MAX_READ;
size_t read_so_far = listconrep->packetLen + 2 - offsetof(CONTINUE_LIST_FILES_REPLY, list);
fflush(stdout);
//fprintf(stderr, "read %zu from total %zu bytes.\n", read_so_far, listconrep_sz);
ret = listconrep->ret;
}
#endif

errmsg = "`LIST_FILES` was successful.";
return ERR_UNK;
Expand Down
Loading

0 comments on commit b83a9f8

Please sign in to comment.