Changes in uspace/lib/drv/generic/remote_usbhc.c [bbce2c2:eb2f7dd] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
rbbce2c2 reb2f7dd 41 41 42 42 #define USB_MAX_PAYLOAD_SIZE 1020 43 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 *); 44 52 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 45 53 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 48 56 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 49 57 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 *);52 58 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 59 54 60 /** Remote USB host controller interface operations. */ 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, 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 66 78 }; 67 79 … … 78 90 ipc_callid_t data_caller; 79 91 void *buffer; 92 void *setup_packet; 80 93 size_t size; 81 94 } async_transaction_t; … … 85 98 if (trans == NULL) { 86 99 return; 100 } 101 102 if (trans->setup_packet != NULL) { 103 free(trans->setup_packet); 87 104 } 88 105 if (trans->buffer != NULL) { … … 103 120 trans->data_caller = 0; 104 121 trans->buffer = NULL; 122 trans->setup_packet = NULL; 105 123 trans->size = 0; 106 124 … … 117 135 return; 118 136 } 119 137 120 138 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 121 139 … … 221 239 async_transaction_destroy(trans); 222 240 } 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 223 515 224 516 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, … … 243 535 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8) 244 536 245 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 537 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1); 538 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1); 246 539 247 540 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2); … … 258 551 #undef _INIT_FROM_LOW_DATA3 259 552 260 int rc = usb_iface->register_endpoint(fun, target.address, speed,261 t arget.endpoint, transfer_type, direction, max_packet_size, interval);553 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint, 554 transfer_type, direction, max_packet_size, interval); 262 555 263 556 async_answer_0(callid, rc); 264 557 } 558 265 559 266 560 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, … … 284 578 } 285 579 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 380 580 381 581 /**
Note:
See TracChangeset
for help on using the changeset viewer.