commit d47ef530f07b7bcdcd8da29bf90f0668271cf914 Author: JayPiKay Date: Tue Aug 10 15:21:40 2021 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c419ccc --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +attic/ +.ccls-cache/ + +compile_commands.json + +*.o + +actionpro +config.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9cd4b91 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +# ACTIONPRO Makefile + +include config.mk + +PRG = actionpro +SRC = main.c +OBJ = ${SRC:.c=.o} +BIN = ${OBJ:.o=} + +all: options ${PRG} + +options: + @echo ${PRG} compile options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +.c.o: + @${CC} -c ${CFLAGS} $< + +${OBJ}: config.h config.mk + +config.h: + @echo creating $@ from config.def.h + @cp config.def.h $@ + +${PRG}: ${OBJ} + ${CC} -o ${PRG} ${OBJ} ${LDFLAGS} + +clean: + @echo cleaning + @rm -f ${BIN} ${OBJ} + +.PHONY: all options clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..e795788 --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +# ACTIONPRO X7 + +## Research + +## Research: File/Drive Access by Action Manager 1.3 + +Opening Drive/Device: +``` +CreateFile(): +Desired Access: Generic Read/Write +Disposition: Open +Options: Synchronous IO Non-Alert, Non-Directory File +Attributes: n/a +ShareMode: Read, Write +AllocationSize: n/a +OpenResult: Opened +``` + +Sending Command: +Windows Application sends `IOCTL_SCSI_PASS_THROUGH` with `DeviceIoControl()`. + + +### Research: Code Snippets using ioctl() + +Code example #1: +``` +#define DEF_TIMEOUT 5000 // 5 seconds +char cDiskName[] = "/dev/sg3"; +int fd = open(cDiskName, O_RDWR); +if (fd < 0) +{ + printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno)); + return 1; +} + +unsigned char turCmbBlk[] = {0x00, 0, 0, 0, 0, 0}; +struct sg_io_hdr io_hdr; + +unsigned char cIOBuffer[100]; + +// buffer initialization code omitted + +memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); +io_hdr.interface_id = 'S'; +io_hdr.cmd_len = sizeof(turCmbBlk); +io_hdr.mx_sb_len = sizeof(cIOBuffer); +io_hdr.dxfer_direction = SG_DXFER_NONE; +io_hdr.cmdp = turCmbBlk; +io_hdr.sbp = cIOBuffer; +io_hdr.timeout = DEF_TIMEOUT; +if (ioctl(fd, SG_IO, &io_hdr) < 0) +{ + printf("ioctl error: errno=%d (%s)\n", errno, strerror(errno)); +} + +// Code returned here without any errors but cIOBuffer remains unchanged. +``` + +``` +#include +#include +#include +#include +#include + +void main(int argc, char **argv) +{ + const char *filename; + int fd; + + filename = argv[1]; + + fd = open(filename, O_WRONLY); + ioctl(fd, USBDEVFS_RESET, 0); + + close(fd); + + return; +} +``` + +``` +#define BUFF_SIZE 100 // - Buffersize + +#define DEF_TIMEOUT 5000 // 5 seconds +char cDiskName[] = "/dev/sg3"; +int fd = open(cDiskName, O_RDWR); +if (fd < 0) +{ + printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno)); + return 1; +} + +unsigned char turCmbBlk[] = {0x00, 0, 0, 0, 0, 0}; +struct sg_io_hdr *p = (struct sg_io_hdr *) malloc(sizeof(struct sg_io_hdr)); // - dynamic memory allocation - free() required somewhere + +unsigned char cIOBuffer[BUFF_SIZE]; +unsigned char replyBuffer[BUFF_SIZE]; // - dxfer buffer + +// buffer initialization code omitted + +memset(p, 0, sizeof(struct sg_io_hdr)); +p->interface_id = 'S'; +p->cmd_len = sizeof(turCmbBlk); +p->mx_sb_len = BUFF_SIZE; +p->dxfer_direction = SG_DXFER_NONE; +p->cmdp = turCmbBlk; +p->sbp = cIOBuffer; +p->timeout = DEF_TIMEOUT; +p->flags = SG_FLAG_DIRECT_IO; // - Does this help? +p->dxferp = replyBuffer; // - Set dxferp buffer - (A) +p->dxfer_len = BUFF_SIZE; // - buffersize + +if (ioctl(fd, SG_IO, p) < 0) +{ + printf("ioctl error: errno=%d (%s)\n", errno, strerror(errno)); +} + +// Code returned here without any errors but cIOBuffer remains unchanged. +``` + +Use for `scsi/sg.h` and `ioctl`. + + diff --git a/config.def.h b/config.def.h new file mode 100644 index 0000000..6a3eda4 --- /dev/null +++ b/config.def.h @@ -0,0 +1,10 @@ +#ifndef config_h +#define config_h + +/* defaults */ + +/* device information */ +#define VENDOR_ID 0x4255 +#define PRODUCT_ID 0x1000 + +#endif /* config_h */ diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..4681630 --- /dev/null +++ b/config.mk @@ -0,0 +1,10 @@ +# includes and libs +INCS = -I. -I/usr/include +LIBS = -L/usr/lib -lusb-1.0 + +# flags +CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} +LDFLAGS = -s ${LIBS} + +# compiler and linker +CC = cc diff --git a/main.c b/main.c new file mode 100644 index 0000000..3b921bd --- /dev/null +++ b/main.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +static struct libusb_device_handle *devh = NULL; + +static libusb_device_handle *open_actionpro() +{ + ssize_t devc; + libusb_device **dev_list; + static libusb_device *dev = NULL; + struct libusb_device_descriptor dev_desc; + struct libusb_config_descriptor *dev_conf = NULL; + const struct libusb_interface *iface = NULL; + const struct libusb_interface_descriptor *iface_desc = NULL; + + int res = 0; + + devc = libusb_get_device_list(NULL, &dev_list); + if (devc < 1) { + return NULL; + } + + for (int i = 0; i < devc; i++) { + dev = dev_list[i]; + if (libusb_get_device_descriptor(dev, &dev_desc)) { + continue; + } + + if ((dev_desc.idVendor != VENDOR_ID || dev_desc.idProduct != PRODUCT_ID)) { + continue; + } + + res = libusb_open(dev, &devh); + if (res < 0) { + perror("libusb_open"); + return(NULL); + } + + for (int j = 0; j < dev_desc.bNumConfigurations; j++) { + if (libusb_get_config_descriptor(dev, j, &dev_conf)) { + continue; + } + + for (int k = 0; k < dev_conf->bNumInterfaces; k++) { + iface = &dev_conf->interface[k]; + for (int l = 0; l < iface->num_altsetting; l++) { + iface_desc = &iface->altsetting[l]; + if (libusb_kernel_driver_active(devh, iface_desc->bInterfaceNumber)) { + libusb_detach_kernel_driver(devh, iface_desc->bInterfaceNumber); + } + + libusb_set_configuration(devh, dev_conf->bConfigurationValue); + libusb_claim_interface(devh, iface_desc->bInterfaceNumber); + + int e = 0; + while (libusb_claim_interface(devh, iface_desc->bInterfaceNumber) && (e < 10)) { + sleep(1); + e++; + } + } + } + + libusb_free_config_descriptor(dev_conf); + } + + return devh; + } + + devh = NULL; + return NULL; +} + +int main(int argc, char *argv[]) +{ + int res = 0; + + res = libusb_init(NULL); + if (res < 0) { + perror("libusb_init"); + fprintf(stderr, "Error: %s\n", libusb_strerror(res)); + exit(EXIT_FAILURE); + } + + if (!open_actionpro()) { + fprintf(stderr, "Error opening device, no ACTIONPRO X7 found!\n"); + libusb_exit(NULL); + exit(EXIT_FAILURE); + } + + libusb_exit(NULL); + + exit(EXIT_SUCCESS); +}