connhost.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Vojtech Horky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <assert.h>
00036 #include <errno.h>
00037 #include <usb/usb.h>
00038 #include <usb/ddfiface.h>
00039 #include <usb/debug.h>
00040 #include <usbhc_iface.h>
00041 #include "vhcd.h"
00042 
00043 #define GET_VHC_DATA(fun) \
00044         ((vhc_data_t *)fun->dev->driver_data)
00045 #define VHC_DATA(vhc, fun) \
00046         vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef)
00047 
00048 #define UNSUPPORTED(methodname) \
00049         usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
00050             methodname, __FILE__, __LINE__)
00051 
00059 static int request_address(ddf_fun_t *fun, usb_speed_t speed,
00060     usb_address_t *address)
00061 {
00062         VHC_DATA(vhc, fun);
00063 
00064         usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper,
00065             USB_SPEED_HIGH);
00066         if (addr < 0) {
00067                 return addr;
00068         }
00069 
00070         if (address != NULL) {
00071                 *address = addr;
00072         }
00073 
00074         return EOK;
00075 }
00076 
00084 static int bind_address(ddf_fun_t *fun,
00085     usb_address_t address, devman_handle_t handle)
00086 {
00087         VHC_DATA(vhc, fun);
00088         usb_log_debug("Binding handle %" PRIun " to address %d.\n",
00089             handle, address);
00090         usb_device_keeper_bind(&vhc->dev_keeper, address, handle);
00091 
00092         return EOK;
00093 }
00094 
00102 static int find_by_address(ddf_fun_t *fun, usb_address_t address,
00103     devman_handle_t *handle)
00104 {
00105         VHC_DATA(vhc, fun);
00106         bool found =
00107             usb_device_keeper_find_by_address(&vhc->dev_keeper, address, handle);
00108         return found ? EOK : ENOENT;
00109 }
00110 
00117 static int release_address(ddf_fun_t *fun, usb_address_t address)
00118 {
00119         VHC_DATA(vhc, fun);
00120         usb_log_debug("Releasing address %d...\n", address);
00121         usb_device_keeper_release(&vhc->dev_keeper, address);
00122 
00123         return ENOTSUP;
00124 }
00125 
00138 static int register_endpoint(ddf_fun_t *fun,
00139     usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
00140     usb_transfer_type_t transfer_type, usb_direction_t direction,
00141     size_t max_packet_size, unsigned int interval)
00142 {
00143         VHC_DATA(vhc, fun);
00144 
00145         endpoint_t *ep = malloc(sizeof(endpoint_t));
00146         if (ep == NULL) {
00147                 return ENOMEM;
00148         }
00149 
00150         int rc = endpoint_init(ep, address, endpoint, direction, transfer_type,
00151             USB_SPEED_FULL, 1);
00152         if (rc != EOK) {
00153                 free(ep);
00154                 return rc;
00155         }
00156 
00157         rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
00158         if (rc != EOK) {
00159                 endpoint_destroy(ep);
00160                 return rc;
00161         }
00162 
00163         return EOK;
00164 }
00165 
00174 static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
00175     usb_endpoint_t endpoint, usb_direction_t direction)
00176 {
00177         VHC_DATA(vhc, fun);
00178 
00179         endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
00180             address, endpoint, direction, NULL);
00181         if (ep == NULL) {
00182                 return ENOENT;
00183         }
00184 
00185         int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
00186             address, endpoint, direction);
00187 
00188         return rc;
00189 }
00190 
00207 static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
00208     void *data, size_t size,
00209     usbhc_iface_transfer_out_callback_t callback, void *arg)
00210 {
00211         VHC_DATA(vhc, fun);
00212 
00213         vhc_transfer_t *transfer = vhc_transfer_create(target.address,
00214             target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_INTERRUPT,
00215             fun, arg);
00216         if (transfer == NULL) {
00217                 return ENOMEM;
00218         }
00219 
00220         transfer->data_buffer = data;
00221         transfer->data_buffer_size = size;
00222         transfer->callback_out = callback;
00223 
00224         int rc = vhc_virtdev_add_transfer(vhc, transfer);
00225         if (rc != EOK) {
00226                 free(transfer);
00227                 return rc;
00228         }
00229 
00230         return EOK;
00231 }
00232 
00249 static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
00250     void *data, size_t size,
00251     usbhc_iface_transfer_in_callback_t callback, void *arg)
00252 {
00253         VHC_DATA(vhc, fun);
00254 
00255         vhc_transfer_t *transfer = vhc_transfer_create(target.address,
00256             target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_INTERRUPT,
00257             fun, arg);
00258         if (transfer == NULL) {
00259                 return ENOMEM;
00260         }
00261 
00262         transfer->data_buffer = data;
00263         transfer->data_buffer_size = size;
00264         transfer->callback_in = callback;
00265 
00266         int rc = vhc_virtdev_add_transfer(vhc, transfer);
00267         if (rc != EOK) {
00268                 free(transfer);
00269                 return rc;
00270         }
00271 
00272         return EOK;
00273 }
00274 
00291 static int bulk_out(ddf_fun_t *fun, usb_target_t target,
00292     void *data, size_t size,
00293     usbhc_iface_transfer_out_callback_t callback, void *arg)
00294 {
00295         UNSUPPORTED("bulk_out");
00296 
00297         return ENOTSUP;
00298 }
00299 
00316 static int bulk_in(ddf_fun_t *fun, usb_target_t target,
00317     void *data, size_t size,
00318     usbhc_iface_transfer_in_callback_t callback, void *arg)
00319 {
00320         UNSUPPORTED("bulk_in");
00321 
00322         return ENOTSUP;
00323 }
00324 
00344 static int control_write(ddf_fun_t *fun, usb_target_t target,
00345     void *setup_packet, size_t setup_packet_size,
00346     void *data_buffer, size_t data_buffer_size,
00347     usbhc_iface_transfer_out_callback_t callback, void *arg)
00348 {
00349         VHC_DATA(vhc, fun);
00350 
00351         vhc_transfer_t *transfer = vhc_transfer_create(target.address,
00352             target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_CONTROL,
00353             fun, arg);
00354         if (transfer == NULL) {
00355                 return ENOMEM;
00356         }
00357 
00358         transfer->setup_buffer = setup_packet;
00359         transfer->setup_buffer_size = setup_packet_size;
00360         transfer->data_buffer = data_buffer;
00361         transfer->data_buffer_size = data_buffer_size;
00362         transfer->callback_out = callback;
00363 
00364         int rc = vhc_virtdev_add_transfer(vhc, transfer);
00365         if (rc != EOK) {
00366                 free(transfer);
00367                 return rc;
00368         }
00369 
00370         return EOK;
00371 }
00372 
00392 static int control_read(ddf_fun_t *fun, usb_target_t target,
00393     void *setup_packet, size_t setup_packet_size,
00394     void *data_buffer, size_t data_buffer_size,
00395     usbhc_iface_transfer_in_callback_t callback, void *arg)
00396 {
00397         VHC_DATA(vhc, fun);
00398 
00399         vhc_transfer_t *transfer = vhc_transfer_create(target.address,
00400             target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_CONTROL,
00401             fun, arg);
00402         if (transfer == NULL) {
00403                 return ENOMEM;
00404         }
00405 
00406         transfer->setup_buffer = setup_packet;
00407         transfer->setup_buffer_size = setup_packet_size;
00408         transfer->data_buffer = data_buffer;
00409         transfer->data_buffer_size = data_buffer_size;
00410         transfer->callback_in = callback;
00411 
00412         int rc = vhc_virtdev_add_transfer(vhc, transfer);
00413         if (rc != EOK) {
00414                 free(transfer);
00415                 return rc;
00416         }
00417 
00418         return EOK;
00419 }
00420 
00421 static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
00422     usb_address_t *address)
00423 {
00424         UNSUPPORTED("tell_address");
00425 
00426         return ENOTSUP;
00427 }
00428 
00429 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
00430     devman_handle_t *handle)
00431 {
00432         VHC_DATA(vhc, root_hub_fun);
00433 
00434         *handle = vhc->hc_fun->handle;
00435 
00436         return EOK;
00437 }
00438 
00439 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
00440     usb_address_t *address)
00441 {
00442         VHC_DATA(vhc, root_hub_fun);
00443 
00444         if (handle == 0) {
00445                 handle = root_hub_fun->handle;
00446         }
00447 
00448         usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
00449         usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle);
00450         if (addr < 0) {
00451                 return addr;
00452         } else {
00453                 *address = addr;
00454                 return EOK;
00455         }
00456 }
00457 
00458 usbhc_iface_t vhc_iface = {
00459         .request_address = request_address,
00460         .bind_address = bind_address,
00461         .find_by_address = find_by_address,
00462         .release_address = release_address,
00463 
00464         .register_endpoint = register_endpoint,
00465         .unregister_endpoint = unregister_endpoint,
00466 
00467         .interrupt_out = interrupt_out,
00468         .interrupt_in = interrupt_in,
00469 
00470         .bulk_in = bulk_in,
00471         .bulk_out = bulk_out,
00472 
00473         .control_write = control_write,
00474         .control_read = control_read
00475 };
00476 
00477 usb_iface_t vhc_usb_iface = {
00478         .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
00479         .get_address = tell_address
00480 };
00481 
00482 usb_iface_t rh_usb_iface = {
00483         .get_hc_handle = usb_iface_get_hc_handle_rh_impl,
00484         .get_address = tell_address_rh
00485 };
00486 
00487 

Generated on Thu Jun 2 07:45:44 2011 for HelenOS/USB by  doxygen 1.4.7