00001 #include <errno.h>
00002 #include "vhcd.h"
00003 #include "hub/virthub.h"
00004
00005
00006 static vhc_virtdev_t *vhc_virtdev_create()
00007 {
00008 vhc_virtdev_t *dev = malloc(sizeof(vhc_virtdev_t));
00009 if (dev == NULL) {
00010 return NULL;
00011 }
00012 dev->address = 0;
00013 dev->dev_phone = -1;
00014 dev->dev_local = NULL;
00015 dev->plugged = true;
00016 link_initialize(&dev->link);
00017 fibril_mutex_initialize(&dev->guard);
00018 list_initialize(&dev->transfer_queue);
00019
00020 return dev;
00021 }
00022
00023 static int vhc_virtdev_plug_generic(vhc_data_t *vhc,
00024 int phone, usbvirt_device_t *virtdev,
00025 uintptr_t *handle, bool connect)
00026 {
00027 vhc_virtdev_t *dev = vhc_virtdev_create();
00028 if (dev == NULL) {
00029 return ENOMEM;
00030 }
00031
00032 dev->dev_phone = phone;
00033 dev->dev_local = virtdev;
00034
00035 fibril_mutex_lock(&vhc->guard);
00036 list_append(&dev->link, &vhc->devices);
00037 fibril_mutex_unlock(&vhc->guard);
00038
00039 fid_t fibril = fibril_create(vhc_transfer_queue_processor, dev);
00040 if (fibril == 0) {
00041 free(dev);
00042 return ENOMEM;
00043 }
00044 fibril_add_ready(fibril);
00045
00046 if (handle != NULL) {
00047 *handle = (uintptr_t) dev;
00048 }
00049
00050 if (connect) {
00051
00052 (void) virthub_connect_device(vhc->hub, dev);
00053 }
00054
00055 return EOK;
00056 }
00057
00058 int vhc_virtdev_plug(vhc_data_t *vhc, int phone, uintptr_t *handle)
00059 {
00060 return vhc_virtdev_plug_generic(vhc, phone, NULL, handle, true);
00061 }
00062
00063 int vhc_virtdev_plug_local(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
00064 {
00065 return vhc_virtdev_plug_generic(vhc, -1, dev, handle, true);
00066 }
00067
00068 int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
00069 {
00070 return vhc_virtdev_plug_generic(vhc, -1, dev, handle, false);
00071 }
00072
00073 void vhc_virtdev_unplug(vhc_data_t *vhc, uintptr_t handle)
00074 {
00075 vhc_virtdev_t *dev = (vhc_virtdev_t *) handle;
00076
00077
00078 (void) virthub_disconnect_device(vhc->hub, dev);
00079
00080 fibril_mutex_lock(&vhc->guard);
00081 fibril_mutex_lock(&dev->guard);
00082 dev->plugged = false;
00083 list_remove(&dev->link);
00084 fibril_mutex_unlock(&dev->guard);
00085 fibril_mutex_unlock(&vhc->guard);
00086 }