Changeset fd07e526 in mainline for uspace/lib/drv/generic/remote_usbhc.c
- Timestamp:
- 2011-09-16T14:50:20Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 432a269, d1e18573
- Parents:
- 47fecbb (diff), 82a31261 (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/drv/generic/remote_usbhc.c
r47fecbb rfd07e526 41 41 42 42 #define USB_MAX_PAYLOAD_SIZE 1020 43 #define HACK_MAX_PACKET_SIZE 8 44 #define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4 45 46 static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 47 static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 48 static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 49 static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 43 52 44 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 45 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 56 48 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 49 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 58 52 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 59 53 60 54 /** Remote USB host controller interface operations. */ 61 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 62 remote_usbhc_request_address, 63 remote_usbhc_bind_address, 64 remote_usbhc_find_by_address, 65 remote_usbhc_release_address, 66 67 remote_usbhc_interrupt_out, 68 remote_usbhc_interrupt_in, 69 70 remote_usbhc_bulk_out, 71 remote_usbhc_bulk_in, 72 73 remote_usbhc_control_write, 74 remote_usbhc_control_read, 75 76 remote_usbhc_register_endpoint, 77 remote_usbhc_unregister_endpoint 55 static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = { 56 [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address, 57 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 58 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address, 59 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 60 61 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 62 [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 63 64 [IPC_M_USBHC_READ] = remote_usbhc_read, 65 [IPC_M_USBHC_WRITE] = remote_usbhc_write, 78 66 }; 79 67 … … 90 78 ipc_callid_t data_caller; 91 79 void *buffer; 92 void *setup_packet;93 80 size_t size; 94 81 } async_transaction_t; … … 98 85 if (trans == NULL) { 99 86 return; 100 }101 102 if (trans->setup_packet != NULL) {103 free(trans->setup_packet);104 87 } 105 88 if (trans->buffer != NULL) { … … 120 103 trans->data_caller = 0; 121 104 trans->buffer = NULL; 122 trans->setup_packet = NULL;123 105 trans->size = 0; 124 106 … … 135 117 return; 136 118 } 137 119 138 120 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 139 121 … … 239 221 async_transaction_destroy(trans); 240 222 } 241 242 /** Process an outgoing transfer (both OUT and SETUP).243 *244 * @param device Target device.245 * @param callid Initiating caller.246 * @param call Initiating call.247 * @param transfer_func Transfer function (might be NULL).248 */249 static void remote_usbhc_out_transfer(ddf_fun_t *fun,250 ipc_callid_t callid, ipc_call_t *call,251 usbhc_iface_transfer_out_t transfer_func)252 {253 if (!transfer_func) {254 async_answer_0(callid, ENOTSUP);255 return;256 }257 258 usb_target_t target = {259 .address = DEV_IPC_GET_ARG1(*call),260 .endpoint = DEV_IPC_GET_ARG2(*call)261 };262 263 size_t len = 0;264 void *buffer = NULL;265 266 int rc = async_data_write_accept(&buffer, false,267 1, USB_MAX_PAYLOAD_SIZE,268 0, &len);269 270 if (rc != EOK) {271 async_answer_0(callid, rc);272 return;273 }274 275 async_transaction_t *trans = async_transaction_create(callid);276 if (trans == NULL) {277 if (buffer != NULL) {278 free(buffer);279 }280 async_answer_0(callid, ENOMEM);281 return;282 }283 284 trans->buffer = buffer;285 trans->size = len;286 287 rc = transfer_func(fun, target,288 buffer, len,289 callback_out, trans);290 291 if (rc != EOK) {292 async_answer_0(callid, rc);293 async_transaction_destroy(trans);294 }295 }296 297 /** Process an incoming transfer.298 *299 * @param device Target device.300 * @param callid Initiating caller.301 * @param call Initiating call.302 * @param transfer_func Transfer function (might be NULL).303 */304 static void remote_usbhc_in_transfer(ddf_fun_t *fun,305 ipc_callid_t callid, ipc_call_t *call,306 usbhc_iface_transfer_in_t transfer_func)307 {308 if (!transfer_func) {309 async_answer_0(callid, ENOTSUP);310 return;311 }312 313 usb_target_t target = {314 .address = DEV_IPC_GET_ARG1(*call),315 .endpoint = DEV_IPC_GET_ARG2(*call)316 };317 318 size_t len;319 ipc_callid_t data_callid;320 if (!async_data_read_receive(&data_callid, &len)) {321 async_answer_0(callid, EPARTY);322 return;323 }324 325 async_transaction_t *trans = async_transaction_create(callid);326 if (trans == NULL) {327 async_answer_0(data_callid, ENOMEM);328 async_answer_0(callid, ENOMEM);329 return;330 }331 trans->data_caller = data_callid;332 trans->buffer = malloc(len);333 trans->size = len;334 335 int rc = transfer_func(fun, target,336 trans->buffer, len,337 callback_in, trans);338 339 if (rc != EOK) {340 async_answer_0(data_callid, rc);341 async_answer_0(callid, rc);342 async_transaction_destroy(trans);343 }344 }345 346 void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,347 ipc_callid_t callid, ipc_call_t *call)348 {349 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;350 assert(usb_iface != NULL);351 352 return remote_usbhc_out_transfer(fun, callid, call,353 usb_iface->interrupt_out);354 }355 356 void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,357 ipc_callid_t callid, ipc_call_t *call)358 {359 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;360 assert(usb_iface != NULL);361 362 return remote_usbhc_in_transfer(fun, callid, call,363 usb_iface->interrupt_in);364 }365 366 void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,367 ipc_callid_t callid, ipc_call_t *call)368 {369 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;370 assert(usb_iface != NULL);371 372 return remote_usbhc_out_transfer(fun, callid, call,373 usb_iface->bulk_out);374 }375 376 void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,377 ipc_callid_t callid, ipc_call_t *call)378 {379 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;380 assert(usb_iface != NULL);381 382 return remote_usbhc_in_transfer(fun, callid, call,383 usb_iface->bulk_in);384 }385 386 void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,387 ipc_callid_t callid, ipc_call_t *call)388 {389 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;390 assert(usb_iface != NULL);391 392 if (!usb_iface->control_write) {393 async_answer_0(callid, ENOTSUP);394 return;395 }396 397 usb_target_t target = {398 .address = DEV_IPC_GET_ARG1(*call),399 .endpoint = DEV_IPC_GET_ARG2(*call)400 };401 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);402 403 int rc;404 405 void *setup_packet = NULL;406 void *data_buffer = NULL;407 size_t setup_packet_len = 0;408 409 rc = async_data_write_accept(&setup_packet, false,410 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);411 if (rc != EOK) {412 async_answer_0(callid, rc);413 return;414 }415 416 if (data_buffer_len > 0) {417 rc = async_data_write_accept(&data_buffer, false,418 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);419 if (rc != EOK) {420 async_answer_0(callid, rc);421 free(setup_packet);422 return;423 }424 }425 426 async_transaction_t *trans = async_transaction_create(callid);427 if (trans == NULL) {428 async_answer_0(callid, ENOMEM);429 free(setup_packet);430 free(data_buffer);431 return;432 }433 trans->setup_packet = setup_packet;434 trans->buffer = data_buffer;435 trans->size = data_buffer_len;436 437 rc = usb_iface->control_write(fun, target,438 setup_packet, setup_packet_len,439 data_buffer, data_buffer_len,440 callback_out, trans);441 442 if (rc != EOK) {443 async_answer_0(callid, rc);444 async_transaction_destroy(trans);445 }446 }447 448 449 void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,450 ipc_callid_t callid, ipc_call_t *call)451 {452 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;453 assert(usb_iface != NULL);454 455 if (!usb_iface->control_read) {456 async_answer_0(callid, ENOTSUP);457 return;458 }459 460 usb_target_t target = {461 .address = DEV_IPC_GET_ARG1(*call),462 .endpoint = DEV_IPC_GET_ARG2(*call)463 };464 465 int rc;466 467 void *setup_packet = NULL;468 size_t setup_packet_len = 0;469 size_t data_len = 0;470 471 rc = async_data_write_accept(&setup_packet, false,472 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);473 if (rc != EOK) {474 async_answer_0(callid, rc);475 return;476 }477 478 ipc_callid_t data_callid;479 if (!async_data_read_receive(&data_callid, &data_len)) {480 async_answer_0(callid, EPARTY);481 free(setup_packet);482 return;483 }484 485 async_transaction_t *trans = async_transaction_create(callid);486 if (trans == NULL) {487 async_answer_0(data_callid, ENOMEM);488 async_answer_0(callid, ENOMEM);489 free(setup_packet);490 return;491 }492 trans->data_caller = data_callid;493 trans->setup_packet = setup_packet;494 trans->size = data_len;495 trans->buffer = malloc(data_len);496 if (trans->buffer == NULL) {497 async_answer_0(data_callid, ENOMEM);498 async_answer_0(callid, ENOMEM);499 async_transaction_destroy(trans);500 return;501 }502 503 rc = usb_iface->control_read(fun, target,504 setup_packet, setup_packet_len,505 trans->buffer, trans->size,506 callback_in, trans);507 508 if (rc != EOK) {509 async_answer_0(data_callid, rc);510 async_answer_0(callid, rc);511 async_transaction_destroy(trans);512 }513 }514 515 223 516 224 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, … … 535 243 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8) 536 244 537 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1); 538 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1); 245 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 539 246 540 247 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2); … … 551 258 #undef _INIT_FROM_LOW_DATA3 552 259 553 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,554 t ransfer_type, direction, max_packet_size, interval);260 int rc = usb_iface->register_endpoint(fun, target.address, speed, 261 target.endpoint, transfer_type, direction, max_packet_size, interval); 555 262 556 263 async_answer_0(callid, rc); 557 264 } 558 559 265 560 266 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, … … 578 284 } 579 285 286 void remote_usbhc_read( 287 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 288 { 289 assert(fun); 290 assert(iface); 291 assert(call); 292 293 const usbhc_iface_t *hc_iface = iface; 294 295 if (!hc_iface->read) { 296 async_answer_0(callid, ENOTSUP); 297 return; 298 } 299 300 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 301 const uint64_t setup = 302 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 303 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 304 305 async_transaction_t *trans = async_transaction_create(callid); 306 if (trans == NULL) { 307 async_answer_0(callid, ENOMEM); 308 return; 309 } 310 311 if (!async_data_read_receive(&trans->data_caller, &trans->size)) { 312 async_answer_0(callid, EPARTY); 313 return; 314 } 315 316 trans->buffer = malloc(trans->size); 317 if (trans->buffer == NULL) { 318 async_answer_0(trans->data_caller, ENOMEM); 319 async_answer_0(callid, ENOMEM); 320 async_transaction_destroy(trans); 321 } 322 323 const int rc = hc_iface->read( 324 fun, target, setup, trans->buffer, trans->size, callback_in, trans); 325 326 if (rc != EOK) { 327 async_answer_0(trans->data_caller, rc); 328 async_answer_0(callid, rc); 329 async_transaction_destroy(trans); 330 } 331 } 332 333 void remote_usbhc_write( 334 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 335 { 336 assert(fun); 337 assert(iface); 338 assert(call); 339 340 const usbhc_iface_t *hc_iface = iface; 341 342 if (!hc_iface->write) { 343 async_answer_0(callid, ENOTSUP); 344 return; 345 } 346 347 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 348 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 349 const uint64_t setup = 350 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 351 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 352 353 async_transaction_t *trans = async_transaction_create(callid); 354 if (trans == NULL) { 355 async_answer_0(callid, ENOMEM); 356 return; 357 } 358 359 if (data_buffer_len > 0) { 360 int rc = async_data_write_accept(&trans->buffer, false, 361 1, USB_MAX_PAYLOAD_SIZE, 362 0, &trans->size); 363 364 if (rc != EOK) { 365 async_answer_0(callid, rc); 366 async_transaction_destroy(trans); 367 return; 368 } 369 } 370 371 int rc = hc_iface->write( 372 fun, target, setup, trans->buffer, trans->size, callback_out, trans); 373 374 if (rc != EOK) { 375 async_answer_0(callid, rc); 376 async_transaction_destroy(trans); 377 } 378 } 379 580 380 581 381 /**
Note:
See TracChangeset
for help on using the changeset viewer.