Upgrade libddekit and introduce devmand.
Devmand (Device manager daemon) is the daemon that will dynamically manage services based on events received from the system.
This commit is contained in:
parent
6b8821515d
commit
ade7dc8ded
16 changed files with 1219 additions and 61 deletions
|
@ -8,7 +8,7 @@ SUBDIR= add_route arp ash at awk \
|
|||
cawf cd cdprobe checkhier cpp \
|
||||
chmod chown ci cksum cleantmp clear cmp co \
|
||||
comm compress cp crc cron crontab cut \
|
||||
dd decomp16 DESCRIBE dev2name devsize df dhcpd \
|
||||
dd decomp16 DESCRIBE dev2name devmand devsize df dhcpd \
|
||||
dhrystone diff dirname diskctl dumpcore \
|
||||
eject elvis env expand factor fbdctl \
|
||||
find finger fingerd fix fold format fortune fsck.mfs \
|
||||
|
|
15
commands/devmand/Makefile
Normal file
15
commands/devmand/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
PROG = devmand
|
||||
|
||||
SRCS = main.c lex.yy.c y.tab.c
|
||||
|
||||
lex.yy.c: usb_scan.l y.tab.h
|
||||
${LEX} usb_scan.l
|
||||
|
||||
y.tab.c y.tab.h: usb.y
|
||||
${YACC} -d usb.y
|
||||
|
||||
CLEANFILES = y.tab.c y.tab.h *.d lex.yy.c lex.yy.o main.o y.tab.o
|
||||
MAN =
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
|
45
commands/devmand/devmand.cfg
Normal file
45
commands/devmand/devmand.cfg
Normal file
|
@ -0,0 +1,45 @@
|
|||
usb_driver usb_storage
|
||||
{
|
||||
binary = /usr/sbin/usb_storage;
|
||||
id {
|
||||
bInterfaceClass = 0x08;
|
||||
}
|
||||
devprefix = usbstor;
|
||||
upscript = /etc/devmand/scripts/block;
|
||||
downscript = /etc/devmand/scripts/block;
|
||||
}
|
||||
|
||||
usb_driver usb_keyboard
|
||||
{
|
||||
binary = /usr/sbin/usb_hid;
|
||||
id {
|
||||
bInterfaceClass = 0x3;
|
||||
bInterfaceProtocol = 0x1;
|
||||
}
|
||||
upscript = /etc/devmand/scripts/singlechar;
|
||||
downscript = /etc/devmand/scripts/singlechar;
|
||||
devprefix = usb_keyboard;
|
||||
}
|
||||
|
||||
usb_driver usb_mouse
|
||||
{
|
||||
binary = /usr/sbin/usb_hid;
|
||||
id {
|
||||
bInterfaceClass = 0x3;
|
||||
bInterfaceProtocol = 0x2;
|
||||
}
|
||||
upscript = /etc/devmand/scripts/singlechar;
|
||||
downscript = /etc/devmand/scripts/singlechar;
|
||||
devprefix = usb_mouse;
|
||||
}
|
||||
|
||||
usb_driver usb_hid
|
||||
{
|
||||
binary = /usr/sbin/usb_hid;
|
||||
id {
|
||||
bInterfaceClass = 0x3;
|
||||
}
|
||||
upscript = /etc/devmand/scripts/singlechar;
|
||||
downscript = /etc/devmand/scripts/singlechar;
|
||||
devprefix = usb_keyboard;
|
||||
}
|
847
commands/devmand/main.c
Normal file
847
commands/devmand/main.c
Normal file
|
@ -0,0 +1,847 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <lib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include "usb_driver.h"
|
||||
#include "proto.h"
|
||||
|
||||
#define CONTROL_FIFO_PATH "/var/tmp/devmand_control"
|
||||
#define SERVICE_BINARY "/bin/service"
|
||||
|
||||
|
||||
#define DEVMAN_TYPE_NAME "dev_type"
|
||||
#define PATH_LEN 256
|
||||
#define INVAL_MAJOR -1
|
||||
|
||||
static void main_loop();
|
||||
static void handle_event();
|
||||
static void cleanup();
|
||||
static void parse_config();
|
||||
static void display_usage();
|
||||
static enum dev_type determine_type(char *path);
|
||||
static int get_major();
|
||||
static void create_pid_file();
|
||||
static void put_major(int major);
|
||||
static struct devmand_usb_driver* match_usb_driver(struct usb_device_id *id);
|
||||
static struct devmand_driver_instance *find_instance(int dev_id);
|
||||
|
||||
#define dbg(fmt, ... ) \
|
||||
if (args.verbose) \
|
||||
printf("%8s:%4d: %13s()| "fmt"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__ )
|
||||
|
||||
static LIST_HEAD(usb_driver_head, devmand_usb_driver) drivers =
|
||||
LIST_HEAD_INITIALIZER(drivers);
|
||||
static LIST_HEAD(usb_driver_inst_head, devmand_driver_instance) instances =
|
||||
LIST_HEAD_INITIALIZER(instances);
|
||||
|
||||
|
||||
static int _run = 1;
|
||||
struct global_args {
|
||||
int deamonize;
|
||||
char *path;
|
||||
char *config;
|
||||
int major_offset;
|
||||
int verbose;
|
||||
};
|
||||
|
||||
enum dev_type {
|
||||
DEV_TYPE_USB_DEVICE,
|
||||
DEV_TYPE_USB_INTF,
|
||||
DEV_TYPE_UNKOWN
|
||||
};
|
||||
|
||||
extern FILE *yyin;
|
||||
|
||||
static struct global_args args = {0,NULL,NULL,25, 0};
|
||||
|
||||
static struct option options[] =
|
||||
{
|
||||
{"deamonize", no_argument, NULL, 'd'},
|
||||
{"path", required_argument, NULL, 'p'},
|
||||
{"config", required_argument, NULL, 'c'},
|
||||
{"verbose", required_argument, NULL, 'v'},
|
||||
{0,0,0,0} /* terminating entry */
|
||||
};
|
||||
|
||||
static char major_bitmap[16]; /* can store up to 128 major number states */
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* run_upscript *
|
||||
*===========================================================================*/
|
||||
int run_upscript(struct devmand_driver_instance *inst)
|
||||
{
|
||||
char cmdl[1024];
|
||||
cmdl[0] = 0;
|
||||
int ret;
|
||||
|
||||
snprintf(cmdl, 1024, "%s up %s %d %d",
|
||||
inst->drv->upscript, inst->label, inst->major, inst->dev_id);
|
||||
dbg("Running Upscript: \"%s\"", cmdl);
|
||||
ret = system(cmdl);
|
||||
if (ret != 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* run_cleanscript *
|
||||
*===========================================================================*/
|
||||
int run_cleanscript(struct devmand_usb_driver *drv)
|
||||
{
|
||||
char cmdl[1024];
|
||||
cmdl[0] = 0;
|
||||
int ret;
|
||||
|
||||
snprintf(cmdl, 1024, "%s clean %s ",
|
||||
drv->upscript, drv->devprefix);
|
||||
dbg("Running Upscript: \"%s\"", cmdl);
|
||||
ret = system(cmdl);
|
||||
|
||||
if (ret != 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* run_downscript *
|
||||
*===========================================================================*/
|
||||
int run_downscript(struct devmand_driver_instance *inst)
|
||||
{
|
||||
char cmdl[1024];
|
||||
cmdl[0] = 0;
|
||||
int ret;
|
||||
|
||||
snprintf(cmdl, 1024, "%s down %s %d",
|
||||
inst->drv->downscript, inst->label, inst->major);
|
||||
|
||||
dbg("Running Upscript: \"%s\"", cmdl);
|
||||
|
||||
ret = system(cmdl);
|
||||
|
||||
if (ret != 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* stop_driver *
|
||||
*===========================================================================*/
|
||||
int stop_driver(struct devmand_driver_instance *inst)
|
||||
{
|
||||
char cmdl[1024];
|
||||
cmdl[0] = 0;
|
||||
int ret;
|
||||
|
||||
snprintf(cmdl, 1024, "%s down %s %d",
|
||||
SERVICE_BINARY, inst->label, inst->dev_id);
|
||||
dbg("executing service: \"%s\"", cmdl);
|
||||
ret = system(cmdl);
|
||||
if (ret != 0)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
printf("Stopped driver %s with label %s for device %d.\n",
|
||||
inst->drv->binary, inst->label, inst->dev_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* start_driver *
|
||||
*===========================================================================*/
|
||||
int start_driver(struct devmand_driver_instance *inst)
|
||||
{
|
||||
char cmdl[1024];
|
||||
cmdl[0] = 0;
|
||||
int ret;
|
||||
|
||||
/* generate label */
|
||||
ret = snprintf(inst->label, 32, "%s%d", inst->drv->devprefix,
|
||||
inst->dev_id);
|
||||
if (ret < 0 || ret > DEVMAND_DRIVER_LABEL_LEN) {
|
||||
dbg("label too long");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
snprintf(cmdl, 1024, "%s up %s -major %d -devid %d -label %s",
|
||||
SERVICE_BINARY, inst->drv->binary, inst->major, inst->dev_id,
|
||||
inst->label);
|
||||
dbg("executing service: \"%s\"", cmdl);
|
||||
|
||||
ret = system(cmdl);
|
||||
|
||||
if (ret != 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
printf("Started driver %s with label %s for device %d.\n",
|
||||
inst->drv->binary, inst->label, inst->dev_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* find_instance *
|
||||
*===========================================================================*/
|
||||
static struct devmand_driver_instance *
|
||||
find_instance(int dev_id)
|
||||
{
|
||||
struct devmand_driver_instance *inst;
|
||||
|
||||
LIST_FOREACH(inst, &instances, list) {
|
||||
if (inst->dev_id == dev_id) {
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* match_usb_driver *
|
||||
*===========================================================================*/
|
||||
static int
|
||||
match_usb_id(struct devmand_usb_match_id *mid, struct usb_device_id *id)
|
||||
{
|
||||
int res = 1;
|
||||
unsigned long match = mid->match_flags;
|
||||
struct usb_device_id *_id = &mid->match_id;
|
||||
|
||||
if (match & USB_MATCH_ID_VENDOR)
|
||||
if (id->idVendor != _id->idVendor) res = 0;
|
||||
if (match & USB_MATCH_ID_PRODUCT)
|
||||
if (id->idProduct != _id->idProduct) res = 0;
|
||||
if (match & USB_MATCH_BCD_DEVICE)
|
||||
if (id->bcdDevice != _id->bcdDevice) res = 0;
|
||||
if (match & USB_MATCH_DEVICE_PROTOCOL)
|
||||
if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
|
||||
if (match & USB_MATCH_DEVICE_SUBCLASS)
|
||||
if (id->bDeviceSubClass != _id->bDeviceSubClass) res = 0;
|
||||
if (match & USB_MATCH_DEVICE_PROTOCOL)
|
||||
if (id->bDeviceProtocol != _id->bDeviceProtocol) res = 0;
|
||||
if (match & USB_MATCH_INTERFACE_CLASS)
|
||||
if (id->bInterfaceClass != _id->bInterfaceClass) res = 0;
|
||||
if (match & USB_MATCH_INTERFACE_SUBCLASS)
|
||||
if (id->bInterfaceSubClass != _id->bInterfaceSubClass) res = 0;
|
||||
if (match & USB_MATCH_INTERFACE_PROTOCOL)
|
||||
if (id->bInterfaceProtocol != _id->bInterfaceProtocol) res = 0;
|
||||
|
||||
if (match == 0UL) {
|
||||
res = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* match_usb_driver *
|
||||
*===========================================================================*/
|
||||
static struct devmand_usb_driver*
|
||||
match_usb_driver(struct usb_device_id *id)
|
||||
{
|
||||
struct devmand_usb_driver *driver;
|
||||
struct devmand_usb_match_id *mid;
|
||||
|
||||
LIST_FOREACH(driver, &drivers, list) {
|
||||
LIST_FOREACH(mid, &driver->ids, list) {
|
||||
if (match_usb_id(mid, id)) {
|
||||
return driver;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* add_usb_match_id *
|
||||
*===========================================================================*/
|
||||
struct devmand_usb_driver * add_usb_driver(char *name)
|
||||
{
|
||||
struct devmand_usb_driver *udrv = (struct devmand_usb_driver*)
|
||||
malloc(sizeof(struct devmand_usb_driver));
|
||||
|
||||
LIST_INSERT_HEAD(&drivers, udrv, list);
|
||||
LIST_INIT(&udrv->ids);
|
||||
|
||||
udrv->name = name;
|
||||
return udrv;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* add_usb_match_id *
|
||||
*===========================================================================*/
|
||||
struct devmand_usb_match_id *
|
||||
add_usb_match_id
|
||||
(struct devmand_usb_driver *drv)
|
||||
{
|
||||
struct devmand_usb_match_id *id = (struct devmand_usb_match_id*)
|
||||
malloc(sizeof(struct devmand_usb_match_id));
|
||||
|
||||
memset(id, 0, sizeof(struct devmand_usb_match_id));
|
||||
|
||||
LIST_INSERT_HEAD(&drv->ids, id, list);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* parse_config *
|
||||
*===========================================================================*/
|
||||
static void parse_config()
|
||||
{
|
||||
yyin = fopen(args.config, "r");
|
||||
|
||||
if (yyin < 0) {
|
||||
printf("Can not open config file: %d.\n", errno);
|
||||
}
|
||||
dbg("Parsing configfile... ");
|
||||
yyparse();
|
||||
dbg("Done.");
|
||||
|
||||
fclose(yyin);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* cleanup *
|
||||
*===========================================================================*/
|
||||
static void cleanup() {
|
||||
int res;
|
||||
struct devmand_driver_instance *inst;
|
||||
/* destroy fifo */
|
||||
dbg("cleaning up... ");
|
||||
/* quit all running drivers */
|
||||
LIST_FOREACH(inst, &instances, list) {
|
||||
dbg("stopping driver %s", inst->label);
|
||||
run_downscript (inst);
|
||||
stop_driver(inst);
|
||||
}
|
||||
res = remove(CONTROL_FIFO_PATH);
|
||||
if (res != 0) {
|
||||
fprintf(stderr, "WARNING: could not remove control fifo");
|
||||
}
|
||||
unlink("/var/run/devmand.pid");
|
||||
}
|
||||
|
||||
static void sig_int(int sig) {
|
||||
dbg("devman: Received SIGINT... cleaning up.");
|
||||
_run = 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* create_pid_file *
|
||||
*===========================================================================*/
|
||||
void create_pid_file()
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
fd = fopen("/var/run/devmand.pid", "r");
|
||||
if(fd) {
|
||||
fprintf(stderr, "devmand: /var/run/devmand.pid exists... "
|
||||
"another devmand running?\n");
|
||||
fclose(fd);
|
||||
exit(1);
|
||||
} else {
|
||||
fd = fopen("/var/run/devmand.pid","w");
|
||||
fprintf(fd, "%d", getpid());
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt, optindex, res;
|
||||
struct devmand_usb_driver *driver;
|
||||
|
||||
create_pid_file();
|
||||
|
||||
/* get command line arguments */
|
||||
while ((opt = getopt_long(argc, argv, "vdc:p:h?", options, &optindex))
|
||||
!= -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
args.deamonize = 1;
|
||||
break;
|
||||
case 'p':
|
||||
args.path = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
args.config = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
args.verbose = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
display_usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* is path set? */
|
||||
if (args.path == NULL) {
|
||||
args.path = "/sys/";
|
||||
}
|
||||
|
||||
/* is path set? */
|
||||
if (args.config == NULL) {
|
||||
args.config = "/etc/devmand/devmand.cfg";
|
||||
}
|
||||
|
||||
dbg("Options: deamonize: %s, path: %s",
|
||||
args.deamonize?"true":"false", args.path);
|
||||
|
||||
/* create control socket if not exists */
|
||||
res = mkfifo(CONTROL_FIFO_PATH, S_IWRITE);
|
||||
|
||||
if ( !((res == 0) || (res == EEXIST)) ) {
|
||||
fprintf(stderr, "Could not create control FIFO (%d)\n", res);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
parse_config();
|
||||
LIST_FOREACH(driver, &drivers, list) {
|
||||
run_cleanscript(driver);
|
||||
}
|
||||
|
||||
signal(SIGINT, sig_int);
|
||||
|
||||
main_loop();
|
||||
|
||||
cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* determine_type *
|
||||
*===========================================================================*/
|
||||
static enum dev_type determine_type (char *path)
|
||||
{
|
||||
FILE * fd;
|
||||
char *mypath;
|
||||
char buf[256];
|
||||
int res;
|
||||
|
||||
mypath = (char *) calloc(1, strlen(path)+strlen(DEVMAN_TYPE_NAME)+1);
|
||||
|
||||
if (mypath == NULL) {
|
||||
fprintf(stderr, "ERROR: out of mem\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strcat(mypath, path);
|
||||
strcat(mypath, DEVMAN_TYPE_NAME);
|
||||
|
||||
fd = fopen(mypath, "r");
|
||||
free(mypath);
|
||||
|
||||
if (fd == NULL) {
|
||||
fprintf(stderr, "WARN: could not open %s\n", mypath);
|
||||
return DEV_TYPE_UNKOWN;
|
||||
}
|
||||
|
||||
res = fscanf(fd , "%s\n", buf);
|
||||
fclose(fd);
|
||||
|
||||
if (res != 1) {
|
||||
fprintf(stderr, "WARN: could not parse %s\n", mypath);
|
||||
return DEV_TYPE_UNKOWN;
|
||||
}
|
||||
|
||||
if (strcmp(buf, "USB_DEV") == 0) {
|
||||
return DEV_TYPE_USB_DEVICE;
|
||||
} else if (strcmp(buf, "USB_INTF") == 0) {
|
||||
return DEV_TYPE_USB_INTF;
|
||||
}
|
||||
|
||||
return DEV_TYPE_UNKOWN;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* read_hex_uint *
|
||||
*===========================================================================*/
|
||||
static int read_hex_uint(char *base_path, char *name, unsigned int* val )
|
||||
{
|
||||
char my_path[PATH_LEN];
|
||||
FILE *fd;
|
||||
memset(my_path,0,PATH_LEN);
|
||||
int ret = 0;
|
||||
|
||||
strcat(my_path, base_path);
|
||||
strcat(my_path, name);
|
||||
|
||||
fd = fopen(my_path, "r");
|
||||
|
||||
if (fd == NULL) {
|
||||
fprintf(stderr, "WARN: could not open %s\n", my_path);
|
||||
return EEXIST;
|
||||
} else if (fscanf(fd, "0x%x\n", val ) != 1) {
|
||||
fprintf(stderr, "WARN: could not parse %s\n", my_path);
|
||||
ret = EINVAL;
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* get_major *
|
||||
*===========================================================================*/
|
||||
static int get_major() {
|
||||
int i, ret = args.major_offset;
|
||||
|
||||
for (i=0; i < 16; i++) {
|
||||
int j;
|
||||
for (j = 0; j < 8; j++ ) {
|
||||
if ((major_bitmap[i] & (1 << j))) {
|
||||
major_bitmap[i] &= !(1 << j);
|
||||
return ret;
|
||||
}
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return INVAL_MAJOR;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* put_major *
|
||||
*===========================================================================*/
|
||||
static void put_major(int major) {
|
||||
int i;
|
||||
major -= args.major_offset;
|
||||
assert(major >= 0);
|
||||
|
||||
for (i=0; i < 16; i++) {
|
||||
int j;
|
||||
for (j = 0; j < 8; j++ ) {
|
||||
if (major==0) {
|
||||
assert(!(major_bitmap[i] & (1 <<j)));
|
||||
major_bitmap[i] |= (1 << j);
|
||||
return;
|
||||
}
|
||||
major--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* generate_usb_device_id *
|
||||
*===========================================================================*/
|
||||
static struct usb_device_id *
|
||||
generate_usb_device_id(char * path, int is_interface)
|
||||
{
|
||||
struct usb_device_id *ret;
|
||||
int res;
|
||||
unsigned int val;
|
||||
|
||||
ret = (struct usb_device_id *)
|
||||
calloc(1,sizeof (struct usb_device_id));
|
||||
|
||||
if (is_interface) {
|
||||
|
||||
res = read_hex_uint(path, "../idVendor", &val);
|
||||
if (res) goto err;
|
||||
ret->idVendor = val;
|
||||
|
||||
res = read_hex_uint(path, "../idProduct", &val);
|
||||
if (res) goto err;
|
||||
ret->idProduct = val;
|
||||
#if 0
|
||||
res = read_hex_uint(path, "../bcdDevice", &val);
|
||||
if (res) goto err;
|
||||
ret->bcdDevice = val;
|
||||
#endif
|
||||
res = read_hex_uint(path, "../bDeviceClass", &val);
|
||||
if (res) goto err;
|
||||
ret->bDeviceClass = val;
|
||||
|
||||
res = read_hex_uint(path, "../bDeviceSubClass", &val);
|
||||
if (res) goto err;
|
||||
ret->bDeviceSubClass = val;
|
||||
|
||||
res = read_hex_uint(path, "../bDeviceProtocol", &val);
|
||||
if (res) goto err;
|
||||
ret->bDeviceProtocol = val;
|
||||
|
||||
res = read_hex_uint(path, "/bInterfaceClass", &val);
|
||||
if (res) goto err;
|
||||
ret->bInterfaceClass = val;
|
||||
|
||||
res = read_hex_uint(path, "/bInterfaceSubClass", &val);
|
||||
if (res) goto err;
|
||||
ret->bInterfaceSubClass = val;
|
||||
|
||||
res = read_hex_uint(path, "/bInterfaceProtocol", &val);
|
||||
if (res) goto err;
|
||||
ret->bInterfaceProtocol = val;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* usb_intf_add_even *
|
||||
*===========================================================================*/
|
||||
static void usb_intf_add_event(char *path, int dev_id)
|
||||
{
|
||||
struct usb_device_id *id;
|
||||
struct devmand_usb_driver *drv;
|
||||
struct devmand_driver_instance *drv_inst;
|
||||
int major, ret;
|
||||
|
||||
/* generate usb_match_id */
|
||||
id = generate_usb_device_id(path,TRUE);
|
||||
if (id == NULL) {
|
||||
fprintf(stderr, "WARN: could not create usb_device id...\n"
|
||||
" ommiting event\n");
|
||||
free(id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* find suitable driver */
|
||||
drv = match_usb_driver(id);
|
||||
free (id);
|
||||
|
||||
if (drv == NULL) {
|
||||
dbg("INFO: could not find a suitable driver for %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
/* create instance */
|
||||
drv_inst = (struct devmand_driver_instance *)
|
||||
calloc(1,sizeof(struct devmand_driver_instance));
|
||||
|
||||
if (drv_inst == NULL) {
|
||||
fprintf(stderr, "ERROR: out of memory");
|
||||
return; /* maybe better quit here. */
|
||||
}
|
||||
|
||||
|
||||
/* allocate inode number, if device files needed */
|
||||
major = get_major();
|
||||
if (major == INVAL_MAJOR) {
|
||||
fprintf(stderr, "WARN: ran out of major numbers\n"
|
||||
" cannot start driver %s for %s\n",
|
||||
drv->name, path);
|
||||
return;
|
||||
}
|
||||
|
||||
drv_inst->major = major;
|
||||
drv_inst->drv = drv;
|
||||
drv_inst->dev_id = dev_id;
|
||||
|
||||
|
||||
/* start driver (invoke service) */
|
||||
start_driver(drv_inst);
|
||||
|
||||
/*
|
||||
* run the up action
|
||||
*
|
||||
* An up action can be any executable. Before running it devmand
|
||||
* will set certain environment variables so the script can configure
|
||||
* the device (or generate device files, etc). See up_action() for that.
|
||||
*/
|
||||
if (drv->upscript) {
|
||||
ret = run_upscript(drv_inst);
|
||||
if (ret) {
|
||||
stop_driver(drv_inst);
|
||||
fprintf(stderr, "devmand: warning, could not run up_action\n");
|
||||
free(drv_inst);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LIST_INSERT_HEAD(&instances,drv_inst,list);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* usb_intf_remove_event *
|
||||
*===========================================================================*/
|
||||
static void usb_intf_remove_event(char *path, int dev_id)
|
||||
{
|
||||
struct devmand_driver_instance *inst;
|
||||
struct devmand_usb_driver *drv;
|
||||
int ret;
|
||||
|
||||
/* find the driver instance */
|
||||
inst = find_instance(dev_id);
|
||||
|
||||
if (inst == NULL) {
|
||||
dbg("No driver running for id: %d", dev_id);
|
||||
return;
|
||||
}
|
||||
drv = inst->drv;
|
||||
|
||||
/* run the down script */
|
||||
if (drv->downscript) {
|
||||
ret = run_downscript(inst);
|
||||
if (ret) {
|
||||
fprintf(stderr, "WARN: error running up_action");
|
||||
}
|
||||
}
|
||||
|
||||
/* stop the driver */
|
||||
stop_driver(inst);
|
||||
|
||||
/* free major */
|
||||
put_major(inst->major);
|
||||
|
||||
/* free instance */
|
||||
LIST_REMOVE(inst,list);
|
||||
free(inst);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* handle_event *
|
||||
*===========================================================================*/
|
||||
static void handle_event(char *event)
|
||||
{
|
||||
enum dev_type type;
|
||||
char path[PATH_LEN];
|
||||
char tmp_path[PATH_LEN];
|
||||
int dev_id, res;
|
||||
|
||||
path[0]=0;
|
||||
|
||||
if (strncmp("ADD ", event, 4) == 0) {
|
||||
|
||||
/* read data from event */
|
||||
res = sscanf(event, "ADD %s 0x%x", tmp_path, &dev_id);
|
||||
|
||||
if (res != 2) {
|
||||
fprintf(stderr, "WARN: could not parse event: %s", event);
|
||||
fprintf(stderr, "WARN: omitting event: %s", event);
|
||||
}
|
||||
|
||||
strcpy(path, args.path);
|
||||
strcat(path, tmp_path);
|
||||
|
||||
/* what kind of device is added? */
|
||||
type = determine_type(path);
|
||||
|
||||
switch (type) {
|
||||
case DEV_TYPE_USB_DEVICE:
|
||||
dbg("USB device added: ommited....");
|
||||
/* ommit usb devices for now */
|
||||
break;
|
||||
case DEV_TYPE_USB_INTF:
|
||||
dbg("USB interface added: (%s, devid: = %d)",path, dev_id);
|
||||
usb_intf_add_event(path, dev_id);
|
||||
return;
|
||||
default:
|
||||
dbg("default");
|
||||
fprintf(stderr, "WARN: ommiting event\n");
|
||||
}
|
||||
} else if (strncmp("REMOVE ", event, 7) == 0) {
|
||||
|
||||
/* read data from event */
|
||||
res = sscanf(event,"REMOVE %s 0x%x", tmp_path, &dev_id);
|
||||
|
||||
if (res != 2) {
|
||||
fprintf(stderr, "WARN: could not parse event: %s", event);
|
||||
fprintf(stderr, "WARN: omitting event: %s", event);
|
||||
}
|
||||
|
||||
usb_intf_remove_event(path, dev_id);
|
||||
|
||||
#if 0
|
||||
strcpy(path, args.path);
|
||||
strcat(path, tmp_path);
|
||||
|
||||
/* what kind of device is added? */
|
||||
type = determine_type(path);
|
||||
|
||||
switch (type) {
|
||||
case DEV_TYPE_USB_DEVICE:
|
||||
/* ommit usb devices for now */
|
||||
break;
|
||||
case DEV_TYPE_USB_INTF:
|
||||
usb_intf_remove_event(path, dev_id);
|
||||
return;
|
||||
default:
|
||||
fprintf(stderr, "WARN: ommiting event\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* main_loop *
|
||||
*===========================================================================*/
|
||||
static void main_loop()
|
||||
{
|
||||
char ev_path[128];
|
||||
char buf[256];
|
||||
int len;
|
||||
|
||||
FILE* fd;
|
||||
len = strlen(args.path);
|
||||
|
||||
/* init major numbers */
|
||||
|
||||
memset(&major_bitmap, 0xff, 16);
|
||||
|
||||
if (len > 128 - 7 /*len of "events" */) {
|
||||
fprintf(stderr, "pathname to long\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strcpy(ev_path, args.path);
|
||||
strcat(ev_path, "events");
|
||||
|
||||
|
||||
while (_run) {
|
||||
|
||||
char *res;
|
||||
|
||||
fd = fopen(ev_path, "r");
|
||||
if (fd == NULL) {
|
||||
fprintf(stderr, "ERROR: could not open event file...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = fgets(buf, 256, fd);
|
||||
fclose(fd);
|
||||
|
||||
if (res == NULL) {
|
||||
/* TODO: wait for control events */
|
||||
usleep(50000);
|
||||
continue;
|
||||
}
|
||||
dbg("handle_event: %s", buf);
|
||||
handle_event(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* display_usage *
|
||||
*===========================================================================*/
|
||||
static void display_usage(const char *name)
|
||||
{
|
||||
printf("Usage: %s [-d|--deamonize] [{-p|--pathname} PATH_TO_SYS}"
|
||||
" [{-c|--config} CONFIG_FILE]\n", name);
|
||||
}
|
||||
|
11
commands/devmand/proto.h
Normal file
11
commands/devmand/proto.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef _DEVMAND_PROTO_H
|
||||
#define _DEVMAND_PROTO_H
|
||||
|
||||
/* main.c */
|
||||
struct devmand_usb_driver * add_usb_driver(char *name);
|
||||
struct devmand_usb_match_id * add_usb_match_id();
|
||||
|
||||
/* y.tab.c */
|
||||
int yyparse();
|
||||
|
||||
#endif
|
134
commands/devmand/usb.y
Normal file
134
commands/devmand/usb.y
Normal file
|
@ -0,0 +1,134 @@
|
|||
%{
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "usb_driver.h"
|
||||
#define YY_NO_INPUT
|
||||
static struct devmand_usb_driver *current_drv;
|
||||
static struct devmand_usb_match_id *current_id;
|
||||
|
||||
int yylex(void);
|
||||
|
||||
void yyerror(char *s)
|
||||
{
|
||||
fprintf(stderr,"parsing error: %s\n",s);
|
||||
}
|
||||
|
||||
int yywrap()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
%}
|
||||
|
||||
%union {
|
||||
char *string;
|
||||
}
|
||||
|
||||
%start drivers
|
||||
%token <string> USB_DRIVER DEV_PREFIX BINARY INTERFACE_CLASS INTERFACE_SUB_CLASS EQUALS DEV_TYPE BLOCK_DEV CHAR_DEV UPSCRIPT DOWNSCRIPT
|
||||
SEMICOLON BRACKET_OPEN BRACKET_CLOSE STRING ID INTERFACE_PROTOCOL
|
||||
|
||||
%%
|
||||
drivers :
|
||||
driver
|
||||
{
|
||||
}
|
||||
| drivers driver
|
||||
{
|
||||
};
|
||||
|
||||
driver :
|
||||
USB_DRIVER STRING {current_drv = add_usb_driver($2);}
|
||||
BRACKET_OPEN
|
||||
usb_driver_statements BRACKET_CLOSE
|
||||
{
|
||||
};
|
||||
|
||||
usb_driver_statements:
|
||||
usb_driver_statement
|
||||
{
|
||||
}
|
||||
| usb_driver_statements usb_driver_statement
|
||||
{
|
||||
};
|
||||
|
||||
usb_driver_statement:
|
||||
{current_id = add_usb_match_id(current_drv);}
|
||||
ID BRACKET_OPEN usb_device_id_statements BRACKET_CLOSE
|
||||
{
|
||||
}
|
||||
| BINARY EQUALS STRING SEMICOLON
|
||||
{
|
||||
current_drv->binary = $3;
|
||||
}
|
||||
| DEV_PREFIX EQUALS STRING SEMICOLON
|
||||
{
|
||||
current_drv->devprefix = $3;
|
||||
}
|
||||
| DEV_TYPE EQUALS BLOCK_DEV SEMICOLON
|
||||
{
|
||||
current_drv->dev_type = block_dev;
|
||||
}
|
||||
| DEV_TYPE EQUALS CHAR_DEV SEMICOLON
|
||||
{
|
||||
current_drv->dev_type = char_dev;
|
||||
}
|
||||
| UPSCRIPT EQUALS STRING SEMICOLON
|
||||
{
|
||||
current_drv->upscript = $3;
|
||||
}
|
||||
| DOWNSCRIPT EQUALS STRING SEMICOLON
|
||||
{
|
||||
current_drv->downscript = $3;
|
||||
};
|
||||
|
||||
|
||||
usb_device_id_statements:
|
||||
usb_device_id_statement
|
||||
{
|
||||
}
|
||||
|usb_device_id_statements usb_device_id_statement
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
usb_device_id_statement:
|
||||
INTERFACE_CLASS EQUALS STRING SEMICOLON
|
||||
{
|
||||
int res;
|
||||
unsigned int num;
|
||||
current_id->match_flags |= USB_MATCH_INTERFACE_CLASS;
|
||||
res = sscanf($3, "0x%x", &num);
|
||||
if (res != 1) {
|
||||
fprintf(stderr, "ERROR");
|
||||
exit(1);
|
||||
}
|
||||
current_id->match_id.bInterfaceClass = num;
|
||||
}
|
||||
| INTERFACE_SUB_CLASS EQUALS STRING SEMICOLON
|
||||
{
|
||||
int res;
|
||||
unsigned int num;
|
||||
current_id->match_flags |= USB_MATCH_INTERFACE_SUBCLASS;
|
||||
res = sscanf($3, "0x%x", &num);
|
||||
if (res != 1) {
|
||||
fprintf(stderr, "ERROR");
|
||||
exit(1);
|
||||
}
|
||||
current_id->match_id.bInterfaceSubClass = num;
|
||||
|
||||
}
|
||||
| INTERFACE_PROTOCOL EQUALS STRING SEMICOLON
|
||||
{
|
||||
int res;
|
||||
unsigned int num;
|
||||
current_id->match_flags |= USB_MATCH_INTERFACE_PROTOCOL;
|
||||
res = sscanf($3, "0x%x", &num);
|
||||
if (res != 1) {
|
||||
fprintf(stderr, "ERROR");
|
||||
exit(1);
|
||||
}
|
||||
current_id->match_id.bInterfaceProtocol = num;
|
||||
|
||||
};
|
||||
%%
|
52
commands/devmand/usb_driver.h
Normal file
52
commands/devmand/usb_driver.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef DEVMAN_USB_DRIVER
|
||||
#define DEVMAN_USB_DRIVER
|
||||
|
||||
#include <minix/usb.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define USB_MATCH_ID_VENDOR (1 << 0)
|
||||
#define USB_MATCH_ID_PRODUCT (1 << 1)
|
||||
#define USB_MATCH_BCD_DEVICE (1 << 2)
|
||||
#define USB_MATCH_DEVICE_CLASS (1 << 3)
|
||||
#define USB_MATCH_DEVICE_SUBCLASS (1 << 4)
|
||||
#define USB_MATCH_DEVICE_PROTOCOL (1 << 5)
|
||||
#define USB_MATCH_INTERFACE_CLASS (1 << 6)
|
||||
#define USB_MATCH_INTERFACE_SUBCLASS (1 << 7)
|
||||
#define USB_MATCH_INTERFACE_PROTOCOL (1 << 8)
|
||||
|
||||
enum devmand_device_type {
|
||||
char_dev,
|
||||
block_dev
|
||||
};
|
||||
|
||||
struct devmand_usb_match_id {
|
||||
unsigned match_flags;
|
||||
struct usb_device_id match_id;
|
||||
LIST_ENTRY(devmand_usb_match_id) list;
|
||||
};
|
||||
|
||||
#define DEVMAND_DRIVER_LABEL_LEN 32
|
||||
|
||||
struct devmand_driver_instance {
|
||||
int dev_id;
|
||||
int major;
|
||||
char label[DEVMAND_DRIVER_LABEL_LEN];
|
||||
struct devmand_usb_driver *drv;
|
||||
LIST_ENTRY(devmand_driver_instance) list;
|
||||
};
|
||||
|
||||
struct devmand_usb_driver {
|
||||
char *name;
|
||||
char *devprefix;
|
||||
char *binary;
|
||||
char *upscript;
|
||||
char *downscript;
|
||||
enum devmand_device_type dev_type;
|
||||
LIST_HEAD(devid_head, devmand_usb_match_id) ids;
|
||||
LIST_ENTRY(devmand_usb_driver) list;
|
||||
};
|
||||
|
||||
struct devmand_usb_driver * add_usb_driver(char *name);
|
||||
struct devmand_usb_match_id *add_usb_match_id(struct devmand_usb_driver *drv);
|
||||
|
||||
#endif
|
43
commands/devmand/usb_scan.l
Normal file
43
commands/devmand/usb_scan.l
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* -*- indented-text -*- */
|
||||
%option noinput
|
||||
%option nounput
|
||||
%{
|
||||
#include "y.tab.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#if 0
|
||||
#define ECHO fwrite(yytext, yyleng, 1, yyout)
|
||||
#else
|
||||
#define ECHO
|
||||
#endif
|
||||
%}
|
||||
BO [{]
|
||||
BC [}]
|
||||
NL [\n]
|
||||
SC [;]
|
||||
CHAR [0-9a-zA-Z_/\-\*\.]
|
||||
EQ [=]
|
||||
SPACE [\032]
|
||||
%%
|
||||
|
||||
usb_driver { ECHO; return USB_DRIVER;}
|
||||
devprefix { ECHO; return DEV_PREFIX;}
|
||||
devtype { ECHO; return DEV_TYPE;}
|
||||
char { ECHO; return BLOCK_DEV;}
|
||||
block { ECHO; return CHAR_DEV;}
|
||||
binary { ECHO; return BINARY;}
|
||||
bInterfaceClass { ECHO; return INTERFACE_CLASS;}
|
||||
bInterfaceSubClass { ECHO; return INTERFACE_SUB_CLASS;}
|
||||
bInterfaceProtocol { ECHO; return INTERFACE_PROTOCOL;}
|
||||
id { ECHO; return ID;}
|
||||
upscript { ECHO; return UPSCRIPT;}
|
||||
downscript { ECHO; return DOWNSCRIPT;}
|
||||
{EQ} { ECHO; return EQUALS;}
|
||||
{SC} { ECHO; return SEMICOLON;}
|
||||
{BO} { ECHO; return BRACKET_OPEN;}
|
||||
{BC} { ECHO; return BRACKET_CLOSE;}
|
||||
{CHAR}+ { ECHO; yylval.string = (char *)strdup(yytext); return STRING;}
|
||||
. ;
|
||||
%%
|
||||
|
|
@ -7,9 +7,10 @@
|
|||
|
||||
struct ddekit_minix_msg_q;
|
||||
|
||||
void ddekit_minix_queue_msg(message *m);
|
||||
void ddekit_minix_queue_msg(message *m, int ipc_status);
|
||||
|
||||
void ddekit_minix_rcv(struct ddekit_minix_msg_q * mq, message *m);
|
||||
void ddekit_minix_rcv
|
||||
(struct ddekit_minix_msg_q * mq, message *m, int *ipc_status);
|
||||
|
||||
struct ddekit_minix_msg_q *ddekit_minix_create_msg_q(unsigned from,
|
||||
unsigned to);
|
||||
|
|
|
@ -32,7 +32,7 @@ int ddekit_release_mem(ddekit_addr_t start, ddekit_addr_t count);
|
|||
*
|
||||
* \return value read from port
|
||||
*/
|
||||
unsigned char dde_kit_inb(ddekit_addr_t port);
|
||||
unsigned char ddekit_inb(ddekit_addr_t port);
|
||||
|
||||
/**
|
||||
* Read I/O port (2-byte)
|
||||
|
@ -41,7 +41,7 @@ unsigned char dde_kit_inb(ddekit_addr_t port);
|
|||
*
|
||||
* \return value read from port
|
||||
*/
|
||||
unsigned short dde_kit_inw(ddekit_addr_t port);
|
||||
unsigned short ddekit_inw(ddekit_addr_t port);
|
||||
|
||||
/**
|
||||
* Read I/O port (4-byte)
|
||||
|
@ -50,7 +50,7 @@ unsigned short dde_kit_inw(ddekit_addr_t port);
|
|||
*
|
||||
* \return value read from port
|
||||
*/
|
||||
unsigned long dde_kit_inl(ddekit_addr_t port);
|
||||
unsigned long ddekit_inl(ddekit_addr_t port);
|
||||
|
||||
/**
|
||||
* Write I/O port (byte)
|
||||
|
@ -58,7 +58,7 @@ unsigned long dde_kit_inl(ddekit_addr_t port);
|
|||
* \param port port to write
|
||||
* \param val value to write
|
||||
*/
|
||||
void dde_kit_outb(ddekit_addr_t port, unsigned char val);
|
||||
void ddekit_outb(ddekit_addr_t port, unsigned char val);
|
||||
|
||||
/**
|
||||
* Write I/O port (2-byte)
|
||||
|
@ -66,7 +66,7 @@ void dde_kit_outb(ddekit_addr_t port, unsigned char val);
|
|||
* \param port port to write
|
||||
* \param val value to write
|
||||
*/
|
||||
void dde_kit_outw(ddekit_addr_t port, unsigned short val);
|
||||
void ddekit_outw(ddekit_addr_t port, unsigned short val);
|
||||
|
||||
/**
|
||||
* Write I/O port (4-byte)
|
||||
|
@ -74,7 +74,7 @@ void dde_kit_outw(ddekit_addr_t port, unsigned short val);
|
|||
* \param port port to write
|
||||
* \param val value to write
|
||||
*/
|
||||
void dde_kit_outl(ddekit_addr_t port, unsigned long val);
|
||||
void ddekit_outl(ddekit_addr_t port, unsigned long val);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -58,3 +58,8 @@ error "_MINIX_MACHINE has incorrect value (0)"
|
|||
#define DEFAULT_STACK_LIMIT (64 * 1024 * 1024)
|
||||
|
||||
#endif /* _MINIX_SYS_CONFIG_H */
|
||||
|
||||
/* Added by release script */
|
||||
#ifndef _VCS_REVISION
|
||||
#define _VCS_REVISION "116fcea"
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,7 @@ static void ddekit_dispatcher_thread_init(void);
|
|||
/****************************************************************************/
|
||||
static void dispatcher_thread(void *unused) {
|
||||
|
||||
/*
|
||||
/*
|
||||
* Gets all messages and dispatches them.
|
||||
*
|
||||
* NOTE: this thread runs only when no other ddekit is
|
||||
|
@ -40,6 +40,7 @@ static void dispatcher_thread(void *unused) {
|
|||
message m;
|
||||
int r;
|
||||
int i;
|
||||
int ipc_status;
|
||||
|
||||
_ddekit_thread_set_myprio(0);
|
||||
|
||||
|
@ -47,17 +48,17 @@ static void dispatcher_thread(void *unused) {
|
|||
|
||||
/* Trigger a timer interrupt at each loop iteration */
|
||||
_ddekit_timer_update();
|
||||
|
||||
|
||||
/* Wait for messages */
|
||||
if ((r = sef_receive(ANY, &m)) != 0) {
|
||||
if ((r = sef_receive_status(ANY, &m, &ipc_status)) != 0) {
|
||||
ddekit_panic("ddekit", "sef_receive failed", r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
_ddekit_timer_interrupt();
|
||||
|
||||
|
||||
_ddekit_thread_wakeup_sleeping();
|
||||
|
||||
|
||||
if (is_notify(m.m_type)) {
|
||||
switch (_ENDPOINT_P(m.m_source)) {
|
||||
case HARDWARE:
|
||||
|
@ -77,15 +78,15 @@ static void dispatcher_thread(void *unused) {
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* I don't know how to handle this msg,
|
||||
* but maybe we have a msg queue which can
|
||||
* handle this msg.
|
||||
*/
|
||||
|
||||
ddekit_minix_queue_msg(&m);
|
||||
}
|
||||
ddekit_minix_queue_msg(&m, ipc_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,9 +115,9 @@ void ddekit_init(void)
|
|||
ddekit_init_irqs();
|
||||
|
||||
ddekit_init_timers();
|
||||
|
||||
|
||||
ddekit_dispatcher_thread_init();
|
||||
|
||||
|
||||
exit_sem = ddekit_sem_init(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define DDEBUG DDEKIT_DEBUG_INITCALL
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "debug.h"
|
||||
|
||||
static struct __ddekit_initcall_s head = {0,0,0};
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ struct ddekit_minix_msg_q {
|
|||
unsigned from, to;
|
||||
|
||||
message messages[MESSAGE_QUEUE_SIZE];
|
||||
int ipc_status[MESSAGE_QUEUE_SIZE];
|
||||
ddekit_sem_t *msg_w_sem, *msg_r_sem;
|
||||
int msg_r_pos, msg_w_pos;
|
||||
|
||||
|
@ -26,8 +27,8 @@ struct ddekit_minix_msg_q {
|
|||
};
|
||||
|
||||
static struct ddekit_minix_msg_q * _list = NULL;
|
||||
static void _ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq,
|
||||
message *m);
|
||||
static void _ddekit_minix_queue_msg
|
||||
(struct ddekit_minix_msg_q *mq, message *m, int ipc_status);
|
||||
|
||||
/*****************************************************************************
|
||||
* ddekit_minix_create_msg_q *
|
||||
|
@ -37,7 +38,7 @@ ddekit_minix_create_msg_q(unsigned from, unsigned to)
|
|||
{
|
||||
struct ddekit_minix_msg_q *mq = (struct ddekit_minix_msg_q *)
|
||||
ddekit_simple_malloc(sizeof(struct ddekit_minix_msg_q));
|
||||
|
||||
|
||||
mq->from = from;
|
||||
mq->to = to;
|
||||
mq->msg_w_pos = 0;
|
||||
|
@ -49,10 +50,10 @@ ddekit_minix_create_msg_q(unsigned from, unsigned to)
|
|||
/* TODO: check for overlapping message ranges */
|
||||
mq->next = _list;
|
||||
_list = mq;
|
||||
|
||||
|
||||
DDEBUG_MSG_VERBOSE("created msg_q from %x to %x\n", from , to);
|
||||
|
||||
return mq;
|
||||
return mq;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -81,8 +82,12 @@ void ddekit_minix_deregister_msg_q(struct ddekit_minix_msg_q *mq)
|
|||
/*****************************************************************************
|
||||
* _ddekit_minix_queue_msg *
|
||||
****************************************************************************/
|
||||
static void
|
||||
_ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m)
|
||||
static void
|
||||
_ddekit_minix_queue_msg (
|
||||
struct ddekit_minix_msg_q *mq,
|
||||
message *m,
|
||||
int ipc_status
|
||||
)
|
||||
{
|
||||
int full;
|
||||
full = ddekit_sem_down_try(mq->msg_w_sem);
|
||||
|
@ -95,7 +100,7 @@ _ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m)
|
|||
m->m_type = TASK_REPLY;
|
||||
m->REP_STATUS = EAGAIN;
|
||||
result = asynsend(m->m_source, m);
|
||||
|
||||
|
||||
if (result != 0) {
|
||||
ddekit_panic("unable to send reply to %d: %d\n",
|
||||
m->m_source, result);
|
||||
|
@ -104,7 +109,7 @@ _ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m)
|
|||
} else {
|
||||
/* queue the message */
|
||||
memcpy(&mq->messages[mq->msg_w_pos], m, sizeof(message));
|
||||
|
||||
mq->ipc_status[mq->msg_w_pos] = ipc_status;
|
||||
if (++mq->msg_w_pos == MESSAGE_QUEUE_SIZE) {
|
||||
mq->msg_w_pos = 0;
|
||||
}
|
||||
|
@ -117,10 +122,10 @@ _ddekit_minix_queue_msg(struct ddekit_minix_msg_q *mq, message *m)
|
|||
/*****************************************************************************
|
||||
* ddekit_minix_queue_msg *
|
||||
****************************************************************************/
|
||||
void ddekit_minix_queue_msg(message *m)
|
||||
void ddekit_minix_queue_msg(message *m, int ipc_status)
|
||||
{
|
||||
struct ddekit_minix_msg_q *it, *mq = NULL;
|
||||
|
||||
|
||||
for (it = _list; it !=NULL ; it = it->next) {
|
||||
if (m->m_type >= it->from && m->m_type <= it->to) {
|
||||
mq = it;
|
||||
|
@ -131,25 +136,29 @@ void ddekit_minix_queue_msg(message *m)
|
|||
DDEBUG_MSG_VERBOSE("no q for msgtype %x\n", m->m_type);
|
||||
return;
|
||||
}
|
||||
_ddekit_minix_queue_msg(mq,m);
|
||||
_ddekit_minix_queue_msg(mq, m, ipc_status);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* ddekit_minix_rcv *
|
||||
****************************************************************************/
|
||||
void ddekit_minix_rcv(struct ddekit_minix_msg_q *mq, message *m)
|
||||
void ddekit_minix_rcv (
|
||||
struct ddekit_minix_msg_q *mq,
|
||||
message *m,
|
||||
int *ipc_status
|
||||
)
|
||||
{
|
||||
DDEBUG_MSG_VERBOSE("waiting for message");
|
||||
|
||||
|
||||
ddekit_sem_down(mq->msg_r_sem);
|
||||
|
||||
memcpy(m, &mq->messages[mq->msg_r_pos], sizeof(message));
|
||||
|
||||
*ipc_status = mq->ipc_status[mq->msg_r_pos];
|
||||
if (++mq->msg_r_pos == MESSAGE_QUEUE_SIZE) {
|
||||
mq->msg_r_pos = 0;
|
||||
}
|
||||
|
||||
|
||||
DDEBUG_MSG_VERBOSE("unqueing message");
|
||||
|
||||
|
||||
ddekit_sem_up(mq->msg_w_sem);
|
||||
}
|
||||
|
|
|
@ -52,18 +52,17 @@ static void _ddekit_usb_completion(struct usb_urb *mx_urb)
|
|||
|
||||
if (mx_urb->type == USB_TRANSFER_ISO) {
|
||||
d_urb->start_frame = mx_urb->start_frame;
|
||||
|
||||
|
||||
memcpy(d_urb->iso_desc, mx_urb->buffer + d_urb->size,
|
||||
d_urb->number_of_packets * sizeof(struct usb_iso_packet_desc));
|
||||
}
|
||||
|
||||
|
||||
memcpy(d_urb->data, mx_urb->buffer, d_urb->size);
|
||||
|
||||
|
||||
/* free mx_urb */
|
||||
ddekit_simple_free(mx_urb);
|
||||
|
||||
/* 'give back' URB */
|
||||
|
||||
|
||||
d_usb_driver->completion(d_urb->priv);
|
||||
}
|
||||
|
@ -139,11 +138,9 @@ int ddekit_usb_submit_urb(struct ddekit_usb_urb *d_urb)
|
|||
{
|
||||
int res;
|
||||
unsigned urb_size = USB_URBSIZE(d_urb->size, d_urb->number_of_packets);
|
||||
|
||||
/* create mx urb out of d_urb */
|
||||
struct usb_urb *mx_urb = (struct usb_urb*)
|
||||
ddekit_simple_malloc(urb_size);
|
||||
|
||||
mx_urb->urb_size = urb_size;
|
||||
|
||||
mx_urb->dev_id = d_urb->dev->id;
|
||||
|
@ -162,18 +159,15 @@ int ddekit_usb_submit_urb(struct ddekit_usb_urb *d_urb)
|
|||
if (mx_urb->type == USB_TRANSFER_ISO) {
|
||||
mx_urb->number_of_packets = d_urb->number_of_packets;
|
||||
mx_urb->start_frame = d_urb->start_frame;
|
||||
|
||||
memcpy(mx_urb->buffer + d_urb->size, d_urb->iso_desc,
|
||||
d_urb->number_of_packets * sizeof(struct usb_iso_packet_desc));
|
||||
}
|
||||
|
||||
memcpy(mx_urb->buffer, d_urb->data, d_urb->size);
|
||||
|
||||
d_urb->ddekit_priv = mx_urb;
|
||||
|
||||
/* submit mx_urb */
|
||||
res = usb_send_urb(mx_urb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -197,14 +191,15 @@ static void _ddekit_usb_thread()
|
|||
struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE,
|
||||
USB_BASE + 0x1000);
|
||||
message m;
|
||||
int ipc_status;
|
||||
|
||||
while (1) {
|
||||
ddekit_minix_rcv(mq, &m);
|
||||
usb_handle_msg(&mx_usb_driver,&m);
|
||||
ddekit_minix_rcv(mq, &m, &ipc_status);
|
||||
usb_handle_msg(&mx_usb_driver, &m);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* ddekit_usb_init *
|
||||
****************************************************************************/
|
||||
|
@ -213,7 +208,6 @@ int ddekit_usb_init
|
|||
ddekit_usb_malloc_fn *unused,
|
||||
ddekit_usb_free_fn *_unused)
|
||||
{
|
||||
|
||||
/* start usb_thread */
|
||||
d_usb_driver = drv;
|
||||
usb_init("dde");
|
||||
|
|
|
@ -415,7 +415,7 @@ static void cancle_urb(message *msg)
|
|||
endpoint_t ep = msg->m_source;
|
||||
|
||||
struct minix_usb_driver *drv;
|
||||
|
||||
|
||||
msg->USB_RESULT = -1;
|
||||
msg->m_type = USB_REPLY;
|
||||
|
||||
|
@ -425,7 +425,7 @@ static void cancle_urb(message *msg)
|
|||
return;
|
||||
} else {
|
||||
struct ddekit_usb_urb *d_urb = NULL;
|
||||
|
||||
|
||||
d_urb = find_pending_urb(drv, msg->USB_URB_ID);
|
||||
|
||||
if (d_urb != NULL) {
|
||||
|
@ -436,7 +436,7 @@ static void cancle_urb(message *msg)
|
|||
msg->USB_RESULT = ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
send(ep, msg);
|
||||
}
|
||||
|
||||
|
@ -468,9 +468,9 @@ static void completion_callback(void *priv)
|
|||
mx_urb->actual_length = d_urb->actual_length;
|
||||
mx_urb->error_count = d_urb->error_count;
|
||||
mx_urb->transfer_flags = d_urb->transfer_flags;
|
||||
|
||||
|
||||
remove_from_pending_urbs(drv, d_urb);
|
||||
|
||||
|
||||
/* copy out URB */
|
||||
res = sys_safecopyto(drv->ep, ctx->gid, 0,
|
||||
(vir_bytes) ((char*)mx_urb) + sizeof(void*),
|
||||
|
@ -486,7 +486,7 @@ static void completion_callback(void *priv)
|
|||
msg.m_type = USB_COMPLETE_URB;
|
||||
msg.USB_URB_ID = ctx->urb_id;
|
||||
asynsend3(drv->ep, &msg, AMF_NOREPLY);
|
||||
|
||||
|
||||
/* free stuff */
|
||||
my_free(ctx);
|
||||
my_free(mx_urb);
|
||||
|
@ -725,10 +725,10 @@ static void devman_thread(void *unused)
|
|||
{
|
||||
struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(DEVMAN_BASE,
|
||||
DEVMAN_BASE + 0xff);
|
||||
|
||||
int ipc_status;
|
||||
message m;
|
||||
while (1) {
|
||||
ddekit_minix_rcv(mq, &m);
|
||||
ddekit_minix_rcv(mq, &m, &ipc_status);
|
||||
devman_handle_msg(&m);
|
||||
}
|
||||
}
|
||||
|
@ -742,6 +742,7 @@ static void _ddekit_usb_thread(void * unused)
|
|||
USB_BASE + 0xff);
|
||||
|
||||
message m;
|
||||
int ipc_status;
|
||||
|
||||
/* create devman thread */
|
||||
ddekit_thread_t * dmth;
|
||||
|
@ -749,7 +750,7 @@ static void _ddekit_usb_thread(void * unused)
|
|||
dmth = ddekit_thread_create(devman_thread, NULL, "devman_thread");
|
||||
|
||||
while (1) {
|
||||
ddekit_minix_rcv(mq, &m);
|
||||
ddekit_minix_rcv(mq, &m, &ipc_status);
|
||||
handle_msg(&m);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue