00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00046 #include <usb/usb.h>
00047 #include <usb/dev/pipes.h>
00048 #include <errno.h>
00049 #include <assert.h>
00050 #include <usbhc_iface.h>
00051 #include <usb/dev/request.h>
00052 #include "pipepriv.h"
00053
00062 static int usb_pipe_read_no_checks(usb_pipe_t *pipe,
00063 void *buffer, size_t size, size_t *size_transfered)
00064 {
00065
00066
00067
00068
00069
00070 usbhc_iface_funcs_t ipc_method;
00071 switch (pipe->transfer_type) {
00072 case USB_TRANSFER_INTERRUPT:
00073 ipc_method = IPC_M_USBHC_INTERRUPT_IN;
00074 break;
00075 case USB_TRANSFER_BULK:
00076 ipc_method = IPC_M_USBHC_BULK_IN;
00077 break;
00078 default:
00079 return ENOTSUP;
00080 }
00081
00082
00083 pipe_start_transaction(pipe);
00084
00085
00086
00087
00088 aid_t opening_request = async_send_3(pipe->hc_phone,
00089 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
00090 pipe->wire->address, pipe->endpoint_no,
00091 NULL);
00092 if (opening_request == 0) {
00093 pipe_end_transaction(pipe);
00094 return ENOMEM;
00095 }
00096
00097
00098
00099
00100 ipc_call_t data_request_call;
00101 aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
00102 &data_request_call);
00103
00104
00105
00106
00107
00108 pipe_end_transaction(pipe);
00109
00110 if (data_request == 0) {
00111
00112
00113
00114
00115 async_wait_for(opening_request, NULL);
00116 return ENOMEM;
00117 }
00118
00119
00120
00121
00122 sysarg_t data_request_rc;
00123 sysarg_t opening_request_rc;
00124 async_wait_for(data_request, &data_request_rc);
00125 async_wait_for(opening_request, &opening_request_rc);
00126
00127 if (data_request_rc != EOK) {
00128
00129 if (opening_request_rc != EOK) {
00130 return (int) opening_request_rc;
00131 } else {
00132 return (int) data_request_rc;
00133 }
00134 }
00135 if (opening_request_rc != EOK) {
00136 return (int) opening_request_rc;
00137 }
00138
00139 *size_transfered = IPC_GET_ARG2(data_request_call);
00140
00141 return EOK;
00142 }
00143
00144
00153 int usb_pipe_read(usb_pipe_t *pipe,
00154 void *buffer, size_t size, size_t *size_transfered)
00155 {
00156 assert(pipe);
00157
00158 if (buffer == NULL) {
00159 return EINVAL;
00160 }
00161
00162 if (size == 0) {
00163 return EINVAL;
00164 }
00165
00166 if (pipe->direction != USB_DIRECTION_IN) {
00167 return EBADF;
00168 }
00169
00170 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
00171 return EBADF;
00172 }
00173
00174 int rc;
00175 rc = pipe_add_ref(pipe, false);
00176 if (rc != EOK) {
00177 return rc;
00178 }
00179
00180
00181 size_t act_size = 0;
00182
00183 rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
00184
00185 pipe_drop_ref(pipe);
00186
00187 if (rc != EOK) {
00188 return rc;
00189 }
00190
00191 if (size_transfered != NULL) {
00192 *size_transfered = act_size;
00193 }
00194
00195 return EOK;
00196 }
00197
00198
00199
00200
00208 static int usb_pipe_write_no_check(usb_pipe_t *pipe,
00209 void *buffer, size_t size)
00210 {
00211
00212
00213
00214
00215
00216 usbhc_iface_funcs_t ipc_method;
00217 switch (pipe->transfer_type) {
00218 case USB_TRANSFER_INTERRUPT:
00219 ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
00220 break;
00221 case USB_TRANSFER_BULK:
00222 ipc_method = IPC_M_USBHC_BULK_OUT;
00223 break;
00224 default:
00225 return ENOTSUP;
00226 }
00227
00228
00229 pipe_start_transaction(pipe);
00230
00231
00232
00233
00234 aid_t opening_request = async_send_3(pipe->hc_phone,
00235 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
00236 pipe->wire->address, pipe->endpoint_no,
00237 NULL);
00238 if (opening_request == 0) {
00239 pipe_end_transaction(pipe);
00240 return ENOMEM;
00241 }
00242
00243
00244
00245
00246 int rc = async_data_write_start(pipe->hc_phone, buffer, size);
00247
00248
00249
00250
00251
00252 pipe_end_transaction(pipe);
00253
00254 if (rc != EOK) {
00255 async_wait_for(opening_request, NULL);
00256 return rc;
00257 }
00258
00259
00260
00261
00262 sysarg_t opening_request_rc;
00263 async_wait_for(opening_request, &opening_request_rc);
00264
00265 return (int) opening_request_rc;
00266 }
00267
00275 int usb_pipe_write(usb_pipe_t *pipe,
00276 void *buffer, size_t size)
00277 {
00278 assert(pipe);
00279
00280 if (buffer == NULL) {
00281 return EINVAL;
00282 }
00283
00284 if (size == 0) {
00285 return EINVAL;
00286 }
00287
00288 if (pipe->direction != USB_DIRECTION_OUT) {
00289 return EBADF;
00290 }
00291
00292 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
00293 return EBADF;
00294 }
00295
00296 int rc;
00297
00298 rc = pipe_add_ref(pipe, false);
00299 if (rc != EOK) {
00300 return rc;
00301 }
00302
00303 rc = usb_pipe_write_no_check(pipe, buffer, size);
00304
00305 pipe_drop_ref(pipe);
00306
00307 return rc;
00308 }
00309
00314 static void clear_self_endpoint_halt(usb_pipe_t *pipe)
00315 {
00316 assert(pipe != NULL);
00317
00318 if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
00319 return;
00320 }
00321
00322
00323
00324 pipe->auto_reset_halt = false;
00325 usb_request_clear_endpoint_halt(pipe, 0);
00326 pipe->auto_reset_halt = true;
00327 }
00328
00329
00341 static int usb_pipe_control_read_no_check(usb_pipe_t *pipe,
00342 void *setup_buffer, size_t setup_buffer_size,
00343 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
00344 {
00345
00346 pipe_start_transaction(pipe);
00347
00348
00349
00350
00351 aid_t opening_request = async_send_3(pipe->hc_phone,
00352 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
00353 pipe->wire->address, pipe->endpoint_no,
00354 NULL);
00355 if (opening_request == 0) {
00356 return ENOMEM;
00357 }
00358
00359
00360
00361
00362 int rc = async_data_write_start(pipe->hc_phone,
00363 setup_buffer, setup_buffer_size);
00364 if (rc != EOK) {
00365 pipe_end_transaction(pipe);
00366 async_wait_for(opening_request, NULL);
00367 return rc;
00368 }
00369
00370
00371
00372
00373 ipc_call_t data_request_call;
00374 aid_t data_request = async_data_read(pipe->hc_phone,
00375 data_buffer, data_buffer_size,
00376 &data_request_call);
00377
00378
00379
00380
00381
00382 pipe_end_transaction(pipe);
00383
00384
00385 if (data_request == 0) {
00386 async_wait_for(opening_request, NULL);
00387 return ENOMEM;
00388 }
00389
00390
00391
00392
00393 sysarg_t data_request_rc;
00394 sysarg_t opening_request_rc;
00395 async_wait_for(data_request, &data_request_rc);
00396 async_wait_for(opening_request, &opening_request_rc);
00397
00398 if (data_request_rc != EOK) {
00399
00400 if (opening_request_rc != EOK) {
00401 return (int) opening_request_rc;
00402 } else {
00403 return (int) data_request_rc;
00404 }
00405 }
00406 if (opening_request_rc != EOK) {
00407 return (int) opening_request_rc;
00408 }
00409
00410 *data_transfered_size = IPC_GET_ARG2(data_request_call);
00411
00412 return EOK;
00413 }
00414
00428 int usb_pipe_control_read(usb_pipe_t *pipe,
00429 void *setup_buffer, size_t setup_buffer_size,
00430 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
00431 {
00432 assert(pipe);
00433
00434 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
00435 return EINVAL;
00436 }
00437
00438 if ((data_buffer == NULL) || (data_buffer_size == 0)) {
00439 return EINVAL;
00440 }
00441
00442 if ((pipe->direction != USB_DIRECTION_BOTH)
00443 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
00444 return EBADF;
00445 }
00446
00447 int rc;
00448
00449 rc = pipe_add_ref(pipe, false);
00450 if (rc != EOK) {
00451 return rc;
00452 }
00453
00454 size_t act_size = 0;
00455 rc = usb_pipe_control_read_no_check(pipe,
00456 setup_buffer, setup_buffer_size,
00457 data_buffer, data_buffer_size, &act_size);
00458
00459 if (rc == ESTALL) {
00460 clear_self_endpoint_halt(pipe);
00461 }
00462
00463 pipe_drop_ref(pipe);
00464
00465 if (rc != EOK) {
00466 return rc;
00467 }
00468
00469 if (data_transfered_size != NULL) {
00470 *data_transfered_size = act_size;
00471 }
00472
00473 return EOK;
00474 }
00475
00476
00486 static int usb_pipe_control_write_no_check(usb_pipe_t *pipe,
00487 void *setup_buffer, size_t setup_buffer_size,
00488 void *data_buffer, size_t data_buffer_size)
00489 {
00490
00491 pipe_start_transaction(pipe);
00492
00493
00494
00495
00496 aid_t opening_request = async_send_4(pipe->hc_phone,
00497 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
00498 pipe->wire->address, pipe->endpoint_no,
00499 data_buffer_size,
00500 NULL);
00501 if (opening_request == 0) {
00502 pipe_end_transaction(pipe);
00503 return ENOMEM;
00504 }
00505
00506
00507
00508
00509 int rc = async_data_write_start(pipe->hc_phone,
00510 setup_buffer, setup_buffer_size);
00511 if (rc != EOK) {
00512 pipe_end_transaction(pipe);
00513 async_wait_for(opening_request, NULL);
00514 return rc;
00515 }
00516
00517
00518
00519
00520 if (data_buffer_size > 0) {
00521 rc = async_data_write_start(pipe->hc_phone,
00522 data_buffer, data_buffer_size);
00523
00524
00525 pipe_end_transaction(pipe);
00526
00527 if (rc != EOK) {
00528 async_wait_for(opening_request, NULL);
00529 return rc;
00530 }
00531 } else {
00532
00533 pipe_end_transaction(pipe);
00534 }
00535
00536
00537
00538
00539 sysarg_t opening_request_rc;
00540 async_wait_for(opening_request, &opening_request_rc);
00541
00542 return (int) opening_request_rc;
00543 }
00544
00556 int usb_pipe_control_write(usb_pipe_t *pipe,
00557 void *setup_buffer, size_t setup_buffer_size,
00558 void *data_buffer, size_t data_buffer_size)
00559 {
00560 assert(pipe);
00561
00562 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
00563 return EINVAL;
00564 }
00565
00566 if ((data_buffer == NULL) && (data_buffer_size > 0)) {
00567 return EINVAL;
00568 }
00569
00570 if ((data_buffer != NULL) && (data_buffer_size == 0)) {
00571 return EINVAL;
00572 }
00573
00574 if ((pipe->direction != USB_DIRECTION_BOTH)
00575 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
00576 return EBADF;
00577 }
00578
00579 int rc;
00580
00581 rc = pipe_add_ref(pipe, false);
00582 if (rc != EOK) {
00583 return rc;
00584 }
00585
00586 rc = usb_pipe_control_write_no_check(pipe,
00587 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
00588
00589 if (rc == ESTALL) {
00590 clear_self_endpoint_halt(pipe);
00591 }
00592
00593 pipe_drop_ref(pipe);
00594
00595 return rc;
00596 }
00597
00598