00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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