Changeset 5595841 in mainline
- Timestamp:
- 2018-01-31T16:02:34Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3b60ea0
- Parents:
- 2b3dd78
- git-author:
- Ondřej Hlavatý <aearsis@…> (2018-01-31 15:49:24)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2018-01-31 16:02:34)
- Location:
- uspace/lib
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
r2b3dd78 r5595841 39 39 #include <errno.h> 40 40 #include <devman.h> 41 #include <as.h> 41 42 42 43 #include "usbhc_iface.h" … … 178 179 } 179 180 180 errno_t usbhc_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 181 void *data, size_t size, size_t *rec_size) 182 { 181 /** 182 * Issue a USB transfer with a data contained in memory area. That area is 183 * temporarily shared with the HC. 184 */ 185 errno_t usbhc_transfer(async_exch_t *exch, usb_endpoint_t endpoint, 186 usb_direction_t dir, uint64_t setup, void *area, size_t size, 187 size_t *transferred) 188 { 189 if (transferred) 190 *transferred = 0; 191 183 192 if (!exch) 184 193 return EBADMEM; … … 187 196 return EOK; 188 197 189 /* Make call identifying target USB device and type of transfer. */ 190 aid_t opening_request = async_send_4(exch, 191 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_READ, endpoint, 192 (setup & UINT32_MAX), (setup >> 32), NULL); 193 194 if (opening_request == 0) { 198 sysarg_t method = (dir == USB_DIRECTION_IN) 199 ? IPC_M_USB_READ : IPC_M_USB_WRITE; 200 201 ipc_call_t call; 202 203 204 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 205 method, endpoint, size, (setup & UINT32_MAX), (setup >> 32), &call); 206 207 if (opening_request == 0) 195 208 return ENOMEM; 196 }197 198 /* Retrieve the data. */199 ipc_call_t data_request_call;200 aid_t data_request =201 async_data_read(exch, data, size, &data_request_call);202 203 if (data_request == 0) {204 // FIXME: How to let the other side know that we want to abort?205 async_forget(opening_request);206 return ENOMEM;207 }208 209 /* Wait for the answer. */210 errno_t data_request_rc;211 errno_t opening_request_rc;212 async_wait_for(data_request, &data_request_rc);213 async_wait_for(opening_request, &opening_request_rc);214 215 if (data_request_rc != EOK) {216 /* Prefer the return code of the opening request. */217 if (opening_request_rc != EOK) {218 return (errno_t) opening_request_rc;219 } else {220 return (errno_t) data_request_rc;221 }222 }223 if (opening_request_rc != EOK) {224 return (errno_t) opening_request_rc;225 }226 227 *rec_size = IPC_GET_ARG2(data_request_call);228 return EOK;229 }230 231 errno_t usbhc_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,232 const void *data, size_t size)233 {234 if (!exch)235 return EBADMEM;236 237 if (size == 0 && setup == 0)238 return EOK;239 240 aid_t opening_request = async_send_5(exch,241 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,242 (setup & UINT32_MAX), (setup >> 32), NULL);243 244 if (opening_request == 0) {245 return ENOMEM;246 }247 209 248 210 /* Send the data if any. */ 249 211 if (size > 0) { 250 const errno_t ret = async_data_write_start(exch, data, size); 212 unsigned flags = (dir == USB_DIRECTION_IN) 213 ? AS_AREA_WRITE : AS_AREA_READ; 214 215 const errno_t ret = async_share_out_start(exch, area, flags); 251 216 if (ret != EOK) { 252 217 async_forget(opening_request); … … 259 224 async_wait_for(opening_request, &opening_request_rc); 260 225 226 if (transferred) 227 *transferred = IPC_GET_ARG1(call); 228 261 229 return (errno_t) opening_request_rc; 230 } 231 232 errno_t usbhc_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 233 void *data, size_t size, size_t *rec_size) 234 { 235 if (size == 0) 236 return usbhc_transfer(exch, endpoint, USB_DIRECTION_IN, 237 setup, NULL, 0, NULL); 238 239 /* Prepare an area to read */ 240 void *area = as_area_create(AS_AREA_ANY, size, 241 AS_AREA_READ | AS_AREA_WRITE, AS_AREA_UNPAGED); 242 if (!area) 243 return ENOMEM; 244 245 const errno_t err = usbhc_transfer(exch, endpoint, USB_DIRECTION_IN, 246 setup, area, size, rec_size); 247 if (err == EOK) 248 memcpy(data, area, *rec_size); 249 250 as_area_destroy(area); 251 return err; 252 } 253 254 errno_t usbhc_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 255 const void *data, size_t size) 256 { 257 if (size == 0) 258 return usbhc_transfer(exch, endpoint, USB_DIRECTION_OUT, 259 setup, NULL, 0, NULL); 260 261 /* Prepare an area to read */ 262 void *area = as_area_create(AS_AREA_ANY, size, 263 AS_AREA_READ | AS_AREA_WRITE, AS_AREA_UNPAGED); 264 if (!area) 265 return ENOMEM; 266 267 memcpy(area, data, size); 268 const errno_t err = usbhc_transfer(exch, endpoint, USB_DIRECTION_OUT, 269 setup, area, size, NULL); 270 as_area_destroy(area); 271 return err; 262 272 } 263 273 … … 267 277 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 268 278 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 269 static void remote_usbhc_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 270 static void remote_usbhc_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 279 static void remote_usbhc_transfer(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 271 280 272 281 /** Remote USB interface operations. */ … … 277 286 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 278 287 [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 279 [IPC_M_USB_READ] = remote_usbhc_ read,280 [IPC_M_USB_WRITE] = remote_usbhc_ write,288 [IPC_M_USB_READ] = remote_usbhc_transfer, 289 [IPC_M_USB_WRITE] = remote_usbhc_transfer, 281 290 }; 282 291 … … 290 299 typedef struct { 291 300 ipc_callid_t caller; 292 ipc_callid_t data_caller;293 301 void *buffer; 294 302 } async_transaction_t; … … 413 421 } 414 422 if (trans->buffer != NULL) { 415 free(trans->buffer);423 as_area_destroy(trans->buffer); 416 424 } 417 425 … … 427 435 428 436 trans->caller = caller; 429 trans->data_caller = 0;430 437 trans->buffer = NULL; 431 438 … … 433 440 } 434 441 435 static errno_t callback_out(void *arg, int error, size_t transferred_size)442 static errno_t transfer_finished(void *arg, int error, size_t transferred_size) 436 443 { 437 444 async_transaction_t *trans = arg; 438 439 const errno_t err = async_answer_0(trans->caller, error); 440 441 async_transaction_destroy(trans); 442 443 return err; 444 } 445 446 static errno_t callback_in(void *arg, int error, size_t transferred_size) 447 { 448 async_transaction_t *trans = arg; 449 450 if (trans->data_caller) { 451 if (error == EOK) { 452 error = async_data_read_finalize(trans->data_caller, 453 trans->buffer, transferred_size); 454 } else { 455 async_answer_0(trans->data_caller, EINTR); 456 } 457 } 458 459 const errno_t err = async_answer_0(trans->caller, error); 445 const errno_t err = async_answer_1(trans->caller, error, transferred_size); 460 446 async_transaction_destroy(trans); 461 447 return err; 462 448 } 463 449 464 void remote_usbhc_read( 465 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 450 static errno_t receive_memory_buffer(async_transaction_t *trans, 451 size_t required_size, unsigned required_flags) 452 { 453 assert(trans); 454 assert(required_size > 0); 455 456 errno_t err; 457 ipc_callid_t data_callid; 458 size_t size; 459 unsigned flags; 460 461 if (!async_share_out_receive(&data_callid, &size, &flags)) 462 return EPARTY; 463 464 if (size < required_size || (flags & required_flags) != required_flags) { 465 async_answer_0(data_callid, EINVAL); 466 return EINVAL; 467 } 468 469 if ((err = async_share_out_finalize(data_callid, &trans->buffer))) 470 return err; 471 472 return EOK; 473 } 474 475 void remote_usbhc_transfer(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 466 476 { 467 477 assert(fun); … … 471 481 const usbhc_iface_t *usbhc_iface = iface; 472 482 473 if (!usbhc_iface-> read) {483 if (!usbhc_iface->transfer) { 474 484 async_answer_0(callid, ENOTSUP); 475 485 return; 476 486 } 477 487 478 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 479 const uint64_t setup = 480 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 481 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 488 const sysarg_t method = IPC_GET_ARG1(*call); 489 const usb_direction_t dir = 490 method == IPC_M_USB_READ ? USB_DIRECTION_IN : USB_DIRECTION_OUT; 491 492 const usb_endpoint_t ep = IPC_GET_ARG2(*call); 493 const size_t size = IPC_GET_ARG3(*call); 494 const uint64_t setup = ((uint64_t)IPC_GET_ARG4(*call)) | 495 (((uint64_t)IPC_GET_ARG5(*call)) << 32); 482 496 483 497 async_transaction_t *trans = async_transaction_create(callid); … … 487 501 } 488 502 489 size_t size = 0; 490 if (!async_data_read_receive(&trans->data_caller, &size)) { 491 async_answer_0(callid, EPARTY); 492 async_transaction_destroy(trans); 493 return; 494 } 495 496 trans->buffer = malloc(size); 497 if (trans->buffer == NULL) { 498 async_answer_0(trans->data_caller, ENOMEM); 499 async_answer_0(callid, ENOMEM); 500 async_transaction_destroy(trans); 501 return; 502 } 503 504 const usb_target_t target = {{ 505 /* .address is initialized by read itself */ 506 .endpoint = ep, 507 }}; 508 509 const errno_t rc = usbhc_iface->read( 510 fun, target, setup, trans->buffer, size, callback_in, trans); 511 512 if (rc != EOK) { 513 async_answer_0(trans->data_caller, rc); 514 async_answer_0(callid, rc); 515 async_transaction_destroy(trans); 516 } 517 } 518 519 void remote_usbhc_write( 520 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 521 { 522 assert(fun); 523 assert(iface); 524 assert(call); 525 526 const usbhc_iface_t *usbhc_iface = iface; 527 528 if (!usbhc_iface->write) { 529 async_answer_0(callid, ENOTSUP); 530 return; 531 } 532 533 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 534 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 535 const uint64_t setup = 536 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 537 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 538 539 async_transaction_t *trans = async_transaction_create(callid); 540 if (trans == NULL) { 541 async_answer_0(callid, ENOMEM); 542 return; 543 } 544 545 size_t size = 0; 546 if (data_buffer_len > 0) { 547 const errno_t rc = async_data_write_accept(&trans->buffer, false, 548 1, data_buffer_len, 0, &size); 549 503 if (size > 0) { 504 const unsigned required_flags = (dir == USB_DIRECTION_IN) 505 ? AS_AREA_WRITE : AS_AREA_READ; 506 507 const errno_t rc = receive_memory_buffer(trans, size, required_flags); 550 508 if (rc != EOK) { 509 async_transaction_destroy(trans); 551 510 async_answer_0(callid, rc); 552 async_transaction_destroy(trans);553 511 return; 554 512 } … … 562 520 }}; 563 521 564 const errno_t rc = usbhc_iface-> write(565 fun, target, setup, trans->buffer, size, callback_out, trans);522 const errno_t rc = usbhc_iface->transfer(fun, target, dir, setup, 523 trans->buffer, size, &transfer_finished, trans); 566 524 567 525 if (rc != EOK) { … … 570 528 } 571 529 } 530 572 531 /** 573 532 * @} -
uspace/lib/drv/include/usbhc_iface.h
r2b3dd78 r5595841 148 148 extern errno_t usbhc_unregister_endpoint(async_exch_t *, const usb_pipe_desc_t *); 149 149 150 extern errno_t usbhc_transfer(async_exch_t *, usb_endpoint_t, usb_direction_t, 151 uint64_t, void *, size_t, size_t *); 150 152 extern errno_t usbhc_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t, 151 153 size_t *); … … 166 168 int (*unregister_endpoint)(ddf_fun_t *, const usb_pipe_desc_t *); 167 169 168 errno_t (*read)(ddf_fun_t *, usb_target_t, 169 uint64_t, char *, size_t, 170 usbhc_iface_transfer_callback_t, void *); 171 errno_t (*write)(ddf_fun_t *, usb_target_t, 172 uint64_t, const char *, size_t, 170 errno_t (*transfer)(ddf_fun_t *, usb_target_t, 171 usb_direction_t, uint64_t, char *, size_t, 173 172 usbhc_iface_transfer_callback_t, void *); 174 173 } usbhc_iface_t; -
uspace/lib/usbhost/src/ddf_helpers.c
r2b3dd78 r5595841 254 254 } 255 255 256 /** Inbound communication interface function. 256 /** 257 * Transfer issuing interface function. 258 * 257 259 * @param fun DDF function. 258 260 * @param target Communication target. 261 * @param dir Communication direction. 259 262 * @param setup_data Data to use in setup stage (control transfers). 260 263 * @param data Pointer to data buffer. … … 264 267 * @return Error code. 265 268 */ 266 static errno_t dev_read(ddf_fun_t *fun, usb_target_t target,267 u int64_t setup_data, char *data, size_t size,269 static errno_t transfer(ddf_fun_t *fun, usb_target_t target, 270 usb_direction_t dir, uint64_t setup_data, char *data, size_t size, 268 271 usbhc_iface_transfer_callback_t callback, void *arg) 269 272 { … … 283 286 return EBADMEM; 284 287 285 return bus_device_send_batch(dev, target, USB_DIRECTION_IN, 286 data, size, setup_data, 287 callback, arg, "READ"); 288 } 289 290 /** Outbound communication interface function. 291 * @param fun DDF function. 292 * @param target Communication target. 293 * @param setup_data Data to use in setup stage (control transfers). 294 * @param data Pointer to data buffer. 295 * @param size Size of the data buffer. 296 * @param callback Function to call on communication end. 297 * @param arg Argument passed to the callback function. 298 * @return Error code. 299 */ 300 static errno_t dev_write(ddf_fun_t *fun, usb_target_t target, 301 uint64_t setup_data, const char *data, size_t size, 302 usbhc_iface_transfer_callback_t callback, void *arg) 303 { 304 assert(fun); 305 device_t *dev = ddf_fun_data_get(fun); 306 assert(dev); 307 308 target.address = dev->address; 309 310 if (!usb_target_is_valid(&target)) 311 return EINVAL; 312 313 if (size > 0 && data == NULL) 314 return EBADMEM; 315 316 if (!callback && arg) 317 return EBADMEM; 318 319 return bus_device_send_batch(dev, target, USB_DIRECTION_OUT, 288 const char *name = (dir == USB_DIRECTION_IN) ? "READ" : "WRITE"; 289 290 return bus_device_send_batch(dev, target, dir, 320 291 (char *) data, size, setup_data, 321 callback, arg, "WRITE");292 callback, arg, name); 322 293 } 323 294 … … 337 308 .unregister_endpoint = unregister_endpoint, 338 309 339 .read = dev_read, 340 .write = dev_write, 310 .transfer = transfer, 341 311 }; 342 312
Note:
See TracChangeset
for help on using the changeset viewer.