1 /* 2 * Copyright 2009, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #include "RemoteHWInterface.h" 10 #include "RemoteDrawingEngine.h" 11 #include "RemoteEventStream.h" 12 #include "RemoteMessage.h" 13 14 #include "NetReceiver.h" 15 #include "NetSender.h" 16 #include "StreamingRingBuffer.h" 17 18 #include "SystemPalette.h" 19 20 #include <Autolock.h> 21 #include <NetEndpoint.h> 22 23 #include <new> 24 #include <string.h> 25 26 27 #define TRACE(x...) /*debug_printf("RemoteHWInterface: " x)*/ 28 #define TRACE_ALWAYS(x...) debug_printf("RemoteHWInterface: " x) 29 #define TRACE_ERROR(x...) debug_printf("RemoteHWInterface: " x) 30 31 32 struct callback_info { 33 uint32 token; 34 RemoteHWInterface::CallbackFunction callback; 35 void* cookie; 36 }; 37 38 39 RemoteHWInterface::RemoteHWInterface(const char* target) 40 : 41 HWInterface(), 42 fTarget(target), 43 fIsConnected(false), 44 fProtocolVersion(100), 45 fConnectionSpeed(0), 46 fListenPort(10901), 47 fListenEndpoint(NULL), 48 fSendBuffer(NULL), 49 fReceiveBuffer(NULL), 50 fSender(NULL), 51 fReceiver(NULL), 52 fEventThread(-1), 53 fEventStream(NULL), 54 fCallbackLocker("callback locker") 55 { 56 memset(&fFallbackMode, 0, sizeof(fFallbackMode)); 57 fFallbackMode.virtual_width = 640; 58 fFallbackMode.virtual_height = 480; 59 fFallbackMode.space = B_RGB32; 60 _FillDisplayModeTiming(fFallbackMode); 61 62 fCurrentMode = fClientMode = fFallbackMode; 63 64 if (sscanf(fTarget, "%" B_SCNu16, &fListenPort) != 1) { 65 fInitStatus = B_BAD_VALUE; 66 return; 67 } 68 69 fListenEndpoint = new(std::nothrow) BNetEndpoint(); 70 if (fListenEndpoint == NULL) { 71 fInitStatus = B_NO_MEMORY; 72 return; 73 } 74 75 fInitStatus = fListenEndpoint->Bind(fListenPort); 76 if (fInitStatus != B_OK) 77 return; 78 79 fSendBuffer = new(std::nothrow) StreamingRingBuffer(16 * 1024); 80 if (fSendBuffer == NULL) { 81 fInitStatus = B_NO_MEMORY; 82 return; 83 } 84 85 fInitStatus = fSendBuffer->InitCheck(); 86 if (fInitStatus != B_OK) 87 return; 88 89 fReceiveBuffer = new(std::nothrow) StreamingRingBuffer(16 * 1024); 90 if (fReceiveBuffer == NULL) { 91 fInitStatus = B_NO_MEMORY; 92 return; 93 } 94 95 fInitStatus = fReceiveBuffer->InitCheck(); 96 if (fInitStatus != B_OK) 97 return; 98 99 fReceiver = new(std::nothrow) NetReceiver(fListenEndpoint, fReceiveBuffer, 100 _NewConnectionCallback, this); 101 if (fReceiver == NULL) { 102 fInitStatus = B_NO_MEMORY; 103 return; 104 } 105 106 fEventStream = new(std::nothrow) RemoteEventStream(); 107 if (fEventStream == NULL) { 108 fInitStatus = B_NO_MEMORY; 109 return; 110 } 111 112 fEventThread = spawn_thread(_EventThreadEntry, "remote event thread", 113 B_NORMAL_PRIORITY, this); 114 if (fEventThread < 0) { 115 fInitStatus = fEventThread; 116 return; 117 } 118 119 resume_thread(fEventThread); 120 } 121 122 123 RemoteHWInterface::~RemoteHWInterface() 124 { 125 delete fReceiver; 126 delete fReceiveBuffer; 127 128 delete fSendBuffer; 129 delete fSender; 130 131 delete fListenEndpoint; 132 133 delete fEventStream; 134 } 135 136 137 status_t 138 RemoteHWInterface::Initialize() 139 { 140 return fInitStatus; 141 } 142 143 144 status_t 145 RemoteHWInterface::Shutdown() 146 { 147 _Disconnect(); 148 return B_OK; 149 } 150 151 152 DrawingEngine* 153 RemoteHWInterface::CreateDrawingEngine() 154 { 155 return new(std::nothrow) RemoteDrawingEngine(this); 156 } 157 158 159 EventStream* 160 RemoteHWInterface::CreateEventStream() 161 { 162 return fEventStream; 163 } 164 165 166 status_t 167 RemoteHWInterface::AddCallback(uint32 token, CallbackFunction callback, 168 void* cookie) 169 { 170 BAutolock lock(fCallbackLocker); 171 int32 index = fCallbacks.BinarySearchIndexByKey(token, &_CallbackCompare); 172 if (index >= 0) 173 return B_NAME_IN_USE; 174 175 callback_info* info = new(std::nothrow) callback_info; 176 if (info == NULL) 177 return B_NO_MEMORY; 178 179 info->token = token; 180 info->callback = callback; 181 info->cookie = cookie; 182 183 fCallbacks.AddItem(info, -index - 1); 184 return B_OK; 185 } 186 187 188 bool 189 RemoteHWInterface::RemoveCallback(uint32 token) 190 { 191 BAutolock lock(fCallbackLocker); 192 int32 index = fCallbacks.BinarySearchIndexByKey(token, &_CallbackCompare); 193 if (index < 0) 194 return false; 195 196 delete fCallbacks.RemoveItemAt(index); 197 return true; 198 } 199 200 201 callback_info* 202 RemoteHWInterface::_FindCallback(uint32 token) 203 { 204 BAutolock lock(fCallbackLocker); 205 return fCallbacks.BinarySearchByKey(token, &_CallbackCompare); 206 } 207 208 209 int 210 RemoteHWInterface::_CallbackCompare(const uint32* key, 211 const callback_info* info) 212 { 213 if (info->token == *key) 214 return 0; 215 216 if (info->token < *key) 217 return -1; 218 219 return 1; 220 } 221 222 223 int32 224 RemoteHWInterface::_EventThreadEntry(void* data) 225 { 226 return ((RemoteHWInterface*)data)->_EventThread(); 227 } 228 229 230 status_t 231 RemoteHWInterface::_EventThread() 232 { 233 RemoteMessage message(fReceiveBuffer, NULL); 234 while (true) { 235 uint16 code; 236 status_t result = message.NextMessage(code); 237 if (result != B_OK) { 238 TRACE_ERROR("failed to read message from receiver: %s\n", 239 strerror(result)); 240 return result; 241 } 242 243 TRACE("got message code %" B_PRIu16 " with %" B_PRIu32 " bytes\n", code, 244 message.DataLeft()); 245 246 if (code >= RP_MOUSE_MOVED && code <= RP_MODIFIERS_CHANGED) { 247 // an input event, dispatch to the event stream 248 if (fEventStream->EventReceived(message)) 249 continue; 250 } 251 252 switch (code) { 253 case RP_INIT_CONNECTION: 254 { 255 RemoteMessage reply(NULL, fSendBuffer); 256 reply.Start(RP_INIT_CONNECTION); 257 status_t result = reply.Flush(); 258 (void)result; 259 TRACE("init connection result: %s\n", strerror(result)); 260 break; 261 } 262 263 case RP_UPDATE_DISPLAY_MODE: 264 { 265 int32 width, height; 266 message.Read(width); 267 result = message.Read(height); 268 if (result != B_OK) { 269 TRACE_ERROR("failed to read display mode\n"); 270 break; 271 } 272 273 fIsConnected = true; 274 fClientMode.virtual_width = width; 275 fClientMode.virtual_height = height; 276 _FillDisplayModeTiming(fClientMode); 277 _NotifyScreenChanged(); 278 break; 279 } 280 281 case RP_GET_SYSTEM_PALETTE: 282 { 283 RemoteMessage reply(NULL, fSendBuffer); 284 reply.Start(RP_GET_SYSTEM_PALETTE_RESULT); 285 286 const color_map *map = SystemColorMap(); 287 uint32 count = (uint32)B_COUNT_OF(map->color_list); 288 289 reply.Add(count); 290 for (size_t i = 0; i < count; i++) { 291 const rgb_color &color = map->color_list[i]; 292 reply.Add(color.red); 293 reply.Add(color.green); 294 reply.Add(color.blue); 295 reply.Add(color.alpha); 296 } 297 298 break; 299 } 300 301 default: 302 { 303 uint32 token; 304 if (message.Read(token) == B_OK) { 305 callback_info* info = _FindCallback(token); 306 if (info != NULL && info->callback(info->cookie, message)) 307 break; 308 } 309 310 TRACE_ERROR("unhandled remote event code %u\n", code); 311 break; 312 } 313 } 314 } 315 } 316 317 318 status_t 319 RemoteHWInterface::_NewConnectionCallback(void *cookie, BNetEndpoint &endpoint) 320 { 321 return ((RemoteHWInterface *)cookie)->_NewConnection(endpoint); 322 } 323 324 325 status_t 326 RemoteHWInterface::_NewConnection(BNetEndpoint &endpoint) 327 { 328 if (fSender != NULL) { 329 delete fSender; 330 fSender = NULL; 331 } 332 333 fSendBuffer->MakeEmpty(); 334 335 BNetEndpoint *sendEndpoint = new(std::nothrow) BNetEndpoint(endpoint); 336 if (sendEndpoint == NULL) 337 return B_NO_MEMORY; 338 339 fSender = new(std::nothrow) NetSender(sendEndpoint, fSendBuffer); 340 if (fSender == NULL) { 341 delete sendEndpoint; 342 return B_NO_MEMORY; 343 } 344 345 return B_OK; 346 } 347 348 349 void 350 RemoteHWInterface::_Disconnect() 351 { 352 if (fIsConnected) { 353 RemoteMessage message(NULL, fSendBuffer); 354 message.Start(RP_CLOSE_CONNECTION); 355 message.Flush(); 356 fIsConnected = false; 357 } 358 359 if (fListenEndpoint != NULL) 360 fListenEndpoint->Close(); 361 } 362 363 364 status_t 365 RemoteHWInterface::SetMode(const display_mode& mode) 366 { 367 TRACE("set mode: %" B_PRIu16 " %" B_PRIu16 "\n", mode.virtual_width, 368 mode.virtual_height); 369 fCurrentMode = mode; 370 return B_OK; 371 } 372 373 374 void 375 RemoteHWInterface::GetMode(display_mode* mode) 376 { 377 if (mode == NULL || !ReadLock()) 378 return; 379 380 *mode = fCurrentMode; 381 ReadUnlock(); 382 383 TRACE("get mode: %" B_PRIu16 " %" B_PRIu16 "\n", mode->virtual_width, 384 mode->virtual_height); 385 } 386 387 388 status_t 389 RemoteHWInterface::GetPreferredMode(display_mode* mode) 390 { 391 *mode = fClientMode; 392 return B_OK; 393 } 394 395 396 status_t 397 RemoteHWInterface::GetDeviceInfo(accelerant_device_info* info) 398 { 399 if (!ReadLock()) 400 return B_ERROR; 401 402 info->version = fProtocolVersion; 403 info->dac_speed = fConnectionSpeed; 404 info->memory = 33554432; // 32MB 405 snprintf(info->name, sizeof(info->name), "Haiku, Inc. RemoteHWInterface"); 406 snprintf(info->chipset, sizeof(info->chipset), "Haiku, Inc. Chipset"); 407 snprintf(info->serial_no, sizeof(info->serial_no), fTarget); 408 409 ReadUnlock(); 410 return B_OK; 411 } 412 413 414 status_t 415 RemoteHWInterface::GetFrameBufferConfig(frame_buffer_config& config) 416 { 417 // We don't actually have a frame buffer. 418 return B_UNSUPPORTED; 419 } 420 421 422 status_t 423 RemoteHWInterface::GetModeList(display_mode** _modes, uint32* _count) 424 { 425 AutoReadLocker _(this); 426 427 display_mode* modes = new(std::nothrow) display_mode[2]; 428 if (modes == NULL) 429 return B_NO_MEMORY; 430 431 modes[0] = fFallbackMode; 432 modes[1] = fClientMode; 433 *_modes = modes; 434 *_count = 2; 435 436 return B_OK; 437 } 438 439 440 status_t 441 RemoteHWInterface::GetPixelClockLimits(display_mode* mode, uint32* low, 442 uint32* high) 443 { 444 TRACE("get pixel clock limits unsupported\n"); 445 return B_UNSUPPORTED; 446 } 447 448 449 status_t 450 RemoteHWInterface::GetTimingConstraints(display_timing_constraints* constraints) 451 { 452 TRACE("get timing constraints unsupported\n"); 453 return B_UNSUPPORTED; 454 } 455 456 457 status_t 458 RemoteHWInterface::ProposeMode(display_mode* candidate, const display_mode* low, 459 const display_mode* high) 460 { 461 TRACE("propose mode: %" B_PRIu16 " %" B_PRIu16 "\n", 462 candidate->virtual_width, candidate->virtual_height); 463 return B_OK; 464 } 465 466 467 status_t 468 RemoteHWInterface::SetDPMSMode(uint32 state) 469 { 470 return B_UNSUPPORTED; 471 } 472 473 474 uint32 475 RemoteHWInterface::DPMSMode() 476 { 477 return B_UNSUPPORTED; 478 } 479 480 481 uint32 482 RemoteHWInterface::DPMSCapabilities() 483 { 484 return 0; 485 } 486 487 488 status_t 489 RemoteHWInterface::SetBrightness(float) 490 { 491 return B_UNSUPPORTED; 492 } 493 494 495 status_t 496 RemoteHWInterface::GetBrightness(float*) 497 { 498 return B_UNSUPPORTED; 499 } 500 501 502 sem_id 503 RemoteHWInterface::RetraceSemaphore() 504 { 505 return -1; 506 } 507 508 509 status_t 510 RemoteHWInterface::WaitForRetrace(bigtime_t timeout) 511 { 512 return B_UNSUPPORTED; 513 } 514 515 516 void 517 RemoteHWInterface::SetCursor(ServerCursor* cursor) 518 { 519 HWInterface::SetCursor(cursor); 520 RemoteMessage message(NULL, fSendBuffer); 521 message.Start(RP_SET_CURSOR); 522 message.AddCursor(CursorAndDragBitmap().Get()); 523 } 524 525 526 void 527 RemoteHWInterface::SetCursorVisible(bool visible) 528 { 529 HWInterface::SetCursorVisible(visible); 530 RemoteMessage message(NULL, fSendBuffer); 531 message.Start(RP_SET_CURSOR_VISIBLE); 532 message.Add(visible); 533 } 534 535 536 void 537 RemoteHWInterface::MoveCursorTo(float x, float y) 538 { 539 HWInterface::MoveCursorTo(x, y); 540 RemoteMessage message(NULL, fSendBuffer); 541 message.Start(RP_MOVE_CURSOR_TO); 542 message.Add(x); 543 message.Add(y); 544 } 545 546 547 void 548 RemoteHWInterface::SetDragBitmap(const ServerBitmap* bitmap, 549 const BPoint& offsetFromCursor) 550 { 551 HWInterface::SetDragBitmap(bitmap, offsetFromCursor); 552 RemoteMessage message(NULL, fSendBuffer); 553 message.Start(RP_SET_CURSOR); 554 message.AddCursor(CursorAndDragBitmap().Get()); 555 } 556 557 558 RenderingBuffer* 559 RemoteHWInterface::FrontBuffer() const 560 { 561 return NULL; 562 } 563 564 565 RenderingBuffer* 566 RemoteHWInterface::BackBuffer() const 567 { 568 return NULL; 569 } 570 571 572 bool 573 RemoteHWInterface::IsDoubleBuffered() const 574 { 575 return false; 576 } 577 578 579 status_t 580 RemoteHWInterface::InvalidateRegion(BRegion& region) 581 { 582 RemoteMessage message(NULL, fSendBuffer); 583 message.Start(RP_INVALIDATE_REGION); 584 message.AddRegion(region); 585 return B_OK; 586 } 587 588 589 status_t 590 RemoteHWInterface::Invalidate(const BRect& frame) 591 { 592 RemoteMessage message(NULL, fSendBuffer); 593 message.Start(RP_INVALIDATE_RECT); 594 message.Add(frame); 595 return B_OK; 596 } 597 598 599 status_t 600 RemoteHWInterface::CopyBackToFront(const BRect& frame) 601 { 602 return B_OK; 603 } 604 605 606 void 607 RemoteHWInterface::_FillDisplayModeTiming(display_mode &mode) 608 { 609 mode.timing.pixel_clock 610 = (uint64_t)mode.virtual_width * mode.virtual_height * 60 / 1000; 611 mode.timing.h_display = mode.timing.h_sync_start = mode.timing.h_sync_end 612 = mode.timing.h_total = mode.virtual_width; 613 mode.timing.v_display = mode.timing.v_sync_start = mode.timing.v_sync_end 614 = mode.timing.v_total = mode.virtual_height; 615 } 616