Changes in / [0748854:77223f8] in mainline
- Location:
- uspace
- Files:
-
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/doc/doxygroups.h
r0748854 r77223f8 269 269 270 270 /** 271 * @defgroup drvusbohci OHCI driver272 * @ingroup usb273 * @brief Driver for OHCI host controller.274 */275 276 /**277 271 * @defgroup drvusbehci EHCI driver 278 272 * @ingroup usb … … 281 275 282 276 /** 283 * @defgroup drvusbfallback USB fallback driver 277 * @defgroup drvusbfallback USB fallback driver. 284 278 * @ingroup usb 285 279 * @brief Fallback driver for any USB device. -
uspace/drv/ohci/batch.c
r0748854 r77223f8 227 227 ed_init(data->ed, instance->ep); 228 228 ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]); 229 usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed, 230 data->ed->status, data->ed->td_tail, data->ed->td_head, 231 data->ed->next); 229 usb_log_debug("Created ED: %x:%x:%x:%x.\n", data->ed->status, 230 data->ed->td_tail, data->ed->td_head, data->ed->next); 232 231 int toggle = 0; 233 232 /* setup stage */ -
uspace/drv/ohci/hc.c
r0748854 r77223f8 108 108 ret, str_error(ret)); 109 109 110 hc_gain_control(instance);111 ret = hc_init_memory(instance);112 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",113 ret, str_error(ret));114 hc_init_hw(instance);115 116 rh_init(&instance->rh, dev, instance->registers);117 118 110 if (!interrupts) { 119 111 instance->interrupt_emulator = … … 122 114 } 123 115 116 hc_gain_control(instance); 117 118 rh_init(&instance->rh, dev, instance->registers); 119 120 hc_init_memory(instance); 121 hc_init_hw(instance); 122 123 /* TODO: implement */ 124 124 return EOK; 125 125 } … … 140 140 switch (batch->transfer_type) { 141 141 case USB_TRANSFER_CONTROL: 142 instance->registers->control &= ~C_CLE;143 142 instance->registers->command_status |= CS_CLF; 144 usb_log_debug2("Set control transfer filled: %x.\n",145 instance->registers->command_status);146 instance->registers->control |= C_CLE;147 143 break; 148 144 case USB_TRANSFER_BULK: 149 145 instance->registers->command_status |= CS_BLF; 150 usb_log_debug2("Set bulk transfer filled: %x.\n",151 instance->registers->command_status);152 146 break; 153 147 default: … … 160 154 { 161 155 assert(instance); 162 if ( (status & ~IS_SF) == 0) /* ignore sof status */156 if (status == 0) 163 157 return; 164 158 if (status & IS_RHSC) … … 166 160 167 161 usb_log_info("OHCI interrupt: %x.\n", status); 168 169 162 170 163 LIST_INITIALIZE(done); … … 199 192 { 200 193 assert(instance); 201 /* Turn off legacy emulation */202 volatile uint32_t *ohci_emulation_reg =203 (uint32_t*)((char*)instance->registers + 0x100);204 usb_log_debug("OHCI legacy register %p: %x.\n",205 ohci_emulation_reg, *ohci_emulation_reg);206 *ohci_emulation_reg = 0;207 208 194 /* Interrupt routing enabled => smm driver is active */ 209 195 if (instance->registers->control & C_IR) { 210 usb_log_ debug("SMM driver: requestownership change.\n");196 usb_log_info("Found SMM driver requesting ownership change.\n"); 211 197 instance->registers->command_status |= CS_OCR; 212 198 while (instance->registers->control & C_IR) { 213 199 async_usleep(1000); 214 200 } 215 usb_log_info(" SMM driver: Ownership taken.\n");201 usb_log_info("Ownership taken from SMM driver.\n"); 216 202 return; 217 203 } … … 221 207 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 222 208 if (hc_status != C_HCFS_RESET) { 223 usb_log_ debug("BIOS driver found.\n");209 usb_log_info("Found BIOS driver.\n"); 224 210 if (hc_status == C_HCFS_OPERATIONAL) { 225 usb_log_info(" BIOS driver: HC operational.\n");211 usb_log_info("HC operational(BIOS).\n"); 226 212 return; 227 213 } … … 229 215 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT); 230 216 async_usleep(20000); 231 usb_log_info("BIOS driver: HC resumed.\n");232 217 return; 233 218 } … … 235 220 /* HC is in reset (hw startup) => no other driver 236 221 * maintain reset for at least the time specified in USB spec (50 ms)*/ 237 usb_log_info("HC found in reset.\n");238 222 async_usleep(50000); 223 224 /* turn off legacy emulation */ 225 volatile uint32_t *ohci_emulation_reg = 226 (uint32_t*)((char*)instance->registers + 0x100); 227 usb_log_info("OHCI legacy register status %p: %x.\n", 228 ohci_emulation_reg, *ohci_emulation_reg); 229 *ohci_emulation_reg = 0; 230 239 231 } 240 232 /*----------------------------------------------------------------------------*/ 241 233 void hc_init_hw(hc_t *instance) 242 234 { 243 /* OHCI guide page 42 */ 244 assert(instance); 245 usb_log_debug2("Started hc initialization routine.\n"); 246 247 /* Save contents of fm_interval register */ 235 assert(instance); 248 236 const uint32_t fm_interval = instance->registers->fm_interval; 249 usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval); 250 251 /* Reset hc */ 252 usb_log_debug2("HC reset.\n"); 253 size_t time = 0; 237 238 /* reset hc */ 254 239 instance->registers->command_status = CS_HCR; 255 while (instance->registers->command_status & CS_HCR) { 256 async_usleep(10); 257 time += 10; 258 } 259 usb_log_debug2("HC reset complete in %zu us.\n", time); 260 261 /* Restore fm_interval */ 240 async_usleep(10); 241 242 /* restore fm_interval */ 262 243 instance->registers->fm_interval = fm_interval; 263 244 assert((instance->registers->command_status & CS_HCR) == 0); 264 245 265 246 /* hc is now in suspend state */ 266 usb_log_debug2("HC should be in suspend state(%x).\n", 267 instance->registers->control); 268 269 /* Enable queues */ 247 248 /* enable queues */ 270 249 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); 271 usb_log_debug2("All queues enabled(%x).\n", 272 instance->registers->control); 273 274 /* Disable interrupts */ 275 instance->registers->interrupt_disable = I_SF | I_OC; 276 usb_log_debug2("Disabling interrupts: %x.\n", 277 instance->registers->interrupt_disable); 278 instance->registers->interrupt_disable = I_MI; 279 usb_log_debug2("Enabled interrupts: %x.\n", 280 instance->registers->interrupt_enable); 281 282 /* Set periodic start to 90% */ 283 uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK); 284 instance->registers->periodic_start = (frame_length / 10) * 9; 285 usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n", 286 instance->registers->periodic_start, 287 instance->registers->periodic_start, frame_length); 250 /* TODO: enable interrupts */ 251 /* set periodic start to 90% */ 252 instance->registers->periodic_start = (fm_interval / 10) * 9; 288 253 289 254 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT); 290 usb_log_info("OHCI HC up and running(%x).\n", 291 instance->registers->control); 255 usb_log_info("OHCI HC up and running.\n"); 292 256 } 293 257 /*----------------------------------------------------------------------------*/ … … 334 298 { 335 299 assert(instance); 336 /* Init queues */300 /* init queues */ 337 301 hc_init_transfer_lists(instance); 338 302 339 /* Init HCCA */303 /* init HCCA */ 340 304 instance->hcca = malloc32(sizeof(hcca_t)); 341 305 if (instance->hcca == NULL) … … 343 307 bzero(instance->hcca, sizeof(hcca_t)); 344 308 instance->registers->hcca = addr_to_phys(instance->hcca); 345 usb_log_debug2("OHCI HCCA initialized at %p(%p).\n", 346 instance->hcca, instance->registers->hcca); 347 348 /* Use queues */ 309 310 /* use queues */ 349 311 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 350 usb_log_debug2("Bulk HEAD set to: %p(%p).\n",351 instance->transfers_bulk.list_head,352 instance->transfers_bulk.list_head_pa);353 354 312 instance->registers->control_head = 355 313 instance->transfers_control.list_head_pa; 356 usb_log_debug2("Control HEAD set to: %p(%p).\n",357 instance->transfers_control.list_head,358 instance->transfers_control.list_head_pa);359 314 360 315 unsigned i = 0; … … 363 318 instance->transfers_interrupt.list_head_pa; 364 319 } 365 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",366 instance->transfers_interrupt.list_head,367 instance->transfers_interrupt.list_head_pa);368 320 369 321 return EOK; -
uspace/drv/ohci/hw_struct/endpoint_descriptor.c
r0748854 r77223f8 42 42 bzero(instance, sizeof(ed_t)); 43 43 if (ep == NULL) { 44 instance->status = ED_STATUS_K_FLAG;44 instance->status |= ED_STATUS_K_FLAG; 45 45 return; 46 46 } … … 57 57 if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS) 58 58 instance->status |= ED_STATUS_F_FLAG; 59 59 60 } 61 60 62 /** 61 63 * @} -
uspace/drv/ohci/iface.c
r0748854 r77223f8 74 74 name, target.address, target.endpoint, size, ep->max_packet_size); 75 75 76 *batch = batch_get( 77 fun, ep, data, size, setup_data, setup_size, in, out, arg); 78 if (!*batch) 76 assert(ep->speed == 77 usb_device_keeper_get_speed(&(*hc)->manager, target.address)); 78 // assert(ep->max_packet_size == max_packet_size); 79 // assert(ep->transfer_type == USB_TRANSFER_CONTROL); 80 81 *batch = 82 batch_get(fun, ep, data, size, setup_data, setup_size, 83 in, out, arg); 84 if (!batch) 79 85 return ENOMEM; 86 return EOK; 87 } 88 89 90 /** Reserve default address interface function 91 * 92 * @param[in] fun DDF function that was called. 93 * @param[in] speed Speed to associate with the new default address. 94 * @return Error code. 95 */ 96 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed) 97 { 98 assert(fun); 99 hc_t *hc = fun_to_hc(fun); 100 assert(hc); 101 usb_log_debug("Default address request with speed %d.\n", speed); 102 usb_device_keeper_reserve_default_address(&hc->manager, speed); 103 return EOK; 104 #if 0 105 endpoint_t *ep = malloc(sizeof(endpoint_t)); 106 if (ep == NULL) 107 return ENOMEM; 108 const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64; 109 endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size); 110 int ret; 111 try_retgister: 112 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, 113 USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0); 114 if (ret == EEXISTS) { 115 async_usleep(1000); 116 goto try_retgister; 117 } 118 if (ret != EOK) { 119 endpoint_destroy(ep); 120 } 121 return ret; 122 #endif 123 } 124 /*----------------------------------------------------------------------------*/ 125 /** Release default address interface function 126 * 127 * @param[in] fun DDF function that was called. 128 * @return Error code. 129 */ 130 static int release_default_address(ddf_fun_t *fun) 131 { 132 assert(fun); 133 hc_t *hc = fun_to_hc(fun); 134 assert(hc); 135 usb_log_debug("Default address release.\n"); 136 // return usb_endpoint_manager_unregister_ep(&hc->ep_manager, 137 // USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH); 138 usb_device_keeper_release_default_address(&hc->manager); 80 139 return EOK; 81 140 } … … 186 245 if (ret != EOK) { 187 246 endpoint_destroy(ep); 247 } else { 248 usb_device_keeper_add_ep(&hc->manager, address, ep); 188 249 } 189 250 return ret; … … 198 259 usb_log_debug("Unregister endpoint %d:%d %d.\n", 199 260 address, endpoint, direction); 261 endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager, 262 address, endpoint, direction, NULL); 263 if (ep != NULL) { 264 usb_device_keeper_del_ep(&hc->manager, address, ep); 265 } 200 266 return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address, 201 267 endpoint, direction); … … 369 435 if (ret != EOK) 370 436 return ret; 371 usb_ endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);437 usb_device_keeper_reset_if_need(&hc->manager, target, setup_data); 372 438 batch_control_write(batch); 373 439 ret = hc_schedule(hc, batch); … … 418 484 /*----------------------------------------------------------------------------*/ 419 485 usbhc_iface_t hc_iface = { 486 .reserve_default_address = reserve_default_address, 487 .release_default_address = release_default_address, 420 488 .request_address = request_address, 421 489 .bind_address = bind_address, -
uspace/drv/ohci/ohci_regs.h
r0748854 r77223f8 84 84 /** Interupt enable/disable, reads give the same value, writing causes 85 85 * enable/disable */ 86 volatile uint32_t inter rupt_enable;86 volatile uint32_t interupt_enable; 87 87 volatile uint32_t interrupt_disable; 88 88 #define I_SO (1 << 0) /* Scheduling overrun */ … … 120 120 /** Frame time and max packet size for all transfers */ 121 121 volatile uint32_t fm_interval; 122 #define FMI_FI_MASK (0x 3fff) /* Frame interval in bit times (should be 11999)*/122 #define FMI_FI_MASK (0x1fff) /* Frame interval in bit times (should be 11999)*/ 123 123 #define FMI_FI_SHIFT (0) 124 124 #define FMI_FSMPS_MASK (0x7fff) /* Full speed max packet size */ … … 138 138 /** Remaining bit time in frame to start periodic transfers */ 139 139 volatile uint32_t periodic_start; 140 #define PS_PS_MASK (0x 3fff) /* bit time when periodic get priority (0x3e67) */140 #define PS_PS_MASK (0x1fff) /* bit time when periodic get priority (0x3e67) */ 141 141 142 142 /** Threshold for starting LS transaction */ -
uspace/drv/ohci/root_hub.c
r0748854 r77223f8 115 115 116 116 static const uint32_t hub_set_feature_valid_mask = 117 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) | 118 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 117 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT); 119 118 120 119 … … 210 209 instance->registers = regs; 211 210 instance->device = dev; 212 instance->port_count = 213 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 211 instance->port_count = instance->registers->rh_desc_a & 0xff; 214 212 rh_init_descriptors(instance); 215 213 // set port power mode to no-power-switching … … 588 586 if (!((1 << feature) & hub_set_feature_valid_mask)) 589 587 return EINVAL; 590 if(feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)591 feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;592 588 instance->registers->rh_status = 593 589 (instance->registers->rh_status | (1 << feature)) -
uspace/drv/ohci/transfer_list.c
r0748854 r77223f8 122 122 usb_transfer_batch_t *first = list_get_instance( 123 123 instance->batch_list.next, usb_transfer_batch_t, link); 124 usb_log_debug("Batch(%p) added to list %s, first is %p(%p).\n", 125 batch, instance->name, first, batch_ed(first)); 126 if (last_ed == instance->list_head) { 127 usb_log_debug2("%s head ED: %x:%x:%x:%x.\n", instance->name, 128 last_ed->status, last_ed->td_tail, last_ed->td_head, 129 last_ed->next); 130 } 124 usb_log_debug("Batch(%p) added to queue %s, first is %p.\n", 125 batch, instance->name, first); 131 126 fibril_mutex_unlock(&instance->guard); 132 127 } -
uspace/drv/uhci-hcd/iface.c
r0748854 r77223f8 74 74 name, target.address, target.endpoint, size, ep->max_packet_size); 75 75 76 *batch = batch_get( 77 fun, ep, data, size, setup_data, setup_size, in, out, arg); 78 if (!*batch) 76 // assert(ep->speed == 77 // usb_device_keeper_get_speed(&(*hc)->manager, target.address)); 78 // assert(ep->max_packet_size == max_packet_size); 79 // assert(ep->transfer_type == USB_TRANSFER_CONTROL); 80 81 *batch = 82 batch_get(fun, ep, data, size, setup_data, setup_size, 83 in, out, arg); 84 if (!batch) 79 85 return ENOMEM; 86 return EOK; 87 } 88 89 90 /** Reserve default address interface function 91 * 92 * @param[in] fun DDF function that was called. 93 * @param[in] speed Speed to associate with the new default address. 94 * @return Error code. 95 */ 96 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed) 97 { 98 assert(fun); 99 hc_t *hc = fun_to_hc(fun); 100 assert(hc); 101 usb_log_debug("Default address request with speed %d.\n", speed); 102 usb_device_keeper_reserve_default_address(&hc->manager, speed); 103 return EOK; 104 #if 0 105 endpoint_t *ep = malloc(sizeof(endpoint_t)); 106 if (ep == NULL) 107 return ENOMEM; 108 const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64; 109 endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size); 110 int ret; 111 try_retgister: 112 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, 113 USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0); 114 if (ret == EEXISTS) { 115 async_usleep(1000); 116 goto try_retgister; 117 } 118 if (ret != EOK) { 119 endpoint_destroy(ep); 120 } 121 return ret; 122 #endif 123 } 124 /*----------------------------------------------------------------------------*/ 125 /** Release default address interface function 126 * 127 * @param[in] fun DDF function that was called. 128 * @return Error code. 129 */ 130 static int release_default_address(ddf_fun_t *fun) 131 { 132 assert(fun); 133 hc_t *hc = fun_to_hc(fun); 134 assert(hc); 135 usb_log_debug("Default address release.\n"); 136 // return usb_endpoint_manager_unregister_ep(&hc->ep_manager, 137 // USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH); 138 usb_device_keeper_release_default_address(&hc->manager); 80 139 return EOK; 81 140 } … … 173 232 if (ret != EOK) { 174 233 endpoint_destroy(ep); 234 } else { 235 usb_device_keeper_add_ep(&hc->manager, address, ep); 175 236 } 176 237 return ret; … … 185 246 usb_log_debug("Unregister endpoint %d:%d %d.\n", 186 247 address, endpoint, direction); 248 endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager, 249 address, endpoint, direction, NULL); 250 if (ep != NULL) { 251 usb_device_keeper_del_ep(&hc->manager, address, ep); 252 } 187 253 return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address, 188 254 endpoint, direction); … … 325 391 if (ret != EOK) 326 392 return ret; 327 usb_ endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);393 usb_device_keeper_reset_if_need(&hc->manager, target, setup_data); 328 394 batch_control_write(batch); 329 395 ret = hc_schedule(hc, batch); … … 367 433 /*----------------------------------------------------------------------------*/ 368 434 usbhc_iface_t hc_iface = { 435 .reserve_default_address = reserve_default_address, 436 .release_default_address = release_default_address, 369 437 .request_address = request_address, 370 438 .bind_address = bind_address, -
uspace/drv/usbhub/Makefile
r0748854 r77223f8 34 34 SOURCES = \ 35 35 main.c \ 36 ports.c \ 36 37 utils.c \ 37 usbhub.c \ 38 ports.c 38 usbhub.c 39 39 40 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/usbhub/port_status.h
r0748854 r77223f8 49 49 50 50 /** 51 * structure holding hub status and changes flags.52 * should not be accessed directly, use supplied getter/setter methods.53 *54 * For more information refer to table 11.16.2.5 in55 * "Universal Serial Bus Specification Revision 1.1"56 *57 */58 typedef uint32_t usb_hub_status_t;59 60 /**61 51 * set values in request to be it a port status request 62 52 * @param request … … 64 54 */ 65 55 static inline void usb_hub_set_port_status_request( 66 67 ){56 usb_device_request_setup_packet_t * request, uint16_t port 57 ){ 68 58 request->index = port; 69 59 request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS; … … 73 63 } 74 64 75 /**76 * set values in request to be it a port status request77 * @param request78 * @param port79 */80 static inline void usb_hub_set_hub_status_request(81 usb_device_request_setup_packet_t * request82 ) {83 request->index = 0;84 request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;85 request->request = USB_HUB_REQUEST_GET_STATUS;86 request->value = 0;87 request->length = 4;88 }89 65 90 66 /** … … 94 70 */ 95 71 static inline usb_device_request_setup_packet_t * 96 usb_hub_create_port_status_request(uint16_t port) 72 usb_hub_create_port_status_request(uint16_t port){ 97 73 usb_device_request_setup_packet_t * result = 98 malloc(sizeof(usb_device_request_setup_packet_t));99 usb_hub_set_port_status_request(result, 74 usb_new(usb_device_request_setup_packet_t); 75 usb_hub_set_port_status_request(result,port); 100 76 return result; 101 77 } 102 78 79 103 80 /** 104 81 * set the device request to be a port feature enable request … … 108 85 */ 109 86 static inline void usb_hub_set_enable_port_feature_request( 110 111 uint16_t feature_selector112 ){87 usb_device_request_setup_packet_t * request, uint16_t port, 88 uint16_t feature_selector 89 ){ 113 90 request->index = port; 114 91 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 125 102 */ 126 103 static inline void usb_hub_set_disable_port_feature_request( 127 128 uint16_t feature_selector129 ){104 usb_device_request_setup_packet_t * request, uint16_t port, 105 uint16_t feature_selector 106 ){ 130 107 request->index = port; 131 108 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 141 118 */ 142 119 static inline void usb_hub_set_enable_port_request( 143 144 ){120 usb_device_request_setup_packet_t * request, uint16_t port 121 ){ 145 122 request->index = port; 146 123 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 156 133 */ 157 134 static inline usb_device_request_setup_packet_t * 158 usb_hub_create_enable_port_request(uint16_t port) 135 usb_hub_create_enable_port_request(uint16_t port){ 159 136 usb_device_request_setup_packet_t * result = 160 malloc(sizeof(usb_device_request_setup_packet_t));161 usb_hub_set_enable_port_request(result, 137 usb_new(usb_device_request_setup_packet_t); 138 usb_hub_set_enable_port_request(result,port); 162 139 return result; 163 140 } … … 169 146 */ 170 147 static inline void usb_hub_set_disable_port_request( 171 172 ){148 usb_device_request_setup_packet_t * request, uint16_t port 149 ){ 173 150 request->index = port; 174 151 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 184 161 */ 185 162 static inline usb_device_request_setup_packet_t * 186 usb_hub_create_disable_port_request(uint16_t port) 163 usb_hub_create_disable_port_request(uint16_t port){ 187 164 usb_device_request_setup_packet_t * result = 188 malloc(sizeof(usb_device_request_setup_packet_t));189 usb_hub_set_disable_port_request(result, 165 usb_new(usb_device_request_setup_packet_t); 166 usb_hub_set_disable_port_request(result,port); 190 167 return result; 191 168 } … … 197 174 */ 198 175 static inline void usb_hub_set_reset_port_request( 199 200 ){176 usb_device_request_setup_packet_t * request, uint16_t port 177 ){ 201 178 request->index = port; 202 179 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 212 189 */ 213 190 static inline usb_device_request_setup_packet_t * 214 usb_hub_create_reset_port_request(uint16_t port) 191 usb_hub_create_reset_port_request(uint16_t port){ 215 192 usb_device_request_setup_packet_t * result = 216 malloc(sizeof(usb_device_request_setup_packet_t));217 usb_hub_set_reset_port_request(result, 193 usb_new(usb_device_request_setup_packet_t); 194 usb_hub_set_reset_port_request(result,port); 218 195 return result; 219 196 } … … 225 202 */ 226 203 static inline void usb_hub_set_power_port_request( 227 228 ){204 usb_device_request_setup_packet_t * request, uint16_t port 205 ){ 229 206 request->index = port; 230 207 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 240 217 */ 241 218 static inline void usb_hub_unset_power_port_request( 242 243 ){219 usb_device_request_setup_packet_t * request, uint16_t port 220 ){ 244 221 request->index = port; 245 222 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 249 226 } 250 227 251 /** 252 * get i`th bit of port status 253 * 254 * @param status 255 * @param idx 256 * @return 257 */ 258 static inline bool usb_port_is_status(usb_port_status_t status, int idx) { 259 return (status&(1 << idx))!=0; 260 } 261 262 /** 263 * set i`th bit of port status 264 * 265 * @param status 266 * @param idx 267 * @param value 268 */ 269 static inline void usb_port_status_set_bit( 270 usb_port_status_t * status, int idx, bool value) { 271 (*status) = value ? 272 ((*status) | (1 << (idx))) : 273 ((*status)&(~(1 << (idx)))); 274 } 275 276 /** 277 * get i`th bit of hub status 278 * 279 * @param status 280 * @param idx 281 * @return 282 */ 283 static inline bool usb_hub_is_status(usb_hub_status_t status, int idx) { 284 return (status&(1 << idx))!=0; 285 } 286 287 /** 288 * set i`th bit of hub status 289 * 290 * @param status 291 * @param idx 292 * @param value 293 */ 294 static inline void usb_hub_status_set_bit( 295 usb_hub_status_t * status, int idx, bool value) { 296 (*status) = value ? 297 ((*status) | (1 << (idx))) : 298 ((*status)&(~(1 << (idx)))); 299 } 300 301 302 #if 0 303 /** 304 * connection status geter for port status 305 * 306 * @param status 307 * @return true if there is something connected 308 */ 309 static inline bool usb_port_dev_connected(usb_port_status_t * status) { 310 return usb_port_get_bit(status, 0); 311 } 312 313 /** 314 * set device connected bit in port status 315 * 316 * @param status 317 * @param connected value of the bit 318 */ 319 static inline void usb_port_set_dev_connected(usb_port_status_t * status, bool connected) { 320 usb_port_set_bit(status, 0, connected); 228 229 /** get i`th bit of port status */ 230 static inline bool usb_port_get_bit(usb_port_status_t * status, int idx) 231 { 232 return (((*status)>>(idx))%2); 233 } 234 235 /** set i`th bit of port status */ 236 static inline void usb_port_set_bit( 237 usb_port_status_t * status, int idx, bool value) 238 { 239 (*status) = value? 240 ((*status)|(1<<(idx))): 241 ((*status)&(~(1<<(idx)))); 242 } 243 244 //device connnected on port 245 static inline bool usb_port_dev_connected(usb_port_status_t * status){ 246 return usb_port_get_bit(status,0); 247 } 248 249 static inline void usb_port_set_dev_connected(usb_port_status_t * status,bool connected){ 250 usb_port_set_bit(status,0,connected); 321 251 } 322 252 323 253 //port enabled 324 325 /** 326 * port enabled getter for port status 327 * 328 * @param status 329 * @return true if the port is enabled 330 */ 331 static inline bool usb_port_enabled(usb_port_status_t * status) { 332 return usb_port_get_bit(status, 1); 333 } 334 335 /** 336 * set port enabled bit in port status 337 * 338 * @param status 339 * @param enabled value of the bit 340 */ 341 static inline void usb_port_set_enabled(usb_port_status_t * status, bool enabled) { 342 usb_port_set_bit(status, 1, enabled); 254 static inline bool usb_port_enabled(usb_port_status_t * status){ 255 return usb_port_get_bit(status,1); 256 } 257 258 static inline void usb_port_set_enabled(usb_port_status_t * status,bool enabled){ 259 usb_port_set_bit(status,1,enabled); 343 260 } 344 261 345 262 //port suspended 346 /** 347 * port suspended getter for port status 348 * 349 * @param status 350 * @return true if port is suspended 351 */ 352 static inline bool usb_port_suspended(usb_port_status_t * status) { 353 return usb_port_get_bit(status, 2); 354 } 355 356 /** 357 * set port suspended bit in port status 358 * 359 * @param status 360 * @param suspended value of the bit 361 */ 362 static inline void usb_port_set_suspended(usb_port_status_t * status, bool suspended) { 363 usb_port_set_bit(status, 2, suspended); 263 static inline bool usb_port_suspended(usb_port_status_t * status){ 264 return usb_port_get_bit(status,2); 265 } 266 267 static inline void usb_port_set_suspended(usb_port_status_t * status,bool suspended){ 268 usb_port_set_bit(status,2,suspended); 364 269 } 365 270 366 271 //over currect 367 /** 368 * over current condition indicator getter for port status 369 * 370 * @param status 371 * @return true if there is opver-current condition on the hub 372 */ 373 static inline bool usb_port_over_current(usb_port_status_t * status) { 374 return usb_port_get_bit(status, 3); 375 } 376 377 /** 378 * set over current indicator bit in port status 379 * 380 * @param status 381 * @param value value of the bit 382 */ 383 static inline void usb_port_set_over_current(usb_port_status_t * status, bool value) { 384 usb_port_set_bit(status, 3, value); 272 static inline bool usb_port_over_current(usb_port_status_t * status){ 273 return usb_port_get_bit(status,3); 274 } 275 276 static inline void usb_port_set_over_current(usb_port_status_t * status,bool value){ 277 usb_port_set_bit(status,3,value); 385 278 } 386 279 387 280 //port reset 388 /** 389 * port reset indicator getter for port status 390 * 391 * @param status 392 * @return true if port is reset 393 */ 394 static inline bool usb_port_reset(usb_port_status_t * status) { 395 return usb_port_get_bit(status, 4); 396 } 397 398 /** 399 * set port reset bit in port status 400 * 401 * @param status 402 * @param value value of the bit 403 */ 404 static inline void usb_port_set_reset(usb_port_status_t * status, bool value) { 405 usb_port_set_bit(status, 4, value); 281 static inline bool usb_port_reset(usb_port_status_t * status){ 282 return usb_port_get_bit(status,4); 283 } 284 285 static inline void usb_port_set_reset(usb_port_status_t * status,bool value){ 286 usb_port_set_bit(status,4,value); 406 287 } 407 288 408 289 //powered 409 /** 410 * power state getter for port status 411 * 412 * @param status 413 * @return true if port is powered 414 */ 415 static inline bool usb_port_powered(usb_port_status_t * status) { 416 return usb_port_get_bit(status, 8); 417 } 418 419 /** 420 * set port powered bit in port status 421 * 422 * @param status 423 * @param powered value of the bit 424 */ 425 static inline void usb_port_set_powered(usb_port_status_t * status, bool powered) { 426 usb_port_set_bit(status, 8, powered); 427 } 428 429 #endif 290 static inline bool usb_port_powered(usb_port_status_t * status){ 291 return usb_port_get_bit(status,8); 292 } 293 294 static inline void usb_port_set_powered(usb_port_status_t * status,bool powered){ 295 usb_port_set_bit(status,8,powered); 296 } 430 297 431 298 //low speed device attached 432 /** 433 * low speed device on the port indicator 434 * 435 * @param status 436 * @return true if low speed device is attached 437 */ 438 static inline bool usb_port_low_speed(usb_port_status_t status) { 439 return usb_port_is_status(status, 9); 440 } 441 442 /** 443 * set low speed device connected bit in port status 444 * 445 * @param status 446 * @param low_speed value of the bit 447 */ 448 static inline void usb_port_set_low_speed(usb_port_status_t * status, bool low_speed) { 449 usb_port_status_set_bit(status, 9, low_speed); 450 } 451 452 //high speed device attached 453 /** 454 * high speed device on the port indicator 455 * 456 * @param status 457 * @return true if high speed device is on port 458 */ 459 static inline bool usb_port_high_speed(usb_port_status_t status) { 460 return usb_port_is_status(status, 10); 461 } 462 463 /** 464 * set high speed device bit in port status 465 * 466 * @param status 467 * @param high_speed value of the bit 468 */ 469 static inline void usb_port_set_high_speed(usb_port_status_t * status, bool high_speed) { 470 usb_port_status_set_bit(status, 10, high_speed); 471 } 472 473 /** 474 * speed getter for port status 475 * 476 * @param status 477 * @return speed of usb device (for more see usb specification) 478 */ 479 static inline usb_speed_t usb_port_speed(usb_port_status_t status) { 480 if (usb_port_low_speed(status)) 299 static inline bool usb_port_low_speed(usb_port_status_t * status){ 300 return usb_port_get_bit(status,9); 301 } 302 303 static inline void usb_port_set_low_speed(usb_port_status_t * status,bool low_speed){ 304 usb_port_set_bit(status,9,low_speed); 305 } 306 307 //low speed device attached 308 static inline bool usb_port_high_speed(usb_port_status_t * status){ 309 return usb_port_get_bit(status,10); 310 } 311 312 static inline void usb_port_set_high_speed(usb_port_status_t * status,bool high_speed){ 313 usb_port_set_bit(status,10,high_speed); 314 } 315 316 static inline usb_speed_t usb_port_speed(usb_port_status_t * status){ 317 if(usb_port_low_speed(status)) 481 318 return USB_SPEED_LOW; 482 if 319 if(usb_port_high_speed(status)) 483 320 return USB_SPEED_HIGH; 484 321 return USB_SPEED_FULL; 485 322 } 486 323 487 #if 0 324 488 325 //connect change 489 /** 490 * port connect change indicator 491 * 492 * @param status 493 * @return true if connection has changed 494 */ 495 static inline bool usb_port_connect_change(usb_port_status_t * status) { 496 return usb_port_get_bit(status, 16); 497 } 498 499 /** 500 * set connection change bit in port status 501 * @param status 502 * @param change value of the bit 503 */ 504 static inline void usb_port_set_connect_change(usb_port_status_t * status, bool change) { 505 usb_port_set_bit(status, 16, change); 326 static inline bool usb_port_connect_change(usb_port_status_t * status){ 327 return usb_port_get_bit(status,16); 328 } 329 330 static inline void usb_port_set_connect_change(usb_port_status_t * status,bool change){ 331 usb_port_set_bit(status,16,change); 506 332 } 507 333 508 334 //port enable change 509 /** 510 * port enable change for port status 511 * 512 * @param status 513 * @return true if the port has been enabled/disabled 514 */ 515 static inline bool usb_port_enabled_change(usb_port_status_t * status) { 516 return usb_port_get_bit(status, 17); 517 } 518 519 /** 520 * set port enable change bit in port status 521 * 522 * @param status 523 * @param change value of the bit 524 */ 525 static inline void usb_port_set_enabled_change(usb_port_status_t * status, bool change) { 526 usb_port_set_bit(status, 17, change); 335 static inline bool usb_port_enabled_change(usb_port_status_t * status){ 336 return usb_port_get_bit(status,17); 337 } 338 339 static inline void usb_port_set_enabled_change(usb_port_status_t * status,bool change){ 340 usb_port_set_bit(status,17,change); 527 341 } 528 342 529 343 //suspend change 530 /** 531 * port suspend change for port status 532 * 533 * @param status 534 * @return ture if suspend status has changed 535 */ 536 static inline bool usb_port_suspend_change(usb_port_status_t * status) { 537 return usb_port_get_bit(status, 18); 538 } 539 540 /** 541 * set port suspend change bit in port status 542 * 543 * @param status 544 * @param change value of the bit 545 */ 546 static inline void usb_port_set_suspend_change(usb_port_status_t * status, bool change) { 547 usb_port_set_bit(status, 18, change); 344 static inline bool usb_port_suspend_change(usb_port_status_t * status){ 345 return usb_port_get_bit(status,18); 346 } 347 348 static inline void usb_port_set_suspend_change(usb_port_status_t * status,bool change){ 349 usb_port_set_bit(status,18,change); 548 350 } 549 351 550 352 //over current change 551 /** 552 * over current change indicator 553 * 554 * @param status 555 * @return true if over-current condition on port has changed 556 */ 557 static inline bool usb_port_overcurrent_change(usb_port_status_t * status) { 558 return usb_port_get_bit(status, 19); 559 } 560 561 /** 562 * set port over current change bit in port status 563 * 564 * @param status 565 * @param change value of the bit 566 */ 567 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status, bool change) { 568 usb_port_set_bit(status, 19, change); 353 static inline bool usb_port_overcurrent_change(usb_port_status_t * status){ 354 return usb_port_get_bit(status,19); 355 } 356 357 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status,bool change){ 358 usb_port_set_bit(status,19,change); 569 359 } 570 360 571 361 //reset change 572 /** 573 * port reset change indicator 574 * @param status 575 * @return true if port has been reset 576 */ 577 static inline bool usb_port_reset_completed(usb_port_status_t * status) { 578 return usb_port_get_bit(status, 20); 579 } 580 581 /** 582 * set port reset completed bit in port status 583 * 584 * @param status 585 * @param change value of the bit 586 */ 587 static inline void usb_port_set_reset_completed(usb_port_status_t * status, bool completed) { 588 usb_port_set_bit(status, 20, completed); 589 } 590 591 //local power status 592 /** 593 * local power lost indicator for hub status 594 * 595 * @param status 596 * @return true if hub is not powered 597 */ 598 static inline bool usb_hub_local_power_lost(usb_hub_status_t * status) { 599 return usb_hub_get_bit(status, 0); 600 } 601 602 /** 603 * set hub power lost bit in hub status 604 * 605 * @param status 606 * @param change value of the bit 607 */ 608 static inline void usb_hub_set_local_power_lost(usb_port_status_t * status, 609 bool power_lost) { 610 usb_hub_set_bit(status, 0, power_lost); 611 } 612 613 //over current ocndition 614 /** 615 * hub over-current indicator 616 * 617 * @param status 618 * @return true if over-current condition occurred on hub 619 */ 620 static inline bool usb_hub_over_current(usb_hub_status_t * status) { 621 return usb_hub_get_bit(status, 1); 622 } 623 624 /** 625 * set hub over current bit in hub status 626 * 627 * @param status 628 * @param change value of the bit 629 */ 630 static inline void usb_hub_set_over_current(usb_port_status_t * status, 631 bool over_current) { 632 usb_hub_set_bit(status, 1, over_current); 633 } 634 635 //local power change 636 /** 637 * hub power change indicator 638 * 639 * @param status 640 * @return true if local power status has been changed - power has been 641 * dropped or re-established 642 */ 643 static inline bool usb_hub_local_power_change(usb_hub_status_t * status) { 644 return usb_hub_get_bit(status, 16); 645 } 646 647 /** 648 * set hub power change bit in hub status 649 * 650 * @param status 651 * @param change value of the bit 652 */ 653 static inline void usb_hub_set_local_power_change(usb_port_status_t * status, 654 bool change) { 655 usb_hub_set_bit(status, 16, change); 656 } 657 658 //local power status 659 /** 660 * hub over-current condition change indicator 661 * 662 * @param status 663 * @return true if over-current condition has changed 664 */ 665 static inline bool usb_hub_over_current_change(usb_hub_status_t * status) { 666 return usb_hub_get_bit(status, 17); 667 } 668 669 /** 670 * set hub over current change bit in hub status 671 * 672 * @param status 673 * @param change value of the bit 674 */ 675 static inline void usb_hub_set_over_current_change(usb_port_status_t * status, 676 bool change) { 677 usb_hub_set_bit(status, 17, change); 678 } 679 #endif 362 static inline bool usb_port_reset_completed(usb_port_status_t * status){ 363 return usb_port_get_bit(status,20); 364 } 365 366 static inline void usb_port_set_reset_completed(usb_port_status_t * status,bool completed){ 367 usb_port_set_bit(status,20,completed); 368 } 369 680 370 681 371 -
uspace/drv/usbhub/ports.c
r0748854 r77223f8 33 33 * Hub ports functions. 34 34 */ 35 36 #include < bool.h>35 #include "port_status.h" 36 #include <inttypes.h> 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <inttypes.h> 40 #include <fibril_synch.h> 41 39 #include <usb/request.h> 42 40 #include <usb/debug.h> 43 41 44 #include "ports.h" 45 #include "usbhub.h" 46 #include "usbhub_private.h" 47 #include "port_status.h" 48 42 /** Retrieve port status. 43 * 44 * @param[in] ctrl_pipe Control pipe to use. 45 * @param[in] port Port number (starting at 1). 46 * @param[out] status Where to store the port status. 47 * @return Error code. 48 */ 49 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port, 50 usb_port_status_t *status) 51 { 52 size_t recv_size; 53 usb_device_request_setup_packet_t request; 54 usb_port_status_t status_tmp; 55 56 usb_hub_set_port_status_request(&request, port); 57 int rc = usb_pipe_control_read(ctrl_pipe, 58 &request, sizeof(usb_device_request_setup_packet_t), 59 &status_tmp, sizeof(status_tmp), &recv_size); 60 if (rc != EOK) { 61 return rc; 62 } 63 64 if (recv_size != sizeof (status_tmp)) { 65 return ELIMIT; 66 } 67 68 if (status != NULL) { 69 *status = status_tmp; 70 } 71 72 return EOK; 73 } 49 74 50 75 /** Information for fibril for device discovery. */ … … 55 80 }; 56 81 57 static void usb_hub_removed_device(58 usb_hub_info_t * hub, uint16_t port);59 60 static void usb_hub_port_reset_completed(usb_hub_info_t * hub,61 uint16_t port, uint32_t status);62 63 static void usb_hub_port_over_current(usb_hub_info_t * hub,64 uint16_t port, uint32_t status);65 66 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,67 usb_port_status_t *status);68 69 static int enable_port_callback(int port_no, void *arg);70 71 static int add_device_phase1_worker_fibril(void *arg);72 73 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,74 usb_speed_t speed);75 76 /**77 * Process interrupts on given hub port78 *79 * Accepts connection, over current and port reset change.80 * @param hub hub representation81 * @param port port number, starting from 182 */83 void usb_hub_process_interrupt(usb_hub_info_t * hub,84 uint16_t port) {85 usb_log_debug("interrupt at port %d\n", port);86 //determine type of change87 //usb_pipe_t *pipe = hub->control_pipe;88 89 int opResult;90 91 usb_port_status_t status;92 opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);93 if (opResult != EOK) {94 usb_log_error("Failed to get port %zu status: %s.\n",95 port, str_error(opResult));96 return;97 }98 //connection change99 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {100 bool device_connected = usb_port_is_status(status,101 USB_HUB_FEATURE_PORT_CONNECTION);102 usb_log_debug("Connection change on port %zu: %s.\n", port,103 device_connected ? "device attached" : "device removed");104 105 if (device_connected) {106 opResult = create_add_device_fibril(hub, port,107 usb_port_speed(status));108 if (opResult != EOK) {109 usb_log_error(110 "Cannot handle change on port %zu: %s.\n",111 str_error(opResult));112 }113 } else {114 usb_hub_removed_device(hub, port);115 }116 }117 //over current118 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {119 //check if it was not auto-resolved120 usb_log_debug("overcurrent change on port\n");121 usb_hub_port_over_current(hub, port, status);122 }123 //port reset124 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {125 usb_hub_port_reset_completed(hub, port, status);126 }127 usb_log_debug("status x%x : %d\n ", status, status);128 129 usb_port_status_set_bit(130 &status, USB_HUB_FEATURE_C_PORT_CONNECTION,false);131 usb_port_status_set_bit(132 &status, USB_HUB_FEATURE_PORT_RESET,false);133 usb_port_status_set_bit(134 &status, USB_HUB_FEATURE_C_PORT_RESET,false);135 usb_port_status_set_bit(136 &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT,false);137 /// \TODO what about port power change?138 if (status >> 16) {139 usb_log_info("there was unsupported change on port %d: %X\n",140 port, status);141 142 }143 }144 145 146 /**147 * routine called when a device on port has been removed148 *149 * If the device on port had default address, it releases default address.150 * Otherwise does not do anything, because DDF does not allow to remove device151 * from it`s device tree.152 * @param hub hub representation153 * @param port port number, starting from 1154 */155 static void usb_hub_removed_device(156 usb_hub_info_t * hub, uint16_t port) {157 158 int opResult = usb_hub_clear_port_feature(hub->control_pipe,159 port, USB_HUB_FEATURE_C_PORT_CONNECTION);160 if (opResult != EOK) {161 usb_log_warning("could not clear port-change-connection flag\n");162 }163 /** \TODO remove device from device manager - not yet implemented in164 * devide manager165 */166 167 //close address168 //if (hub->attached_devs[port].address != 0) {169 if(hub->ports[port].attached_device.address >= 0){170 /*uncomment this code to use it when DDF allows device removal171 opResult = usb_hc_unregister_device(172 &hub->connection,173 hub->attached_devs[port].address);174 if(opResult != EOK) {175 dprintf(USB_LOG_LEVEL_WARNING, "could not release "176 "address of "177 "removed device: %d", opResult);178 }179 hub->attached_devs[port].address = 0;180 hub->attached_devs[port].handle = 0;181 */182 } else {183 usb_log_warning("this is strange, disconnected device had "184 "no address\n");185 //device was disconnected before it`s port was reset -186 //return default address187 usb_hub_release_default_address(hub);188 }189 }190 191 192 /**193 * Process port reset change194 *195 * After this change port should be enabled, unless some problem occured.196 * This functions triggers second phase of enabling new device.197 * @param hub198 * @param port199 * @param status200 */201 static void usb_hub_port_reset_completed(usb_hub_info_t * hub,202 uint16_t port, uint32_t status){203 usb_log_debug("Port %zu reset complete.\n", port);204 if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {205 /* Finalize device adding. */206 usb_hub_port_t *the_port = hub->ports + port;207 fibril_mutex_lock(&the_port->reset_mutex);208 the_port->reset_completed = true;209 fibril_condvar_broadcast(&the_port->reset_cv);210 fibril_mutex_unlock(&the_port->reset_mutex);211 } else {212 usb_log_warning(213 "Port %zu reset complete but port not enabled.\n",214 port);215 }216 }217 218 /**219 * Process over current condition on port.220 *221 * Turn off the power on the port.222 *223 * @param hub hub representation224 * @param port port number, starting from 1225 */226 static void usb_hub_port_over_current(usb_hub_info_t * hub,227 uint16_t port, uint32_t status) {228 int opResult;229 if(usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)){230 opResult = usb_hub_clear_port_feature(hub->control_pipe,231 port, USB_HUB_FEATURE_PORT_POWER);232 if (opResult != EOK) {233 usb_log_error("cannot power off port %d; %d\n",234 port, opResult);235 }236 }else{237 opResult = usb_hub_set_port_feature(hub->control_pipe,238 port, USB_HUB_FEATURE_PORT_POWER);239 if (opResult != EOK) {240 usb_log_error("cannot power on port %d; %d\n",241 port, opResult);242 }243 }244 }245 246 /** Retrieve port status.247 *248 * @param[in] ctrl_pipe Control pipe to use.249 * @param[in] port Port number (starting at 1).250 * @param[out] status Where to store the port status.251 * @return Error code.252 */253 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,254 usb_port_status_t *status)255 {256 size_t recv_size;257 usb_device_request_setup_packet_t request;258 usb_port_status_t status_tmp;259 260 usb_hub_set_port_status_request(&request, port);261 int rc = usb_pipe_control_read(ctrl_pipe,262 &request, sizeof(usb_device_request_setup_packet_t),263 &status_tmp, sizeof(status_tmp), &recv_size);264 if (rc != EOK) {265 return rc;266 }267 268 if (recv_size != sizeof (status_tmp)) {269 return ELIMIT;270 }271 272 if (status != NULL) {273 *status = status_tmp;274 }275 276 return EOK;277 }278 279 82 /** Callback for enabling a specific port. 280 83 * … … 288 91 static int enable_port_callback(int port_no, void *arg) 289 92 { 290 usb_hub_info_t *hub = arg;93 usb_hub_info_t *hub = (usb_hub_info_t *) arg; 291 94 int rc; 292 95 usb_device_request_setup_packet_t request; … … 353 156 data->hub->ports[data->port].attached_device.address = new_address; 354 157 355 usb_log_info("Detected new device on `%s' (port %zu), " 158 usb_log_info("Detected new device on `%s' (port %zu), " \ 356 159 "address %d (handle %" PRIun ").\n", 357 160 data->hub->usb_device->ddf_dev->name, data->port, … … 363 166 return EOK; 364 167 } 365 366 168 367 169 /** Start device adding when connection change is detected. … … 374 176 * @return Error code. 375 177 */ 376 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,178 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port, 377 179 usb_speed_t speed) 378 180 { … … 411 213 } 412 214 215 /** Process change on a single port. 216 * 217 * @param hub Hub to which the port belongs. 218 * @param port Port index (starting at 1). 219 */ 220 static void process_port_change(usb_hub_info_t *hub, size_t port) 221 { 222 int rc; 223 224 usb_port_status_t port_status; 225 226 rc = get_port_status(&hub->usb_device->ctrl_pipe, port, &port_status); 227 if (rc != EOK) { 228 usb_log_error("Failed to get port %zu status: %s.\n", 229 port, str_error(rc)); 230 return; 231 } 232 233 /* 234 * Check exact nature of the change. 235 */ 236 usb_log_debug("Port %zu change status: %x.\n", port, 237 (unsigned int) port_status); 238 239 if (usb_port_connect_change(&port_status)) { 240 bool device_connected = usb_port_dev_connected(&port_status); 241 usb_log_debug("Connection change on port %zu: %s.\n", port, 242 device_connected ? "device attached" : "device removed"); 243 244 if (device_connected) { 245 rc = add_device_phase1_new_fibril(hub, port, 246 usb_port_speed(&port_status)); 247 if (rc != EOK) { 248 usb_log_error( 249 "Cannot handle change on port %zu: %s.\n", 250 str_error(rc)); 251 } 252 } else { 253 usb_hub_removed_device(hub, port); 254 } 255 } 256 257 if (usb_port_overcurrent_change(&port_status)) { 258 if (usb_port_over_current(&port_status)) { 259 usb_log_warning("Overcurrent on port %zu.\n", port); 260 usb_hub_over_current(hub, port); 261 } else { 262 usb_log_debug("Overcurrent on port %zu autoresolved.\n", 263 port); 264 } 265 } 266 267 if (usb_port_reset_completed(&port_status)) { 268 usb_log_debug("Port %zu reset complete.\n", port); 269 if (usb_port_enabled(&port_status)) { 270 /* Finalize device adding. */ 271 usb_hub_port_t *the_port = hub->ports + port; 272 fibril_mutex_lock(&the_port->reset_mutex); 273 the_port->reset_completed = true; 274 fibril_condvar_broadcast(&the_port->reset_cv); 275 fibril_mutex_unlock(&the_port->reset_mutex); 276 } else { 277 usb_log_warning( 278 "Port %zu reset complete but port not enabled.\n", 279 port); 280 } 281 } 282 283 usb_port_set_connect_change(&port_status, false); 284 usb_port_set_reset(&port_status, false); 285 usb_port_set_reset_completed(&port_status, false); 286 usb_port_set_dev_connected(&port_status, false); 287 if (port_status >> 16) { 288 usb_log_warning("Unsupported change on port %zu: %x.\n", 289 port, (unsigned int) port_status); 290 } 291 } 292 293 294 /** Callback for polling hub for port changes. 295 * 296 * @param dev Device where the change occured. 297 * @param change_bitmap Bitmap of changed ports. 298 * @param change_bitmap_size Size of the bitmap in bytes. 299 * @param arg Custom argument, points to @c usb_hub_info_t. 300 * @return Whether to continue polling. 301 */ 302 bool hub_port_changes_callback(usb_device_t *dev, 303 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) 304 { 305 usb_hub_info_t *hub = (usb_hub_info_t *) arg; 306 307 /* FIXME: check that we received enough bytes. */ 308 if (change_bitmap_size == 0) { 309 goto leave; 310 } 311 312 size_t port; 313 for (port = 1; port < hub->port_count + 1; port++) { 314 bool change = (change_bitmap[port / 8] >> (port % 8)) % 2; 315 if (change) { 316 process_port_change(hub, port); 317 } 318 } 319 320 321 leave: 322 /* FIXME: proper interval. */ 323 async_usleep(1000 * 1000 * 10 ); 324 325 return true; 326 } 327 328 413 329 /** 414 330 * @} -
uspace/drv/usbhub/ports.h
r0748854 r77223f8 36 36 #define DRV_USBHUB_PORTS_H 37 37 38 #include <usb/devdrv.h> 38 #include <ipc/devman.h> 39 #include <usb/usb.h> 40 #include <ddf/driver.h> 41 #include <fibril_synch.h> 42 39 43 #include <usb/hub.h> 40 44 41 typedef struct usb_hub_info_t usb_hub_info_t; 45 #include <usb/pipes.h> 46 #include <usb/devdrv.h> 42 47 43 48 /** Information about single port on a hub. */ … … 67 72 } 68 73 69 70 void usb_hub_process_interrupt(usb_hub_info_t * hub, 71 uint16_t port); 72 74 bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *); 73 75 74 76 -
uspace/drv/usbhub/usbhub.c
r0748854 r77223f8 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <inttypes.h>40 39 41 40 #include <usb_iface.h> … … 54 53 #include "usb/classes/classes.h" 55 54 56 57 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev); 58 59 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info); 60 61 static int usb_hub_set_configuration(usb_hub_info_t * hub_info); 62 63 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info); 64 65 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 66 usb_hub_status_t status); 67 68 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 69 usb_hub_status_t status); 70 71 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info); 72 73 74 /// \TODO malloc checking 55 static int usb_hub_trigger_connecting_non_removable_devices( 56 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 57 75 58 76 59 //********************************************* … … 81 64 82 65 /** 83 * Initialize hub device driver fibril84 *85 * Creates hub representation and fibril that periodically checks hub`s status.86 * Hub representation is passed to the fibril.87 * @param usb_dev generic usb device information88 * @return error code89 */90 int usb_hub_add_device(usb_device_t * usb_dev) {91 if (!usb_dev) return EINVAL;92 usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);93 //create hc connection94 usb_log_debug("Initializing USB wire abstraction.\n");95 int opResult = usb_hc_connection_initialize_from_device(96 &hub_info->connection,97 hub_info->usb_device->ddf_dev);98 if (opResult != EOK) {99 usb_log_error("could not initialize connection to device, "100 "errno %d\n",101 opResult);102 free(hub_info);103 return opResult;104 }105 106 usb_pipe_start_session(hub_info->control_pipe);107 //set hub configuration108 opResult = usb_hub_set_configuration(hub_info);109 if (opResult != EOK) {110 usb_log_error("could not set hub configuration, errno %d\n",111 opResult);112 free(hub_info);113 return opResult;114 }115 //get port count and create attached_devs116 opResult = usb_hub_process_hub_specific_info(hub_info);117 if (opResult != EOK) {118 usb_log_error("could process hub specific info, errno %d\n",119 opResult);120 free(hub_info);121 return opResult;122 }123 usb_pipe_end_session(hub_info->control_pipe);124 125 /// \TODO what is this?126 usb_log_debug("Creating `hub' function.\n");127 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,128 fun_exposed, "hub");129 assert(hub_fun != NULL);130 hub_fun->ops = NULL;131 132 opResult = ddf_fun_bind(hub_fun);133 assert(opResult == EOK);134 opResult = ddf_fun_add_to_class(hub_fun, "hub");135 assert(opResult == EOK);136 137 opResult = usb_hub_start_hub_fibril(hub_info);138 if(opResult!=EOK)139 free(hub_info);140 return opResult;141 }142 143 144 /** Callback for polling hub for changes.145 *146 * @param dev Device where the change occured.147 * @param change_bitmap Bitmap of changed ports.148 * @param change_bitmap_size Size of the bitmap in bytes.149 * @param arg Custom argument, points to @c usb_hub_info_t.150 * @return Whether to continue polling.151 */152 bool hub_port_changes_callback(usb_device_t *dev,153 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {154 usb_hub_info_t *hub = (usb_hub_info_t *) arg;155 156 /* FIXME: check that we received enough bytes. */157 if (change_bitmap_size == 0) {158 goto leave;159 }160 161 bool change;162 change = ((uint8_t*) change_bitmap)[0] & 1;163 if (change) {164 usb_hub_process_global_interrupt(hub);165 }166 167 size_t port;168 for (port = 1; port < hub->port_count + 1; port++) {169 bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;170 if (change) {171 usb_hub_process_interrupt(hub, port);172 }173 }174 leave:175 /* FIXME: proper interval. */176 async_usleep(1000 * 1000 * 10);177 178 return true;179 }180 181 /**182 * release default address used by given hub183 *184 * Also unsets hub->is_default_address_used. Convenience wrapper function.185 * @note hub->connection MUST be open for communication186 * @param hub hub representation187 * @return error code188 */189 int usb_hub_release_default_address(usb_hub_info_t * hub) {190 int opResult = usb_hc_release_default_address(&hub->connection);191 if (opResult != EOK) {192 usb_log_error("could not release default address, errno %d\n",193 opResult);194 return opResult;195 }196 hub->is_default_address_used = false;197 return EOK;198 }199 200 201 //*********************************************202 //203 // support functions204 //205 //*********************************************206 207 /**208 66 * create usb_hub_info_t structure 209 67 * … … 213 71 */ 214 72 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) { 215 usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t));216 if 73 usb_hub_info_t * result = usb_new(usb_hub_info_t); 74 if(!result) return NULL; 217 75 result->usb_device = usb_dev; 218 76 result->status_change_pipe = usb_dev->pipes[0].pipe; … … 232 90 * @return error code 233 91 */ 234 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) 92 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info){ 235 93 // get hub descriptor 236 94 usb_log_debug("creating serialized descriptor\n"); 237 95 void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE); 238 96 usb_hub_descriptor_t * descriptor; 239 int opResult; 240 97 98 /* this was one fix of some bug, should not be needed anymore 99 * these lines allow to reset hub once more, it can be used as 100 * brute-force initialization for non-removable devices 101 int opResult = usb_request_set_configuration(&result->endpoints.control, 1); 102 if(opResult!=EOK){ 103 usb_log_error("could not set default configuration, errno %d",opResult); 104 return opResult; 105 } 106 */ 241 107 size_t received_size; 242 opResult = usb_request_get_descriptor(hub_info->control_pipe, 243 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, 244 USB_DESCTYPE_HUB, 0, 0, serialized_descriptor, 245 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 108 int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe, 109 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, 110 USB_DESCTYPE_HUB, 111 0, 0, serialized_descriptor, 112 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 246 113 247 114 if (opResult != EOK) { 248 usb_log_error("failed when receiving hub descriptor, " 249 "badcode = %d\n", 250 opResult); 115 usb_log_error("failed when receiving hub descriptor, badcode = %d\n", 116 opResult); 251 117 free(serialized_descriptor); 252 118 return opResult; … … 254 120 usb_log_debug2("deserializing descriptor\n"); 255 121 descriptor = usb_deserialize_hub_desriptor(serialized_descriptor); 256 if (descriptor == NULL){122 if(descriptor==NULL){ 257 123 usb_log_warning("could not deserialize descriptor \n"); 258 124 return opResult; 259 125 } 260 usb_log_debug("setting port count to %d\n", 126 usb_log_debug("setting port count to %d\n",descriptor->ports_count); 261 127 hub_info->port_count = descriptor->ports_count; 262 /// \TODO this is not semantically correct 263 hub_info->ports = malloc( 264 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 128 hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1)); 265 129 size_t port; 266 130 for (port = 0; port < hub_info->port_count + 1; port++) { 267 131 usb_hub_port_init(&hub_info->ports[port]); 268 132 } 133 //handle non-removable devices 134 usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor); 269 135 usb_log_debug2("freeing data\n"); 270 136 free(serialized_descriptor); … … 273 139 return EOK; 274 140 } 275 276 141 /** 277 142 * Set configuration of hub … … 282 147 * @return error code 283 148 */ 284 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) 149 static int usb_hub_set_configuration(usb_hub_info_t * hub_info){ 285 150 //device descriptor 286 151 usb_standard_device_descriptor_t *std_descriptor … … 288 153 usb_log_debug("hub has %d configurations\n", 289 154 std_descriptor->configuration_count); 290 if (std_descriptor->configuration_count < 1){155 if(std_descriptor->configuration_count<1){ 291 156 usb_log_error("there are no configurations available\n"); 292 157 return EINVAL; … … 308 173 } 309 174 usb_log_debug("\tused configuration %d\n", 310 175 config_descriptor->configuration_number); 311 176 312 177 return EOK; … … 314 179 315 180 /** 316 * create and start fibril with hub control loop 317 * 318 * Before the fibril is started, the control pipe and host controller 319 * connection of the hub is open. 320 * 321 * @param hub_info hub representing structure 181 * Initialize hub device driver fibril 182 * 183 * Creates hub representation and fibril that periodically checks hub`s status. 184 * Hub representation is passed to the fibril. 185 * @param usb_dev generic usb device information 322 186 * @return error code 323 187 */ 324 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){ 188 int usb_hub_add_device(usb_device_t * usb_dev){ 189 if(!usb_dev) return EINVAL; 190 usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev); 191 //create hc connection 192 usb_log_debug("Initializing USB wire abstraction.\n"); 193 int opResult = usb_hc_connection_initialize_from_device( 194 &hub_info->connection, 195 hub_info->usb_device->ddf_dev); 196 if(opResult != EOK){ 197 usb_log_error("could not initialize connection to device, errno %d\n", 198 opResult); 199 free(hub_info); 200 return opResult; 201 } 202 203 usb_pipe_start_session(hub_info->control_pipe); 204 //set hub configuration 205 opResult = usb_hub_set_configuration(hub_info); 206 if(opResult!=EOK){ 207 usb_log_error("could not set hub configuration, errno %d\n",opResult); 208 free(hub_info); 209 return opResult; 210 } 211 //get port count and create attached_devs 212 opResult = usb_hub_process_hub_specific_info(hub_info); 213 if(opResult!=EOK){ 214 usb_log_error("could not set hub configuration, errno %d\n",opResult); 215 free(hub_info); 216 return opResult; 217 } 218 usb_pipe_end_session(hub_info->control_pipe); 219 220 221 /// \TODO what is this? 222 usb_log_debug("Creating `hub' function.\n"); 223 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev, 224 fun_exposed, "hub"); 225 assert(hub_fun != NULL); 226 hub_fun->ops = NULL; 227 228 int rc = ddf_fun_bind(hub_fun); 229 assert(rc == EOK); 230 rc = ddf_fun_add_to_class(hub_fun, "hub"); 231 assert(rc == EOK); 232 325 233 /* 326 234 * The processing will require opened control pipe and connection … … 331 239 * auto destruction, this could work better. 332 240 */ 333 int rc = usb_pipe_start_session(hub_info->control_pipe);241 rc = usb_pipe_start_session(&usb_dev->ctrl_pipe); 334 242 if (rc != EOK) { 335 243 usb_log_error("Failed to start session on control pipe: %s.\n", 336 244 str_error(rc)); 337 return rc;245 goto leave; 338 246 } 339 247 rc = usb_hc_connection_open(&hub_info->connection); 340 248 if (rc != EOK) { 341 usb_pipe_end_session( hub_info->control_pipe);249 usb_pipe_end_session(&usb_dev->ctrl_pipe); 342 250 usb_log_error("Failed to open connection to HC: %s.\n", 343 251 str_error(rc)); 344 return rc;252 goto leave; 345 253 } 346 254 347 255 rc = usb_device_auto_poll(hub_info->usb_device, 0, 348 hub_port_changes_callback, ((hub_info->port_count +1) / 8) + 1,256 hub_port_changes_callback, ((hub_info->port_count+1) / 8) + 1, 349 257 NULL, hub_info); 350 258 if (rc != EOK) { … … 358 266 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 359 267 return EOK; 360 } 268 269 leave: 270 free(hub_info); 271 272 return rc; 273 } 274 361 275 362 276 //********************************************* 363 277 // 364 // change handling functions278 // hub driver code, main loop and port handling 365 279 // 366 280 //********************************************* 367 281 368 369 /** 370 * process hub over current change371 * 372 * This means either to power off the hub or power iton.373 * @param hub _info hub instance374 * @param status hub status bitmask282 /** 283 * triggers actions to connect non0removable devices 284 * 285 * This will trigger operations leading to activated non-removable device. 286 * Control pipe of the hub must be open fo communication. 287 * @param hub hub representation 288 * @param descriptor usb hub descriptor 375 289 * @return error code 376 290 */ 377 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 378 usb_hub_status_t status) { 291 static int usb_hub_trigger_connecting_non_removable_devices(usb_hub_info_t * hub, 292 usb_hub_descriptor_t * descriptor) 293 { 294 usb_log_info("attaching non-removable devices(if any)\n"); 295 usb_device_request_setup_packet_t request; 379 296 int opResult; 380 if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_OVER_CURRENT)){ 381 opResult = usb_hub_clear_feature(hub_info->control_pipe, 382 USB_HUB_FEATURE_HUB_LOCAL_POWER); 383 if (opResult != EOK) { 384 usb_log_error("cannot power off hub: %d\n", 385 opResult); 386 } 387 } else { 388 opResult = usb_hub_set_feature(hub_info->control_pipe, 389 USB_HUB_FEATURE_HUB_LOCAL_POWER); 390 if (opResult != EOK) { 391 usb_log_error("cannot power on hub: %d\n", 392 opResult); 393 } 394 } 395 return opResult; 396 } 397 398 /** 399 * process hub power change 400 * 401 * If the power has been lost, reestablish it. 402 * If it was reestablished, re-power all ports. 403 * @param hub_info hub instance 404 * @param status hub status bitmask 405 * @return error code 406 */ 407 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 408 usb_hub_status_t status) { 409 int opResult; 410 if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) { 411 //restart power on hub 412 opResult = usb_hub_set_feature(hub_info->control_pipe, 413 USB_HUB_FEATURE_HUB_LOCAL_POWER); 414 if (opResult != EOK) { 415 usb_log_error("cannot power on hub: %d\n", 416 opResult); 417 } 418 } else {//power reestablished on hub- restart ports 419 size_t port; 420 for (port = 0; port < hub_info->port_count; ++port) { 421 opResult = usb_hub_set_port_feature( 422 hub_info->control_pipe, 423 port, USB_HUB_FEATURE_PORT_POWER); 297 size_t rcvd_size; 298 usb_port_status_t status; 299 uint8_t * non_removable_dev_bitmap = descriptor->devices_removable; 300 int port; 301 for(port=1;port<=descriptor->ports_count;++port){ 302 bool is_non_removable = 303 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2; 304 if(is_non_removable){ 305 usb_log_debug("non-removable device on port %d\n",port); 306 usb_hub_set_port_status_request(&request, port); 307 opResult = usb_pipe_control_read( 308 hub->control_pipe, 309 &request, sizeof(usb_device_request_setup_packet_t), 310 &status, 4, &rcvd_size 311 ); 424 312 if (opResult != EOK) { 425 usb_log_error("cannot power on port %d; %d\n", 426 port, opResult); 313 usb_log_error("could not get port status of port %d errno:%d\n", 314 port, opResult); 315 return opResult; 316 } 317 //set the status change bit, so it will be noticed in driver loop 318 if(usb_port_dev_connected(&status)){ 319 usb_hub_set_disable_port_feature_request(&request, port, 320 USB_HUB_FEATURE_PORT_CONNECTION); 321 opResult = usb_pipe_control_read( 322 hub->control_pipe, 323 &request, sizeof(usb_device_request_setup_packet_t), 324 &status, 4, &rcvd_size 325 ); 326 if (opResult != EOK) { 327 usb_log_warning( 328 "could not clear port connection on port %d errno:%d\n", 329 port, opResult); 330 } 331 usb_log_debug("cleared port connection\n"); 332 usb_hub_set_enable_port_feature_request(&request, port, 333 USB_HUB_FEATURE_PORT_ENABLE); 334 opResult = usb_pipe_control_read( 335 hub->control_pipe, 336 &request, sizeof(usb_device_request_setup_packet_t), 337 &status, 4, &rcvd_size 338 ); 339 if (opResult != EOK) { 340 usb_log_warning( 341 "could not set port enabled on port %d errno:%d\n", 342 port, opResult); 343 } 344 usb_log_debug("port set to enabled - should lead to connection change\n"); 427 345 } 428 346 } 429 347 } 430 return opResult; 431 } 432 433 /** 434 * process hub interrupts 435 * 436 * The change can be either in the over-current condition or 437 * local-power lost condition. 438 * @param hub_info hub instance 439 */ 440 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info) { 441 usb_log_debug("global interrupt on a hub\n"); 442 usb_pipe_t *pipe = hub_info->control_pipe; 348 /// \TODO this is just a debug code 349 for(port=1;port<=descriptor->ports_count;++port){ 350 bool is_non_removable = 351 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2; 352 if(is_non_removable){ 353 usb_log_debug("port %d is non-removable\n",port); 354 usb_port_status_t status; 355 size_t rcvd_size; 356 usb_device_request_setup_packet_t request; 357 //int opResult; 358 usb_hub_set_port_status_request(&request, port); 359 //endpoint 0 360 opResult = usb_pipe_control_read( 361 hub->control_pipe, 362 &request, sizeof(usb_device_request_setup_packet_t), 363 &status, 4, &rcvd_size 364 ); 365 if (opResult != EOK) { 366 usb_log_error("could not get port status %d\n",opResult); 367 } 368 if (rcvd_size != sizeof (usb_port_status_t)) { 369 usb_log_error("received status has incorrect size\n"); 370 } 371 //something connected/disconnected 372 if (usb_port_connect_change(&status)) { 373 usb_log_debug("some connection changed\n"); 374 } 375 usb_log_debug("status: %s\n",usb_debug_str_buffer( 376 (uint8_t *)&status,4,4)); 377 } 378 } 379 return EOK; 380 } 381 382 383 /** 384 * release default address used by given hub 385 * 386 * Also unsets hub->is_default_address_used. Convenience wrapper function. 387 * @note hub->connection MUST be open for communication 388 * @param hub hub representation 389 * @return error code 390 */ 391 static int usb_hub_release_default_address(usb_hub_info_t * hub){ 392 int opResult = usb_hc_release_default_address(&hub->connection); 393 if(opResult!=EOK){ 394 usb_log_error("could not release default address, errno %d\n",opResult); 395 return opResult; 396 } 397 hub->is_default_address_used = false; 398 return EOK; 399 } 400 401 /** 402 * routine called when a device on port has been removed 403 * 404 * If the device on port had default address, it releases default address. 405 * Otherwise does not do anything, because DDF does not allow to remove device 406 * from it`s device tree. 407 * @param hub hub representation 408 * @param port port number, starting from 1 409 */ 410 void usb_hub_removed_device( 411 usb_hub_info_t * hub,uint16_t port) { 412 413 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 414 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 415 if(opResult != EOK){ 416 usb_log_warning("could not clear port-change-connection flag\n"); 417 } 418 /** \TODO remove device from device manager - not yet implemented in 419 * devide manager 420 */ 421 422 //close address 423 if(hub->ports[port].attached_device.address >= 0){ 424 /*uncomment this code to use it when DDF allows device removal 425 opResult = usb_hc_unregister_device( 426 &hub->connection, hub->attached_devs[port].address); 427 if(opResult != EOK) { 428 dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \ 429 "removed device: %d", opResult); 430 } 431 hub->attached_devs[port].address = 0; 432 hub->attached_devs[port].handle = 0; 433 */ 434 }else{ 435 usb_log_warning("this is strange, disconnected device had no address\n"); 436 //device was disconnected before it`s port was reset - return default address 437 usb_hub_release_default_address(hub); 438 } 439 } 440 441 442 /** 443 * Process over current condition on port. 444 * 445 * Turn off the power on the port. 446 * 447 * @param hub hub representation 448 * @param port port number, starting from 1 449 */ 450 void usb_hub_over_current( usb_hub_info_t * hub, 451 uint16_t port){ 443 452 int opResult; 444 445 usb_port_status_t status; 446 size_t rcvd_size; 447 usb_device_request_setup_packet_t request; 448 //int opResult; 449 usb_hub_set_hub_status_request(&request); 450 //endpoint 0 451 452 opResult = usb_pipe_control_read( 453 pipe, 454 &request, sizeof (usb_device_request_setup_packet_t), 455 &status, 4, &rcvd_size 456 ); 457 if (opResult != EOK) { 458 usb_log_error("could not get hub status\n"); 459 return; 460 } 461 if (rcvd_size != sizeof (usb_port_status_t)) { 462 usb_log_error("received status has incorrect size\n"); 463 return; 464 } 465 //port reset 466 if ( 467 usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) { 468 usb_process_hub_over_current(hub_info, status); 469 } 470 if ( 471 usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) { 472 usb_process_hub_power_change(hub_info, status); 473 } 474 } 453 opResult = usb_hub_clear_port_feature(hub->control_pipe, 454 port, USB_HUB_FEATURE_PORT_POWER); 455 if(opResult!=EOK){ 456 usb_log_error("cannot power off port %d; %d\n", 457 port, opResult); 458 } 459 } 460 475 461 476 462 /** -
uspace/drv/usbhub/usbhub.h
r0748854 r77223f8 37 37 38 38 #include <ipc/devman.h> 39 #include <usb/usb.h> 39 40 #include <ddf/driver.h> 40 41 42 #define NAME "usbhub" 43 41 44 #include <usb/hub.h> 42 #include <usb/classes/hub.h>43 45 44 46 #include <usb/pipes.h> 45 47 #include <usb/devdrv.h> 46 47 #include <fibril_synch.h>48 49 #define NAME "usbhub"50 48 51 49 #include "ports.h" … … 54 52 55 53 /** Information about attached hub. */ 56 struct usb_hub_info_t{54 typedef struct { 57 55 /** Number of ports. */ 58 56 size_t port_count; 59 57 60 /** attached device handles, for each port one*/58 /** Ports. */ 61 59 usb_hub_port_t *ports; 62 60 63 61 /** connection to hcd */ 64 62 usb_hc_connection_t connection; … … 89 87 /** generic usb device data*/ 90 88 usb_device_t * usb_device; 91 } ;89 } usb_hub_info_t; 92 90 93 //int usb_hub_control_loop(void * hub_info_param); 91 /** 92 * function running the hub-controlling loop. 93 * @param hub_info_param hub info pointer 94 */ 95 int usb_hub_control_loop(void * hub_info_param); 96 97 /** 98 * Check changes on specified hub 99 * @param hub_info_param pointer to usb_hub_info_t structure 100 * @return error code if there is problem when initializing communication with 101 * hub, EOK otherwise 102 */ 103 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param); 104 105 void usb_hub_removed_device(usb_hub_info_t *, uint16_t); 106 void usb_hub_over_current(usb_hub_info_t *, uint16_t); 94 107 95 108 int usb_hub_add_device(usb_device_t * usb_dev); 96 97 bool hub_port_changes_callback(usb_device_t *dev,98 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);99 100 int usb_hub_release_default_address(usb_hub_info_t * hub);101 109 102 110 #endif -
uspace/drv/usbhub/usbhub_private.h
r0748854 r77223f8 54 54 // 55 55 //************ 56 #define usb_new(type) (type*)malloc(sizeof(type)) 56 57 57 58 59 /** 60 * Create hub structure instance 61 * 62 * Set the address and port count information most importantly. 63 * 64 * @param device 65 * @param hc host controller phone 66 * @return 67 */ 58 68 usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device); 59 69 … … 100 110 101 111 /** 102 * Clear feature on hub port.103 *104 * @param hc Host controller telephone105 * @param address Hub address106 * @param port_index Port107 * @param feature Feature selector108 * @return Operation result109 */110 static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,111 int port_index,112 usb_hub_class_feature_t feature) {113 114 usb_device_request_setup_packet_t clear_request = {115 .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,116 .request = USB_DEVREQ_SET_FEATURE,117 .length = 0,118 .index = port_index119 };120 clear_request.value = feature;121 return usb_pipe_control_write(pipe, &clear_request,122 sizeof(clear_request), NULL, 0);123 }124 125 126 /**127 * Clear feature on hub port.128 *129 * @param pipe pipe to hub control endpoint130 * @param feature Feature selector131 * @return Operation result132 */133 static inline int usb_hub_clear_feature(usb_pipe_t *pipe,134 usb_hub_class_feature_t feature) {135 136 usb_device_request_setup_packet_t clear_request = {137 .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,138 .request = USB_DEVREQ_CLEAR_FEATURE,139 .length = 0,140 .index = 0141 };142 clear_request.value = feature;143 return usb_pipe_control_write(pipe, &clear_request,144 sizeof(clear_request), NULL, 0);145 }146 147 /**148 * Clear feature on hub port.149 *150 * @param pipe pipe to hub control endpoint151 * @param feature Feature selector152 * @return Operation result153 */154 static inline int usb_hub_set_feature(usb_pipe_t *pipe,155 usb_hub_class_feature_t feature) {156 157 usb_device_request_setup_packet_t clear_request = {158 .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,159 .request = USB_DEVREQ_SET_FEATURE,160 .length = 0,161 .index = 0162 };163 clear_request.value = feature;164 return usb_pipe_control_write(pipe, &clear_request,165 sizeof(clear_request), NULL, 0);166 }167 168 /**169 112 * create uint8_t array with serialized descriptor 170 113 * -
uspace/drv/usbhub/utils.c
r0748854 r77223f8 60 60 size_t size = 7; 61 61 //variable size according to port count 62 size_t var_size = (descriptor->ports_count+7)/8;62 size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0); 63 63 size += 2 * var_size; 64 uint8_t * result = malloc(size);64 uint8_t * result = (uint8_t*) malloc(size); 65 65 //size 66 66 result[0] = size; … … 84 84 } 85 85 86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor( 87 void * serialized_descriptor) { 88 uint8_t * sdescriptor = serialized_descriptor; 86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) { 87 uint8_t * sdescriptor = (uint8_t*) serialized_descriptor; 89 88 90 89 if (sdescriptor[1] != USB_DESCTYPE_HUB) { 91 usb_log_warning("trying to deserialize wrong descriptor %x\n", 92 sdescriptor[1]); 90 usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]); 93 91 return NULL; 94 92 } 95 93 96 usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t));94 usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t); 97 95 98 96 … … 102 100 result->pwr_on_2_good_time = sdescriptor[5]; 103 101 result->current_requirement = sdescriptor[6]; 104 size_t var_size = (result->ports_count+7) / 8; 102 size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0) 103 ? 1 : 0); 105 104 result->devices_removable = (uint8_t*) malloc(var_size); 106 105 -
uspace/lib/usb/include/usb/classes/hub.h
r0748854 r77223f8 43 43 */ 44 44 typedef enum { 45 USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,46 USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,47 45 USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0, 48 46 USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1, … … 61 59 /* USB_HUB_FEATURE_ = , */ 62 60 } usb_hub_class_feature_t; 63 64 61 65 62 /** Header of standard hub descriptor without the "variadic" part. */ -
uspace/lib/usb/include/usb/host/device_keeper.h
r0748854 r77223f8 71 71 void usb_device_keeper_init(usb_device_keeper_t *instance); 72 72 73 void usb_device_keeper_add_ep( 74 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep); 75 void usb_device_keeper_del_ep( 76 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep); 77 73 78 void usb_device_keeper_reserve_default_address( 74 79 usb_device_keeper_t *instance, usb_speed_t speed); -
uspace/lib/usb/include/usb/host/endpoint.h
r0748854 r77223f8 54 54 fibril_condvar_t avail; 55 55 volatile bool active; 56 link_t same_device_eps; 56 57 } endpoint_t; 57 58 … … 70 71 void endpoint_toggle_set(endpoint_t *instance, int toggle); 71 72 72 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 73 void endpoint_toggle_reset(link_t *ep); 74 75 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn); 76 73 77 #endif 74 78 /** -
uspace/lib/usb/include/usb/host/usb_endpoint_manager.h
r0748854 r77223f8 78 78 size_t *bw); 79 79 80 void usb_endpoint_manager_reset_if_need(81 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);82 80 #endif 83 81 /** -
uspace/lib/usb/src/host/device_keeper.c
r0748854 r77223f8 54 54 for (; i < USB_ADDRESS_COUNT; ++i) { 55 55 instance->devices[i].occupied = false; 56 instance->devices[i].control_used = 0; 56 57 instance->devices[i].handle = 0; 57 58 instance->devices[i].speed = USB_SPEED_MAX; 59 list_initialize(&instance->devices[i].endpoints); 58 60 } 59 61 // TODO: is this hack enough? … … 62 64 } 63 65 /*----------------------------------------------------------------------------*/ 66 void usb_device_keeper_add_ep( 67 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep) 68 { 69 assert(instance); 70 fibril_mutex_lock(&instance->guard); 71 assert(instance->devices[address].occupied); 72 list_append(&ep->same_device_eps, &instance->devices[address].endpoints); 73 fibril_mutex_unlock(&instance->guard); 74 } 75 /*----------------------------------------------------------------------------*/ 76 void usb_device_keeper_del_ep( 77 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep) 78 { 79 assert(instance); 80 fibril_mutex_lock(&instance->guard); 81 assert(instance->devices[address].occupied); 82 list_remove(&ep->same_device_eps); 83 list_initialize(&ep->same_device_eps); 84 fibril_mutex_unlock(&instance->guard); 85 } 86 /*----------------------------------------------------------------------------*/ 64 87 /** Attempt to obtain address 0, blocks. 65 88 * … … 94 117 } 95 118 /*----------------------------------------------------------------------------*/ 119 /** Check setup packet data for signs of toggle reset. 120 * 121 * @param[in] instance Device keeper structure to use. 122 * @param[in] target Device to receive setup packet. 123 * @param[in] data Setup packet data. 124 * 125 * Really ugly one. 126 */ 127 void usb_device_keeper_reset_if_need( 128 usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data) 129 { 130 assert(instance); 131 fibril_mutex_lock(&instance->guard); 132 if (target.endpoint > 15 || target.endpoint < 0 133 || target.address >= USB_ADDRESS_COUNT || target.address < 0 134 || !instance->devices[target.address].occupied) { 135 fibril_mutex_unlock(&instance->guard); 136 usb_log_error("Invalid data when checking for toggle reset.\n"); 137 return; 138 } 139 140 switch (data[1]) 141 { 142 case 0x01: /*clear feature*/ 143 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 144 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 145 link_t *current = 146 instance->devices[target.address].endpoints.next; 147 while (current != 148 &instance->devices[target.address].endpoints) 149 { 150 /* endpoint number is < 16, thus first byte is enough */ 151 endpoint_toggle_reset_filtered( 152 current, data[4]); 153 current = current->next; 154 } 155 } 156 break; 157 158 case 0x9: /* set configuration */ 159 case 0x11: /* set interface */ 160 /* target must be device */ 161 if ((data[0] & 0xf) == 0) { 162 link_t *current = 163 instance->devices[target.address].endpoints.next; 164 while (current != 165 &instance->devices[target.address].endpoints) 166 { 167 endpoint_toggle_reset(current); 168 current = current->next; 169 } 170 } 171 break; 172 } 173 fibril_mutex_unlock(&instance->guard); 174 } 96 175 /*----------------------------------------------------------------------------*/ 97 176 /** Get a free USB address -
uspace/lib/usb/src/host/endpoint.c
r0748854 r77223f8 53 53 fibril_mutex_initialize(&instance->guard); 54 54 fibril_condvar_initialize(&instance->avail); 55 link_initialize(&instance->same_device_eps); 55 56 return EOK; 56 57 } … … 60 61 assert(instance); 61 62 assert(!instance->active); 63 list_remove(&instance->same_device_eps); 62 64 free(instance); 63 65 } … … 95 97 } 96 98 /*----------------------------------------------------------------------------*/ 97 void endpoint_toggle_reset _filtered(endpoint_t *instance, usb_target_t target)99 void endpoint_toggle_reset(link_t *ep) 98 100 { 101 endpoint_t *instance = 102 list_get_instance(ep, endpoint_t, same_device_eps); 99 103 assert(instance); 100 if (instance->address == target.address && 101 instance->endpoint == target.endpoint) 104 instance->toggle = 0; 105 } 106 /*----------------------------------------------------------------------------*/ 107 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn) 108 { 109 endpoint_t *instance = 110 list_get_instance(ep, endpoint_t, same_device_eps); 111 assert(instance); 112 if (instance->endpoint == epn) 102 113 instance->toggle = 0; 103 114 } -
uspace/lib/usb/src/host/usb_endpoint_manager.c
r0748854 r77223f8 31 31 #include <errno.h> 32 32 33 #include <usb/debug.h>34 33 #include <usb/host/usb_endpoint_manager.h> 35 34 … … 81 80 endpoint_destroy(node->ep); 82 81 free(node); 83 }84 /*----------------------------------------------------------------------------*/85 static void node_toggle_reset_filtered(link_t *item, void *arg)86 {87 assert(item);88 node_t *node = hash_table_get_instance(item, node_t, link);89 usb_target_t *target = arg;90 endpoint_toggle_reset_filtered(node->ep, *target);91 82 } 92 83 /*----------------------------------------------------------------------------*/ … … 239 230 return node->ep; 240 231 } 241 /*----------------------------------------------------------------------------*/242 /** Check setup packet data for signs of toggle reset.243 *244 * @param[in] instance Device keeper structure to use.245 * @param[in] target Device to receive setup packet.246 * @param[in] data Setup packet data.247 *248 * Really ugly one.249 */250 void usb_endpoint_manager_reset_if_need(251 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)252 {253 assert(instance);254 if (target.endpoint > 15 || target.endpoint < 0255 || target.address >= USB11_ADDRESS_MAX || target.address < 0) {256 usb_log_error("Invalid data when checking for toggle reset.\n");257 return;258 }259 260 switch (data[1])261 {262 case 0x01: /*clear feature*/263 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */264 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {265 /* endpoint number is < 16, thus first byte is enough */266 usb_target_t reset_target =267 { .address = target.address, data[4] };268 fibril_mutex_lock(&instance->guard);269 hash_table_apply(&instance->ep_table,270 node_toggle_reset_filtered, &reset_target);271 fibril_mutex_unlock(&instance->guard);272 }273 break;274 275 case 0x9: /* set configuration */276 case 0x11: /* set interface */277 /* target must be device */278 if ((data[0] & 0xf) == 0) {279 usb_target_t reset_target =280 { .address = target.address, 0 };281 fibril_mutex_lock(&instance->guard);282 hash_table_apply(&instance->ep_table,283 node_toggle_reset_filtered, &reset_target);284 fibril_mutex_unlock(&instance->guard);285 }286 break;287 }288 }
Note:
See TracChangeset
for help on using the changeset viewer.