Changeset 07b39338 in mainline for uspace/srv/devman/main.c
- Timestamp:
- 2011-08-20T18:21:49Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6ab014d
- Parents:
- 0cf27ee (diff), f00af83 (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/srv/devman/main.c
r0cf27ee r07b39338 64 64 static driver_list_t drivers_list; 65 65 static dev_tree_t device_tree; 66 static class_list_t class_list;67 66 68 67 /** Register running driver. */ … … 279 278 return; 280 279 } 281 280 282 281 fun_node_t *fun = create_fun_node(); 282 fun->ftype = ftype; 283 283 284 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 284 285 fibril_rwlock_write_unlock(&tree->rwlock); … … 333 334 } 334 335 335 static void loc_register_class_dev(dev_class_info_t *cli) 336 { 337 /* Create loc path and name for the service. */ 338 char *loc_pathname = NULL; 339 340 asprintf(&loc_pathname, "%s/%s%c%s", LOC_CLASS_NAMESPACE, 341 cli->dev_class->name, LOC_SEPARATOR, cli->dev_name); 342 if (loc_pathname == NULL) 343 return; 344 345 /* 346 * Register the device with location service and remember its 347 * service ID. 348 */ 349 loc_service_register_with_iface(loc_pathname, 350 &cli->service_id, DEVMAN_CONNECT_FROM_LOC); 351 352 /* 353 * Add device to the hash map of class devices registered with 354 * location service. 355 */ 356 class_add_loc_function(&class_list, cli); 357 358 free(loc_pathname); 359 } 360 361 static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call) 336 static void devman_add_function_to_cat(ipc_callid_t callid, ipc_call_t *call) 362 337 { 363 338 devman_handle_t handle = IPC_GET_ARG1(*call); … … 365 340 int rc; 366 341 367 /* Get c lassname. */368 char *c lass_name;369 rc = async_data_write_accept((void **) &c lass_name, true,342 /* Get category name. */ 343 char *cat_name; 344 rc = async_data_write_accept((void **) &cat_name, true, 370 345 0, 0, 0, 0); 371 346 if (rc != EOK) { … … 380 355 } 381 356 382 dev_class_t *cl = get_dev_class(&class_list, class_name); 383 dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL); 384 385 /* Register the device's class alias with location service. */ 386 loc_register_class_dev(class_info); 387 388 rc = loc_category_get_id(class_name, &cat_id, IPC_FLAG_BLOCKING); 357 rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING); 389 358 if (rc == EOK) { 390 359 loc_service_add_to_cat(fun->service_id, cat_id); 391 360 } else { 392 361 log_msg(LVL_ERROR, "Failed adding function `%s' to category " 393 "`%s'.", fun->pathname, class_name); 394 } 395 396 log_msg(LVL_NOTE, "Function `%s' added to class `%s' as `%s'.", 397 fun->pathname, class_name, class_info->dev_name); 398 362 "`%s'.", fun->pathname, cat_name); 363 } 364 365 log_msg(LVL_NOTE, "Function `%s' added to category `%s'.", 366 fun->pathname, cat_name); 367 368 async_answer_0(callid, EOK); 369 } 370 371 /** Remove function. */ 372 static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call) 373 { 374 devman_handle_t fun_handle = IPC_GET_ARG1(*call); 375 dev_tree_t *tree = &device_tree; 376 int rc; 377 378 fibril_rwlock_write_lock(&tree->rwlock); 379 380 fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle); 381 if (fun == NULL) { 382 fibril_rwlock_write_unlock(&tree->rwlock); 383 async_answer_0(callid, ENOENT); 384 return; 385 } 386 387 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname); 388 389 if (fun->ftype == fun_inner) { 390 /* Handle possible descendants */ 391 /* TODO */ 392 log_msg(LVL_WARN, "devman_remove_function(): not handling " 393 "descendants\n"); 394 } else { 395 /* Unregister from location service */ 396 rc = loc_service_unregister(fun->service_id); 397 if (rc != EOK) { 398 log_msg(LVL_ERROR, "Failed unregistering tree service."); 399 fibril_rwlock_write_unlock(&tree->rwlock); 400 async_answer_0(callid, EIO); 401 return; 402 } 403 } 404 405 remove_fun_node(&device_tree, fun); 406 fibril_rwlock_write_unlock(&tree->rwlock); 407 delete_fun_node(fun); 408 409 log_msg(LVL_DEBUG, "devman_remove_function() succeeded."); 399 410 async_answer_0(callid, EOK); 400 411 } … … 449 460 devman_add_function(callid, &call); 450 461 break; 451 case DEVMAN_ADD_DEVICE_TO_CLASS: 452 devman_add_function_to_class(callid, &call); 462 case DEVMAN_ADD_DEVICE_TO_CATEGORY: 463 devman_add_function_to_cat(callid, &call); 464 break; 465 case DEVMAN_REMOVE_FUNCTION: 466 devman_remove_function(callid, &call); 453 467 break; 454 468 default: … … 483 497 } 484 498 485 /** Find handle for the device instance identified by device class name. */ 486 static void devman_function_get_handle_by_class(ipc_callid_t iid, 487 ipc_call_t *icall) 488 { 489 char *classname; 490 char *devname; 491 492 int rc = async_data_write_accept((void **) &classname, true, 0, 0, 0, 0); 493 if (rc != EOK) { 494 async_answer_0(iid, rc); 495 return; 496 } 497 rc = async_data_write_accept((void **) &devname, true, 0, 0, 0, 0); 498 if (rc != EOK) { 499 free(classname); 500 async_answer_0(iid, rc); 501 return; 502 } 503 504 505 fun_node_t *fun = find_fun_node_by_class(&class_list, 506 classname, devname); 507 508 free(classname); 509 free(devname); 510 511 if (fun == NULL) { 512 async_answer_0(iid, ENOENT); 513 return; 514 } 515 516 async_answer_1(iid, EOK, fun->handle); 517 } 518 519 /** Find device path by its handle. */ 520 static void devman_get_device_path_by_handle(ipc_callid_t iid, 521 ipc_call_t *icall) 499 /** Get device name. */ 500 static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall) 522 501 { 523 502 devman_handle_t handle = IPC_GET_ARG1(*icall); … … 543 522 } 544 523 524 size_t sent_length = str_size(fun->name); 525 if (sent_length > data_len) { 526 sent_length = data_len; 527 } 528 529 async_data_read_finalize(data_callid, fun->name, sent_length); 530 async_answer_0(iid, EOK); 531 532 free(buffer); 533 } 534 535 536 /** Get device path. */ 537 static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall) 538 { 539 devman_handle_t handle = IPC_GET_ARG1(*icall); 540 541 fun_node_t *fun = find_fun_node(&device_tree, handle); 542 if (fun == NULL) { 543 async_answer_0(iid, ENOMEM); 544 return; 545 } 546 547 ipc_callid_t data_callid; 548 size_t data_len; 549 if (!async_data_read_receive(&data_callid, &data_len)) { 550 async_answer_0(iid, EINVAL); 551 return; 552 } 553 554 void *buffer = malloc(data_len); 555 if (buffer == NULL) { 556 async_answer_0(data_callid, ENOMEM); 557 async_answer_0(iid, ENOMEM); 558 return; 559 } 560 545 561 size_t sent_length = str_size(fun->pathname); 546 562 if (sent_length > data_len) { … … 554 570 } 555 571 572 static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall) 573 { 574 ipc_callid_t callid; 575 size_t size; 576 size_t act_size; 577 int rc; 578 579 if (!async_data_read_receive(&callid, &size)) { 580 async_answer_0(callid, EREFUSED); 581 async_answer_0(iid, EREFUSED); 582 return; 583 } 584 585 fibril_rwlock_read_lock(&device_tree.rwlock); 586 587 dev_node_t *dev = find_dev_node_no_lock(&device_tree, 588 IPC_GET_ARG1(*icall)); 589 if (dev == NULL) { 590 fibril_rwlock_read_unlock(&device_tree.rwlock); 591 async_answer_0(callid, ENOENT); 592 async_answer_0(iid, ENOENT); 593 return; 594 } 595 596 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size); 597 if (hdl_buf == NULL) { 598 fibril_rwlock_read_unlock(&device_tree.rwlock); 599 async_answer_0(callid, ENOMEM); 600 async_answer_0(iid, ENOMEM); 601 return; 602 } 603 604 rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size); 605 if (rc != EOK) { 606 fibril_rwlock_read_unlock(&device_tree.rwlock); 607 async_answer_0(callid, rc); 608 async_answer_0(iid, rc); 609 return; 610 } 611 612 fibril_rwlock_read_unlock(&device_tree.rwlock); 613 614 sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size); 615 free(hdl_buf); 616 617 async_answer_1(iid, retval, act_size); 618 } 619 620 621 /** Get handle for child device of a function. */ 622 static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall) 623 { 624 fun_node_t *fun; 625 626 fibril_rwlock_read_lock(&device_tree.rwlock); 627 628 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 629 if (fun == NULL) { 630 fibril_rwlock_read_unlock(&device_tree.rwlock); 631 async_answer_0(iid, ENOENT); 632 return; 633 } 634 635 if (fun->child == NULL) { 636 fibril_rwlock_read_unlock(&device_tree.rwlock); 637 async_answer_0(iid, ENOENT); 638 return; 639 } 640 641 async_answer_1(iid, EOK, fun->child->handle); 642 643 fibril_rwlock_read_unlock(&device_tree.rwlock); 644 } 645 646 /** Find handle for the function instance identified by its service ID. */ 647 static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall) 648 { 649 fun_node_t *fun; 650 651 fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall)); 652 653 if (fun == NULL) { 654 async_answer_0(iid, ENOENT); 655 return; 656 } 657 658 async_answer_1(iid, EOK, fun->handle); 659 } 556 660 557 661 /** Function for handling connections from a client to the device manager. */ … … 572 676 devman_function_get_handle(callid, &call); 573 677 break; 574 case DEVMAN_DEVICE_GET_HANDLE_BY_CLASS: 575 devman_function_get_handle_by_class(callid, &call); 576 break; 577 case DEVMAN_DEVICE_GET_DEVICE_PATH: 578 devman_get_device_path_by_handle(callid, &call); 678 case DEVMAN_DEV_GET_FUNCTIONS: 679 devman_dev_get_functions(callid, &call); 680 break; 681 case DEVMAN_FUN_GET_CHILD: 682 devman_fun_get_child(callid, &call); 683 break; 684 case DEVMAN_FUN_GET_NAME: 685 devman_fun_get_name(callid, &call); 686 break; 687 case DEVMAN_FUN_GET_PATH: 688 devman_fun_get_path(callid, &call); 689 break; 690 case DEVMAN_FUN_SID_TO_HANDLE: 691 devman_fun_sid_to_handle(callid, &call); 579 692 break; 580 693 default: … … 678 791 679 792 fun = find_loc_tree_function(&device_tree, service_id); 680 if (fun == NULL)681 fun = find_loc_class_function(&class_list, service_id);682 793 683 794 if (fun == NULL || fun->dev->drv == NULL) { 795 log_msg(LVL_WARN, "devman_connection_loc(): function " 796 "not found.\n"); 684 797 async_answer_0(iid, ENOENT); 685 798 return; … … 687 800 688 801 dev = fun->dev; 689 690 if ((dev->state != DEVICE_USABLE) || (!dev->drv->sess)) {691 async_answer_0(iid, EINVAL);692 return;693 }694 802 695 803 async_exch_t *exch = async_exchange_begin(dev->drv->sess); … … 753 861 } 754 862 755 init_class_list(&class_list);756 757 863 /* 758 864 * !!! devman_connection ... as the device manager is not a real loc
Note:
See TracChangeset
for help on using the changeset viewer.