--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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;
+}