17 #define assert(cond) do{ if (!(cond)) {if (handle) ev3_close(handle);exit(ERR_ARG);}}while(0)
19 #include <hidapi/hidapi.h>
30 #define VendorID 0x694
31 #define ProductID 0x005
33 #define ExecName "/tmp/Executing shell cmd.rbf"
49 static const char EXEC_SUFFIX[] =
55 "printf \"\\t%08x\\n%s\","
58 "' | dd bs=1000 of=/dev/lms_usbdev";
61 "USAGE: ev3duder " "[ --tcp | --usb | --serial ] [=dev1,dev2] \n"
62 " " "[ up loc rem | dl rem loc | rm rem | ls [rem] |\n"
63 " " " mkdir rem | mkrbf rem loc | run rem | exec cmd |\n"
64 " " " wpa2 SSID [pass] | info | tunnel ]\n"
66 "rem = remote (EV3) path, loc = local path, dev = device identifier" "\n";
68 " up\t" "upload local file to remote ev3 brick\n"
69 " dl\t" "download remote file to local system\n"
70 " rm\t" "remove file on ev3 brick\n"
71 " ls\t" "list files. Standard value is '/'\n"
72 " info\t" "attempt a beep and print information about the connection\n"
73 " mkdir\t" "create directory. Relative to path of VM.\n"
74 " mkrbf\t" "create rbf (menu entry) file locally. Sensible upload paths are:\n"
75 "\t" "\t../prjs/BrkProg_SAVE/ Internal memory\n"
76 "\t" "\t../prjs/BrkProg_DL/ Internal memory\n"
77 "\t" "\t./apps/ Internal memory - Applicatios (3rd tab)\n"
78 "\t" "\t/media/card/myapps/ Memory card\n"
79 "\t" "\t/media/usb/myappps/ USB stick\n"
80 "run\t" "instruct the VM to run a rbf file\n"
81 "exec\t" "pass cmd to root shell. Handle with caution\n"
82 "wpa2\t" "connect to WPA-Network SSID, if pass isn't specified, read from stdin\n"
83 "tunnel\t" "connects stdout/stdin to the ev3 VM\n"
86 #define FOREACH_ARG(ARG) \
103 #define MK_ENUM(x) ARG_##x,
104 #define MK_STR(x) #x,
107 static const char *offline_args[] = {
MK_STR(
mkrbf) };
109 static char* my_chrsub(
char *s,
char old,
char new);
111 #define SANITIZE(s) (my_chrsub((s), '/', '\\'))
129 int main(
int argc,
char *argv[])
133 strcmp(argv[1],
"-h") == 0 ||
134 strcmp(argv[1],
"--help") == 0 ||
135 strcmp(argv[1],
"/?") == 0))
137 printf(
"%s (%s; %s) v%s\n"
138 "Copyright (C) 2015 Ahmad Fatoum\n"
139 "This is free software; see the source for copying conditions. There is NO\n"
140 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
141 "Source is available under the GNU GPL v3.0 https://github.com/a3f/ev3duder/\n\n",
142 argv[0], CONFIGURATION, SYSTEM, VERSION);
147 while (argv[1] && *argv[1] ==
'-')
149 if (argv[1][1] ==
'-')
151 char *a = argv[1] + 2;
153 char *device = strtok(NULL,
","),
154 *device2 = strtok(NULL,
"");
162 if (strcmp(
"usb", a) == 0 || strcmp(
"hid", a) == 0)
164 switches.select = switches.hid = 1;
165 params.usb_id = device;
167 else if (strcmp(
"tcp", a) == 0 || strcmp(
"inet", a) == 0)
169 switches.select = switches.tcp = 1;
170 params.tcp_id = device;
172 else if (strcmp(
"serial", a) == 0 || strcmp(
"bt", a) == 0)
174 switches.select = switches.serial = 1;
175 params.serial_id[0] = device;
176 params.serial_id[1] = device2;
178 else if (strcmp(
"nop", a) == 0)
185 fprintf(stderr,
"Invalid switch '%s'\n", argv[1]);
190 }
else if (argv[1][1] ==
't')
195 if (argv[1][2] ==
'=')
196 params.timeout = atoi(&argv[1][3]);
198 params.timeout = atoi(argv[2]);
203 fprintf(stderr,
"Invalid parameter '%s'\n", argv[1]);
214 for (i = 0; i < (int)
ARRAY_SIZE(offline_args); ++i)
215 if (strcmp(argv[1], offline_args[i]) == 0)
break;
219 if ((switches.hid || !switches.select) &&
222 if (!switches.select)
223 fputs(
"USB connection established.\n", stderr);
225 ev3_write = (int (*)(
void*,
const u8*, size_t))hid_write;
227 ev3_error = (
const wchar_t* (*)(
void*))hid_error;
230 else if ((switches.serial || !switches.select) &&
231 (
handle =
bt_open(params.serial_id[0], params.serial_id[1])))
233 if (!switches.select)
234 fprintf(stderr,
"Bluetooth serial connection established (%s).\n", params.serial_id[0]);
240 else if ((switches.tcp || !switches.select) &&
243 if (!switches.select)
246 fprintf(stderr,
"TCP connection established (%s@%s:%u).\n", info->
name, info->
ip, info->
tcp_port);
255 puts(
"EV3 not found. Either plug it into the USB port or pair over Bluetooth.\n");
257 puts(
"Insufficient access to the usb device might be a reason too, try sudo.");
264 for (i = 0; i < ARG_end; ++i)
265 if (strcmp(argv[1], args[i]) == 0)
break;
282 fp = fopen(
SANITIZE(argv[0]),
"rb");
285 printf(
"File <%s> doesn't exist.\n", argv[0]);
288 ret =
up(fp, argv[1]);
294 buf = strrchr(argv[0],
'/');
299 }
else buf = argv[1];
301 fp = fopen(buf,
"wb");
304 printf(
"File <%s> couldn't be opened for writing.\n", buf);
308 ret =
dl(argv[0], fp);
312 ret =
run(argv[0], params.timeout);
321 ret =
ls(argv[0] ?:
"/");
336 ret =
mkdir(argv[0]);
340 fp = fopen(
SANITIZE(argv[1]),
"wb");
344 len =
mkrbf(&buf, argv[0]);
345 fwrite(buf, len, 1, fp);
366 size_t len_cmd = strlen(argv[0]),
367 len_out =
sizeof EXEC_SUFFIX;
368 buf = malloc(len_cmd + len_out);
369 (void)mempcpy(mempcpy(buf,
371 EXEC_SUFFIX, len_out);
373 len =
mkrbf(&buf, argv[0]);
377 fwrite(buf, len, 1, fp);
394 printf(
"<%s> hasn't been implemented yet.\n", argv[0]);
397 FILE *out = ret ==
ERR_UNK ? stderr : stdout;
405 err =
"An unknown error occured";
407 fprintf(out,
"%s (%s)\n", err ?:
"-",
errmsg ?:
"-");
417 #pragma GCC diagnostic ignored "-Wunused-function"
418 static char* my_chrsub(
char *s,
char old,
char new)
421 if (ptr == NULL || *ptr ==
'\0')
425 if (*ptr == old) *ptr =
new;
int ls(const char *rem)
list contents of remote directory rem
int main(int argc, char *argv[])
EXTERN const wchar_t *(* ev3_error)(void *)
int info(const char *arg)
print connection information, beep and exit
void bt_close(void *handle)
Closes the file descriptor opened by bt_open()
void * bt_open(const char *file, const char *file2)
open a bluetooth device described by device. NULL leads to default action
int bt_write(void *fd_, const u8 *buf, size_t count)
writes buf[1] till buf[count - 2] to device
int bt_read(void *fd_, u8 *buf, size_t count, int milliseconds)
writes buf[1] till buf[count - 2] to device
#define ARRAY_SIZE(array)
EXTERN const char *const ev3_error_msgs[ERRORS_END+1]
Error enumerations and decriptions.
int dl(const char *path, FILE *fp)
download remote source rem to local file loc
int run(const char *rem, unsigned timeout)
run remote .rbf file rem via VM
EXTERN void(* ev3_close)(void *)
int up(FILE *loc, const char *rem)
upload local file loc to remote destination rem
Input/Output wrappers for Bluetooth.
EXTERN int(* ev3_read_timeout)(void *, u8 *, size_t, int milliseconds)
#define ExecName
Filename used for executing command with exec
void * tcp_open(const char *serial, unsigned timeout)
connects to a ev3 device on the same subnet.
int rm(const char *rem)
remove remote file or directory rem
packed structs for the packets.
int mkdir(const char *rem)
create directory rem on remote system
int(* tcp_write)(void *device, const u8 *buf, size_t count)
writes buf[1] till buf[count - 2] to device
const char *const usage_desc
int tunnel()
tunnel stdio to established ev3 connection
void tcp_close(void *sock)
releases the socket file descriptor opened by tcp_open()
size_t mkrbf(char **buf, const char *cmd)
fill *buf with a rbf file executing cmd
const wchar_t * bt_error(void *fd_)
Returns an error string describing the last error occured.
EXTERN const char * errmsg
global variable for last error message
BSD sockets/Winsock2 Input/Output wrappers.
contains declarations for ev3 commands
const wchar_t * tcp_error(void *fd_)
Returns an error string describing the last error occured.
#define VendorID
LEGO GROUP.
EXTERN int(* ev3_write)(void *, const u8 *, size_t)
int(* tcp_read)(void *device, u8 *buf, size_t count, int milliseconds)
writes buf[1] till buf[count - 2] to device