驅動程式 - VxWorks - 23.09 - C/C++ - Select Operation



參考資訊:
https://zhuanlan.zhihu.com/p/597577575
https://blog.csdn.net/tttt234567890/article/details/7094636
https://studies.ac.upc.edu/doctorat/ENGRAP/VxWorks-device-drivers.htm
https://forums.windriver.com/t/vxworks-software-development-kit-sdk/43
https://mail.prz-rzeszow.pl/~ssamolej/vxworks/vxworks_kernel_programmers_guide_6.6.pdf
https://d13321s3lxgewa.cloudfront.net/downloads/wrsdk-vxworks7-docs/2309/README_qemu.html
https://learning.windriver.com/path/vxworks7-essentials-workbench-and-tools/vxworks-kernel-shell
https://www.ecb.torontomu.ca/~courses/ee8205/Data-Sheets/Tornado-VxWorks/vxworks/ref/selectLib.html#selWakeupListInit

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iosLib.h>
#include <selectLib.h>

static int drvNum = {0};
static DEV_HDR hdr = {0};
static SEL_WAKEUP_LIST selWakeupList = {0};

static void* myOpen(struct dev_hdr *dev, const char *remainder, int access, int mode)
{
    if (remainder[0] != '\0') {
        return NULL;
    }

    printf("%s()\n", __func__);
    return dev;
}
 
static STATUS myClose(void *dev)
{
    if (dev == NULL) {
        return ERROR;
    }

    printf("%s()\n", __func__);
    return OK;
}

static long myRead(void *dev, char *rbuf, size_t rbytes)
{
    if (dev == NULL) {
        return 0;
    }

    printf("%s()\n", __func__);
    return 0;
}

static long myWrite(void *dev, const char *wbuf, size_t wbytes)
{
    if (dev == NULL) {
        return 0;
    }

    printf("%s()\n", __func__);
    return 0;
}

static STATUS myIOCTL(void *dev, int cmd, long arg)
{
    SEL_WAKEUP_NODE *node = (SEL_WAKEUP_NODE *)arg;

    if (dev == NULL) {
        return ERROR;
    }

    switch (cmd) {
    case FIOSELECT:
        if (selNodeAdd(&selWakeupList, node) == OK) {
            if (selWakeupType(node) == SELREAD) {
                printf("%s(), wakeup\n", __func__);
                selWakeupAll(&selWakeupList, SELREAD);
            }
        }
        break;
    case FIOUNSELECT:
        selNodeDelete(&selWakeupList, (SEL_WAKEUP_NODE *)arg);
        break;
    }
    return OK;
}

STATUS myProbe(void)
{
    drvNum = iosDrvInstall(NULL, NULL, myOpen, myClose, myRead, myWrite, myIOCTL);
    iosDevAdd(&hdr, "/dev/hello", drvNum);
    selWakeupListInit(&selWakeupList);
    return OK;
}

app.c

#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/select.h>
#include <fcntl.h>

#define BUF_SIZE 255
#define DEV_NAME "/dev/hello"

static char buf[BUF_SIZE] = {0};

int main(int argc, char **argv)
{
    int fd = open(DEV_NAME, O_RDONLY);
    if (fd < 0) {
        printf("Failed tp open "DEV_NAME"\n");
        return -1;
    }

    fd_set rfds;
    struct timeval tv;

    tv.tv_sec = 5;
    tv.tv_usec = 0;
    while (1) {
        FD_ZERO(&rfds);
        FD_SET(fd, &rfds);

        int ret = select(fd + 1, &rfds, NULL, NULL, &tv);
        if (ret == -1) {
            return -1;
        }
        else if (ret > 0) {
            read(fd, buf, BUF_SIZE);
            break;
        }
    }
    close(fd);
    return 0;
}

編譯

$ wr-cc main.c -o hello -dkm
$ wr-cc app.c -o app -dkm

執行

-> ld < hello
    value = -140737379950592 = 0xffff800006762000 = _sysTableEnd + 0xffff800006354000

-> sp myProbe
    Task spawned: id = 0xffff80000035bab0, name = t1
    value = -140737484834128 = 0xffff80000035bab0 = _sysTableEnd + 0xffff7ffffff4dab0

-> devs
    drv refs name
     22 [ 5] /dev/hello
     13 [ 5] /dev/random
     13 [ 5] /dev/urandom
     12 [ 5] /dev/zero
     11 [ 5] /fifos
     16 [ 5] /host.host
     14 [ 5] /input/event
      0 [ 7] /null
      5 [ 5] /ram
     10 [ 5] /ram0
      9 [ 5] /romfs
      3 [ 5] /shm
     10 [ 5] /tmp
      2 [ 7] /ttyS0
    value = 0 = 0x0

-> cmd
[vxWorks *]# app
    Launching process 'app' ...
    Process 'app' (process Id = 0xffff80000035c640) launched.
    myOpen()
    myIOCTL(), wakeup
    myRead()
    myClose()