Changeset 92574f4 in mainline for uspace/lib/usb/src/pipes.c
- Timestamp:
- 2011-02-24T12:03:27Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e7b7ebd5
- Parents:
- 4837092 (diff), a80849c (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/pipes.c
r4837092 r92574f4 31 31 */ 32 32 /** @file 33 * Communication between device drivers and host controller driver. 34 * 35 * Note on synchronousness of the operations: there is ABSOLUTELY NO 36 * guarantee that a call to particular function will not trigger a fibril 37 * switch. 38 * The initialization functions may actually involve contacting some other 39 * task, starting/ending a session might involve asynchronous IPC and since 40 * the transfer functions uses IPC, asynchronous nature of them is obvious. 41 * The pseudo synchronous versions for the transfers internally call the 42 * asynchronous ones and so fibril switch is possible in them as well. 33 * USB endpoint pipes miscellaneous functions. 43 34 */ 44 35 #include <usb/usb.h> 45 36 #include <usb/pipes.h> 37 #include <usb/debug.h> 38 #include <usbhc_iface.h> 39 #include <usb_iface.h> 40 #include <devman.h> 46 41 #include <errno.h> 47 42 #include <assert.h> 48 #include <usb/usbdrv.h> 49 50 #define _PREPARE_TARGET(varname, pipe) \ 51 usb_target_t varname = { \ 52 .address = (pipe)->wire->address, \ 53 .endpoint = (pipe)->endpoint_no \ 54 } 43 44 /** Tell USB address assigned to given device. 45 * 46 * @param phone Phone to parent device. 47 * @param dev Device in question. 48 * @return USB address or error code. 49 */ 50 static usb_address_t get_my_address(int phone, ddf_dev_t *dev) 51 { 52 sysarg_t address; 53 54 55 /* 56 * We are sending special value as a handle - zero - to get 57 * handle of the parent function (that handle was used 58 * when registering our device @p dev. 59 */ 60 int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE), 61 IPC_M_USB_GET_ADDRESS, 62 0, &address); 63 64 if (rc != EOK) { 65 return rc; 66 } 67 68 return (usb_address_t) address; 69 } 70 71 /** Tell USB interface assigned to given device. 72 * 73 * @param device Device in question. 74 * @return Interface number (negative code means any). 75 */ 76 int usb_device_get_assigned_interface(ddf_dev_t *device) 77 { 78 int parent_phone = devman_parent_device_connect(device->handle, 79 IPC_FLAG_BLOCKING); 80 if (parent_phone < 0) { 81 return -1; 82 } 83 84 sysarg_t iface_no; 85 int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE), 86 IPC_M_USB_GET_INTERFACE, 87 device->handle, &iface_no); 88 89 async_hangup(parent_phone); 90 91 if (rc != EOK) { 92 return -1; 93 } 94 95 return (int) iface_no; 96 } 55 97 56 98 /** Initialize connection to USB device. … … 61 103 */ 62 104 int usb_device_connection_initialize_from_device( 63 usb_device_connection_t *connection, d evice_t *device)105 usb_device_connection_t *connection, ddf_dev_t *dev) 64 106 { 65 107 assert(connection); 66 assert(dev ice);108 assert(dev); 67 109 68 110 int rc; … … 70 112 usb_address_t my_address; 71 113 72 rc = usb_ drv_find_hc(device, &hc_handle);114 rc = usb_hc_find(dev->handle, &hc_handle); 73 115 if (rc != EOK) { 74 116 return rc; 75 117 } 76 118 77 int hc_phone = devman_device_connect(hc_handle, 0); 78 if (hc_phone < 0) { 79 return hc_phone; 80 } 81 82 my_address = usb_drv_get_my_address(hc_phone, device); 119 int parent_phone = devman_parent_device_connect(dev->handle, 120 IPC_FLAG_BLOCKING); 121 if (parent_phone < 0) { 122 return parent_phone; 123 } 124 125 my_address = get_my_address(parent_phone, dev); 83 126 if (my_address < 0) { 84 127 rc = my_address; … … 90 133 91 134 leave: 92 ipc_hangup(hc_phone);135 async_hangup(parent_phone); 93 136 return rc; 94 137 } … … 117 160 } 118 161 119 /** Initialize USB endpoint pipe. 120 * 121 * @param pipe Endpoint pipe to be initialized. 122 * @param connection Connection to the USB device backing this pipe (the wire). 123 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15). 124 * @param transfer_type Transfer type (e.g. interrupt or bulk). 125 * @param direction Endpoint direction (in/out). 126 * @return Error code. 127 */ 128 int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *pipe, 129 usb_device_connection_t *connection, usb_endpoint_t endpoint_no, 130 usb_transfer_type_t transfer_type, usb_direction_t direction) 131 { 132 assert(pipe); 133 assert(connection); 134 135 pipe->wire = connection; 136 pipe->hc_phone = -1; 137 pipe->endpoint_no = endpoint_no; 138 pipe->transfer_type = transfer_type; 139 pipe->direction = direction; 140 141 return EOK; 142 } 143 144 145 /** Initialize USB endpoint pipe as the default zero control pipe. 146 * 147 * @param pipe Endpoint pipe to be initialized. 148 * @param connection Connection to the USB device backing this pipe (the wire). 149 * @return Error code. 150 */ 151 int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *pipe, 152 usb_device_connection_t *connection) 153 { 154 assert(pipe); 155 assert(connection); 156 157 int rc = usb_endpoint_pipe_initialize(pipe, connection, 158 0, USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH); 159 160 return rc; 162 /** Initialize connection to USB device on default address. 163 * 164 * @param dev_connection Device connection structure to be initialized. 165 * @param hc_connection Initialized connection to host controller. 166 * @return Error code. 167 */ 168 int usb_device_connection_initialize_on_default_address( 169 usb_device_connection_t *dev_connection, 170 usb_hc_connection_t *hc_connection) 171 { 172 assert(dev_connection); 173 174 if (hc_connection == NULL) { 175 return EBADMEM; 176 } 177 178 return usb_device_connection_initialize(dev_connection, 179 hc_connection->hc_handle, (usb_address_t) 0); 161 180 } 162 181 … … 181 200 assert(pipe); 182 201 183 if ( pipe->hc_phone >= 0) {202 if (usb_endpoint_pipe_is_session_started(pipe)) { 184 203 return EBUSY; 185 204 } … … 207 226 assert(pipe); 208 227 209 if ( pipe->hc_phone < 0) {228 if (!usb_endpoint_pipe_is_session_started(pipe)) { 210 229 return ENOENT; 211 230 } 212 231 213 int rc = ipc_hangup(pipe->hc_phone);232 int rc = async_hangup(pipe->hc_phone); 214 233 if (rc != EOK) { 215 234 return rc; … … 221 240 } 222 241 223 224 /** Request a read (in) transfer on an endpoint pipe. 225 * 226 * @param[in] pipe Pipe used for the transfer. 227 * @param[out] buffer Buffer where to store the data. 228 * @param[in] size Size of the buffer (in bytes). 229 * @param[out] size_transfered Number of bytes that were actually transfered. 230 * @return Error code. 231 */ 232 int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe, 233 void *buffer, size_t size, size_t *size_transfered) 234 { 235 assert(pipe); 236 237 int rc; 238 usb_handle_t handle; 239 240 rc = usb_endpoint_pipe_async_read(pipe, buffer, size, size_transfered, 241 &handle); 242 if (rc != EOK) { 243 return rc; 244 } 245 246 rc = usb_endpoint_pipe_wait_for(pipe, handle); 247 return rc; 248 } 249 250 /** Request a write (out) transfer on an endpoint pipe. 251 * 252 * @param[in] pipe Pipe used for the transfer. 253 * @param[in] buffer Buffer with data to transfer. 254 * @param[in] size Size of the buffer (in bytes). 255 * @return Error code. 256 */ 257 int usb_endpoint_pipe_write(usb_endpoint_pipe_t *pipe, 258 void *buffer, size_t size) 259 { 260 assert(pipe); 261 262 int rc; 263 usb_handle_t handle; 264 265 rc = usb_endpoint_pipe_async_write(pipe, buffer, size, &handle); 266 if (rc != EOK) { 267 return rc; 268 } 269 270 rc = usb_endpoint_pipe_wait_for(pipe, handle); 271 return rc; 272 } 273 274 275 /** Request a control read transfer on an endpoint pipe. 276 * 277 * This function encapsulates all three stages of a control transfer. 278 * 279 * @param[in] pipe Pipe used for the transfer. 280 * @param[in] setup_buffer Buffer with the setup packet. 281 * @param[in] setup_buffer_size Size of the setup packet (in bytes). 282 * @param[out] data_buffer Buffer for incoming data. 283 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes). 284 * @param[out] data_transfered_size Number of bytes that were actually 285 * transfered during the DATA stage. 286 * @return Error code. 287 */ 288 int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe, 289 void *setup_buffer, size_t setup_buffer_size, 290 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size) 291 { 292 assert(pipe); 293 294 int rc; 295 usb_handle_t handle; 296 297 rc = usb_endpoint_pipe_async_control_read(pipe, 298 setup_buffer, setup_buffer_size, 299 data_buffer, data_buffer_size, data_transfered_size, 300 &handle); 301 if (rc != EOK) { 302 return rc; 303 } 304 305 rc = usb_endpoint_pipe_wait_for(pipe, handle); 306 return rc; 307 } 308 309 310 /** Request a control write transfer on an endpoint pipe. 311 * 312 * This function encapsulates all three stages of a control transfer. 313 * 314 * @param[in] pipe Pipe used for the transfer. 315 * @param[in] setup_buffer Buffer with the setup packet. 316 * @param[in] setup_buffer_size Size of the setup packet (in bytes). 317 * @param[in] data_buffer Buffer with data to be sent. 318 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes). 319 * @return Error code. 320 */ 321 int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe, 322 void *setup_buffer, size_t setup_buffer_size, 323 void *data_buffer, size_t data_buffer_size) 324 { 325 assert(pipe); 326 327 int rc; 328 usb_handle_t handle; 329 330 rc = usb_endpoint_pipe_async_control_write(pipe, 331 setup_buffer, setup_buffer_size, 332 data_buffer, data_buffer_size, 333 &handle); 334 if (rc != EOK) { 335 return rc; 336 } 337 338 rc = usb_endpoint_pipe_wait_for(pipe, handle); 339 return rc; 340 } 341 342 343 /** Request a read (in) transfer on an endpoint pipe (asynchronous version). 344 * 345 * @param[in] pipe Pipe used for the transfer. 346 * @param[out] buffer Buffer where to store the data. 347 * @param[in] size Size of the buffer (in bytes). 348 * @param[out] size_transfered Number of bytes that were actually transfered. 349 * @param[out] handle Handle of the transfer. 350 * @return Error code. 351 */ 352 int usb_endpoint_pipe_async_read(usb_endpoint_pipe_t *pipe, 353 void *buffer, size_t size, size_t *size_transfered, 354 usb_handle_t *handle) 355 { 356 assert(pipe); 357 358 if (pipe->hc_phone < 0) { 359 return EBADF; 360 } 361 362 if (pipe->direction != USB_DIRECTION_IN) { 363 return EBADF; 364 } 365 366 int rc; 367 _PREPARE_TARGET(target, pipe); 368 369 switch (pipe->transfer_type) { 370 case USB_TRANSFER_INTERRUPT: 371 rc = usb_drv_async_interrupt_in(pipe->hc_phone, target, 372 buffer, size, size_transfered, handle); 373 break; 374 case USB_TRANSFER_CONTROL: 375 rc = EBADF; 376 break; 377 default: 378 rc = ENOTSUP; 379 break; 380 } 381 382 return rc; 383 } 384 385 386 /** Request a write (out) transfer on an endpoint pipe (asynchronous version). 387 * 388 * @param[in] pipe Pipe used for the transfer. 389 * @param[in] buffer Buffer with data to transfer. 390 * @param[in] size Size of the buffer (in bytes). 391 * @param[out] handle Handle of the transfer. 392 * @return Error code. 393 */ 394 int usb_endpoint_pipe_async_write(usb_endpoint_pipe_t *pipe, 395 void *buffer, size_t size, 396 usb_handle_t *handle) 397 { 398 assert(pipe); 399 400 if (pipe->hc_phone < 0) { 401 return EBADF; 402 } 403 404 if (pipe->direction != USB_DIRECTION_OUT) { 405 return EBADF; 406 } 407 408 int rc; 409 _PREPARE_TARGET(target, pipe); 410 411 switch (pipe->transfer_type) { 412 case USB_TRANSFER_INTERRUPT: 413 rc = usb_drv_async_interrupt_out(pipe->hc_phone, target, 414 buffer, size, handle); 415 break; 416 case USB_TRANSFER_CONTROL: 417 rc = EBADF; 418 break; 419 default: 420 rc = ENOTSUP; 421 break; 422 } 423 424 return rc; 425 } 426 427 428 /** Request a control read transfer on an endpoint pipe (asynchronous version). 429 * 430 * This function encapsulates all three stages of a control transfer. 431 * 432 * @param[in] pipe Pipe used for the transfer. 433 * @param[in] setup_buffer Buffer with the setup packet. 434 * @param[in] setup_buffer_size Size of the setup packet (in bytes). 435 * @param[out] data_buffer Buffer for incoming data. 436 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes). 437 * @param[out] data_transfered_size Number of bytes that were actually 438 * transfered during the DATA stage. 439 * @param[out] handle Handle of the transfer. 440 * @return Error code. 441 */ 442 int usb_endpoint_pipe_async_control_read(usb_endpoint_pipe_t *pipe, 443 void *setup_buffer, size_t setup_buffer_size, 444 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size, 445 usb_handle_t *handle) 446 { 447 assert(pipe); 448 449 if (pipe->hc_phone < 0) { 450 return EBADF; 451 } 452 453 if ((pipe->direction != USB_DIRECTION_BOTH) 454 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 455 return EBADF; 456 } 457 458 int rc; 459 _PREPARE_TARGET(target, pipe); 460 461 rc = usb_drv_async_control_read(pipe->hc_phone, target, 462 setup_buffer, setup_buffer_size, 463 data_buffer, data_buffer_size, data_transfered_size, 464 handle); 465 466 return rc; 467 } 468 469 470 /** Request a control write transfer on an endpoint pipe (asynchronous version). 471 * 472 * This function encapsulates all three stages of a control transfer. 473 * 474 * @param[in] pipe Pipe used for the transfer. 475 * @param[in] setup_buffer Buffer with the setup packet. 476 * @param[in] setup_buffer_size Size of the setup packet (in bytes). 477 * @param[in] data_buffer Buffer with data to be sent. 478 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes). 479 * @param[out] handle Handle of the transfer. 480 * @return Error code. 481 */ 482 int usb_endpoint_pipe_async_control_write(usb_endpoint_pipe_t *pipe, 483 void *setup_buffer, size_t setup_buffer_size, 484 void *data_buffer, size_t data_buffer_size, 485 usb_handle_t *handle) 486 { 487 assert(pipe); 488 489 if (pipe->hc_phone < 0) { 490 return EBADF; 491 } 492 493 if ((pipe->direction != USB_DIRECTION_BOTH) 494 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 495 return EBADF; 496 } 497 498 int rc; 499 _PREPARE_TARGET(target, pipe); 500 501 rc = usb_drv_async_control_write(pipe->hc_phone, target, 502 setup_buffer, setup_buffer_size, 503 data_buffer, data_buffer_size, 504 handle); 505 506 return rc; 507 } 508 509 /** Wait for transfer completion. 510 * 511 * The function blocks the caller fibril until the transfer associated 512 * with given @p handle is completed. 513 * 514 * @param[in] pipe Pipe the transfer executed on. 515 * @param[in] handle Transfer handle. 516 * @return Error code. 517 */ 518 int usb_endpoint_pipe_wait_for(usb_endpoint_pipe_t *pipe, usb_handle_t handle) 519 { 520 return usb_drv_async_wait_for(handle); 521 } 522 242 /** Tell whether a session is started (open) on the endpoint pipe. 243 * 244 * The expected usage of this function is in assertions for some 245 * nested functions. 246 * 247 * @param pipe Endpoint pipe in question. 248 * @return Whether @p pipe has opened a session. 249 */ 250 bool usb_endpoint_pipe_is_session_started(usb_endpoint_pipe_t *pipe) 251 { 252 return (pipe->hc_phone >= 0); 253 } 523 254 524 255 /**
Note:
See TracChangeset
for help on using the changeset viewer.