Skip to content

Commit

Permalink
libusb: move process driver implementation to separate source file
Browse files Browse the repository at this point in the history
JIRA: RTOS-970
  • Loading branch information
adamgreloch committed Dec 2, 2024
1 parent 4aa29b4 commit 5ccd210
Show file tree
Hide file tree
Showing 5 changed files with 366 additions and 328 deletions.
3 changes: 2 additions & 1 deletion libusb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
NAME := libusb
LOCAL_PATH := $(call my-dir)
HEADERS := $(wildcard $(LOCAL_PATH)*.h)
LOCAL_SRCS := cdc_client.c hid_client.c driver.c
LOCAL_SRCS := cdc_client.c hid_client.c driver.c procdriver.c
LOCAL_CFLAGS := -I$(LOCAL_PATH)

include $(static-lib.mk)
325 changes: 1 addition & 324 deletions libusb/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,16 @@
*/

#include <errno.h>
#include <signal.h>
#include <usbdriver.h>
#include <sys/msg.h>
#include <sys/threads.h>
#include <sys/list.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>


#ifndef USB_N_UMSG_THREADS
#define USB_N_UMSG_THREADS 2
#endif

#ifndef USB_UMSG_PRIO
#define USB_UMSG_PRIO 3
#endif


static usb_pipeOps_t usbprocdrv_pipeOps;
#include <usbdriver.h>


static struct {
#ifndef USB_INTERNAL_ONLY
char ustack[USB_N_UMSG_THREADS - 1][2048] __attribute__((aligned(8)));
unsigned srvport;
unsigned drvport;
#endif
usb_driver_t *registeredDrivers;
} usbdrv_common;

Expand Down Expand Up @@ -84,226 +66,6 @@ int usb_transferAsync(usb_driver_t *drv, unsigned pipe, unsigned urbid, size_t s
}


#ifndef USB_INTERNAL_ONLY
static void usb_hostLookup(oid_t *oid)
{
int ret;

for (;;) {
ret = lookup("devfs/usb", NULL, oid);
if (ret >= 0) {
break;
}

ret = lookup("/dev/usb", NULL, oid);
if (ret >= 0) {
break;
}

usleep(1000000);
}
}


static void usb_thread(void *arg)
{
usb_driver_t *drv = (usb_driver_t *)arg;
msg_t msg = { 0 };
usb_msg_t *umsg = (usb_msg_t *)&msg.i.raw;
int ret;

for (;;) {
ret = usb_eventsWait(usbdrv_common.drvport, &msg);
if (ret < 0) {
fprintf(stderr, "usbdrv: error when receiving event from host\n");
continue;
}

switch (umsg->type) {
case usb_msg_insertion:
drv->handlers->insertion(drv, &umsg->insertion);
break;
case usb_msg_deletion:
drv->handlers->deletion(drv, &umsg->deletion);
break;
case usb_msg_completion:
drv->handlers->completion(drv, &umsg->completion, msg.i.data, msg.i.size);
break;
default:
fprintf(stderr, "usbdrv: unknown msg type\n");
break;
}
}
}


static void usb_signalExit(int sig)
{
exit(EXIT_SUCCESS);
}


static int usb_connect(const usb_device_id_t *filters, unsigned int nfilters)
{
msg_t msg = { 0 };
usb_msg_t *umsg = (usb_msg_t *)&msg.i.raw;

msg.type = mtDevCtl;
msg.i.size = sizeof(*filters) * nfilters;
msg.i.data = (void *)filters;

umsg->type = usb_msg_connect;
umsg->connect.port = usbdrv_common.drvport;
umsg->connect.nfilters = nfilters;

return msgSend(usbdrv_common.srvport, &msg) < 0;
}


int usb_driverProcRun(usb_driver_t *drv, bool daemonize, void *args)
{
oid_t oid;
int ret, i;
pid_t pid;

/* usb_driverProcRun is invoked iff drivers are in the proc variant */
drv->pipeOps = &usbprocdrv_pipeOps;

if (daemonize) {
/* Set parent exit handler */
signal(SIGUSR1, usb_signalExit);

/* Daemonize server */
pid = fork();
if (pid < 0) {
fprintf(stderr, "usbdrv: failed to daemonize server\n");
exit(EXIT_FAILURE);
}
else if (pid > 0) {
/* Parent waits to be killed by the child after finished server initialization */
sleep(10);
fprintf(stderr, "usbdrv: failed to successfully initialize server\n");
exit(EXIT_FAILURE);
}

/* Set child exit handler */
signal(SIGUSR1, usb_signalExit);

ret = setsid();
if (ret < 0) {
fprintf(stderr, "usbdrv: failed to create new session\n");
exit(EXIT_FAILURE);
}
}

ret = drv->ops->init(drv, args);
if (ret < 0) {
return -1;
}

if (daemonize) {
/* Finished server initialization - kill parent */
kill(getppid(), SIGUSR1);
}

usb_hostLookup(&oid);
usbdrv_common.srvport = oid.port;

ret = portCreate(&usbdrv_common.drvport);
if (ret != 0) {
return -1;
}

ret = usb_connect(drv->filters, drv->nfilters);
if (ret < 0) {
return -1;
}

for (i = 0; i < USB_N_UMSG_THREADS - 1; i++) {
ret = beginthread(usb_thread, USB_UMSG_PRIO, usbdrv_common.ustack[i], sizeof(usbdrv_common.ustack[i]), drv);
if (ret < 0) {
fprintf(stderr, "usbdrv: fail to beginthread ret: %d\n", ret);
return -1;
}
}

priority(USB_UMSG_PRIO);
usb_thread(drv);

return 0;
}


int usb_eventsWait(int port, msg_t *msg)
{
msg_rid_t rid;
int err;

do {
err = msgRecv(port, msg, &rid);
if (err < 0 && err != -EINTR)
return -1;
} while (err == -EINTR);

if (msgRespond(port, msg, rid) < 0)
return -1;

return 0;
}


static int usbprocdrv_open(usb_driver_t *drv, usb_devinfo_t *dev, usb_transfer_type_t type, usb_dir_t dir)
{
msg_t msg = { 0 };
usb_msg_t *umsg = (usb_msg_t *)msg.i.raw;
int ret;

msg.type = mtDevCtl;
umsg->type = usb_msg_open;

umsg->open.bus = dev->bus;
umsg->open.dev = dev->dev;
umsg->open.iface = dev->interface;
umsg->open.type = type;
umsg->open.dir = dir;
umsg->open.locationID = dev->locationID;

ret = msgSend(usbdrv_common.srvport, &msg);
if (ret != 0) {
return ret;
}

return msg.o.err;
}


static int usbprocdrv_urbSubmitSync(usb_driver_t *drv, usb_urb_t *urb, void *data)
{
msg_t msg = { 0 };
usb_msg_t *umsg = (usb_msg_t *)msg.i.raw;
int ret;

msg.type = mtDevCtl;
umsg->type = usb_msg_urb;

memcpy(&umsg->urb, urb, sizeof(usb_urb_t));

if (urb->dir == usb_dir_out) {
msg.i.data = data;
msg.i.size = urb->size;
}
else {
msg.o.data = data;
msg.o.size = urb->size;
}

if ((ret = msgSend(usbdrv_common.srvport, &msg)) != 0)
return ret;

return msg.o.err;
}


int usb_transferControl(usb_driver_t *drv, unsigned pipe, usb_setup_packet_t *setup, void *data, size_t size, usb_dir_t dir)
{
usb_urb_t urb = {
Expand Down Expand Up @@ -361,79 +123,6 @@ int usb_clearFeatureHalt(usb_driver_t *drv, unsigned pipe, int ep)
}


static int usbprocdrv_urbAlloc(usb_driver_t *drv, unsigned pipe, void *data, usb_dir_t dir, size_t size, int type)
{
msg_t msg = { 0 };
usb_msg_t *umsg = (usb_msg_t *)msg.i.raw;
int ret;
usb_urb_t *urb = &umsg->urb;

urb->pipe = pipe;
urb->type = type;
urb->dir = dir;
urb->size = size;
urb->sync = 0;

msg.type = mtDevCtl;
umsg->type = usb_msg_urb;

ret = msgSend(usbdrv_common.srvport, &msg);
if (ret < 0) {
return ret;
}

/* URB id */
return msg.o.err;
}


static int usbprocdrv_transferAsync(usb_driver_t *drv, unsigned pipe, unsigned urbid, size_t size, usb_setup_packet_t *setup)
{
msg_t msg = { 0 };
usb_msg_t *umsg = (usb_msg_t *)msg.i.raw;
int ret;
usb_urbcmd_t *urbcmd = &umsg->urbcmd;

urbcmd->pipeid = pipe;
urbcmd->size = size;
urbcmd->urbid = urbid;
urbcmd->cmd = urbcmd_submit;

if (setup != NULL) {
memcpy(&urbcmd->setup, setup, sizeof(*setup));
}
msg.type = mtDevCtl;
umsg->type = usb_msg_urbcmd;
ret = msgSend(usbdrv_common.srvport, &msg);
if (ret < 0) {
return ret;
}

return 0;
}


static int usbprocdrv_urbFree(usb_driver_t *drv, unsigned pipe, unsigned urb)
{
msg_t msg = { 0 };
usb_msg_t *umsg = (usb_msg_t *)msg.i.raw;
int ret;
usb_urbcmd_t *urbcmd = &umsg->urbcmd;

urbcmd->pipeid = pipe;
urbcmd->urbid = urb;
urbcmd->cmd = urbcmd_free;

msg.type = mtDevCtl;
umsg->type = usb_msg_urbcmd;
if ((ret = msgSend(usbdrv_common.srvport, &msg)) < 0)
return ret;

return 0;
}
#endif


const usb_modeswitch_t *usb_modeswitchFind(uint16_t vid, uint16_t pid, const usb_modeswitch_t *modes, int nmodes)
{
int i;
Expand Down Expand Up @@ -550,15 +239,3 @@ int usb_modeswitchHandle(usb_driver_t *drv, usb_devinfo_t *dev, const usb_modesw

return 0;
}


#ifndef USB_INTERNAL_ONLY
static usb_pipeOps_t usbprocdrv_pipeOps = {
.open = usbprocdrv_open,
.submitSync = usbprocdrv_urbSubmitSync,
.transferAsync = usbprocdrv_transferAsync,

.urbFree = usbprocdrv_urbFree,
.urbAlloc = usbprocdrv_urbAlloc,
};
#endif
Loading

0 comments on commit 5ccd210

Please sign in to comment.