Changes in / [e8ab32f:c83a55c] in mainline
- Location:
- uspace
- Files:
-
- 37 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/endpoint_list.c
re8ab32f rc83a55c 73 73 * Does not check whether this replaces an existing list. 74 74 */ 75 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next) 75 void endpoint_list_set_next( 76 const endpoint_list_t *instance, const endpoint_list_t *next) 76 77 { 77 78 assert(instance); -
uspace/drv/bus/usb/ohci/endpoint_list.h
re8ab32f rc83a55c 68 68 69 69 int endpoint_list_init(endpoint_list_t *instance, const char *name); 70 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next); 70 void endpoint_list_set_next( 71 const endpoint_list_t *instance, const endpoint_list_t *next); 71 72 void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep); 72 73 void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep); -
uspace/drv/bus/usb/ohci/hc.c
re8ab32f rc83a55c 142 142 if (ret != EOK) { \ 143 143 usb_log_error(message); \ 144 usb_endpoint_manager_unregister_ep( \ 145 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\ 144 usb_endpoint_manager_remove_ep( \ 145 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, \ 146 NULL, NULL);\ 146 147 usb_device_manager_release( \ 147 148 &instance->generic.dev_manager, hub_address); \ … … 150 151 int ret = usb_endpoint_manager_add_ep( 151 152 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, 152 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0 );153 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0, NULL, NULL); 153 154 CHECK_RET_UNREG_RETURN(ret, 154 155 "Failed to register root hub control endpoint: %s.\n", … … 192 193 list_initialize(&instance->pending_batches); 193 194 194 ret =hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,195 hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 195 196 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n",197 str_error(ret));198 197 instance->generic.private_data = instance; 199 198 instance->generic.schedule = hc_schedule; 200 199 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, endpoint_t *ep) 224 { 223 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep) 224 { 225 assert(instance); 226 assert(ep); 227 225 228 endpoint_list_t *list = &instance->lists[ep->transfer_type]; 226 229 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep); 230 assert(list); 231 assert(ohci_ep); 232 227 233 /* Enqueue ep */ 228 234 switch (ep->transfer_type) { … … 247 253 } 248 254 /*----------------------------------------------------------------------------*/ 249 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep) 250 { 255 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep) 256 { 257 assert(instance); 258 assert(ep); 259 251 260 /* Dequeue ep */ 252 261 endpoint_list_t *list = &instance->lists[ep->transfer_type]; 253 262 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep); 263 264 assert(list); 265 assert(ohci_ep); 254 266 switch (ep->transfer_type) { 255 267 case USB_TRANSFER_CONTROL: -
uspace/drv/bus/usb/ohci/hc.h
re8ab32f rc83a55c 86 86 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 87 87 88 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep);89 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep);88 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep); 89 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep); 90 90 91 91 void hc_interrupt(hc_t *instance, uint32_t status); -
uspace/drv/bus/usb/ohci/ohci.c
re8ab32f rc83a55c 89 89 &dev_to_ohci(fun->dev)->hc.generic.dev_manager; 90 90 91 const usb_address_t addr = usb_device_manager_find(manager, handle); 91 const usb_address_t addr = 92 usb_device_manager_find_address(manager, handle); 92 93 if (addr < 0) { 93 94 return addr; -
uspace/drv/bus/usb/ohci/ohci_batch.c
re8ab32f rc83a55c 59 59 free(ohci_batch->tds); 60 60 } 61 usb_transfer_batch_d ispose(ohci_batch->usb_batch);61 usb_transfer_batch_destroy(ohci_batch->usb_batch); 62 62 free32(ohci_batch->device_buffer); 63 63 free(ohci_batch); -
uspace/drv/bus/usb/ohci/ohci_endpoint.c
re8ab32f rc83a55c 62 62 } 63 63 /*----------------------------------------------------------------------------*/ 64 /** Disposes hcd endpoint structure65 *66 * @param[in] hcd_ep endpoint structure67 */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 /*----------------------------------------------------------------------------*/79 64 /** Creates new hcd endpoint representation. 80 65 * 81 66 * @param[in] ep USBD endpoint structure 82 * @return pointer to a new hcd endpoint structure, NULL on failure.67 * @return Error code. 83 68 */ 84 69 int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep) … … 104 89 ed_init(ohci_ep->ed, ep, ohci_ep->td); 105 90 endpoint_set_hc_data( 106 ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set); 107 ohci_ep->hcd = hcd; 91 ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set); 108 92 hc_enqueue_endpoint(hcd->private_data, ep); 109 93 return EOK; 94 } 95 /*----------------------------------------------------------------------------*/ 96 /** Disposes hcd endpoint structure 97 * 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); 110 113 } 111 114 /** -
uspace/drv/bus/usb/ohci/ohci_endpoint.h
re8ab32f rc83a55c 51 51 /** Linked list used by driver software */ 52 52 link_t link; 53 /** Device using this ep */54 hcd_t *hcd;55 53 } ohci_endpoint_t; 56 54 57 55 int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep); 56 void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep); 58 57 59 58 /** Get and convert assigned ohci_endpoint_t structure … … 61 60 * @return Pointer to assigned hcd endpoint structure 62 61 */ 63 static inline ohci_endpoint_t * ohci_endpoint_get( endpoint_t *ep)62 static inline ohci_endpoint_t * ohci_endpoint_get(const endpoint_t *ep) 64 63 { 65 64 assert(ep); -
uspace/drv/bus/usb/ohci/ohci_regs.h
re8ab32f rc83a55c 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbohci hc28 /** @addtogroup drvusbohci 29 29 * @{ 30 30 */ -
uspace/drv/bus/usb/ohci/root_hub.c
re8ab32f rc83a55c 235 235 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 236 236 } 237 usb_transfer_batch_d ispose(request);237 usb_transfer_batch_destroy(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 ispose(256 usb_transfer_batch_destroy( 257 257 instance->unfinished_interrupt_transfer); 258 258 instance->unfinished_interrupt_transfer = NULL; -
uspace/drv/bus/usb/uhci/hc.c
re8ab32f rc83a55c 192 192 "Device registers at %p (%zuB) accessible.\n", io, reg_size); 193 193 194 ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 194 ret = hc_init_mem_structures(instance); 195 CHECK_RET_RETURN(ret, 196 "Failed to initialize UHCI memory structures: %s.\n", 197 str_error(ret)); 198 199 #undef CHECK_RET_RETURN 200 201 hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 195 202 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",197 str_error(ret));198 203 199 204 instance->generic.private_data = instance; 200 205 instance->generic.schedule = hc_schedule; 201 206 instance->generic.ep_add_hook = NULL; 202 203 #undef CHECK_RET_DEST_FUN_RETURN204 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 }213 207 214 208 hc_init_hw(instance); -
uspace/drv/bus/usb/uhci/uhci.c
re8ab32f rc83a55c 101 101 usb_device_manager_t *manager = 102 102 &dev_to_uhci(fun->dev)->hc.generic.dev_manager; 103 const usb_address_t addr = usb_device_manager_find(manager, handle); 103 const usb_address_t addr = 104 usb_device_manager_find_address(manager, handle); 104 105 105 106 if (addr < 0) { -
uspace/drv/bus/usb/uhci/uhci_batch.c
re8ab32f rc83a55c 48 48 { 49 49 if (uhci_batch) { 50 usb_transfer_batch_d ispose(uhci_batch->usb_batch);50 usb_transfer_batch_destroy(uhci_batch->usb_batch); 51 51 free32(uhci_batch->device_buffer); 52 52 free(uhci_batch); -
uspace/drv/bus/usb/usbflbk/main.c
re8ab32f rc83a55c 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 76 86 /** Callback when new device is removed and recognized as gone by DDF. 77 87 * … … 93 103 return EOK; 94 104 } 105 95 106 /** USB fallback driver ops. */ 96 static usb_driver_ops_t usbfallback_driver_ops = {107 static const usb_driver_ops_t usbfallback_driver_ops = { 97 108 .device_add = usbfallback_device_add, 109 .device_rem = usbfallback_device_remove, 98 110 .device_gone = usbfallback_device_gone, 99 111 }; 100 112 101 113 /** USB fallback driver. */ 102 static usb_driver_t usbfallback_driver = {114 static const usb_driver_t usbfallback_driver = { 103 115 .name = NAME, 104 116 .ops = &usbfallback_driver_ops, -
uspace/drv/bus/usb/usbhid/main.c
re8ab32f rc83a55c 46 46 #include "usbhid.h" 47 47 48 /*----------------------------------------------------------------------------*/49 50 48 #define NAME "usbhid" 51 49 … … 67 65 * 68 66 * @param dev Device to add. 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(). 67 * @return Error code. 74 68 */ 75 69 static int usb_hid_try_add_device(usb_device_t *dev) … … 138 132 return EOK; 139 133 } 140 141 134 /*----------------------------------------------------------------------------*/ 142 135 /** … … 146 139 * 147 140 * @param dev Structure representing the new device. 148 * 149 * @retval EOK if successful. 150 * @retval EREFUSED if the device is not supported. 141 * @return Error code. 151 142 */ 152 143 static int usb_hid_device_add(usb_device_t *dev) … … 179 170 return EOK; 180 171 } 181 182 /*----------------------------------------------------------------------------*/ 183 172 /*----------------------------------------------------------------------------*/ 173 /** 174 * Callback for a device about to be removed from the driver. 175 * 176 * @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 184 /** 185 185 * Callback for removing a device from the driver. 186 186 * 187 187 * @param dev Structure representing the device. 188 * 189 * @retval EOK if successful. 190 * @retval EREFUSED if the device is not supported. 188 * @return Error code. 191 189 */ 192 190 static int usb_hid_device_gone(usb_device_t *dev) … … 198 196 if (!tries--) { 199 197 usb_log_error("Can't remove hub, still running.\n"); 200 return E INPROGRESS;198 return EBUSY; 201 199 } 202 200 } … … 207 205 return EOK; 208 206 } 209 207 /*----------------------------------------------------------------------------*/ 210 208 /** USB generic driver callbacks */ 211 static usb_driver_ops_t usb_hid_driver_ops = {209 static const usb_driver_ops_t usb_hid_driver_ops = { 212 210 .device_add = usb_hid_device_add, 211 .device_rem = usb_hid_device_rem, 213 212 .device_gone = usb_hid_device_gone, 214 213 }; 215 216 214 /*----------------------------------------------------------------------------*/ 217 215 /** The driver itself. */ 218 static usb_driver_t usb_hid_driver = {216 static const usb_driver_t usb_hid_driver = { 219 217 .name = NAME, 220 218 .ops = &usb_hid_driver_ops, 221 219 .endpoints = usb_hid_endpoints 222 220 }; 223 224 /*----------------------------------------------------------------------------*/ 225 221 /*----------------------------------------------------------------------------*/ 226 222 int main(int argc, char *argv[]) 227 223 { … … 232 228 return usb_driver_main(&usb_hid_driver); 233 229 } 234 235 230 /** 236 231 * @} -
uspace/drv/bus/usb/usbhub/main.c
re8ab32f rc83a55c 47 47 * For more information see section 11.15.1 of USB 1.1 specification. 48 48 */ 49 static usb_endpoint_description_t hub_status_change_endpoint_description = { 49 static const usb_endpoint_description_t hub_status_change_endpoint_description = 50 { 50 51 .transfer_type = USB_TRANSFER_INTERRUPT, 51 52 .direction = USB_DIRECTION_IN, … … 56 57 }; 57 58 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 = { 59 /** USB hub driver operations. */ 60 static const usb_driver_ops_t usb_hub_driver_ops = { 64 61 .device_add = usb_hub_device_add, 62 // .device_rem = usb_hub_device_remove, 65 63 .device_gone = usb_hub_device_gone, 66 64 }; … … 72 70 }; 73 71 /** Static usb hub driver information. */ 74 static usb_driver_t usb_hub_driver = {72 static const usb_driver_t usb_hub_driver = { 75 73 .name = NAME, 76 74 .ops = &usb_hub_driver_ops, 77 75 .endpoints = usb_hub_endpoints 78 76 }; 79 80 77 81 78 int main(int argc, char *argv[]) -
uspace/drv/bus/usb/usbhub/port.h
re8ab32f rc83a55c 44 44 /** Information about single port on a hub. */ 45 45 typedef struct { 46 /* Port number as reporteed in descriptors. */ 46 47 size_t port_number; 48 /** Device communication pipe. */ 47 49 usb_pipe_t *control_pipe; 48 50 /** Mutex needed not only by CV for checking port reset. */ -
uspace/drv/bus/usb/usbhub/usbhub.c
re8ab32f rc83a55c 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);71 70 static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev); 72 71 static void usb_hub_over_current(const usb_hub_dev_t *hub_dev, … … 75 74 static void usb_hub_polling_terminated_callback(usb_device_t *device, 76 75 bool was_error, void *data); 77 /** 78 * Initialize hub device driver fibril 76 77 /** 78 * Initialize hub device driver structure. 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 information 83 * @return error code 84 */ 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 information 168 * @return error code 169 */ 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 devices 82 205 * @param usb_dev generic usb device information 83 206 * @return error code … … 121 244 } 122 245 /*----------------------------------------------------------------------------*/ 123 /**124 * Initialize hub device driver fibril125 *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 information129 * @return error code130 */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 /*----------------------------------------------------------------------------*/207 246 /** Callback for polling hub for changes. 208 247 * … … 243 282 /*----------------------------------------------------------------------------*/ 244 283 /** 245 * create usb_hub_dev_t structure246 *247 * Does only basic copying of known information into new structure.248 * @param usb_dev usb device structure249 * @return basic usb_hub_dev_t structure250 */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 /**271 284 * Load hub-specific information into hub_dev structure and process if needed 272 285 * … … 311 324 } 312 325 313 const bool is_power_switched =326 hub_dev->power_switched = 314 327 !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG); 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 } 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; 334 352 } 335 353 } 336 } else {337 usb_log_debug("Power not switched, ports always powered\n");338 354 } 339 355 return EOK; … … 402 418 usb_log_warning("Detected hub over-current condition, " 403 419 "all ports should be powered off."); 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 } 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 428 441 } 429 442 /*----------------------------------------------------------------------------*/ … … 461 474 if (status & USB_HUB_STATUS_C_OVER_CURRENT) { 462 475 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 } 463 485 } 464 486 … … 477 499 * Just ACK the change. 478 500 */ 479 const int opResult = usb_request_clear_feature(501 const int ret = usb_request_clear_feature( 480 502 control_pipe, USB_REQUEST_TYPE_CLASS, 481 503 USB_REQUEST_RECIPIENT_DEVICE, 482 504 USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0); 483 505 if (opResult != EOK) { 484 usb_log_error( 485 "Failed to clear hub power change flag: %s.\n", 486 str_error(opResult)); 506 usb_log_error("Failed to clear hub power change " 507 "flag: %s.\n", str_error(ret)); 487 508 } 488 509 } -
uspace/drv/bus/usb/usbhub/usbhub.h
re8ab32f rc83a55c 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; 79 83 }; 80 84 81 85 int usb_hub_device_add(usb_device_t *usb_dev); 86 int usb_hub_device_remove(usb_device_t *usb_dev); 82 87 int usb_hub_device_gone(usb_device_t *usb_dev); 83 88 -
uspace/drv/bus/usb/usbmast/main.c
re8ab32f rc83a55c 55 55 #define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe) 56 56 57 static usb_endpoint_description_t bulk_in_ep = {57 static const 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 usb_endpoint_description_t bulk_out_ep = {65 static const 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 108 119 /** Callback when new device is attached and recognized as a mass storage. 109 120 * 110 * @param dev Representation of a theUSB device.121 * @param dev Representation of USB device. 111 122 * @return Error code. 112 123 */ … … 336 347 337 348 /** USB mass storage driver ops. */ 338 static usb_driver_ops_t usbmast_driver_ops = {349 static const usb_driver_ops_t usbmast_driver_ops = { 339 350 .device_add = usbmast_device_add, 351 .device_rem = usbmast_device_remove, 340 352 .device_gone = usbmast_device_gone, 341 353 }; 342 354 343 355 /** USB mass storage driver. */ 344 static usb_driver_t usbmast_driver = {356 static const usb_driver_t usbmast_driver = { 345 357 .name = NAME, 346 358 .ops = &usbmast_driver_ops, -
uspace/drv/bus/usb/usbmid/main.c
re8ab32f rc83a55c 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); 67 79 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 */ 68 97 static int usbmid_device_gone(usb_device_t *dev) 69 98 { … … 86 115 list_remove(item); 87 116 88 usbmid_interface_t *iface = list_get_instance(item, 89 usbmid_interface_t, link); 117 usbmid_interface_t *iface = usbmid_interface_from_link(item); 90 118 91 119 usb_log_info("Removing child for interface %d (%s).\n", … … 107 135 108 136 /** USB MID driver ops. */ 109 static usb_driver_ops_t mid_driver_ops = {137 static const usb_driver_ops_t mid_driver_ops = { 110 138 .device_add = usbmid_device_add, 139 .device_rem = usbmid_device_remove, 111 140 .device_gone = usbmid_device_gone, 112 141 }; 113 142 114 143 /** USB MID driver. */ 115 static usb_driver_t mid_driver = {144 static const usb_driver_t mid_driver = { 116 145 .name = NAME, 117 146 .ops = &mid_driver_ops, -
uspace/drv/bus/usb/usbmid/usbmid.h
re8ab32f rc83a55c 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 73 78 #endif 74 79 /** -
uspace/drv/bus/usb/vhc/connhost.c
re8ab32f rc83a55c 104 104 { 105 105 VHC_DATA(vhc, fun); 106 bool found = 107 usb_device_manager_find_by_address(&vhc->dev_manager, address, handle); 108 return found ? EOK : ENOENT; 106 return usb_device_manager_get_info_by_address( 107 &vhc->dev_manager, address, handle, NULL); 109 108 } 110 109 … … 141 140 size_t max_packet_size, unsigned int interval) 142 141 { 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; 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 159 148 } 160 149 … … 172 161 VHC_DATA(vhc, fun); 173 162 174 int rc = usb_endpoint_manager_ unregister_ep(&vhc->ep_manager,175 address, endpoint, direction );163 int rc = usb_endpoint_manager_remove_ep(&vhc->ep_manager, 164 address, endpoint, direction, NULL, NULL); 176 165 177 166 return rc; … … 414 403 VHC_DATA(vhc, fun); 415 404 416 endpoint_t *ep = usb_endpoint_manager_ get_ep(&vhc->ep_manager,417 target.address, target.endpoint, USB_DIRECTION_IN , NULL);405 endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager, 406 target.address, target.endpoint, USB_DIRECTION_IN); 418 407 if (ep == NULL) { 419 408 return ENOENT; … … 456 445 VHC_DATA(vhc, fun); 457 446 458 endpoint_t *ep = usb_endpoint_manager_ get_ep(&vhc->ep_manager,459 target.address, target.endpoint, USB_DIRECTION_OUT , NULL);447 endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager, 448 target.address, target.endpoint, USB_DIRECTION_OUT); 460 449 if (ep == NULL) { 461 450 return ENOENT; … … 518 507 519 508 usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle); 520 usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle); 509 const usb_address_t addr = 510 usb_device_manager_find_address(&vhc->dev_manager, handle); 521 511 if (addr < 0) { 522 512 return addr; -
uspace/lib/usbdev/include/usb/dev/driver.h
re8ab32f rc83a55c 161 161 } usb_driver_t; 162 162 163 int usb_driver_main( usb_driver_t *);163 int usb_driver_main(const 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_ create(ddf_dev_t *, const usb_endpoint_description_t **,174 usb_device_t **, const char **);173 int usb_device_init(usb_device_t *, ddf_dev_t *, 174 const usb_endpoint_description_t **, const char **); 175 175 void usb_device_deinit(usb_device_t *); 176 176 177 void * usb_device_data_alloc(usb_device_t *, size_t); 177 178 … … 179 180 int usb_alternate_interfaces_create(const uint8_t *, size_t, int, 180 181 usb_alternate_interfaces_t **); 181 182 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *); 182 183 #endif 183 184 /** -
uspace/lib/usbdev/src/altiface.c
re8ab32f rc83a55c 98 98 assert(config_descr_size > 0); 99 99 100 *alternates_ptr = NULL; 100 101 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 108 107 if (alternates == NULL) { 109 108 return ENOMEM; … … 119 118 } 120 119 121 alternates->alternatives = malloc(alternates->alternative_count122 *sizeof(usb_alternate_interface_descriptors_t));120 alternates->alternatives = calloc(alternates->alternative_count, 121 sizeof(usb_alternate_interface_descriptors_t)); 123 122 if (alternates->alternatives == NULL) { 124 123 free(alternates); … … 176 175 } 177 176 178 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 } 179 184 /** 180 185 * @} -
uspace/lib/usbdev/src/devdrv.c
re8ab32f rc83a55c 64 64 * @return Task exit status. 65 65 */ 66 int usb_driver_main( usb_driver_t *drv)66 int usb_driver_main(const usb_driver_t *drv) 67 67 { 68 68 assert(drv != NULL); … … 140 140 assert(driver->ops->device_add); 141 141 142 int rc; 143 144 usb_device_t *dev = NULL; 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 } 145 148 const char *err_msg = NULL; 146 rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);147 if (rc != EOK) { 148 usb_log_error("USB device `%s' creationfailed (%s): %s.\n",149 int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg); 150 if (rc != EOK) { 151 usb_log_error("USB device `%s' init failed (%s): %s.\n", 149 152 gen_dev->name, err_msg, str_error(rc)); 150 153 return rc; 151 154 } 152 gen_dev->driver_data = dev;153 155 154 156 rc = driver->ops->device_add(dev); … … 516 518 517 519 518 /** Create new instance of USB device. 519 * 520 /** Initialize new instance of USB device. 521 * 522 * @param[in] usb_dev Pointer to the new device. 520 523 * @param[in] ddf_dev Generic DDF device backing the USB one. 521 524 * @param[in] endpoints NULL terminated array of endpoints (NULL for none). 522 * @param[out] dev_ptr Where to store pointer to the new device.523 525 * @param[out] errstr_ptr Where to store description of context 524 526 * (in case error occurs). 525 527 * @return Error code. 526 528 */ 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); 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); 532 533 assert(ddf_dev != NULL); 533 534 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; 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; 551 541 552 542 /* Initialize backing wire and control pipe. */ 553 rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);543 int rc = init_wire_and_ctrl_pipe(usb_dev, errstr_ptr); 554 544 if (rc != EOK) { 555 545 return rc; … … 557 547 558 548 /* Get our interface. */ 559 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);549 usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev); 560 550 561 551 /* Retrieve standard descriptors. */ 562 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 563 &dev->descriptors); 564 if (rc != EOK) { 552 rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe, 553 &usb_dev->descriptors); 554 if (rc != EOK) { 555 /* Nothing allocated, nothing to free. */ 565 556 *errstr_ptr = "descriptor retrieval"; 566 557 return rc; 567 558 } 568 559 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) { 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); 580 572 *errstr_ptr = "pipes initialization"; 581 573 return rc; … … 583 575 584 576 *errstr_ptr = NULL; 585 *dev_ptr = dev;586 577 587 578 return EOK; 588 579 } 589 580 590 /** Destroyinstance of a USB device.581 /** Clean instance of a USB device. 591 582 * 592 583 * @param dev Device to be de-initialized. … … 596 587 void usb_device_deinit(usb_device_t *dev) 597 588 { 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); 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 } 611 597 } 612 598 -
uspace/lib/usbhost/include/usb/host/endpoint.h
re8ab32f rc83a55c 36 36 #define LIBUSBHOST_HOST_ENDPOINT_H 37 37 38 #include <assert.h>39 38 #include <bool.h> 40 39 #include <adt/list.h> 41 40 #include <fibril_synch.h> 42 43 41 #include <usb/usb.h> 44 42 43 /** Host controller side endpoint structure. */ 45 44 typedef struct endpoint { 45 /** Part of linked list. */ 46 link_t link; 47 /** USB address. */ 46 48 usb_address_t address; 49 /** USB endpoint number. */ 47 50 usb_endpoint_t endpoint; 51 /** Communication direction. */ 48 52 usb_direction_t direction; 53 /** USB transfer type. */ 49 54 usb_transfer_type_t transfer_type; 55 /** Communication speed. */ 50 56 usb_speed_t speed; 57 /** Maximum size of data packets. */ 51 58 size_t max_packet_size; 59 /** Necessary bandwidth. */ 60 size_t bandwidth; 61 /** Value of the toggle bit. */ 52 62 unsigned toggle:1; 63 /** True if there is a batch using this scheduled for this endpoint. */ 64 volatile bool active; 65 /** Protects resources and active status changes. */ 53 66 fibril_mutex_t guard; 67 /** Signals change of active status. */ 54 68 fibril_condvar_t avail; 55 volatile bool active; 56 void (*destroy_hook)(struct endpoint *); 69 /** Optional device specific data. */ 57 70 struct { 71 /** Device specific data. */ 58 72 void *data; 73 /** Callback to get the value of toggle bit. */ 59 74 int (*toggle_get)(void *); 75 /** Callback to set the value of toggle bit. */ 60 76 void (*toggle_set)(void *, int); 61 77 } hc_data; 62 78 } endpoint_t; 63 79 64 endpoint_t * endpoint_ get(usb_address_t address, usb_endpoint_t endpoint,80 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 65 81 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 66 size_t max_packet_size); 67 82 size_t max_packet_size, size_t bw); 68 83 void endpoint_destroy(endpoint_t *instance); 69 84 70 85 void endpoint_set_hc_data(endpoint_t *instance, 71 void *data, void (*destroy_hook)(endpoint_t *), 72 int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 73 86 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 74 87 void endpoint_clear_hc_data(endpoint_t *instance); 75 88 76 89 void endpoint_use(endpoint_t *instance); 77 78 90 void endpoint_release(endpoint_t *instance); 79 91 80 92 int endpoint_toggle_get(endpoint_t *instance); 81 82 93 void endpoint_toggle_set(endpoint_t *instance, int toggle); 83 94 84 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 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 } 85 103 #endif 86 104 /** -
uspace/lib/usbhost/include/usb/host/hcd.h
re8ab32f rc83a55c 37 37 38 38 #include <assert.h> 39 #include <usbhc_iface.h> 40 39 41 #include <usb/host/usb_device_manager.h> 40 42 #include <usb/host/usb_endpoint_manager.h> 41 43 #include <usb/host/usb_transfer_batch.h> 42 #include <usbhc_iface.h>43 44 44 45 typedef struct hcd hcd_t; 45 46 47 /** Generic host controller driver structure. */ 46 48 struct hcd { 49 /** Device manager storing handles and addresses. */ 47 50 usb_device_manager_t dev_manager; 51 /** Endpoint manager. */ 48 52 usb_endpoint_manager_t ep_manager; 53 54 /** Device specific driver data. */ 49 55 void *private_data; 50 56 /** Transfer scheduling, implement in device driver. */ 51 57 int (*schedule)(hcd_t *, usb_transfer_batch_t *); 58 /** Hook called upon registering new endpoint. */ 52 59 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 *); 53 62 }; 54 63 /*----------------------------------------------------------------------------*/ 55 static inline int hcd_init(hcd_t *hcd, size_t bandwidth, 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, 56 71 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)) 57 72 { 58 73 assert(hcd); 59 74 usb_device_manager_init(&hcd->dev_manager); 60 return usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count); 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; 61 80 } 62 81 /*----------------------------------------------------------------------------*/ 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)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]) 70 89 { 71 90 assert(hcd); 72 usb_endpoint_manager_reset_ if_need(91 usb_endpoint_manager_reset_eps_if_need( 73 92 &hcd->ep_manager, target, (const uint8_t *)setup_data); 74 93 } 75 94 /*----------------------------------------------------------------------------*/ 76 static inline hcd_t * fun_to_hcd(ddf_fun_t *fun) 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) 77 100 { 78 101 assert(fun); -
uspace/lib/usbhost/include/usb/host/usb_device_manager.h
re8ab32f rc83a55c 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 58 51 /** Host controller device manager. 59 * You shall not access members directly but only using functions below.52 * You shall not access members directly. 60 53 */ 61 54 typedef struct { 62 struct usb_device_info devices[USB_ADDRESS_COUNT]; 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]; 63 61 fibril_mutex_t guard; 62 /** The last reserved address */ 64 63 usb_address_t last_address; 65 64 } usb_device_manager_t; … … 70 69 usb_device_manager_t *instance, usb_speed_t speed); 71 70 72 voidusb_device_manager_bind(usb_device_manager_t *instance,71 int usb_device_manager_bind(usb_device_manager_t *instance, 73 72 usb_address_t address, devman_handle_t handle); 74 73 75 voidusb_device_manager_release(usb_device_manager_t *instance,74 int usb_device_manager_release(usb_device_manager_t *instance, 76 75 usb_address_t address); 77 76 78 usb_address_t usb_device_manager_find (usb_device_manager_t *instance,77 usb_address_t usb_device_manager_find_address(usb_device_manager_t *instance, 79 78 devman_handle_t handle); 80 79 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); 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); 86 82 #endif 87 83 /** -
uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
re8ab32f rc83a55c 40 40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 41 41 42 #include <stdlib.h> 43 #include <adt/hash_table.h> 42 #include <adt/list.h> 44 43 #include <fibril_synch.h> 45 44 #include <usb/usb.h> 45 46 46 #include <usb/host/endpoint.h> 47 47 48 #define BANDWIDTH_TOTAL_USB11 12000000 48 /** Bytes per second in FULL SPEED */ 49 #define BANDWIDTH_TOTAL_USB11 (12000000 / 8) 50 /** 90% of total bandwidth is available for periodic transfers */ 49 51 #define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9) 52 /** 16 addresses per list */ 53 #define ENDPOINT_LIST_COUNT 8 50 54 55 /** Endpoint management structure */ 51 56 typedef struct usb_endpoint_manager { 52 hash_table_t ep_table; 57 /** Store endpoint_t instances */ 58 list_t endpoint_lists[ENDPOINT_LIST_COUNT]; 59 /** Prevents races accessing lists */ 53 60 fibril_mutex_t guard; 61 /** Size of the bandwidth pool */ 54 62 size_t free_bw; 63 /** Use this function to count bw required by EP */ 55 64 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t); 56 65 } usb_endpoint_manager_t; … … 63 72 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)); 64 73 65 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance); 74 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance, 75 usb_target_t target, const uint8_t data[8]); 66 76 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, 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, 71 82 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction); 72 83 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, 84 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 82 85 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 83 86 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size, 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; 87 size_t data_size, int (*callback)(endpoint_t *, void *), void *arg); 90 88 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 } 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); 98 92 #endif 99 93 /** 100 94 * @} 101 95 */ 102 -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
re8ab32f rc83a55c 43 43 #define USB_SETUP_PACKET_SIZE 8 44 44 45 typedef struct usb_transfer_batch usb_transfer_batch_t;46 45 /** Structure stores additional data needed for communication with EP */ 47 struct usb_transfer_batch {46 typedef struct usb_transfer_batch { 48 47 /** Endpoint used for communication */ 49 48 endpoint_t *ep; … … 77 76 /** Callback to properly remove driver data during destruction */ 78 77 void (*private_data_dtor)(void *p_data); 79 } ;78 } usb_transfer_batch_t; 80 79 81 80 /** Printf formatting string for dumping usb_transfer_batch_t. */ … … 93 92 94 93 95 usb_transfer_batch_t * usb_transfer_batch_ get(94 usb_transfer_batch_t * usb_transfer_batch_create( 96 95 endpoint_t *ep, 97 96 char *buffer, … … 105 104 void (*private_data_dtor)(void *p_data) 106 105 ); 106 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance); 107 107 108 void usb_transfer_batch_finish( usb_transfer_batch_t *instance,108 void usb_transfer_batch_finish(const 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 }125 110 /*----------------------------------------------------------------------------*/ 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. 111 /** Override error value and finishes transfer. 139 112 * 140 113 * @param[in] instance Batch structure to use. … … 151 124 } 152 125 /*----------------------------------------------------------------------------*/ 153 /** Helper function, determines batch direction absed on the present callbacks154 * @param[in] instance Batch structure to use .126 /** Determine batch direction based on the callbacks present 127 * @param[in] instance Batch structure to use, non-null. 155 128 * @return USB_DIRECTION_IN, or USB_DIRECTION_OUT. 156 129 */ -
uspace/lib/usbhost/src/endpoint.c
re8ab32f rc83a55c 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 /** @addtogroup drvusbuhcihc 28 /** @addtogroup libusbhost 30 29 * @{ 31 30 */ … … 39 38 #include <usb/host/endpoint.h> 40 39 41 endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint, 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, 42 51 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 43 size_t max_packet_size )52 size_t max_packet_size, size_t bw) 44 53 { 45 54 endpoint_t *instance = malloc(sizeof(endpoint_t)); … … 51 60 instance->speed = speed; 52 61 instance->max_packet_size = max_packet_size; 62 instance->bandwidth = bw; 53 63 instance->toggle = 0; 54 64 instance->active = false; 55 instance->destroy_hook = NULL;56 65 instance->hc_data.data = NULL; 57 66 instance->hc_data.toggle_get = NULL; 58 67 instance->hc_data.toggle_set = NULL; 68 link_initialize(&instance->link); 59 69 fibril_mutex_initialize(&instance->guard); 60 70 fibril_condvar_initialize(&instance->avail); 61 endpoint_clear_hc_data(instance);62 71 } 63 72 return instance; 64 73 } 65 74 /*----------------------------------------------------------------------------*/ 75 /** Properly dispose of endpoint_t structure. 76 * @param instance endpoint_t structure. 77 */ 66 78 void endpoint_destroy(endpoint_t *instance) 67 79 { 68 80 assert(instance); 81 //TODO: Do something about waiting fibrils. 69 82 assert(!instance->active); 70 if (instance->hc_data.data) { 71 assert(instance->destroy_hook); 72 instance->destroy_hook(instance); 73 } 83 assert(instance->hc_data.data == NULL); 74 84 free(instance); 75 85 } 76 86 /*----------------------------------------------------------------------------*/ 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 */ 77 93 void endpoint_set_hc_data(endpoint_t *instance, 78 void *data, void (*destroy_hook)(endpoint_t *), 79 int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 94 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 80 95 { 81 96 assert(instance); 82 instance->destroy_hook = destroy_hook;97 fibril_mutex_lock(&instance->guard); 83 98 instance->hc_data.data = data; 84 99 instance->hc_data.toggle_get = toggle_get; 85 100 instance->hc_data.toggle_set = toggle_set; 101 fibril_mutex_unlock(&instance->guard); 86 102 } 87 103 /*----------------------------------------------------------------------------*/ 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 */ 88 108 void endpoint_clear_hc_data(endpoint_t *instance) 89 109 { 90 110 assert(instance); 91 instance->destroy_hook = NULL;111 fibril_mutex_lock(&instance->guard); 92 112 instance->hc_data.data = NULL; 93 113 instance->hc_data.toggle_get = NULL; 94 114 instance->hc_data.toggle_set = NULL; 115 fibril_mutex_unlock(&instance->guard); 95 116 } 96 117 /*----------------------------------------------------------------------------*/ 118 /** Mark the endpoint as active and block access for further fibrils. 119 * @param instance endpoint_t structure. 120 */ 97 121 void endpoint_use(endpoint_t *instance) 98 122 { … … 105 129 } 106 130 /*----------------------------------------------------------------------------*/ 131 /** Mark the endpoint as inactive and allow access for further fibrils. 132 * @param instance endpoint_t structure. 133 */ 107 134 void endpoint_release(endpoint_t *instance) 108 135 { … … 114 141 } 115 142 /*----------------------------------------------------------------------------*/ 143 /** Get the value of toggle bit. 144 * @param instance endpoint_t structure. 145 * @note Will use provided hook. 146 */ 116 147 int endpoint_toggle_get(endpoint_t *instance) 117 148 { 118 149 assert(instance); 150 fibril_mutex_lock(&instance->guard); 119 151 if (instance->hc_data.toggle_get) 120 152 instance->toggle = 121 153 instance->hc_data.toggle_get(instance->hc_data.data); 122 return (int)instance->toggle; 154 const int ret = instance->toggle; 155 fibril_mutex_unlock(&instance->guard); 156 return ret; 123 157 } 124 158 /*----------------------------------------------------------------------------*/ 159 /** Set the value of toggle bit. 160 * @param instance endpoint_t structure. 161 * @note Will use provided hook. 162 */ 125 163 void endpoint_toggle_set(endpoint_t *instance, int toggle) 126 164 { 127 165 assert(instance); 128 166 assert(toggle == 0 || toggle == 1); 167 fibril_mutex_lock(&instance->guard); 168 instance->toggle = toggle; 129 169 if (instance->hc_data.toggle_set) 130 170 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 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); 171 fibril_mutex_unlock(&instance->guard); 140 172 } 141 173 /** -
uspace/lib/usbhost/src/iface.c
re8ab32f rc83a55c 49 49 assert(hcd); 50 50 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); 51 endpoint_t *ep = usb_endpoint_manager_find_ep(&hcd->ep_manager, 52 target.address, target.endpoint, direction); 56 53 if (ep == NULL) { 57 54 usb_log_error("Endpoint(%d:%d) not registered for %s.\n", … … 65 62 const size_t bw = bandwidth_count_usb11( 66 63 ep->speed, ep->transfer_type, size, ep->max_packet_size); 67 if (res_bw < bw) { 64 /* Check if we have enough bandwidth reserved */ 65 if (ep->bandwidth < bw) { 68 66 usb_log_error("Endpoint(%d:%d) %s needs %zu bw " 69 67 "but only %zu is reserved.\n", 70 target.address, target.endpoint, name, bw, res_bw);68 ep->address, ep->endpoint, name, bw, ep->bandwidth); 71 69 return ENOSPC; 72 70 } … … 78 76 /* No private data and no private data dtor */ 79 77 usb_transfer_batch_t *batch = 80 usb_transfer_batch_ get(ep, data, size, setup_data,78 usb_transfer_batch_create(ep, data, size, setup_data, 81 79 in, out, arg, fun, NULL, NULL); 82 80 if (!batch) { … … 84 82 } 85 83 86 ret = hcd->schedule(hcd, batch);84 const int ret = hcd->schedule(hcd, batch); 87 85 if (ret != EOK) 88 usb_transfer_batch_d ispose(batch);86 usb_transfer_batch_destroy(batch); 89 87 90 88 return ret; … … 130 128 131 129 usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle); 132 usb_device_manager_bind(&hcd->dev_manager, address, handle); 133 return EOK; 130 return usb_device_manager_bind(&hcd->dev_manager, address, handle); 134 131 } 135 132 /*----------------------------------------------------------------------------*/ … … 147 144 hcd_t *hcd = fun_to_hcd(fun); 148 145 assert(hcd); 149 const bool found = 150 usb_device_manager_find_by_address(&hcd->dev_manager, address, handle); 151 return found ? EOK : ENOENT; 146 return usb_device_manager_get_info_by_address( 147 &hcd->dev_manager, address, handle, NULL); 152 148 } 153 149 /*----------------------------------------------------------------------------*/ … … 166 162 usb_device_manager_release(&hcd->dev_manager, address); 167 163 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); 168 183 } 169 184 /*----------------------------------------------------------------------------*/ … … 180 195 /* Default address is not bound or registered, 181 196 * thus it does not provide speed info. */ 182 const usb_speed_t speed = (address == 0) ? ep_speed : 183 usb_device_manager_get_speed(&hcd->dev_manager, address); 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); 184 202 185 203 usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n", … … 188 206 max_packet_size, interval); 189 207 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; 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); 209 211 } 210 212 /*----------------------------------------------------------------------------*/ … … 218 220 usb_log_debug("Unregister endpoint %d:%d %s.\n", 219 221 address, endpoint, usb_str_direction(direction)); 220 return usb_endpoint_manager_ unregister_ep(&hcd->ep_manager, address,221 endpoint, direction );222 return usb_endpoint_manager_remove_ep(&hcd->ep_manager, address, 223 endpoint, direction, unregister_helper, hcd); 222 224 } 223 225 /*----------------------------------------------------------------------------*/ -
uspace/lib/usbhost/src/usb_device_manager.c
re8ab32f rc83a55c 38 38 #include <usb/host/usb_device_manager.h> 39 39 40 /*----------------------------------------------------------------------------*/41 40 /** Initialize device manager structure. 42 41 * … … 48 47 { 49 48 assert(instance); 50 unsigned i = 0; 51 for (; i < USB_ADDRESS_COUNT; ++i) { 49 for (unsigned i = 0; i < USB_ADDRESS_COUNT; ++i) { 52 50 instance->devices[i].occupied = false; 53 51 instance->devices[i].handle = 0; … … 77 75 ++new_address; 78 76 if (new_address > USB11_ADDRESS_MAX) 79 new_address = 1; 77 new_address = 1; // NOTE it should be safe to put 0 here 78 // TODO Use mod 80 79 if (new_address == instance->last_address) { 81 80 fibril_mutex_unlock(&instance->guard); … … 86 85 assert(new_address != USB_ADDRESS_DEFAULT); 87 86 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 */ 103 void usb_device_manager_bind(usb_device_manager_t *instance, 102 * @return Error code. 103 */ 104 int usb_device_manager_bind(usb_device_manager_t *instance, 104 105 usb_address_t address, devman_handle_t handle) 105 106 { 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 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 } 113 123 instance->devices[address].handle = handle; 114 124 fibril_mutex_unlock(&instance->guard); 125 return EOK; 115 126 } 116 127 /*----------------------------------------------------------------------------*/ … … 119 130 * @param[in] instance Device manager structure to use. 120 131 * @param[in] address Device address 121 */ 122 void usb_device_manager_release( 132 * @return Error code. 133 */ 134 int usb_device_manager_release( 123 135 usb_device_manager_t *instance, usb_address_t address) 124 136 { 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); 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 } 131 147 132 148 instance->devices[address].occupied = false; 133 fibril_mutex_unlock(&instance->guard); 149 instance->devices[address].handle = 0; 150 fibril_mutex_unlock(&instance->guard); 151 return EOK; 134 152 } 135 153 /*----------------------------------------------------------------------------*/ … … 140 158 * @return USB Address, or error code. 141 159 */ 142 usb_address_t usb_device_manager_find (160 usb_address_t usb_device_manager_find_address( 143 161 usb_device_manager_t *instance, devman_handle_t handle) 144 162 { 145 163 assert(instance); 146 164 fibril_mutex_lock(&instance->guard); 147 usb_address_t address = 1;148 while (address <= USB11_ADDRESS_MAX){165 for (usb_address_t address = 1; address <= USB11_ADDRESS_MAX; ++address) 166 { 149 167 if (instance->devices[address].handle == handle) { 150 168 assert(instance->devices[address].occupied); … … 152 170 return address; 153 171 } 154 ++address;155 172 } 156 173 fibril_mutex_unlock(&instance->guard); 157 174 return ENOENT; 158 175 } 159 160 /** Find devman handle a ssigned to USB address.161 * Intentionally refuse to find handle ofdefault address.176 /*----------------------------------------------------------------------------*/ 177 /** Find devman handle and speed assigned to USB address. 178 * Intentionally refuse to work on default address. 162 179 * 163 180 * @param[in] instance Device manager structure to use. 164 181 * @param[in] address Address the caller wants to find. 165 182 * @param[out] handle Where to store found handle. 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);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); 173 190 if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) { 174 fibril_mutex_unlock(&instance->guard); 175 return false; 176 } 191 return EINVAL; 192 } 193 194 fibril_mutex_lock(&instance->guard); 177 195 if (!instance->devices[address].occupied) { 178 196 fibril_mutex_unlock(&instance->guard); 179 return false;197 return ENOENT; 180 198 } 181 199 … … 183 201 *handle = instance->devices[address].handle; 184 202 } 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; 203 if (speed != NULL) { 204 *speed = instance->devices[address].speed; 205 } 206 207 fibril_mutex_unlock(&instance->guard); 208 return EOK; 205 209 } 206 210 /** -
uspace/lib/usbhost/src/usb_endpoint_manager.c
re8ab32f rc83a55c 34 34 #include <usb/host/usb_endpoint_manager.h> 35 35 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 /*----------------------------------------------------------------------------*/ 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 */ 97 100 size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type, 98 101 size_t size, size_t max_packet_size) … … 106 109 const unsigned packet_count = 107 110 (size + max_packet_size - 1) / max_packet_size; 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 */ 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 */ 111 113 /* NOTE: All data packets will be considered to be max_packet_size */ 112 114 switch (speed) … … 137 139 } 138 140 /*----------------------------------------------------------------------------*/ 141 /** Initialize to default state. 142 * You need to provide valid bw_count function if you plan to use 143 * 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 */ 139 150 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 140 151 size_t available_bandwidth, … … 145 156 instance->free_bw = available_bandwidth; 146 157 instance->bw_count = bw_count; 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); 196 return EOK; 197 } 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; 158 for (unsigned i = 0; i < ENDPOINT_LIST_COUNT; ++i) { 159 list_initialize(&instance->endpoint_lists[i]); 160 } 161 return EOK; 244 162 } 245 163 /*----------------------------------------------------------------------------*/ 246 164 /** Check setup packet data for signs of toggle reset. 247 165 * 248 * @param[in] instance Device keeper structure to use.166 * @param[in] instance usb_endpoint_manager structure, non-null. 249 167 * @param[in] target Device to receive setup packet. 250 168 * @param[in] data Setup packet data. 251 169 * 252 * Really ugly one. 253 */ 254 void usb_endpoint_manager_reset_ if_need(255 usb_ endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)170 * Really ugly one. Resets toggle bit on all endpoints that need it. 171 */ 172 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance, 173 usb_target_t target, const uint8_t data[8]) 256 174 { 257 175 assert(instance); … … 267 185 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */ 268 186 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 187 fibril_mutex_lock(&instance->guard); 269 188 /* endpoint number is < 16, thus first byte is enough */ 270 usb_target_t reset_target = 271 { .address = target.address, data[4] }; 272 fibril_mutex_lock(&instance->guard); 273 hash_table_apply(&instance->ep_table, 274 node_toggle_reset_filtered, &reset_target); 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 } 275 196 fibril_mutex_unlock(&instance->guard); 276 197 } … … 279 200 case 0x9: /* Set Configuration */ 280 201 case 0x11: /* Set Interface */ 281 /* Recipient must be device */ 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. */ 282 205 if ((data[0] & 0xf) == 0) { 283 usb_target_t reset_target =284 { .address = target.address, 0 };285 206 fibril_mutex_lock(&instance->guard); 286 hash_table_apply(&instance->ep_table, 287 node_toggle_reset_filtered, &reset_target); 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 } 288 213 fibril_mutex_unlock(&instance->guard); 289 214 } … … 291 216 } 292 217 } 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 address 281 */ 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
re8ab32f rc83a55c 37 37 #include <usb/usb.h> 38 38 #include <usb/debug.h> 39 39 40 #include <usb/host/usb_transfer_batch.h> 40 41 #include <usb/host/hcd.h> 41 42 42 usb_transfer_batch_t * usb_transfer_batch_get( 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( 43 56 endpoint_t *ep, 44 57 char *buffer, … … 53 66 ) 54 67 { 68 if (func_in == NULL && func_out == NULL) 69 return NULL; 70 if (func_in != NULL && func_out != NULL) 71 return NULL; 72 55 73 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 56 74 if (instance) { … … 78 96 } 79 97 /*----------------------------------------------------------------------------*/ 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_OUT93 && 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 appropriate109 * 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_CONTROL138 && 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 /*----------------------------------------------------------------------------*/149 98 /** Correctly dispose all used data structures. 150 99 * 151 100 * @param[in] instance Batch structure to use. 152 101 */ 153 void usb_transfer_batch_d ispose(usb_transfer_batch_t *instance)102 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance) 154 103 { 155 104 if (!instance) … … 166 115 free(instance); 167 116 } 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_CONTROL 135 && 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_size 149 ? 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 } 168 156 /** 169 157 * @} -
uspace/srv/fs/mfs/mfs_ops.c
re8ab32f rc83a55c 384 384 if (flags & L_DIRECTORY) { 385 385 ino_i->i_mode = S_IFDIR; 386 ino_i->i_nlinks = 2; /* This accounts for the '.' dentry */387 } else {386 ino_i->i_nlinks = 1; /* This accounts for the '.' dentry */ 387 } else 388 388 ino_i->i_mode = S_IFREG; 389 ino_i->i_nlinks = 1;390 }391 389 392 390 ino_i->i_uid = 0; … … 675 673 if (r != EOK) 676 674 goto exit_error; 675 676 child->ino_i->i_nlinks++; 677 child->ino_i->dirty = true; 677 678 678 679 if (S_ISDIR(child->ino_i->i_mode)) {
Note:
See TracChangeset
for help on using the changeset viewer.