Changeset 00aece0 in mainline for uspace/lib/drv/generic
- Timestamp:
- 2012-02-18T16:47:38Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4449c6c
- Parents:
- bd5f3b7 (diff), f943dd3 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib/drv/generic
- Files:
-
- 2 added
- 5 edited
-
dev_iface.c (modified) (3 diffs)
-
driver.c (modified) (19 diffs)
-
interrupt.c (added)
-
remote_nic.c (added)
-
remote_pci.c (modified) (1 diff)
-
remote_usb.c (modified) (4 diffs)
-
remote_usbhc.c (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/dev_iface.c
rbd5f3b7 r00aece0 41 41 #include "remote_hw_res.h" 42 42 #include "remote_char_dev.h" 43 #include "remote_nic.h" 43 44 #include "remote_usb.h" 44 45 #include "remote_usbhc.h" … … 46 47 #include "remote_pci.h" 47 48 48 #include <stdio.h>49 50 49 static iface_dipatch_table_t remote_ifaces = { 51 50 .ifaces = { 52 51 &remote_hw_res_iface, 53 52 &remote_char_dev_iface, 53 &remote_nic_iface, 54 54 &remote_pci_iface, 55 55 &remote_usb_iface, … … 68 68 get_remote_method(remote_iface_t *rem_iface, sysarg_t iface_method_idx) 69 69 { 70 if (iface_method_idx >= rem_iface->method_count) {70 if (iface_method_idx >= rem_iface->method_count) 71 71 return NULL; 72 } 73 72 74 73 return rem_iface->methods[iface_method_idx]; 75 74 } -
uspace/lib/drv/generic/driver.c
rbd5f3b7 r00aece0 63 63 64 64 /** Devices */ 65 LIST_INITIALIZE(devices); 66 FIBRIL_MUTEX_INITIALIZE(devices_mutex); 67 68 /** Functions */ 65 69 LIST_INITIALIZE(functions); 66 70 FIBRIL_MUTEX_INITIALIZE(functions_mutex); 67 71 68 /** Interrupts */69 static interrupt_context_list_t interrupt_contexts;70 71 static irq_cmd_t default_cmds[] = {72 {73 .cmd = CMD_ACCEPT74 }75 };76 77 static irq_code_t default_pseudocode = {78 sizeof(default_cmds) / sizeof(irq_cmd_t),79 default_cmds80 };81 82 72 static ddf_dev_t *create_device(void); 83 73 static void delete_device(ddf_dev_t *); 74 static void dev_add_ref(ddf_dev_t *); 75 static void dev_del_ref(ddf_dev_t *); 76 static void fun_add_ref(ddf_fun_t *); 77 static void fun_del_ref(ddf_fun_t *); 84 78 static remote_handler_t *function_get_default_handler(ddf_fun_t *); 85 79 static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t); 86 87 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)88 {89 int id = (int)IPC_GET_IMETHOD(*icall);90 interrupt_context_t *ctx;91 92 ctx = find_interrupt_context_by_id(&interrupt_contexts, id);93 if (ctx != NULL && ctx->handler != NULL)94 (*ctx->handler)(ctx->dev, iid, icall);95 }96 97 interrupt_context_t *create_interrupt_context(void)98 {99 interrupt_context_t *ctx;100 101 ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));102 if (ctx != NULL)103 memset(ctx, 0, sizeof(interrupt_context_t));104 105 return ctx;106 }107 108 void delete_interrupt_context(interrupt_context_t *ctx)109 {110 if (ctx != NULL)111 free(ctx);112 }113 114 void init_interrupt_context_list(interrupt_context_list_t *list)115 {116 memset(list, 0, sizeof(interrupt_context_list_t));117 fibril_mutex_initialize(&list->mutex);118 list_initialize(&list->contexts);119 }120 121 void122 add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)123 {124 fibril_mutex_lock(&list->mutex);125 ctx->id = list->curr_id++;126 list_append(&ctx->link, &list->contexts);127 fibril_mutex_unlock(&list->mutex);128 }129 130 void remove_interrupt_context(interrupt_context_list_t *list,131 interrupt_context_t *ctx)132 {133 fibril_mutex_lock(&list->mutex);134 list_remove(&ctx->link);135 fibril_mutex_unlock(&list->mutex);136 }137 138 interrupt_context_t *139 find_interrupt_context_by_id(interrupt_context_list_t *list, int id)140 {141 interrupt_context_t *ctx;142 143 fibril_mutex_lock(&list->mutex);144 145 list_foreach(list->contexts, link) {146 ctx = list_get_instance(link, interrupt_context_t, link);147 if (ctx->id == id) {148 fibril_mutex_unlock(&list->mutex);149 return ctx;150 }151 }152 153 fibril_mutex_unlock(&list->mutex);154 return NULL;155 }156 157 interrupt_context_t *158 find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)159 {160 interrupt_context_t *ctx;161 162 fibril_mutex_lock(&list->mutex);163 164 list_foreach(list->contexts, link) {165 ctx = list_get_instance(link, interrupt_context_t, link);166 if (ctx->irq == irq && ctx->dev == dev) {167 fibril_mutex_unlock(&list->mutex);168 return ctx;169 }170 }171 172 fibril_mutex_unlock(&list->mutex);173 return NULL;174 }175 176 177 int178 register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,179 irq_code_t *pseudocode)180 {181 interrupt_context_t *ctx = create_interrupt_context();182 183 ctx->dev = dev;184 ctx->irq = irq;185 ctx->handler = handler;186 187 add_interrupt_context(&interrupt_contexts, ctx);188 189 if (pseudocode == NULL)190 pseudocode = &default_pseudocode;191 192 int res = register_irq(irq, dev->handle, ctx->id, pseudocode);193 if (res != EOK) {194 remove_interrupt_context(&interrupt_contexts, ctx);195 delete_interrupt_context(ctx);196 }197 198 return res;199 }200 201 int unregister_interrupt_handler(ddf_dev_t *dev, int irq)202 {203 interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,204 dev, irq);205 int res = unregister_irq(irq, dev->handle);206 207 if (ctx != NULL) {208 remove_interrupt_context(&interrupt_contexts, ctx);209 delete_interrupt_context(ctx);210 }211 212 return res;213 }214 80 215 81 static void add_to_functions_list(ddf_fun_t *fun) … … 227 93 } 228 94 229 static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle) 95 static ddf_dev_t *driver_get_device(devman_handle_t handle) 96 { 97 ddf_dev_t *dev = NULL; 98 99 assert(fibril_mutex_is_locked(&devices_mutex)); 100 101 list_foreach(devices, link) { 102 dev = list_get_instance(link, ddf_dev_t, link); 103 if (dev->handle == handle) 104 return dev; 105 } 106 107 return NULL; 108 } 109 110 static ddf_fun_t *driver_get_function(devman_handle_t handle) 230 111 { 231 112 ddf_fun_t *fun = NULL; 232 113 233 fibril_mutex_lock(&functions_mutex);234 235 list_foreach( *functions, link) {114 assert(fibril_mutex_is_locked(&functions_mutex)); 115 116 list_foreach(functions, link) { 236 117 fun = list_get_instance(link, ddf_fun_t, link); 237 if (fun->handle == handle) { 238 fibril_mutex_unlock(&functions_mutex); 118 if (fun->handle == handle) 239 119 return fun; 240 } 241 } 242 243 fibril_mutex_unlock(&functions_mutex); 120 } 244 121 245 122 return NULL; 246 123 } 247 124 248 static void driver_ add_device(ipc_callid_t iid, ipc_call_t *icall)125 static void driver_dev_add(ipc_callid_t iid, ipc_call_t *icall) 249 126 { 250 127 char *dev_name = NULL; … … 252 129 253 130 devman_handle_t dev_handle = IPC_GET_ARG1(*icall); 254 devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);131 devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall); 255 132 256 133 ddf_dev_t *dev = create_device(); 134 135 /* Add one reference that will be dropped by driver_dev_remove() */ 136 dev_add_ref(dev); 257 137 dev->handle = dev_handle; 258 138 … … 266 146 (void) parent_fun_handle; 267 147 268 res = driver->driver_ops->add_device(dev); 269 if (res != EOK) 270 delete_device(dev); 148 res = driver->driver_ops->dev_add(dev); 149 150 if (res != EOK) { 151 dev_del_ref(dev); 152 async_answer_0(iid, res); 153 return; 154 } 155 156 fibril_mutex_lock(&devices_mutex); 157 list_append(&dev->link, &devices); 158 fibril_mutex_unlock(&devices_mutex); 271 159 272 160 async_answer_0(iid, res); 161 } 162 163 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall) 164 { 165 devman_handle_t devh; 166 ddf_dev_t *dev; 167 int rc; 168 169 devh = IPC_GET_ARG1(*icall); 170 171 fibril_mutex_lock(&devices_mutex); 172 dev = driver_get_device(devh); 173 if (dev != NULL) 174 dev_add_ref(dev); 175 fibril_mutex_unlock(&devices_mutex); 176 177 if (dev == NULL) { 178 async_answer_0(iid, ENOENT); 179 return; 180 } 181 182 if (driver->driver_ops->dev_remove != NULL) 183 rc = driver->driver_ops->dev_remove(dev); 184 else 185 rc = ENOTSUP; 186 187 if (rc == EOK) 188 dev_del_ref(dev); 189 190 async_answer_0(iid, (sysarg_t) rc); 191 } 192 193 static void driver_dev_gone(ipc_callid_t iid, ipc_call_t *icall) 194 { 195 devman_handle_t devh; 196 ddf_dev_t *dev; 197 int rc; 198 199 devh = IPC_GET_ARG1(*icall); 200 201 fibril_mutex_lock(&devices_mutex); 202 dev = driver_get_device(devh); 203 if (dev != NULL) 204 dev_add_ref(dev); 205 fibril_mutex_unlock(&devices_mutex); 206 207 if (dev == NULL) { 208 async_answer_0(iid, ENOENT); 209 return; 210 } 211 212 if (driver->driver_ops->dev_gone != NULL) 213 rc = driver->driver_ops->dev_gone(dev); 214 else 215 rc = ENOTSUP; 216 217 if (rc == EOK) 218 dev_del_ref(dev); 219 220 async_answer_0(iid, (sysarg_t) rc); 221 } 222 223 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall) 224 { 225 devman_handle_t funh; 226 ddf_fun_t *fun; 227 int rc; 228 229 funh = IPC_GET_ARG1(*icall); 230 231 /* 232 * Look the function up. Bump reference count so that 233 * the function continues to exist until we return 234 * from the driver. 235 */ 236 fibril_mutex_lock(&functions_mutex); 237 238 fun = driver_get_function(funh); 239 if (fun != NULL) 240 fun_add_ref(fun); 241 242 fibril_mutex_unlock(&functions_mutex); 243 244 if (fun == NULL) { 245 async_answer_0(iid, ENOENT); 246 return; 247 } 248 249 /* Call driver entry point */ 250 if (driver->driver_ops->fun_online != NULL) 251 rc = driver->driver_ops->fun_online(fun); 252 else 253 rc = ENOTSUP; 254 255 fun_del_ref(fun); 256 257 async_answer_0(iid, (sysarg_t) rc); 258 } 259 260 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 261 { 262 devman_handle_t funh; 263 ddf_fun_t *fun; 264 int rc; 265 266 funh = IPC_GET_ARG1(*icall); 267 268 /* 269 * Look the function up. Bump reference count so that 270 * the function continues to exist until we return 271 * from the driver. 272 */ 273 fibril_mutex_lock(&functions_mutex); 274 275 fun = driver_get_function(funh); 276 if (fun != NULL) 277 fun_add_ref(fun); 278 279 fibril_mutex_unlock(&functions_mutex); 280 281 if (fun == NULL) { 282 async_answer_0(iid, ENOENT); 283 return; 284 } 285 286 /* Call driver entry point */ 287 if (driver->driver_ops->fun_offline != NULL) 288 rc = driver->driver_ops->fun_offline(fun); 289 else 290 rc = ENOTSUP; 291 292 async_answer_0(iid, (sysarg_t) rc); 273 293 } 274 294 … … 286 306 287 307 switch (IPC_GET_IMETHOD(call)) { 288 case DRIVER_ADD_DEVICE: 289 driver_add_device(callid, &call); 308 case DRIVER_DEV_ADD: 309 driver_dev_add(callid, &call); 310 break; 311 case DRIVER_DEV_REMOVE: 312 driver_dev_remove(callid, &call); 313 break; 314 case DRIVER_DEV_GONE: 315 driver_dev_gone(callid, &call); 316 break; 317 case DRIVER_FUN_ONLINE: 318 driver_fun_online(callid, &call); 319 break; 320 case DRIVER_FUN_OFFLINE: 321 driver_fun_offline(callid, &call); 290 322 break; 291 323 default: 292 async_answer_0(callid, ENO ENT);324 async_answer_0(callid, ENOTSUP); 293 325 } 294 326 } … … 308 340 */ 309 341 devman_handle_t handle = IPC_GET_ARG2(*icall); 310 ddf_fun_t *fun = driver_get_function(&functions, handle); 342 343 fibril_mutex_lock(&functions_mutex); 344 ddf_fun_t *fun = driver_get_function(handle); 345 fibril_mutex_unlock(&functions_mutex); 346 /* XXX Need a lock on fun */ 311 347 312 348 if (fun == NULL) { … … 466 502 ddf_dev_t *dev; 467 503 468 dev = malloc(sizeof(ddf_dev_t));504 dev = calloc(1, sizeof(ddf_dev_t)); 469 505 if (dev == NULL) 470 506 return NULL; 471 507 472 memset(dev, 0, sizeof(ddf_dev_t));473 508 return dev; 474 509 } … … 498 533 static void delete_device(ddf_dev_t *dev) 499 534 { 535 if (dev->driver_data != NULL) 536 free(dev->driver_data); 500 537 free(dev); 501 538 } 502 539 503 /** Delete devicestructure.540 /** Delete function structure. 504 541 * 505 542 * @param dev The device structure. … … 508 545 { 509 546 clean_match_ids(&fun->match_ids); 547 if (fun->driver_data != NULL) 548 free(fun->driver_data); 510 549 if (fun->name != NULL) 511 550 free(fun->name); … … 513 552 } 514 553 554 /** Increase device reference count. */ 555 static void dev_add_ref(ddf_dev_t *dev) 556 { 557 atomic_inc(&dev->refcnt); 558 } 559 560 /** Decrease device reference count. 561 * 562 * Free the device structure if the reference count drops to zero. 563 */ 564 static void dev_del_ref(ddf_dev_t *dev) 565 { 566 if (atomic_predec(&dev->refcnt) == 0) 567 delete_device(dev); 568 } 569 570 /** Increase function reference count. 571 * 572 * This also increases reference count on the device. The device structure 573 * will thus not be deallocated while there are some associated function 574 * structures. 575 */ 576 static void fun_add_ref(ddf_fun_t *fun) 577 { 578 dev_add_ref(fun->dev); 579 atomic_inc(&fun->refcnt); 580 } 581 582 /** Decrease function reference count. 583 * 584 * Free the function structure if the reference count drops to zero. 585 */ 586 static void fun_del_ref(ddf_fun_t *fun) 587 { 588 ddf_dev_t *dev = fun->dev; 589 590 if (atomic_predec(&fun->refcnt) == 0) 591 delete_function(fun); 592 593 dev_del_ref(dev); 594 } 595 596 /** Allocate driver-specific device data. */ 597 void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size) 598 { 599 void *data; 600 601 assert(dev->driver_data == NULL); 602 603 data = calloc(1, size); 604 if (data == NULL) 605 return NULL; 606 607 dev->driver_data = data; 608 return data; 609 } 610 515 611 /** Create a DDF function node. 516 612 * … … 544 640 return NULL; 545 641 642 /* Add one reference that will be dropped by ddf_fun_destroy() */ 643 fun->dev = dev; 644 fun_add_ref(fun); 645 546 646 fun->bound = false; 547 fun->dev = dev;548 647 fun->ftype = ftype; 549 648 … … 557 656 } 558 657 658 /** Allocate driver-specific function data. */ 659 void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size) 660 { 661 void *data; 662 663 assert(fun->bound == false); 664 assert(fun->driver_data == NULL); 665 666 data = calloc(1, size); 667 if (data == NULL) 668 return NULL; 669 670 fun->driver_data = data; 671 return data; 672 } 673 559 674 /** Destroy DDF function node. 560 675 * … … 567 682 { 568 683 assert(fun->bound == false); 569 delete_function(fun); 684 685 /* 686 * Drop the reference added by ddf_fun_create(). This will deallocate 687 * the function as soon as all other references are dropped (i.e. 688 * as soon control leaves all driver entry points called in context 689 * of this function. 690 */ 691 fun_del_ref(fun); 570 692 } 571 693 … … 614 736 * the function invisible to the system. 615 737 * 616 * @param fun Function to bind738 * @param fun Function to unbind 617 739 * @return EOK on success or negative error code 618 740 */ … … 623 745 assert(fun->bound == true); 624 746 625 add_to_functions_list(fun);626 747 res = devman_remove_function(fun->handle); 627 748 if (res != EOK) … … 631 752 632 753 fun->bound = false; 754 return EOK; 755 } 756 757 /** Online function. 758 * 759 * @param fun Function to online 760 * @return EOK on success or negative error code 761 */ 762 int ddf_fun_online(ddf_fun_t *fun) 763 { 764 int res; 765 766 assert(fun->bound == true); 767 768 res = devman_drv_fun_online(fun->handle); 769 if (res != EOK) 770 return res; 771 772 return EOK; 773 } 774 775 /** Offline function. 776 * 777 * @param fun Function to offline 778 * @return EOK on success or negative error code 779 */ 780 int ddf_fun_offline(ddf_fun_t *fun) 781 { 782 int res; 783 784 assert(fun->bound == true); 785 786 res = devman_drv_fun_offline(fun->handle); 787 if (res != EOK) 788 return res; 789 633 790 return EOK; 634 791 } … … 657 814 658 815 match_id->id = str_dup(match_id_str); 659 match_id->score = 90;816 match_id->score = match_score; 660 817 661 818 add_match_id(&fun->match_ids, match_id); … … 693 850 driver = drv; 694 851 695 /* Initialize the list of interrupt contexts. */ 696 init_interrupt_context_list(&interrupt_contexts); 697 698 /* Set generic interrupt handler. */ 699 async_set_interrupt_received(driver_irq_handler); 852 /* Initialize interrupt module */ 853 interrupt_init(); 700 854 701 855 /* … … 703 857 * incoming connections. 704 858 */ 705 rc = devman_driver_register(driver->name, driver_connection); 859 async_set_client_connection(driver_connection); 860 rc = devman_driver_register(driver->name); 706 861 if (rc != EOK) { 707 862 printf("Error: Failed to register driver with device manager " -
uspace/lib/drv/generic/remote_pci.c
rbd5f3b7 r00aece0 32 32 /** @file 33 33 */ 34 34 35 #include <assert.h> 35 36 #include <async.h> -
uspace/lib/drv/generic/remote_usb.c
rbd5f3b7 r00aece0 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 39 40 #include "ddf/driver.h" 40 41 42 typedef enum { 43 IPC_M_USB_GET_MY_ADDRESS, 44 IPC_M_USB_GET_MY_INTERFACE, 45 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, 46 } usb_iface_funcs_t; 41 47 42 static void remote_usb_get_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 43 static void remote_usb_get_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 48 /** Tell USB address assigned to device. 49 * @param exch Vaid IPC exchange 50 * @param address Pointer to address storage place. 51 * @return Error code. 52 * 53 * Exch param is an open communication to device implementing usb_iface. 54 */ 55 int usb_get_my_address(async_exch_t *exch, usb_address_t *address) 56 { 57 if (!exch) 58 return EINVAL; 59 sysarg_t addr; 60 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 61 IPC_M_USB_GET_MY_ADDRESS, &addr); 62 63 if (ret == EOK && address != NULL) 64 *address = (usb_address_t) addr; 65 return ret; 66 } 67 /*----------------------------------------------------------------------------*/ 68 /** Tell interface number given device can use. 69 * @param[in] exch IPC communication exchange 70 * @param[in] handle Id of the device 71 * @param[out] usb_iface Assigned USB interface 72 * @return Error code. 73 */ 74 int usb_get_my_interface(async_exch_t *exch, int *usb_iface) 75 { 76 if (!exch) 77 return EINVAL; 78 sysarg_t iface_no; 79 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 80 IPC_M_USB_GET_MY_INTERFACE, &iface_no); 81 if (ret == EOK && usb_iface) 82 *usb_iface = (int)iface_no; 83 return ret; 84 } 85 /*----------------------------------------------------------------------------*/ 86 /** Tell devman handle of device host controller. 87 * @param[in] exch IPC communication exchange 88 * @param[out] hc_handle devman handle of the HC used by the target device. 89 * @return Error code. 90 */ 91 int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle) 92 { 93 if (!exch) 94 return EINVAL; 95 devman_handle_t h; 96 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 97 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h); 98 if (ret == EOK && hc_handle) 99 *hc_handle = (devman_handle_t)h; 100 return ret; 101 } 102 103 104 static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 105 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 44 106 static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 45 //static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);46 107 47 108 /** Remote USB interface operations. */ 48 109 static remote_iface_func_ptr_t remote_usb_iface_ops [] = { 49 remote_usb_get_address,50 remote_usb_get_interface,51 remote_usb_get_hc_handle110 [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address, 111 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface, 112 [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle, 52 113 }; 53 114 … … 60 121 }; 61 122 62 63 void remote_usb_get_ address(ddf_fun_t *fun, void *iface,123 /*----------------------------------------------------------------------------*/ 124 void remote_usb_get_my_address(ddf_fun_t *fun, void *iface, 64 125 ipc_callid_t callid, ipc_call_t *call) 65 126 { 66 usb_iface_t *usb_iface = (usb_iface_t *) iface;127 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 67 128 68 if (usb_iface->get_ address == NULL) {129 if (usb_iface->get_my_address == NULL) { 69 130 async_answer_0(callid, ENOTSUP); 70 131 return; 71 132 } 72 133 73 devman_handle_t handle = DEV_IPC_GET_ARG1(*call);74 75 134 usb_address_t address; 76 int rc = usb_iface->get_address(fun, handle, &address);77 if (r c!= EOK) {78 async_answer_0(callid, r c);135 const int ret = usb_iface->get_my_address(fun, &address); 136 if (ret != EOK) { 137 async_answer_0(callid, ret); 79 138 } else { 80 139 async_answer_1(callid, EOK, address); 81 140 } 82 141 } 83 84 void remote_usb_get_ interface(ddf_fun_t *fun, void *iface,142 /*----------------------------------------------------------------------------*/ 143 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface, 85 144 ipc_callid_t callid, ipc_call_t *call) 86 145 { 87 usb_iface_t *usb_iface = (usb_iface_t *) iface;146 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 88 147 89 if (usb_iface->get_ interface == NULL) {148 if (usb_iface->get_my_interface == NULL) { 90 149 async_answer_0(callid, ENOTSUP); 91 150 return; 92 151 } 93 152 94 devman_handle_t handle = DEV_IPC_GET_ARG1(*call);95 96 153 int iface_no; 97 int rc = usb_iface->get_interface(fun, handle, &iface_no);98 if (r c!= EOK) {99 async_answer_0(callid, r c);154 const int ret = usb_iface->get_my_interface(fun, &iface_no); 155 if (ret != EOK) { 156 async_answer_0(callid, ret); 100 157 } else { 101 158 async_answer_1(callid, EOK, iface_no); 102 159 } 103 160 } 104 161 /*----------------------------------------------------------------------------*/ 105 162 void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface, 106 163 ipc_callid_t callid, ipc_call_t *call) 107 164 { 108 usb_iface_t *usb_iface = (usb_iface_t *) iface;165 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 109 166 110 167 if (usb_iface->get_hc_handle == NULL) { … … 114 171 115 172 devman_handle_t handle; 116 int rc= usb_iface->get_hc_handle(fun, &handle);117 if (r c!= EOK) {118 async_answer_0(callid, r c);173 const int ret = usb_iface->get_hc_handle(fun, &handle); 174 if (ret != EOK) { 175 async_answer_0(callid, ret); 119 176 } 120 177 121 178 async_answer_1(callid, EOK, (sysarg_t) handle); 122 179 } 123 124 125 126 180 /** 127 181 * @} -
uspace/lib/drv/generic/remote_usbhc.c
rbd5f3b7 r00aece0 1 1 /* 2 2 * Copyright (c) 2010-2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 41 42 42 43 #define USB_MAX_PAYLOAD_SIZE 1020 43 #define HACK_MAX_PACKET_SIZE 8 44 #define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4 45 46 static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 47 static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 48 static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 49 static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 44 45 /** IPC methods for communication with HC through DDF interface. 46 * 47 * Notes for async methods: 48 * 49 * Methods for sending data to device (OUT transactions) 50 * - e.g. IPC_M_USBHC_INTERRUPT_OUT - 51 * always use the same semantics: 52 * - first, IPC call with given method is made 53 * - argument #1 is target address 54 * - argument #2 is target endpoint 55 * - argument #3 is max packet size of the endpoint 56 * - this call is immediately followed by IPC data write (from caller) 57 * - the initial call (and the whole transaction) is answer after the 58 * transaction is scheduled by the HC and acknowledged by the device 59 * or immediately after error is detected 60 * - the answer carries only the error code 61 * 62 * Methods for retrieving data from device (IN transactions) 63 * - e.g. IPC_M_USBHC_INTERRUPT_IN - 64 * also use the same semantics: 65 * - first, IPC call with given method is made 66 * - argument #1 is target address 67 * - argument #2 is target endpoint 68 * - this call is immediately followed by IPC data read (async version) 69 * - the call is not answered until the device returns some data (or until 70 * error occurs) 71 * 72 * Some special methods (NO-DATA transactions) do not send any data. These 73 * might behave as both OUT or IN transactions because communication parts 74 * where actual buffers are exchanged are omitted. 75 ** 76 * For all these methods, wrap functions exists. Important rule: functions 77 * for IN transactions have (as parameters) buffers where retrieved data 78 * will be stored. These buffers must be already allocated and shall not be 79 * touch until the transaction is completed 80 * (e.g. not before calling usb_wait_for() with appropriate handle). 81 * OUT transactions buffers can be freed immediately after call is dispatched 82 * (i.e. after return from wrapping function). 83 * 84 */ 85 typedef enum { 86 /** Asks for address assignment by host controller. 87 * Answer: 88 * - ELIMIT - host controller run out of address 89 * - EOK - address assigned 90 * Answer arguments: 91 * - assigned address 92 * 93 * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS. 94 */ 95 IPC_M_USBHC_REQUEST_ADDRESS, 96 97 /** Bind USB address with devman handle. 98 * Parameters: 99 * - USB address 100 * - devman handle 101 * Answer: 102 * - EOK - address binded 103 * - ENOENT - address is not in use 104 */ 105 IPC_M_USBHC_BIND_ADDRESS, 106 107 /** Get handle binded with given USB address. 108 * Parameters 109 * - USB address 110 * Answer: 111 * - EOK - address binded, first parameter is the devman handle 112 * - ENOENT - address is not in use at the moment 113 */ 114 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, 115 116 /** Release address in use. 117 * Arguments: 118 * - address to be released 119 * Answer: 120 * - ENOENT - address not in use 121 * - EPERM - trying to release default USB address 122 */ 123 IPC_M_USBHC_RELEASE_ADDRESS, 124 125 /** Register endpoint attributes at host controller. 126 * This is used to reserve portion of USB bandwidth. 127 * When speed is invalid, speed of the device is used. 128 * Parameters: 129 * - USB address + endpoint number 130 * - packed as ADDR << 16 + EP 131 * - speed + transfer type + direction 132 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 133 * - maximum packet size + interval (in milliseconds) 134 * - packed as MPS << 16 + INT 135 * Answer: 136 * - EOK - reservation successful 137 * - ELIMIT - not enough bandwidth to satisfy the request 138 */ 139 IPC_M_USBHC_REGISTER_ENDPOINT, 140 141 /** Revert endpoint registration. 142 * Parameters: 143 * - USB address 144 * - endpoint number 145 * - data direction 146 * Answer: 147 * - EOK - endpoint unregistered 148 * - ENOENT - unknown endpoint 149 */ 150 IPC_M_USBHC_UNREGISTER_ENDPOINT, 151 152 /** Get data from device. 153 * See explanation at usb_iface_funcs_t (IN transaction). 154 */ 155 IPC_M_USBHC_READ, 156 157 /** Send data to device. 158 * See explanation at usb_iface_funcs_t (OUT transaction). 159 */ 160 IPC_M_USBHC_WRITE, 161 } usbhc_iface_funcs_t; 162 163 int usbhc_request_address(async_exch_t *exch, usb_address_t *address, 164 bool strict, usb_speed_t speed) 165 { 166 if (!exch || !address) 167 return EINVAL; 168 sysarg_t new_address; 169 const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 170 IPC_M_USBHC_REQUEST_ADDRESS, *address, strict, speed, &new_address); 171 if (ret == EOK) 172 *address = (usb_address_t)new_address; 173 return ret; 174 } 175 /*----------------------------------------------------------------------------*/ 176 int usbhc_bind_address(async_exch_t *exch, usb_address_t address, 177 devman_handle_t handle) 178 { 179 if (!exch) 180 return EINVAL; 181 return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 182 IPC_M_USBHC_BIND_ADDRESS, address, handle); 183 } 184 /*----------------------------------------------------------------------------*/ 185 int usbhc_get_handle(async_exch_t *exch, usb_address_t address, 186 devman_handle_t *handle) 187 { 188 if (!exch) 189 return EINVAL; 190 sysarg_t h; 191 const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 192 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, address, &h); 193 if (ret == EOK && handle) 194 *handle = (devman_handle_t)h; 195 return ret; 196 } 197 /*----------------------------------------------------------------------------*/ 198 int usbhc_release_address(async_exch_t *exch, usb_address_t address) 199 { 200 if (!exch) 201 return EINVAL; 202 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 203 IPC_M_USBHC_RELEASE_ADDRESS, address); 204 } 205 /*----------------------------------------------------------------------------*/ 206 int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address, 207 usb_endpoint_t endpoint, usb_transfer_type_t type, 208 usb_direction_t direction, size_t mps, unsigned interval) 209 { 210 if (!exch) 211 return EINVAL; 212 const usb_target_t target = 213 {{ .address = address, .endpoint = endpoint }}; 214 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff)) 215 216 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 217 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed, 218 _PACK2(type, direction), _PACK2(mps, interval)); 219 220 #undef _PACK2 221 } 222 /*----------------------------------------------------------------------------*/ 223 int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address, 224 usb_endpoint_t endpoint, usb_direction_t direction) 225 { 226 if (!exch) 227 return EINVAL; 228 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 229 IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction); 230 } 231 /*----------------------------------------------------------------------------*/ 232 int usbhc_read(async_exch_t *exch, usb_address_t address, 233 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size, 234 size_t *rec_size) 235 { 236 if (size == 0 && setup == 0) 237 return EOK; 238 239 if (!exch) 240 return EINVAL; 241 const usb_target_t target = 242 {{ .address = address, .endpoint = endpoint }}; 243 244 /* Make call identifying target USB device and type of transfer. */ 245 aid_t opening_request = async_send_4(exch, 246 DEV_IFACE_ID(USBHC_DEV_IFACE), 247 IPC_M_USBHC_READ, target.packed, 248 (setup & UINT32_MAX), (setup >> 32), NULL); 249 250 if (opening_request == 0) { 251 return ENOMEM; 252 } 253 254 /* Retrieve the data. */ 255 ipc_call_t data_request_call; 256 aid_t data_request = 257 async_data_read(exch, data, size, &data_request_call); 258 259 if (data_request == 0) { 260 // FIXME: How to let the other side know that we want to abort? 261 async_wait_for(opening_request, NULL); 262 return ENOMEM; 263 } 264 265 /* Wait for the answer. */ 266 sysarg_t data_request_rc; 267 sysarg_t opening_request_rc; 268 async_wait_for(data_request, &data_request_rc); 269 async_wait_for(opening_request, &opening_request_rc); 270 271 if (data_request_rc != EOK) { 272 /* Prefer the return code of the opening request. */ 273 if (opening_request_rc != EOK) { 274 return (int) opening_request_rc; 275 } else { 276 return (int) data_request_rc; 277 } 278 } 279 if (opening_request_rc != EOK) { 280 return (int) opening_request_rc; 281 } 282 283 *rec_size = IPC_GET_ARG2(data_request_call); 284 return EOK; 285 } 286 /*----------------------------------------------------------------------------*/ 287 int usbhc_write(async_exch_t *exch, usb_address_t address, 288 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size) 289 { 290 if (size == 0 && setup == 0) 291 return EOK; 292 293 if (!exch) 294 return EINVAL; 295 const usb_target_t target = 296 {{ .address = address, .endpoint = endpoint }}; 297 298 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 299 IPC_M_USBHC_WRITE, target.packed, size, 300 (setup & UINT32_MAX), (setup >> 32), NULL); 301 302 if (opening_request == 0) { 303 return ENOMEM; 304 } 305 306 /* Send the data if any. */ 307 if (size > 0) { 308 const int ret = async_data_write_start(exch, data, size); 309 if (ret != EOK) { 310 async_wait_for(opening_request, NULL); 311 return ret; 312 } 313 } 314 315 /* Wait for the answer. */ 316 sysarg_t opening_request_rc; 317 async_wait_for(opening_request, &opening_request_rc); 318 319 return (int) opening_request_rc; 320 } 321 /*----------------------------------------------------------------------------*/ 322 52 323 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 324 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 54 static void remote_usbhc_ find_by_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);325 static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 55 326 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 56 327 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 328 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 329 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 330 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 58 331 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 59 332 60 333 /** Remote USB host controller interface operations. */ 61 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 62 remote_usbhc_request_address, 63 remote_usbhc_bind_address, 64 remote_usbhc_find_by_address, 65 remote_usbhc_release_address, 66 67 remote_usbhc_interrupt_out, 68 remote_usbhc_interrupt_in, 69 70 remote_usbhc_bulk_out, 71 remote_usbhc_bulk_in, 72 73 remote_usbhc_control_write, 74 remote_usbhc_control_read, 75 76 remote_usbhc_register_endpoint, 77 remote_usbhc_unregister_endpoint 334 static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = { 335 [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address, 336 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 337 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 338 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle, 339 340 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 341 [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 342 343 [IPC_M_USBHC_READ] = remote_usbhc_read, 344 [IPC_M_USBHC_WRITE] = remote_usbhc_write, 78 345 }; 79 346 … … 90 357 ipc_callid_t data_caller; 91 358 void *buffer; 92 void *setup_packet;93 size_t size;94 359 } async_transaction_t; 95 360 … … 98 363 if (trans == NULL) { 99 364 return; 100 }101 102 if (trans->setup_packet != NULL) {103 free(trans->setup_packet);104 365 } 105 366 if (trans->buffer != NULL) { … … 120 381 trans->data_caller = 0; 121 382 trans->buffer = NULL; 122 trans->setup_packet = NULL;123 trans->size = 0;124 383 125 384 return trans; 126 385 } 127 386 /*----------------------------------------------------------------------------*/ 128 387 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 129 388 ipc_callid_t callid, ipc_call_t *call) 130 389 { 131 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;390 const usbhc_iface_t *usb_iface = iface; 132 391 133 392 if (!usb_iface->request_address) { … … 135 394 return; 136 395 } 137 138 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 139 140 usb_address_t address; 141 int rc = usb_iface->request_address(fun, speed, &address); 396 397 usb_address_t address = DEV_IPC_GET_ARG1(*call); 398 const bool strict = DEV_IPC_GET_ARG2(*call); 399 const usb_speed_t speed = DEV_IPC_GET_ARG3(*call); 400 401 const int rc = usb_iface->request_address(fun, &address, strict, speed); 142 402 if (rc != EOK) { 143 403 async_answer_0(callid, rc); … … 146 406 } 147 407 } 148 408 /*----------------------------------------------------------------------------*/ 149 409 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface, 150 410 ipc_callid_t callid, ipc_call_t *call) 151 411 { 152 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;412 const usbhc_iface_t *usb_iface = iface; 153 413 154 414 if (!usb_iface->bind_address) { … … 157 417 } 158 418 159 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 160 devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 161 162 int rc = usb_iface->bind_address(fun, address, handle); 163 164 async_answer_0(callid, rc); 165 } 166 167 void remote_usbhc_find_by_address(ddf_fun_t *fun, void *iface, 419 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 420 const devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 421 422 const int ret = usb_iface->bind_address(fun, address, handle); 423 async_answer_0(callid, ret); 424 } 425 /*----------------------------------------------------------------------------*/ 426 void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface, 168 427 ipc_callid_t callid, ipc_call_t *call) 169 428 { 170 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;171 172 if (!usb_iface-> find_by_address) {173 async_answer_0(callid, ENOTSUP); 174 return; 175 } 176 177 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);429 const usbhc_iface_t *usb_iface = iface; 430 431 if (!usb_iface->get_handle) { 432 async_answer_0(callid, ENOTSUP); 433 return; 434 } 435 436 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 178 437 devman_handle_t handle; 179 int rc = usb_iface->find_by_address(fun, address, &handle);180 181 if (r c== EOK) {182 async_answer_1(callid, EOK, handle);438 const int ret = usb_iface->get_handle(fun, address, &handle); 439 440 if (ret == EOK) { 441 async_answer_1(callid, ret, handle); 183 442 } else { 184 async_answer_0(callid, r c);185 } 186 } 187 443 async_answer_0(callid, ret); 444 } 445 } 446 /*----------------------------------------------------------------------------*/ 188 447 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface, 189 448 ipc_callid_t callid, ipc_call_t *call) 190 449 { 191 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;450 const usbhc_iface_t *usb_iface = iface; 192 451 193 452 if (!usb_iface->release_address) { … … 196 455 } 197 456 198 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 199 200 int rc = usb_iface->release_address(fun, address); 201 202 async_answer_0(callid, rc); 203 } 204 205 457 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 458 459 const int ret = usb_iface->release_address(fun, address); 460 async_answer_0(callid, ret); 461 } 462 /*----------------------------------------------------------------------------*/ 206 463 static void callback_out(ddf_fun_t *fun, 207 464 int outcome, void *arg) 208 465 { 209 async_transaction_t *trans = (async_transaction_t *)arg;466 async_transaction_t *trans = arg; 210 467 211 468 async_answer_0(trans->caller, outcome); … … 213 470 async_transaction_destroy(trans); 214 471 } 215 472 /*----------------------------------------------------------------------------*/ 216 473 static void callback_in(ddf_fun_t *fun, 217 474 int outcome, size_t actual_size, void *arg) … … 228 485 } 229 486 230 trans->size = actual_size;231 232 487 if (trans->data_caller) { 233 488 async_data_read_finalize(trans->data_caller, … … 239 494 async_transaction_destroy(trans); 240 495 } 241 242 /** Process an outgoing transfer (both OUT and SETUP). 243 * 244 * @param device Target device. 245 * @param callid Initiating caller. 246 * @param call Initiating call. 247 * @param transfer_func Transfer function (might be NULL). 248 */ 249 static void remote_usbhc_out_transfer(ddf_fun_t *fun, 250 ipc_callid_t callid, ipc_call_t *call, 251 usbhc_iface_transfer_out_t transfer_func) 252 { 253 if (!transfer_func) { 254 async_answer_0(callid, ENOTSUP); 255 return; 256 } 257 258 usb_target_t target = { 259 .address = DEV_IPC_GET_ARG1(*call), 260 .endpoint = DEV_IPC_GET_ARG2(*call) 261 }; 262 263 size_t len = 0; 264 void *buffer = NULL; 265 266 int rc = async_data_write_accept(&buffer, false, 267 1, USB_MAX_PAYLOAD_SIZE, 268 0, &len); 269 270 if (rc != EOK) { 271 async_answer_0(callid, rc); 272 return; 273 } 496 /*----------------------------------------------------------------------------*/ 497 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 498 ipc_callid_t callid, ipc_call_t *call) 499 { 500 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 501 502 if (!usb_iface->register_endpoint) { 503 async_answer_0(callid, ENOTSUP); 504 return; 505 } 506 507 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \ 508 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16) 509 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \ 510 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff) 511 512 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 513 514 _INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2); 515 _INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2); 516 517 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3); 518 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3); 519 520 #undef _INIT_FROM_HIGH_DATA2 521 #undef _INIT_FROM_LOW_DATA2 522 523 int rc = usb_iface->register_endpoint(fun, target.address, 524 target.endpoint, transfer_type, direction, max_packet_size, interval); 525 526 async_answer_0(callid, rc); 527 } 528 529 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, 530 ipc_callid_t callid, ipc_call_t *call) 531 { 532 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 533 534 if (!usb_iface->unregister_endpoint) { 535 async_answer_0(callid, ENOTSUP); 536 return; 537 } 538 539 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 540 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call); 541 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call); 542 543 int rc = usb_iface->unregister_endpoint(fun, 544 address, endpoint, direction); 545 546 async_answer_0(callid, rc); 547 } 548 549 void remote_usbhc_read( 550 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 551 { 552 assert(fun); 553 assert(iface); 554 assert(call); 555 556 const usbhc_iface_t *hc_iface = iface; 557 558 if (!hc_iface->read) { 559 async_answer_0(callid, ENOTSUP); 560 return; 561 } 562 563 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 564 const uint64_t setup = 565 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 566 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 274 567 275 568 async_transaction_t *trans = async_transaction_create(callid); 276 569 if (trans == NULL) { 277 if (buffer != NULL) { 278 free(buffer); 570 async_answer_0(callid, ENOMEM); 571 return; 572 } 573 574 size_t size = 0; 575 if (!async_data_read_receive(&trans->data_caller, &size)) { 576 async_answer_0(callid, EPARTY); 577 return; 578 } 579 580 trans->buffer = malloc(size); 581 if (trans->buffer == NULL) { 582 async_answer_0(trans->data_caller, ENOMEM); 583 async_answer_0(callid, ENOMEM); 584 async_transaction_destroy(trans); 585 } 586 587 const int rc = hc_iface->read( 588 fun, target, setup, trans->buffer, size, callback_in, trans); 589 590 if (rc != EOK) { 591 async_answer_0(trans->data_caller, rc); 592 async_answer_0(callid, rc); 593 async_transaction_destroy(trans); 594 } 595 } 596 /*----------------------------------------------------------------------------*/ 597 void remote_usbhc_write( 598 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 599 { 600 assert(fun); 601 assert(iface); 602 assert(call); 603 604 const usbhc_iface_t *hc_iface = iface; 605 606 if (!hc_iface->write) { 607 async_answer_0(callid, ENOTSUP); 608 return; 609 } 610 611 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 612 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 613 const uint64_t setup = 614 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 615 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 616 617 async_transaction_t *trans = async_transaction_create(callid); 618 if (trans == NULL) { 619 async_answer_0(callid, ENOMEM); 620 return; 621 } 622 623 size_t size = 0; 624 if (data_buffer_len > 0) { 625 const int rc = async_data_write_accept(&trans->buffer, false, 626 1, USB_MAX_PAYLOAD_SIZE, 627 0, &size); 628 629 if (rc != EOK) { 630 async_answer_0(callid, rc); 631 async_transaction_destroy(trans); 632 return; 279 633 } 280 async_answer_0(callid, ENOMEM); 281 return; 282 } 283 284 trans->buffer = buffer; 285 trans->size = len; 286 287 rc = transfer_func(fun, target, 288 buffer, len, 289 callback_out, trans); 634 } 635 636 const int rc = hc_iface->write( 637 fun, target, setup, trans->buffer, size, callback_out, trans); 290 638 291 639 if (rc != EOK) { … … 294 642 } 295 643 } 296 297 /** Process an incoming transfer.298 *299 * @param device Target device.300 * @param callid Initiating caller.301 * @param call Initiating call.302 * @param transfer_func Transfer function (might be NULL).303 */304 static void remote_usbhc_in_transfer(ddf_fun_t *fun,305 ipc_callid_t callid, ipc_call_t *call,306 usbhc_iface_transfer_in_t transfer_func)307 {308 if (!transfer_func) {309 async_answer_0(callid, ENOTSUP);310 return;311 }312 313 usb_target_t target = {314 .address = DEV_IPC_GET_ARG1(*call),315 .endpoint = DEV_IPC_GET_ARG2(*call)316 };317 318 size_t len;319 ipc_callid_t data_callid;320 if (!async_data_read_receive(&data_callid, &len)) {321 async_answer_0(callid, EPARTY);322 return;323 }324 325 async_transaction_t *trans = async_transaction_create(callid);326 if (trans == NULL) {327 async_answer_0(data_callid, ENOMEM);328 async_answer_0(callid, ENOMEM);329 return;330 }331 trans->data_caller = data_callid;332 trans->buffer = malloc(len);333 trans->size = len;334 335 int rc = transfer_func(fun, target,336 trans->buffer, len,337 callback_in, trans);338 339 if (rc != EOK) {340 async_answer_0(data_callid, rc);341 async_answer_0(callid, rc);342 async_transaction_destroy(trans);343 }344 }345 346 void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,347 ipc_callid_t callid, ipc_call_t *call)348 {349 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;350 assert(usb_iface != NULL);351 352 return remote_usbhc_out_transfer(fun, callid, call,353 usb_iface->interrupt_out);354 }355 356 void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,357 ipc_callid_t callid, ipc_call_t *call)358 {359 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;360 assert(usb_iface != NULL);361 362 return remote_usbhc_in_transfer(fun, callid, call,363 usb_iface->interrupt_in);364 }365 366 void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,367 ipc_callid_t callid, ipc_call_t *call)368 {369 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;370 assert(usb_iface != NULL);371 372 return remote_usbhc_out_transfer(fun, callid, call,373 usb_iface->bulk_out);374 }375 376 void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,377 ipc_callid_t callid, ipc_call_t *call)378 {379 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;380 assert(usb_iface != NULL);381 382 return remote_usbhc_in_transfer(fun, callid, call,383 usb_iface->bulk_in);384 }385 386 void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,387 ipc_callid_t callid, ipc_call_t *call)388 {389 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;390 assert(usb_iface != NULL);391 392 if (!usb_iface->control_write) {393 async_answer_0(callid, ENOTSUP);394 return;395 }396 397 usb_target_t target = {398 .address = DEV_IPC_GET_ARG1(*call),399 .endpoint = DEV_IPC_GET_ARG2(*call)400 };401 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);402 403 int rc;404 405 void *setup_packet = NULL;406 void *data_buffer = NULL;407 size_t setup_packet_len = 0;408 409 rc = async_data_write_accept(&setup_packet, false,410 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);411 if (rc != EOK) {412 async_answer_0(callid, rc);413 return;414 }415 416 if (data_buffer_len > 0) {417 rc = async_data_write_accept(&data_buffer, false,418 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);419 if (rc != EOK) {420 async_answer_0(callid, rc);421 free(setup_packet);422 return;423 }424 }425 426 async_transaction_t *trans = async_transaction_create(callid);427 if (trans == NULL) {428 async_answer_0(callid, ENOMEM);429 free(setup_packet);430 free(data_buffer);431 return;432 }433 trans->setup_packet = setup_packet;434 trans->buffer = data_buffer;435 trans->size = data_buffer_len;436 437 rc = usb_iface->control_write(fun, target,438 setup_packet, setup_packet_len,439 data_buffer, data_buffer_len,440 callback_out, trans);441 442 if (rc != EOK) {443 async_answer_0(callid, rc);444 async_transaction_destroy(trans);445 }446 }447 448 449 void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,450 ipc_callid_t callid, ipc_call_t *call)451 {452 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;453 assert(usb_iface != NULL);454 455 if (!usb_iface->control_read) {456 async_answer_0(callid, ENOTSUP);457 return;458 }459 460 usb_target_t target = {461 .address = DEV_IPC_GET_ARG1(*call),462 .endpoint = DEV_IPC_GET_ARG2(*call)463 };464 465 int rc;466 467 void *setup_packet = NULL;468 size_t setup_packet_len = 0;469 size_t data_len = 0;470 471 rc = async_data_write_accept(&setup_packet, false,472 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);473 if (rc != EOK) {474 async_answer_0(callid, rc);475 return;476 }477 478 ipc_callid_t data_callid;479 if (!async_data_read_receive(&data_callid, &data_len)) {480 async_answer_0(callid, EPARTY);481 free(setup_packet);482 return;483 }484 485 async_transaction_t *trans = async_transaction_create(callid);486 if (trans == NULL) {487 async_answer_0(data_callid, ENOMEM);488 async_answer_0(callid, ENOMEM);489 free(setup_packet);490 return;491 }492 trans->data_caller = data_callid;493 trans->setup_packet = setup_packet;494 trans->size = data_len;495 trans->buffer = malloc(data_len);496 if (trans->buffer == NULL) {497 async_answer_0(data_callid, ENOMEM);498 async_answer_0(callid, ENOMEM);499 async_transaction_destroy(trans);500 return;501 }502 503 rc = usb_iface->control_read(fun, target,504 setup_packet, setup_packet_len,505 trans->buffer, trans->size,506 callback_in, trans);507 508 if (rc != EOK) {509 async_answer_0(data_callid, rc);510 async_answer_0(callid, rc);511 async_transaction_destroy(trans);512 }513 }514 515 516 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,517 ipc_callid_t callid, ipc_call_t *call)518 {519 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;520 521 if (!usb_iface->register_endpoint) {522 async_answer_0(callid, ENOTSUP);523 return;524 }525 526 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \527 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)528 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \529 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16)530 #define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \531 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)532 #define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \533 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8)534 #define _INIT_FROM_LOW_DATA3(type, var, arg_no) \535 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)536 537 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);538 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);539 540 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);541 _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2);542 _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2);543 544 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);545 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3);546 547 #undef _INIT_FROM_HIGH_DATA2548 #undef _INIT_FROM_LOW_DATA2549 #undef _INIT_FROM_HIGH_DATA3550 #undef _INIT_FROM_MIDDLE_DATA3551 #undef _INIT_FROM_LOW_DATA3552 553 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,554 transfer_type, direction, max_packet_size, interval);555 556 async_answer_0(callid, rc);557 }558 559 560 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,561 ipc_callid_t callid, ipc_call_t *call)562 {563 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;564 565 if (!usb_iface->unregister_endpoint) {566 async_answer_0(callid, ENOTSUP);567 return;568 }569 570 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);571 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);572 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);573 574 int rc = usb_iface->unregister_endpoint(fun,575 address, endpoint, direction);576 577 async_answer_0(callid, rc);578 }579 580 581 644 /** 582 645 * @}
Note:
See TracChangeset
for help on using the changeset viewer.
