Changeset 501e5df in mainline
- Timestamp:
- 2011-04-09T20:56:50Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ba038f4
- Parents:
- 8790650 (diff), 709e868 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- uspace
- Files:
-
- 2 added
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/usbinfo/dev.c
r8790650 r501e5df 50 50 51 51 int rc; 52 bool transfer_started = false; 52 53 53 54 rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr); … … 76 77 } 77 78 78 rc = usb_pipe_start_ session(&dev->ctrl_pipe);79 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe); 79 80 if (rc != EOK) { 80 81 fprintf(stderr, 81 NAME ": failed to start sessionon control pipe: %s.\n",82 NAME ": failed to start transfer on control pipe: %s.\n", 82 83 str_error(rc)); 83 84 goto leave; 84 85 } 86 transfer_started = true; 85 87 86 88 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, … … 107 109 108 110 leave: 109 if ( usb_pipe_is_session_started(&dev->ctrl_pipe)) {110 usb_pipe_end_ session(&dev->ctrl_pipe);111 if (transfer_started) { 112 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 111 113 } 112 114 … … 118 120 void destroy_device(usbinfo_device_t *dev) 119 121 { 120 usb_pipe_end_ session(&dev->ctrl_pipe);122 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 121 123 free(dev); 122 124 } -
uspace/doc/doxygroups.h
r8790650 r501e5df 269 269 270 270 /** 271 * @defgroup drvusbohci OHCI driver 272 * @ingroup usb 273 * @brief Driver for OHCI host controller. 274 */ 275 276 /** 271 277 * @defgroup drvusbehci EHCI driver 272 278 * @ingroup usb … … 275 281 276 282 /** 277 * @defgroup drvusbfallback USB fallback driver .283 * @defgroup drvusbfallback USB fallback driver 278 284 * @ingroup usb 279 285 * @brief Fallback driver for any USB device. -
uspace/drv/ehci-hcd/hc_iface.c
r8790650 r501e5df 123 123 * @param[in] fun Device function the action was invoked on. 124 124 * @param[in] address USB address of the device. 125 * @param[in] speed Endpoint speed (invalid means to use device one). 125 126 * @param[in] endpoint Endpoint number. 126 127 * @param[in] transfer_type USB transfer type. … … 131 132 */ 132 133 static int register_endpoint(ddf_fun_t *fun, 133 usb_address_t address, usb_ endpoint_t endpoint,134 usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint, 134 135 usb_transfer_type_t transfer_type, usb_direction_t direction, 135 136 size_t max_packet_size, unsigned int interval) … … 165 166 * @param[in] fun Device function the action was invoked on. 166 167 * @param[in] target Target pipe (address and endpoint number) specification. 167 * @param[in] max_packet_size Max packet size for the transfer.168 168 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 169 169 * by the caller). … … 174 174 */ 175 175 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 176 size_t max_packet_size,void *data, size_t size,176 void *data, size_t size, 177 177 usbhc_iface_transfer_out_callback_t callback, void *arg) 178 178 { … … 191 191 * @param[in] fun Device function the action was invoked on. 192 192 * @param[in] target Target pipe (address and endpoint number) specification. 193 * @param[in] max_packet_size Max packet size for the transfer.194 193 * @param[in] data Buffer where to store the data (in USB endianess, 195 194 * allocated and deallocated by the caller). … … 200 199 */ 201 200 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 202 size_t max_packet_size,void *data, size_t size,201 void *data, size_t size, 203 202 usbhc_iface_transfer_in_callback_t callback, void *arg) 204 203 { … … 217 216 * @param[in] fun Device function the action was invoked on. 218 217 * @param[in] target Target pipe (address and endpoint number) specification. 219 * @param[in] max_packet_size Max packet size for the transfer.220 218 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 221 219 * by the caller). … … 226 224 */ 227 225 static int bulk_out(ddf_fun_t *fun, usb_target_t target, 228 size_t max_packet_size,void *data, size_t size,226 void *data, size_t size, 229 227 usbhc_iface_transfer_out_callback_t callback, void *arg) 230 228 { … … 243 241 * @param[in] fun Device function the action was invoked on. 244 242 * @param[in] target Target pipe (address and endpoint number) specification. 245 * @param[in] max_packet_size Max packet size for the transfer.246 243 * @param[in] data Buffer where to store the data (in USB endianess, 247 244 * allocated and deallocated by the caller). … … 252 249 */ 253 250 static int bulk_in(ddf_fun_t *fun, usb_target_t target, 254 size_t max_packet_size,void *data, size_t size,251 void *data, size_t size, 255 252 usbhc_iface_transfer_in_callback_t callback, void *arg) 256 253 { … … 269 266 * @param[in] fun Device function the action was invoked on. 270 267 * @param[in] target Target pipe (address and endpoint number) specification. 271 * @param[in] max_packet_size Max packet size for the transfer.272 268 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 273 269 * and deallocated by the caller). … … 281 277 */ 282 278 static int control_write(ddf_fun_t *fun, usb_target_t target, 283 size_t max_packet_size,284 279 void *setup_packet, size_t setup_packet_size, 285 280 void *data_buffer, size_t data_buffer_size, … … 300 295 * @param[in] fun Device function the action was invoked on. 301 296 * @param[in] target Target pipe (address and endpoint number) specification. 302 * @param[in] max_packet_size Max packet size for the transfer.303 297 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 304 298 * and deallocated by the caller). … … 312 306 */ 313 307 static int control_read(ddf_fun_t *fun, usb_target_t target, 314 size_t max_packet_size,315 308 void *setup_packet, size_t setup_packet_size, 316 309 void *data_buffer, size_t data_buffer_size, -
uspace/drv/ohci/iface.c
r8790650 r501e5df 197 197 } 198 198 /*----------------------------------------------------------------------------*/ 199 static int register_endpoint( 200 ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint, 199 /** Register endpoint for bandwidth reservation. 200 * 201 * @param[in] fun Device function the action was invoked on. 202 * @param[in] address USB address of the device. 203 * @param[in] ep_speed Endpoint speed (invalid means to use device one). 204 * @param[in] endpoint Endpoint number. 205 * @param[in] transfer_type USB transfer type. 206 * @param[in] direction Endpoint data direction. 207 * @param[in] max_packet_size Max packet size of the endpoint. 208 * @param[in] interval Polling interval. 209 * @return Error code. 210 */ 211 static int register_endpoint(ddf_fun_t *fun, 212 usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint, 201 213 usb_transfer_type_t transfer_type, usb_direction_t direction, 202 214 size_t max_packet_size, unsigned int interval) … … 204 216 hc_t *hc = fun_to_hc(fun); 205 217 assert(hc); 206 const usb_speed_t speed = 207 usb_device_keeper_get_speed(&hc->manager, address); 218 if (address == hc->rh.address) 219 return EOK; 220 usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address); 221 if (speed >= USB_SPEED_MAX) { 222 speed = ep_speed; 223 } 208 224 const size_t size = 209 225 (transfer_type == USB_TRANSFER_INTERRUPT … … 243 259 usb_log_debug("Unregister endpoint %d:%d %d.\n", 244 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 } 245 266 return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address, 246 267 endpoint, direction); 247 268 } 248 269 /*----------------------------------------------------------------------------*/ 249 /** Interrupt out transaction interface function 250 * 251 * @param[in] fun DDF function that was called. 252 * @param[in] target USB device to write to. 253 * @param[in] max_packet_size maximum size of data packet the device accepts 254 * @param[in] data Source of data. 255 * @param[in] size Size of data source. 256 * @param[in] callback Function to call on transaction completion 257 * @param[in] arg Additional for callback function. 270 /** Schedule interrupt out transfer. 271 * 272 * The callback is supposed to be called once the transfer (on the wire) is 273 * complete regardless of the outcome. 274 * However, the callback could be called only when this function returns 275 * with success status (i.e. returns EOK). 276 * 277 * @param[in] fun Device function the action was invoked on. 278 * @param[in] target Target pipe (address and endpoint number) specification. 279 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 280 * by the caller). 281 * @param[in] size Size of the @p data buffer in bytes. 282 * @param[in] callback Callback to be issued once the transfer is complete. 283 * @param[in] arg Pass-through argument to the callback. 258 284 * @return Error code. 259 285 */ 260 286 static int interrupt_out( 261 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,287 ddf_fun_t *fun, usb_target_t target, void *data, 262 288 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 263 289 { … … 276 302 } 277 303 /*----------------------------------------------------------------------------*/ 278 /** Interrupt in transaction interface function 279 * 280 * @param[in] fun DDF function that was called. 281 * @param[in] target USB device to write to. 282 * @param[in] max_packet_size maximum size of data packet the device accepts 283 * @param[out] data Data destination. 284 * @param[in] size Size of data source. 285 * @param[in] callback Function to call on transaction completion 286 * @param[in] arg Additional for callback function. 304 /** Schedule interrupt in transfer. 305 * 306 * The callback is supposed to be called once the transfer (on the wire) is 307 * complete regardless of the outcome. 308 * However, the callback could be called only when this function returns 309 * with success status (i.e. returns EOK). 310 * 311 * @param[in] fun Device function the action was invoked on. 312 * @param[in] target Target pipe (address and endpoint number) specification. 313 * @param[in] data Buffer where to store the data (in USB endianess, 314 * allocated and deallocated by the caller). 315 * @param[in] size Size of the @p data buffer in bytes. 316 * @param[in] callback Callback to be issued once the transfer is complete. 317 * @param[in] arg Pass-through argument to the callback. 287 318 * @return Error code. 288 319 */ 289 320 static int interrupt_in( 290 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,321 ddf_fun_t *fun, usb_target_t target, void *data, 291 322 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 292 323 { … … 305 336 } 306 337 /*----------------------------------------------------------------------------*/ 307 /** Bulk out transaction interface function 308 * 309 * @param[in] fun DDF function that was called. 310 * @param[in] target USB device to write to. 311 * @param[in] max_packet_size maximum size of data packet the device accepts 312 * @param[in] data Source of data. 313 * @param[in] size Size of data source. 314 * @param[in] callback Function to call on transaction completion 315 * @param[in] arg Additional for callback function. 338 /** Schedule bulk out transfer. 339 * 340 * The callback is supposed to be called once the transfer (on the wire) is 341 * complete regardless of the outcome. 342 * However, the callback could be called only when this function returns 343 * with success status (i.e. returns EOK). 344 * 345 * @param[in] fun Device function the action was invoked on. 346 * @param[in] target Target pipe (address and endpoint number) specification. 347 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 348 * by the caller). 349 * @param[in] size Size of the @p data buffer in bytes. 350 * @param[in] callback Callback to be issued once the transfer is complete. 351 * @param[in] arg Pass-through argument to the callback. 316 352 * @return Error code. 317 353 */ 318 354 static int bulk_out( 319 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,355 ddf_fun_t *fun, usb_target_t target, void *data, 320 356 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 321 357 { … … 334 370 } 335 371 /*----------------------------------------------------------------------------*/ 336 /** Bulk in transaction interface function 337 * 338 * @param[in] fun DDF function that was called. 339 * @param[in] target USB device to write to. 340 * @param[in] max_packet_size maximum size of data packet the device accepts 341 * @param[out] data Data destination. 342 * @param[in] size Size of data source. 343 * @param[in] callback Function to call on transaction completion 344 * @param[in] arg Additional for callback function. 372 /** Schedule bulk in transfer. 373 * 374 * The callback is supposed to be called once the transfer (on the wire) is 375 * complete regardless of the outcome. 376 * However, the callback could be called only when this function returns 377 * with success status (i.e. returns EOK). 378 * 379 * @param[in] fun Device function the action was invoked on. 380 * @param[in] target Target pipe (address and endpoint number) specification. 381 * @param[in] data Buffer where to store the data (in USB endianess, 382 * allocated and deallocated by the caller). 383 * @param[in] size Size of the @p data buffer in bytes. 384 * @param[in] callback Callback to be issued once the transfer is complete. 385 * @param[in] arg Pass-through argument to the callback. 345 386 * @return Error code. 346 387 */ 347 388 static int bulk_in( 348 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,389 ddf_fun_t *fun, usb_target_t target, void *data, 349 390 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 350 391 { … … 363 404 } 364 405 /*----------------------------------------------------------------------------*/ 365 /** Control write transaction interface function 366 * 367 * @param[in] fun DDF function that was called. 368 * @param[in] target USB device to write to. 369 * @param[in] max_packet_size maximum size of data packet the device accepts. 370 * @param[in] setup_data Data to send with SETUP transfer. 371 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B). 372 * @param[in] data Source of data. 373 * @param[in] size Size of data source. 374 * @param[in] callback Function to call on transaction completion. 375 * @param[in] arg Additional for callback function. 406 /** Schedule control write transfer. 407 * 408 * The callback is supposed to be called once the transfer (on the wire) is 409 * complete regardless of the outcome. 410 * However, the callback could be called only when this function returns 411 * with success status (i.e. returns EOK). 412 * 413 * @param[in] fun Device function the action was invoked on. 414 * @param[in] target Target pipe (address and endpoint number) specification. 415 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 416 * and deallocated by the caller). 417 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes. 418 * @param[in] data_buffer Data buffer (in USB endianess, allocated and 419 * deallocated by the caller). 420 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes. 421 * @param[in] callback Callback to be issued once the transfer is complete. 422 * @param[in] arg Pass-through argument to the callback. 376 423 * @return Error code. 377 424 */ 378 425 static int control_write( 379 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,426 ddf_fun_t *fun, usb_target_t target, 380 427 void *setup_data, size_t setup_size, void *data, size_t size, 381 428 usbhc_iface_transfer_out_callback_t callback, void *arg) … … 397 444 } 398 445 /*----------------------------------------------------------------------------*/ 399 /** Control read transaction interface function 400 * 401 * @param[in] fun DDF function that was called. 402 * @param[in] target USB device to write to. 403 * @param[in] max_packet_size maximum size of data packet the device accepts. 404 * @param[in] setup_data Data to send with SETUP packet. 405 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B). 406 * @param[out] data Source of data. 407 * @param[in] size Size of data source. 408 * @param[in] callback Function to call on transaction completion. 409 * @param[in] arg Additional for callback function. 446 /** Schedule control read transfer. 447 * 448 * The callback is supposed to be called once the transfer (on the wire) is 449 * complete regardless of the outcome. 450 * However, the callback could be called only when this function returns 451 * with success status (i.e. returns EOK). 452 * 453 * @param[in] fun Device function the action was invoked on. 454 * @param[in] target Target pipe (address and endpoint number) specification. 455 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 456 * and deallocated by the caller). 457 * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes. 458 * @param[in] data_buffer Buffer where to store the data (in USB endianess, 459 * allocated and deallocated by the caller). 460 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes. 461 * @param[in] callback Callback to be issued once the transfer is complete. 462 * @param[in] arg Pass-through argument to the callback. 410 463 * @return Error code. 411 464 */ 412 465 static int control_read( 413 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,466 ddf_fun_t *fun, usb_target_t target, 414 467 void *setup_data, size_t setup_size, void *data, size_t size, 415 468 usbhc_iface_transfer_in_callback_t callback, void *arg) -
uspace/drv/ohci/root_hub.c
r8790650 r501e5df 115 115 116 116 static const uint32_t hub_set_feature_valid_mask = 117 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT); 117 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) | 118 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 118 119 119 120 … … 587 588 if (!((1 << feature) & hub_set_feature_valid_mask)) 588 589 return EINVAL; 590 if(feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER) 591 feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16; 589 592 instance->registers->rh_status = 590 593 (instance->registers->rh_status | (1 << feature)) -
uspace/drv/uhci-hcd/iface.c
r8790650 r501e5df 74 74 name, target.address, target.endpoint, size, ep->max_packet_size); 75 75 76 assert(ep->speed ==77 usb_device_keeper_get_speed(&(*hc)->manager, target.address));76 // assert(ep->speed == 77 // usb_device_keeper_get_speed(&(*hc)->manager, target.address)); 78 78 // assert(ep->max_packet_size == max_packet_size); 79 79 // assert(ep->transfer_type == USB_TRANSFER_CONTROL); … … 198 198 /*----------------------------------------------------------------------------*/ 199 199 static int register_endpoint( 200 ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint, 200 ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed, 201 usb_endpoint_t endpoint, 201 202 usb_transfer_type_t transfer_type, usb_direction_t direction, 202 203 size_t max_packet_size, unsigned int interval) … … 204 205 hc_t *hc = fun_to_hc(fun); 205 206 assert(hc); 206 const usb_speed_t speed = 207 usb_device_keeper_get_speed(&hc->manager, address); 208 const size_t size = max_packet_size; 207 usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address); 208 if (speed >= USB_SPEED_MAX) { 209 speed = ep_speed; 210 } 211 const size_t size = 212 (transfer_type == USB_TRANSFER_INTERRUPT 213 || transfer_type == USB_TRANSFER_ISOCHRONOUS) ? 214 max_packet_size : 0; 209 215 int ret; 210 216 … … 240 246 usb_log_debug("Unregister endpoint %d:%d %d.\n", 241 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 } 242 253 return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address, 243 254 endpoint, direction); … … 248 259 * @param[in] fun DDF function that was called. 249 260 * @param[in] target USB device to write to. 250 * @param[in] max_packet_size maximum size of data packet the device accepts251 261 * @param[in] data Source of data. 252 262 * @param[in] size Size of data source. … … 256 266 */ 257 267 static int interrupt_out( 258 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,268 ddf_fun_t *fun, usb_target_t target, void *data, 259 269 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 260 270 { … … 277 287 * @param[in] fun DDF function that was called. 278 288 * @param[in] target USB device to write to. 279 * @param[in] max_packet_size maximum size of data packet the device accepts280 289 * @param[out] data Data destination. 281 290 * @param[in] size Size of data source. … … 285 294 */ 286 295 static int interrupt_in( 287 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,296 ddf_fun_t *fun, usb_target_t target, void *data, 288 297 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 289 298 { … … 306 315 * @param[in] fun DDF function that was called. 307 316 * @param[in] target USB device to write to. 308 * @param[in] max_packet_size maximum size of data packet the device accepts309 317 * @param[in] data Source of data. 310 318 * @param[in] size Size of data source. … … 314 322 */ 315 323 static int bulk_out( 316 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,324 ddf_fun_t *fun, usb_target_t target, void *data, 317 325 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 318 326 { … … 335 343 * @param[in] fun DDF function that was called. 336 344 * @param[in] target USB device to write to. 337 * @param[in] max_packet_size maximum size of data packet the device accepts338 345 * @param[out] data Data destination. 339 346 * @param[in] size Size of data source. … … 343 350 */ 344 351 static int bulk_in( 345 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,352 ddf_fun_t *fun, usb_target_t target, void *data, 346 353 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 347 354 { … … 364 371 * @param[in] fun DDF function that was called. 365 372 * @param[in] target USB device to write to. 366 * @param[in] max_packet_size maximum size of data packet the device accepts.367 373 * @param[in] setup_data Data to send with SETUP transfer. 368 374 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B). … … 374 380 */ 375 381 static int control_write( 376 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,382 ddf_fun_t *fun, usb_target_t target, 377 383 void *setup_data, size_t setup_size, void *data, size_t size, 378 384 usbhc_iface_transfer_out_callback_t callback, void *arg) … … 398 404 * @param[in] fun DDF function that was called. 399 405 * @param[in] target USB device to write to. 400 * @param[in] max_packet_size maximum size of data packet the device accepts.401 406 * @param[in] setup_data Data to send with SETUP packet. 402 407 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B). … … 408 413 */ 409 414 static int control_read( 410 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,415 ddf_fun_t *fun, usb_target_t target, 411 416 void *setup_data, size_t setup_size, void *data, size_t size, 412 417 usbhc_iface_transfer_in_callback_t callback, void *arg) -
uspace/drv/usbhub/Makefile
r8790650 r501e5df 34 34 SOURCES = \ 35 35 main.c \ 36 ports.c \37 36 utils.c \ 38 usbhub.c 37 usbhub.c \ 38 ports.c 39 39 40 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/usbhub/port_status.h
r8790650 r501e5df 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 in 55 * "Universal Serial Bus Specification Revision 1.1" 56 * 57 */ 58 typedef uint32_t usb_hub_status_t; 59 60 /** 51 61 * set values in request to be it a port status request 52 62 * @param request … … 54 64 */ 55 65 static inline void usb_hub_set_port_status_request( 56 usb_device_request_setup_packet_t * request, uint16_t port57 ){66 usb_device_request_setup_packet_t * request, uint16_t port 67 ) { 58 68 request->index = port; 59 69 request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS; … … 63 73 } 64 74 75 /** 76 * set values in request to be it a port status request 77 * @param request 78 * @param port 79 */ 80 static inline void usb_hub_set_hub_status_request( 81 usb_device_request_setup_packet_t * request 82 ) { 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 } 65 89 66 90 /** … … 70 94 */ 71 95 static inline usb_device_request_setup_packet_t * 72 usb_hub_create_port_status_request(uint16_t port) {96 usb_hub_create_port_status_request(uint16_t port) { 73 97 usb_device_request_setup_packet_t * result = 74 usb_new(usb_device_request_setup_packet_t);75 usb_hub_set_port_status_request(result, port);98 malloc(sizeof(usb_device_request_setup_packet_t)); 99 usb_hub_set_port_status_request(result, port); 76 100 return result; 77 101 } 78 102 79 80 103 /** 81 104 * set the device request to be a port feature enable request … … 85 108 */ 86 109 static inline void usb_hub_set_enable_port_feature_request( 87 usb_device_request_setup_packet_t * request, uint16_t port,88 89 ){110 usb_device_request_setup_packet_t * request, uint16_t port, 111 uint16_t feature_selector 112 ) { 90 113 request->index = port; 91 114 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 102 125 */ 103 126 static inline void usb_hub_set_disable_port_feature_request( 104 usb_device_request_setup_packet_t * request, uint16_t port,105 106 ){127 usb_device_request_setup_packet_t * request, uint16_t port, 128 uint16_t feature_selector 129 ) { 107 130 request->index = port; 108 131 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 118 141 */ 119 142 static inline void usb_hub_set_enable_port_request( 120 usb_device_request_setup_packet_t * request, uint16_t port121 ){143 usb_device_request_setup_packet_t * request, uint16_t port 144 ) { 122 145 request->index = port; 123 146 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 133 156 */ 134 157 static inline usb_device_request_setup_packet_t * 135 usb_hub_create_enable_port_request(uint16_t port) {158 usb_hub_create_enable_port_request(uint16_t port) { 136 159 usb_device_request_setup_packet_t * result = 137 usb_new(usb_device_request_setup_packet_t);138 usb_hub_set_enable_port_request(result, port);160 malloc(sizeof(usb_device_request_setup_packet_t)); 161 usb_hub_set_enable_port_request(result, port); 139 162 return result; 140 163 } … … 146 169 */ 147 170 static inline void usb_hub_set_disable_port_request( 148 usb_device_request_setup_packet_t * request, uint16_t port149 ){171 usb_device_request_setup_packet_t * request, uint16_t port 172 ) { 150 173 request->index = port; 151 174 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 161 184 */ 162 185 static inline usb_device_request_setup_packet_t * 163 usb_hub_create_disable_port_request(uint16_t port) {186 usb_hub_create_disable_port_request(uint16_t port) { 164 187 usb_device_request_setup_packet_t * result = 165 usb_new(usb_device_request_setup_packet_t);166 usb_hub_set_disable_port_request(result, port);188 malloc(sizeof(usb_device_request_setup_packet_t)); 189 usb_hub_set_disable_port_request(result, port); 167 190 return result; 168 191 } … … 174 197 */ 175 198 static inline void usb_hub_set_reset_port_request( 176 usb_device_request_setup_packet_t * request, uint16_t port177 ){199 usb_device_request_setup_packet_t * request, uint16_t port 200 ) { 178 201 request->index = port; 179 202 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 189 212 */ 190 213 static inline usb_device_request_setup_packet_t * 191 usb_hub_create_reset_port_request(uint16_t port) {214 usb_hub_create_reset_port_request(uint16_t port) { 192 215 usb_device_request_setup_packet_t * result = 193 usb_new(usb_device_request_setup_packet_t);194 usb_hub_set_reset_port_request(result, port);216 malloc(sizeof(usb_device_request_setup_packet_t)); 217 usb_hub_set_reset_port_request(result, port); 195 218 return result; 196 219 } … … 202 225 */ 203 226 static inline void usb_hub_set_power_port_request( 204 usb_device_request_setup_packet_t * request, uint16_t port205 ){227 usb_device_request_setup_packet_t * request, uint16_t port 228 ) { 206 229 request->index = port; 207 230 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 217 240 */ 218 241 static inline void usb_hub_unset_power_port_request( 219 usb_device_request_setup_packet_t * request, uint16_t port220 ){242 usb_device_request_setup_packet_t * request, uint16_t port 243 ) { 221 244 request->index = port; 222 245 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 226 249 } 227 250 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); 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); 251 321 } 252 322 253 323 //port 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); 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); 260 343 } 261 344 262 345 //port 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); 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); 269 364 } 270 365 271 366 //over currect 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); 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); 278 385 } 279 386 280 387 //port reset 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); 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); 287 406 } 288 407 289 408 //powered 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 } 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 297 430 298 431 //low speed device attached 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)) 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)) 318 481 return USB_SPEED_LOW; 319 if (usb_port_high_speed(status))482 if (usb_port_high_speed(status)) 320 483 return USB_SPEED_HIGH; 321 484 return USB_SPEED_FULL; 322 485 } 323 486 324 487 #if 0 325 488 //connect 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); 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); 332 506 } 333 507 334 508 //port enable 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); 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); 341 527 } 342 528 343 529 //suspend 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); 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); 350 548 } 351 549 352 550 //over current 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); 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); 359 569 } 360 570 361 571 //reset change 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 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 370 680 371 681 -
uspace/drv/usbhub/ports.c
r8790650 r501e5df 33 33 * Hub ports functions. 34 34 */ 35 #include "port_status.h" 36 #include < inttypes.h>35 36 #include <bool.h> 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <usb/request.h> 39 #include <inttypes.h> 40 #include <fibril_synch.h> 41 40 42 #include <usb/debug.h> 43 44 #include "ports.h" 45 #include "usbhub.h" 46 #include "usbhub_private.h" 47 #include "port_status.h" 48 49 50 /** Information for fibril for device discovery. */ 51 struct add_device_phase1 { 52 usb_hub_info_t *hub; 53 size_t port; 54 usb_speed_t speed; 55 }; 56 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 port 78 * 79 * Accepts connection, over current and port reset change. 80 * @param hub hub representation 81 * @param port port number, starting from 1 82 */ 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 change 87 //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 change 99 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 current 118 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) { 119 //check if it was not auto-resolved 120 usb_log_debug("overcurrent change on port\n"); 121 usb_hub_port_over_current(hub, port, status); 122 } 123 //port reset 124 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 removed 148 * 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 device 151 * from it`s device tree. 152 * @param hub hub representation 153 * @param port port number, starting from 1 154 */ 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 in 164 * devide manager 165 */ 166 167 //close address 168 //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 removal 171 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 address 187 usb_hub_release_default_address(hub); 188 } 189 } 190 191 192 /** 193 * Process port reset change 194 * 195 * After this change port should be enabled, unless some problem occured. 196 * This functions triggers second phase of enabling new device. 197 * @param hub 198 * @param port 199 * @param status 200 */ 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 representation 224 * @param port port number, starting from 1 225 */ 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 } 41 245 42 246 /** Retrieve port status. … … 73 277 } 74 278 75 /** Information for fibril for device discovery. */76 struct add_device_phase1 {77 usb_hub_info_t *hub;78 size_t port;79 usb_speed_t speed;80 };81 82 279 /** Callback for enabling a specific port. 83 280 * … … 91 288 static int enable_port_callback(int port_no, void *arg) 92 289 { 93 usb_hub_info_t *hub = (usb_hub_info_t *)arg;290 usb_hub_info_t *hub = arg; 94 291 int rc; 95 292 usb_device_request_setup_packet_t request; … … 156 353 data->hub->ports[data->port].attached_device.address = new_address; 157 354 158 usb_log_info("Detected new device on `%s' (port %zu), " \355 usb_log_info("Detected new device on `%s' (port %zu), " 159 356 "address %d (handle %" PRIun ").\n", 160 357 data->hub->usb_device->ddf_dev->name, data->port, … … 166 363 return EOK; 167 364 } 365 168 366 169 367 /** Start device adding when connection change is detected. … … 176 374 * @return Error code. 177 375 */ 178 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port,376 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port, 179 377 usb_speed_t speed) 180 378 { … … 213 411 } 214 412 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 329 413 /** 330 414 * @} -
uspace/drv/usbhub/ports.h
r8790650 r501e5df 36 36 #define DRV_USBHUB_PORTS_H 37 37 38 #include <ipc/devman.h> 39 #include <usb/usb.h> 40 #include <ddf/driver.h> 41 #include <fibril_synch.h> 42 38 #include <usb/devdrv.h> 43 39 #include <usb/hub.h> 44 40 45 #include <usb/pipes.h> 46 #include <usb/devdrv.h> 41 typedef struct usb_hub_info_t usb_hub_info_t; 47 42 48 43 /** Information about single port on a hub. */ … … 72 67 } 73 68 74 bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *); 69 70 void usb_hub_process_interrupt(usb_hub_info_t * hub, 71 uint16_t port); 72 75 73 76 74 -
uspace/drv/usbhub/usbhub.c
r8790650 r501e5df 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <inttypes.h> 39 40 40 41 #include <usb_iface.h> … … 53 54 #include "usb/classes/classes.h" 54 55 55 static int usb_hub_trigger_connecting_non_removable_devices( 56 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 57 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 58 75 59 76 //********************************************* 60 77 // 61 78 // hub driver code, initialization 79 // 80 //********************************************* 81 82 /** 83 * Initialize hub device driver fibril 84 * 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 information 88 * @return error code 89 */ 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 connection 94 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 configuration 108 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_devs 116 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 hub 183 * 184 * Also unsets hub->is_default_address_used. Convenience wrapper function. 185 * @note hub->connection MUST be open for communication 186 * @param hub hub representation 187 * @return error code 188 */ 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 functions 62 204 // 63 205 //********************************************* … … 71 213 */ 72 214 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) { 73 usb_hub_info_t * result = usb_new(usb_hub_info_t);74 if (!result) return NULL;215 usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t)); 216 if (!result) return NULL; 75 217 result->usb_device = usb_dev; 76 218 result->status_change_pipe = usb_dev->pipes[0].pipe; … … 90 232 * @return error code 91 233 */ 92 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {234 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) { 93 235 // get hub descriptor 94 236 usb_log_debug("creating serialized descriptor\n"); 95 237 void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE); 96 238 usb_hub_descriptor_t * descriptor; 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 */ 239 int opResult; 240 107 241 size_t received_size; 108 int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe,109 110 USB_DESCTYPE_HUB,111 0, 0, serialized_descriptor,112 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 113 114 if (opResult != EOK) {115 usb_log_error("failed when receiving hub descriptor,badcode = %d\n",116 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); 246 247 if (opResult != EOK) { 248 usb_log_error("failed when receiving hub descriptor, " 249 "badcode = %d\n", 250 opResult); 117 251 free(serialized_descriptor); 118 252 return opResult; … … 120 254 usb_log_debug2("deserializing descriptor\n"); 121 255 descriptor = usb_deserialize_hub_desriptor(serialized_descriptor); 122 if (descriptor==NULL){256 if (descriptor == NULL) { 123 257 usb_log_warning("could not deserialize descriptor \n"); 124 258 return opResult; 125 259 } 126 usb_log_debug("setting port count to %d\n", descriptor->ports_count);260 usb_log_debug("setting port count to %d\n", descriptor->ports_count); 127 261 hub_info->port_count = descriptor->ports_count; 128 hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1)); 262 /// \TODO this is not semantically correct 263 hub_info->ports = malloc( 264 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 129 265 size_t port; 130 266 for (port = 0; port < hub_info->port_count + 1; port++) { 131 267 usb_hub_port_init(&hub_info->ports[port]); 132 268 } 133 //handle non-removable devices134 usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);135 269 usb_log_debug2("freeing data\n"); 136 270 free(serialized_descriptor); … … 139 273 return EOK; 140 274 } 275 141 276 /** 142 277 * Set configuration of hub … … 147 282 * @return error code 148 283 */ 149 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {284 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) { 150 285 //device descriptor 151 286 usb_standard_device_descriptor_t *std_descriptor … … 153 288 usb_log_debug("hub has %d configurations\n", 154 289 std_descriptor->configuration_count); 155 if (std_descriptor->configuration_count<1){290 if (std_descriptor->configuration_count < 1) { 156 291 usb_log_error("there are no configurations available\n"); 157 292 return EINVAL; … … 173 308 } 174 309 usb_log_debug("\tused configuration %d\n", 175 310 config_descriptor->configuration_number); 176 311 177 312 return EOK; … … 179 314 180 315 /** 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 186 * @return error code 187 */ 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 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 322 * @return error code 323 */ 324 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){ 233 325 /* 234 326 * The processing will require opened control pipe and connection … … 239 331 * auto destruction, this could work better. 240 332 */ 241 rc = usb_pipe_start_session(&usb_dev->ctrl_pipe);333 int rc = usb_pipe_start_session(hub_info->control_pipe); 242 334 if (rc != EOK) { 243 335 usb_log_error("Failed to start session on control pipe: %s.\n", 244 336 str_error(rc)); 245 goto leave;337 return rc; 246 338 } 247 339 rc = usb_hc_connection_open(&hub_info->connection); 248 340 if (rc != EOK) { 249 usb_pipe_end_session( &usb_dev->ctrl_pipe);341 usb_pipe_end_session(hub_info->control_pipe); 250 342 usb_log_error("Failed to open connection to HC: %s.\n", 251 343 str_error(rc)); 252 goto leave;344 return rc; 253 345 } 254 346 255 347 rc = usb_device_auto_poll(hub_info->usb_device, 0, 256 hub_port_changes_callback, ((hub_info->port_count +1) / 8) + 1,348 hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1, 257 349 NULL, hub_info); 258 350 if (rc != EOK) { … … 266 358 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 267 359 return EOK; 268 269 leave: 270 free(hub_info); 271 272 return rc; 273 } 274 275 276 //********************************************* 277 // 278 // hub driver code, main loop and port handling 279 // 280 //********************************************* 281 282 /** 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 289 * @return error code 290 */ 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; 360 } 361 362 //********************************************* 363 // 364 // change handling functions 365 // 366 //********************************************* 367 368 369 /** 370 * process hub over current change 371 * 372 * This means either to power off the hub or power it on. 373 * @param hub_info hub instance 374 * @param status hub status bitmask 375 * @return error code 376 */ 377 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 378 usb_hub_status_t status) { 296 379 int opResult; 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 ); 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); 312 424 if (opResult != EOK) { 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"); 425 usb_log_error("cannot power on port %d; %d\n", 426 port, opResult); 345 427 } 346 428 } 347 429 } 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){ 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; 452 443 int opResult; 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 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 } 461 475 462 476 /** -
uspace/drv/usbhub/usbhub.h
r8790650 r501e5df 37 37 38 38 #include <ipc/devman.h> 39 #include <usb/usb.h>40 39 #include <ddf/driver.h> 41 40 42 #define NAME "usbhub"43 44 41 #include <usb/hub.h> 42 #include <usb/classes/hub.h> 45 43 46 44 #include <usb/pipes.h> 47 45 #include <usb/devdrv.h> 46 47 #include <fibril_synch.h> 48 49 #define NAME "usbhub" 48 50 49 51 #include "ports.h" … … 52 54 53 55 /** Information about attached hub. */ 54 typedef struct{56 struct usb_hub_info_t{ 55 57 /** Number of ports. */ 56 58 size_t port_count; 57 59 58 /** Ports.*/60 /** attached device handles, for each port one */ 59 61 usb_hub_port_t *ports; 60 62 61 63 /** connection to hcd */ 62 64 usb_hc_connection_t connection; … … 87 89 /** generic usb device data*/ 88 90 usb_device_t * usb_device; 89 } usb_hub_info_t;91 }; 90 92 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); 93 //int usb_hub_control_loop(void * hub_info_param); 107 94 108 95 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); 109 101 110 102 #endif -
uspace/drv/usbhub/usbhub_private.h
r8790650 r501e5df 54 54 // 55 55 //************ 56 #define usb_new(type) (type*)malloc(sizeof(type))57 56 58 57 59 /**60 * Create hub structure instance61 *62 * Set the address and port count information most importantly.63 *64 * @param device65 * @param hc host controller phone66 * @return67 */68 58 usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device); 69 59 … … 110 100 111 101 /** 102 * Clear feature on hub port. 103 * 104 * @param hc Host controller telephone 105 * @param address Hub address 106 * @param port_index Port 107 * @param feature Feature selector 108 * @return Operation result 109 */ 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_index 119 }; 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 endpoint 130 * @param feature Feature selector 131 * @return Operation result 132 */ 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 = 0 141 }; 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 endpoint 151 * @param feature Feature selector 152 * @return Operation result 153 */ 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 = 0 162 }; 163 clear_request.value = feature; 164 return usb_pipe_control_write(pipe, &clear_request, 165 sizeof(clear_request), NULL, 0); 166 } 167 168 /** 112 169 * create uint8_t array with serialized descriptor 113 170 * -
uspace/drv/usbhub/utils.c
r8790650 r501e5df 60 60 size_t size = 7; 61 61 //variable size according to port count 62 size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0);62 size_t var_size = (descriptor->ports_count+7)/8; 63 63 size += 2 * var_size; 64 uint8_t * result = (uint8_t*)malloc(size);64 uint8_t * result = malloc(size); 65 65 //size 66 66 result[0] = size; … … 84 84 } 85 85 86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) { 87 uint8_t * sdescriptor = (uint8_t*) serialized_descriptor; 86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor( 87 void * serialized_descriptor) { 88 uint8_t * sdescriptor = serialized_descriptor; 88 89 89 90 if (sdescriptor[1] != USB_DESCTYPE_HUB) { 90 usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]); 91 usb_log_warning("trying to deserialize wrong descriptor %x\n", 92 sdescriptor[1]); 91 93 return NULL; 92 94 } 93 95 94 usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t);96 usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t)); 95 97 96 98 … … 100 102 result->pwr_on_2_good_time = sdescriptor[5]; 101 103 result->current_requirement = sdescriptor[6]; 102 size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0) 103 ? 1 : 0); 104 size_t var_size = (result->ports_count+7) / 8; 104 105 result->devices_removable = (uint8_t*) malloc(var_size); 105 106 -
uspace/drv/usbmid/main.c
r8790650 r501e5df 55 55 int rc; 56 56 57 rc = usb_pipe_start_ session(&dev->ctrl_pipe);57 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe); 58 58 if (rc != EOK) { 59 usb_log_error("Failed to start sessionon control pipe: %s.\n",59 usb_log_error("Failed to start transfer on control pipe: %s.\n", 60 60 str_error(rc)); 61 61 return rc; … … 64 64 bool accept = usbmid_explore_device(dev); 65 65 66 rc = usb_pipe_end_session(&dev->ctrl_pipe); 67 if (rc != EOK) { 68 usb_log_warning("Failed to end session on control pipe: %s.\n", 69 str_error(rc)); 70 } 66 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 71 67 72 68 if (!accept) { -
uspace/drv/vhc/connhost.c
r8790650 r501e5df 257 257 258 258 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 259 size_t max_packet_size,260 259 void *data, size_t size, 261 260 usbhc_iface_transfer_out_callback_t callback, void *arg) … … 267 266 268 267 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 269 size_t max_packet_size,270 268 void *data, size_t size, 271 269 usbhc_iface_transfer_in_callback_t callback, void *arg) … … 277 275 278 276 static int control_write(ddf_fun_t *fun, usb_target_t target, 279 size_t max_packet_size,280 277 void *setup_packet, size_t setup_packet_size, 281 278 void *data, size_t data_size, … … 295 292 296 293 static int control_read(ddf_fun_t *fun, usb_target_t target, 297 size_t max_packet_size,298 294 void *setup_packet, size_t setup_packet_size, 299 295 void *data, size_t data_size, -
uspace/lib/drv/generic/remote_usbhc.c
r8790650 r501e5df 270 270 } 271 271 272 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);273 272 usb_target_t target = { 274 273 .address = DEV_IPC_GET_ARG1(*call), … … 300 299 trans->size = len; 301 300 302 rc = transfer_func(fun, target, max_packet_size,301 rc = transfer_func(fun, target, 303 302 buffer, len, 304 303 callback_out, trans); … … 326 325 } 327 326 328 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);329 327 usb_target_t target = { 330 328 .address = DEV_IPC_GET_ARG1(*call), … … 348 346 trans->size = len; 349 347 350 int rc = transfer_func(fun, target, max_packet_size,348 int rc = transfer_func(fun, target, 351 349 trans->buffer, len, 352 350 callback_in, trans); … … 414 412 }; 415 413 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call); 416 size_t max_packet_size = DEV_IPC_GET_ARG4(*call);417 414 418 415 int rc; … … 450 447 trans->size = data_buffer_len; 451 448 452 rc = usb_iface->control_write(fun, target, max_packet_size,449 rc = usb_iface->control_write(fun, target, 453 450 setup_packet, setup_packet_len, 454 451 data_buffer, data_buffer_len, … … 477 474 .endpoint = DEV_IPC_GET_ARG2(*call) 478 475 }; 479 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);480 476 481 477 int rc; … … 515 511 } 516 512 517 rc = usb_iface->control_read(fun, target, max_packet_size,513 rc = usb_iface->control_read(fun, target, 518 514 setup_packet, setup_packet_len, 519 515 trans->buffer, trans->size, … … 537 533 } 538 534 539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \ 540 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256 541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \ 542 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256 543 544 INIT_FROM_HIGH_DATA(usb_address_t, address, 1); 545 INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1); 546 INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2); 547 INIT_FROM_LOW_DATA(usb_direction_t, direction, 2); 548 549 #undef INIT_FROM_HIGH_DATA 550 #undef INIT_FROM_LOW_DATA 551 552 size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call); 553 unsigned int interval = (unsigned int) DEV_IPC_GET_ARG4(*call); 554 555 int rc = usb_iface->register_endpoint(fun, address, endpoint, 535 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \ 536 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16) 537 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \ 538 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16) 539 #define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \ 540 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16) 541 #define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \ 542 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8) 543 #define _INIT_FROM_LOW_DATA3(type, var, arg_no) \ 544 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8) 545 546 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1); 547 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1); 548 549 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2); 550 _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2); 551 _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2); 552 553 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3); 554 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3); 555 556 #undef _INIT_FROM_HIGH_DATA2 557 #undef _INIT_FROM_LOW_DATA2 558 #undef _INIT_FROM_HIGH_DATA3 559 #undef _INIT_FROM_MIDDLE_DATA3 560 #undef _INIT_FROM_LOW_DATA3 561 562 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint, 556 563 transfer_type, direction, max_packet_size, interval); 557 564 -
uspace/lib/drv/include/usbhc_iface.h
r8790650 r501e5df 66 66 * - argument #1 is target address 67 67 * - argument #2 is target endpoint 68 * - argument #3 is max packet size of the endpoint69 68 * - this call is immediately followed by IPC data read (async version) 70 69 * - the call is not answered until the device returns some data (or until … … 169 168 /** Register endpoint attributes at host controller. 170 169 * This is used to reserve portion of USB bandwidth. 170 * When speed is invalid, speed of the device is used. 171 171 * Parameters: 172 * - USB address + endpoint number (ADDR * 256 + EP) 173 * - transfer type + direction (TYPE * 256 + DIR) 174 * - maximum packet size 175 * - interval (in milliseconds) 172 * - USB address + endpoint number 173 * - packed as ADDR << 16 + EP 174 * - speed + transfer type + direction 175 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 176 * - maximum packet size + interval (in milliseconds) 177 * - packed as MPS << 16 + INT 176 178 * Answer: 177 179 * - EOK - reservation successful … … 202 204 203 205 /** Out transfer processing function prototype. */ 204 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t,206 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, 205 207 void *, size_t, 206 208 usbhc_iface_transfer_out_callback_t, void *); … … 210 212 211 213 /** In transfer processing function prototype. */ 212 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t,214 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, 213 215 void *, size_t, 214 216 usbhc_iface_transfer_in_callback_t, void *); … … 222 224 int (*release_address)(ddf_fun_t *, usb_address_t); 223 225 224 int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, 226 int (*register_endpoint)(ddf_fun_t *, 227 usb_address_t, usb_speed_t, usb_endpoint_t, 225 228 usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 226 229 int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, … … 234 237 235 238 int (*control_write)(ddf_fun_t *, usb_target_t, 236 size_t,237 239 void *, size_t, void *, size_t, 238 240 usbhc_iface_transfer_out_callback_t, void *); 239 241 240 242 int (*control_read)(ddf_fun_t *, usb_target_t, 241 size_t,242 243 void *, size_t, void *, size_t, 243 244 usbhc_iface_transfer_in_callback_t, void *); -
uspace/lib/usb/Makefile
r8790650 r501e5df 43 43 src/hidparser.c \ 44 44 src/hub.c \ 45 src/pipepriv.c \ 45 46 src/pipes.c \ 46 47 src/pipesinit.c \ -
uspace/lib/usb/include/usb/classes/hub.h
r8790650 r501e5df 43 43 */ 44 44 typedef enum { 45 USB_HUB_FEATURE_HUB_LOCAL_POWER = 0, 46 USB_HUB_FEATURE_HUB_OVER_CURRENT = 1, 45 47 USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0, 46 48 USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1, … … 59 61 /* USB_HUB_FEATURE_ = , */ 60 62 } usb_hub_class_feature_t; 63 61 64 62 65 /** Header of standard hub descriptor without the "variadic" part. */ -
uspace/lib/usb/include/usb/devdrv.h
r8790650 r501e5df 169 169 usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *); 170 170 171 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *); 172 int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *, 173 usb_endpoint_description_t **, uint8_t *, size_t, int, int, 174 usb_endpoint_mapping_t **, size_t *); 175 int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t); 176 177 size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t); 178 171 179 #endif 172 180 /** -
uspace/lib/usb/include/usb/host/device_keeper.h
r8790650 r501e5df 73 73 void usb_device_keeper_add_ep( 74 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); 75 77 76 78 void usb_device_keeper_reserve_default_address( -
uspace/lib/usb/include/usb/pipes.h
r8790650 r501e5df 42 42 #include <ipc/devman.h> 43 43 #include <ddf/driver.h> 44 #include <fibril_synch.h> 44 45 45 46 /** Abstraction of a physical connection to the device. … … 59 60 * This endpoint must be bound with existing usb_device_connection_t 60 61 * (i.e. the wire to send data over). 62 * 63 * Locking order: if you want to lock both mutexes 64 * (@c guard and @c hc_phone_mutex), lock @c guard first. 65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex 66 * only. 61 67 */ 62 68 typedef struct { 69 /** Guard of the whole pipe. */ 70 fibril_mutex_t guard; 71 63 72 /** The connection used for sending the data. */ 64 73 usb_device_connection_t *wire; … … 78 87 /** Phone to the host controller. 79 88 * Negative when no session is active. 89 * It is an error to access this member without @c hc_phone_mutex 90 * being locked. 91 * If call over the phone is to be made, it must be preceeded by 92 * call to pipe_add_ref() [internal libusb function]. 80 93 */ 81 94 int hc_phone; 95 96 /** Guard for serialization of requests over the phone. */ 97 fibril_mutex_t hc_phone_mutex; 98 99 /** Number of active transfers over the pipe. */ 100 int refcount; 82 101 } usb_pipe_t; 83 102 … … 134 153 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 135 154 size_t, uint8_t *, size_t, usb_device_connection_t *); 155 int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t, 156 unsigned int, usb_hc_connection_t *); 136 157 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *); 137 158 int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *); … … 140 161 int usb_pipe_end_session(usb_pipe_t *); 141 162 bool usb_pipe_is_session_started(usb_pipe_t *); 163 164 int usb_pipe_start_long_transfer(usb_pipe_t *); 165 void usb_pipe_end_long_transfer(usb_pipe_t *); 142 166 143 167 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); -
uspace/lib/usb/include/usb/usb.h
r8790650 r501e5df 77 77 USB_SPEED_FULL, 78 78 /** USB 2.0 high speed (480Mbits/s). */ 79 USB_SPEED_HIGH 79 USB_SPEED_HIGH, 80 /** Psuedo-speed serving as a boundary. */ 81 USB_SPEED_MAX 80 82 } usb_speed_t; 81 83 -
uspace/lib/usb/src/devdrv.c
r8790650 r501e5df 72 72 } 73 73 74 /** Log out of memory error on given device.75 *76 * @param dev Device causing the trouble.77 */78 static void usb_log_oom(ddf_dev_t *dev)79 {80 usb_log_error("Out of memory when adding device `%s'.\n",81 dev->name);82 }83 84 74 /** Count number of pipes the driver expects. 85 75 * … … 108 98 */ 109 99 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 110 usb_device_t *dev) 111 { 112 int rc; 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 116 return EOK; 117 } 118 119 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 120 if (dev->pipes == NULL) { 121 usb_log_oom(dev->ddf_dev); 122 return ENOMEM; 123 } 124 125 size_t i; 126 127 /* Initialize to NULL first for rollback purposes. */ 128 for (i = 0; i < pipe_count; i++) { 129 dev->pipes[i].pipe = NULL; 130 } 131 132 for (i = 0; i < pipe_count; i++) { 133 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 134 if (dev->pipes[i].pipe == NULL) { 135 usb_log_oom(dev->ddf_dev); 136 rc = ENOMEM; 137 goto rollback; 138 } 139 140 dev->pipes[i].description = endpoints[i]; 141 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0; 143 } 144 145 rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count, 100 usb_device_t *dev, int alternate_setting) 101 { 102 usb_endpoint_mapping_t *pipes; 103 size_t pipes_count; 104 105 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints, 146 106 dev->descriptors.configuration, dev->descriptors.configuration_size, 147 &dev->wire); 148 if (rc != EOK) { 149 usb_log_error("Failed initializing USB endpoints: %s.\n", 150 str_error(rc)); 151 goto rollback; 152 } 153 154 /* Register the endpoints. */ 155 usb_hc_connection_t hc_conn; 156 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 107 dev->interface_no, alternate_setting, 108 &pipes, &pipes_count); 109 157 110 if (rc != EOK) { 158 111 usb_log_error( 159 "Failed initializing connection to host controller: %s.\n", 160 str_error(rc)); 161 goto rollback; 162 } 163 rc = usb_hc_connection_open(&hc_conn); 164 if (rc != EOK) { 165 usb_log_error("Failed to connect to host controller: %s.\n", 166 str_error(rc)); 167 goto rollback; 168 } 169 for (i = 0; i < pipe_count; i++) { 170 if (dev->pipes[i].present) { 171 rc = usb_pipe_register(dev->pipes[i].pipe, 172 dev->pipes[i].descriptor->poll_interval, 173 &hc_conn); 174 /* Ignore error when operation not supported by HC. */ 175 if ((rc != EOK) && (rc != ENOTSUP)) { 176 /* FIXME: what shall we do? */ 177 dev->pipes[i].present = false; 178 free(dev->pipes[i].pipe); 179 dev->pipes[i].pipe = NULL; 180 } 181 } 182 } 183 /* Ignoring errors here. */ 184 usb_hc_connection_close(&hc_conn); 185 186 dev->pipes_count = pipe_count; 112 "Failed to create endpoint pipes for `%s': %s.\n", 113 dev->ddf_dev->name, str_error(rc)); 114 return rc; 115 } 116 117 dev->pipes = pipes; 118 dev->pipes_count = pipes_count; 187 119 188 120 return EOK; 189 190 rollback:191 for (i = 0; i < pipe_count; i++) {192 if (dev->pipes[i].pipe != NULL) {193 free(dev->pipes[i].pipe);194 }195 }196 free(dev->pipes);197 198 return rc;199 121 } 200 122 … … 239 161 240 162 /* 241 * For further actions, we need open session on default control pipe. 163 * We will do some querying of the device, it is worth to prepare 164 * the long transfer. 242 165 */ 243 rc = usb_pipe_start_ session(&dev->ctrl_pipe);244 if (rc != EOK) { 245 usb_log_error("Failed to start an IPC session: %s.\n",166 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe); 167 if (rc != EOK) { 168 usb_log_error("Failed to start transfer: %s.\n", 246 169 str_error(rc)); 247 170 return rc; 248 171 } 249 172 250 /* Get the device descriptor. */ 251 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, 252 &dev->descriptors.device); 253 if (rc != EOK) { 254 usb_log_error("Failed to retrieve device descriptor: %s.\n", 255 str_error(rc)); 256 return rc; 257 } 258 259 /* Get the full configuration descriptor. */ 260 rc = usb_request_get_full_configuration_descriptor_alloc( 261 &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration, 262 &dev->descriptors.configuration_size); 263 if (rc != EOK) { 264 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n", 173 /* Retrieve the descriptors. */ 174 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 175 &dev->descriptors); 176 if (rc != EOK) { 177 usb_log_error("Failed to retrieve standard device " \ 178 "descriptors of %s: %s.\n", 265 179 dev->ddf_dev->name, str_error(rc)); 266 180 return rc; 267 181 } 268 182 183 269 184 if (driver->endpoints != NULL) { 270 rc = initialize_other_pipes(driver->endpoints, dev); 271 } 272 273 /* No checking here. */ 274 usb_pipe_end_session(&dev->ctrl_pipe); 185 rc = initialize_other_pipes(driver->endpoints, dev, 0); 186 } 187 188 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 275 189 276 190 /* Rollback actions. */ … … 291 205 * @return Number of alternate interfaces for @p interface_no interface. 292 206 */ 293 s tatic size_t count_alternate_interfaces(uint8_t *config_descr,294 size_t config_descr_size, int interface_no)207 size_t usb_interface_count_alternates(uint8_t *config_descr, 208 size_t config_descr_size, uint8_t interface_no) 295 209 { 296 210 assert(config_descr != NULL); 211 assert(config_descr_size > 0); 212 297 213 usb_dp_parser_t dp_parser = { 298 214 .nesting = usb_dp_standard_descriptor_nesting … … 343 259 344 260 alternates->alternative_count 345 = count_alternate_interfaces(dev->descriptors.configuration,261 = usb_interface_count_alternates(dev->descriptors.configuration, 346 262 dev->descriptors.configuration_size, dev->interface_no); 347 263 … … 457 373 static int destroy_current_pipes(usb_device_t *dev) 458 374 { 459 size_t i; 460 int rc; 461 462 /* TODO: this shall be done under some device mutex. */ 463 464 /* First check that no session is opened. */ 465 for (i = 0; i < dev->pipes_count; i++) { 466 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) { 467 return EBUSY; 468 } 469 } 470 471 /* Prepare connection to HC. */ 472 usb_hc_connection_t hc_conn; 473 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 474 if (rc != EOK) { 475 return rc; 476 } 477 rc = usb_hc_connection_open(&hc_conn); 478 if (rc != EOK) { 479 return rc; 480 } 481 482 /* Destroy the pipes. */ 483 for (i = 0; i < dev->pipes_count; i++) { 484 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn); 485 free(dev->pipes[i].pipe); 486 } 487 488 usb_hc_connection_close(&hc_conn); 489 490 free(dev->pipes); 375 int rc = usb_device_destroy_pipes(dev->ddf_dev, 376 dev->pipes, dev->pipes_count); 377 if (rc != EOK) { 378 return rc; 379 } 380 491 381 dev->pipes = NULL; 492 382 dev->pipes_count = 0; … … 535 425 536 426 /* Create new pipes. */ 537 rc = initialize_other_pipes(endpoints, dev );427 rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting); 538 428 539 429 return rc; 430 } 431 432 /** Retrieve basic descriptors from the device. 433 * 434 * @param[in] ctrl_pipe Control pipe with opened session. 435 * @param[out] descriptors Where to store the descriptors. 436 * @return Error code. 437 */ 438 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe, 439 usb_device_descriptors_t *descriptors) 440 { 441 assert(descriptors != NULL); 442 assert(usb_pipe_is_session_started(ctrl_pipe)); 443 444 descriptors->configuration = NULL; 445 446 int rc; 447 448 /* Get the device descriptor. */ 449 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 450 if (rc != EOK) { 451 return rc; 452 } 453 454 /* Get the full configuration descriptor. */ 455 rc = usb_request_get_full_configuration_descriptor_alloc( 456 ctrl_pipe, 0, (void **) &descriptors->configuration, 457 &descriptors->configuration_size); 458 if (rc != EOK) { 459 return rc; 460 } 461 462 return EOK; 463 } 464 465 /** Create pipes for a device. 466 * 467 * This is more or less a wrapper that does following actions: 468 * - allocate and initialize pipes 469 * - map endpoints to the pipes based on the descriptions 470 * - registers endpoints with the host controller 471 * 472 * @param[in] dev Generic DDF device backing the USB one. 473 * @param[in] wire Initialized backing connection to the host controller. 474 * @param[in] endpoints Endpoints description, NULL terminated. 475 * @param[in] config_descr Configuration descriptor of active configuration. 476 * @param[in] config_descr_size Size of @p config_descr in bytes. 477 * @param[in] interface_no Interface to map from. 478 * @param[in] interface_setting Interface setting (default is usually 0). 479 * @param[out] pipes_ptr Where to store array of created pipes 480 * (not NULL terminated). 481 * @param[out] pipes_count_ptr Where to store number of pipes 482 * (set to if you wish to ignore the count). 483 * @return Error code. 484 */ 485 int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire, 486 usb_endpoint_description_t **endpoints, 487 uint8_t *config_descr, size_t config_descr_size, 488 int interface_no, int interface_setting, 489 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr) 490 { 491 assert(dev != NULL); 492 assert(wire != NULL); 493 assert(endpoints != NULL); 494 assert(config_descr != NULL); 495 assert(config_descr_size > 0); 496 assert(pipes_ptr != NULL); 497 498 size_t i; 499 int rc; 500 501 size_t pipe_count = count_other_pipes(endpoints); 502 if (pipe_count == 0) { 503 *pipes_ptr = NULL; 504 return EOK; 505 } 506 507 usb_endpoint_mapping_t *pipes 508 = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 509 if (pipes == NULL) { 510 return ENOMEM; 511 } 512 513 /* Initialize to NULL to allow smooth rollback. */ 514 for (i = 0; i < pipe_count; i++) { 515 pipes[i].pipe = NULL; 516 } 517 518 /* Now allocate and fully initialize. */ 519 for (i = 0; i < pipe_count; i++) { 520 pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 521 if (pipes[i].pipe == NULL) { 522 rc = ENOMEM; 523 goto rollback_free_only; 524 } 525 pipes[i].description = endpoints[i]; 526 pipes[i].interface_no = interface_no; 527 pipes[i].interface_setting = interface_setting; 528 } 529 530 /* Find the mapping from configuration descriptor. */ 531 rc = usb_pipe_initialize_from_configuration(pipes, pipe_count, 532 config_descr, config_descr_size, wire); 533 if (rc != EOK) { 534 goto rollback_free_only; 535 } 536 537 /* Register the endpoints with HC. */ 538 usb_hc_connection_t hc_conn; 539 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 540 if (rc != EOK) { 541 goto rollback_free_only; 542 } 543 544 rc = usb_hc_connection_open(&hc_conn); 545 if (rc != EOK) { 546 goto rollback_free_only; 547 } 548 549 for (i = 0; i < pipe_count; i++) { 550 if (pipes[i].present) { 551 rc = usb_pipe_register(pipes[i].pipe, 552 pipes[i].descriptor->poll_interval, &hc_conn); 553 if (rc != EOK) { 554 goto rollback_unregister_endpoints; 555 } 556 } 557 } 558 559 usb_hc_connection_close(&hc_conn); 560 561 *pipes_ptr = pipes; 562 if (pipes_count_ptr != NULL) { 563 *pipes_count_ptr = pipe_count; 564 } 565 566 return EOK; 567 568 /* 569 * Jump here if something went wrong after endpoints have 570 * been registered. 571 * This is also the target when the registration of 572 * endpoints fails. 573 */ 574 rollback_unregister_endpoints: 575 for (i = 0; i < pipe_count; i++) { 576 if (pipes[i].present) { 577 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 578 } 579 } 580 581 usb_hc_connection_close(&hc_conn); 582 583 /* 584 * Jump here if something went wrong before some actual communication 585 * with HC. Then the only thing that needs to be done is to free 586 * allocated memory. 587 */ 588 rollback_free_only: 589 for (i = 0; i < pipe_count; i++) { 590 if (pipes[i].pipe != NULL) { 591 free(pipes[i].pipe); 592 } 593 } 594 free(pipes); 595 596 return rc; 597 } 598 599 /** Destroy pipes previously created by usb_device_create_pipes. 600 * 601 * @param[in] dev Generic DDF device backing the USB one. 602 * @param[in] pipes Endpoint mapping to be destroyed. 603 * @param[in] pipes_count Number of endpoints. 604 */ 605 int usb_device_destroy_pipes(ddf_dev_t *dev, 606 usb_endpoint_mapping_t *pipes, size_t pipes_count) 607 { 608 assert(dev != NULL); 609 assert(((pipes != NULL) && (pipes_count > 0)) 610 || ((pipes == NULL) && (pipes_count == 0))); 611 612 if (pipes_count == 0) { 613 return EOK; 614 } 615 616 int rc; 617 618 /* Prepare connection to HC to allow endpoint unregistering. */ 619 usb_hc_connection_t hc_conn; 620 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 621 if (rc != EOK) { 622 return rc; 623 } 624 rc = usb_hc_connection_open(&hc_conn); 625 if (rc != EOK) { 626 return rc; 627 } 628 629 /* Destroy the pipes. */ 630 size_t i; 631 for (i = 0; i < pipes_count; i++) { 632 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 633 free(pipes[i].pipe); 634 } 635 636 usb_hc_connection_close(&hc_conn); 637 638 free(pipes); 639 640 return EOK; 540 641 } 541 642 -
uspace/lib/usb/src/devpoll.c
r8790650 r501e5df 77 77 int rc; 78 78 79 rc = usb_pipe_start_session(pipe);80 if (rc != EOK) {81 failed_attempts++;82 continue;83 }84 85 79 size_t actual_size; 86 80 rc = usb_pipe_read(pipe, polling_data->buffer, 87 81 polling_data->request_size, &actual_size); 88 82 89 /* Quit the session regardless of errors. */90 usb_pipe_end_session(pipe);91 83 92 84 // if (rc == ESTALL) { -
uspace/lib/usb/src/host/device_keeper.c
r8790650 r501e5df 56 56 instance->devices[i].control_used = 0; 57 57 instance->devices[i].handle = 0; 58 instance->devices[i].speed = USB_SPEED_MAX; 58 59 list_initialize(&instance->devices[i].endpoints); 59 60 } 61 // TODO: is this hack enough? 62 // (it is needed to allow smooth registration at default address) 63 instance->devices[0].occupied = true; 60 64 } 61 65 /*----------------------------------------------------------------------------*/ … … 67 71 assert(instance->devices[address].occupied); 68 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); 69 84 fibril_mutex_unlock(&instance->guard); 70 85 } -
uspace/lib/usb/src/hub.c
r8790650 r501e5df 40 40 #include <errno.h> 41 41 #include <assert.h> 42 #include <usb/debug.h> 42 43 43 44 /** Check that HC connection is alright. … … 55 56 56 57 /** Tell host controller to reserve default address. 58 * @deprecated 57 59 * 58 60 * @param connection Opened connection to host controller. … … 65 67 CHECK_CONNECTION(connection); 66 68 69 usb_log_warning("usb_hc_reserve_default_address() considered obsolete"); 70 67 71 return async_req_2_0(connection->hc_phone, 68 72 DEV_IFACE_ID(USBHC_DEV_IFACE), … … 71 75 72 76 /** Tell host controller to release default address. 77 * @deprecated 73 78 * 74 79 * @param connection Opened connection to host controller. … … 78 83 { 79 84 CHECK_CONNECTION(connection); 85 86 usb_log_warning("usb_hc_release_default_address() considered obsolete"); 80 87 81 88 return async_req_1_0(connection->hc_phone, … … 235 242 } 236 243 237 238 /* 239 * Reserve the default address. 240 */ 241 rc = usb_hc_reserve_default_address(&hc_conn, dev_speed); 242 if (rc != EOK) { 243 rc = EBUSY; 244 goto leave_release_free_address; 245 } 246 247 /* 248 * Enable the port (i.e. allow signaling through this port). 249 */ 250 rc = enable_port(port_no, arg); 251 if (rc != EOK) { 252 goto leave_release_default_address; 253 } 254 255 /* 256 * Change the address from default to the free one. 257 * We need to create a new control pipe for that. 244 /* 245 * We will not register control pipe on default address. 246 * The registration might fail. That means that someone else already 247 * registered that endpoint. We will simply wait and try again. 248 * (Someone else already wants to add a new device.) 258 249 */ 259 250 usb_device_connection_t dev_conn; … … 262 253 if (rc != EOK) { 263 254 rc = ENOTCONN; 264 goto leave_release_ default_address;255 goto leave_release_free_address; 265 256 } 266 257 … … 270 261 if (rc != EOK) { 271 262 rc = ENOTCONN; 263 goto leave_release_free_address; 264 } 265 266 do { 267 rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0, 268 &hc_conn); 269 if (rc != EOK) { 270 /* Do not overheat the CPU ;-). */ 271 async_usleep(10); 272 } 273 } while (rc != EOK); 274 275 /* 276 * Endpoint is registered. We can enable the port and change 277 * device address. 278 */ 279 rc = enable_port(port_no, arg); 280 if (rc != EOK) { 272 281 goto leave_release_default_address; 273 282 } 274 283 275 /* Before sending any traffic, we need to register this 276 * endpoint. 284 rc = usb_pipe_probe_default_control(&ctrl_pipe); 285 if (rc != EOK) { 286 rc = ESTALL; 287 goto leave_release_default_address; 288 } 289 290 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 291 if (rc != EOK) { 292 rc = ESTALL; 293 goto leave_release_default_address; 294 } 295 296 /* 297 * Address changed. We can release the original endpoint, thus 298 * allowing other to access the default address. 299 */ 300 unregister_control_endpoint_on_default_address(&hc_conn); 301 302 /* 303 * Time to register the new endpoint. 277 304 */ 278 305 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 279 306 if (rc != EOK) { 280 rc = EREFUSED; 281 goto leave_release_default_address; 282 } 283 rc = usb_pipe_probe_default_control(&ctrl_pipe); 284 if (rc != EOK) { 285 rc = ENOTCONN; 286 goto leave_release_default_address; 287 } 288 289 rc = usb_pipe_start_session(&ctrl_pipe); 290 if (rc != EOK) { 291 rc = ENOTCONN; 292 goto leave_unregister_endpoint; 293 } 294 295 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 296 if (rc != EOK) { 297 rc = ESTALL; 298 goto leave_stop_session; 299 } 300 301 usb_pipe_end_session(&ctrl_pipe); 302 303 /* 304 * Register the control endpoint for the new device. 305 */ 306 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 307 if (rc != EOK) { 308 rc = EREFUSED; 309 goto leave_unregister_endpoint; 310 } 311 312 /* 313 * Release the original endpoint. 314 */ 315 unregister_control_endpoint_on_default_address(&hc_conn); 316 317 /* 318 * Once the address is changed, we can return the default address. 319 */ 320 usb_hc_release_default_address(&hc_conn); 321 307 goto leave_release_free_address; 308 } 322 309 323 310 /* … … 334 321 } 335 322 336 337 338 323 /* 339 324 * And now inform the host controller about the handle. … … 367 352 * Completely ignoring errors here. 368 353 */ 369 370 leave_stop_session: 371 usb_pipe_end_session(&ctrl_pipe); 372 373 leave_unregister_endpoint: 354 leave_release_default_address: 374 355 usb_pipe_unregister(&ctrl_pipe, &hc_conn); 375 376 leave_release_default_address:377 usb_hc_release_default_address(&hc_conn);378 356 379 357 leave_release_free_address: -
uspace/lib/usb/src/pipes.c
r8790650 r501e5df 41 41 #include <errno.h> 42 42 #include <assert.h> 43 #include "pipepriv.h" 43 44 44 45 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */ … … 241 242 * necessary. 242 243 * 244 * @deprecated 245 * Obsoleted with introduction of usb_pipe_start_long_transfer 246 * 243 247 * @param pipe Endpoint pipe to start the session on. 244 248 * @return Error code. … … 246 250 int usb_pipe_start_session(usb_pipe_t *pipe) 247 251 { 248 assert(pipe); 249 250 if (usb_pipe_is_session_started(pipe)) { 251 return EBUSY; 252 } 253 254 int phone = devman_device_connect(pipe->wire->hc_handle, 0); 255 if (phone < 0) { 256 return phone; 257 } 258 259 pipe->hc_phone = phone; 260 252 usb_log_warning("usb_pipe_start_session() was deprecated.\n"); 261 253 return EOK; 262 254 } … … 265 257 /** Ends a session on the endpoint pipe. 266 258 * 259 * @deprecated 260 * Obsoleted with introduction of usb_pipe_end_long_transfer 261 * 267 262 * @see usb_pipe_start_session 268 263 * … … 272 267 int usb_pipe_end_session(usb_pipe_t *pipe) 273 268 { 274 assert(pipe); 275 276 if (!usb_pipe_is_session_started(pipe)) { 277 return ENOENT; 278 } 279 280 int rc = async_hangup(pipe->hc_phone); 281 if (rc != EOK) { 282 return rc; 283 } 284 285 pipe->hc_phone = -1; 286 269 usb_log_warning("usb_pipe_end_session() was deprecated.\n"); 287 270 return EOK; 288 271 } … … 298 281 bool usb_pipe_is_session_started(usb_pipe_t *pipe) 299 282 { 300 return (pipe->hc_phone >= 0); 283 pipe_acquire(pipe); 284 bool started = pipe->refcount > 0; 285 pipe_release(pipe); 286 return started; 287 } 288 289 /** Prepare pipe for a long transfer. 290 * 291 * By a long transfer is mean transfer consisting of several 292 * requests to the HC. 293 * Calling such function is optional and it has positive effect of 294 * improved performance because IPC session is initiated only once. 295 * 296 * @param pipe Pipe over which the transfer will happen. 297 * @return Error code. 298 */ 299 int usb_pipe_start_long_transfer(usb_pipe_t *pipe) 300 { 301 return pipe_add_ref(pipe); 302 } 303 304 /** Terminate a long transfer on a pipe. 305 * 306 * @see usb_pipe_start_long_transfer 307 * 308 * @param pipe Pipe where to end the long transfer. 309 */ 310 void usb_pipe_end_long_transfer(usb_pipe_t *pipe) 311 { 312 pipe_drop_ref(pipe); 301 313 } 302 314 -
uspace/lib/usb/src/pipesinit.c
r8790650 r501e5df 356 356 assert(connection); 357 357 358 fibril_mutex_initialize(&pipe->guard); 358 359 pipe->wire = connection; 359 360 pipe->hc_phone = -1; 361 fibril_mutex_initialize(&pipe->hc_phone_mutex); 360 362 pipe->endpoint_no = endpoint_no; 361 363 pipe->transfer_type = transfer_type; 362 364 pipe->max_packet_size = max_packet_size; 363 365 pipe->direction = direction; 366 pipe->refcount = 0; 364 367 365 368 return EOK; … … 413 416 int rc; 414 417 415 TRY_LOOP(failed_attempts) { 416 rc = usb_pipe_start_session(pipe); 417 if (rc == EOK) { 418 break; 419 } 420 } 418 rc = usb_pipe_start_long_transfer(pipe); 421 419 if (rc != EOK) { 422 420 return rc; … … 439 437 } 440 438 } 441 usb_pipe_end_ session(pipe);439 usb_pipe_end_long_transfer(pipe); 442 440 if (rc != EOK) { 443 441 return rc; … … 461 459 usb_hc_connection_t *hc_connection) 462 460 { 461 return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1, 462 interval, hc_connection); 463 } 464 465 /** Register endpoint with a speed at the host controller. 466 * 467 * You will rarely need to use this function because it is needed only 468 * if the registered endpoint is of address 0 and there is no other way 469 * to tell speed of the device at address 0. 470 * 471 * @param pipe Pipe to be registered. 472 * @param speed Speed of the device 473 * (invalid speed means use previously specified one). 474 * @param interval Polling interval. 475 * @param hc_connection Connection to the host controller (must be opened). 476 * @return Error code. 477 */ 478 int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed, 479 unsigned int interval, 480 usb_hc_connection_t *hc_connection) 481 { 463 482 assert(pipe); 464 483 assert(hc_connection); … … 468 487 } 469 488 470 #define _PACK(high, low) ((high) * 256 + (low)) 471 472 return async_req_5_0(hc_connection->hc_phone, 489 #define _PACK2(high, low) (((high) << 16) + (low)) 490 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low)) 491 492 return async_req_4_0(hc_connection->hc_phone, 473 493 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT, 474 _PACK(pipe->wire->address, pipe->endpoint_no), 475 _PACK(pipe->transfer_type, pipe->direction), 476 pipe->max_packet_size, interval); 477 478 #undef _PACK 494 _PACK2(pipe->wire->address, pipe->endpoint_no), 495 _PACK3(speed, pipe->transfer_type, pipe->direction), 496 _PACK2(pipe->max_packet_size, interval)); 497 498 #undef _PACK2 499 #undef _PACK3 479 500 } 480 501 -
uspace/lib/usb/src/pipesio.c
r8790650 r501e5df 49 49 #include <assert.h> 50 50 #include <usbhc_iface.h> 51 #include "pipepriv.h" 51 52 52 53 /** Request an in transfer, no checking of input parameters. … … 78 79 } 79 80 81 /* Ensure serialization over the phone. */ 82 pipe_start_transaction(pipe); 83 80 84 /* 81 85 * Make call identifying target USB device and type of transfer. 82 86 */ 83 aid_t opening_request = async_send_ 4(pipe->hc_phone,87 aid_t opening_request = async_send_3(pipe->hc_phone, 84 88 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 85 89 pipe->wire->address, pipe->endpoint_no, 86 pipe->max_packet_size,87 90 NULL); 88 91 if (opening_request == 0) { 92 pipe_end_transaction(pipe); 89 93 return ENOMEM; 90 94 } … … 96 100 aid_t data_request = async_data_read(pipe->hc_phone, buffer, size, 97 101 &data_request_call); 102 103 /* 104 * Since now on, someone else might access the backing phone 105 * without breaking the transfer IPC protocol. 106 */ 107 pipe_end_transaction(pipe); 98 108 99 109 if (data_request == 0) { … … 146 156 147 157 if (buffer == NULL) { 148 158 return EINVAL; 149 159 } 150 160 151 161 if (size == 0) { 152 162 return EINVAL; 153 }154 155 if (!usb_pipe_is_session_started(pipe)) {156 return EBADF;157 163 } 158 164 … … 165 171 } 166 172 173 int rc; 174 rc = pipe_add_ref(pipe); 175 if (rc != EOK) { 176 return rc; 177 } 178 179 167 180 size_t act_size = 0; 168 int rc;169 181 170 182 rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size); 183 184 pipe_drop_ref(pipe); 185 171 186 if (rc != EOK) { 172 187 return rc; … … 210 225 } 211 226 227 /* Ensure serialization over the phone. */ 228 pipe_start_transaction(pipe); 229 212 230 /* 213 231 * Make call identifying target USB device and type of transfer. 214 232 */ 215 aid_t opening_request = async_send_ 4(pipe->hc_phone,233 aid_t opening_request = async_send_3(pipe->hc_phone, 216 234 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 217 235 pipe->wire->address, pipe->endpoint_no, 218 pipe->max_packet_size,219 236 NULL); 220 237 if (opening_request == 0) { 238 pipe_end_transaction(pipe); 221 239 return ENOMEM; 222 240 } … … 226 244 */ 227 245 int rc = async_data_write_start(pipe->hc_phone, buffer, size); 246 247 /* 248 * Since now on, someone else might access the backing phone 249 * without breaking the transfer IPC protocol. 250 */ 251 pipe_end_transaction(pipe); 252 228 253 if (rc != EOK) { 229 254 async_wait_for(opening_request, NULL); … … 260 285 } 261 286 262 if (!usb_pipe_is_session_started(pipe)) {263 return EBADF;264 }265 266 287 if (pipe->direction != USB_DIRECTION_OUT) { 267 288 return EBADF; … … 272 293 } 273 294 274 int rc = usb_pipe_write_no_check(pipe, buffer, size); 295 int rc; 296 297 rc = pipe_add_ref(pipe); 298 if (rc != EOK) { 299 return rc; 300 } 301 302 rc = usb_pipe_write_no_check(pipe, buffer, size); 303 304 pipe_drop_ref(pipe); 275 305 276 306 return rc; … … 293 323 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size) 294 324 { 325 /* Ensure serialization over the phone. */ 326 pipe_start_transaction(pipe); 327 295 328 /* 296 329 * Make call identifying target USB device and control transfer type. 297 330 */ 298 aid_t opening_request = async_send_ 4(pipe->hc_phone,331 aid_t opening_request = async_send_3(pipe->hc_phone, 299 332 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ, 300 333 pipe->wire->address, pipe->endpoint_no, 301 pipe->max_packet_size,302 334 NULL); 303 335 if (opening_request == 0) { … … 311 343 setup_buffer, setup_buffer_size); 312 344 if (rc != EOK) { 345 pipe_end_transaction(pipe); 313 346 async_wait_for(opening_request, NULL); 314 347 return rc; … … 322 355 data_buffer, data_buffer_size, 323 356 &data_request_call); 357 358 /* 359 * Since now on, someone else might access the backing phone 360 * without breaking the transfer IPC protocol. 361 */ 362 pipe_end_transaction(pipe); 363 364 324 365 if (data_request == 0) { 325 366 async_wait_for(opening_request, NULL); … … 379 420 } 380 421 381 if (!usb_pipe_is_session_started(pipe)) {382 return EBADF;383 }384 385 422 if ((pipe->direction != USB_DIRECTION_BOTH) 386 423 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 388 425 } 389 426 427 int rc; 428 429 rc = pipe_add_ref(pipe); 430 if (rc != EOK) { 431 return rc; 432 } 433 390 434 size_t act_size = 0; 391 intrc = usb_pipe_control_read_no_check(pipe,435 rc = usb_pipe_control_read_no_check(pipe, 392 436 setup_buffer, setup_buffer_size, 393 437 data_buffer, data_buffer_size, &act_size); 438 439 pipe_drop_ref(pipe); 394 440 395 441 if (rc != EOK) { … … 418 464 void *data_buffer, size_t data_buffer_size) 419 465 { 466 /* Ensure serialization over the phone. */ 467 pipe_start_transaction(pipe); 468 420 469 /* 421 470 * Make call identifying target USB device and control transfer type. 422 471 */ 423 aid_t opening_request = async_send_ 5(pipe->hc_phone,472 aid_t opening_request = async_send_4(pipe->hc_phone, 424 473 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE, 425 474 pipe->wire->address, pipe->endpoint_no, 426 475 data_buffer_size, 427 pipe->max_packet_size,428 476 NULL); 429 477 if (opening_request == 0) { 478 pipe_end_transaction(pipe); 430 479 return ENOMEM; 431 480 } … … 437 486 setup_buffer, setup_buffer_size); 438 487 if (rc != EOK) { 488 pipe_end_transaction(pipe); 439 489 async_wait_for(opening_request, NULL); 440 490 return rc; … … 447 497 rc = async_data_write_start(pipe->hc_phone, 448 498 data_buffer, data_buffer_size); 499 500 /* All data sent, pipe can be released. */ 501 pipe_end_transaction(pipe); 502 449 503 if (rc != EOK) { 450 504 async_wait_for(opening_request, NULL); 451 505 return rc; 452 506 } 507 } else { 508 /* No data to send, we can release the pipe for others. */ 509 pipe_end_transaction(pipe); 453 510 } 454 511 … … 491 548 } 492 549 493 if (!usb_pipe_is_session_started(pipe)) {494 return EBADF;495 }496 497 550 if ((pipe->direction != USB_DIRECTION_BOTH) 498 551 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 500 553 } 501 554 502 int rc = usb_pipe_control_write_no_check(pipe, 555 int rc; 556 557 rc = pipe_add_ref(pipe); 558 if (rc != EOK) { 559 return rc; 560 } 561 562 rc = usb_pipe_control_write_no_check(pipe, 503 563 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size); 564 565 pipe_drop_ref(pipe); 504 566 505 567 return rc; -
uspace/lib/usb/src/recognise.c
r8790650 r501e5df 404 404 child->driver_data = dev_data; 405 405 406 rc = usb_pipe_start_session(&ctrl_pipe);407 if (rc != EOK) {408 goto failure;409 }410 411 406 rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids); 412 if (rc != EOK) {413 goto failure;414 }415 416 rc = usb_pipe_end_session(&ctrl_pipe);417 407 if (rc != EOK) { 418 408 goto failure;
Note:
See TracChangeset
for help on using the changeset viewer.