From 15a432108bf5000851d56f3fcd9b5bd2626bdfbd Mon Sep 17 00:00:00 2001 From: Kevin Kirspel Date: Wed, 17 May 2017 08:40:35 -0400 Subject: Add tests for USB keyboard and mouse as well as EVDEV --- testsuite/evdev01/init.c | 764 ++++++++++++++++++++++++++++++++++++++++++++ testsuite/usbkbd01/init.c | 278 ++++++++++++++++ testsuite/usbmouse01/init.c | 283 ++++++++++++++++ 3 files changed, 1325 insertions(+) create mode 100644 testsuite/evdev01/init.c create mode 100644 testsuite/usbkbd01/init.c create mode 100644 testsuite/usbmouse01/init.c diff --git a/testsuite/evdev01/init.c b/testsuite/evdev01/init.c new file mode 100644 index 00000000..fa16e618 --- /dev/null +++ b/testsuite/evdev01/init.c @@ -0,0 +1,764 @@ +/*- + * COPYRIGHT (c) 2017 Kevin Kirspel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TEST_NAME "LIBBSD EVDEV" + +#define PRIO_OPEN (RTEMS_MAXIMUM_PRIORITY - 12) +#define PRIO_KEYBOARD (RTEMS_MAXIMUM_PRIORITY - 11) +#define PRIO_MOUSE (RTEMS_MAXIMUM_PRIORITY - 10) +#define PRIO_TOUCH (RTEMS_MAXIMUM_PRIORITY - 9) +#define MAX_ACTIVE_DEVICES 256 + +#define DEVICE_INPUT_DIR "/dev/input" + +#define LONG_BITS (sizeof(long) * 8) +#define LONG_FIELD_SIZE(bits) ((bits / LONG_BITS) + 1) + +struct evdev_test_message { + int fd; + char device[256]; +}; + +static rtems_id oid, omid, kid, kmid, mid, mmid, tid, tmid, psema; +static volatile bool kill_otask, kill_ktask, kill_mtask, kill_ttask; +static volatile bool otask_active, ktask_active, mtask_active, ttask_active; +static char* active_devices[MAX_ACTIVE_DEVICES]; +static int active_device_count = 0; + +static void evdev_keyboard_task(rtems_task_argument arg); +static void evdev_mouse_task(rtems_task_argument arg); +static void evdev_touch_task(rtems_task_argument arg); + +static void +add_active_device(char* dev) +{ + rtems_semaphore_obtain(psema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (active_device_count < MAX_ACTIVE_DEVICES) { + active_devices[active_device_count++] = strdup(dev); + } + rtems_semaphore_release(psema); +} + +static void +remove_active_device(char* dev) +{ + int ii; + bool found = false; + + rtems_semaphore_obtain(psema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + for (ii = 0; ii < active_device_count; ii++) { + if (strcmp(dev, active_devices[ii]) == 0) { + free(active_devices[ii]); + found = true; + break; + } + } + if (found) { + ii++; + for (; ii < active_device_count; ii++) { + active_devices[ii] = active_devices[ii + 1]; + } + active_device_count--; + } + rtems_semaphore_release(psema); +} + +static bool +check_device_active(char* dev) +{ + int ii; + + rtems_semaphore_obtain(psema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + for (ii = 0; ii < active_device_count; ii++) { + if (strcmp(dev, active_devices[ii]) == 0) { + rtems_semaphore_release(psema); + return true; + } + } + rtems_semaphore_release(psema); + return false; +} + +static void +delete_active_devices(void) +{ + int ii; + + rtems_semaphore_obtain(psema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + for (ii = 0; ii < active_device_count; ii++) { + free(active_devices[ii]); + } + rtems_semaphore_release(psema); +} + +static void +print_message(char *fmt, ...) +{ + va_list ap; + + rtems_semaphore_obtain(psema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + rtems_semaphore_release(psema); +} + +static int +get_input_device_count(void) +{ + DIR *dir; + struct dirent *entry; + struct stat sbuf; + int file_count = 0; + int rv; + char fname[256]; + + if ((dir = opendir(DEVICE_INPUT_DIR)) != NULL) { + /* print all the files and directories within directory */ + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + strcpy(fname, DEVICE_INPUT_DIR); + strcat(fname, "/"); + strcat(fname, entry->d_name); + rv = stat(fname, &sbuf); + assert(rv != -1); + if (S_ISCHR(sbuf.st_mode)) { + file_count++; + } + } + closedir (dir); + } + return file_count; +} + +static char** +get_input_device_names(int file_count) +{ + DIR *dir; + struct dirent *entry; + struct stat sbuf; + char** s_arr = NULL; + int current_count = 0; + int rv; + char fname[256]; + + if (file_count > 0) { + s_arr = malloc(file_count * sizeof(char*)); + if ((dir = opendir(DEVICE_INPUT_DIR)) != NULL) { + /* print all the files and directories within directory */ + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + strcpy(fname, DEVICE_INPUT_DIR); + strcat(fname, "/"); + strcat(fname, entry->d_name); + rv = stat(fname, &sbuf); + assert(rv != -1); + if (S_ISCHR(sbuf.st_mode)) { + s_arr[current_count] = malloc((strlen(fname) + 1) * sizeof(char)); + strcpy(s_arr[current_count], fname); + current_count++; + } + } + closedir (dir); + } + } + return s_arr; +} + +static bool +test_bit(long bit, const long *field) +{ + return (field[bit / LONG_BITS] >> bit % LONG_BITS) & 1; +} + +static int +check_device_type(char* device) +{ + rtems_status_code sc; + struct evdev_test_message msg; + long bitsAbs[LONG_FIELD_SIZE(ABS_CNT)]; + long bitsKey[LONG_FIELD_SIZE(KEY_CNT)]; + long bitsRel[LONG_FIELD_SIZE(REL_CNT)]; + int ret = -1; + int rv; + int fd; + + if (!check_device_active(device)) { + fd = open(device, O_RDONLY); + if (fd != -1) { + memset(bitsAbs, 0, sizeof(bitsAbs)); + memset(bitsKey, 0, sizeof(bitsKey)); + memset(bitsRel, 0, sizeof(bitsRel)); + + rv = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs); + assert(rv != -1); + rv = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitsKey)), bitsKey); + assert(rv != -1); + rv = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(bitsRel)), bitsRel); + assert(rv != -1); + + close(fd); + + if (test_bit(KEY_Q, bitsKey)) { + printf("Found keyboard(%d) at %s\n", fd, device); + add_active_device(device); + strcpy(msg.device, device); + sc = rtems_message_queue_send(kmid, &msg, sizeof(msg)); + assert(sc == RTEMS_SUCCESSFUL); + ret = 0; + } + if (test_bit(REL_X, bitsRel) && test_bit(REL_Y, bitsRel) && test_bit(BTN_MOUSE, bitsKey)) { + printf("Found mouse(%d) at %s\n", fd, device); + add_active_device(device); + strcpy(msg.device, device); + sc = rtems_message_queue_send(mmid, &msg, sizeof(msg)); + assert(sc == RTEMS_SUCCESSFUL); + ret = 0; + } + if (test_bit(ABS_X, bitsAbs) && test_bit(ABS_Y, bitsAbs)) { + if (test_bit(BTN_TOOL_FINGER, bitsKey)) { + printf("Found touchpad(%d) at %s\n", fd, device); + add_active_device(device); + ret = 0; + } else if (test_bit(BTN_TOUCH, bitsKey)) { + printf("Found touchscreen(%d) at %s\n", fd, device); + add_active_device(device); + strcpy(msg.device, device); + sc = rtems_message_queue_send(tmid, &msg, sizeof(msg)); + assert(sc == RTEMS_SUCCESSFUL); + ret = 0; + } else if ((test_bit(BTN_STYLUS, bitsKey) || test_bit(BTN_TOOL_PEN, bitsKey))) { + printf("Found tablet(%d) at %s\n", fd, device); + add_active_device(device); + ret = 0; + } + } else if (test_bit(ABS_MT_POSITION_X, bitsAbs) && test_bit(ABS_MT_POSITION_Y, bitsAbs)) { + printf("Found new-style touchscreen(%d) at %s\n", fd, device); + add_active_device(device); + strcpy(msg.device, device); + sc = rtems_message_queue_send(tmid, &msg, sizeof(msg)); + assert(sc == RTEMS_SUCCESSFUL); + ret = 0; + } + if (test_bit(BTN_A, bitsKey) || test_bit(BTN_TRIGGER, bitsKey) || test_bit(ABS_RX, bitsAbs)) { + printf("Found joystick/gamepad(%d) at %s\n", fd, device); + add_active_device(device); + ret = 0; + } + if (ret == -1) { + printf("Unknown device(%d) at %s\n", fd, device); + } + } + } + return ret; +} + +static int +scan_for_devices(void) +{ + int device_count; + char** s_arr; + int ii; + + device_count = get_input_device_count(); + if (device_count > 0) { + s_arr = get_input_device_names(device_count); + if (s_arr != NULL) { + for (ii = 0; ii < device_count; ii++) { + check_device_type(s_arr[ii]); + free(s_arr[ii]); + } + free(s_arr); + } + } +} + +static void +evdev_scan_task(rtems_task_argument arg) +{ + rtems_status_code sc; + struct evdev_test_message msg; + uint32_t size; + + otask_active = true; + kill_otask = false; + while (!kill_otask) { + sc = rtems_message_queue_receive(omid, &msg, &size, RTEMS_WAIT, RTEMS_MILLISECONDS_TO_TICKS(1000)); + if (sc == RTEMS_SUCCESSFUL) { + while (!kill_otask) { + scan_for_devices(); + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000)); + } + } + } + otask_active = false; + rtems_task_delete(RTEMS_SELF); +} + +static void +process_keyboard_input_event(struct input_event *data) +{ + if (data->type != EV_KEY) + return; + print_message("Keyboard: %d,%d\n", data->code, data->value); +} + +static void +evdev_keyboard_task(rtems_task_argument arg) +{ + int fd, bytes, n, i, rv, grab; + struct input_event buffer[32]; + rtems_status_code sc; + struct evdev_test_message msg; + uint32_t size; + + ktask_active = true; + kill_ktask = false; + while (!kill_ktask) { + sc = rtems_message_queue_receive(kmid, &msg, &size, RTEMS_WAIT, RTEMS_MILLISECONDS_TO_TICKS(1000)); + if (sc == RTEMS_SUCCESSFUL) { + fd = open(msg.device, O_RDONLY | O_NONBLOCK); + if (fd != -1) { + grab = 1; + rv = ioctl(fd, EVIOCGRAB, &grab); + assert(rv == 0); + while (!kill_ttask) { + n = 0; + while (!kill_ttask) { + bytes = read(fd, (char*)buffer + n, sizeof(buffer) - n); + if (bytes == 0) { + print_message("evdevkeyboard: Got EOF from the input device\n"); + } else if (bytes < 0) { + if (errno != EINTR && errno != EAGAIN) { + print_message("evdevkeyboard: Could not read from input device\n"); + goto err; + } + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(10)); + } else { + n += bytes; + if (n % sizeof(buffer[0]) == 0) + break; + } + } + n /= sizeof(buffer[0]); + + for (i = 0; i < n; ++i) + process_keyboard_input_event(&buffer[i]); + } +err: + close(fd); + } + remove_active_device(msg.device); + } + } + ktask_active = false; + rtems_task_delete(RTEMS_SELF); +} + +static void +process_mouse_input_event(struct input_event *data) +{ + if (data->type == EV_ABS) { + /*Touchpads: store the absolute position for now, will calculate a relative one later.*/ + if (data->code == ABS_X) { + print_message("Mouse ABS: X = %d\n", data->value); + } else if (data->code == ABS_Y) { + print_message("Mouse ABS: Y = %d\n", data->value); + } + } else if (data->type == EV_REL) { + if (data->code == REL_X) { + print_message("Mouse REL: X = %d\n", data->value); + } else if (data->code == REL_Y) { + print_message("Mouse REL: Y = %d\n", data->value); + } else if (data->code == ABS_WHEEL) { /* vertical scroll */ + print_message("Mouse REL: W = %d\n", data->value); + } else if (data->code == ABS_THROTTLE) { /* horizontal scroll */ + print_message("Mouse REL: T = %d\n", data->value); + } + } else if (data->type == EV_KEY && data->code == BTN_TOUCH) { + print_message("Mouse Key: B = %d\n", data->value); + } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_JOYSTICK) { + print_message("Mouse Key: %d,%d\n", data->code, data->value); + } else if (data->type == EV_SYN && data->code == SYN_REPORT) { + print_message("Mouse Sync Report: %d\n", data->value); + } else if (data->type == EV_MSC && data->code == MSC_SCAN) { + print_message("Mouse MSC: %d,%d\n", data->code, data->value); + } +} + +static void +evdev_mouse_task(rtems_task_argument arg) +{ + int fd, bytes, n, i, rv, grab; + struct input_event buffer[32]; + rtems_status_code sc; + struct evdev_test_message msg; + uint32_t size; + + mtask_active = true; + kill_mtask = false; + while (!kill_mtask) { + sc = rtems_message_queue_receive(mmid, &msg, &size, RTEMS_WAIT, RTEMS_MILLISECONDS_TO_TICKS(1000)); + if (sc == RTEMS_SUCCESSFUL) { + fd = open(msg.device, O_RDONLY | O_NONBLOCK); + if (fd != -1) { + grab = 1; + rv = ioctl(fd, EVIOCGRAB, &grab); + assert(rv == 0); + while (!kill_ttask) { + n = 0; + while (!kill_ttask) { + bytes = read(fd, (char*)buffer + n, sizeof(buffer) - n); + if (bytes == 0) { + print_message("evdevmouse: Got EOF from the input device\n"); + } else if (bytes < 0) { + if (errno != EINTR && errno != EAGAIN) { + print_message("evdevmouse: Could not read from input device\n"); + goto err; + } + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(10)); + } else { + n += bytes; + if (n % sizeof(buffer[0]) == 0) + break; + } + } + n /= sizeof(buffer[0]); + + for (i = 0; i < n; ++i) + process_mouse_input_event(&buffer[i]); + } +err: + close(fd); + } + remove_active_device(msg.device); + } + } + mtask_active = false; + rtems_task_delete(RTEMS_SELF); +} + +static void +process_touch_input_event(struct input_event *data) +{ + if (data->type == EV_ABS) { + if (data->code == ABS_MT_POSITION_X || (data->code == ABS_X)) { + print_message("Touch ABS: X = %d\n", data->value); + } else if (data->code == ABS_MT_POSITION_Y || (data->code == ABS_Y)) { + print_message("Touch ABS: Y = %d\n", data->value); + } else if (data->code == ABS_MT_TRACKING_ID) { + print_message("Touch ABS: T = %d\n", data->value); + } else if (data->code == ABS_MT_TOUCH_MAJOR) { + print_message("Touch ABS: TM = %d\n", data->value); + } else if (data->code == ABS_PRESSURE) { + print_message("Touch ABS: P = %d\n", data->value); + } else if (data->code == ABS_MT_SLOT) { + print_message("Touch ABS: S = %d\n", data->value); + } + } else if (data->type == EV_KEY) { + if (data->code == BTN_TOUCH) + print_message("Touch Key: %d\n", data->value); + } else if (data->type == EV_SYN && data->code == SYN_REPORT) { + print_message("Touch Sync Report: %d\n", data->value); + } +} + +static void +evdev_touch_task(rtems_task_argument arg) +{ + int fd, n, i, bytes, rv, grab; + struct input_event buffer[32]; + rtems_status_code sc; + struct evdev_test_message msg; + uint32_t size; + + ttask_active = true; + kill_ttask = false; + while (!kill_ttask) { + sc = rtems_message_queue_receive(tmid, &msg, &size, RTEMS_WAIT, RTEMS_MILLISECONDS_TO_TICKS(1000)); + if (sc == RTEMS_SUCCESSFUL) { + fd = open(msg.device, O_RDONLY | O_NONBLOCK); + if (fd != -1) { + grab = 1; + rv = ioctl(fd, EVIOCGRAB, &grab); + assert(rv == 0); + while (!kill_ttask) { + n = 0; + while (!kill_ttask) { + bytes = read(fd, (char*)buffer + n, sizeof(buffer) - n); + if (bytes == 0) { + print_message("evdevtouch: Got EOF from the input device\n"); + } else if (bytes < 0) { + if (errno != EINTR && errno != EAGAIN) { + print_message("evdevtouch: Could not read from input device\n"); + goto err; + } + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(10)); + } else { + n += bytes; + if (n % sizeof(struct input_event) == 0) + break; + } + } + n /= sizeof(struct input_event); + + for (i = 0; i < n; ++i) + process_touch_input_event(&buffer[i]); + } +err: + close(fd); + } + remove_active_device(msg.device); + } + } + ttask_active = false; + rtems_task_delete(RTEMS_SELF); +} + +static void +Init(rtems_task_argument arg) +{ + rtems_status_code sc; + struct evdev_test_message msg; + + (void) arg; + puts("*** " TEST_NAME " TEST ***"); + + sc = rtems_semaphore_create( + rtems_build_name('E', 'V', 'D', 'S'), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, + RTEMS_NO_PRIORITY, + &psema); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_create( + rtems_build_name ('E', 'V', 'O', 'M'), + 16, + sizeof(struct evdev_test_message), + RTEMS_PRIORITY, + &omid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_create( + rtems_build_name ('E', 'V', 'K', 'M'), + 16, + sizeof(struct evdev_test_message), + RTEMS_PRIORITY, + &kmid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_create( + rtems_build_name ('E', 'V', 'M', 'M'), + 16, + sizeof(struct evdev_test_message), + RTEMS_PRIORITY, + &mmid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_create( + rtems_build_name ('E', 'V', 'T', 'M'), + 16, + sizeof(struct evdev_test_message), + RTEMS_PRIORITY, + &tmid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('E', 'V', 'D', 'K'), + PRIO_KEYBOARD, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &kid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('E', 'V', 'D', 'M'), + PRIO_MOUSE, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &mid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('E', 'V', 'D', 'T'), + PRIO_TOUCH, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &tid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('E', 'V', 'D', 'O'), + PRIO_OPEN, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &oid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(oid, evdev_scan_task, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(kid, evdev_keyboard_task, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(mid, evdev_mouse_task, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(tid, evdev_touch_task, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_bsd_initialize(); + assert(sc == RTEMS_SUCCESSFUL); + + msg.fd = -1; + rtems_message_queue_send(omid, &msg, sizeof(msg)); + + sc = rtems_shell_init("SHLL", 16 * 1024, 1, CONSOLE_DEVICE_NAME, + false, true, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + kill_otask = true; + kill_ktask = true; + kill_mtask = true; + kill_ttask = true; + while (otask_active || ktask_active || mtask_active || ttask_active) { + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(10)); + } + + delete_active_devices(); + + sc = rtems_message_queue_delete(omid); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_delete(kmid); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_delete(mmid); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_delete(tmid); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_semaphore_delete(psema); + assert(sc == RTEMS_SUCCESSFUL); + + exit(0); +} + +#define CONFIGURE_MICROSECONDS_PER_TICK 1000 + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK + +#define CONFIGURE_MAXIMUM_DRIVERS 32 + +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32 + +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 + +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_STACK_CHECKER_ENABLED + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024) +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + +#define CONFIGURE_INIT + +#include + +#include + +SYSINIT_DRIVER_REFERENCE(ukbd, uhub); +SYSINIT_DRIVER_REFERENCE(ums, uhub); + +#define CONFIGURE_SHELL_COMMANDS_INIT + +#include + +#include + +#define CONFIGURE_SHELL_USER_COMMANDS \ + &bsp_interrupt_shell_command, \ + &rtems_shell_SYSCTL_Command + +#define CONFIGURE_SHELL_COMMAND_CPUUSE +#define CONFIGURE_SHELL_COMMAND_PERIODUSE +#define CONFIGURE_SHELL_COMMAND_STACKUSE +#define CONFIGURE_SHELL_COMMAND_PROFREPORT + +#define CONFIGURE_SHELL_COMMAND_CP +#define CONFIGURE_SHELL_COMMAND_PWD +#define CONFIGURE_SHELL_COMMAND_LS +#define CONFIGURE_SHELL_COMMAND_LN +#define CONFIGURE_SHELL_COMMAND_LSOF +#define CONFIGURE_SHELL_COMMAND_CHDIR +#define CONFIGURE_SHELL_COMMAND_CD +#define CONFIGURE_SHELL_COMMAND_MKDIR +#define CONFIGURE_SHELL_COMMAND_RMDIR +#define CONFIGURE_SHELL_COMMAND_CAT +#define CONFIGURE_SHELL_COMMAND_MV +#define CONFIGURE_SHELL_COMMAND_RM +#define CONFIGURE_SHELL_COMMAND_MALLOC_INFO + +#include diff --git a/testsuite/usbkbd01/init.c b/testsuite/usbkbd01/init.c new file mode 100644 index 00000000..bec5a228 --- /dev/null +++ b/testsuite/usbkbd01/init.c @@ -0,0 +1,278 @@ +/*- + * COPYRIGHT (c) 2017 Kevin Kirspel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TEST_NAME "LIBBSD USB KEYBOARD" + +#define USB_SERIAL_TEST_BUFFER_SIZE 48 +#define PRIO_OPEN (RTEMS_MAXIMUM_PRIORITY - 12) +#define PRIO_READ (RTEMS_MAXIMUM_PRIORITY - 11) + +struct usb_test_message { + int fd; + char rbuf[USB_SERIAL_TEST_BUFFER_SIZE]; +}; + +static rtems_id oid, rid, omid, rmid; +static volatile bool kill_otask, kill_rtask; +static volatile bool otask_active, rtask_active; + +static void +usb_keyboard_read_task(rtems_task_argument arg) +{ + rtems_status_code sc; + struct usb_test_message msg; + uint32_t size; + int bytes; + + rtask_active = true; + kill_rtask = false; + while (!kill_rtask) { + while (!kill_rtask) { + sc = rtems_message_queue_receive(rmid, &msg, &size, RTEMS_WAIT, RTEMS_MILLISECONDS_TO_TICKS(1000)); + if (sc == RTEMS_SUCCESSFUL) { + if (msg.fd > 0) { + break; + } else { + printf("Invalid file descriptor\n"); + } + } + } + while (!kill_rtask) { + msg.rbuf[0] = 0; + bytes = read(msg.fd, &msg.rbuf[0], 1); + if (bytes == 0) { + printf("Got EOF from the input device\n"); + } else if (bytes < 0) { + if (errno != EINTR && errno != EAGAIN) { + printf("Could not read from input device\n"); + break; + } + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(10)); + } else { + printf("%c", msg.rbuf[0]); + fflush(stdout); + } + } + msg.fd = -1; + rtems_message_queue_send(omid, &msg, sizeof(msg)); + } + rtask_active = false; + rtems_task_delete(RTEMS_SELF); +} + +static void +usb_keyboard_open_task(rtems_task_argument arg) +{ + rtems_status_code sc; + struct usb_test_message msg; + struct termios t; + uint32_t size; + int fd, iret; + + fd = -2; + otask_active = true; + kill_otask = false; + while (!kill_otask) { + sc = rtems_message_queue_receive(omid, &msg, &size, RTEMS_WAIT, RTEMS_MILLISECONDS_TO_TICKS(1000)); + if (sc == RTEMS_SUCCESSFUL) { + if (fd >= 0) { + close(fd); + printf("keyboard device closed\n"); + } + fd = msg.fd; + } + if (fd == -1) { + fd = open("/dev/ukbd0", O_RDWR | O_NONBLOCK); + if (fd != -1) { + printf("keyboard device opened: %d\n", fd); + msg.fd = fd; + rtems_message_queue_send(rmid, &msg, sizeof(msg)); + } + else { + /*printf("keyboard device open failed: %d\n", errno);*/ + } + } + } + if (fd >= 0) { + close(fd); + printf("keyboard device closed\n"); + } + otask_active = false; + rtems_task_delete(RTEMS_SELF); +} + +static void +Init(rtems_task_argument arg) +{ + rtems_status_code sc; + struct usb_test_message msg; + + (void) arg; + puts("*** " TEST_NAME " TEST ***"); + + sc = rtems_message_queue_create( + rtems_build_name ('M', 'U', 'O', 'P'), + 16, + sizeof(struct usb_test_message), + RTEMS_PRIORITY, + &omid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_create( + rtems_build_name ('M', 'U', 'R', 'D'), + 16, + sizeof(struct usb_test_message), + RTEMS_PRIORITY, + &rmid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('U', 'S', 'B', 'R'), + PRIO_READ, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &rid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('U', 'S', 'B', 'O'), + PRIO_OPEN, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &oid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(rid, usb_keyboard_read_task, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(oid, usb_keyboard_open_task, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_bsd_initialize(); + assert(sc == RTEMS_SUCCESSFUL); + + msg.fd = -1; + rtems_message_queue_send(omid, &msg, sizeof(msg)); + + sc = rtems_shell_init("SHLL", 16 * 1024, 1, CONSOLE_DEVICE_NAME, + false, true, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + kill_otask = true; + kill_rtask = true; + while (otask_active || rtask_active) { + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(10)); + } + + sc = rtems_message_queue_delete(rmid); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_delete(omid); + assert(sc == RTEMS_SUCCESSFUL); + + exit(0); +} + +#define CONFIGURE_MICROSECONDS_PER_TICK 1000 + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK + +#define CONFIGURE_MAXIMUM_DRIVERS 32 + +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32 + +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 + +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_STACK_CHECKER_ENABLED + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024) +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + +#define CONFIGURE_INIT + +#include + +#include + +SYSINIT_DRIVER_REFERENCE(ukbd, uhub); + +#define CONFIGURE_SHELL_COMMANDS_INIT + +#include + +#include + +#define CONFIGURE_SHELL_USER_COMMANDS \ + &bsp_interrupt_shell_command, \ + &rtems_shell_SYSCTL_Command + +#define CONFIGURE_SHELL_COMMAND_CPUUSE +#define CONFIGURE_SHELL_COMMAND_PERIODUSE +#define CONFIGURE_SHELL_COMMAND_STACKUSE +#define CONFIGURE_SHELL_COMMAND_PROFREPORT + +#define CONFIGURE_SHELL_COMMAND_CP +#define CONFIGURE_SHELL_COMMAND_PWD +#define CONFIGURE_SHELL_COMMAND_LS +#define CONFIGURE_SHELL_COMMAND_LN +#define CONFIGURE_SHELL_COMMAND_LSOF +#define CONFIGURE_SHELL_COMMAND_CHDIR +#define CONFIGURE_SHELL_COMMAND_CD +#define CONFIGURE_SHELL_COMMAND_MKDIR +#define CONFIGURE_SHELL_COMMAND_RMDIR +#define CONFIGURE_SHELL_COMMAND_CAT +#define CONFIGURE_SHELL_COMMAND_MV +#define CONFIGURE_SHELL_COMMAND_RM +#define CONFIGURE_SHELL_COMMAND_MALLOC_INFO + +#include diff --git a/testsuite/usbmouse01/init.c b/testsuite/usbmouse01/init.c new file mode 100644 index 00000000..b607c2a6 --- /dev/null +++ b/testsuite/usbmouse01/init.c @@ -0,0 +1,283 @@ +/*- + * COPYRIGHT (c) 2017 Kevin Kirspel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This test requires a USB mouse to be attached to a USB port. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TEST_NAME "LIBBSD USB MOUSE" + +#define USB_SERIAL_TEST_BUFFER_SIZE 48 +#define PRIO_OPEN (RTEMS_MAXIMUM_PRIORITY - 12) +#define PRIO_READ (RTEMS_MAXIMUM_PRIORITY - 11) + +struct usb_test_message { + int fd; + char rbuf[USB_SERIAL_TEST_BUFFER_SIZE]; +}; + +static rtems_id oid, rid, omid, rmid; +static volatile bool kill_otask, kill_rtask; +static volatile bool otask_active, rtask_active; + +static void +usb_mouse_read_task(rtems_task_argument arg) +{ + rtems_status_code sc; + struct usb_test_message msg; + uint32_t size; + int bytes; + + rtask_active = true; + kill_rtask = false; + while (!kill_rtask) { + while (!kill_rtask) { + sc = rtems_message_queue_receive(rmid, &msg, &size, RTEMS_WAIT, RTEMS_MILLISECONDS_TO_TICKS(1000)); + if (sc == RTEMS_SUCCESSFUL) { + if (msg.fd > 0) { + break; + } else { + printf("Invalid file descriptor\n"); + } + } + } + while (!kill_rtask) { + msg.rbuf[0] = 0; + bytes = read(msg.fd, &msg.rbuf[0], 1); + if (bytes == 0) { + printf("Got EOF from the input device\n"); + } else if (bytes < 0) { + if (errno != EINTR && errno != EAGAIN) { + printf("Could not read from input device\n"); + break; + } + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(10)); + } else { + printf("received char: 0x%02X\n", msg.rbuf[0]); + } + } + msg.fd = -1; + rtems_message_queue_send(omid, &msg, sizeof(msg)); + } + + rtask_active = false; + rtems_task_delete(RTEMS_SELF); +} + +static void +usb_mouse_open_task(rtems_task_argument arg) +{ + rtems_status_code sc; + struct usb_test_message msg; + struct termios t; + uint32_t size; + int fd, iret; + + fd = -2; + otask_active = true; + kill_otask = false; + while (!kill_otask) { + sc = rtems_message_queue_receive(omid, &msg, &size, RTEMS_WAIT, RTEMS_MILLISECONDS_TO_TICKS(1000)); + if (sc == RTEMS_SUCCESSFUL) { + if (fd >= 0) { + close(fd); + printf("mouse device closed\n"); + } + fd = msg.fd; + } + if (fd == -1) { + fd = open("/dev/ums0", O_RDWR | O_NONBLOCK); + if (fd != -1) { + printf("mouse device opened: %d\n", fd); + msg.fd = fd; + rtems_message_queue_send(rmid, &msg, sizeof(msg)); + } + else { + /*printf("mouse device open failed: %d\n", errno);*/ + } + } + } + if (fd >= 0) { + close(fd); + printf("mouse device closed\n"); + } + otask_active = false; + rtems_task_delete(RTEMS_SELF); +} + +static void +Init(rtems_task_argument arg) +{ + rtems_status_code sc; + struct usb_test_message msg; + + (void) arg; + puts("*** " TEST_NAME " TEST ***"); + + sc = rtems_message_queue_create( + rtems_build_name ('M', 'U', 'O', 'P'), + 16, + sizeof(struct usb_test_message), + RTEMS_PRIORITY, + &omid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_create( + rtems_build_name ('M', 'U', 'R', 'D'), + 16, + sizeof(struct usb_test_message), + RTEMS_PRIORITY, + &rmid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('U', 'S', 'B', 'R'), + PRIO_READ, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &rid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_create( + rtems_build_name('U', 'S', 'B', 'O'), + PRIO_OPEN, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_FLOATING_POINT, + &oid + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(rid, usb_mouse_read_task, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(oid, usb_mouse_open_task, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_bsd_initialize(); + assert(sc == RTEMS_SUCCESSFUL); + + msg.fd = -1; + rtems_message_queue_send(omid, &msg, sizeof(msg)); + + sc = rtems_shell_init("SHLL", 16 * 1024, 1, CONSOLE_DEVICE_NAME, + false, true, NULL); + assert(sc == RTEMS_SUCCESSFUL); + + kill_otask = true; + kill_rtask = true; + while (otask_active || rtask_active) { + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(10)); + } + + sc = rtems_message_queue_delete(rmid); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_message_queue_delete(omid); + assert(sc == RTEMS_SUCCESSFUL); + + exit(0); +} + +#define CONFIGURE_MICROSECONDS_PER_TICK 1000 + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK + +#define CONFIGURE_MAXIMUM_DRIVERS 32 + +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32 + +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 + +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_STACK_CHECKER_ENABLED + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024) +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + +#define CONFIGURE_INIT + +#include + +#include + +SYSINIT_DRIVER_REFERENCE(ums, uhub); + +#define CONFIGURE_SHELL_COMMANDS_INIT + +#include + +#include + +#define CONFIGURE_SHELL_USER_COMMANDS \ + &bsp_interrupt_shell_command, \ + &rtems_shell_SYSCTL_Command + +#define CONFIGURE_SHELL_COMMAND_CPUUSE +#define CONFIGURE_SHELL_COMMAND_PERIODUSE +#define CONFIGURE_SHELL_COMMAND_STACKUSE +#define CONFIGURE_SHELL_COMMAND_PROFREPORT + +#define CONFIGURE_SHELL_COMMAND_CP +#define CONFIGURE_SHELL_COMMAND_PWD +#define CONFIGURE_SHELL_COMMAND_LS +#define CONFIGURE_SHELL_COMMAND_LN +#define CONFIGURE_SHELL_COMMAND_LSOF +#define CONFIGURE_SHELL_COMMAND_CHDIR +#define CONFIGURE_SHELL_COMMAND_CD +#define CONFIGURE_SHELL_COMMAND_MKDIR +#define CONFIGURE_SHELL_COMMAND_RMDIR +#define CONFIGURE_SHELL_COMMAND_CAT +#define CONFIGURE_SHELL_COMMAND_MV +#define CONFIGURE_SHELL_COMMAND_RM +#define CONFIGURE_SHELL_COMMAND_MALLOC_INFO + +#include -- cgit v1.2.3