libdevman: IPC wrapper for devman
This commit is contained in:
parent
77fa5b4116
commit
8c8e44d0ae
6 changed files with 618 additions and 3 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
SUBDIR= csu libc libcurses libdriver libnetdriver libedit libm libsys \
|
SUBDIR= csu libc libcurses libdriver libnetdriver libedit libm libsys \
|
||||||
libtimers libutil libbz2 libl libhgfs libz libfetch libarchive \
|
libtimers libutil libbz2 libl libhgfs libz libfetch libarchive \
|
||||||
libvtreefs libaudiodriver libmthread libexec libusb
|
libvtreefs libaudiodriver libmthread libexec libdevman libusb
|
||||||
|
|
||||||
.if ${COMPILER_TYPE} == "ack"
|
.if ${COMPILER_TYPE} == "ack"
|
||||||
SUBDIR+= ack/libd ack/libe ack/libfp ack/liby
|
SUBDIR+= ack/libd ack/libe ack/libfp ack/liby
|
||||||
|
|
8
lib/libdevman/Makefile
Normal file
8
lib/libdevman/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
LIB = devman
|
||||||
|
|
||||||
|
SRCS = generic.c \
|
||||||
|
usb.c
|
||||||
|
|
||||||
|
.include <bsd.lib.mk>
|
||||||
|
|
||||||
|
|
280
lib/libdevman/generic.c
Normal file
280
lib/libdevman/generic.c
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <minix/com.h>
|
||||||
|
#include <minix/ipc.h>
|
||||||
|
#include <minix/const.h>
|
||||||
|
#include <minix/devman.h>
|
||||||
|
#include <minix/safecopies.h>
|
||||||
|
|
||||||
|
#include "local.h"
|
||||||
|
|
||||||
|
PRIVATE endpoint_t devman_ep;
|
||||||
|
|
||||||
|
FORWARD _PROTOTYPE( int save_string,
|
||||||
|
(char *buffer, char *src, size_t *offset));
|
||||||
|
|
||||||
|
PRIVATE TAILQ_HEAD(devlist_head, devman_dev) dev_list;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* save_string *
|
||||||
|
***************************************************************************/
|
||||||
|
PRIVATE int save_string(char *buffer, char *src, size_t *offset)
|
||||||
|
{
|
||||||
|
unsigned old_offset = *offset;
|
||||||
|
size_t len = strlen(src) + 1;
|
||||||
|
memcpy(buffer + *offset, src, len);
|
||||||
|
*offset += len;
|
||||||
|
return old_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* serialize_dev *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC void *serialize_dev(struct devman_dev *dev, size_t *overall_size)
|
||||||
|
{
|
||||||
|
/* determine size of serialized version of dev */
|
||||||
|
char *buffer;
|
||||||
|
char *string_buffer;
|
||||||
|
size_t string_buffer_offset;
|
||||||
|
size_t count = 0;
|
||||||
|
size_t size = sizeof(struct devman_device_info);
|
||||||
|
size_t strings_size = strlen(dev->name) + 1;
|
||||||
|
struct devman_device_info * serialized_dev;
|
||||||
|
struct devman_device_info_entry *entry;
|
||||||
|
struct devman_static_attribute *attribute;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(attribute, &dev->attrs, list) {
|
||||||
|
strings_size += strlen(attribute->name) + 1;
|
||||||
|
strings_size += strlen(attribute->data) + 1;
|
||||||
|
size += sizeof(struct devman_device_info_entry);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = malloc(size + strings_size);
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_buffer = buffer;
|
||||||
|
string_buffer_offset = size; /* strings start after
|
||||||
|
devman_device_info and
|
||||||
|
devman_device_info_entries */
|
||||||
|
|
||||||
|
/* serialize device */
|
||||||
|
serialized_dev = (struct devman_device_info *) buffer;
|
||||||
|
|
||||||
|
serialized_dev->count = count;
|
||||||
|
serialized_dev->parent_dev_id = dev->parent_dev_id;
|
||||||
|
serialized_dev->name_offset =
|
||||||
|
save_string(string_buffer, dev->name, &string_buffer_offset);
|
||||||
|
#if 0
|
||||||
|
serialized_dev->bus =
|
||||||
|
save_string(string_buffer, dev->bus, &string_buffer_offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* serialize entries */
|
||||||
|
entry =
|
||||||
|
(struct devman_device_info_entry *)
|
||||||
|
(buffer + sizeof(struct devman_device_info));
|
||||||
|
|
||||||
|
TAILQ_FOREACH(attribute, &dev->attrs, list) {
|
||||||
|
entry->type = 0; /* TODO: use macro */
|
||||||
|
entry->name_offset =
|
||||||
|
save_string(string_buffer, attribute->name, &string_buffer_offset);
|
||||||
|
entry->data_offset =
|
||||||
|
save_string(string_buffer, attribute->data, &string_buffer_offset);
|
||||||
|
entry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*overall_size = size + strings_size;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_add_device *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC int devman_add_device(struct devman_dev *dev)
|
||||||
|
{
|
||||||
|
message msg;
|
||||||
|
int res;
|
||||||
|
size_t grant_size;
|
||||||
|
void *buf = serialize_dev(dev, &grant_size);
|
||||||
|
|
||||||
|
cp_grant_id_t gid =
|
||||||
|
cpf_grant_direct(devman_ep,(vir_bytes) buf,
|
||||||
|
grant_size, CPF_READ);
|
||||||
|
|
||||||
|
/* prepare message */
|
||||||
|
msg.m_type = DEVMAN_ADD_DEV;
|
||||||
|
msg.DEVMAN_GRANT_ID = gid;
|
||||||
|
msg.DEVMAN_GRANT_SIZE = grant_size;
|
||||||
|
|
||||||
|
/* send message */
|
||||||
|
res = sendrec(devman_ep, &msg);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
panic("devman_add_device: could not talk to devman: %d", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.m_type != DEVMAN_REPLY) {
|
||||||
|
panic("devman_add_device: got illegal response from devman: %d",
|
||||||
|
msg.m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.DEVMAN_RESULT != 0) {
|
||||||
|
panic("devman_add_device: could add device: %d",
|
||||||
|
msg.DEVMAN_RESULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store given dev_id to dev */
|
||||||
|
dev->dev_id = msg.DEVMAN_DEVICE_ID;
|
||||||
|
|
||||||
|
cpf_revoke(gid);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
/* put device in list */
|
||||||
|
TAILQ_INSERT_HEAD(&dev_list, dev, dev_list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_del_device *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC int devman_del_device(struct devman_dev *dev)
|
||||||
|
{
|
||||||
|
message msg;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
msg.m_type = DEVMAN_DEL_DEV;
|
||||||
|
msg.DEVMAN_DEVICE_ID = dev->dev_id;
|
||||||
|
|
||||||
|
res = sendrec(devman_ep, &msg);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
panic("devman_del_device: could not talk to devman: %d", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.m_type != DEVMAN_REPLY) {
|
||||||
|
panic("devman_del_device: got illegal response from devman: %d",
|
||||||
|
msg.m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.DEVMAN_RESULT != 0) {
|
||||||
|
panic("devman_del_device: could delete device: %d",
|
||||||
|
msg.DEVMAN_RESULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the device from list */
|
||||||
|
TAILQ_REMOVE(&dev_list, dev, dev_list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_get_ep *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC endpoint_t devman_get_ep()
|
||||||
|
{
|
||||||
|
return devman_ep;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_init *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC int devman_init()
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
message msg;
|
||||||
|
|
||||||
|
/* get the endpoint of the HCD */
|
||||||
|
res = ds_retrieve_label_endpt("devman", &devman_ep);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
panic("usb_init: ds_retrieve_label_endpt failed for 'devman': %d", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
TAILQ_INIT(&dev_list);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* do_bind *
|
||||||
|
***************************************************************************/
|
||||||
|
PRIVATE void do_bind(message *m)
|
||||||
|
{
|
||||||
|
struct devman_dev *dev;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* find device */
|
||||||
|
TAILQ_FOREACH(dev, &dev_list, dev_list) {
|
||||||
|
if (dev->dev_id == m->DEVMAN_DEVICE_ID) {
|
||||||
|
if (dev->bind_cb) {
|
||||||
|
res = dev->bind_cb(dev->data, m->DEVMAN_ENDPOINT);
|
||||||
|
m->m_type = DEVMAN_REPLY;
|
||||||
|
m->DEVMAN_RESULT = res;
|
||||||
|
send(devman_ep, m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m->m_type = DEVMAN_REPLY;
|
||||||
|
m->DEVMAN_RESULT = ENODEV;
|
||||||
|
send(devman_ep, m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* do_unbind *
|
||||||
|
***************************************************************************/
|
||||||
|
PRIVATE int do_unbind(message *m)
|
||||||
|
{
|
||||||
|
struct devman_dev *dev;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* find device */
|
||||||
|
TAILQ_FOREACH(dev, &dev_list, dev_list) {
|
||||||
|
if (dev->dev_id == m->DEVMAN_DEVICE_ID) {
|
||||||
|
if (dev->unbind_cb) {
|
||||||
|
res = dev->unbind_cb(dev->data, m->DEVMAN_ENDPOINT);
|
||||||
|
m->m_type = DEVMAN_REPLY;
|
||||||
|
m->DEVMAN_RESULT = res;
|
||||||
|
send(devman_ep, m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m->m_type = DEVMAN_REPLY;
|
||||||
|
m->DEVMAN_RESULT = ENODEV;
|
||||||
|
send(devman_ep, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_handle_msg *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC int devman_handle_msg(message *m)
|
||||||
|
{
|
||||||
|
/* make sure msg comes from devman server */
|
||||||
|
if (m->m_source != devman_ep) {
|
||||||
|
/* we don't honor requests from others by answering them */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (m->m_type) {
|
||||||
|
case DEVMAN_BIND:
|
||||||
|
do_bind(m);
|
||||||
|
return 1;
|
||||||
|
case DEVMAN_UNBIND:
|
||||||
|
do_unbind(m);
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
27
lib/libdevman/local.h
Normal file
27
lib/libdevman/local.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef _LIB_LIBDEVMAN_LOCAL
|
||||||
|
#define _LIB_LIBDEVMAN_LOCAL
|
||||||
|
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <minix/com.h>
|
||||||
|
|
||||||
|
#define DEVMAN_DEV_NAME_LEN 32
|
||||||
|
|
||||||
|
struct devman_dev {
|
||||||
|
int dev_id;
|
||||||
|
int parent_dev_id;
|
||||||
|
char name[DEVMAN_DEV_NAME_LEN];
|
||||||
|
char *subsys;
|
||||||
|
void *data;
|
||||||
|
int (*bind_cb) (void *data, endpoint_t ep);
|
||||||
|
int (*unbind_cb)(void *data, endpoint_t ep);
|
||||||
|
TAILQ_HEAD(static_attribute_head, devman_static_attribute) attrs;
|
||||||
|
TAILQ_ENTRY(devman_dev) dev_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct devman_static_attribute {
|
||||||
|
char *name;
|
||||||
|
char *data;
|
||||||
|
TAILQ_ENTRY(devman_static_attribute) list;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
300
lib/libdevman/usb.c
Normal file
300
lib/libdevman/usb.c
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <minix/config.h>
|
||||||
|
#include <minix/const.h>
|
||||||
|
#include <minix/devman.h>
|
||||||
|
#include <minix/usb.h>
|
||||||
|
|
||||||
|
#include "local.h"
|
||||||
|
|
||||||
|
#define CHECKOUTOFMEM(ptr) if(ptr == NULL) \
|
||||||
|
panic("Out of memory! (%s, line %d)" \
|
||||||
|
__FILE__, __LINE__)
|
||||||
|
|
||||||
|
|
||||||
|
static int (*bind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep);
|
||||||
|
static int (*unbind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_usb_add_attr *
|
||||||
|
***************************************************************************/
|
||||||
|
PRIVATE void
|
||||||
|
devman_usb_add_attr
|
||||||
|
(struct devman_dev *dev, char *name, char *data)
|
||||||
|
{
|
||||||
|
struct devman_static_attribute *attr = (struct devman_static_attribute *)
|
||||||
|
malloc(sizeof(struct devman_static_attribute));
|
||||||
|
|
||||||
|
CHECKOUTOFMEM(attr);
|
||||||
|
|
||||||
|
attr->name = malloc((strlen(name)+1)*sizeof(char));
|
||||||
|
memcpy(attr->name, name, (strlen(name)+1));
|
||||||
|
|
||||||
|
attr->data = malloc((strlen(data)+1)*sizeof(char));
|
||||||
|
memcpy(attr->data, data, (strlen(data)+1));
|
||||||
|
TAILQ_INSERT_TAIL(&dev->attrs, attr, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* add_device_attributes *
|
||||||
|
***************************************************************************/
|
||||||
|
PRIVATE void
|
||||||
|
add_device_attributes
|
||||||
|
(struct devman_usb_dev *udev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char data[32];
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",udev->desc->bDeviceClass);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(udev->dev, "bDeviceClass", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",udev->desc->bDeviceSubClass);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(udev->dev, "bDeviceSubClass", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",udev->desc->bDeviceProtocol);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(udev->dev, "bDeviceProtocol", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%04x",UGETW(udev->desc->idVendor));
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(udev->dev, "idVendor", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%04x",UGETW(udev->desc->idProduct));
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(udev->dev, "idProduct", data);
|
||||||
|
|
||||||
|
if (udev->product)
|
||||||
|
devman_usb_add_attr(udev->dev, "Product", udev->product);
|
||||||
|
if (udev->manufacturer)
|
||||||
|
devman_usb_add_attr(udev->dev, "Manufacturer", udev->manufacturer);
|
||||||
|
if (udev->serial)
|
||||||
|
devman_usb_add_attr(udev->dev, "SerialNumber", udev->serial);
|
||||||
|
devman_usb_add_attr(udev->dev, "dev_type", "USB_DEV");
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* add_interface_attributes *
|
||||||
|
***************************************************************************/
|
||||||
|
PRIVATE void
|
||||||
|
add_interface_attributes
|
||||||
|
(struct devman_usb_interface *intf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char data[32];
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",intf->desc->bInterfaceNumber);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(intf->dev, "bInterfaceNumber", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",intf->desc->bAlternateSetting);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(intf->dev, "bAlternateSetting", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",intf->desc->bNumEndpoints);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(intf->dev, "bNumEndpoints", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",intf->desc->bInterfaceClass);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(intf->dev, "bInterfaceClass", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",intf->desc->bInterfaceSubClass);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(intf->dev, "bInterfaceSubClass", data);
|
||||||
|
|
||||||
|
ret = sprintf(data,"0x%02x",intf->desc->bInterfaceProtocol);
|
||||||
|
if (ret < 0) {
|
||||||
|
panic("add_device_attributes: sprintf failed");
|
||||||
|
}
|
||||||
|
devman_usb_add_attr(intf->dev, "bInterfaceProtocol", data);
|
||||||
|
|
||||||
|
devman_usb_add_attr(intf->dev, "dev_type", "USB_INTF");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_usb_device_new *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC struct devman_usb_dev*
|
||||||
|
devman_usb_device_new
|
||||||
|
(int dev_id)
|
||||||
|
{
|
||||||
|
struct devman_usb_dev *udev = NULL;
|
||||||
|
struct devman_dev * dev = NULL;
|
||||||
|
|
||||||
|
udev = (struct devman_usb_dev *) malloc(sizeof(struct devman_usb_dev));
|
||||||
|
|
||||||
|
CHECKOUTOFMEM(udev);
|
||||||
|
|
||||||
|
/* allocate device */
|
||||||
|
dev = (struct devman_dev *) malloc(sizeof(struct devman_dev));
|
||||||
|
|
||||||
|
CHECKOUTOFMEM(dev);
|
||||||
|
|
||||||
|
udev->dev_id = dev_id;
|
||||||
|
udev->dev = dev;
|
||||||
|
|
||||||
|
dev->parent_dev_id = 0; /* For now add it directly to the root dev */
|
||||||
|
|
||||||
|
snprintf(dev->name, DEVMAN_DEV_NAME_LEN, "USB%d", dev_id);
|
||||||
|
|
||||||
|
TAILQ_INIT(&dev->attrs);
|
||||||
|
|
||||||
|
return udev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_usb_device_delete *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC void devman_usb_device_delete(struct devman_usb_dev *udev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct devman_static_attribute *attr,*temp;
|
||||||
|
|
||||||
|
|
||||||
|
for (i=0; i < udev->intf_count; i++) {
|
||||||
|
TAILQ_FOREACH_SAFE(attr, &udev->interfaces[i].dev->attrs, list, temp)
|
||||||
|
{
|
||||||
|
free(attr->name);
|
||||||
|
free(attr->data);
|
||||||
|
free(attr);
|
||||||
|
}
|
||||||
|
free(udev->interfaces[i].dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(attr, &udev->dev->attrs, list, temp) {
|
||||||
|
free(attr->name);
|
||||||
|
free(attr->data);
|
||||||
|
free(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(udev->dev);
|
||||||
|
free(udev);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE int devman_usb_bind_cb(void *data, endpoint_t ep) {
|
||||||
|
if (bind_cb) {
|
||||||
|
return bind_cb((struct devman_usb_bind_cb_data *) data, ep);
|
||||||
|
} else {
|
||||||
|
return ENODEV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIVATE int devman_usb_unbind_cb(void *data, endpoint_t ep) {
|
||||||
|
if (unbind_cb) {
|
||||||
|
return unbind_cb((struct devman_usb_bind_cb_data *) data, ep);
|
||||||
|
} else {
|
||||||
|
return ENODEV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_usb_device_add *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC int devman_usb_device_add(struct devman_usb_dev *dev)
|
||||||
|
{
|
||||||
|
int i,res = 0;
|
||||||
|
add_device_attributes(dev);
|
||||||
|
|
||||||
|
/* add the USB device */
|
||||||
|
dev->cb_data.dev_id = dev->dev_id;
|
||||||
|
dev->cb_data.interface = -1;
|
||||||
|
|
||||||
|
dev->dev->bind_cb = devman_usb_bind_cb;
|
||||||
|
dev->dev->unbind_cb = devman_usb_unbind_cb;
|
||||||
|
dev->dev->data = &dev->cb_data;
|
||||||
|
|
||||||
|
res = devman_add_device(dev->dev);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
panic("devman_usb_device_add(): devman_add_device failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the USB interfaces */
|
||||||
|
for (i=0; i < dev->intf_count; i++) {
|
||||||
|
/* prepare */
|
||||||
|
dev->interfaces[i].dev =
|
||||||
|
(struct devman_dev *) malloc(sizeof(struct devman_dev));
|
||||||
|
CHECKOUTOFMEM(dev->interfaces[i].dev);
|
||||||
|
|
||||||
|
TAILQ_INIT(&dev->interfaces[i].dev->attrs);
|
||||||
|
snprintf(dev->interfaces[i].dev->name, DEVMAN_DEV_NAME_LEN,
|
||||||
|
"intf%d", i);
|
||||||
|
|
||||||
|
add_interface_attributes(&dev->interfaces[i]);
|
||||||
|
|
||||||
|
dev->interfaces[i].dev->parent_dev_id = dev->dev->dev_id;
|
||||||
|
|
||||||
|
|
||||||
|
dev->interfaces[i].cb_data.dev_id = dev->dev_id;
|
||||||
|
dev->interfaces[i].cb_data.interface =
|
||||||
|
dev->interfaces[i].desc->bInterfaceNumber;
|
||||||
|
|
||||||
|
dev->interfaces[i].dev->bind_cb = devman_usb_bind_cb;
|
||||||
|
dev->interfaces[i].dev->unbind_cb = devman_usb_unbind_cb;
|
||||||
|
dev->interfaces[i].dev->data = &dev->interfaces[i].cb_data;
|
||||||
|
|
||||||
|
/* add */
|
||||||
|
res = devman_add_device(dev->interfaces[i].dev);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
panic("devman_usb_device_add(): devman_add_device failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_usb_device_remove *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC int devman_usb_device_remove(struct devman_usb_dev *dev)
|
||||||
|
{
|
||||||
|
int i, res = 0;
|
||||||
|
|
||||||
|
for (i=0; i < dev->intf_count; i++) {
|
||||||
|
|
||||||
|
res = devman_del_device(dev->interfaces[i].dev);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
panic("devman_usb_device_remove(): devman_del_device failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = devman_del_device(dev->dev);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* devman_usb_init *
|
||||||
|
***************************************************************************/
|
||||||
|
PUBLIC int devman_usb_init
|
||||||
|
(int (*_bind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep),
|
||||||
|
int (*_unbind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep))
|
||||||
|
{
|
||||||
|
bind_cb = _bind_cb;
|
||||||
|
unbind_cb = _unbind_cb;
|
||||||
|
}
|
|
@ -59,7 +59,7 @@ MKDEP_SUFFIXES?= .o .ln
|
||||||
# rumpfs_tmpfs rumpfs_udf rumpfs_ufs
|
# rumpfs_tmpfs rumpfs_udf rumpfs_ufs
|
||||||
.for _lib in \
|
.for _lib in \
|
||||||
c curses driver netdriver edit end m sys timers util bz2 l hgfs \
|
c curses driver netdriver edit end m sys timers util bz2 l hgfs \
|
||||||
audiodriver exec usb
|
audiodriver exec devman usb
|
||||||
.ifndef LIB${_lib:tu}
|
.ifndef LIB${_lib:tu}
|
||||||
LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a
|
LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a
|
||||||
.if ${COMPILER_TYPE} == "ack"
|
.if ${COMPILER_TYPE} == "ack"
|
||||||
|
|
Loading…
Reference in a new issue