1 /** 2 * Copyright (c) 2010-2012 Broadcom. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions, and the following disclaimer, 9 * without modification. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The names of the above-listed copyright holders may not be used 14 * to endorse or promote products derived from this software without 15 * specific prior written permission. 16 * 17 * ALTERNATIVELY, this software may be distributed under the terms of the 18 * GNU General Public License ("GPL") version 2, as published by the Free 19 * Software Foundation. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <interface/compat/vchi_bsd.h> 35 36 #include "interface/vchi/vchi.h" 37 #include "vchiq.h" 38 #include "vchiq_core.h" 39 40 #include "vchiq_util.h" 41 42 #define vchiq_status_to_vchi(status) ((int32_t)status) 43 44 typedef struct { 45 VCHIQ_SERVICE_HANDLE_T handle; 46 47 VCHIU_QUEUE_T queue; 48 49 VCHI_CALLBACK_T callback; 50 void *callback_param; 51 } SHIM_SERVICE_T; 52 53 /* ---------------------------------------------------------------------- 54 * return pointer to the mphi message driver function table 55 * -------------------------------------------------------------------- */ 56 const VCHI_MESSAGE_DRIVER_T * 57 vchi_mphi_message_driver_func_table(void) 58 { 59 return NULL; 60 } 61 62 /* ---------------------------------------------------------------------- 63 * return a pointer to the 'single' connection driver fops 64 * -------------------------------------------------------------------- */ 65 const VCHI_CONNECTION_API_T * 66 single_get_func_table(void) 67 { 68 return NULL; 69 } 70 71 VCHI_CONNECTION_T *vchi_create_connection( 72 const VCHI_CONNECTION_API_T *function_table, 73 const VCHI_MESSAGE_DRIVER_T *low_level) 74 { 75 (void)function_table; 76 (void)low_level; 77 return NULL; 78 } 79 80 /*********************************************************** 81 * Name: vchi_msg_peek 82 * 83 * Arguments: const VCHI_SERVICE_HANDLE_T handle, 84 * void **data, 85 * uint32_t *msg_size, 86 87 88 * VCHI_FLAGS_T flags 89 * 90 * Description: Routine to return a pointer to the current message (to allow in 91 * place processing). The message can be removed using 92 * vchi_msg_remove when you're finished 93 * 94 * Returns: int32_t - success == 0 95 * 96 ***********************************************************/ 97 int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle, 98 void **data, 99 uint32_t *msg_size, 100 VCHI_FLAGS_T flags) 101 { 102 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 103 VCHIQ_HEADER_T *header; 104 105 WARN_ON((flags != VCHI_FLAGS_NONE) && 106 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 107 108 if (flags == VCHI_FLAGS_NONE) 109 if (vchiu_queue_is_empty(&service->queue)) 110 return -1; 111 112 header = vchiu_queue_peek(&service->queue); 113 114 *data = header->data; 115 *msg_size = header->size; 116 117 return 0; 118 } 119 EXPORT_SYMBOL(vchi_msg_peek); 120 121 /*********************************************************** 122 * Name: vchi_msg_remove 123 * 124 * Arguments: const VCHI_SERVICE_HANDLE_T handle, 125 * 126 * Description: Routine to remove a message (after it has been read with 127 * vchi_msg_peek) 128 * 129 * Returns: int32_t - success == 0 130 * 131 ***********************************************************/ 132 int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle) 133 { 134 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 135 VCHIQ_HEADER_T *header; 136 137 header = vchiu_queue_pop(&service->queue); 138 139 vchiq_release_message(service->handle, header); 140 141 return 0; 142 } 143 EXPORT_SYMBOL(vchi_msg_remove); 144 145 /*********************************************************** 146 * Name: vchi_msg_queue 147 * 148 * Arguments: VCHI_SERVICE_HANDLE_T handle, 149 * const void *data, 150 * uint32_t data_size, 151 * VCHI_FLAGS_T flags, 152 * void *msg_handle, 153 * 154 * Description: Thin wrapper to queue a message onto a connection 155 * 156 * Returns: int32_t - success == 0 157 * 158 ***********************************************************/ 159 int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, 160 const void *data, 161 uint32_t data_size, 162 VCHI_FLAGS_T flags, 163 void *msg_handle) 164 { 165 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 166 VCHIQ_ELEMENT_T element = {data, data_size}; 167 VCHIQ_STATUS_T status; 168 169 (void)msg_handle; 170 171 WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); 172 173 status = vchiq_queue_message(service->handle, &element, 1); 174 175 /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to 176 ** implement a retry mechanism since this function is supposed 177 ** to block until queued 178 */ 179 while (status == VCHIQ_RETRY) { 180 msleep(1); 181 status = vchiq_queue_message(service->handle, &element, 1); 182 } 183 184 return vchiq_status_to_vchi(status); 185 } 186 EXPORT_SYMBOL(vchi_msg_queue); 187 188 /*********************************************************** 189 * Name: vchi_bulk_queue_receive 190 * 191 * Arguments: VCHI_BULK_HANDLE_T handle, 192 * void *data_dst, 193 * const uint32_t data_size, 194 * VCHI_FLAGS_T flags 195 * void *bulk_handle 196 * 197 * Description: Routine to setup a rcv buffer 198 * 199 * Returns: int32_t - success == 0 200 * 201 ***********************************************************/ 202 int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, 203 void *data_dst, 204 uint32_t data_size, 205 VCHI_FLAGS_T flags, 206 void *bulk_handle) 207 { 208 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 209 VCHIQ_BULK_MODE_T mode; 210 VCHIQ_STATUS_T status; 211 212 switch ((int)flags) { 213 case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE 214 | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 215 WARN_ON(!service->callback); 216 mode = VCHIQ_BULK_MODE_CALLBACK; 217 break; 218 case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: 219 mode = VCHIQ_BULK_MODE_BLOCKING; 220 break; 221 case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 222 case VCHI_FLAGS_NONE: 223 mode = VCHIQ_BULK_MODE_NOCALLBACK; 224 break; 225 default: 226 WARN(1, "unsupported message\n"); 227 return vchiq_status_to_vchi(VCHIQ_ERROR); 228 } 229 230 status = vchiq_bulk_receive(service->handle, data_dst, data_size, 231 bulk_handle, mode); 232 233 /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to 234 ** implement a retry mechanism since this function is supposed 235 ** to block until queued 236 */ 237 while (status == VCHIQ_RETRY) { 238 msleep(1); 239 status = vchiq_bulk_receive(service->handle, data_dst, 240 data_size, bulk_handle, mode); 241 } 242 243 return vchiq_status_to_vchi(status); 244 } 245 EXPORT_SYMBOL(vchi_bulk_queue_receive); 246 247 /*********************************************************** 248 * Name: vchi_bulk_queue_transmit 249 * 250 * Arguments: VCHI_BULK_HANDLE_T handle, 251 * void *data_src, 252 * uint32_t data_size, 253 * VCHI_FLAGS_T flags, 254 * void *bulk_handle 255 * 256 * Description: Routine to transmit some data 257 * 258 * Returns: int32_t - success == 0 259 * 260 ***********************************************************/ 261 int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, 262 void *data_src, 263 uint32_t data_size, 264 VCHI_FLAGS_T flags, 265 void *bulk_handle) 266 { 267 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 268 VCHIQ_BULK_MODE_T mode; 269 VCHIQ_STATUS_T status; 270 271 switch ((int)flags) { 272 case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE 273 | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 274 WARN_ON(!service->callback); 275 mode = VCHIQ_BULK_MODE_CALLBACK; 276 break; 277 case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: 278 case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: 279 mode = VCHIQ_BULK_MODE_BLOCKING; 280 break; 281 case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 282 case VCHI_FLAGS_NONE: 283 mode = VCHIQ_BULK_MODE_NOCALLBACK; 284 break; 285 default: 286 WARN(1, "unsupported message\n"); 287 return vchiq_status_to_vchi(VCHIQ_ERROR); 288 } 289 290 status = vchiq_bulk_transmit(service->handle, data_src, data_size, 291 bulk_handle, mode); 292 293 /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to 294 ** implement a retry mechanism since this function is supposed 295 ** to block until queued 296 */ 297 while (status == VCHIQ_RETRY) { 298 msleep(1); 299 status = vchiq_bulk_transmit(service->handle, data_src, 300 data_size, bulk_handle, mode); 301 } 302 303 return vchiq_status_to_vchi(status); 304 } 305 EXPORT_SYMBOL(vchi_bulk_queue_transmit); 306 307 /*********************************************************** 308 * Name: vchi_msg_dequeue 309 * 310 * Arguments: VCHI_SERVICE_HANDLE_T handle, 311 * void *data, 312 * uint32_t max_data_size_to_read, 313 * uint32_t *actual_msg_size 314 * VCHI_FLAGS_T flags 315 * 316 * Description: Routine to dequeue a message into the supplied buffer 317 * 318 * Returns: int32_t - success == 0 319 * 320 ***********************************************************/ 321 int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, 322 void *data, 323 uint32_t max_data_size_to_read, 324 uint32_t *actual_msg_size, 325 VCHI_FLAGS_T flags) 326 { 327 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 328 VCHIQ_HEADER_T *header; 329 330 WARN_ON((flags != VCHI_FLAGS_NONE) && 331 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 332 333 if (flags == VCHI_FLAGS_NONE) 334 if (vchiu_queue_is_empty(&service->queue)) 335 return -1; 336 337 header = vchiu_queue_pop(&service->queue); 338 339 memcpy(data, header->data, header->size < max_data_size_to_read ? 340 header->size : max_data_size_to_read); 341 342 *actual_msg_size = header->size; 343 344 vchiq_release_message(service->handle, header); 345 346 return 0; 347 } 348 EXPORT_SYMBOL(vchi_msg_dequeue); 349 350 /*********************************************************** 351 * Name: vchi_msg_queuev 352 * 353 * Arguments: VCHI_SERVICE_HANDLE_T handle, 354 * VCHI_MSG_VECTOR_T *vector, 355 * uint32_t count, 356 * VCHI_FLAGS_T flags, 357 * void *msg_handle 358 * 359 * Description: Thin wrapper to queue a message onto a connection 360 * 361 * Returns: int32_t - success == 0 362 * 363 ***********************************************************/ 364 365 vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T)); 366 vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == 367 offsetof(VCHIQ_ELEMENT_T, data)); 368 vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == 369 offsetof(VCHIQ_ELEMENT_T, size)); 370 371 int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle, 372 VCHI_MSG_VECTOR_T *vector, 373 uint32_t count, 374 VCHI_FLAGS_T flags, 375 void *msg_handle) 376 { 377 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 378 379 (void)msg_handle; 380 381 WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); 382 383 return vchiq_status_to_vchi(vchiq_queue_message(service->handle, 384 (const VCHIQ_ELEMENT_T *)vector, count)); 385 } 386 EXPORT_SYMBOL(vchi_msg_queuev); 387 388 /*********************************************************** 389 * Name: vchi_held_msg_release 390 * 391 * Arguments: VCHI_HELD_MSG_T *message 392 * 393 * Description: Routine to release a held message (after it has been read with 394 * vchi_msg_hold) 395 * 396 * Returns: int32_t - success == 0 397 * 398 ***********************************************************/ 399 int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) 400 { 401 vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service, 402 (VCHIQ_HEADER_T *)message->message); 403 404 return 0; 405 } 406 407 /*********************************************************** 408 * Name: vchi_msg_hold 409 * 410 * Arguments: VCHI_SERVICE_HANDLE_T handle, 411 * void **data, 412 * uint32_t *msg_size, 413 * VCHI_FLAGS_T flags, 414 * VCHI_HELD_MSG_T *message_handle 415 * 416 * Description: Routine to return a pointer to the current message (to allow 417 * in place processing). The message is dequeued - don't forget 418 * to release the message using vchi_held_msg_release when you're 419 * finished. 420 * 421 * Returns: int32_t - success == 0 422 * 423 ***********************************************************/ 424 int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, 425 void **data, 426 uint32_t *msg_size, 427 VCHI_FLAGS_T flags, 428 VCHI_HELD_MSG_T *message_handle) 429 { 430 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 431 VCHIQ_HEADER_T *header; 432 433 WARN_ON((flags != VCHI_FLAGS_NONE) && 434 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 435 436 if (flags == VCHI_FLAGS_NONE) 437 if (vchiu_queue_is_empty(&service->queue)) 438 return -1; 439 440 header = vchiu_queue_pop(&service->queue); 441 442 *data = header->data; 443 *msg_size = header->size; 444 445 message_handle->service = 446 (struct opaque_vchi_service_t *)service->handle; 447 message_handle->message = header; 448 449 return 0; 450 } 451 452 /*********************************************************** 453 * Name: vchi_initialise 454 * 455 * Arguments: VCHI_INSTANCE_T *instance_handle 456 * VCHI_CONNECTION_T **connections 457 * const uint32_t num_connections 458 * 459 * Description: Initialises the hardware but does not transmit anything 460 * When run as a Host App this will be called twice hence the need 461 * to malloc the state information 462 * 463 * Returns: 0 if successful, failure otherwise 464 * 465 ***********************************************************/ 466 467 int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle) 468 { 469 VCHIQ_INSTANCE_T instance; 470 VCHIQ_STATUS_T status; 471 472 status = vchiq_initialise(&instance); 473 474 *instance_handle = (VCHI_INSTANCE_T)instance; 475 476 return vchiq_status_to_vchi(status); 477 } 478 EXPORT_SYMBOL(vchi_initialise); 479 480 /*********************************************************** 481 * Name: vchi_connect 482 * 483 * Arguments: VCHI_CONNECTION_T **connections 484 * const uint32_t num_connections 485 * VCHI_INSTANCE_T instance_handle) 486 * 487 * Description: Starts the command service on each connection, 488 * causing INIT messages to be pinged back and forth 489 * 490 * Returns: 0 if successful, failure otherwise 491 * 492 ***********************************************************/ 493 int32_t vchi_connect(VCHI_CONNECTION_T **connections, 494 const uint32_t num_connections, 495 VCHI_INSTANCE_T instance_handle) 496 { 497 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 498 499 (void)connections; 500 (void)num_connections; 501 502 return vchiq_connect(instance); 503 } 504 EXPORT_SYMBOL(vchi_connect); 505 506 507 /*********************************************************** 508 * Name: vchi_disconnect 509 * 510 * Arguments: VCHI_INSTANCE_T instance_handle 511 * 512 * Description: Stops the command service on each connection, 513 * causing DE-INIT messages to be pinged back and forth 514 * 515 * Returns: 0 if successful, failure otherwise 516 * 517 ***********************************************************/ 518 int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle) 519 { 520 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 521 return vchiq_status_to_vchi(vchiq_shutdown(instance)); 522 } 523 EXPORT_SYMBOL(vchi_disconnect); 524 525 526 /*********************************************************** 527 * Name: vchi_service_open 528 * Name: vchi_service_create 529 * 530 * Arguments: VCHI_INSTANCE_T *instance_handle 531 * SERVICE_CREATION_T *setup, 532 * VCHI_SERVICE_HANDLE_T *handle 533 * 534 * Description: Routine to open a service 535 * 536 * Returns: int32_t - success == 0 537 * 538 ***********************************************************/ 539 540 static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, 541 VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user) 542 { 543 SHIM_SERVICE_T *service = 544 (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle); 545 546 if (!service->callback) 547 goto release; 548 549 switch (reason) { 550 case VCHIQ_MESSAGE_AVAILABLE: 551 vchiu_queue_push(&service->queue, header); 552 553 service->callback(service->callback_param, 554 VCHI_CALLBACK_MSG_AVAILABLE, NULL); 555 556 goto done; 557 break; 558 559 case VCHIQ_BULK_TRANSMIT_DONE: 560 service->callback(service->callback_param, 561 VCHI_CALLBACK_BULK_SENT, bulk_user); 562 break; 563 564 case VCHIQ_BULK_RECEIVE_DONE: 565 service->callback(service->callback_param, 566 VCHI_CALLBACK_BULK_RECEIVED, bulk_user); 567 break; 568 569 case VCHIQ_SERVICE_CLOSED: 570 service->callback(service->callback_param, 571 VCHI_CALLBACK_SERVICE_CLOSED, NULL); 572 break; 573 574 case VCHIQ_SERVICE_OPENED: 575 /* No equivalent VCHI reason */ 576 break; 577 578 case VCHIQ_BULK_TRANSMIT_ABORTED: 579 service->callback(service->callback_param, 580 VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, 581 bulk_user); 582 break; 583 584 case VCHIQ_BULK_RECEIVE_ABORTED: 585 service->callback(service->callback_param, 586 VCHI_CALLBACK_BULK_RECEIVE_ABORTED, 587 bulk_user); 588 break; 589 590 default: 591 WARN(1, "not supported\n"); 592 break; 593 } 594 595 release: 596 vchiq_release_message(service->handle, header); 597 done: 598 return VCHIQ_SUCCESS; 599 } 600 601 static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance, 602 SERVICE_CREATION_T *setup) 603 { 604 SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL); 605 606 (void)instance; 607 608 if (service) { 609 if (vchiu_queue_init(&service->queue, 64)) { 610 service->callback = setup->callback; 611 service->callback_param = setup->callback_param; 612 } else { 613 kfree(service); 614 service = NULL; 615 } 616 } 617 618 return service; 619 } 620 621 static void service_free(SHIM_SERVICE_T *service) 622 { 623 if (service) { 624 vchiu_queue_delete(&service->queue); 625 kfree(service); 626 } 627 } 628 629 int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, 630 SERVICE_CREATION_T *setup, 631 VCHI_SERVICE_HANDLE_T *handle) 632 { 633 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 634 SHIM_SERVICE_T *service = service_alloc(instance, setup); 635 636 *handle = (VCHI_SERVICE_HANDLE_T)service; 637 638 if (service) { 639 VCHIQ_SERVICE_PARAMS_T params; 640 VCHIQ_STATUS_T status; 641 642 memset(¶ms, 0, sizeof(params)); 643 params.fourcc = setup->service_id; 644 params.callback = shim_callback; 645 params.userdata = service; 646 params.version = setup->version.version; 647 params.version_min = setup->version.version_min; 648 649 status = vchiq_open_service(instance, ¶ms, 650 &service->handle); 651 if (status != VCHIQ_SUCCESS) { 652 service_free(service); 653 service = NULL; 654 *handle = NULL; 655 } 656 } 657 658 return (service != NULL) ? 0 : -1; 659 } 660 EXPORT_SYMBOL(vchi_service_open); 661 662 int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, 663 SERVICE_CREATION_T *setup, 664 VCHI_SERVICE_HANDLE_T *handle) 665 { 666 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 667 SHIM_SERVICE_T *service = service_alloc(instance, setup); 668 669 *handle = (VCHI_SERVICE_HANDLE_T)service; 670 671 if (service) { 672 VCHIQ_SERVICE_PARAMS_T params; 673 VCHIQ_STATUS_T status; 674 675 memset(¶ms, 0, sizeof(params)); 676 params.fourcc = setup->service_id; 677 params.callback = shim_callback; 678 params.userdata = service; 679 params.version = setup->version.version; 680 params.version_min = setup->version.version_min; 681 status = vchiq_add_service(instance, ¶ms, &service->handle); 682 683 if (status != VCHIQ_SUCCESS) { 684 service_free(service); 685 service = NULL; 686 *handle = NULL; 687 } 688 } 689 690 return (service != NULL) ? 0 : -1; 691 } 692 EXPORT_SYMBOL(vchi_service_create); 693 694 int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle) 695 { 696 int32_t ret = -1; 697 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 698 if (service) { 699 VCHIQ_STATUS_T status = vchiq_close_service(service->handle); 700 if (status == VCHIQ_SUCCESS) { 701 service_free(service); 702 service = NULL; 703 } 704 705 ret = vchiq_status_to_vchi(status); 706 } 707 return ret; 708 } 709 EXPORT_SYMBOL(vchi_service_close); 710 711 int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle) 712 { 713 int32_t ret = -1; 714 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 715 if (service) { 716 VCHIQ_STATUS_T status = vchiq_remove_service(service->handle); 717 if (status == VCHIQ_SUCCESS) { 718 service_free(service); 719 service = NULL; 720 } 721 722 ret = vchiq_status_to_vchi(status); 723 } 724 return ret; 725 } 726 EXPORT_SYMBOL(vchi_service_destroy); 727 728 int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version ) 729 { 730 int32_t ret = -1; 731 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 732 if(service) 733 { 734 VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version); 735 ret = vchiq_status_to_vchi( status ); 736 } 737 return ret; 738 } 739 EXPORT_SYMBOL(vchi_get_peer_version); 740 741 #ifdef notyet 742 /* ---------------------------------------------------------------------- 743 * read a uint32_t from buffer. 744 * network format is defined to be little endian 745 * -------------------------------------------------------------------- */ 746 uint32_t 747 vchi_readbuf_uint32(const void *_ptr) 748 { 749 const unsigned char *ptr = _ptr; 750 return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); 751 } 752 753 /* ---------------------------------------------------------------------- 754 * write a uint32_t to buffer. 755 * network format is defined to be little endian 756 * -------------------------------------------------------------------- */ 757 void 758 vchi_writebuf_uint32(void *_ptr, uint32_t value) 759 { 760 unsigned char *ptr = _ptr; 761 ptr[0] = (unsigned char)((value >> 0) & 0xFF); 762 ptr[1] = (unsigned char)((value >> 8) & 0xFF); 763 ptr[2] = (unsigned char)((value >> 16) & 0xFF); 764 ptr[3] = (unsigned char)((value >> 24) & 0xFF); 765 } 766 767 /* ---------------------------------------------------------------------- 768 * read a uint16_t from buffer. 769 * network format is defined to be little endian 770 * -------------------------------------------------------------------- */ 771 uint16_t 772 vchi_readbuf_uint16(const void *_ptr) 773 { 774 const unsigned char *ptr = _ptr; 775 return ptr[0] | (ptr[1] << 8); 776 } 777 778 /* ---------------------------------------------------------------------- 779 * write a uint16_t into the buffer. 780 * network format is defined to be little endian 781 * -------------------------------------------------------------------- */ 782 void 783 vchi_writebuf_uint16(void *_ptr, uint16_t value) 784 { 785 unsigned char *ptr = _ptr; 786 ptr[0] = (value >> 0) & 0xFF; 787 ptr[1] = (value >> 8) & 0xFF; 788 } 789 #endif 790 791 /*********************************************************** 792 * Name: vchi_service_use 793 * 794 * Arguments: const VCHI_SERVICE_HANDLE_T handle 795 * 796 * Description: Routine to increment refcount on a service 797 * 798 * Returns: void 799 * 800 ***********************************************************/ 801 int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle) 802 { 803 int32_t ret = -1; 804 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 805 if (service) 806 ret = vchiq_status_to_vchi(vchiq_use_service(service->handle)); 807 return ret; 808 } 809 EXPORT_SYMBOL(vchi_service_use); 810 811 /*********************************************************** 812 * Name: vchi_service_release 813 * 814 * Arguments: const VCHI_SERVICE_HANDLE_T handle 815 * 816 * Description: Routine to decrement refcount on a service 817 * 818 * Returns: void 819 * 820 ***********************************************************/ 821 int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle) 822 { 823 int32_t ret = -1; 824 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 825 if (service) 826 ret = vchiq_status_to_vchi( 827 vchiq_release_service(service->handle)); 828 return ret; 829 } 830 EXPORT_SYMBOL(vchi_service_release); 831