/* * mu_read_file mmaps the file and returns its contents as a string */ void mu_read_file() /* fd - addr len */ { char *p = NULL; struct stat s; int fd; fd = TOP; if (fstat(fd, &s) == -1) { close(fd); return abort_strerror(); } /* If size of file is zero, don't try to mmap; it will fail and error * out. Instead, simply return a buffer starting at address 0, of * length 0. */ if (s.st_size != 0) { p = (char *) mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (p == MAP_FAILED) { close(fd); return abort_strerror(); } } DROP(-1); ST1 = (addr) p; TOP = s.st_size; }
/* * usb-find-device (vendor-id product-id -- handle -1 | 0) */ void mu_usb_find_device() { int matched; /* Enumerate USB device tree, looking for a match */ matched = enumerate_devices(ST1, TOP); /* * enumerate_devices only returns failure (-1) if it found a match but * couldn't open the device for read & write. Tell the user about the * error. */ if (matched < 0) return abort_strerror(); if (matched == 0) { /* No match found */ DROP(1); TOP = 0; } else { /* Matched; return the device's _open_ file descriptor */ ST1 = matched; TOP = -1; } }
/* * This is bogus, ridiculously dangerous and unportable, and for testing * only. But here it is: A generic ioctl interface! */ void mu_ioctl() /* fd ioctl arg */ { if (ioctl(ST2, ST1, TOP) == -1) return abort_strerror(); DROP(3); }
/* * usb-control (bmRequestType bRequest wValue wIndex wLength 'buffer device - count) */ void mu_usb_control() { struct usb_ctl_request ucr; int fd; #define req ucr.ucr_request req.bmRequestType = SP[6]; req.bRequest = SP[5]; USETW(req.wValue, SP[4]); USETW(req.wIndex, ST3); USETW(req.wLength, ST2); ucr.ucr_data = (void *)ST1; ucr.ucr_addr = 0; ucr.ucr_flags = (req.bmRequestType == UT_READ_DEVICE) ? USBD_SHORT_XFER_OK : 0; fd = TOP; DROP(6); if (ioctl(fd, USB_DO_REQUEST, &ucr) == -1) { TOP = 0; /* count of bytes transferred */ return abort_strerror(); } TOP = ucr.ucr_actlen; /* actual length transferred */ }
/* stack: ( fd termios - ) */ void mu_set_termios() { /* drain out, flush in, set */ if (tcsetattr(ST1, TCSAFLUSH, (struct termios *)TOP) == -1) return abort_strerror(); DROP(2); }
void mu_close_file() { while (close(TOP) == -1) { if (errno == EINTR) continue; return abort_strerror(); } DROP(1); }
/* * We need a way to do short sleeps for talking to sensitive hardware * targets (like the Freescale HC908 series). I'm not getting good data * from the bootloader, and wondering if some short pauses would help. */ void mu_nanosleep() { struct timespec ts; ts.tv_sec = ST1; ts.tv_nsec = TOP; while (nanosleep(&ts, &ts) == -1) { if (errno == EINTR) continue; return abort_strerror(); } DROP(2); }
void mu_create_file() /* C-string-name - fd */ { int fd; char pathbuf[1024]; char *path = abs_path((char *)TOP, pathbuf, 1024); if (path == NULL) return abort_zmsg("path too long"); fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0666); if (fd == -1) return abort_strerror(); TOP = fd; }
static void mu_open_file() /* C-string-name flags - fd */ { int fd; char pathbuf[1024]; char *path = abs_path((char *)ST1, pathbuf, 1024); if (path == NULL) return abort_zmsg("path too long"); fd = open(path, TOP); if (fd == -1) return abort_strerror(); DROP(1); TOP = fd; }
/* * Support for querying the column width of terminals, and staying updated * (via SIGWINCH) when they change. * * In case the user has redirected stdout to a file, use stderr as the file * descriptor to test. */ void mu_tty_width() /* ( fd - width) */ { int fd = TOP; struct winsize tty_size; if (!isatty(fd)) { TOP = 80; /* default width for file output */ return; } if (ioctl(fd, TIOCGWINSZ, &tty_size) == -1) return abort_strerror(); TOP = tty_size.ws_col; }
void mu_read_carefully() /* fd buffer len -- #read */ { int fd; char *buffer; size_t len; ssize_t count; fd = ST2; buffer = (char *) ST1; len = TOP; DROP(2); while((count = read(fd, buffer, len)) == -1) { if (errno == EINTR) continue; return abort_strerror(); } TOP = count; }
/* * usb-request (bmRequestType bRequest wValue wIndex wLength 'buffer device) * XXX should return actual length of transfer? */ void mu_usb_request() { struct usb_ctl_request ucr; int fd; #define req ucr.ucr_request req.bmRequestType = SP[6]; req.bRequest = SP[5]; USETW(req.wValue, SP[4]); USETW(req.wIndex, ST3); USETW(req.wLength, ST2); ucr.ucr_data = (void *)ST1; ucr.ucr_addr = 0; ucr.ucr_flags = (req.bmRequestType == UT_READ_DEVICE) ? USB_SHORT_XFER_OK : 0; fd = TOP; DROP(7); if (ioctl(fd, USB_DO_REQUEST, &ucr) == -1) return abort_strerror(); }
/* * usb-find-device (vendor-id product-id -- handle -1 | 0) */ void mu_usb_find_device() { int matched; /* Enumerate USB device tree, looking for a match */ matched = enumerate_devices(ST1, TOP); if (matched < 0) return abort_strerror(); if (matched == 0) { /* No match found */ DROP(1); TOP = 0; } else { /* Matched; return the device's _open_ file descriptor */ ST1 = matched; TOP = -1; } }
void mu_write_carefully() /* fd buffer len */ { int fd; char *buffer; size_t len; ssize_t written; fd = ST2; buffer = (char *) ST1; len = TOP; DROP(3); while (len > 0) { written = write(fd, buffer, len); if (written == -1) { if (errno == EINTR) continue; return abort_strerror(); } buffer += written; len -= written; } }
/* * Sometimes it's nice to know how many characters are waiting in the input * buffer. */ void mu_tty_icount() { if (ioctl(TOP, FIONREAD, &TOP) == -1) return abort_strerror(); }