Changes in / [45bf63c:1737bfb] in mainline
- Location:
- uspace
- Files:
-
- 36 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/endpoint_list.c
r45bf63c r1737bfb 73 73 * Does not check whether this replaces an existing list. 74 74 */ 75 void endpoint_list_set_next( 76 const endpoint_list_t *instance, const endpoint_list_t *next) 75 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next) 77 76 { 78 77 assert(instance); -
uspace/drv/bus/usb/ohci/endpoint_list.h
r45bf63c r1737bfb 68 68 69 69 int endpoint_list_init(endpoint_list_t *instance, const char *name); 70 void endpoint_list_set_next( 71 const endpoint_list_t *instance, const endpoint_list_t *next); 70 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next); 72 71 void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep); 73 72 void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep); -
uspace/drv/bus/usb/ohci/hc.c
r45bf63c r1737bfb 142 142 if (ret != EOK) { \ 143 143 usb_log_error(message); \ 144 usb_endpoint_manager_remove_ep( \ 145 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, \ 146 NULL, NULL);\ 144 usb_endpoint_manager_unregister_ep( \ 145 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\ 147 146 usb_device_manager_release( \ 148 147 &instance->generic.dev_manager, hub_address); \ … … 151 150 int ret = usb_endpoint_manager_add_ep( 152 151 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, 153 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0 , NULL, NULL);152 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0); 154 153 CHECK_RET_UNREG_RETURN(ret, 155 154 "Failed to register root hub control endpoint: %s.\n", … … 193 192 list_initialize(&instance->pending_batches); 194 193 195 hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,194 ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 196 195 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n", 197 str_error(ret)); 197 198 instance->generic.private_data = instance; 198 199 instance->generic.schedule = hc_schedule; 199 200 instance->generic.ep_add_hook = ohci_endpoint_init; 200 instance->generic.ep_remove_hook = ohci_endpoint_fini;201 201 202 202 ret = hc_init_memory(instance); … … 221 221 } 222 222 /*----------------------------------------------------------------------------*/ 223 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep) 224 { 225 assert(instance); 226 assert(ep); 227 223 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep) 224 { 228 225 endpoint_list_t *list = &instance->lists[ep->transfer_type]; 229 226 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep); 230 assert(list);231 assert(ohci_ep);232 233 227 /* Enqueue ep */ 234 228 switch (ep->transfer_type) { … … 253 247 } 254 248 /*----------------------------------------------------------------------------*/ 255 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep) 256 { 257 assert(instance); 258 assert(ep); 259 249 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep) 250 { 260 251 /* Dequeue ep */ 261 252 endpoint_list_t *list = &instance->lists[ep->transfer_type]; 262 253 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep); 263 264 assert(list);265 assert(ohci_ep);266 254 switch (ep->transfer_type) { 267 255 case USB_TRANSFER_CONTROL: -
uspace/drv/bus/usb/ohci/hc.h
r45bf63c r1737bfb 86 86 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 87 87 88 void hc_enqueue_endpoint(hc_t *instance, constendpoint_t *ep);89 void hc_dequeue_endpoint(hc_t *instance, constendpoint_t *ep);88 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep); 89 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep); 90 90 91 91 void hc_interrupt(hc_t *instance, uint32_t status); -
uspace/drv/bus/usb/ohci/ohci.c
r45bf63c r1737bfb 89 89 &dev_to_ohci(fun->dev)->hc.generic.dev_manager; 90 90 91 const usb_address_t addr = 92 usb_device_manager_find_address(manager, handle); 91 const usb_address_t addr = usb_device_manager_find(manager, handle); 93 92 if (addr < 0) { 94 93 return addr; -
uspace/drv/bus/usb/ohci/ohci_batch.c
r45bf63c r1737bfb 59 59 free(ohci_batch->tds); 60 60 } 61 usb_transfer_batch_d estroy(ohci_batch->usb_batch);61 usb_transfer_batch_dispose(ohci_batch->usb_batch); 62 62 free32(ohci_batch->device_buffer); 63 63 free(ohci_batch); -
uspace/drv/bus/usb/ohci/ohci_endpoint.c
r45bf63c r1737bfb 62 62 } 63 63 /*----------------------------------------------------------------------------*/ 64 /** Disposes hcd endpoint structure 65 * 66 * @param[in] hcd_ep endpoint structure 67 */ 68 static void ohci_endpoint_fini(endpoint_t *ep) 69 { 70 ohci_endpoint_t *instance = ep->hc_data.data; 71 hc_dequeue_endpoint(instance->hcd->private_data, ep); 72 if (instance) { 73 free32(instance->ed); 74 free32(instance->td); 75 free(instance); 76 } 77 } 78 /*----------------------------------------------------------------------------*/ 64 79 /** Creates new hcd endpoint representation. 65 80 * 66 81 * @param[in] ep USBD endpoint structure 67 * @return Error code.82 * @return pointer to a new hcd endpoint structure, NULL on failure. 68 83 */ 69 84 int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep) … … 89 104 ed_init(ohci_ep->ed, ep, ohci_ep->td); 90 105 endpoint_set_hc_data( 91 ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set); 106 ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set); 107 ohci_ep->hcd = hcd; 92 108 hc_enqueue_endpoint(hcd->private_data, ep); 93 109 return EOK; 94 }95 /*----------------------------------------------------------------------------*/96 /** Disposes hcd endpoint structure97 *98 * @param[in] hcd driver using this instance.99 * @param[in] ep endpoint structure.100 */101 void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep)102 {103 assert(hcd);104 assert(ep);105 ohci_endpoint_t *instance = ohci_endpoint_get(ep);106 hc_dequeue_endpoint(hcd->private_data, ep);107 if (instance) {108 free32(instance->ed);109 free32(instance->td);110 free(instance);111 }112 endpoint_clear_hc_data(ep);113 110 } 114 111 /** -
uspace/drv/bus/usb/ohci/ohci_endpoint.h
r45bf63c r1737bfb 51 51 /** Linked list used by driver software */ 52 52 link_t link; 53 /** Device using this ep */ 54 hcd_t *hcd; 53 55 } ohci_endpoint_t; 54 56 55 57 int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep); 56 void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep);57 58 58 59 /** Get and convert assigned ohci_endpoint_t structure … … 60 61 * @return Pointer to assigned hcd endpoint structure 61 62 */ 62 static inline ohci_endpoint_t * ohci_endpoint_get( constendpoint_t *ep)63 static inline ohci_endpoint_t * ohci_endpoint_get(endpoint_t *ep) 63 64 { 64 65 assert(ep); -
uspace/drv/bus/usb/ohci/ohci_regs.h
r45bf63c r1737bfb 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbohci 28 /** @addtogroup drvusbohcihc 29 29 * @{ 30 30 */ -
uspace/drv/bus/usb/ohci/root_hub.c
r45bf63c r1737bfb 235 235 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 236 236 } 237 usb_transfer_batch_d estroy(request);237 usb_transfer_batch_dispose(request); 238 238 } 239 239 /*----------------------------------------------------------------------------*/ … … 254 254 interrupt_request(instance->unfinished_interrupt_transfer, 255 255 mask, instance->interrupt_mask_size); 256 usb_transfer_batch_d estroy(256 usb_transfer_batch_dispose( 257 257 instance->unfinished_interrupt_transfer); 258 258 instance->unfinished_interrupt_transfer = NULL; -
uspace/drv/bus/usb/uhci/hc.c
r45bf63c r1737bfb 192 192 "Device registers at %p (%zuB) accessible.\n", io, reg_size); 193 193 194 ret = hc _init_mem_structures(instance);195 CHECK_RET_RETURN(ret,196 "Failed to initialize UHCI memory structures: %s.\n",194 ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 195 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n", 197 197 str_error(ret)); 198 199 #undef CHECK_RET_RETURN200 201 hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,202 bandwidth_count_usb11);203 198 204 199 instance->generic.private_data = instance; 205 200 instance->generic.schedule = hc_schedule; 206 201 instance->generic.ep_add_hook = NULL; 202 203 #undef CHECK_RET_DEST_FUN_RETURN 204 205 ret = hc_init_mem_structures(instance); 206 if (ret != EOK) { 207 usb_log_error( 208 "Failed to initialize UHCI memory structures: %s.\n", 209 str_error(ret)); 210 hcd_destroy(&instance->generic); 211 return ret; 212 } 207 213 208 214 hc_init_hw(instance); -
uspace/drv/bus/usb/uhci/uhci.c
r45bf63c r1737bfb 101 101 usb_device_manager_t *manager = 102 102 &dev_to_uhci(fun->dev)->hc.generic.dev_manager; 103 const usb_address_t addr = 104 usb_device_manager_find_address(manager, handle); 103 const usb_address_t addr = usb_device_manager_find(manager, handle); 105 104 106 105 if (addr < 0) { -
uspace/drv/bus/usb/uhci/uhci_batch.c
r45bf63c r1737bfb 48 48 { 49 49 if (uhci_batch) { 50 usb_transfer_batch_d estroy(uhci_batch->usb_batch);50 usb_transfer_batch_dispose(uhci_batch->usb_batch); 51 51 free32(uhci_batch->device_buffer); 52 52 free(uhci_batch); -
uspace/drv/bus/usb/usbflbk/main.c
r45bf63c r1737bfb 74 74 } 75 75 76 /** Callback when new device is about to be removed.77 *78 * @param dev Representation of a generic DDF device.79 * @return Error code.80 */81 static int usbfallback_device_remove(usb_device_t *dev)82 {83 return EOK;84 }85 86 76 /** Callback when new device is removed and recognized as gone by DDF. 87 77 * … … 103 93 return EOK; 104 94 } 105 106 95 /** USB fallback driver ops. */ 107 static constusb_driver_ops_t usbfallback_driver_ops = {96 static usb_driver_ops_t usbfallback_driver_ops = { 108 97 .device_add = usbfallback_device_add, 109 .device_rem = usbfallback_device_remove,110 98 .device_gone = usbfallback_device_gone, 111 99 }; 112 100 113 101 /** USB fallback driver. */ 114 static constusb_driver_t usbfallback_driver = {102 static usb_driver_t usbfallback_driver = { 115 103 .name = NAME, 116 104 .ops = &usbfallback_driver_ops, -
uspace/drv/bus/usb/usbhid/main.c
r45bf63c r1737bfb 46 46 #include "usbhid.h" 47 47 48 /*----------------------------------------------------------------------------*/ 49 48 50 #define NAME "usbhid" 49 51 … … 65 67 * 66 68 * @param dev Device to add. 67 * @return Error code. 69 * 70 * @retval EOK if successful. 71 * @retval ENOMEM if there 72 * @return Other error code inherited from one of functions usb_kbd_init(), 73 * ddf_fun_bind() and ddf_fun_add_to_class(). 68 74 */ 69 75 static int usb_hid_try_add_device(usb_device_t *dev) … … 132 138 return EOK; 133 139 } 140 134 141 /*----------------------------------------------------------------------------*/ 135 142 /** … … 139 146 * 140 147 * @param dev Structure representing the new device. 141 * @return Error code. 148 * 149 * @retval EOK if successful. 150 * @retval EREFUSED if the device is not supported. 142 151 */ 143 152 static int usb_hid_device_add(usb_device_t *dev) … … 170 179 return EOK; 171 180 } 172 /*----------------------------------------------------------------------------*/ 173 /** 174 * Callback for a device about to be removed from the driver. 181 182 /*----------------------------------------------------------------------------*/ 183 184 /** 185 * Callback for removing a device from the driver. 175 186 * 176 187 * @param dev Structure representing the device. 177 * @return Error code. 178 */ 179 static int usb_hid_device_rem(usb_device_t *dev) 180 { 181 return EOK; 182 } 183 /*----------------------------------------------------------------------------*/ 184 /** 185 * Callback for removing a device from the driver. 186 * 187 * @param dev Structure representing the device. 188 * @return Error code. 188 * 189 * @retval EOK if successful. 190 * @retval EREFUSED if the device is not supported. 189 191 */ 190 192 static int usb_hid_device_gone(usb_device_t *dev) … … 196 198 if (!tries--) { 197 199 usb_log_error("Can't remove hub, still running.\n"); 198 return E BUSY;200 return EINPROGRESS; 199 201 } 200 202 } … … 205 207 return EOK; 206 208 } 207 /*----------------------------------------------------------------------------*/ 209 208 210 /** USB generic driver callbacks */ 209 static constusb_driver_ops_t usb_hid_driver_ops = {211 static usb_driver_ops_t usb_hid_driver_ops = { 210 212 .device_add = usb_hid_device_add, 211 .device_rem = usb_hid_device_rem,212 213 .device_gone = usb_hid_device_gone, 213 214 }; 214 /*----------------------------------------------------------------------------*/ 215 216 215 217 /** The driver itself. */ 216 static constusb_driver_t usb_hid_driver = {218 static usb_driver_t usb_hid_driver = { 217 219 .name = NAME, 218 220 .ops = &usb_hid_driver_ops, 219 221 .endpoints = usb_hid_endpoints 220 222 }; 221 /*----------------------------------------------------------------------------*/ 223 224 /*----------------------------------------------------------------------------*/ 225 222 226 int main(int argc, char *argv[]) 223 227 { … … 228 232 return usb_driver_main(&usb_hid_driver); 229 233 } 234 230 235 /** 231 236 * @} -
uspace/drv/bus/usb/usbhub/main.c
r45bf63c r1737bfb 47 47 * For more information see section 11.15.1 of USB 1.1 specification. 48 48 */ 49 static const usb_endpoint_description_t hub_status_change_endpoint_description = 50 { 49 static usb_endpoint_description_t hub_status_change_endpoint_description = { 51 50 .transfer_type = USB_TRANSFER_INTERRUPT, 52 51 .direction = USB_DIRECTION_IN, … … 57 56 }; 58 57 59 /** USB hub driver operations. */ 60 static const usb_driver_ops_t usb_hub_driver_ops = { 58 /** 59 * USB hub driver operations 60 * 61 * The most important one is device_add, which is set to usb_hub_device_add. 62 */ 63 static usb_driver_ops_t usb_hub_driver_ops = { 61 64 .device_add = usb_hub_device_add, 62 // .device_rem = usb_hub_device_remove,63 65 .device_gone = usb_hub_device_gone, 64 66 }; … … 70 72 }; 71 73 /** Static usb hub driver information. */ 72 static constusb_driver_t usb_hub_driver = {74 static usb_driver_t usb_hub_driver = { 73 75 .name = NAME, 74 76 .ops = &usb_hub_driver_ops, 75 77 .endpoints = usb_hub_endpoints 76 78 }; 79 77 80 78 81 int main(int argc, char *argv[]) -
uspace/drv/bus/usb/usbhub/port.h
r45bf63c r1737bfb 44 44 /** Information about single port on a hub. */ 45 45 typedef struct { 46 /* Port number as reporteed in descriptors. */47 46 size_t port_number; 48 /** Device communication pipe. */49 47 usb_pipe_t *control_pipe; 50 48 /** Mutex needed not only by CV for checking port reset. */ -
uspace/drv/bus/usb/usbhub/usbhub.c
r45bf63c r1737bfb 68 68 69 69 static int usb_set_first_configuration(usb_device_t *usb_device); 70 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev); 70 71 static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev); 71 72 static void usb_hub_over_current(const usb_hub_dev_t *hub_dev, … … 74 75 static void usb_hub_polling_terminated_callback(usb_device_t *device, 75 76 bool was_error, void *data); 76 77 /** 78 * Initialize hub device driver structure. 77 /** 78 * Initialize hub device driver fibril 79 79 * 80 80 * Creates hub representation and fibril that periodically checks hub's status. 81 81 * Hub representation is passed to the fibril. 82 * @param usb_dev generic usb device information83 * @return error code84 */85 int usb_hub_device_add(usb_device_t *usb_dev)86 {87 assert(usb_dev);88 /* Create driver soft-state structure */89 usb_hub_dev_t *hub_dev =90 usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));91 if (hub_dev == NULL) {92 usb_log_error("Failed to create hub driver structure.\n");93 return ENOMEM;94 }95 hub_dev->usb_device = usb_dev;96 hub_dev->pending_ops_count = 0;97 hub_dev->running = false;98 fibril_mutex_initialize(&hub_dev->pending_ops_mutex);99 fibril_condvar_initialize(&hub_dev->pending_ops_cv);100 101 /* Create hc connection */102 usb_log_debug("Initializing USB wire abstraction.\n");103 int opResult = usb_hc_connection_initialize_from_device(104 &hub_dev->connection, hub_dev->usb_device->ddf_dev);105 if (opResult != EOK) {106 usb_log_error("Could not initialize connection to device: %s\n",107 str_error(opResult));108 return opResult;109 }110 111 /* Set hub's first configuration. (There should be only one) */112 opResult = usb_set_first_configuration(usb_dev);113 if (opResult != EOK) {114 usb_log_error("Could not set hub configuration: %s\n",115 str_error(opResult));116 return opResult;117 }118 119 /* Get port count and create attached_devices. */120 opResult = usb_hub_process_hub_specific_info(hub_dev);121 if (opResult != EOK) {122 usb_log_error("Could process hub specific info, %s\n",123 str_error(opResult));124 return opResult;125 }126 127 /* Create hub control function. */128 usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");129 hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,130 fun_exposed, HUB_FNC_NAME);131 if (hub_dev->hub_fun == NULL) {132 usb_log_error("Failed to create hub function.\n");133 return ENOMEM;134 }135 136 /* Bind hub control function. */137 opResult = ddf_fun_bind(hub_dev->hub_fun);138 if (opResult != EOK) {139 usb_log_error("Failed to bind hub function: %s.\n",140 str_error(opResult));141 ddf_fun_destroy(hub_dev->hub_fun);142 return opResult;143 }144 145 /* Start hub operation. */146 opResult = usb_device_auto_poll(hub_dev->usb_device, 0,147 hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),148 usb_hub_polling_terminated_callback, hub_dev);149 if (opResult != EOK) {150 /* Function is already bound */151 ddf_fun_unbind(hub_dev->hub_fun);152 ddf_fun_destroy(hub_dev->hub_fun);153 usb_log_error("Failed to create polling fibril: %s.\n",154 str_error(opResult));155 return opResult;156 }157 hub_dev->running = true;158 usb_log_info("Controlling hub '%s' (%zu ports).\n",159 hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);160 161 return EOK;162 }163 /*----------------------------------------------------------------------------*/164 /**165 * Turn off power to all ports.166 *167 * @param usb_dev generic usb device information168 * @return error code169 */170 int usb_hub_device_remove(usb_device_t *usb_dev)171 {172 assert(usb_dev);173 usb_hub_dev_t *hub_dev = usb_dev->driver_data;174 assert(hub_dev);175 //TODO: Cascade the call here.176 //TODO: Enable after cascading is implemented.177 return ENOTSUP;178 if (!hub_dev->power_switched) {179 /* That is all we can do. */180 return EOK;181 }182 int ret = EOK;183 usb_log_info("Hub is about to be removed, powering down all ports.\n");184 for (size_t port = 0; port < hub_dev->port_count; ++port) {185 usb_log_debug("Powering down port %zu.\n", port);186 int pret = usb_hub_port_clear_feature(187 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);188 if (pret != EOK) {189 usb_log_error("Cannot power down port %zu: %s.\n",190 hub_dev->ports[port].port_number, str_error(pret));191 ret = pret;192 } else {193 if (!hub_dev->per_port_power) {194 usb_log_debug("Ganged power switching mode, "195 "one port is enough.\n");196 break;197 }198 }199 }200 return ret;201 }202 /*----------------------------------------------------------------------------*/203 /**204 * Remove all attached devices205 82 * @param usb_dev generic usb device information 206 83 * @return error code … … 244 121 } 245 122 /*----------------------------------------------------------------------------*/ 123 /** 124 * Initialize hub device driver fibril 125 * 126 * Creates hub representation and fibril that periodically checks hub's status. 127 * Hub representation is passed to the fibril. 128 * @param usb_dev generic usb device information 129 * @return error code 130 */ 131 int usb_hub_device_add(usb_device_t *usb_dev) 132 { 133 assert(usb_dev); 134 /* Create driver soft-state structure */ 135 usb_hub_dev_t *hub_dev = usb_hub_dev_create(usb_dev); 136 if (hub_dev == NULL) { 137 usb_log_error("Failed to create hun driver structure.\n"); 138 return ENOMEM; 139 } 140 141 /* Create hc connection */ 142 usb_log_debug("Initializing USB wire abstraction.\n"); 143 int opResult = usb_hc_connection_initialize_from_device( 144 &hub_dev->connection, hub_dev->usb_device->ddf_dev); 145 if (opResult != EOK) { 146 usb_log_error("Could not initialize connection to device: %s\n", 147 str_error(opResult)); 148 free(hub_dev); 149 return opResult; 150 } 151 152 /* Set hub's first configuration. (There should be only one) */ 153 opResult = usb_set_first_configuration(usb_dev); 154 if (opResult != EOK) { 155 usb_log_error("Could not set hub configuration: %s\n", 156 str_error(opResult)); 157 free(hub_dev); 158 return opResult; 159 } 160 161 /* Get port count and create attached_devices. */ 162 opResult = usb_hub_process_hub_specific_info(hub_dev); 163 if (opResult != EOK) { 164 usb_log_error("Could process hub specific info, %s\n", 165 str_error(opResult)); 166 free(hub_dev); 167 return opResult; 168 } 169 170 usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n"); 171 hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev, 172 fun_exposed, HUB_FNC_NAME); 173 if (hub_dev->hub_fun == NULL) { 174 usb_log_error("Failed to create hub function.\n"); 175 free(hub_dev); 176 return ENOMEM; 177 } 178 179 opResult = ddf_fun_bind(hub_dev->hub_fun); 180 if (opResult != EOK) { 181 usb_log_error("Failed to bind hub function: %s.\n", 182 str_error(opResult)); 183 free(hub_dev); 184 ddf_fun_destroy(hub_dev->hub_fun); 185 return opResult; 186 } 187 188 opResult = usb_device_auto_poll(hub_dev->usb_device, 0, 189 hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8), 190 usb_hub_polling_terminated_callback, hub_dev); 191 if (opResult != EOK) { 192 /* Function is already bound */ 193 ddf_fun_unbind(hub_dev->hub_fun); 194 ddf_fun_destroy(hub_dev->hub_fun); 195 free(hub_dev); 196 usb_log_error("Failed to create polling fibril: %s.\n", 197 str_error(opResult)); 198 return opResult; 199 } 200 hub_dev->running = true; 201 usb_log_info("Controlling hub '%s' (%zu ports).\n", 202 hub_dev->usb_device->ddf_dev->name, hub_dev->port_count); 203 204 return EOK; 205 } 206 /*----------------------------------------------------------------------------*/ 246 207 /** Callback for polling hub for changes. 247 208 * … … 282 243 /*----------------------------------------------------------------------------*/ 283 244 /** 245 * create usb_hub_dev_t structure 246 * 247 * Does only basic copying of known information into new structure. 248 * @param usb_dev usb device structure 249 * @return basic usb_hub_dev_t structure 250 */ 251 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev) 252 { 253 assert(usb_dev); 254 usb_hub_dev_t *hub_dev = 255 usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t)); 256 if (!hub_dev) 257 return NULL; 258 259 hub_dev->usb_device = usb_dev; 260 hub_dev->ports = NULL; 261 hub_dev->port_count = 0; 262 hub_dev->pending_ops_count = 0; 263 hub_dev->running = false; 264 fibril_mutex_initialize(&hub_dev->pending_ops_mutex); 265 fibril_condvar_initialize(&hub_dev->pending_ops_cv); 266 267 return hub_dev; 268 } 269 /*----------------------------------------------------------------------------*/ 270 /** 284 271 * Load hub-specific information into hub_dev structure and process if needed 285 272 * … … 324 311 } 325 312 326 hub_dev->power_switched =313 const bool is_power_switched = 327 314 !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG); 328 hub_dev->per_port_power = 329 descriptor.characteristics & HUB_CHAR_POWER_PER_PORT_FLAG; 330 331 if (!hub_dev->power_switched) { 332 usb_log_info( 333 "Power switching not supported, ports always powered.\n"); 334 return EOK; 335 } 336 337 usb_log_info("Hub port power switching enabled.\n"); 338 339 for (size_t port = 0; port < hub_dev->port_count; ++port) { 340 usb_log_debug("Powering port %zu.\n", port); 341 const int ret = usb_hub_port_set_feature( 342 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 343 344 if (ret != EOK) { 345 usb_log_error("Cannot power on port %zu: %s.\n", 346 hub_dev->ports[port].port_number, str_error(ret)); 347 } else { 348 if (!hub_dev->per_port_power) { 349 usb_log_debug("Ganged power switching, " 350 "one port is enough.\n"); 351 break; 315 if (is_power_switched) { 316 usb_log_debug("Hub power switched\n"); 317 const bool per_port_power = descriptor.characteristics 318 & HUB_CHAR_POWER_PER_PORT_FLAG; 319 320 for (size_t port = 0; port < hub_dev->port_count; ++port) { 321 usb_log_debug("Powering port %zu.\n", port); 322 opResult = usb_hub_port_set_feature( 323 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 324 if (opResult != EOK) { 325 usb_log_error("Cannot power on port %zu: %s.\n", 326 port, str_error(opResult)); 327 } else { 328 if (!per_port_power) { 329 usb_log_debug( 330 "Ganged power switching mode, " 331 "one port is enough.\n"); 332 break; 333 } 352 334 } 353 335 } 336 } else { 337 usb_log_debug("Power not switched, ports always powered\n"); 354 338 } 355 339 return EOK; … … 418 402 usb_log_warning("Detected hub over-current condition, " 419 403 "all ports should be powered off."); 420 return; 421 } 422 423 /* Ports are always powered. */ 424 if (!hub_dev->power_switched) 425 return; 426 427 /* Over-current condition is gone, it is safe to turn the ports on. */ 428 for (size_t port = 0; port < hub_dev->port_count; ++port) { 429 const int ret = usb_hub_port_set_feature( 430 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 431 if (ret != EOK) { 432 usb_log_warning("HUB OVER-CURRENT GONE: Cannot power on" 433 " port %zu: %s\n", hub_dev->ports[port].port_number, 434 str_error(ret)); 435 } else { 436 if (!hub_dev->per_port_power) 437 return; 438 } 439 } 440 404 } else { 405 /* Over-current condition is gone, it is safe to turn the 406 * ports on. */ 407 for (size_t port = 0; port < hub_dev->port_count; ++port) { 408 const int opResult = usb_hub_port_set_feature( 409 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 410 // TODO: consider power policy here 411 if (opResult != EOK) { 412 usb_log_warning( 413 "HUB OVER-CURRENT GONE: Cannot power on " 414 "port %zu; %s\n", 415 port, str_error(opResult)); 416 } 417 } 418 } 419 const int opResult = usb_request_clear_feature( 420 &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS, 421 USB_REQUEST_RECIPIENT_DEVICE, 422 USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0); 423 if (opResult != EOK) { 424 usb_log_error( 425 "Failed to clear hub over-current change flag: %s.\n", 426 str_error(opResult)); 427 } 441 428 } 442 429 /*----------------------------------------------------------------------------*/ … … 474 461 if (status & USB_HUB_STATUS_C_OVER_CURRENT) { 475 462 usb_hub_over_current(hub_dev, status); 476 /* Ack change in hub OC flag */477 const int ret = usb_request_clear_feature(478 &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,479 USB_REQUEST_RECIPIENT_DEVICE,480 USB_HUB_FEATURE_C_HUB_OVER_CURRENT, 0);481 if (ret != EOK) {482 usb_log_error("Failed to clear hub over-current "483 "change flag: %s.\n", str_error(opResult));484 }485 463 } 486 464 … … 499 477 * Just ACK the change. 500 478 */ 501 const int ret = usb_request_clear_feature(479 const int opResult = usb_request_clear_feature( 502 480 control_pipe, USB_REQUEST_TYPE_CLASS, 503 481 USB_REQUEST_RECIPIENT_DEVICE, 504 482 USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0); 505 483 if (opResult != EOK) { 506 usb_log_error("Failed to clear hub power change " 507 "flag: %s.\n", str_error(ret)); 484 usb_log_error( 485 "Failed to clear hub power change flag: %s.\n", 486 str_error(opResult)); 508 487 } 509 488 } -
uspace/drv/bus/usb/usbhub/usbhub.h
r45bf63c r1737bfb 77 77 /** Status indicator */ 78 78 bool running; 79 /** Hub supports port power switching. */80 bool power_switched;81 /** Each port is switched individually. */82 bool per_port_power;83 79 }; 84 80 85 81 int usb_hub_device_add(usb_device_t *usb_dev); 86 int usb_hub_device_remove(usb_device_t *usb_dev);87 82 int usb_hub_device_gone(usb_device_t *usb_dev); 88 83 -
uspace/drv/bus/usb/usbmast/main.c
r45bf63c r1737bfb 55 55 #define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe) 56 56 57 static constusb_endpoint_description_t bulk_in_ep = {57 static usb_endpoint_description_t bulk_in_ep = { 58 58 .transfer_type = USB_TRANSFER_BULK, 59 59 .direction = USB_DIRECTION_IN, … … 63 63 .flags = 0 64 64 }; 65 static constusb_endpoint_description_t bulk_out_ep = {65 static usb_endpoint_description_t bulk_out_ep = { 66 66 .transfer_type = USB_TRANSFER_BULK, 67 67 .direction = USB_DIRECTION_OUT, … … 106 106 } 107 107 108 /** Callback when a device is about to be removed.109 *110 * @param dev Representation of USB device.111 * @return Error code.112 */113 static int usbmast_device_remove(usb_device_t *dev)114 {115 //TODO: flush buffers, or whatever.116 return ENOTSUP;117 }118 119 108 /** Callback when new device is attached and recognized as a mass storage. 120 109 * 121 * @param dev Representation of USB device.110 * @param dev Representation of a the USB device. 122 111 * @return Error code. 123 112 */ … … 347 336 348 337 /** USB mass storage driver ops. */ 349 static constusb_driver_ops_t usbmast_driver_ops = {338 static usb_driver_ops_t usbmast_driver_ops = { 350 339 .device_add = usbmast_device_add, 351 .device_rem = usbmast_device_remove,352 340 .device_gone = usbmast_device_gone, 353 341 }; 354 342 355 343 /** USB mass storage driver. */ 356 static constusb_driver_t usbmast_driver = {344 static usb_driver_t usbmast_driver = { 357 345 .name = NAME, 358 346 .ops = &usbmast_driver_ops, -
uspace/drv/bus/usb/usbmid/main.c
r45bf63c r1737bfb 65 65 return EOK; 66 66 } 67 /*----------------------------------------------------------------------------*/68 /** Callback when a MID device is about to be removed from the host.69 *70 * @param gen_dev Generic DDF device representing the removed device.71 * @return Error code.72 */73 static int usbmid_device_remove(usb_device_t *dev)74 {75 assert(dev);76 int ret = ENOTSUP;77 usb_mid_t *usb_mid = dev->driver_data;78 assert(usb_mid);79 67 80 /* Signal all interface functions */81 list_foreach(usb_mid->interface_list, item) {82 usbmid_interface_t *iface = usbmid_interface_from_link(item);83 84 usb_log_info("Signaling remove to child for interface "85 "%d (%s).\n", iface->interface_no,86 usb_str_class(iface->interface->interface_class));87 // TODO cascade the call.88 }89 return ret;90 }91 /*----------------------------------------------------------------------------*/92 /** Callback when a MID device was removed from the host.93 *94 * @param gen_dev Generic DDF device representing the removed device.95 * @return Error code.96 */97 68 static int usbmid_device_gone(usb_device_t *dev) 98 69 { … … 115 86 list_remove(item); 116 87 117 usbmid_interface_t *iface = usbmid_interface_from_link(item); 88 usbmid_interface_t *iface = list_get_instance(item, 89 usbmid_interface_t, link); 118 90 119 91 usb_log_info("Removing child for interface %d (%s).\n", … … 135 107 136 108 /** USB MID driver ops. */ 137 static constusb_driver_ops_t mid_driver_ops = {109 static usb_driver_ops_t mid_driver_ops = { 138 110 .device_add = usbmid_device_add, 139 .device_rem = usbmid_device_remove,140 111 .device_gone = usbmid_device_gone, 141 112 }; 142 113 143 114 /** USB MID driver. */ 144 static constusb_driver_t mid_driver = {115 static usb_driver_t mid_driver = { 145 116 .name = NAME, 146 117 .ops = &mid_driver_ops, -
uspace/drv/bus/usb/usbmid/usbmid.h
r45bf63c r1737bfb 71 71 int usbmid_interface_destroy(usbmid_interface_t *mid_iface); 72 72 73 static inline usbmid_interface_t * usbmid_interface_from_link(link_t *item)74 {75 return list_get_instance(item, usbmid_interface_t, link);76 }77 78 73 #endif 79 74 /** -
uspace/drv/bus/usb/vhc/connhost.c
r45bf63c r1737bfb 104 104 { 105 105 VHC_DATA(vhc, fun); 106 return usb_device_manager_get_info_by_address( 107 &vhc->dev_manager, address, handle, NULL); 106 bool found = 107 usb_device_manager_find_by_address(&vhc->dev_manager, address, handle); 108 return found ? EOK : ENOENT; 108 109 } 109 110 … … 140 141 size_t max_packet_size, unsigned int interval) 141 142 { 142 VHC_DATA(vhc, fun); 143 144 return usb_endpoint_manager_add_ep(&vhc->ep_manager, 145 address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1, 0, 146 NULL, NULL); 147 143 /* TODO: Use usb_endpoint_manager_add_ep */ 144 VHC_DATA(vhc, fun); 145 146 endpoint_t *ep = endpoint_get( 147 address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1); 148 if (ep == NULL) { 149 return ENOMEM; 150 } 151 152 int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1); 153 if (rc != EOK) { 154 endpoint_destroy(ep); 155 return rc; 156 } 157 158 return EOK; 148 159 } 149 160 … … 161 172 VHC_DATA(vhc, fun); 162 173 163 int rc = usb_endpoint_manager_ remove_ep(&vhc->ep_manager,164 address, endpoint, direction , NULL, NULL);174 int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager, 175 address, endpoint, direction); 165 176 166 177 return rc; … … 403 414 VHC_DATA(vhc, fun); 404 415 405 endpoint_t *ep = usb_endpoint_manager_ find_ep(&vhc->ep_manager,406 target.address, target.endpoint, USB_DIRECTION_IN );416 endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager, 417 target.address, target.endpoint, USB_DIRECTION_IN, NULL); 407 418 if (ep == NULL) { 408 419 return ENOENT; … … 445 456 VHC_DATA(vhc, fun); 446 457 447 endpoint_t *ep = usb_endpoint_manager_ find_ep(&vhc->ep_manager,448 target.address, target.endpoint, USB_DIRECTION_OUT );458 endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager, 459 target.address, target.endpoint, USB_DIRECTION_OUT, NULL); 449 460 if (ep == NULL) { 450 461 return ENOENT; … … 507 518 508 519 usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle); 509 const usb_address_t addr = 510 usb_device_manager_find_address(&vhc->dev_manager, handle); 520 usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle); 511 521 if (addr < 0) { 512 522 return addr; -
uspace/lib/usbdev/include/usb/dev/driver.h
r45bf63c r1737bfb 161 161 } usb_driver_t; 162 162 163 int usb_driver_main( constusb_driver_t *);163 int usb_driver_main(usb_driver_t *); 164 164 165 165 int usb_device_select_interface(usb_device_t *, uint8_t, … … 171 171 usb_endpoint_mapping_t **, size_t *); 172 172 int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t); 173 int usb_device_ init(usb_device_t *, ddf_dev_t*,174 const usb_endpoint_description_t **, const char **);173 int usb_device_create(ddf_dev_t *, const usb_endpoint_description_t **, 174 usb_device_t **, const char **); 175 175 void usb_device_deinit(usb_device_t *); 176 177 176 void * usb_device_data_alloc(usb_device_t *, size_t); 178 177 … … 180 179 int usb_alternate_interfaces_create(const uint8_t *, size_t, int, 181 180 usb_alternate_interfaces_t **); 182 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *); 181 183 182 #endif 184 183 /** -
uspace/lib/usbdev/src/altiface.c
r45bf63c r1737bfb 98 98 assert(config_descr_size > 0); 99 99 100 *alternates_ptr = NULL;101 100 if (interface_number < 0) { 101 alternates_ptr = NULL; 102 102 return EOK; 103 103 } … … 105 105 usb_alternate_interfaces_t *alternates 106 106 = malloc(sizeof(usb_alternate_interfaces_t)); 107 107 108 if (alternates == NULL) { 108 109 return ENOMEM; … … 118 119 } 119 120 120 alternates->alternatives = calloc(alternates->alternative_count,121 sizeof(usb_alternate_interface_descriptors_t));121 alternates->alternatives = malloc(alternates->alternative_count 122 * sizeof(usb_alternate_interface_descriptors_t)); 122 123 if (alternates->alternatives == NULL) { 123 124 free(alternates); … … 175 176 } 176 177 177 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *alternate) 178 { 179 if (!alternate) 180 return; 181 free(alternate->alternatives); 182 free(alternate); 183 } 178 184 179 /** 185 180 * @} -
uspace/lib/usbdev/src/devdrv.c
r45bf63c r1737bfb 64 64 * @return Task exit status. 65 65 */ 66 int usb_driver_main( constusb_driver_t *drv)66 int usb_driver_main(usb_driver_t *drv) 67 67 { 68 68 assert(drv != NULL); … … 140 140 assert(driver->ops->device_add); 141 141 142 usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t)); 143 if (dev == NULL) { 144 usb_log_error("USB device `%s' structure allocation failed.\n", 145 gen_dev->name); 146 return ENOMEM; 147 } 142 int rc; 143 144 usb_device_t *dev = NULL; 148 145 const char *err_msg = NULL; 149 int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg);150 if (rc != EOK) { 151 usb_log_error("USB device `%s' initfailed (%s): %s.\n",146 rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg); 147 if (rc != EOK) { 148 usb_log_error("USB device `%s' creation failed (%s): %s.\n", 152 149 gen_dev->name, err_msg, str_error(rc)); 153 150 return rc; 154 151 } 152 gen_dev->driver_data = dev; 155 153 156 154 rc = driver->ops->device_add(dev); … … 518 516 519 517 520 /** Initialize new instance of USB device. 521 * 522 * @param[in] usb_dev Pointer to the new device. 518 /** Create new instance of USB device. 519 * 523 520 * @param[in] ddf_dev Generic DDF device backing the USB one. 524 521 * @param[in] endpoints NULL terminated array of endpoints (NULL for none). 522 * @param[out] dev_ptr Where to store pointer to the new device. 525 523 * @param[out] errstr_ptr Where to store description of context 526 524 * (in case error occurs). 527 525 * @return Error code. 528 526 */ 529 int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev, 530 const usb_endpoint_description_t **endpoints, const char **errstr_ptr) 531 { 532 assert(usb_dev != NULL); 527 int usb_device_create(ddf_dev_t *ddf_dev, 528 const usb_endpoint_description_t **endpoints, 529 usb_device_t **dev_ptr, const char **errstr_ptr) 530 { 531 assert(dev_ptr != NULL); 533 532 assert(ddf_dev != NULL); 534 533 535 usb_dev->ddf_dev = ddf_dev; 536 usb_dev->driver_data = NULL; 537 usb_dev->descriptors.configuration = NULL; 538 usb_dev->alternate_interfaces = NULL; 539 usb_dev->pipes_count = 0; 540 usb_dev->pipes = NULL; 534 int rc; 535 536 usb_device_t *dev = malloc(sizeof(usb_device_t)); 537 if (dev == NULL) { 538 *errstr_ptr = "structure allocation"; 539 return ENOMEM; 540 } 541 542 // FIXME: proper deallocation in case of errors 543 544 dev->ddf_dev = ddf_dev; 545 dev->driver_data = NULL; 546 dev->descriptors.configuration = NULL; 547 dev->alternate_interfaces = NULL; 548 549 dev->pipes_count = 0; 550 dev->pipes = NULL; 541 551 542 552 /* Initialize backing wire and control pipe. */ 543 int rc = init_wire_and_ctrl_pipe(usb_dev, errstr_ptr);553 rc = init_wire_and_ctrl_pipe(dev, errstr_ptr); 544 554 if (rc != EOK) { 545 555 return rc; … … 547 557 548 558 /* Get our interface. */ 549 usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev);559 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 550 560 551 561 /* Retrieve standard descriptors. */ 552 rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe, 553 &usb_dev->descriptors); 554 if (rc != EOK) { 555 /* Nothing allocated, nothing to free. */ 562 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 563 &dev->descriptors); 564 if (rc != EOK) { 556 565 *errstr_ptr = "descriptor retrieval"; 557 566 return rc; 558 567 } 559 568 560 /* Create alternate interfaces. We will silently ignore failure. */ 561 //TODO Why ignore? 562 usb_alternate_interfaces_create(usb_dev->descriptors.configuration, 563 usb_dev->descriptors.configuration_size, usb_dev->interface_no, 564 &usb_dev->alternate_interfaces); 565 566 rc = initialize_other_pipes(endpoints, usb_dev, 0); 567 if (rc != EOK) { 568 /* Full configuration descriptor is allocated. */ 569 free(usb_dev->descriptors.configuration); 570 /* Alternate interfaces may be allocated */ 571 usb_alternate_interfaces_destroy(usb_dev->alternate_interfaces); 569 /* Create alternate interfaces. */ 570 rc = usb_alternate_interfaces_create(dev->descriptors.configuration, 571 dev->descriptors.configuration_size, dev->interface_no, 572 &dev->alternate_interfaces); 573 if (rc != EOK) { 574 /* We will try to silently ignore this. */ 575 dev->alternate_interfaces = NULL; 576 } 577 578 rc = initialize_other_pipes(endpoints, dev, 0); 579 if (rc != EOK) { 572 580 *errstr_ptr = "pipes initialization"; 573 581 return rc; … … 575 583 576 584 *errstr_ptr = NULL; 585 *dev_ptr = dev; 577 586 578 587 return EOK; 579 588 } 580 589 581 /** Cleaninstance of a USB device.590 /** Destroy instance of a USB device. 582 591 * 583 592 * @param dev Device to be de-initialized. … … 587 596 void usb_device_deinit(usb_device_t *dev) 588 597 { 589 if (dev) { 590 /* Ignore errors and hope for the best. */ 591 destroy_current_pipes(dev); 592 593 usb_alternate_interfaces_destroy(dev->alternate_interfaces); 594 free(dev->descriptors.configuration); 595 free(dev->driver_data); 596 } 598 if (dev == NULL) { 599 return; 600 } 601 602 /* Ignore errors and hope for the best. */ 603 destroy_current_pipes(dev); 604 605 if (dev->alternate_interfaces != NULL) { 606 free(dev->alternate_interfaces->alternatives); 607 } 608 free(dev->alternate_interfaces); 609 free(dev->descriptors.configuration); 610 free(dev->driver_data); 597 611 } 598 612 -
uspace/lib/usbhost/include/usb/host/endpoint.h
r45bf63c r1737bfb 36 36 #define LIBUSBHOST_HOST_ENDPOINT_H 37 37 38 #include <assert.h> 38 39 #include <bool.h> 39 40 #include <adt/list.h> 40 41 #include <fibril_synch.h> 42 41 43 #include <usb/usb.h> 42 44 43 /** Host controller side endpoint structure. */44 45 typedef struct endpoint { 45 /** Part of linked list. */46 link_t link;47 /** USB address. */48 46 usb_address_t address; 49 /** USB endpoint number. */50 47 usb_endpoint_t endpoint; 51 /** Communication direction. */52 48 usb_direction_t direction; 53 /** USB transfer type. */54 49 usb_transfer_type_t transfer_type; 55 /** Communication speed. */56 50 usb_speed_t speed; 57 /** Maximum size of data packets. */58 51 size_t max_packet_size; 59 /** Necessary bandwidth. */60 size_t bandwidth;61 /** Value of the toggle bit. */62 52 unsigned toggle:1; 63 /** True if there is a batch using this scheduled for this endpoint. */ 53 fibril_mutex_t guard; 54 fibril_condvar_t avail; 64 55 volatile bool active; 65 /** Protects resources and active status changes. */ 66 fibril_mutex_t guard; 67 /** Signals change of active status. */ 68 fibril_condvar_t avail; 69 /** Optional device specific data. */ 56 void (*destroy_hook)(struct endpoint *); 70 57 struct { 71 /** Device specific data. */72 58 void *data; 73 /** Callback to get the value of toggle bit. */74 59 int (*toggle_get)(void *); 75 /** Callback to set the value of toggle bit. */76 60 void (*toggle_set)(void *, int); 77 61 } hc_data; 78 62 } endpoint_t; 79 63 80 endpoint_t * endpoint_ create(usb_address_t address, usb_endpoint_t endpoint,64 endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint, 81 65 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 82 size_t max_packet_size, size_t bw); 66 size_t max_packet_size); 67 83 68 void endpoint_destroy(endpoint_t *instance); 84 69 85 70 void endpoint_set_hc_data(endpoint_t *instance, 86 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 71 void *data, void (*destroy_hook)(endpoint_t *), 72 int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 73 87 74 void endpoint_clear_hc_data(endpoint_t *instance); 88 75 89 76 void endpoint_use(endpoint_t *instance); 77 90 78 void endpoint_release(endpoint_t *instance); 91 79 92 80 int endpoint_toggle_get(endpoint_t *instance); 81 93 82 void endpoint_toggle_set(endpoint_t *instance, int toggle); 94 83 95 /** list_get_instance wrapper. 96 * @param item Pointer to link member. 97 * @return Pointer to enpoint_t structure. 98 */ 99 static inline endpoint_t * endpoint_get_instance(link_t *item) 100 { 101 return list_get_instance(item, endpoint_t, link); 102 } 84 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 103 85 #endif 104 86 /** -
uspace/lib/usbhost/include/usb/host/hcd.h
r45bf63c r1737bfb 37 37 38 38 #include <assert.h> 39 #include <usbhc_iface.h>40 41 39 #include <usb/host/usb_device_manager.h> 42 40 #include <usb/host/usb_endpoint_manager.h> 43 41 #include <usb/host/usb_transfer_batch.h> 42 #include <usbhc_iface.h> 44 43 45 44 typedef struct hcd hcd_t; 46 45 47 /** Generic host controller driver structure. */48 46 struct hcd { 49 /** Device manager storing handles and addresses. */50 47 usb_device_manager_t dev_manager; 51 /** Endpoint manager. */52 48 usb_endpoint_manager_t ep_manager; 49 void *private_data; 53 50 54 /** Device specific driver data. */55 void *private_data;56 /** Transfer scheduling, implement in device driver. */57 51 int (*schedule)(hcd_t *, usb_transfer_batch_t *); 58 /** Hook called upon registering new endpoint. */59 52 int (*ep_add_hook)(hcd_t *, endpoint_t *); 60 /** Hook called upon removing of an endpoint. */61 void (*ep_remove_hook)(hcd_t *, endpoint_t *);62 53 }; 63 54 /*----------------------------------------------------------------------------*/ 64 /** Initialize hcd_t structure. 65 * Initializes device and endpoint managers. Sets data nd hook pointer to NULL. 66 * @param hcd hcd_t structure to initialize, non-null. 67 * @param bandwidth Available bandwidth, passed to endpoint manager. 68 * @param bw_count Bandwidth compute function, passed to endpoint manager. 69 */ 70 static inline void hcd_init(hcd_t *hcd, size_t bandwidth, 55 static inline int hcd_init(hcd_t *hcd, size_t bandwidth, 71 56 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)) 72 57 { 73 58 assert(hcd); 74 59 usb_device_manager_init(&hcd->dev_manager); 75 usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count); 76 hcd->private_data = NULL; 77 hcd->schedule = NULL; 78 hcd->ep_add_hook = NULL; 79 hcd->ep_remove_hook = NULL; 60 return usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count); 80 61 } 81 62 /*----------------------------------------------------------------------------*/ 82 /** Check registered endpoints and reset toggle bit if necessary. 83 * @param hcd hcd_t structure, non-null. 84 * @param target Control communication target. 85 * @param setup_data Setup packet of the control communication. 86 87 static inline void reset_ep_if_need( hcd_t *hcd, usb_target_t target,88 const char setup_data[8])63 static inline void hcd_destroy(hcd_t *hcd) 64 { 65 usb_endpoint_manager_destroy(&hcd->ep_manager); 66 } 67 /*----------------------------------------------------------------------------*/ 68 static inline void reset_ep_if_need( 69 hcd_t *hcd, usb_target_t target, const char* setup_data) 89 70 { 90 71 assert(hcd); 91 usb_endpoint_manager_reset_ eps_if_need(72 usb_endpoint_manager_reset_if_need( 92 73 &hcd->ep_manager, target, (const uint8_t *)setup_data); 93 74 } 94 75 /*----------------------------------------------------------------------------*/ 95 /** Data retrieve wrapper. 96 * @param fun ddf function, non-null. 97 * @return pointer cast to hcd_t*. 98 */ 99 static inline hcd_t * fun_to_hcd(const ddf_fun_t *fun) 76 static inline hcd_t * fun_to_hcd(ddf_fun_t *fun) 100 77 { 101 78 assert(fun); -
uspace/lib/usbhost/include/usb/host/usb_device_manager.h
r45bf63c r1737bfb 49 49 #define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1) 50 50 51 /** Information about attached USB device. */ 52 struct usb_device_info { 53 usb_speed_t speed; 54 bool occupied; 55 devman_handle_t handle; 56 }; 57 51 58 /** Host controller device manager. 52 * You shall not access members directly .59 * You shall not access members directly but only using functions below. 53 60 */ 54 61 typedef struct { 55 /** Information about attached USB devices. */ 56 struct { 57 usb_speed_t speed; /**< Device speed */ 58 bool occupied; /**< The address is in use. */ 59 devman_handle_t handle; /**< Devman handle of the device. */ 60 } devices[USB_ADDRESS_COUNT]; 62 struct usb_device_info devices[USB_ADDRESS_COUNT]; 61 63 fibril_mutex_t guard; 62 /** The last reserved address */63 64 usb_address_t last_address; 64 65 } usb_device_manager_t; … … 69 70 usb_device_manager_t *instance, usb_speed_t speed); 70 71 71 intusb_device_manager_bind(usb_device_manager_t *instance,72 void usb_device_manager_bind(usb_device_manager_t *instance, 72 73 usb_address_t address, devman_handle_t handle); 73 74 74 intusb_device_manager_release(usb_device_manager_t *instance,75 void usb_device_manager_release(usb_device_manager_t *instance, 75 76 usb_address_t address); 76 77 77 usb_address_t usb_device_manager_find _address(usb_device_manager_t *instance,78 usb_address_t usb_device_manager_find(usb_device_manager_t *instance, 78 79 devman_handle_t handle); 79 80 80 int usb_device_manager_get_info_by_address(usb_device_manager_t *instance, 81 usb_address_t address, devman_handle_t *handle, usb_speed_t *speed); 81 bool usb_device_manager_find_by_address(usb_device_manager_t *instance, 82 usb_address_t address, devman_handle_t *handle); 83 84 usb_speed_t usb_device_manager_get_speed(usb_device_manager_t *instance, 85 usb_address_t address); 82 86 #endif 83 87 /** -
uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
r45bf63c r1737bfb 40 40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 41 41 42 #include <adt/list.h> 42 #include <stdlib.h> 43 #include <adt/hash_table.h> 43 44 #include <fibril_synch.h> 44 45 #include <usb/usb.h> 45 46 46 #include <usb/host/endpoint.h> 47 47 48 /** Bytes per second in FULL SPEED */ 49 #define BANDWIDTH_TOTAL_USB11 (12000000 / 8) 50 /** 90% of total bandwidth is available for periodic transfers */ 48 #define BANDWIDTH_TOTAL_USB11 12000000 51 49 #define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9) 52 /** 16 addresses per list */53 #define ENDPOINT_LIST_COUNT 854 50 55 /** Endpoint management structure */56 51 typedef struct usb_endpoint_manager { 57 /** Store endpoint_t instances */ 58 list_t endpoint_lists[ENDPOINT_LIST_COUNT]; 59 /** Prevents races accessing lists */ 52 hash_table_t ep_table; 60 53 fibril_mutex_t guard; 61 /** Size of the bandwidth pool */62 54 size_t free_bw; 63 /** Use this function to count bw required by EP */64 55 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t); 65 56 } usb_endpoint_manager_t; … … 72 63 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)); 73 64 74 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance, 75 usb_target_t target, const uint8_t data[8]); 65 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance); 76 66 77 int usb_endpoint_manager_register_ep( 78 usb_endpoint_manager_t *instance, endpoint_t *ep, size_t data_size); 79 int usb_endpoint_manager_unregister_ep( 80 usb_endpoint_manager_t *instance, endpoint_t *ep); 81 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance, 67 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 68 endpoint_t *ep, size_t data_size); 69 70 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance, 82 71 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction); 83 72 84 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 73 endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance, 74 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction, 75 size_t *bw); 76 77 void usb_endpoint_manager_reset_if_need( 78 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data); 79 80 /** Wrapper combining allocation and insertion */ 81 static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 85 82 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 86 83 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size, 87 size_t data_size, int (*callback)(endpoint_t *, void *), void *arg); 84 size_t data_size) 85 { 86 endpoint_t *ep = endpoint_get( 87 address, endpoint, direction, type, speed, max_packet_size); 88 if (!ep) 89 return ENOMEM; 88 90 89 int usb_endpoint_manager_remove_ep(usb_endpoint_manager_t *instance, 90 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 91 void (*callback)(endpoint_t *, void *), void *arg); 91 const int ret = 92 usb_endpoint_manager_register_ep(instance, ep, data_size); 93 if (ret != EOK) { 94 endpoint_destroy(ep); 95 } 96 return ret; 97 } 92 98 #endif 93 99 /** 94 100 * @} 95 101 */ 102 -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
r45bf63c r1737bfb 43 43 #define USB_SETUP_PACKET_SIZE 8 44 44 45 typedef struct usb_transfer_batch usb_transfer_batch_t; 45 46 /** Structure stores additional data needed for communication with EP */ 46 typedefstruct usb_transfer_batch {47 struct usb_transfer_batch { 47 48 /** Endpoint used for communication */ 48 49 endpoint_t *ep; … … 76 77 /** Callback to properly remove driver data during destruction */ 77 78 void (*private_data_dtor)(void *p_data); 78 } usb_transfer_batch_t;79 }; 79 80 80 81 /** Printf formatting string for dumping usb_transfer_batch_t. */ … … 92 93 93 94 94 usb_transfer_batch_t * usb_transfer_batch_ create(95 usb_transfer_batch_t * usb_transfer_batch_get( 95 96 endpoint_t *ep, 96 97 char *buffer, … … 104 105 void (*private_data_dtor)(void *p_data) 105 106 ); 106 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance);107 107 108 void usb_transfer_batch_finish( constusb_transfer_batch_t *instance,108 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, 109 109 const void* data, size_t size); 110 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance); 111 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance); 112 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance); 113 114 /** Helper function, calls callback and correctly destroys batch structure. 115 * 116 * @param[in] instance Batch structure to use. 117 */ 118 static inline void usb_transfer_batch_call_in_and_dispose( 119 usb_transfer_batch_t *instance) 120 { 121 assert(instance); 122 usb_transfer_batch_call_in(instance); 123 usb_transfer_batch_dispose(instance); 124 } 110 125 /*----------------------------------------------------------------------------*/ 111 /** Override error value and finishes transfer. 126 /** Helper function calls callback and correctly destroys batch structure. 127 * 128 * @param[in] instance Batch structure to use. 129 */ 130 static inline void usb_transfer_batch_call_out_and_dispose( 131 usb_transfer_batch_t *instance) 132 { 133 assert(instance); 134 usb_transfer_batch_call_out(instance); 135 usb_transfer_batch_dispose(instance); 136 } 137 /*----------------------------------------------------------------------------*/ 138 /** Helper function, sets error value and finishes transfer. 112 139 * 113 140 * @param[in] instance Batch structure to use. … … 124 151 } 125 152 /*----------------------------------------------------------------------------*/ 126 /** Determine batch direction based on the callbacks present127 * @param[in] instance Batch structure to use , non-null.153 /** Helper function, determines batch direction absed on the present callbacks 154 * @param[in] instance Batch structure to use. 128 155 * @return USB_DIRECTION_IN, or USB_DIRECTION_OUT. 129 156 */ -
uspace/lib/usbhost/src/endpoint.c
r45bf63c r1737bfb 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup libusbhost 28 29 /** @addtogroup drvusbuhcihc 29 30 * @{ 30 31 */ … … 38 39 #include <usb/host/endpoint.h> 39 40 40 /** Allocate ad initialize endpoint_t structure. 41 * @param address USB address. 42 * @param endpoint USB endpoint number. 43 * @param direction Communication direction. 44 * @param type USB transfer type. 45 * @param speed Communication speed. 46 * @param max_packet_size Maximum size of data packets. 47 * @param bw Required bandwidth. 48 * @return Pointer to initialized endpoint_t structure, NULL on failure. 49 */ 50 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 41 endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint, 51 42 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 52 size_t max_packet_size , size_t bw)43 size_t max_packet_size) 53 44 { 54 45 endpoint_t *instance = malloc(sizeof(endpoint_t)); … … 60 51 instance->speed = speed; 61 52 instance->max_packet_size = max_packet_size; 62 instance->bandwidth = bw;63 53 instance->toggle = 0; 64 54 instance->active = false; 55 instance->destroy_hook = NULL; 65 56 instance->hc_data.data = NULL; 66 57 instance->hc_data.toggle_get = NULL; 67 58 instance->hc_data.toggle_set = NULL; 68 link_initialize(&instance->link);69 59 fibril_mutex_initialize(&instance->guard); 70 60 fibril_condvar_initialize(&instance->avail); 61 endpoint_clear_hc_data(instance); 71 62 } 72 63 return instance; 73 64 } 74 65 /*----------------------------------------------------------------------------*/ 75 /** Properly dispose of endpoint_t structure.76 * @param instance endpoint_t structure.77 */78 66 void endpoint_destroy(endpoint_t *instance) 79 67 { 80 68 assert(instance); 81 //TODO: Do something about waiting fibrils.82 69 assert(!instance->active); 83 assert(instance->hc_data.data == NULL); 70 if (instance->hc_data.data) { 71 assert(instance->destroy_hook); 72 instance->destroy_hook(instance); 73 } 84 74 free(instance); 85 75 } 86 76 /*----------------------------------------------------------------------------*/ 87 /** Set device specific data and hooks.88 * @param instance endpoint_t structure.89 * @param data device specific data.90 * @param toggle_get Hook to call when retrieving value of toggle bit.91 * @param toggle_set Hook to call when setting the value of toggle bit.92 */93 77 void endpoint_set_hc_data(endpoint_t *instance, 94 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 78 void *data, void (*destroy_hook)(endpoint_t *), 79 int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 95 80 { 96 81 assert(instance); 97 fibril_mutex_lock(&instance->guard);82 instance->destroy_hook = destroy_hook; 98 83 instance->hc_data.data = data; 99 84 instance->hc_data.toggle_get = toggle_get; 100 85 instance->hc_data.toggle_set = toggle_set; 101 fibril_mutex_unlock(&instance->guard);102 86 } 103 87 /*----------------------------------------------------------------------------*/ 104 /** Clear device specific data and hooks.105 * @param instance endpoint_t structure.106 * @note This function does not free memory pointed to by data pointer.107 */108 88 void endpoint_clear_hc_data(endpoint_t *instance) 109 89 { 110 90 assert(instance); 111 fibril_mutex_lock(&instance->guard);91 instance->destroy_hook = NULL; 112 92 instance->hc_data.data = NULL; 113 93 instance->hc_data.toggle_get = NULL; 114 94 instance->hc_data.toggle_set = NULL; 115 fibril_mutex_unlock(&instance->guard);116 95 } 117 96 /*----------------------------------------------------------------------------*/ 118 /** Mark the endpoint as active and block access for further fibrils.119 * @param instance endpoint_t structure.120 */121 97 void endpoint_use(endpoint_t *instance) 122 98 { … … 129 105 } 130 106 /*----------------------------------------------------------------------------*/ 131 /** Mark the endpoint as inactive and allow access for further fibrils.132 * @param instance endpoint_t structure.133 */134 107 void endpoint_release(endpoint_t *instance) 135 108 { … … 141 114 } 142 115 /*----------------------------------------------------------------------------*/ 143 /** Get the value of toggle bit.144 * @param instance endpoint_t structure.145 * @note Will use provided hook.146 */147 116 int endpoint_toggle_get(endpoint_t *instance) 148 117 { 149 118 assert(instance); 150 fibril_mutex_lock(&instance->guard);151 119 if (instance->hc_data.toggle_get) 152 120 instance->toggle = 153 121 instance->hc_data.toggle_get(instance->hc_data.data); 154 const int ret = instance->toggle; 155 fibril_mutex_unlock(&instance->guard); 156 return ret; 122 return (int)instance->toggle; 157 123 } 158 124 /*----------------------------------------------------------------------------*/ 159 /** Set the value of toggle bit.160 * @param instance endpoint_t structure.161 * @note Will use provided hook.162 */163 125 void endpoint_toggle_set(endpoint_t *instance, int toggle) 164 126 { 165 127 assert(instance); 166 128 assert(toggle == 0 || toggle == 1); 167 fibril_mutex_lock(&instance->guard);168 instance->toggle = toggle;169 129 if (instance->hc_data.toggle_set) 170 130 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 171 fibril_mutex_unlock(&instance->guard); 131 instance->toggle = toggle; 132 } 133 /*----------------------------------------------------------------------------*/ 134 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target) 135 { 136 assert(instance); 137 if (instance->address == target.address && 138 (instance->endpoint == target.endpoint || target.endpoint == 0)) 139 endpoint_toggle_set(instance, 0); 172 140 } 173 141 /** -
uspace/lib/usbhost/src/iface.c
r45bf63c r1737bfb 49 49 assert(hcd); 50 50 51 endpoint_t *ep = usb_endpoint_manager_find_ep(&hcd->ep_manager, 52 target.address, target.endpoint, direction); 51 int ret; 52 53 size_t res_bw; 54 endpoint_t *ep = usb_endpoint_manager_get_ep(&hcd->ep_manager, 55 target.address, target.endpoint, direction, &res_bw); 53 56 if (ep == NULL) { 54 57 usb_log_error("Endpoint(%d:%d) not registered for %s.\n", … … 62 65 const size_t bw = bandwidth_count_usb11( 63 66 ep->speed, ep->transfer_type, size, ep->max_packet_size); 64 /* Check if we have enough bandwidth reserved */ 65 if (ep->bandwidth < bw) { 67 if (res_bw < bw) { 66 68 usb_log_error("Endpoint(%d:%d) %s needs %zu bw " 67 69 "but only %zu is reserved.\n", 68 ep->address, ep->endpoint, name, bw, ep->bandwidth);70 target.address, target.endpoint, name, bw, res_bw); 69 71 return ENOSPC; 70 72 } … … 76 78 /* No private data and no private data dtor */ 77 79 usb_transfer_batch_t *batch = 78 usb_transfer_batch_ create(ep, data, size, setup_data,80 usb_transfer_batch_get(ep, data, size, setup_data, 79 81 in, out, arg, fun, NULL, NULL); 80 82 if (!batch) { … … 82 84 } 83 85 84 const intret = hcd->schedule(hcd, batch);86 ret = hcd->schedule(hcd, batch); 85 87 if (ret != EOK) 86 usb_transfer_batch_d estroy(batch);88 usb_transfer_batch_dispose(batch); 87 89 88 90 return ret; … … 128 130 129 131 usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle); 130 return usb_device_manager_bind(&hcd->dev_manager, address, handle); 132 usb_device_manager_bind(&hcd->dev_manager, address, handle); 133 return EOK; 131 134 } 132 135 /*----------------------------------------------------------------------------*/ … … 144 147 hcd_t *hcd = fun_to_hcd(fun); 145 148 assert(hcd); 146 return usb_device_manager_get_info_by_address( 147 &hcd->dev_manager, address, handle, NULL); 149 const bool found = 150 usb_device_manager_find_by_address(&hcd->dev_manager, address, handle); 151 return found ? EOK : ENOENT; 148 152 } 149 153 /*----------------------------------------------------------------------------*/ … … 162 166 usb_device_manager_release(&hcd->dev_manager, address); 163 167 return EOK; 164 }165 /*----------------------------------------------------------------------------*/166 static int register_helper(endpoint_t *ep, void *arg)167 {168 hcd_t *hcd = arg;169 assert(ep);170 assert(hcd);171 if (hcd->ep_add_hook)172 return hcd->ep_add_hook(hcd, ep);173 return EOK;174 }175 /*----------------------------------------------------------------------------*/176 static void unregister_helper(endpoint_t *ep, void *arg)177 {178 hcd_t *hcd = arg;179 assert(ep);180 assert(hcd);181 if (hcd->ep_remove_hook)182 hcd->ep_remove_hook(hcd, ep);183 168 } 184 169 /*----------------------------------------------------------------------------*/ … … 195 180 /* Default address is not bound or registered, 196 181 * thus it does not provide speed info. */ 197 usb_speed_t speed = ep_speed; 198 /* NOTE The function will return EINVAL and won't 199 * touch speed variable for default address */ 200 usb_device_manager_get_info_by_address( 201 &hcd->dev_manager, address, NULL, &speed); 182 const usb_speed_t speed = (address == 0) ? ep_speed : 183 usb_device_manager_get_speed(&hcd->dev_manager, address); 202 184 203 185 usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n", … … 206 188 max_packet_size, interval); 207 189 208 return usb_endpoint_manager_add_ep(&hcd->ep_manager, address, endpoint, 209 direction, transfer_type, speed, max_packet_size, size, 210 register_helper, hcd); 190 endpoint_t *ep = endpoint_get( 191 address, endpoint, direction, transfer_type, speed, max_packet_size); 192 if (!ep) 193 return ENOMEM; 194 int ret = EOK; 195 196 if (hcd->ep_add_hook) { 197 ret = hcd->ep_add_hook(hcd, ep); 198 } 199 if (ret != EOK) { 200 endpoint_destroy(ep); 201 return ret; 202 } 203 204 ret = usb_endpoint_manager_register_ep(&hcd->ep_manager, ep, size); 205 if (ret != EOK) { 206 endpoint_destroy(ep); 207 } 208 return ret; 211 209 } 212 210 /*----------------------------------------------------------------------------*/ … … 220 218 usb_log_debug("Unregister endpoint %d:%d %s.\n", 221 219 address, endpoint, usb_str_direction(direction)); 222 return usb_endpoint_manager_ remove_ep(&hcd->ep_manager, address,223 endpoint, direction , unregister_helper, hcd);220 return usb_endpoint_manager_unregister_ep(&hcd->ep_manager, address, 221 endpoint, direction); 224 222 } 225 223 /*----------------------------------------------------------------------------*/ -
uspace/lib/usbhost/src/usb_device_manager.c
r45bf63c r1737bfb 38 38 #include <usb/host/usb_device_manager.h> 39 39 40 /*----------------------------------------------------------------------------*/ 40 41 /** Initialize device manager structure. 41 42 * … … 47 48 { 48 49 assert(instance); 49 for (unsigned i = 0; i < USB_ADDRESS_COUNT; ++i) { 50 unsigned i = 0; 51 for (; i < USB_ADDRESS_COUNT; ++i) { 50 52 instance->devices[i].occupied = false; 51 53 instance->devices[i].handle = 0; … … 75 77 ++new_address; 76 78 if (new_address > USB11_ADDRESS_MAX) 77 new_address = 1; // NOTE it should be safe to put 0 here 78 // TODO Use mod 79 new_address = 1; 79 80 if (new_address == instance->last_address) { 80 81 fibril_mutex_unlock(&instance->guard); … … 85 86 assert(new_address != USB_ADDRESS_DEFAULT); 86 87 assert(instance->devices[new_address].occupied == false); 87 assert(instance->devices[new_address].handle == 0);88 88 89 89 instance->devices[new_address].occupied = true; … … 100 100 * @param[in] address Device address 101 101 * @param[in] handle Devman handle of the device. 102 * @return Error code. 103 */ 104 int usb_device_manager_bind(usb_device_manager_t *instance, 102 */ 103 void usb_device_manager_bind(usb_device_manager_t *instance, 105 104 usb_address_t address, devman_handle_t handle) 106 105 { 107 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 108 return EINVAL; 109 } 110 assert(instance); 111 112 fibril_mutex_lock(&instance->guard); 113 /* Not reserved */ 114 if (!instance->devices[address].occupied) { 115 fibril_mutex_unlock(&instance->guard); 116 return ENOENT; 117 } 118 /* Already bound */ 119 if (instance->devices[address].handle != 0) { 120 fibril_mutex_unlock(&instance->guard); 121 return EEXISTS; 122 } 106 assert(instance); 107 fibril_mutex_lock(&instance->guard); 108 109 assert(address > 0); 110 assert(address <= USB11_ADDRESS_MAX); 111 assert(instance->devices[address].occupied); 112 123 113 instance->devices[address].handle = handle; 124 114 fibril_mutex_unlock(&instance->guard); 125 return EOK;126 115 } 127 116 /*----------------------------------------------------------------------------*/ … … 130 119 * @param[in] instance Device manager structure to use. 131 120 * @param[in] address Device address 132 * @return Error code. 133 */ 134 int usb_device_manager_release( 121 */ 122 void usb_device_manager_release( 135 123 usb_device_manager_t *instance, usb_address_t address) 136 124 { 137 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 138 return EINVAL; 139 } 140 assert(instance); 141 142 fibril_mutex_lock(&instance->guard); 143 if (!instance->devices[address].occupied) { 144 fibril_mutex_unlock(&instance->guard); 145 return ENOENT; 146 } 125 assert(instance); 126 assert(address > 0); 127 assert(address <= USB11_ADDRESS_MAX); 128 129 fibril_mutex_lock(&instance->guard); 130 assert(instance->devices[address].occupied); 147 131 148 132 instance->devices[address].occupied = false; 149 instance->devices[address].handle = 0; 150 fibril_mutex_unlock(&instance->guard); 151 return EOK; 133 fibril_mutex_unlock(&instance->guard); 152 134 } 153 135 /*----------------------------------------------------------------------------*/ … … 158 140 * @return USB Address, or error code. 159 141 */ 160 usb_address_t usb_device_manager_find _address(142 usb_address_t usb_device_manager_find( 161 143 usb_device_manager_t *instance, devman_handle_t handle) 162 144 { 163 145 assert(instance); 164 146 fibril_mutex_lock(&instance->guard); 165 for (usb_address_t address = 1; address <= USB11_ADDRESS_MAX; ++address)166 {147 usb_address_t address = 1; 148 while (address <= USB11_ADDRESS_MAX) { 167 149 if (instance->devices[address].handle == handle) { 168 150 assert(instance->devices[address].occupied); … … 170 152 return address; 171 153 } 154 ++address; 172 155 } 173 156 fibril_mutex_unlock(&instance->guard); 174 157 return ENOENT; 175 158 } 176 /*----------------------------------------------------------------------------*/ 177 /** Find devman handle a nd speed assigned to USB address.178 * Intentionally refuse to work ondefault address.159 160 /** Find devman handle assigned to USB address. 161 * Intentionally refuse to find handle of default address. 179 162 * 180 163 * @param[in] instance Device manager structure to use. 181 164 * @param[in] address Address the caller wants to find. 182 165 * @param[out] handle Where to store found handle. 183 * @ param[out] speed Assigned speed.184 * @return Error code.185 */ 186 int usb_device_manager_get_info_by_address(usb_device_manager_t *instance, 187 usb_address_t address, devman_handle_t *handle, usb_speed_t *speed) 188 { 189 assert(instance);166 * @return Whether such address is currently occupied. 167 */ 168 bool usb_device_manager_find_by_address(usb_device_manager_t *instance, 169 usb_address_t address, devman_handle_t *handle) 170 { 171 assert(instance); 172 fibril_mutex_lock(&instance->guard); 190 173 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 191 return EINVAL; 192 } 193 194 fibril_mutex_lock(&instance->guard); 174 fibril_mutex_unlock(&instance->guard); 175 return false; 176 } 195 177 if (!instance->devices[address].occupied) { 196 178 fibril_mutex_unlock(&instance->guard); 197 return ENOENT;179 return false; 198 180 } 199 181 … … 201 183 *handle = instance->devices[address].handle; 202 184 } 203 if (speed != NULL) { 204 *speed = instance->devices[address].speed; 205 } 206 207 fibril_mutex_unlock(&instance->guard); 208 return EOK; 185 186 fibril_mutex_unlock(&instance->guard); 187 return true; 188 } 189 190 /*----------------------------------------------------------------------------*/ 191 /** Get speed associated with the address 192 * 193 * @param[in] instance Device manager structure to use. 194 * @param[in] address Address of the device. 195 * @return USB speed. 196 */ 197 usb_speed_t usb_device_manager_get_speed( 198 usb_device_manager_t *instance, usb_address_t address) 199 { 200 assert(instance); 201 assert(address >= 0); 202 assert(address <= USB11_ADDRESS_MAX); 203 204 return instance->devices[address].speed; 209 205 } 210 206 /** -
uspace/lib/usbhost/src/usb_endpoint_manager.c
r45bf63c r1737bfb 34 34 #include <usb/host/usb_endpoint_manager.h> 35 35 36 /** Endpoint compare helper function. 37 * 38 * USB_DIRECTION_BOTH matches both IN and OUT. 39 * @param ep Endpoint to compare, non-null. 40 * @param address Tested address. 41 * @param endpoint Tested endpoint number. 42 * @param direction Tested direction. 43 * @return True if ep can be used to communicate with given device, 44 * false otherwise. 45 */ 46 static inline bool ep_match(const endpoint_t *ep, 47 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 48 { 49 assert(ep); 50 return 51 ((direction == ep->direction) 52 || (ep->direction == USB_DIRECTION_BOTH) 53 || (direction == USB_DIRECTION_BOTH)) 54 && (endpoint == ep->endpoint) 55 && (address == ep->address); 56 } 57 /*----------------------------------------------------------------------------*/ 58 /** Get list that holds endpints for given address. 59 * @param instance usb_endpoint_manager structure, non-null. 60 * @param addr USB address, must be >= 0. 61 * @return Pointer to the appropriate list. 62 */ 63 static list_t * get_list(usb_endpoint_manager_t *instance, usb_address_t addr) 64 { 65 assert(instance); 66 assert(addr >= 0); 67 return &instance->endpoint_lists[addr % ENDPOINT_LIST_COUNT]; 68 } 69 /*----------------------------------------------------------------------------*/ 70 /** Internal search function, works on locked structure. 71 * @param instance usb_endpoint_manager structure, non-null. 72 * @param address USB address, must be valid. 73 * @param endpoint USB endpoint number. 74 * @param direction Communication direction. 75 * @return Pointer to endpoint_t structure representing given communication 76 * target, NULL if there is no such endpoint registered. 77 */ 78 static endpoint_t * find_locked(usb_endpoint_manager_t *instance, 79 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 80 { 81 assert(instance); 82 assert(fibril_mutex_is_locked(&instance->guard)); 83 if (address < 0) 84 return NULL; 85 list_foreach(*get_list(instance, address), iterator) { 86 endpoint_t *ep = endpoint_get_instance(iterator); 87 if (ep_match(ep, address, endpoint, direction)) 88 return ep; 89 } 90 return NULL; 91 } 92 /*----------------------------------------------------------------------------*/ 93 /** Calculate bandwidth that needs to be reserved for communication with EP. 94 * Calculation follows USB 1.1 specification. 95 * @param speed Device's speed. 96 * @param type Type of the transfer. 97 * @param size Number of byte to transfer. 98 * @param max_packet_size Maximum bytes in one packet. 99 */ 36 #define BUCKET_COUNT 7 37 38 #define MAX_KEYS (3) 39 typedef struct { 40 link_t link; 41 size_t bw; 42 endpoint_t *ep; 43 } node_t; 44 /*----------------------------------------------------------------------------*/ 45 static hash_index_t node_hash(unsigned long key[]) 46 { 47 /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1]) 48 * produces unique value for every address.endpoint pair */ 49 return ((key[0] << 4) | key[1]) % BUCKET_COUNT; 50 } 51 /*----------------------------------------------------------------------------*/ 52 static int node_compare(unsigned long key[], hash_count_t keys, link_t *item) 53 { 54 assert(item); 55 node_t *node = hash_table_get_instance(item, node_t, link); 56 assert(node); 57 assert(node->ep); 58 bool match = true; 59 switch (keys) { 60 case 3: 61 match = match && 62 ((key[2] == node->ep->direction) 63 || (node->ep->direction == USB_DIRECTION_BOTH)); 64 case 2: 65 match = match && (key[1] == (unsigned long)node->ep->endpoint); 66 case 1: 67 match = match && (key[0] == (unsigned long)node->ep->address); 68 break; 69 default: 70 match = false; 71 } 72 return match; 73 } 74 /*----------------------------------------------------------------------------*/ 75 static void node_remove(link_t *item) 76 { 77 assert(item); 78 node_t *node = hash_table_get_instance(item, node_t, link); 79 endpoint_destroy(node->ep); 80 free(node); 81 } 82 /*----------------------------------------------------------------------------*/ 83 static void node_toggle_reset_filtered(link_t *item, void *arg) 84 { 85 assert(item); 86 node_t *node = hash_table_get_instance(item, node_t, link); 87 usb_target_t *target = arg; 88 endpoint_toggle_reset_filtered(node->ep, *target); 89 } 90 /*----------------------------------------------------------------------------*/ 91 static hash_table_operations_t op = { 92 .hash = node_hash, 93 .compare = node_compare, 94 .remove_callback = node_remove, 95 }; 96 /*----------------------------------------------------------------------------*/ 100 97 size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type, 101 98 size_t size, size_t max_packet_size) … … 109 106 const unsigned packet_count = 110 107 (size + max_packet_size - 1) / max_packet_size; 111 /* TODO: It may be that ISO and INT transfers use only one packet per 112 * transaction, but I did not find text in USB spec to confirm this */ 108 /* TODO: It may be that ISO and INT transfers use only one data packet 109 * per transaction, but I did not find text in UB spec that confirms 110 * this */ 113 111 /* NOTE: All data packets will be considered to be max_packet_size */ 114 112 switch (speed) … … 139 137 } 140 138 /*----------------------------------------------------------------------------*/ 141 /** Initialize to default state.142 * You need to provide valid bw_count function if you plan to use143 * add_endpoint/remove_endpoint pair.144 *145 * @param instance usb_endpoint_manager structure, non-null.146 * @param available_bandwidth Size of the bandwidth pool.147 * @param bw_count function to use to calculate endpoint bw requirements.148 * @return Error code.149 */150 139 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 151 140 size_t available_bandwidth, … … 156 145 instance->free_bw = available_bandwidth; 157 146 instance->bw_count = bw_count; 158 for (unsigned i = 0; i < ENDPOINT_LIST_COUNT; ++i) { 159 list_initialize(&instance->endpoint_lists[i]); 160 } 147 const bool ht = 148 hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op); 149 return ht ? EOK : ENOMEM; 150 } 151 /*----------------------------------------------------------------------------*/ 152 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance) 153 { 154 hash_table_destroy(&instance->ep_table); 155 } 156 /*----------------------------------------------------------------------------*/ 157 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 158 endpoint_t *ep, size_t data_size) 159 { 160 assert(instance); 161 assert(instance->bw_count); 162 assert(ep); 163 const size_t bw = instance->bw_count(ep->speed, ep->transfer_type, 164 data_size, ep->max_packet_size); 165 166 fibril_mutex_lock(&instance->guard); 167 168 if (bw > instance->free_bw) { 169 fibril_mutex_unlock(&instance->guard); 170 return ENOSPC; 171 } 172 173 unsigned long key[MAX_KEYS] = 174 {ep->address, ep->endpoint, ep->direction}; 175 176 const link_t *item = 177 hash_table_find(&instance->ep_table, key); 178 if (item != NULL) { 179 fibril_mutex_unlock(&instance->guard); 180 return EEXISTS; 181 } 182 183 node_t *node = malloc(sizeof(node_t)); 184 if (node == NULL) { 185 fibril_mutex_unlock(&instance->guard); 186 return ENOMEM; 187 } 188 189 node->bw = bw; 190 node->ep = ep; 191 link_initialize(&node->link); 192 193 hash_table_insert(&instance->ep_table, key, &node->link); 194 instance->free_bw -= bw; 195 fibril_mutex_unlock(&instance->guard); 161 196 return EOK; 162 197 } 163 198 /*----------------------------------------------------------------------------*/ 199 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance, 200 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 201 { 202 assert(instance); 203 unsigned long key[MAX_KEYS] = {address, endpoint, direction}; 204 205 fibril_mutex_lock(&instance->guard); 206 link_t *item = hash_table_find(&instance->ep_table, key); 207 if (item == NULL) { 208 fibril_mutex_unlock(&instance->guard); 209 return EINVAL; 210 } 211 212 node_t *node = hash_table_get_instance(item, node_t, link); 213 if (node->ep->active) { 214 fibril_mutex_unlock(&instance->guard); 215 return EBUSY; 216 } 217 218 instance->free_bw += node->bw; 219 hash_table_remove(&instance->ep_table, key, MAX_KEYS); 220 221 fibril_mutex_unlock(&instance->guard); 222 return EOK; 223 } 224 /*----------------------------------------------------------------------------*/ 225 endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance, 226 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 227 size_t *bw) 228 { 229 assert(instance); 230 unsigned long key[MAX_KEYS] = {address, endpoint, direction}; 231 232 fibril_mutex_lock(&instance->guard); 233 const link_t *item = hash_table_find(&instance->ep_table, key); 234 if (item == NULL) { 235 fibril_mutex_unlock(&instance->guard); 236 return NULL; 237 } 238 const node_t *node = hash_table_get_instance(item, node_t, link); 239 if (bw) 240 *bw = node->bw; 241 242 fibril_mutex_unlock(&instance->guard); 243 return node->ep; 244 } 245 /*----------------------------------------------------------------------------*/ 164 246 /** Check setup packet data for signs of toggle reset. 165 247 * 166 * @param[in] instance usb_endpoint_manager structure, non-null.248 * @param[in] instance Device keeper structure to use. 167 249 * @param[in] target Device to receive setup packet. 168 250 * @param[in] data Setup packet data. 169 251 * 170 * Really ugly one. Resets toggle bit on all endpoints that need it.252 * Really ugly one. 171 253 */ 172 void usb_endpoint_manager_reset_ eps_if_need(usb_endpoint_manager_t *instance,173 usb_ target_t target, const uint8_t data[8])254 void usb_endpoint_manager_reset_if_need( 255 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data) 174 256 { 175 257 assert(instance); … … 185 267 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */ 186 268 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 269 /* endpoint number is < 16, thus first byte is enough */ 270 usb_target_t reset_target = 271 { .address = target.address, data[4] }; 187 272 fibril_mutex_lock(&instance->guard); 188 /* endpoint number is < 16, thus first byte is enough */ 189 list_foreach(*get_list(instance, target.address), it) { 190 endpoint_t *ep = endpoint_get_instance(it); 191 if ((ep->address == target.address) 192 && (ep->endpoint = data[4])) { 193 endpoint_toggle_set(ep,0); 194 } 195 } 273 hash_table_apply(&instance->ep_table, 274 node_toggle_reset_filtered, &reset_target); 196 275 fibril_mutex_unlock(&instance->guard); 197 276 } … … 200 279 case 0x9: /* Set Configuration */ 201 280 case 0x11: /* Set Interface */ 202 /* Recipient must be device, this resets all endpoints, 203 * In fact there should be no endpoints but EP 0 registered 204 * as different interfaces use different endpoints. */ 281 /* Recipient must be device */ 205 282 if ((data[0] & 0xf) == 0) { 283 usb_target_t reset_target = 284 { .address = target.address, 0 }; 206 285 fibril_mutex_lock(&instance->guard); 207 list_foreach(*get_list(instance, target.address), it) { 208 endpoint_t *ep = endpoint_get_instance(it); 209 if (ep->address == target.address) { 210 endpoint_toggle_set(ep,0); 211 } 212 } 286 hash_table_apply(&instance->ep_table, 287 node_toggle_reset_filtered, &reset_target); 213 288 fibril_mutex_unlock(&instance->guard); 214 289 } … … 216 291 } 217 292 } 218 /*----------------------------------------------------------------------------*/219 /** Register endpoint structure.220 * Checks for duplicates.221 * @param instance usb_endpoint_manager, non-null.222 * @param ep endpoint_t to register.223 * @param data_size Size of data to transfer.224 * @return Error code.225 */226 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,227 endpoint_t *ep, size_t data_size)228 {229 assert(instance);230 if (ep == NULL || ep->address < 0)231 return EINVAL;232 233 fibril_mutex_lock(&instance->guard);234 /* Check for available bandwidth */235 if (ep->bandwidth > instance->free_bw) {236 fibril_mutex_unlock(&instance->guard);237 return ENOSPC;238 }239 240 /* Check for existence */241 const endpoint_t *endpoint =242 find_locked(instance, ep->address, ep->endpoint, ep->direction);243 if (endpoint != NULL) {244 fibril_mutex_unlock(&instance->guard);245 return EEXISTS;246 }247 list_append(&ep->link, get_list(instance, ep->address));248 249 instance->free_bw -= ep->bandwidth;250 fibril_mutex_unlock(&instance->guard);251 return EOK;252 }253 /*----------------------------------------------------------------------------*/254 /** Unregister endpoint structure.255 * Checks for duplicates.256 * @param instance usb_endpoint_manager, non-null.257 * @param ep endpoint_t to unregister.258 * @return Error code.259 */260 int usb_endpoint_manager_unregister_ep(261 usb_endpoint_manager_t *instance, endpoint_t *ep)262 {263 assert(instance);264 if (ep == NULL || ep->address < 0)265 return EINVAL;266 267 fibril_mutex_lock(&instance->guard);268 if (!list_member(&ep->link, get_list(instance, ep->address))) {269 fibril_mutex_unlock(&instance->guard);270 return ENOENT;271 }272 list_remove(&ep->link);273 instance->free_bw += ep->bandwidth;274 fibril_mutex_unlock(&instance->guard);275 return EOK;276 }277 /*----------------------------------------------------------------------------*/278 /** Find endpoint_t representing the given communication route.279 * @param instance usb_endpoint_manager, non-null.280 * @param address281 */282 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance,283 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)284 {285 assert(instance);286 287 fibril_mutex_lock(&instance->guard);288 endpoint_t *ep = find_locked(instance, address, endpoint, direction);289 fibril_mutex_unlock(&instance->guard);290 return ep;291 }292 /*----------------------------------------------------------------------------*/293 /** Create and register new endpoint_t structure.294 * @param instance usb_endpoint_manager structure, non-null.295 * @param address USB address.296 * @param endpoint USB endpoint number.297 * @param direction Communication direction.298 * @param type USB transfer type.299 * @param speed USB Communication speed.300 * @param max_packet_size Maximum size of data packets.301 * @param data_size Expected communication size.302 * @param callback function to call just after registering.303 * @param arg Argument to pass to the callback function.304 * @return Error code.305 */306 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,307 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,308 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,309 size_t data_size, int (*callback)(endpoint_t *, void *), void *arg)310 {311 assert(instance);312 if (instance->bw_count == NULL)313 return ENOTSUP;314 if (address < 0)315 return EINVAL;316 317 const size_t bw =318 instance->bw_count(speed, type, data_size, max_packet_size);319 320 fibril_mutex_lock(&instance->guard);321 /* Check for available bandwidth */322 if (bw > instance->free_bw) {323 fibril_mutex_unlock(&instance->guard);324 return ENOSPC;325 }326 327 /* Check for existence */328 endpoint_t *ep = find_locked(instance, address, endpoint, direction);329 if (ep != NULL) {330 fibril_mutex_unlock(&instance->guard);331 return EEXISTS;332 }333 334 ep = endpoint_create(335 address, endpoint, direction, type, speed, max_packet_size, bw);336 if (!ep) {337 fibril_mutex_unlock(&instance->guard);338 return ENOMEM;339 }340 341 if (callback) {342 const int ret = callback(ep, arg);343 if (ret != EOK) {344 fibril_mutex_unlock(&instance->guard);345 endpoint_destroy(ep);346 return ret;347 }348 }349 list_append(&ep->link, get_list(instance, ep->address));350 351 instance->free_bw -= ep->bandwidth;352 fibril_mutex_unlock(&instance->guard);353 return EOK;354 }355 /*----------------------------------------------------------------------------*/356 /** Unregister and destroy endpoint_t structure representing given route.357 * @param instance usb_endpoint_manager structure, non-null.358 * @param address USB address.359 * @param endpoint USB endpoint number.360 * @param direction Communication direction.361 * @param callback Function to call after unregister, before destruction.362 * @arg Argument to pass to the callback function.363 * @return Error code.364 */365 int usb_endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,366 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,367 void (*callback)(endpoint_t *, void *), void *arg)368 {369 assert(instance);370 fibril_mutex_lock(&instance->guard);371 endpoint_t *ep = find_locked(instance, address, endpoint, direction);372 if (ep != NULL) {373 list_remove(&ep->link);374 instance->free_bw += ep->bandwidth;375 }376 fibril_mutex_unlock(&instance->guard);377 if (ep == NULL)378 return ENOENT;379 380 if (callback) {381 callback(ep, arg);382 }383 endpoint_destroy(ep);384 return EOK;385 } -
uspace/lib/usbhost/src/usb_transfer_batch.c
r45bf63c r1737bfb 37 37 #include <usb/usb.h> 38 38 #include <usb/debug.h> 39 40 39 #include <usb/host/usb_transfer_batch.h> 41 40 #include <usb/host/hcd.h> 42 41 43 /** Allocate and initialize usb_transfer_batch structure. 44 * @param ep endpoint used by the transfer batch. 45 * @param buffer data to send/recieve. 46 * @param buffer_size Size of data buffer. 47 * @param setup_buffer Data to send in SETUP stage of control transfer. 48 * @param func_in callback on IN transfer completion. 49 * @param func_out callback on OUT transfer completion. 50 * @param arg Argument to pass to the callback function. 51 * @param private_data driver specific per batch data. 52 * @param private_data_dtor Function to properly destroy private_data. 53 * @return Pointer to valid usb_transfer_batch_t structure, NULL on failure. 54 */ 55 usb_transfer_batch_t * usb_transfer_batch_create( 42 usb_transfer_batch_t * usb_transfer_batch_get( 56 43 endpoint_t *ep, 57 44 char *buffer, … … 66 53 ) 67 54 { 68 if (func_in == NULL && func_out == NULL)69 return NULL;70 if (func_in != NULL && func_out != NULL)71 return NULL;72 73 55 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 74 56 if (instance) { … … 96 78 } 97 79 /*----------------------------------------------------------------------------*/ 80 /** Mark batch as finished and run callback. 81 * 82 * @param[in] instance Batch structure to use. 83 * @param[in] data Data to copy to the output buffer. 84 * @param[in] size Size of @p data. 85 */ 86 void usb_transfer_batch_finish( 87 usb_transfer_batch_t *instance, const void *data, size_t size) 88 { 89 assert(instance); 90 assert(instance->ep); 91 /* we care about the data and there are some to copy */ 92 if (instance->ep->direction != USB_DIRECTION_OUT 93 && data) { 94 const size_t min_size = 95 size < instance->buffer_size ? size : instance->buffer_size; 96 memcpy(instance->buffer, data, min_size); 97 } 98 if (instance->callback_out) 99 usb_transfer_batch_call_out(instance); 100 if (instance->callback_in) 101 usb_transfer_batch_call_in(instance); 102 103 } 104 /*----------------------------------------------------------------------------*/ 105 /** Prepare data, get error status and call callback in. 106 * 107 * @param[in] instance Batch structure to use. 108 * Copies data from transport buffer, and calls callback with appropriate 109 * parameters. 110 */ 111 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance) 112 { 113 assert(instance); 114 assert(instance->callback_in); 115 116 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n", 117 instance, USB_TRANSFER_BATCH_ARGS(*instance), 118 instance->transfered_size, str_error(instance->error)); 119 120 instance->callback_in(instance->fun, instance->error, 121 instance->transfered_size, instance->arg); 122 } 123 /*----------------------------------------------------------------------------*/ 124 /** Get error status and call callback out. 125 * 126 * @param[in] instance Batch structure to use. 127 */ 128 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance) 129 { 130 assert(instance); 131 assert(instance->callback_out); 132 133 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n", 134 instance, USB_TRANSFER_BATCH_ARGS(*instance), 135 str_error(instance->error)); 136 137 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL 138 && instance->error == EOK) { 139 const usb_target_t target = 140 {{ instance->ep->address, instance->ep->endpoint }}; 141 reset_ep_if_need( 142 fun_to_hcd(instance->fun), target, instance->setup_buffer); 143 } 144 145 instance->callback_out(instance->fun, 146 instance->error, instance->arg); 147 } 148 /*----------------------------------------------------------------------------*/ 98 149 /** Correctly dispose all used data structures. 99 150 * 100 151 * @param[in] instance Batch structure to use. 101 152 */ 102 void usb_transfer_batch_d estroy(constusb_transfer_batch_t *instance)153 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance) 103 154 { 104 155 if (!instance) … … 115 166 free(instance); 116 167 } 117 /*----------------------------------------------------------------------------*/118 /** Prepare data and call the right callback.119 *120 * @param[in] instance Batch structure to use.121 * @param[in] data Data to copy to the output buffer.122 * @param[in] size Size of @p data.123 */124 void usb_transfer_batch_finish(125 const usb_transfer_batch_t *instance, const void *data, size_t size)126 {127 assert(instance);128 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.\n",129 instance, USB_TRANSFER_BATCH_ARGS(*instance));130 131 /* NOTE: Only one of these pointers should be set. */132 if (instance->callback_out) {133 /* Check for commands that reset toggle bit */134 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL135 && instance->error == EOK) {136 const usb_target_t target =137 {{ instance->ep->address, instance->ep->endpoint }};138 reset_ep_if_need(fun_to_hcd(instance->fun), target,139 instance->setup_buffer);140 }141 instance->callback_out(instance->fun,142 instance->error, instance->arg);143 }144 145 if (instance->callback_in) {146 /* We care about the data and there are some to copy */147 if (data) {148 const size_t min_size = size < instance->buffer_size149 ? size : instance->buffer_size;150 memcpy(instance->buffer, data, min_size);151 }152 instance->callback_in(instance->fun, instance->error,153 instance->transfered_size, instance->arg);154 }155 }156 168 /** 157 169 * @}
Note:
See TracChangeset
for help on using the changeset viewer.