Changeset 43364 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Sep 20, 2012 12:12:09 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 80828
- Location:
- trunk/src/VBox/Additions/haiku
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/haiku/SharedFolders/OpenHashTable.h
r43363 r43364 34 34 35 35 #ifdef _KERNEL_MODE 36 # 37 # 36 # include <KernelExport.h> 37 # include "kernel_cpp.h" 38 38 #endif 39 39 40 40 /*! 41 The Definition template must have four methods: `HashKey', `Hash', 42 `Compare' and `GetLink;. It must also define several types as shown in the 43 following example: 44 45 struct Foo { 46 int bar; 47 48 Foo* fNext; 49 }; 50 51 struct HashTableDefinition { 52 typedef int KeyType; 53 typedef Foo ValueType; 54 55 size_t HashKey(int key) const 41 The Definition template must have four methods: `HashKey', `Hash', 42 `Compare' and `GetLink;. It must also define several types as shown in the 43 following example: 44 45 struct Foo { 46 int bar; 47 48 Foo* fNext; 49 }; 50 51 struct HashTableDefinition { 52 typedef int KeyType; 53 typedef Foo ValueType; 54 55 size_t HashKey(int key) const 56 { 57 return key >> 1; 58 } 59 60 size_t Hash(Foo* value) const 61 { 62 return HashKey(value->bar); 63 } 64 65 bool Compare(int key, Foo* value) const 66 { 67 return value->bar == key; 68 } 69 70 Foo*& GetLink(Foo* value) const 71 { 72 return value->fNext; 73 } 74 }; 75 */ 76 77 78 struct MallocAllocator 79 { 80 void* Allocate(size_t size) const 81 { 82 return malloc(size); 83 } 84 85 void Free(void* memory) const 86 { 87 free(memory); 88 } 89 }; 90 91 92 template<typename Definition, bool AutoExpand = true, 93 bool CheckDuplicates = false, typename Allocator = MallocAllocator> 94 class BOpenHashTable 95 { 96 public: 97 typedef BOpenHashTable<Definition, AutoExpand, CheckDuplicates> HashTable; 98 typedef typename Definition::KeyType KeyType; 99 typedef typename Definition::ValueType ValueType; 100 101 static const size_t kMinimumSize = 8; 102 103 // All allocations are of power of 2 lengths. 104 105 // regrowth factor: 200 / 256 = 78.125% 106 // 50 / 256 = 19.53125% 107 108 BOpenHashTable() 109 : 110 fTableSize(0), 111 fItemCount(0), 112 fTable(NULL) 113 { 114 } 115 116 BOpenHashTable(const Definition& definition) 117 : 118 fDefinition(definition), 119 fTableSize(0), 120 fItemCount(0), 121 fTable(NULL) 122 { 123 } 124 125 BOpenHashTable(const Definition& definition, const Allocator& allocator) 126 : 127 fDefinition(definition), 128 fAllocator(allocator), 129 fTableSize(0), 130 fItemCount(0), 131 fTable(NULL) 132 { 133 } 134 135 ~BOpenHashTable() 136 { 137 fAllocator.Free(fTable); 138 } 139 140 status_t Init(size_t initialSize = kMinimumSize) 141 { 142 if (initialSize > 0 && !_Resize(initialSize)) 143 return B_NO_MEMORY; 144 return B_OK; 145 } 146 147 size_t TableSize() const 148 { 149 return fTableSize; 150 } 151 152 size_t CountElements() const 153 { 154 return fItemCount; 155 } 156 157 ValueType* Lookup(const KeyType& key) const 158 { 159 if (fTableSize == 0) 160 return NULL; 161 162 size_t index = fDefinition.HashKey(key) & (fTableSize - 1); 163 ValueType* slot = fTable[index]; 164 165 while (slot) 166 { 167 if (fDefinition.Compare(key, slot)) 168 break; 169 slot = _Link(slot); 170 } 171 172 return slot; 173 } 174 175 status_t Insert(ValueType* value) 176 { 177 if (fTableSize == 0) 178 { 179 if (!_Resize(kMinimumSize)) 180 return B_NO_MEMORY; 181 } 182 else if (AutoExpand && fItemCount >= (fTableSize * 200 / 256)) 183 _Resize(fTableSize * 2); 184 185 InsertUnchecked(value); 186 return B_OK; 187 } 188 189 void InsertUnchecked(ValueType* value) 190 { 191 if (CheckDuplicates && _ExhaustiveSearch(value)) 192 { 193 #ifdef _KERNEL_MODE 194 panic("Hash Table: value already in table."); 195 #else 196 debugger("Hash Table: value already in table."); 197 #endif 198 } 199 200 _Insert(fTable, fTableSize, value); 201 fItemCount++; 202 } 203 204 // TODO: a ValueType* Remove(const KeyType& key) method is missing 205 206 bool Remove(ValueType* value) 207 { 208 if (!RemoveUnchecked(value)) 209 return false; 210 211 if (AutoExpand && fTableSize > kMinimumSize 212 && fItemCount < (fTableSize * 50 / 256)) 213 _Resize(fTableSize / 2); 214 215 return true; 216 } 217 218 bool RemoveUnchecked(ValueType* value) 219 { 220 size_t index = fDefinition.Hash(value) & (fTableSize - 1); 221 ValueType* previous = NULL; 222 ValueType* slot = fTable[index]; 223 224 while (slot) 225 { 226 ValueType* next = _Link(slot); 227 228 if (value == slot) 229 { 230 if (previous) 231 _Link(previous) = next; 232 else 233 fTable[index] = next; 234 break; 235 } 236 237 previous = slot; 238 slot = next; 239 } 240 241 if (slot == NULL) 242 return false; 243 244 if (CheckDuplicates && _ExhaustiveSearch(value)) 245 { 246 #ifdef _KERNEL_MODE 247 panic("Hash Table: duplicate detected."); 248 #else 249 debugger("Hash Table: duplicate detected."); 250 #endif 251 } 252 253 fItemCount--; 254 return true; 255 } 256 257 /*! Removes all elements from the hash table. No resizing happens. The 258 elements are not deleted. If \a returnElements is \c true, the method 259 returns all elements chained via their hash table link. 260 */ 261 ValueType* Clear(bool returnElements = false) 262 { 263 if (this->fItemCount == 0) 264 return NULL; 265 266 ValueType* result = NULL; 267 268 if (returnElements) 56 269 { 57 return key >> 1; 58 } 59 60 size_t Hash(Foo* value) const 61 { 62 return HashKey(value->bar); 63 } 64 65 bool Compare(int key, Foo* value) const 66 { 67 return value->bar == key; 68 } 69 70 Foo*& GetLink(Foo* value) const 71 { 72 return value->fNext; 73 } 74 }; 75 */ 76 77 78 struct MallocAllocator { 79 void* Allocate(size_t size) const 270 ValueType** nextPointer = &result; 271 272 // iterate through all buckets 273 for (size_t i = 0; i < fTableSize; i++) 274 { 275 ValueType* element = fTable[i]; 276 if (element != NULL) 277 { 278 // add the bucket to the list 279 *nextPointer = element; 280 281 // update nextPointer to point to the fNext of the last 282 // element in the bucket 283 while (element != NULL) 284 { 285 nextPointer = &_Link(element); 286 element = *nextPointer; 287 } 288 } 289 } 290 } 291 292 memset(this->fTable, 0, sizeof(ValueType*) * this->fTableSize); 293 294 return result; 295 } 296 297 /*! If the table needs resizing, the number of bytes for the required 298 allocation is returned. If no resizing is needed, 0 is returned. 299 */ 300 size_t ResizeNeeded() const 301 { 302 size_t size = fTableSize; 303 if (size == 0 || fItemCount >= (size * 200 / 256)) 304 { 305 // grow table 306 if (size == 0) 307 size = kMinimumSize; 308 while (fItemCount >= size * 200 / 256) 309 size <<= 1; 310 } 311 else if (size > kMinimumSize && fItemCount < size * 50 / 256) 312 { 313 // shrink table 314 while (fItemCount < size * 50 / 256) 315 size >>= 1; 316 if (size < kMinimumSize) 317 size = kMinimumSize; 318 } 319 320 if (size == fTableSize) 321 return 0; 322 323 return size * sizeof(ValueType*); 324 } 325 326 /*! Resizes the table using the given allocation. The allocation must not 327 be \c NULL. It must be of size \a size, which must a value returned 328 earlier by ResizeNeeded(). If the size requirements have changed in the 329 meantime, the method free()s the given allocation and returns \c false, 330 unless \a force is \c true, in which case the supplied allocation is 331 used in any event. 332 Otherwise \c true is returned. 333 If \a oldTable is non-null and resizing is successful, the old table 334 will not be freed, but will be returned via this parameter instead. 335 */ 336 bool Resize(void* allocation, size_t size, bool force = false, 337 void** oldTable = NULL) 338 { 339 if (!force && size != ResizeNeeded()) 340 { 341 fAllocator.Free(allocation); 342 return false; 343 } 344 345 _Resize((ValueType**)allocation, size / sizeof(ValueType*), oldTable); 346 return true; 347 } 348 349 class Iterator 80 350 { 81 return malloc(size); 82 } 83 84 void Free(void* memory) const 85 { 86 free(memory); 87 } 351 public: 352 Iterator(const HashTable* table) 353 : fTable(table) 354 { 355 Rewind(); 356 } 357 358 Iterator(const HashTable* table, size_t index, ValueType* value) 359 : fTable(table), fIndex(index), fNext(value) {} 360 361 bool HasNext() const { return fNext != NULL; } 362 363 ValueType* Next() 364 { 365 ValueType* current = fNext; 366 _GetNext(); 367 return current; 368 } 369 370 void Rewind() 371 { 372 // get the first one 373 fIndex = 0; 374 fNext = NULL; 375 _GetNext(); 376 } 377 378 protected: 379 Iterator() {} 380 381 void _GetNext() 382 { 383 if (fNext) 384 fNext = fTable->_Link(fNext); 385 386 while (fNext == NULL && fIndex < fTable->fTableSize) 387 fNext = fTable->fTable[fIndex++]; 388 } 389 390 const HashTable* fTable; 391 size_t fIndex; 392 ValueType* fNext; 393 }; 394 395 Iterator GetIterator() const 396 { 397 return Iterator(this); 398 } 399 400 Iterator GetIterator(const KeyType& key) const 401 { 402 if (fTableSize == 0) 403 return Iterator(this, fTableSize, NULL); 404 405 size_t index = fDefinition.HashKey(key) & (fTableSize - 1); 406 ValueType* slot = fTable[index]; 407 408 while (slot) 409 { 410 if (fDefinition.Compare(key, slot)) 411 break; 412 slot = _Link(slot); 413 } 414 415 if (slot == NULL) 416 return Iterator(this, fTableSize, NULL); 417 418 return Iterator(this, index + 1, slot); 419 } 420 421 protected: 422 // for g++ 2.95 423 friend class Iterator; 424 425 void _Insert(ValueType** table, size_t tableSize, ValueType* value) 426 { 427 size_t index = fDefinition.Hash(value) & (tableSize - 1); 428 429 _Link(value) = table[index]; 430 table[index] = value; 431 } 432 433 bool _Resize(size_t newSize) 434 { 435 ValueType** newTable 436 = (ValueType**)fAllocator.Allocate(sizeof(ValueType*) * newSize); 437 if (newTable == NULL) 438 return false; 439 440 _Resize(newTable, newSize); 441 return true; 442 } 443 444 void _Resize(ValueType** newTable, size_t newSize, void** _oldTable = NULL) 445 { 446 for (size_t i = 0; i < newSize; i++) 447 newTable[i] = NULL; 448 449 if (fTable) 450 { 451 for (size_t i = 0; i < fTableSize; i++) 452 { 453 ValueType* bucket = fTable[i]; 454 while (bucket) 455 { 456 ValueType* next = _Link(bucket); 457 _Insert(newTable, newSize, bucket); 458 bucket = next; 459 } 460 } 461 462 if (_oldTable != NULL) 463 *_oldTable = fTable; 464 else 465 fAllocator.Free(fTable); 466 } 467 else if (_oldTable != NULL) 468 *_oldTable = NULL; 469 470 fTableSize = newSize; 471 fTable = newTable; 472 } 473 474 ValueType*& _Link(ValueType* bucket) const 475 { 476 return fDefinition.GetLink(bucket); 477 } 478 479 bool _ExhaustiveSearch(ValueType* value) const 480 { 481 for (size_t i = 0; i < fTableSize; i++) 482 { 483 ValueType* bucket = fTable[i]; 484 while (bucket) { 485 if (bucket == value) 486 return true; 487 bucket = _Link(bucket); 488 } 489 } 490 491 return false; 492 } 493 494 Definition fDefinition; 495 Allocator fAllocator; 496 size_t fTableSize; 497 size_t fItemCount; 498 ValueType** fTable; 88 499 }; 89 500 90 91 template<typename Definition, bool AutoExpand = true, 92 bool CheckDuplicates = false, typename Allocator = MallocAllocator> 93 class BOpenHashTable { 94 public: 95 typedef BOpenHashTable<Definition, AutoExpand, CheckDuplicates> HashTable; 96 typedef typename Definition::KeyType KeyType; 97 typedef typename Definition::ValueType ValueType; 98 99 static const size_t kMinimumSize = 8; 100 101 // All allocations are of power of 2 lengths. 102 103 // regrowth factor: 200 / 256 = 78.125% 104 // 50 / 256 = 19.53125% 105 106 BOpenHashTable() 107 : 108 fTableSize(0), 109 fItemCount(0), 110 fTable(NULL) 111 { 112 } 113 114 BOpenHashTable(const Definition& definition) 115 : 116 fDefinition(definition), 117 fTableSize(0), 118 fItemCount(0), 119 fTable(NULL) 120 { 121 } 122 123 BOpenHashTable(const Definition& definition, const Allocator& allocator) 124 : 125 fDefinition(definition), 126 fAllocator(allocator), 127 fTableSize(0), 128 fItemCount(0), 129 fTable(NULL) 130 { 131 } 132 133 ~BOpenHashTable() 134 { 135 fAllocator.Free(fTable); 136 } 137 138 status_t Init(size_t initialSize = kMinimumSize) 139 { 140 if (initialSize > 0 && !_Resize(initialSize)) 141 return B_NO_MEMORY; 142 return B_OK; 143 } 144 145 size_t TableSize() const 146 { 147 return fTableSize; 148 } 149 150 size_t CountElements() const 151 { 152 return fItemCount; 153 } 154 155 ValueType* Lookup(const KeyType& key) const 156 { 157 if (fTableSize == 0) 158 return NULL; 159 160 size_t index = fDefinition.HashKey(key) & (fTableSize - 1); 161 ValueType* slot = fTable[index]; 162 163 while (slot) { 164 if (fDefinition.Compare(key, slot)) 165 break; 166 slot = _Link(slot); 167 } 168 169 return slot; 170 } 171 172 status_t Insert(ValueType* value) 173 { 174 if (fTableSize == 0) { 175 if (!_Resize(kMinimumSize)) 176 return B_NO_MEMORY; 177 } else if (AutoExpand && fItemCount >= (fTableSize * 200 / 256)) 178 _Resize(fTableSize * 2); 179 180 InsertUnchecked(value); 181 return B_OK; 182 } 183 184 void InsertUnchecked(ValueType* value) 185 { 186 if (CheckDuplicates && _ExhaustiveSearch(value)) { 187 #ifdef _KERNEL_MODE 188 panic("Hash Table: value already in table."); 189 #else 190 debugger("Hash Table: value already in table."); 191 #endif 192 } 193 194 _Insert(fTable, fTableSize, value); 195 fItemCount++; 196 } 197 198 // TODO: a ValueType* Remove(const KeyType& key) method is missing 199 200 bool Remove(ValueType* value) 201 { 202 if (!RemoveUnchecked(value)) 203 return false; 204 205 if (AutoExpand && fTableSize > kMinimumSize 206 && fItemCount < (fTableSize * 50 / 256)) 207 _Resize(fTableSize / 2); 208 209 return true; 210 } 211 212 bool RemoveUnchecked(ValueType* value) 213 { 214 size_t index = fDefinition.Hash(value) & (fTableSize - 1); 215 ValueType* previous = NULL; 216 ValueType* slot = fTable[index]; 217 218 while (slot) { 219 ValueType* next = _Link(slot); 220 221 if (value == slot) { 222 if (previous) 223 _Link(previous) = next; 224 else 225 fTable[index] = next; 226 break; 227 } 228 229 previous = slot; 230 slot = next; 231 } 232 233 if (slot == NULL) 234 return false; 235 236 if (CheckDuplicates && _ExhaustiveSearch(value)) { 237 #ifdef _KERNEL_MODE 238 panic("Hash Table: duplicate detected."); 239 #else 240 debugger("Hash Table: duplicate detected."); 241 #endif 242 } 243 244 fItemCount--; 245 return true; 246 } 247 248 /*! Removes all elements from the hash table. No resizing happens. The 249 elements are not deleted. If \a returnElements is \c true, the method 250 returns all elements chained via their hash table link. 251 */ 252 ValueType* Clear(bool returnElements = false) 253 { 254 if (this->fItemCount == 0) 255 return NULL; 256 257 ValueType* result = NULL; 258 259 if (returnElements) { 260 ValueType** nextPointer = &result; 261 262 // iterate through all buckets 263 for (size_t i = 0; i < fTableSize; i++) { 264 ValueType* element = fTable[i]; 265 if (element != NULL) { 266 // add the bucket to the list 267 *nextPointer = element; 268 269 // update nextPointer to point to the fNext of the last 270 // element in the bucket 271 while (element != NULL) { 272 nextPointer = &_Link(element); 273 element = *nextPointer; 274 } 275 } 276 } 277 } 278 279 memset(this->fTable, 0, sizeof(ValueType*) * this->fTableSize); 280 281 return result; 282 } 283 284 /*! If the table needs resizing, the number of bytes for the required 285 allocation is returned. If no resizing is needed, 0 is returned. 286 */ 287 size_t ResizeNeeded() const 288 { 289 size_t size = fTableSize; 290 if (size == 0 || fItemCount >= (size * 200 / 256)) { 291 // grow table 292 if (size == 0) 293 size = kMinimumSize; 294 while (fItemCount >= size * 200 / 256) 295 size <<= 1; 296 } else if (size > kMinimumSize && fItemCount < size * 50 / 256) { 297 // shrink table 298 while (fItemCount < size * 50 / 256) 299 size >>= 1; 300 if (size < kMinimumSize) 301 size = kMinimumSize; 302 } 303 304 if (size == fTableSize) 305 return 0; 306 307 return size * sizeof(ValueType*); 308 } 309 310 /*! Resizes the table using the given allocation. The allocation must not 311 be \c NULL. It must be of size \a size, which must a value returned 312 earlier by ResizeNeeded(). If the size requirements have changed in the 313 meantime, the method free()s the given allocation and returns \c false, 314 unless \a force is \c true, in which case the supplied allocation is 315 used in any event. 316 Otherwise \c true is returned. 317 If \a oldTable is non-null and resizing is successful, the old table 318 will not be freed, but will be returned via this parameter instead. 319 */ 320 bool Resize(void* allocation, size_t size, bool force = false, 321 void** oldTable = NULL) 322 { 323 if (!force && size != ResizeNeeded()) { 324 fAllocator.Free(allocation); 325 return false; 326 } 327 328 _Resize((ValueType**)allocation, size / sizeof(ValueType*), oldTable); 329 return true; 330 } 331 332 class Iterator { 333 public: 334 Iterator(const HashTable* table) 335 : fTable(table) 336 { 337 Rewind(); 338 } 339 340 Iterator(const HashTable* table, size_t index, ValueType* value) 341 : fTable(table), fIndex(index), fNext(value) {} 342 343 bool HasNext() const { return fNext != NULL; } 344 345 ValueType* Next() 346 { 347 ValueType* current = fNext; 348 _GetNext(); 349 return current; 350 } 351 352 void Rewind() 353 { 354 // get the first one 355 fIndex = 0; 356 fNext = NULL; 357 _GetNext(); 358 } 359 360 protected: 361 Iterator() {} 362 363 void _GetNext() 364 { 365 if (fNext) 366 fNext = fTable->_Link(fNext); 367 368 while (fNext == NULL && fIndex < fTable->fTableSize) 369 fNext = fTable->fTable[fIndex++]; 370 } 371 372 const HashTable* fTable; 373 size_t fIndex; 374 ValueType* fNext; 375 }; 376 377 Iterator GetIterator() const 378 { 379 return Iterator(this); 380 } 381 382 Iterator GetIterator(const KeyType& key) const 383 { 384 if (fTableSize == 0) 385 return Iterator(this, fTableSize, NULL); 386 387 size_t index = fDefinition.HashKey(key) & (fTableSize - 1); 388 ValueType* slot = fTable[index]; 389 390 while (slot) { 391 if (fDefinition.Compare(key, slot)) 392 break; 393 slot = _Link(slot); 394 } 395 396 if (slot == NULL) 397 return Iterator(this, fTableSize, NULL); 398 399 return Iterator(this, index + 1, slot); 400 } 401 402 protected: 403 // for g++ 2.95 404 friend class Iterator; 405 406 void _Insert(ValueType** table, size_t tableSize, ValueType* value) 407 { 408 size_t index = fDefinition.Hash(value) & (tableSize - 1); 409 410 _Link(value) = table[index]; 411 table[index] = value; 412 } 413 414 bool _Resize(size_t newSize) 415 { 416 ValueType** newTable 417 = (ValueType**)fAllocator.Allocate(sizeof(ValueType*) * newSize); 418 if (newTable == NULL) 419 return false; 420 421 _Resize(newTable, newSize); 422 return true; 423 } 424 425 void _Resize(ValueType** newTable, size_t newSize, void** _oldTable = NULL) 426 { 427 for (size_t i = 0; i < newSize; i++) 428 newTable[i] = NULL; 429 430 if (fTable) { 431 for (size_t i = 0; i < fTableSize; i++) { 432 ValueType* bucket = fTable[i]; 433 while (bucket) { 434 ValueType* next = _Link(bucket); 435 _Insert(newTable, newSize, bucket); 436 bucket = next; 437 } 438 } 439 440 if (_oldTable != NULL) 441 *_oldTable = fTable; 442 else 443 fAllocator.Free(fTable); 444 } else if (_oldTable != NULL) 445 *_oldTable = NULL; 446 447 fTableSize = newSize; 448 fTable = newTable; 449 } 450 451 ValueType*& _Link(ValueType* bucket) const 452 { 453 return fDefinition.GetLink(bucket); 454 } 455 456 bool _ExhaustiveSearch(ValueType* value) const 457 { 458 for (size_t i = 0; i < fTableSize; i++) { 459 ValueType* bucket = fTable[i]; 460 while (bucket) { 461 if (bucket == value) 462 return true; 463 bucket = _Link(bucket); 464 } 465 } 466 467 return false; 468 } 469 470 Definition fDefinition; 471 Allocator fAllocator; 472 size_t fTableSize; 473 size_t fItemCount; 474 ValueType** fTable; 475 }; 476 477 #endif // _KERNEL_UTIL_OPEN_HASH_TABLE_H 501 #endif // _KERNEL_UTIL_OPEN_HASH_TABLE_H 502 -
trunk/src/VBox/Additions/haiku/SharedFolders/vboxsf.c
r43363 r43364 55 55 status_t init_module(void) 56 56 { 57 if (get_module(VBOXGUEST_MODULE_NAME, (module_info **)&g_VBoxGuest) != B_OK) { 58 dprintf("get_module(%s) failed\n", VBOXGUEST_MODULE_NAME); 59 return B_ERROR; 60 } 61 62 if (RT_FAILURE(vboxInit())) { 63 dprintf("vboxInit failed\n"); 64 return B_ERROR; 65 } 66 67 if (RT_FAILURE(vboxConnect(&g_clientHandle))) { 68 dprintf("vboxConnect failed\n"); 69 return B_ERROR; 70 } 71 72 if (RT_FAILURE(vboxCallSetUtf8(&g_clientHandle))) { 73 dprintf("vboxCallSetUtf8 failed\n"); 74 return B_ERROR; 75 } 76 77 if (RT_FAILURE(vboxCallSetSymlinks(&g_clientHandle))) { 78 dprintf("warning: vboxCallSetSymlinks failed (old vbox?) - symlinks will appear as copies\n"); 79 } 80 81 mutex_init(&g_vnodeCacheLock, "vboxsf vnode cache lock"); 82 83 dprintf(FS_NAME ": inited successfully\n"); 84 return B_OK; 57 if (get_module(VBOXGUEST_MODULE_NAME, (module_info **)&g_VBoxGuest) != B_OK) 58 { 59 dprintf("get_module(%s) failed\n", VBOXGUEST_MODULE_NAME); 60 return B_ERROR; 61 } 62 63 if (RT_FAILURE(vboxInit())) 64 { 65 dprintf("vboxInit failed\n"); 66 return B_ERROR; 67 } 68 69 if (RT_FAILURE(vboxConnect(&g_clientHandle))) 70 { 71 dprintf("vboxConnect failed\n"); 72 return B_ERROR; 73 } 74 75 if (RT_FAILURE(vboxCallSetUtf8(&g_clientHandle))) 76 { 77 dprintf("vboxCallSetUtf8 failed\n"); 78 return B_ERROR; 79 } 80 81 if (RT_FAILURE(vboxCallSetSymlinks(&g_clientHandle))) 82 { 83 dprintf("warning: vboxCallSetSymlinks failed (old vbox?) - symlinks will appear as copies\n"); 84 } 85 86 mutex_init(&g_vnodeCacheLock, "vboxsf vnode cache lock"); 87 88 dprintf(FS_NAME ": inited successfully\n"); 89 return B_OK; 85 90 } 86 91 87 92 void uninit_module(void) 88 93 { 89 mutex_destroy(&g_vnodeCacheLock); 90 put_module(VBOXGUEST_MODULE_NAME); 91 } 92 93 PSHFLSTRING make_shflstring(const char* const s) { 94 int len = strlen(s); 95 if (len > 0xFFFE) { 96 dprintf(FS_NAME ": make_shflstring: string too long\n"); 97 return NULL; 98 } 99 100 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + len); 101 if (!rv) { 102 return NULL; 103 } 104 105 rv->u16Length = len; 94 mutex_destroy(&g_vnodeCacheLock); 95 put_module(VBOXGUEST_MODULE_NAME); 96 } 97 98 99 PSHFLSTRING make_shflstring(const char* const s) 100 { 101 int len = strlen(s); 102 if (len > 0xFFFE) 103 { 104 dprintf(FS_NAME ": make_shflstring: string too long\n"); 105 return NULL; 106 } 107 108 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + len); 109 if (!rv) 110 return NULL; 111 112 rv->u16Length = len; 106 113 rv->u16Size = len + 1; 107 114 strcpy(rv->String.utf8, s); 108 return rv; 109 } 110 111 PSHFLSTRING clone_shflstring(PSHFLSTRING s) { 112 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + s->u16Length); 113 if (rv) 114 memcpy(rv, s, sizeof(SHFLSTRING) + s->u16Length); 115 return rv; 116 } 117 118 PSHFLSTRING concat_shflstring_cstr(PSHFLSTRING s1, const char* const s2) { 119 size_t s2len = strlen(s2); 120 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + s1->u16Length + s2len); 121 if (rv) { 122 memcpy(rv, s1, sizeof(SHFLSTRING) + s1->u16Length); 123 strcat(rv->String.utf8, s2); 124 rv->u16Length += s2len; 125 rv->u16Size += s2len; 126 } 127 return rv; 128 } 129 130 PSHFLSTRING concat_cstr_shflstring(const char* const s1, PSHFLSTRING s2) { 131 size_t s1len = strlen(s1); 132 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + s1len + s2->u16Length); 133 if (rv) { 134 strcpy(rv->String.utf8, s1); 135 strcat(rv->String.utf8, s2->String.utf8); 136 rv->u16Length = s1len + s2->u16Length; 137 rv->u16Size = rv->u16Length + 1; 138 } 139 return rv; 140 } 141 142 PSHFLSTRING build_path(vboxsf_vnode* dir, const char* const name) { 143 144 dprintf("*** build_path(%p, %p)\n", dir, name); 145 if (!dir || !name) 146 return NULL; 147 148 size_t len = dir->path->u16Length + strlen(name) + 1; 149 150 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + len); 151 if (rv) { 152 strcpy(rv->String.utf8, dir->path->String.utf8); 153 strcat(rv->String.utf8, "/"); 154 strcat(rv->String.utf8, name); 155 rv->u16Length = len; 156 rv->u16Size = rv->u16Length + 1; 157 } 158 return rv; 159 } 160 161 status_t mount(fs_volume *volume, const char *device, uint32 flags, const char *args, ino_t *_rootVnodeID) { 162 if (device) { 163 dprintf(FS_NAME ": trying to mount a real device as a vbox share is silly\n"); 164 return B_BAD_TYPE; 165 } 166 167 dprintf(FS_NAME ": mount(%s)\n", args); 168 169 PSHFLSTRING sharename = make_shflstring(args); 170 171 vboxsf_volume* vbsfvolume = malloc(sizeof(vboxsf_volume)); 172 volume->private_volume = vbsfvolume; 173 int rv = vboxCallMapFolder(&g_clientHandle, sharename, &(vbsfvolume->map)); 174 free(sharename); 175 176 if (rv == 0) { 177 vboxsf_vnode* root_vnode; 178 179 PSHFLSTRING name = make_shflstring(""); 180 if (!name) { 181 dprintf(FS_NAME ": make_shflstring() failed\n"); 182 return B_NO_MEMORY; 183 } 184 185 status_t rs = vboxsf_new_vnode(&vbsfvolume->map, name, name, &root_vnode); 186 dprintf(FS_NAME ": allocated %p (path=%p name=%p)\n", root_vnode, root_vnode->path, root_vnode->name); 187 188 if (rs != B_OK) { 189 dprintf(FS_NAME ": vboxsf_new_vnode() failed (%d)\n", (int)rs); 190 return rs; 191 } 192 193 rs = publish_vnode(volume, root_vnode->vnode, root_vnode, &vboxsf_vnode_ops, S_IFDIR, 0); 194 dprintf(FS_NAME ": publish_vnode(): %d\n", (int)rs); 195 *_rootVnodeID = root_vnode->vnode; 196 volume->ops = &vboxsf_volume_ops; 197 return B_OK; 198 } 199 else { 200 dprintf(FS_NAME ": vboxCallMapFolder failed (%d)\n", rv); 201 free(volume->private_volume); 202 return vbox_err_to_haiku_err(rv); 203 } 204 } 205 206 status_t unmount(fs_volume *volume) { 207 dprintf(FS_NAME ": unmount\n"); 208 vboxCallUnmapFolder(&g_clientHandle, volume->private_volume); 209 return B_OK; 210 } 211 212 status_t vboxsf_read_stat(fs_volume* _volume, fs_vnode* _vnode, struct stat* st) { 213 vboxsf_vnode* vnode = _vnode->private_node; 214 vboxsf_volume* volume = _volume->private_volume; 215 SHFLCREATEPARMS params; 216 int rc; 217 218 dprintf("vboxsf_read_stat (_vnode=%p, vnode=%p, path=%p (%s))\n", _vnode, vnode, vnode->path->String.utf8, vnode->path->String.utf8); 219 220 params.Handle = SHFL_HANDLE_NIL; 221 params.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 222 dprintf("sf_stat: calling vboxCallCreate, file %s, flags %x\n", vnode->path->String.utf8, params.CreateFlags); 223 rc = vboxCallCreate(&g_clientHandle, &volume->map, vnode->path, ¶ms); 224 if (rc == VERR_INVALID_NAME) 225 { 226 /* this can happen for names like 'foo*' on a Windows host */ 227 return B_ENTRY_NOT_FOUND; 228 } 229 if (RT_FAILURE(rc)) 230 { 231 dprintf("vboxCallCreate: %d\n", params.Result); 232 return vbox_err_to_haiku_err(params.Result); 233 } 234 if (params.Result != SHFL_FILE_EXISTS) 235 { 236 dprintf("vboxCallCreate: %d\n", params.Result); 237 return B_ENTRY_NOT_FOUND; 238 } 239 240 st->st_dev = 0; 241 st->st_ino = vnode->vnode; 242 st->st_mode = mode_from_fmode(params.Info.Attr.fMode); 243 st->st_nlink = 1; 244 st->st_uid = 0; 245 st->st_gid = 0; 246 st->st_rdev = 0; 247 st->st_size = params.Info.cbObject; 248 st->st_blksize = 1; 249 st->st_blocks = params.Info.cbAllocated; 250 st->st_atime = RTTimeSpecGetSeconds(¶ms.Info.AccessTime); 251 st->st_mtime = RTTimeSpecGetSeconds(¶ms.Info.ModificationTime); 252 st->st_ctime = RTTimeSpecGetSeconds(¶ms.Info.BirthTime); 253 return B_OK; 254 } 255 256 status_t vboxsf_open_dir(fs_volume* _volume, fs_vnode* _vnode, void** _cookie) { 257 vboxsf_volume* volume = _volume->private_volume; 258 vboxsf_vnode* vnode = _vnode->private_node; 259 SHFLCREATEPARMS params; 260 261 RT_ZERO(params); 262 params.Handle = SHFL_HANDLE_NIL; 263 params.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS 264 | SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; 265 266 int rc = vboxCallCreate(&g_clientHandle, &volume->map, vnode->path, ¶ms); 267 if (RT_SUCCESS(rc)) { 268 if (params.Result == SHFL_FILE_EXISTS && params.Handle != SHFL_HANDLE_NIL) { 269 vboxsf_dir_cookie* cookie = malloc(sizeof(vboxsf_dir_cookie)); 270 *_cookie = cookie; 271 cookie->index = 0; 272 cookie->path = build_path(vnode, "*"); 273 cookie->handle = params.Handle; 274 cookie->has_more_files = true; 275 cookie->buffer_start = cookie->buffer = NULL; 276 cookie->buffer_length = cookie->num_files = 0; 277 return B_OK; 278 } 279 else { 280 return B_ENTRY_NOT_FOUND; 281 } 282 } 283 else { 284 dprintf(FS_NAME ": vboxCallCreate: %d\n", rc); 285 return vbox_err_to_haiku_err(rc); 286 } 287 } 115 return rv; 116 } 117 118 119 PSHFLSTRING clone_shflstring(PSHFLSTRING s) 120 { 121 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + s->u16Length); 122 if (rv) 123 memcpy(rv, s, sizeof(SHFLSTRING) + s->u16Length); 124 return rv; 125 } 126 127 PSHFLSTRING concat_shflstring_cstr(PSHFLSTRING s1, const char* const s2) 128 { 129 size_t s2len = strlen(s2); 130 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + s1->u16Length + s2len); 131 if (rv) 132 { 133 memcpy(rv, s1, sizeof(SHFLSTRING) + s1->u16Length); 134 strcat(rv->String.utf8, s2); 135 rv->u16Length += s2len; 136 rv->u16Size += s2len; 137 } 138 return rv; 139 } 140 141 142 PSHFLSTRING concat_cstr_shflstring(const char* const s1, PSHFLSTRING s2) 143 { 144 size_t s1len = strlen(s1); 145 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + s1len + s2->u16Length); 146 if (rv) 147 { 148 strcpy(rv->String.utf8, s1); 149 strcat(rv->String.utf8, s2->String.utf8); 150 rv->u16Length = s1len + s2->u16Length; 151 rv->u16Size = rv->u16Length + 1; 152 } 153 return rv; 154 } 155 156 157 PSHFLSTRING build_path(vboxsf_vnode* dir, const char* const name) 158 { 159 160 dprintf("*** build_path(%p, %p)\n", dir, name); 161 if (!dir || !name) 162 return NULL; 163 164 size_t len = dir->path->u16Length + strlen(name) + 1; 165 PSHFLSTRING rv = malloc(sizeof(SHFLSTRING) + len); 166 if (rv) 167 { 168 strcpy(rv->String.utf8, dir->path->String.utf8); 169 strcat(rv->String.utf8, "/"); 170 strcat(rv->String.utf8, name); 171 rv->u16Length = len; 172 rv->u16Size = rv->u16Length + 1; 173 } 174 return rv; 175 } 176 177 178 status_t mount(fs_volume *volume, const char *device, uint32 flags, const char *args, ino_t *_rootVnodeID) 179 { 180 if (device) 181 { 182 dprintf(FS_NAME ": trying to mount a real device as a vbox share is silly\n"); 183 return B_BAD_TYPE; 184 } 185 186 dprintf(FS_NAME ": mount(%s)\n", args); 187 188 PSHFLSTRING sharename = make_shflstring(args); 189 190 vboxsf_volume* vbsfvolume = malloc(sizeof(vboxsf_volume)); 191 volume->private_volume = vbsfvolume; 192 int rv = vboxCallMapFolder(&g_clientHandle, sharename, &(vbsfvolume->map)); 193 free(sharename); 194 195 if (rv == 0) 196 { 197 vboxsf_vnode* root_vnode; 198 199 PSHFLSTRING name = make_shflstring(""); 200 if (!name) 201 { 202 dprintf(FS_NAME ": make_shflstring() failed\n"); 203 return B_NO_MEMORY; 204 } 205 206 status_t rs = vboxsf_new_vnode(&vbsfvolume->map, name, name, &root_vnode); 207 dprintf(FS_NAME ": allocated %p (path=%p name=%p)\n", root_vnode, root_vnode->path, root_vnode->name); 208 209 if (rs != B_OK) 210 { 211 dprintf(FS_NAME ": vboxsf_new_vnode() failed (%d)\n", (int)rs); 212 return rs; 213 } 214 215 rs = publish_vnode(volume, root_vnode->vnode, root_vnode, &vboxsf_vnode_ops, S_IFDIR, 0); 216 dprintf(FS_NAME ": publish_vnode(): %d\n", (int)rs); 217 *_rootVnodeID = root_vnode->vnode; 218 volume->ops = &vboxsf_volume_ops; 219 return B_OK; 220 } 221 else 222 { 223 dprintf(FS_NAME ": vboxCallMapFolder failed (%d)\n", rv); 224 free(volume->private_volume); 225 return vbox_err_to_haiku_err(rv); 226 } 227 } 228 229 230 status_t unmount(fs_volume *volume) 231 { 232 dprintf(FS_NAME ": unmount\n"); 233 vboxCallUnmapFolder(&g_clientHandle, volume->private_volume); 234 return B_OK; 235 } 236 237 238 status_t vboxsf_read_stat(fs_volume* _volume, fs_vnode* _vnode, struct stat* st) 239 { 240 vboxsf_vnode* vnode = _vnode->private_node; 241 vboxsf_volume* volume = _volume->private_volume; 242 SHFLCREATEPARMS params; 243 int rc; 244 245 dprintf("vboxsf_read_stat (_vnode=%p, vnode=%p, path=%p (%s))\n", _vnode, vnode, vnode->path->String.utf8, vnode->path->String.utf8); 246 247 params.Handle = SHFL_HANDLE_NIL; 248 params.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 249 dprintf("sf_stat: calling vboxCallCreate, file %s, flags %x\n", vnode->path->String.utf8, params.CreateFlags); 250 rc = vboxCallCreate(&g_clientHandle, &volume->map, vnode->path, ¶ms); 251 if (rc == VERR_INVALID_NAME) 252 { 253 /* this can happen for names like 'foo*' on a Windows host */ 254 return B_ENTRY_NOT_FOUND; 255 } 256 if (RT_FAILURE(rc)) 257 { 258 dprintf("vboxCallCreate: %d\n", params.Result); 259 return vbox_err_to_haiku_err(params.Result); 260 } 261 if (params.Result != SHFL_FILE_EXISTS) 262 { 263 dprintf("vboxCallCreate: %d\n", params.Result); 264 return B_ENTRY_NOT_FOUND; 265 } 266 267 st->st_dev = 0; 268 st->st_ino = vnode->vnode; 269 st->st_mode = mode_from_fmode(params.Info.Attr.fMode); 270 st->st_nlink = 1; 271 st->st_uid = 0; 272 st->st_gid = 0; 273 st->st_rdev = 0; 274 st->st_size = params.Info.cbObject; 275 st->st_blksize = 1; 276 st->st_blocks = params.Info.cbAllocated; 277 st->st_atime = RTTimeSpecGetSeconds(¶ms.Info.AccessTime); 278 st->st_mtime = RTTimeSpecGetSeconds(¶ms.Info.ModificationTime); 279 st->st_ctime = RTTimeSpecGetSeconds(¶ms.Info.BirthTime); 280 return B_OK; 281 } 282 283 284 status_t vboxsf_open_dir(fs_volume* _volume, fs_vnode* _vnode, void** _cookie) 285 { 286 vboxsf_volume* volume = _volume->private_volume; 287 vboxsf_vnode* vnode = _vnode->private_node; 288 SHFLCREATEPARMS params; 289 290 RT_ZERO(params); 291 params.Handle = SHFL_HANDLE_NIL; 292 params.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS 293 | SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; 294 295 int rc = vboxCallCreate(&g_clientHandle, &volume->map, vnode->path, ¶ms); 296 if (RT_SUCCESS(rc)) 297 { 298 if (params.Result == SHFL_FILE_EXISTS && params.Handle != SHFL_HANDLE_NIL) 299 { 300 vboxsf_dir_cookie* cookie = malloc(sizeof(vboxsf_dir_cookie)); 301 *_cookie = cookie; 302 cookie->index = 0; 303 cookie->path = build_path(vnode, "*"); 304 cookie->handle = params.Handle; 305 cookie->has_more_files = true; 306 cookie->buffer_start = cookie->buffer = NULL; 307 cookie->buffer_length = cookie->num_files = 0; 308 return B_OK; 309 } 310 else 311 return B_ENTRY_NOT_FOUND; 312 } 313 else 314 { 315 dprintf(FS_NAME ": vboxCallCreate: %d\n", rc); 316 return vbox_err_to_haiku_err(rc); 317 } 318 } 319 288 320 289 321 /** read a single entry from a dir */ 290 322 status_t vboxsf_read_dir_1(vboxsf_volume* volume, vboxsf_vnode* vnode, vboxsf_dir_cookie* cookie, 291 struct dirent* buffer, size_t bufferSize) { 292 dprintf("%p, %d, %p\n", cookie, cookie->has_more_files, cookie->buffer); 293 if (!cookie->has_more_files) { 294 return B_ENTRY_NOT_FOUND; 295 } 296 if (!cookie->buffer) { 297 cookie->buffer_length = 16384; 298 cookie->buffer_start = cookie->buffer = malloc(cookie->buffer_length); 299 300 int rc = vboxCallDirInfo(&g_clientHandle, &volume->map, cookie->handle, cookie->path, 301 0, cookie->index, &cookie->buffer_length, cookie->buffer, &cookie->num_files); 302 303 if (rc != 0 && rc != VERR_NO_MORE_FILES) { 304 dprintf(FS_NAME ": vboxCallDirInfo failed: %d\n", rc); 305 free(cookie->buffer_start); 306 cookie->buffer_start = NULL; 307 return vbox_err_to_haiku_err(rc); 308 } 309 310 if (rc == VERR_NO_MORE_FILES) { 311 free(cookie->buffer_start); 312 cookie->buffer_start = NULL; 313 cookie->has_more_files = false; 314 return B_ENTRY_NOT_FOUND; 315 } 316 } 317 318 if (bufferSize <= sizeof(struct dirent) + cookie->buffer->name.u16Length) { 319 dprintf("hit end of buffer\n"); 320 return B_BUFFER_OVERFLOW; 321 } 322 323 PSHFLSTRING name1 = clone_shflstring(&cookie->buffer->name); 324 if (!name1) { 325 dprintf(FS_NAME ": make_shflstring() failed\n"); 326 return B_NO_MEMORY; 327 } 328 329 vboxsf_vnode* new_vnode; 330 int rv = vboxsf_new_vnode(&volume->map, build_path(vnode, name1->String.utf8), name1, &new_vnode); 331 if (rv != B_OK) { 332 dprintf(FS_NAME ": vboxsf_new_vnode() failed\n"); 333 return rv; 334 } 335 buffer->d_dev = 0; 336 buffer->d_pdev = 0; 337 buffer->d_ino = new_vnode->vnode; 338 buffer->d_pino = vnode->vnode; 339 buffer->d_reclen = sizeof(struct dirent) + cookie->buffer->name.u16Length; 340 strncpy(buffer->d_name, cookie->buffer->name.String.utf8, NAME_MAX); 341 342 size_t size = offsetof(SHFLDIRINFO, name.String) + cookie->buffer->name.u16Size; 343 cookie->buffer = ((void*)cookie->buffer + size); 344 cookie->index++; 345 346 if (cookie->index >= cookie->num_files) { 347 // hit end of this buffer, next call will reallocate a new one 348 free(cookie->buffer_start); 349 cookie->buffer_start = cookie->buffer = NULL; 350 } 351 return B_OK; 352 } 323 struct dirent* buffer, size_t bufferSize) 324 { 325 dprintf("%p, %d, %p\n", cookie, cookie->has_more_files, cookie->buffer); 326 if (!cookie->has_more_files) 327 return B_ENTRY_NOT_FOUND; 328 329 if (!cookie->buffer) 330 { 331 cookie->buffer_length = 16384; 332 cookie->buffer_start = cookie->buffer = malloc(cookie->buffer_length); 333 334 int rc = vboxCallDirInfo(&g_clientHandle, &volume->map, cookie->handle, cookie->path, 335 0, cookie->index, &cookie->buffer_length, cookie->buffer, &cookie->num_files); 336 337 if (rc != 0 && rc != VERR_NO_MORE_FILES) 338 { 339 dprintf(FS_NAME ": vboxCallDirInfo failed: %d\n", rc); 340 free(cookie->buffer_start); 341 cookie->buffer_start = NULL; 342 return vbox_err_to_haiku_err(rc); 343 } 344 345 if (rc == VERR_NO_MORE_FILES) 346 { 347 free(cookie->buffer_start); 348 cookie->buffer_start = NULL; 349 cookie->has_more_files = false; 350 return B_ENTRY_NOT_FOUND; 351 } 352 } 353 354 if (bufferSize <= sizeof(struct dirent) + cookie->buffer->name.u16Length) 355 { 356 dprintf("hit end of buffer\n"); 357 return B_BUFFER_OVERFLOW; 358 } 359 360 PSHFLSTRING name1 = clone_shflstring(&cookie->buffer->name); 361 if (!name1) 362 { 363 dprintf(FS_NAME ": make_shflstring() failed\n"); 364 return B_NO_MEMORY; 365 } 366 367 vboxsf_vnode* new_vnode; 368 int rv = vboxsf_new_vnode(&volume->map, build_path(vnode, name1->String.utf8), name1, &new_vnode); 369 if (rv != B_OK) 370 { 371 dprintf(FS_NAME ": vboxsf_new_vnode() failed\n"); 372 return rv; 373 } 374 buffer->d_dev = 0; 375 buffer->d_pdev = 0; 376 buffer->d_ino = new_vnode->vnode; 377 buffer->d_pino = vnode->vnode; 378 buffer->d_reclen = sizeof(struct dirent) + cookie->buffer->name.u16Length; 379 strncpy(buffer->d_name, cookie->buffer->name.String.utf8, NAME_MAX); 380 381 size_t size = offsetof(SHFLDIRINFO, name.String) + cookie->buffer->name.u16Size; 382 cookie->buffer = ((void*)cookie->buffer + size); 383 cookie->index++; 384 385 if (cookie->index >= cookie->num_files) 386 { 387 // hit end of this buffer, next call will reallocate a new one 388 free(cookie->buffer_start); 389 cookie->buffer_start = cookie->buffer = NULL; 390 } 391 return B_OK; 392 } 393 353 394 354 395 status_t vboxsf_read_dir(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, 355 struct dirent* buffer, size_t bufferSize, uint32* _num) { 356 vboxsf_dir_cookie* cookie = _cookie; 357 vboxsf_volume* volume = _volume->private_volume; 358 vboxsf_vnode* vnode = _vnode->private_node; 359 uint32 num_read = 0; 360 status_t rv = B_OK; 361 362 for (num_read = 0; num_read < *_num && cookie->has_more_files; num_read++) { 363 rv = vboxsf_read_dir_1(volume, vnode, cookie, buffer, bufferSize); 364 if (rv == B_BUFFER_OVERFLOW || rv == B_ENTRY_NOT_FOUND) { 365 // hit end of at least one of the buffers - not really an error 366 rv = B_OK; 367 break; 368 } 369 bufferSize -= buffer->d_reclen; 370 buffer = ((void*)(buffer)) + buffer->d_reclen; 371 } 372 373 *_num = num_read; 374 return rv; 375 } 376 377 status_t vboxsf_free_dir_cookie(fs_volume* _volume, fs_vnode* vnode, void* _cookie) { 378 vboxsf_volume* volume = _volume->private_volume; 379 vboxsf_dir_cookie* cookie = _cookie; 380 381 vboxCallClose(&g_clientHandle, &volume->map, cookie->handle); 382 free(cookie->path); 383 free(cookie); 384 385 return B_OK; 386 } 387 388 status_t vboxsf_read_fs_info(fs_volume* _volume, struct fs_info* info) { 389 vboxsf_volume* volume = _volume->private_volume; 390 391 SHFLVOLINFO volume_info; 392 uint32_t bytes = sizeof(SHFLVOLINFO); 393 394 int rc = vboxCallFSInfo(&g_clientHandle, &volume->map, 0, 395 (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (PSHFLDIRINFO)&volume_info); 396 397 if (RT_FAILURE(rc)) { 398 dprintf(FS_NAME ": vboxCallFSInfo failed (%d)\n", rc); 399 return vbox_err_to_haiku_err(rc); 400 } 401 402 info->flags = B_FS_IS_PERSISTENT; 403 if (volume_info.fsProperties.fReadOnly) 404 info->flags |= B_FS_IS_READONLY; 405 406 info->dev = 0; 407 info->root = 1; 408 info->block_size = volume_info.ulBytesPerAllocationUnit; 409 info->io_size = volume_info.ulBytesPerAllocationUnit; 410 info->total_blocks = volume_info.ullTotalAllocationBytes / info->block_size; 411 info->free_blocks = volume_info.ullAvailableAllocationBytes / info->block_size; 412 info->total_nodes = LONGLONG_MAX; 413 info->free_nodes = LONGLONG_MAX; 414 strcpy(info->volume_name, "VBox share"); 415 return B_OK; 416 } 417 418 status_t vboxsf_lookup(fs_volume* _volume, fs_vnode* dir, const char* name, ino_t* _id) { 419 dprintf(FS_NAME ": lookup %s\n", name); 420 vboxsf_volume* volume = _volume->private_volume; 421 SHFLCREATEPARMS params; 422 423 RT_ZERO(params); 424 params.Handle = SHFL_HANDLE_NIL; 425 params.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 426 427 PSHFLSTRING path = build_path(dir->private_node, name); 428 if (!path) { 429 dprintf(FS_NAME ": make_shflstring() failed\n"); 430 return B_NO_MEMORY; 431 } 432 433 int rc = vboxCallCreate(&g_clientHandle, &volume->map, path, ¶ms); 434 if (RT_SUCCESS(rc)) { 435 if (params.Result == SHFL_FILE_EXISTS) { 436 vboxsf_vnode* vn; 437 status_t rv = vboxsf_new_vnode(&volume->map, path, path, &vn); 438 if (rv == B_OK) { 439 *_id = vn->vnode; 440 rv = publish_vnode(_volume, vn->vnode, vn, &vboxsf_vnode_ops, mode_from_fmode(params.Info.Attr.fMode), 0); 441 } 442 return rv; 443 } 444 else { 445 free(path); 446 return B_ENTRY_NOT_FOUND; 447 } 448 } 449 else { 450 free(path); 451 dprintf(FS_NAME ": vboxCallCreate: %d\n", rc); 452 return vbox_err_to_haiku_err(rc); 453 } 454 } 455 456 mode_t mode_from_fmode(RTFMODE fMode) { 457 mode_t m = 0; 458 459 if (RTFS_IS_DIRECTORY(fMode)) 460 m |= S_IFDIR; 461 else if (RTFS_IS_FILE(fMode)) 462 m |= S_IFREG; 463 else if (RTFS_IS_FIFO(fMode)) 464 m |= S_IFIFO; 465 else if (RTFS_IS_DEV_CHAR(fMode)) 466 m |= S_IFCHR; 467 else if (RTFS_IS_DEV_BLOCK(fMode)) 468 m |= S_IFBLK; 469 else if (RTFS_IS_SYMLINK(fMode)) 470 m |= S_IFLNK; 471 else if (RTFS_IS_SOCKET(fMode)) 472 m |= S_IFSOCK; 473 474 if (fMode & RTFS_UNIX_IRUSR) 475 m |= S_IRUSR; 476 if (fMode & RTFS_UNIX_IWUSR) 477 m |= S_IWUSR; 478 if (fMode & RTFS_UNIX_IXUSR) 479 m |= S_IXUSR; 480 if (fMode & RTFS_UNIX_IRGRP) 481 m |= S_IRGRP; 482 if (fMode & RTFS_UNIX_IWGRP) 483 m |= S_IWGRP; 484 if (fMode & RTFS_UNIX_IXGRP) 485 m |= S_IXGRP; 486 if (fMode & RTFS_UNIX_IROTH) 487 m |= S_IROTH; 488 if (fMode & RTFS_UNIX_IWOTH) 489 m |= S_IWOTH; 490 if (fMode & RTFS_UNIX_IXOTH) 491 m |= S_IXOTH; 492 if (fMode & RTFS_UNIX_ISUID) 493 m |= S_ISUID; 494 if (fMode & RTFS_UNIX_ISGID) 495 m |= S_ISGID; 496 if (fMode & RTFS_UNIX_ISTXT) 497 m |= S_ISVTX; 498 499 return m; 500 } 501 502 status_t vboxsf_open(fs_volume* _volume, fs_vnode* _vnode, int openMode, void** _cookie) { 503 vboxsf_volume* volume = _volume->private_volume; 504 vboxsf_vnode* vnode = _vnode->private_node; 505 506 dprintf(FS_NAME ": open %s (mode=%x)\n", vnode->path->String.utf8, openMode); 507 508 SHFLCREATEPARMS params; 509 510 RT_ZERO(params); 511 params.Handle = SHFL_HANDLE_NIL; 512 513 if (openMode & O_RDWR) 514 params.CreateFlags |= SHFL_CF_ACCESS_READWRITE; 515 else if (openMode & O_RDONLY) 516 params.CreateFlags |= SHFL_CF_ACCESS_READ; 517 else if (openMode & O_WRONLY) 518 params.CreateFlags |= SHFL_CF_ACCESS_WRITE; 519 520 if (openMode & O_APPEND) 521 params.CreateFlags |= SHFL_CF_ACCESS_APPEND; 522 523 if (openMode & O_CREAT) { 524 params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW; 525 if (openMode & O_EXCL) 526 params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS; 527 else if (openMode & O_TRUNC) 528 params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 529 else 530 params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 531 } 532 else { 533 params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; 534 if (openMode & O_TRUNC) 535 params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 536 else 537 params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 538 } 539 540 int rc = vboxCallCreate(&g_clientHandle, &volume->map, vnode->path, ¶ms); 541 if (!RT_SUCCESS(rc)) { 542 dprintf("vboxCallCreate returned %d\n", rc); 543 return vbox_err_to_haiku_err(rc); 544 } 545 546 vboxsf_file_cookie* cookie = malloc(sizeof(vboxsf_file_cookie)); 547 if (!cookie) { 548 dprintf("couldn't allocate file cookie\n"); 549 return B_NO_MEMORY; 550 } 551 552 cookie->handle = params.Handle; 553 cookie->path = vnode->path; 554 555 *_cookie = cookie; 556 557 return B_OK; 558 } 559 560 status_t vboxsf_create(fs_volume* _volume, fs_vnode* _dir, const char *name, int openMode, int perms, void **_cookie, ino_t *_newVnodeID) { 561 vboxsf_volume* volume = _volume->private_volume; 562 563 SHFLCREATEPARMS params; 564 565 RT_ZERO(params); 566 params.Handle = SHFL_HANDLE_NIL; 567 568 if (openMode & O_RDWR) 569 params.CreateFlags |= SHFL_CF_ACCESS_READWRITE; 570 else if (openMode & O_RDONLY) 571 params.CreateFlags |= SHFL_CF_ACCESS_READ; 572 else if (openMode & O_WRONLY) 573 params.CreateFlags |= SHFL_CF_ACCESS_WRITE; 574 575 if (openMode & O_APPEND) 576 params.CreateFlags |= SHFL_CF_ACCESS_APPEND; 577 578 if (openMode & O_CREAT) { 579 params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW; 580 if (openMode & O_EXCL) 581 params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS; 582 else if (openMode & O_TRUNC) 583 params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 584 else 585 params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 586 } 587 else { 588 params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; 589 if (openMode & O_TRUNC) 590 params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 591 else 592 params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 593 } 594 595 PSHFLSTRING path = build_path(_dir->private_node, name); 596 int rc = vboxCallCreate(&g_clientHandle, &volume->map, path, ¶ms); 597 598 if (!RT_SUCCESS(rc)) { 599 dprintf("vboxCallCreate returned %d\n", rc); 600 free(path); 601 return vbox_err_to_haiku_err(rc); 602 } 603 604 vboxsf_file_cookie* cookie = malloc(sizeof(vboxsf_file_cookie)); 605 if (!cookie) { 606 dprintf("couldn't allocate file cookie\n"); 607 free(path); 608 return B_NO_MEMORY; 609 } 610 611 cookie->handle = params.Handle; 612 cookie->path = path; 613 614 *_cookie = cookie; 615 return vboxsf_lookup(_volume, _dir, name, _newVnodeID); 616 } 617 618 status_t vboxsf_close(fs_volume* _volume, fs_vnode* _vnode, void* _cookie) { 619 vboxsf_volume* volume = _volume->private_volume; 620 vboxsf_file_cookie* cookie = _cookie; 621 622 int rc = vboxCallClose(&g_clientHandle, &volume->map, cookie->handle); 623 dprintf("vboxCallClose returned %d\n", rc); 624 return vbox_err_to_haiku_err(rc); 625 } 626 627 status_t vboxsf_rewind_dir(fs_volume* _volume, fs_vnode* _vnode, void* _cookie) { 628 vboxsf_dir_cookie* cookie = _cookie; 629 cookie->index = 0; 630 return B_OK; 631 } 632 633 status_t vboxsf_close_dir(fs_volume *volume, fs_vnode *vnode, void *cookie) { 634 return B_OK; 635 } 636 637 status_t vboxsf_free_cookie(fs_volume *volume, fs_vnode *vnode, void *_cookie) { 638 vboxsf_dir_cookie* cookie = _cookie; 639 free(cookie); 640 return B_OK; 641 } 642 643 status_t vboxsf_read(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, off_t pos, void *buffer, size_t *length) { 644 vboxsf_volume* volume = _volume->private_volume; 645 vboxsf_vnode* vnode = _vnode->private_node; 646 vboxsf_file_cookie* cookie = _cookie; 647 648 if (*length > 0xFFFFFFFF) { 649 *length = 0xFFFFFFFF; 650 } 651 652 uint32_t l = *length; 653 void* other_buffer = malloc(l); // TODO map the user memory into kernel space here for efficiency 654 int rc = vboxCallRead(&g_clientHandle, &volume->map, cookie->handle, pos, &l, other_buffer, false); 655 memcpy(buffer, other_buffer, l); 656 free(other_buffer); 657 658 dprintf("vboxCallRead returned %d\n", rc); 659 *length = l; 660 return vbox_err_to_haiku_err(rc); 661 } 662 663 status_t vboxsf_write(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, off_t pos, const void *buffer, size_t *length) { 664 vboxsf_volume* volume = _volume->private_volume; 665 vboxsf_vnode* vnode = _vnode->private_node; 666 vboxsf_file_cookie* cookie = _cookie; 667 668 if (*length > 0xFFFFFFFF) { 669 *length = 0xFFFFFFFF; 670 } 671 672 uint32_t l = *length; 673 void* other_buffer = malloc(l); // TODO map the user memory into kernel space here for efficiency 674 memcpy(other_buffer, buffer, l); 675 int rc = vboxCallWrite(&g_clientHandle, &volume->map, cookie->handle, pos, &l, other_buffer, false); 676 free(other_buffer); 677 678 *length = l; 679 return vbox_err_to_haiku_err(rc); 680 } 681 682 status_t vboxsf_write_stat(fs_volume *volume, fs_vnode *vnode, const struct stat *stat, uint32 statMask) { 683 // the host handles updating the stat info - in the guest, this is a no-op 684 return B_OK; 685 } 686 687 status_t vboxsf_create_dir(fs_volume *_volume, fs_vnode *parent, const char *name, int perms) { 688 vboxsf_volume* volume = _volume->private_volume; 689 690 SHFLCREATEPARMS params; 691 params.Handle = 0; 692 params.Info.cbObject = 0; 693 params.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_CREATE_IF_NEW | 694 SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACCESS_READ; 695 696 PSHFLSTRING path = build_path(parent->private_node, name); 697 int rc = vboxCallCreate(&g_clientHandle, &volume->map, path, ¶ms); 698 free(path); 699 if (params.Handle == SHFL_HANDLE_NIL) { 700 return vbox_err_to_haiku_err(rc); 701 } 702 else { 703 vboxCallClose(&g_clientHandle, &volume->map, params.Handle); 704 return B_OK; 705 } 706 } 707 708 status_t vboxsf_remove_dir(fs_volume *_volume, fs_vnode *parent, const char *name) { 709 vboxsf_volume* volume = _volume->private_volume; 710 711 PSHFLSTRING path = build_path(parent->private_node, name); 712 int rc = vboxCallRemove(&g_clientHandle, &volume->map, path, SHFL_REMOVE_DIR); 713 free(path); 714 715 return vbox_err_to_haiku_err(rc); 716 } 717 718 status_t vboxsf_unlink(fs_volume *_volume, fs_vnode *parent, const char *name) { 719 vboxsf_volume* volume = _volume->private_volume; 720 721 PSHFLSTRING path = build_path(parent->private_node, name); 722 int rc = vboxCallRemove(&g_clientHandle, &volume->map, path, SHFL_REMOVE_FILE); 723 free(path); 724 725 return vbox_err_to_haiku_err(rc); 726 } 727 728 status_t vboxsf_link(fs_volume *volume, fs_vnode *dir, const char *name, fs_vnode *vnode) { 729 return B_UNSUPPORTED; 730 } 731 732 status_t vboxsf_rename(fs_volume* _volume, fs_vnode* fromDir, const char* fromName, fs_vnode* toDir, const char* toName) { 733 vboxsf_volume* volume = _volume->private_volume; 734 735 PSHFLSTRING oldpath = build_path(fromDir->private_node, fromName); 736 PSHFLSTRING newpath = build_path(toDir->private_node, toName); 737 int rc = vboxCallRename(&g_clientHandle, &volume->map, oldpath, newpath, SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS); 738 free(oldpath); 739 free(newpath); 740 741 return vbox_err_to_haiku_err(rc); 742 } 743 744 status_t vboxsf_create_symlink(fs_volume* _volume, fs_vnode* dir, const char* name, const char* path, int mode) { 745 vboxsf_volume* volume = _volume->private_volume; 746 747 PSHFLSTRING target = make_shflstring(path); 748 PSHFLSTRING linkpath = build_path(dir->private_node, name); 749 SHFLFSOBJINFO stuff; 750 RT_ZERO(stuff); 751 752 int rc = vboxCallSymlink(&g_clientHandle, &volume->map, linkpath, target, &stuff); 753 754 free(target); 755 free(linkpath); 756 757 return vbox_err_to_haiku_err(rc); 758 } 759 760 status_t vboxsf_read_symlink(fs_volume* _volume, fs_vnode* link, char* buffer, size_t* _bufferSize) { 761 vboxsf_volume* volume = _volume->private_volume; 762 vboxsf_vnode* vnode = link->private_node; 763 764 int rc = vboxReadLink(&g_clientHandle, &volume->map, vnode->path, *_bufferSize, buffer); 765 *_bufferSize = strlen(buffer); 766 767 return vbox_err_to_haiku_err(rc); 768 } 396 struct dirent* buffer, size_t bufferSize, uint32* _num) 397 { 398 vboxsf_dir_cookie* cookie = _cookie; 399 vboxsf_volume* volume = _volume->private_volume; 400 vboxsf_vnode* vnode = _vnode->private_node; 401 uint32 num_read = 0; 402 status_t rv = B_OK; 403 404 for (num_read = 0; num_read < *_num && cookie->has_more_files; num_read++) 405 { 406 rv = vboxsf_read_dir_1(volume, vnode, cookie, buffer, bufferSize); 407 if (rv == B_BUFFER_OVERFLOW || rv == B_ENTRY_NOT_FOUND) 408 { 409 // hit end of at least one of the buffers - not really an error 410 rv = B_OK; 411 break; 412 } 413 bufferSize -= buffer->d_reclen; 414 buffer = ((void*)(buffer)) + buffer->d_reclen; 415 } 416 417 *_num = num_read; 418 return rv; 419 } 420 421 422 status_t vboxsf_free_dir_cookie(fs_volume* _volume, fs_vnode* vnode, void* _cookie) 423 { 424 vboxsf_volume* volume = _volume->private_volume; 425 vboxsf_dir_cookie* cookie = _cookie; 426 427 vboxCallClose(&g_clientHandle, &volume->map, cookie->handle); 428 free(cookie->path); 429 free(cookie); 430 431 return B_OK; 432 } 433 434 435 status_t vboxsf_read_fs_info(fs_volume* _volume, struct fs_info* info) 436 { 437 vboxsf_volume* volume = _volume->private_volume; 438 439 SHFLVOLINFO volume_info; 440 uint32_t bytes = sizeof(SHFLVOLINFO); 441 442 int rc = vboxCallFSInfo(&g_clientHandle, &volume->map, 0, 443 (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (PSHFLDIRINFO)&volume_info); 444 445 if (RT_FAILURE(rc)) 446 { 447 dprintf(FS_NAME ": vboxCallFSInfo failed (%d)\n", rc); 448 return vbox_err_to_haiku_err(rc); 449 } 450 451 info->flags = B_FS_IS_PERSISTENT; 452 if (volume_info.fsProperties.fReadOnly) 453 info->flags |= B_FS_IS_READONLY; 454 455 info->dev = 0; 456 info->root = 1; 457 info->block_size = volume_info.ulBytesPerAllocationUnit; 458 info->io_size = volume_info.ulBytesPerAllocationUnit; 459 info->total_blocks = volume_info.ullTotalAllocationBytes / info->block_size; 460 info->free_blocks = volume_info.ullAvailableAllocationBytes / info->block_size; 461 info->total_nodes = LONGLONG_MAX; 462 info->free_nodes = LONGLONG_MAX; 463 strcpy(info->volume_name, "VBox share"); 464 return B_OK; 465 } 466 467 468 status_t vboxsf_lookup(fs_volume* _volume, fs_vnode* dir, const char* name, ino_t* _id) 469 { 470 dprintf(FS_NAME ": lookup %s\n", name); 471 vboxsf_volume* volume = _volume->private_volume; 472 SHFLCREATEPARMS params; 473 474 RT_ZERO(params); 475 params.Handle = SHFL_HANDLE_NIL; 476 params.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 477 478 PSHFLSTRING path = build_path(dir->private_node, name); 479 if (!path) 480 { 481 dprintf(FS_NAME ": make_shflstring() failed\n"); 482 return B_NO_MEMORY; 483 } 484 485 int rc = vboxCallCreate(&g_clientHandle, &volume->map, path, ¶ms); 486 if (RT_SUCCESS(rc)) 487 { 488 if (params.Result == SHFL_FILE_EXISTS) 489 { 490 vboxsf_vnode* vn; 491 status_t rv = vboxsf_new_vnode(&volume->map, path, path, &vn); 492 if (rv == B_OK) 493 { 494 *_id = vn->vnode; 495 rv = publish_vnode(_volume, vn->vnode, vn, &vboxsf_vnode_ops, mode_from_fmode(params.Info.Attr.fMode), 0); 496 } 497 return rv; 498 } 499 else 500 { 501 free(path); 502 return B_ENTRY_NOT_FOUND; 503 } 504 } 505 else 506 { 507 free(path); 508 dprintf(FS_NAME ": vboxCallCreate: %d\n", rc); 509 return vbox_err_to_haiku_err(rc); 510 } 511 } 512 513 514 mode_t mode_from_fmode(RTFMODE fMode) 515 { 516 mode_t m = 0; 517 518 if (RTFS_IS_DIRECTORY(fMode)) 519 m |= S_IFDIR; 520 else if (RTFS_IS_FILE(fMode)) 521 m |= S_IFREG; 522 else if (RTFS_IS_FIFO(fMode)) 523 m |= S_IFIFO; 524 else if (RTFS_IS_DEV_CHAR(fMode)) 525 m |= S_IFCHR; 526 else if (RTFS_IS_DEV_BLOCK(fMode)) 527 m |= S_IFBLK; 528 else if (RTFS_IS_SYMLINK(fMode)) 529 m |= S_IFLNK; 530 else if (RTFS_IS_SOCKET(fMode)) 531 m |= S_IFSOCK; 532 533 if (fMode & RTFS_UNIX_IRUSR) 534 m |= S_IRUSR; 535 if (fMode & RTFS_UNIX_IWUSR) 536 m |= S_IWUSR; 537 if (fMode & RTFS_UNIX_IXUSR) 538 m |= S_IXUSR; 539 if (fMode & RTFS_UNIX_IRGRP) 540 m |= S_IRGRP; 541 if (fMode & RTFS_UNIX_IWGRP) 542 m |= S_IWGRP; 543 if (fMode & RTFS_UNIX_IXGRP) 544 m |= S_IXGRP; 545 if (fMode & RTFS_UNIX_IROTH) 546 m |= S_IROTH; 547 if (fMode & RTFS_UNIX_IWOTH) 548 m |= S_IWOTH; 549 if (fMode & RTFS_UNIX_IXOTH) 550 m |= S_IXOTH; 551 if (fMode & RTFS_UNIX_ISUID) 552 m |= S_ISUID; 553 if (fMode & RTFS_UNIX_ISGID) 554 m |= S_ISGID; 555 if (fMode & RTFS_UNIX_ISTXT) 556 m |= S_ISVTX; 557 558 return m; 559 } 560 561 562 status_t vboxsf_open(fs_volume* _volume, fs_vnode* _vnode, int openMode, void** _cookie) 563 { 564 vboxsf_volume* volume = _volume->private_volume; 565 vboxsf_vnode* vnode = _vnode->private_node; 566 567 dprintf(FS_NAME ": open %s (mode=%x)\n", vnode->path->String.utf8, openMode); 568 569 SHFLCREATEPARMS params; 570 571 RT_ZERO(params); 572 params.Handle = SHFL_HANDLE_NIL; 573 574 if (openMode & O_RDWR) 575 params.CreateFlags |= SHFL_CF_ACCESS_READWRITE; 576 else if (openMode & O_RDONLY) 577 params.CreateFlags |= SHFL_CF_ACCESS_READ; 578 else if (openMode & O_WRONLY) 579 params.CreateFlags |= SHFL_CF_ACCESS_WRITE; 580 581 if (openMode & O_APPEND) 582 params.CreateFlags |= SHFL_CF_ACCESS_APPEND; 583 584 if (openMode & O_CREAT) 585 { 586 params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW; 587 if (openMode & O_EXCL) 588 params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS; 589 else if (openMode & O_TRUNC) 590 params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 591 else 592 params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 593 } 594 else 595 { 596 params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; 597 if (openMode & O_TRUNC) 598 params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 599 else 600 params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 601 } 602 603 int rc = vboxCallCreate(&g_clientHandle, &volume->map, vnode->path, ¶ms); 604 if (!RT_SUCCESS(rc)) 605 { 606 dprintf("vboxCallCreate returned %d\n", rc); 607 return vbox_err_to_haiku_err(rc); 608 } 609 610 vboxsf_file_cookie* cookie = malloc(sizeof(vboxsf_file_cookie)); 611 if (!cookie) 612 { 613 dprintf("couldn't allocate file cookie\n"); 614 return B_NO_MEMORY; 615 } 616 617 cookie->handle = params.Handle; 618 cookie->path = vnode->path; 619 620 *_cookie = cookie; 621 622 return B_OK; 623 } 624 625 626 status_t vboxsf_create(fs_volume* _volume, fs_vnode* _dir, const char *name, int openMode, int perms, void **_cookie, ino_t *_newVnodeID) 627 { 628 vboxsf_volume* volume = _volume->private_volume; 629 630 SHFLCREATEPARMS params; 631 632 RT_ZERO(params); 633 params.Handle = SHFL_HANDLE_NIL; 634 635 if (openMode & O_RDWR) 636 params.CreateFlags |= SHFL_CF_ACCESS_READWRITE; 637 else if (openMode & O_RDONLY) 638 params.CreateFlags |= SHFL_CF_ACCESS_READ; 639 else if (openMode & O_WRONLY) 640 params.CreateFlags |= SHFL_CF_ACCESS_WRITE; 641 642 if (openMode & O_APPEND) 643 params.CreateFlags |= SHFL_CF_ACCESS_APPEND; 644 645 if (openMode & O_CREAT) 646 { 647 params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW; 648 if (openMode & O_EXCL) 649 params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS; 650 else if (openMode & O_TRUNC) 651 params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 652 else 653 params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 654 } 655 else 656 { 657 params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; 658 if (openMode & O_TRUNC) 659 params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 660 else 661 params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 662 } 663 664 PSHFLSTRING path = build_path(_dir->private_node, name); 665 int rc = vboxCallCreate(&g_clientHandle, &volume->map, path, ¶ms); 666 667 if (!RT_SUCCESS(rc)) 668 { 669 dprintf("vboxCallCreate returned %d\n", rc); 670 free(path); 671 return vbox_err_to_haiku_err(rc); 672 } 673 674 vboxsf_file_cookie* cookie = malloc(sizeof(vboxsf_file_cookie)); 675 if (!cookie) 676 { 677 dprintf("couldn't allocate file cookie\n"); 678 free(path); 679 return B_NO_MEMORY; 680 } 681 682 cookie->handle = params.Handle; 683 cookie->path = path; 684 685 *_cookie = cookie; 686 return vboxsf_lookup(_volume, _dir, name, _newVnodeID); 687 } 688 689 690 status_t vboxsf_close(fs_volume* _volume, fs_vnode* _vnode, void* _cookie) 691 { 692 vboxsf_volume* volume = _volume->private_volume; 693 vboxsf_file_cookie* cookie = _cookie; 694 695 int rc = vboxCallClose(&g_clientHandle, &volume->map, cookie->handle); 696 dprintf("vboxCallClose returned %d\n", rc); 697 return vbox_err_to_haiku_err(rc); 698 } 699 700 701 status_t vboxsf_rewind_dir(fs_volume* _volume, fs_vnode* _vnode, void* _cookie) 702 { 703 vboxsf_dir_cookie* cookie = _cookie; 704 cookie->index = 0; 705 return B_OK; 706 } 707 708 709 status_t vboxsf_close_dir(fs_volume *volume, fs_vnode *vnode, void *cookie) 710 { 711 return B_OK; 712 } 713 714 715 status_t vboxsf_free_cookie(fs_volume *volume, fs_vnode *vnode, void *_cookie) 716 { 717 vboxsf_dir_cookie* cookie = _cookie; 718 free(cookie); 719 return B_OK; 720 } 721 722 status_t vboxsf_read(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, off_t pos, void *buffer, size_t *length) 723 { 724 vboxsf_volume* volume = _volume->private_volume; 725 vboxsf_vnode* vnode = _vnode->private_node; 726 vboxsf_file_cookie* cookie = _cookie; 727 728 if (*length > 0xFFFFFFFF) 729 *length = 0xFFFFFFFF; 730 731 uint32_t l = *length; 732 void* other_buffer = malloc(l); // TODO map the user memory into kernel space here for efficiency 733 int rc = vboxCallRead(&g_clientHandle, &volume->map, cookie->handle, pos, &l, other_buffer, false); 734 memcpy(buffer, other_buffer, l); 735 free(other_buffer); 736 737 dprintf("vboxCallRead returned %d\n", rc); 738 *length = l; 739 return vbox_err_to_haiku_err(rc); 740 } 741 742 743 status_t vboxsf_write(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, off_t pos, const void *buffer, size_t *length) 744 { 745 vboxsf_volume* volume = _volume->private_volume; 746 vboxsf_vnode* vnode = _vnode->private_node; 747 vboxsf_file_cookie* cookie = _cookie; 748 749 if (*length > 0xFFFFFFFF) 750 *length = 0xFFFFFFFF; 751 752 uint32_t l = *length; 753 void* other_buffer = malloc(l); // TODO map the user memory into kernel space here for efficiency 754 memcpy(other_buffer, buffer, l); 755 int rc = vboxCallWrite(&g_clientHandle, &volume->map, cookie->handle, pos, &l, other_buffer, false); 756 free(other_buffer); 757 758 *length = l; 759 return vbox_err_to_haiku_err(rc); 760 } 761 762 763 status_t vboxsf_write_stat(fs_volume *volume, fs_vnode *vnode, const struct stat *stat, uint32 statMask) 764 { 765 // the host handles updating the stat info - in the guest, this is a no-op 766 return B_OK; 767 } 768 769 770 status_t vboxsf_create_dir(fs_volume *_volume, fs_vnode *parent, const char *name, int perms) 771 { 772 vboxsf_volume* volume = _volume->private_volume; 773 774 SHFLCREATEPARMS params; 775 params.Handle = 0; 776 params.Info.cbObject = 0; 777 params.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_CREATE_IF_NEW | 778 SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACCESS_READ; 779 780 PSHFLSTRING path = build_path(parent->private_node, name); 781 int rc = vboxCallCreate(&g_clientHandle, &volume->map, path, ¶ms); 782 free(path); 783 if (params.Handle == SHFL_HANDLE_NIL) 784 return vbox_err_to_haiku_err(rc); 785 else 786 { 787 vboxCallClose(&g_clientHandle, &volume->map, params.Handle); 788 return B_OK; 789 } 790 } 791 792 793 status_t vboxsf_remove_dir(fs_volume *_volume, fs_vnode *parent, const char *name) 794 { 795 vboxsf_volume* volume = _volume->private_volume; 796 797 PSHFLSTRING path = build_path(parent->private_node, name); 798 int rc = vboxCallRemove(&g_clientHandle, &volume->map, path, SHFL_REMOVE_DIR); 799 free(path); 800 801 return vbox_err_to_haiku_err(rc); 802 } 803 804 805 status_t vboxsf_unlink(fs_volume *_volume, fs_vnode *parent, const char *name) 806 { 807 vboxsf_volume* volume = _volume->private_volume; 808 809 PSHFLSTRING path = build_path(parent->private_node, name); 810 int rc = vboxCallRemove(&g_clientHandle, &volume->map, path, SHFL_REMOVE_FILE); 811 free(path); 812 813 return vbox_err_to_haiku_err(rc); 814 } 815 816 status_t vboxsf_link(fs_volume *volume, fs_vnode *dir, const char *name, fs_vnode *vnode) 817 { 818 return B_UNSUPPORTED; 819 } 820 821 822 status_t vboxsf_rename(fs_volume* _volume, fs_vnode* fromDir, const char* fromName, fs_vnode* toDir, const char* toName) 823 { 824 vboxsf_volume* volume = _volume->private_volume; 825 826 PSHFLSTRING oldpath = build_path(fromDir->private_node, fromName); 827 PSHFLSTRING newpath = build_path(toDir->private_node, toName); 828 int rc = vboxCallRename(&g_clientHandle, &volume->map, oldpath, newpath, SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS); 829 free(oldpath); 830 free(newpath); 831 832 return vbox_err_to_haiku_err(rc); 833 } 834 835 836 status_t vboxsf_create_symlink(fs_volume* _volume, fs_vnode* dir, const char* name, const char* path, int mode) 837 { 838 vboxsf_volume* volume = _volume->private_volume; 839 840 PSHFLSTRING target = make_shflstring(path); 841 PSHFLSTRING linkpath = build_path(dir->private_node, name); 842 SHFLFSOBJINFO stuff; 843 RT_ZERO(stuff); 844 845 int rc = vboxCallSymlink(&g_clientHandle, &volume->map, linkpath, target, &stuff); 846 847 free(target); 848 free(linkpath); 849 850 return vbox_err_to_haiku_err(rc); 851 } 852 853 854 status_t vboxsf_read_symlink(fs_volume* _volume, fs_vnode* link, char* buffer, size_t* _bufferSize) 855 { 856 vboxsf_volume* volume = _volume->private_volume; 857 vboxsf_vnode* vnode = link->private_node; 858 859 int rc = vboxReadLink(&g_clientHandle, &volume->map, vnode->path, *_bufferSize, buffer); 860 *_bufferSize = strlen(buffer); 861 862 return vbox_err_to_haiku_err(rc); 863 } 864 769 865 770 866 // TODO move this into the runtime 771 status_t vbox_err_to_haiku_err(int rc) {772 switch (rc){773 case VINF_SUCCESS: return B_OK; 774 case VERR_INVALID_POINTER: return B_BAD_ADDRESS;775 case VERR_INVALID_PARAMETER: return B_BAD_VALUE;776 case VERR_PERMISSION_DENIED: return B_PERMISSION_DENIED;777 case VERR_NOT_IMPLEMENTED: return B_UNSUPPORTED;778 case VERR_FILE_NOT_FOUND: return B_ENTRY_NOT_FOUND;779 780 case SHFL_FILE_EXISTS: return B_FILE_EXISTS; 781 case SHFL_PATH_NOT_FOUND: 782 case SHFL_FILE_NOT_FOUND: return B_ENTRY_NOT_FOUND; 783 784 default: return B_ERROR; 785 } 786 }787 788 static status_t std_ops(int32 op, ...) { 789 switch(op) { 790 case B_MODULE_INIT: 791 dprintf(MODULE_NAME ": B_MODULE_INIT\n"); 792 return init_module(); 793 case B_MODULE_UNINIT: 794 dprintf(MODULE_NAME ": B_MODULE_UNINIT\n"); 795 uninit_module();796 return B_OK;797 default:798 return B_ERROR;799 } 800 } 801 802 static fs_volume_ops vboxsf_volume_ops = { 803 unmount, 804 805 vboxsf_read_fs_info, // read_fs_info 806 NULL, // write_fs_info 807 NULL, // sync 808 809 vboxsf_get_vnode, // get_vnode 810 811 NULL, // open_index_dir 812 NULL, // close_index_dir 813 NULL, // free_index_dir_cookie814 NULL, // read_index_dir815 NULL, // rewind_index_dir816 817 NULL, // create_index 818 NULL, // remove_index 819 NULL, // read_index_stat 820 821 NULL, // open_query 822 NULL, // close_query823 NULL, // free_query_cookie 824 NULL, // read_query 825 NULL, // rewind_query826 827 828 829 867 status_t vbox_err_to_haiku_err(int rc) 868 { 869 switch (rc) { 870 case VINF_SUCCESS: return B_OK; 871 case VERR_INVALID_POINTER: return B_BAD_ADDRESS; 872 case VERR_INVALID_PARAMETER: return B_BAD_VALUE; 873 case VERR_PERMISSION_DENIED: return B_PERMISSION_DENIED; 874 case VERR_NOT_IMPLEMENTED: return B_UNSUPPORTED; 875 case VERR_FILE_NOT_FOUND: return B_ENTRY_NOT_FOUND; 876 877 case SHFL_FILE_EXISTS: return B_FILE_EXISTS; 878 case SHFL_PATH_NOT_FOUND: 879 case SHFL_FILE_NOT_FOUND: return B_ENTRY_NOT_FOUND; 880 881 default: return B_ERROR; 882 } 883 } 884 885 886 static status_t std_ops(int32 op, ...) 887 { 888 switch(op) 889 { 890 case B_MODULE_INIT: 891 dprintf(MODULE_NAME ": B_MODULE_INIT\n"); 892 return init_module(); 893 case B_MODULE_UNINIT: 894 dprintf(MODULE_NAME ": B_MODULE_UNINIT\n"); 895 uninit_module(); 896 return B_OK; 897 default: 898 return B_ERROR; 899 } 900 } 901 902 903 static fs_volume_ops vboxsf_volume_ops = 904 { 905 unmount, 906 vboxsf_read_fs_info, // read_fs_info 907 NULL, // write_fs_info 908 NULL, // sync 909 vboxsf_get_vnode, // get_vnode 910 NULL, // open_index_dir 911 NULL, // close_index_dir 912 NULL, // free_index_dir_cookie 913 NULL, // read_index_dir 914 NULL, // rewind_index_dir 915 NULL, // create_index 916 NULL, // remove_index 917 NULL, // read_index_stat 918 NULL, // open_query 919 NULL, // close_query 920 NULL, // free_query_cookie 921 NULL, // read_query 922 NULL, // rewind_query 923 NULL, // all_layers_mounted 924 NULL, // create_sub_vnode 925 NULL, // delete_sub_vnode 830 926 }; 831 927 832 static fs_vnode_ops vboxsf_vnode_ops = { 833 vboxsf_lookup, // lookup 834 NULL, // get_vnode_name 835 vboxsf_put_vnode, // put_vnode 836 NULL, // remove_vnode 837 NULL, // can_page 838 NULL, // read_pages 839 NULL, // write_pages 840 NULL, // io 841 NULL, // cancel_io 842 NULL, // get_file_map 843 NULL, // ioctl 844 NULL, // set_flags 845 NULL, // select 846 NULL, // deselect 847 NULL, // fsync 848 vboxsf_read_symlink, // read_symlink 849 vboxsf_create_symlink, // create_symlink 850 vboxsf_link, // link 851 vboxsf_unlink, // unlink 852 vboxsf_rename, // rename 853 NULL, // access 854 vboxsf_read_stat, // read_stat 855 vboxsf_write_stat, // write_stat 856 NULL, // preallocate 857 vboxsf_create, // create 858 vboxsf_open, // open 859 vboxsf_close, // close 860 vboxsf_free_cookie, // free_cookie 861 vboxsf_read, // read 862 vboxsf_write, // write 863 vboxsf_create_dir, // create_dir 864 vboxsf_remove_dir, // remove_dir 865 vboxsf_open_dir, // open_dir 866 vboxsf_close_dir, // close_dir 867 vboxsf_free_dir_cookie, // free_dir_cookie 868 vboxsf_read_dir, // read_dir 869 vboxsf_rewind_dir, // rewind_dir 870 NULL, // open_attr_dir 871 NULL, // close_attr_dir 872 NULL, // free_attr_dir_cookie 873 NULL, // read_attr_dir 874 NULL, // rewind_attr_dir 875 NULL, // create_attr 876 NULL, // open_attr 877 NULL, // close_attr 878 NULL, // free_attr_cookie 879 NULL, // read_attr 880 NULL, // write_attr 881 NULL, // read_attr_stat 882 NULL, // write_attr_stat 883 NULL, // rename_attr 884 NULL, // remove_attr 885 NULL, // create_special_node 886 NULL, // get_super_vnode 928 static fs_vnode_ops vboxsf_vnode_ops = 929 { 930 vboxsf_lookup, // lookup 931 NULL, // get_vnode_name 932 vboxsf_put_vnode, // put_vnode 933 NULL, // remove_vnode 934 NULL, // can_page 935 NULL, // read_pages 936 NULL, // write_pages 937 NULL, // io 938 NULL, // cancel_io 939 NULL, // get_file_map 940 NULL, // ioctl 941 NULL, // set_flags 942 NULL, // select 943 NULL, // deselect 944 NULL, // fsync 945 vboxsf_read_symlink, // read_symlink 946 vboxsf_create_symlink, // create_symlink 947 vboxsf_link, // link 948 vboxsf_unlink, // unlink 949 vboxsf_rename, // rename 950 NULL, // access 951 vboxsf_read_stat, // read_stat 952 vboxsf_write_stat, // write_stat 953 NULL, // preallocate 954 vboxsf_create, // create 955 vboxsf_open, // open 956 vboxsf_close, // close 957 vboxsf_free_cookie, // free_cookie 958 vboxsf_read, // read 959 vboxsf_write, // write 960 vboxsf_create_dir, // create_dir 961 vboxsf_remove_dir, // remove_dir 962 vboxsf_open_dir, // open_dir 963 vboxsf_close_dir, // close_dir 964 vboxsf_free_dir_cookie, // free_dir_cookie 965 vboxsf_read_dir, // read_dir 966 vboxsf_rewind_dir, // rewind_dir 967 NULL, // open_attr_dir 968 NULL, // close_attr_dir 969 NULL, // free_attr_dir_cookie 970 NULL, // read_attr_dir 971 NULL, // rewind_attr_dir 972 NULL, // create_attr 973 NULL, // open_attr 974 NULL, // close_attr 975 NULL, // free_attr_cookie 976 NULL, // read_attr 977 NULL, // write_attr 978 NULL, // read_attr_stat 979 NULL, // write_attr_stat 980 NULL, // rename_attr 981 NULL, // remove_attr 982 NULL, // create_special_node 983 NULL, // get_super_vnode 887 984 }; 888 985 889 static file_system_module_info sVBoxSharedFileSystem = { 890 { 891 MODULE_NAME B_CURRENT_FS_API_VERSION, 892 0, 893 std_ops, 894 }, 895 896 FS_NAME, // short_name 897 "VirtualBox shared folders", // pretty_name 898 0, //B_DISK_SYSTEM_SUPPORTS_WRITING, // DDM flags 899 900 // scanning 901 NULL, // identify_partition 902 NULL, // scan_partition 903 NULL, // free_identify_partition_cookie 904 NULL, // free_partition_content_cookie() 905 906 mount, 986 static file_system_module_info sVBoxSharedFileSystem = 987 { 988 { 989 MODULE_NAME B_CURRENT_FS_API_VERSION, 990 0, 991 std_ops, 992 }, 993 FS_NAME, // short_name 994 "VirtualBox shared folders", // pretty_name 995 0, //B_DISK_SYSTEM_SUPPORTS_WRITING, // DDM flags 996 // scanning 997 NULL, // identify_partition 998 NULL, // scan_partition 999 NULL, // free_identify_partition_cookie 1000 NULL, // free_partition_content_cookie() 1001 mount, 907 1002 }; 908 1003 909 module_info *modules[] = { 910 (module_info *)&sVBoxSharedFileSystem, 911 NULL, 1004 module_info *modules[] = 1005 { 1006 (module_info *)&sVBoxSharedFileSystem, 1007 NULL, 912 1008 }; 1009 -
trunk/src/VBox/Additions/haiku/SharedFolders/vboxsf.h
r43363 r43364 57 57 #include "lock.h" 58 58 59 typedef struct vboxsf_volume { 60 VBSFMAP map; 61 ino_t rootid; 59 typedef struct vboxsf_volume 60 { 61 VBSFMAP map; 62 ino_t rootid; 62 63 } vboxsf_volume; 63 64 64 typedef struct vboxsf_vnode {65 PVBSFMAP map; 66 PSHFLSTRING name;67 PSHFLSTRING path;68 69 70 65 typedef struct vboxsf_vnode 66 { 67 PVBSFMAP map; 68 PSHFLSTRING name; 69 PSHFLSTRING path; 70 ino_t vnode; 71 struct vboxsf_vnode* next; 71 72 } vboxsf_vnode; 72 73 73 typedef struct vboxsf_dir_cookie { 74 SHFLHANDLE handle; 75 PSHFLSTRING path; 76 uint32_t index; 77 bool has_more_files; 78 PSHFLDIRINFO buffer_start, buffer; 79 uint32_t buffer_length, num_files; 74 typedef struct vboxsf_dir_cookie 75 { 76 SHFLHANDLE handle; 77 PSHFLSTRING path; 78 uint32_t index; 79 bool has_more_files; 80 PSHFLDIRINFO buffer_start, buffer; 81 uint32_t buffer_length, num_files; 80 82 } vboxsf_dir_cookie; 81 83 82 typedef struct vboxsf_file_cookie { 83 SHFLHANDLE handle; 84 PSHFLSTRING path; 84 typedef struct vboxsf_file_cookie 85 { 86 SHFLHANDLE handle; 87 PSHFLSTRING path; 85 88 } vboxsf_file_cookie; 86 89 … … 100 103 101 104 #endif 105 -
trunk/src/VBox/Additions/haiku/SharedFolders/vnode_cache.cpp
r43363 r43364 47 47 #include "OpenHashTable.h" 48 48 49 struct HashTableDefinition { 50 typedef uint32 KeyType; 51 typedef vboxsf_vnode ValueType; 49 struct HashTableDefinition 50 { 51 typedef uint32 KeyType; 52 typedef vboxsf_vnode ValueType; 52 53 53 54 55 56 54 size_t HashKey(uint32 key) const 55 { 56 return key; 57 } 57 58 58 59 60 61 59 size_t Hash(vboxsf_vnode* value) const 60 { 61 return HashKey(value->vnode); 62 } 62 63 63 64 65 66 64 bool Compare(uint32 key, vboxsf_vnode* value) const 65 { 66 return value->vnode == key; 67 } 67 68 68 69 70 71 69 vboxsf_vnode*& GetLink(vboxsf_vnode* value) const 70 { 71 return value->next; 72 } 72 73 }; 73 74 … … 76 77 mutex g_vnodeCacheLock; 77 78 78 extern "C" status_t vboxsf_new_vnode(PVBSFMAP map, PSHFLSTRING path, PSHFLSTRING name, vboxsf_vnode** p) {79 vboxsf_vnode* vn = (vboxsf_vnode*)malloc(sizeof(vboxsf_vnode));80 if (vn == NULL) {81 return B_NO_MEMORY;82 }83 dprintf("creating new vnode at %p with path=%p (%s)\n", vn, path->String.utf8, path->String.utf8);84 vn->map = map;85 vn->path = path;86 if (name) {87 vn->name = name;88 }89 else {90 const char* cname = strrchr((char*)path->String.utf8, '/');91 if (!cname)92 vn->name = path; // no slash, assume this *is* the filename93 else94 vn->name = make_shflstring(cname);95 }96 79 97 if (mutex_lock(&g_vnodeCacheLock) < B_OK) { 98 free(vn); 99 return B_ERROR; 100 } 80 extern "C" status_t vboxsf_new_vnode(PVBSFMAP map, PSHFLSTRING path, PSHFLSTRING name, vboxsf_vnode** p) 81 { 82 vboxsf_vnode* vn = (vboxsf_vnode*)malloc(sizeof(vboxsf_vnode)); 83 if (vn == NULL) 84 return B_NO_MEMORY; 101 85 102 vn->vnode = g_nextVnid++; 103 *p = vn; 104 dprintf("vboxsf: allocated %p (path=%p name=%p)\n", vn, vn->path, vn->name); 105 status_t rv = g_cache.Insert(vn); 86 dprintf("creating new vnode at %p with path=%p (%s)\n", vn, path->String.utf8, path->String.utf8); 87 vn->map = map; 88 vn->path = path; 89 if (name) 90 vn->name = name; 91 else 92 { 93 const char* cname = strrchr((char*)path->String.utf8, '/'); 94 if (!cname) 95 vn->name = path; // no slash, assume this *is* the filename 96 else 97 vn->name = make_shflstring(cname); 98 } 106 99 107 mutex_unlock(&g_vnodeCacheLock); 100 if (mutex_lock(&g_vnodeCacheLock) < B_OK) 101 { 102 free(vn); 103 return B_ERROR; 104 } 108 105 109 return rv; 106 vn->vnode = g_nextVnid++; 107 *p = vn; 108 dprintf("vboxsf: allocated %p (path=%p name=%p)\n", vn, vn->path, vn->name); 109 status_t rv = g_cache.Insert(vn); 110 111 mutex_unlock(&g_vnodeCacheLock); 112 113 return rv; 110 114 } 111 115 116 112 117 extern "C" status_t vboxsf_get_vnode(fs_volume* volume, ino_t id, fs_vnode* vnode, 113 int* _type, uint32* _flags, bool reenter) { 114 vboxsf_vnode* vn = g_cache.Lookup(id); 115 if (vn) { 116 vnode->private_node = vn; 117 return B_OK; 118 } 119 else { 120 return B_ERROR; 121 } 118 int* _type, uint32* _flags, bool reenter) 119 { 120 vboxsf_vnode* vn = g_cache.Lookup(id); 121 if (vn) 122 { 123 vnode->private_node = vn; 124 return B_OK; 125 } 126 return B_ERROR; 122 127 } 123 128 124 extern "C" status_t vboxsf_put_vnode(fs_volume* volume, fs_vnode* vnode, bool reenter) { 125 g_cache.Remove((vboxsf_vnode*)vnode->private_node); 129 130 extern "C" status_t vboxsf_put_vnode(fs_volume* volume, fs_vnode* vnode, bool reenter) 131 { 132 g_cache.Remove((vboxsf_vnode*)vnode->private_node); 126 133 } 134 -
trunk/src/VBox/Additions/haiku/VBoxMouse/VBoxMouse.cpp
r43363 r43364 63 63 64 64 /* Export as global symbol with C linkage, RTDECL is necessary. */ 65 RTDECL(BInputServerDevice *)65 RTDECL(BInputServerDevice *) 66 66 instantiate_input_device() 67 67 { … … 69 69 } 70 70 71 71 72 VBoxMouse::VBoxMouse() 72 : BInputServerDevice(), 73 fDriverFD(-1), 74 fServiceThreadID(-1), 75 fExiting(false) 76 { 77 } 73 : BInputServerDevice(), 74 fDriverFD(-1), 75 fServiceThreadID(-1), 76 fExiting(false) 77 { 78 } 79 78 80 79 81 VBoxMouse::~VBoxMouse() 80 82 { 81 83 } 84 82 85 83 86 status_t VBoxMouse::InitCheck() … … 85 88 int rc = VbglR3Init(); 86 89 if (!RT_SUCCESS(rc)) 87 88 89 90 return ENXIO; 91 92 //// Start() will *not* Init() again 90 93 //VbglR3Term(); 91 94 92 // return B_DEVICE_NOT_FOUND; 93 94 input_device_ref device = { (char *)"VBoxMouse", 95 B_POINTING_DEVICE, (void*)this }; 96 input_device_ref* deviceList[2] = { &device, NULL }; 97 RegisterDevices(deviceList); 98 99 return B_OK; 100 } 95 // return B_DEVICE_NOT_FOUND; 96 97 input_device_ref device = { (char *)"VBoxMouse", 98 B_POINTING_DEVICE, (void *)this }; 99 input_device_ref *deviceList[2] = { &device, NULL }; 100 RegisterDevices(deviceList); 101 102 return B_OK; 103 } 104 101 105 102 106 status_t VBoxMouse::SystemShuttingDown() … … 104 108 VbglR3Term(); 105 109 106 return B_OK; 107 } 108 109 status_t VBoxMouse::Start(const char* device, void* cookie) 110 { 111 status_t err; 112 int rc; 110 return B_OK; 111 } 112 113 114 status_t VBoxMouse::Start(const char *device, void *cookie) 115 { 116 status_t err; 117 int rc; 113 118 uint32_t fFeatures = 0; 114 119 Log(("VBoxMouse::%s()\n", __FUNCTION__)); … … 116 121 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL); 117 122 if (RT_SUCCESS(rc)) 118 rc = VbglR3SetMouseStatus( 123 rc = VbglR3SetMouseStatus(fFeatures 119 124 | VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE 120 125 | VMMDEV_MOUSE_NEW_PROTOCOL); 121 if (!RT_SUCCESS(rc)) { 122 LogRel(("VBoxMouse: Error switching guest mouse into absolute mode: %d\n", rc)); 126 if (!RT_SUCCESS(rc)) 127 { 128 LogRel(("VBoxMouse: Error switching guest mouse into absolute mode: %d\n", rc)); 123 129 return B_DEVICE_NOT_FOUND; 124 130 } 125 131 126 err = fServiceThreadID = spawn_thread(_ServiceThreadNub, 127 "VBoxMouse", B_NORMAL_PRIORITY, this); 128 if (err >= B_OK) { 129 resume_thread(fServiceThreadID); 130 return B_OK; 131 } else 132 err = fServiceThreadID = spawn_thread(_ServiceThreadNub, 133 "VBoxMouse", B_NORMAL_PRIORITY, this); 134 if (err >= B_OK) 135 { 136 resume_thread(fServiceThreadID); 137 return B_OK; 138 } 139 else 132 140 LogRel(("VBoxMouse: Error starting service thread: 0x%08lx\n", 133 134 135 141 err)); 142 143 // release the mouse 136 144 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL); 137 145 if (RT_SUCCESS(rc)) 138 rc = VbglR3SetMouseStatus( 146 rc = VbglR3SetMouseStatus(fFeatures 139 147 & ~VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE 140 148 & ~VMMDEV_MOUSE_NEW_PROTOCOL); 141 149 142 return B_ERROR; 143 } 144 145 status_t VBoxMouse::Stop(const char* device, void* cookie) 146 { 147 status_t status; 148 int rc; 150 return B_ERROR; 151 } 152 153 154 status_t VBoxMouse::Stop(const char *device, void *cookie) 155 { 156 status_t status; 157 int rc; 149 158 uint32_t fFeatures = 0; 150 159 Log(("VBoxMouse::%s()\n", __FUNCTION__)); 151 160 152 161 fExiting = true; 153 162 154 163 155 164 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL); 156 165 if (RT_SUCCESS(rc)) 157 rc = VbglR3SetMouseStatus( 166 rc = VbglR3SetMouseStatus(fFeatures 158 167 & ~VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE 159 168 & ~VMMDEV_MOUSE_NEW_PROTOCOL); 160 169 161 170 162 163 164 165 166 167 168 169 170 return B_OK; 171 } 172 173 status_t VBoxMouse::Control(const char *device, 174 void *cookie, 175 uint32 code, 176 BMessage *message) 177 { 178 // respond to changes in the system 179 switch (code) { 180 case B_MOUSE_SPEED_CHANGED:181 case B_CLICK_SPEED_CHANGED:182 case B_MOUSE_ACCELERATION_CHANGED:183 default: 184 return BInputServerDevice::Control(device, cookie, code, message); 185 } 186 return B_OK; 187 } 171 close(fDriverFD); 172 fDriverFD = -1; 173 //XXX WTF ? 174 suspend_thread(fServiceThreadID); 175 resume_thread(fServiceThreadID); 176 wait_for_thread(fServiceThreadID, &status); 177 fServiceThreadID = -1; 178 fExiting = false; 179 return B_OK; 180 } 181 182 183 status_t VBoxMouse::Control(const char *device, void *cookie, uint32 code, BMessage *message) 184 { 185 // respond to changes in the system 186 switch (code) 187 { 188 case B_MOUSE_SPEED_CHANGED: 189 case B_CLICK_SPEED_CHANGED: 190 case B_MOUSE_ACCELERATION_CHANGED: 191 default: 192 return BInputServerDevice::Control(device, cookie, code, message); 193 } 194 return B_OK; 195 } 196 188 197 189 198 status_t VBoxMouse::_ServiceThreadNub(void *_this) 190 199 { 191 VBoxMouse *service = (VBoxMouse *)_this; 192 return service->_ServiceThread(); 193 } 200 VBoxMouse *service = (VBoxMouse *)_this; 201 return service->_ServiceThread(); 202 } 203 194 204 195 205 status_t VBoxMouse::_ServiceThread() … … 197 207 Log(("VBoxMouse::%s()\n", __FUNCTION__)); 198 208 199 200 201 209 fDriverFD = open(VBOXGUEST_DEVICE_NAME, O_RDWR); 210 if (fDriverFD < 0) 211 return ENXIO; 202 212 203 213 /* The thread waits for incoming messages from the host. */ 204 214 while (!fExiting) 205 215 { 206 207 208 209 210 211 212 213 214 215 216 217 218 if (rc < 0) { 219 if (errno == EINTR || errno == EAGAIN) 220 continue; 221 break;222 } 223 224 if (RT_SUCCESS(VbglR3GetMouseStatus(&fFeatures, &cx, &cy)) 225 && (fFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))226 {227 float x = cx * 1.0 / 65535; 228 float y = cy* 1.0 / 65535;229 230 _debugPrintf("VBoxMouse: at %d,%d %f,%f\n", cx, cy, x, y); 231 232 /* send absolute movement */ 233 234 bigtime_t now = system_time(); 235 BMessage* event = new BMessage(B_MOUSE_MOVED);236 event->AddInt64("when", now);237 event->AddFloat("x", x);238 event->AddFloat("y", y);239 event->AddFloat("be:tablet_x", x);240 event->AddFloat("be:tablet_y", y);241 //event->PrintToStream();242 EnqueueMessage(event);243 244 //LogRelFlow(("processed host event rc = %d\n", rc)); 245 }246 }247 return 0; 248 } 249 250 216 uint32_t cx, cy, fFeatures; 217 int rc; 218 219 220 fd_set readSet, writeSet, errorSet; 221 FD_ZERO(&readSet); 222 FD_ZERO(&writeSet); 223 FD_ZERO(&errorSet); 224 FD_SET(fDriverFD, &readSet); 225 if (fDriverFD < 0) 226 break; 227 rc = select(fDriverFD + 1, &readSet, &writeSet, &errorSet, NULL); 228 if (rc < 0) 229 { 230 if (errno == EINTR || errno == EAGAIN) 231 continue; 232 break; 233 } 234 235 if (RT_SUCCESS(VbglR3GetMouseStatus(&fFeatures, &cx, &cy)) 236 && (fFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE)) 237 { 238 float x = cx * 1.0 / 65535; 239 float y = cy * 1.0 / 65535; 240 241 _debugPrintf("VBoxMouse: at %d,%d %f,%f\n", cx, cy, x, y); 242 243 /* send absolute movement */ 244 245 bigtime_t now = system_time(); 246 BMessage *event = new BMessage(B_MOUSE_MOVED); 247 event->AddInt64("when", now); 248 event->AddFloat("x", x); 249 event->AddFloat("y", y); 250 event->AddFloat("be:tablet_x", x); 251 event->AddFloat("be:tablet_y", y); 252 //event->PrintToStream(); 253 EnqueueMessage(event); 254 255 //LogRelFlow(("processed host event rc = %d\n", rc)); 256 } 257 } 258 return 0; 259 } 260 -
trunk/src/VBox/Additions/haiku/VBoxMouse/VBoxMouse.h
r43363 r43364 50 50 #include <InputServerDevice.h> 51 51 52 extern "C" _EXPORT BInputServerDevice* instantiate_input_device(); 52 extern "C" 53 _EXPORT BInputServerDevice* instantiate_input_device(); 53 54 54 class VBoxMouse : public BInputServerDevice { 55 public: 56 VBoxMouse(); 57 virtual ~VBoxMouse(); 55 class VBoxMouse : public BInputServerDevice 56 { 57 public: 58 VBoxMouse(); 59 virtual ~VBoxMouse(); 58 60 59 60 61 virtual status_t InitCheck(); 62 virtual status_t SystemShuttingDown(); 61 63 62 virtual status_t Start(const char* device, void*cookie);63 virtual status_t Stop(const char* device, void*cookie);64 65 66 67 64 virtual status_t Start(const char *device, void *cookie); 65 virtual status_t Stop(const char *device, void *cookie); 66 virtual status_t Control(const char *device, 67 void *cookie, 68 uint32 code, 69 BMessage *message); 68 70 69 private:71 private: 70 72 71 static status_t _ServiceThreadNub(void *_this);72 73 static status_t _ServiceThreadNub(void *_this); 74 status_t _ServiceThread(); 73 75 74 75 76 76 int fDriverFD; 77 thread_id fServiceThreadID; 78 bool fExiting; 77 79 78 80 }; … … 80 82 81 83 #endif /* __VBOXMOUSE__H */ 84 -
trunk/src/VBox/Additions/haiku/VBoxMouse/VBoxMouseFilter.cpp
r43363 r43364 64 64 // TODO can this be merged with VBoxMouse? 65 65 66 RTDECL(BInputServerFilter *)66 RTDECL(BInputServerFilter *) 67 67 instantiate_input_filter() 68 68 { 69 69 return new VBoxMouseFilter(); 70 70 } 71 71 72 72 VBoxMouseFilter::VBoxMouseFilter() 73 74 75 76 77 73 : BInputServerFilter(), 74 fDriverFD(-1), 75 fServiceThreadID(-1), 76 fExiting(false), 77 fCurrentButtons(0) 78 78 { 79 79 } … … 83 83 } 84 84 85 filter_result VBoxMouseFilter::Filter(BMessage * message, BList*outList)85 filter_result VBoxMouseFilter::Filter(BMessage *message, BList *outList) 86 86 { 87 switch(message->what) { 88 case B_MOUSE_UP: 89 case B_MOUSE_DOWN: 90 { 91 printf("click|release\n"); 92 message->FindInt32("buttons", &fCurrentButtons); 93 } 94 case B_MOUSE_MOVED: 95 { 96 printf("mouse moved\n"); 97 message->ReplaceInt32("buttons", fCurrentButtons); 98 } 99 } 87 switch (message->what) 88 { 89 case B_MOUSE_UP: 90 case B_MOUSE_DOWN: 91 { 92 printf("click|release\n"); 93 message->FindInt32("buttons", &fCurrentButtons); 94 } 95 case B_MOUSE_MOVED: 96 { 97 printf("mouse moved\n"); 98 message->ReplaceInt32("buttons", fCurrentButtons); 99 } 100 } 100 101 101 102 return B_DISPATCH_MESSAGE; 102 103 } -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxClipboard.cpp
r43363 r43364 74 74 #define LogRelFlowFunc(x) printf x 75 75 76 76 77 VBoxClipboardService::VBoxClipboardService() 77 : BHandler("VBoxClipboardService"), 78 fClientId(-1), 79 fServiceThreadID(-1), 80 fExiting(false) 81 { 82 } 78 : BHandler("VBoxClipboardService"), 79 fClientId(-1), 80 fServiceThreadID(-1), 81 fExiting(false) 82 { 83 } 84 83 85 84 86 VBoxClipboardService::~VBoxClipboardService() … … 86 88 } 87 89 90 88 91 status_t VBoxClipboardService::Connect() 89 92 { 90 93 status_t err; 91 94 printf("VBoxClipboardService::%s()\n", __FUNCTION__); 92 95 93 96 int rc = VbglR3ClipboardConnect(&fClientId); 94 if (RT_SUCCESS (rc)) { 95 err = fServiceThreadID = spawn_thread(_ServiceThreadNub, 96 "VBoxClipboardService", B_NORMAL_PRIORITY, this); 97 98 if (err >= B_OK) { 99 resume_thread(fServiceThreadID); 100 101 err = be_clipboard->StartWatching(BMessenger(this)); 102 printf("be_clipboard->StartWatching: %ld\n", err); 103 if (err == B_OK) 104 return B_OK; 105 else 106 LogRel(("VBoxClipboardService: Error watching the system clipboard: %ld\n", err)); 107 } else 108 LogRel(("VBoxClipboardService: Error starting service thread: %ld\n", err)); 109 110 //rc = RTErrConvertFromErrno(err); 97 if (RT_SUCCESS(rc)) 98 { 99 err = fServiceThreadID = spawn_thread(_ServiceThreadNub, 100 "VBoxClipboardService", B_NORMAL_PRIORITY, this); 101 102 if (err >= B_OK) 103 { 104 resume_thread(fServiceThreadID); 105 106 err = be_clipboard->StartWatching(BMessenger(this)); 107 printf("be_clipboard->StartWatching: %ld\n", err); 108 if (err == B_OK) 109 return B_OK; 110 else 111 LogRel(("VBoxClipboardService: Error watching the system clipboard: %ld\n", err)); 112 } 113 else 114 LogRel(("VBoxClipboardService: Error starting service thread: %ld\n", err)); 115 116 //rc = RTErrConvertFromErrno(err); 111 117 VbglR3ClipboardDisconnect(fClientId); 112 } else 118 } 119 else 113 120 LogRel(("VBoxClipboardService: Error starting service thread: %d\n", rc)); 114 return B_ERROR; 115 } 121 return B_ERROR; 122 } 123 116 124 117 125 status_t VBoxClipboardService::Disconnect() 118 126 { 119 120 121 122 123 127 status_t status; 128 129 be_clipboard->StopWatching(BMessenger(this)); 130 131 fExiting = true; 124 132 125 133 VbglR3ClipboardDisconnect(fClientId); 126 134 127 135 wait_for_thread(fServiceThreadID, &status); 128 136 return B_OK; 129 137 } 130 138 131 void VBoxClipboardService::MessageReceived(BMessage* message) 132 { 133 uint32_t formats = 0; 134 message->PrintToStream(); 135 switch (message->what) { 136 case VBOX_GUEST_CLIPBOARD_HOST_MSG_FORMATS: 137 { 138 int rc; 139 uint32_t cb; 140 void *pv; 141 bool commit = false; 142 143 if (message->FindInt32("Formats", (int32 *)&formats) != B_OK) 144 break; 145 146 if (!formats) 147 break; 148 if (!be_clipboard->Lock()) 149 break; 150 151 be_clipboard->Clear(); 152 BMessage *clip = be_clipboard->Data(); 153 if (!clip) { 154 be_clipboard->Unlock(); 155 break; 156 } 157 158 if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { 159 pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &cb); 160 if (pv) { 161 char *text; 162 rc = RTUtf16ToUtf8((PCRTUTF16)pv, &text); 139 140 void VBoxClipboardService::MessageReceived(BMessage *message) 141 { 142 uint32_t formats = 0; 143 message->PrintToStream(); 144 switch (message->what) 145 { 146 case VBOX_GUEST_CLIPBOARD_HOST_MSG_FORMATS: 147 { 148 int rc; 149 uint32_t cb; 150 void *pv; 151 bool commit = false; 152 153 if (message->FindInt32("Formats", (int32 *)&formats) != B_OK) 154 break; 155 156 if (!formats) 157 break; 158 if (!be_clipboard->Lock()) 159 break; 160 161 be_clipboard->Clear(); 162 BMessage *clip = be_clipboard->Data(); 163 if (!clip) 164 { 165 be_clipboard->Unlock(); 166 break; 167 } 168 169 if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 170 { 171 pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &cb); 172 if (pv) 173 { 174 char *text; 175 rc = RTUtf16ToUtf8((PCRTUTF16)pv, &text); 163 176 if (RT_SUCCESS(rc)) 164 177 { 165 166 167 168 169 170 171 172 178 BString str(text); 179 // @todo use vboxClipboardUtf16WinToLin() 180 // convert Windows CRLF to LF 181 str.ReplaceAll("\r\n", "\n"); 182 // don't include the \0 183 clip->AddData("text/plain", B_MIME_TYPE, str.String(), str.Length()); 184 RTStrFree(text); 185 commit = true; 173 186 } 174 free(pv); 175 } 176 } 177 178 if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { 179 pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_BITMAP, &cb); 180 if (pv) { 181 void *pBmp; 182 size_t cbBmp; 183 rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmp); 187 free(pv); 188 } 189 } 190 191 if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 192 { 193 pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_BITMAP, &cb); 194 if (pv) 195 { 196 void *pBmp; 197 size_t cbBmp; 198 rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmp); 184 199 if (RT_SUCCESS(rc)) 185 200 { 186 187 188 189 190 191 192 193 194 195 196 197 198 199 201 BMemoryIO mio(pBmp, cbBmp); 202 BBitmap *bitmap = BTranslationUtils::GetBitmap(&mio); 203 if (bitmap) 204 { 205 BMessage bitmapArchive; 206 if (bitmap->IsValid() && 207 bitmap->Archive(&bitmapArchive) == B_OK && 208 clip->AddMessage("image/bitmap", &bitmapArchive) == B_OK) 209 { 210 commit = true; 211 } 212 delete bitmap; 213 } 214 RTMemFree(pBmp); 200 215 } 201 free(pv); 202 } 203 } 204 205 /* make sure we don't bounce this data back to the host, 206 * it's impolite. 207 * It can also be used as a hint to applications probably. */ 208 clip->AddBool("FromVirtualBoxHost", true); 209 210 if (commit) 211 be_clipboard->Commit(); 212 be_clipboard->Unlock(); 213 break; 214 } 215 216 case VBOX_GUEST_CLIPBOARD_HOST_MSG_READ_DATA: 217 { 218 int rc; 219 220 if (message->FindInt32("Formats", (int32 *)&formats) != B_OK) 221 break; 222 223 if (!formats) 224 break; 225 if (!be_clipboard->Lock()) 226 break; 227 228 BMessage *clip = be_clipboard->Data(); 229 if (!clip) { 230 be_clipboard->Unlock(); 231 break; 232 } 233 clip->PrintToStream(); 234 235 if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { 236 const char *text; 237 int32 textLen; 238 if (clip->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &textLen) == B_OK) { 239 // usually doesn't include the \0 so be safe 240 BString str(text, textLen); 241 // convert from LF to Windows CRLF 242 str.ReplaceAll("\n", "\r\n"); 216 free(pv); 217 } 218 } 219 220 /* make sure we don't bounce this data back to the host, 221 * it's impolite. 222 * It can also be used as a hint to applications probably. */ 223 clip->AddBool("FromVirtualBoxHost", true); 224 225 if (commit) 226 be_clipboard->Commit(); 227 be_clipboard->Unlock(); 228 break; 229 } 230 231 case VBOX_GUEST_CLIPBOARD_HOST_MSG_READ_DATA: 232 { 233 int rc; 234 235 if (message->FindInt32("Formats", (int32 *)&formats) != B_OK) 236 break; 237 238 if (!formats) 239 break; 240 if (!be_clipboard->Lock()) 241 break; 242 243 BMessage *clip = be_clipboard->Data(); 244 if (!clip) 245 { 246 be_clipboard->Unlock(); 247 break; 248 } 249 clip->PrintToStream(); 250 251 if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 252 { 253 const char *text; 254 int32 textLen; 255 if (clip->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &textLen) == B_OK) 256 { 257 // usually doesn't include the \0 so be safe 258 BString str(text, textLen); 259 // convert from LF to Windows CRLF 260 str.ReplaceAll("\n", "\r\n"); 243 261 PRTUTF16 pwsz; 244 262 rc = RTStrToUtf16(str.String(), &pwsz); … … 247 265 uint32_t cb = (RTUtf16Len(pwsz) + 1) * sizeof(RTUTF16); 248 266 249 250 251 252 253 267 rc = VbglR3ClipboardWriteData(fClientId, 268 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, pwsz, cb); 269 //printf("VbglR3ClipboardWriteData: %d\n", rc); 270 271 RTUtf16Free(pwsz); 254 272 } 255 } 256 } 257 else if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 258 { 259 BMessage archivedBitmap; 260 if (clip->FindMessage("image/bitmap", &archivedBitmap) == B_OK || 261 clip->FindMessage("image/x-be-bitmap", &archivedBitmap) == B_OK) { 262 BBitmap *bitmap = new(std::nothrow) BBitmap(&archivedBitmap); 263 if (bitmap) 264 { 265 // Don't delete bitmap, BBitmapStream will. 266 BBitmapStream stream(bitmap); 267 BTranslatorRoster *roster = BTranslatorRoster::Default(); 268 if (roster && bitmap->IsValid()) 269 { 270 BMallocIO bmpStream; 271 if (roster->Translate(&stream, NULL, NULL, &bmpStream, B_BMP_FORMAT) == B_OK) 272 { 273 const void *pDib; 274 size_t cbDibSize; 275 /* Strip out the BM header */ 276 rc = vboxClipboardBmpGetDib(bmpStream.Buffer(), bmpStream.BufferLength(), &pDib, &cbDibSize); 277 if (RT_SUCCESS(rc)) 278 { 279 rc = VbglR3ClipboardWriteData(fClientId, 280 VBOX_SHARED_CLIPBOARD_FMT_BITMAP, (void *)pDib, cbDibSize); 281 } 282 } 283 } 284 } 285 } 286 } 287 288 be_clipboard->Unlock(); 289 break; 290 } 291 292 case B_CLIPBOARD_CHANGED: 293 { 294 printf("B_CLIPBOARD_CHANGED\n"); 295 const void *data; 296 int32 dataLen; 297 if (!be_clipboard->Lock()) 298 break; 299 300 BMessage *clip = be_clipboard->Data(); 301 if (!clip) { 302 be_clipboard->Unlock(); 303 break; 304 } 305 306 bool fromVBox; 307 if (clip->FindBool("FromVirtualBoxHost", &fromVBox) == B_OK && fromVBox) { 308 // It already comes from the host, discard. 309 be_clipboard->Unlock(); 310 break; 311 } 312 313 if (clip->FindData("text/plain", B_MIME_TYPE, &data, &dataLen) == B_OK) 314 formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 315 if (clip->HasMessage("image/bitmap") || clip->HasMessage("image/x-be-bitmap")) 316 formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP; 317 318 be_clipboard->Unlock(); 319 320 VbglR3ClipboardReportFormats(fClientId, formats); 321 break; 322 } 323 324 case B_QUIT_REQUESTED: 325 fExiting = true; 326 break; 327 328 default: 329 BHandler::MessageReceived(message); 330 } 331 } 273 } 274 } 275 else if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 276 { 277 BMessage archivedBitmap; 278 if (clip->FindMessage("image/bitmap", &archivedBitmap) == B_OK || 279 clip->FindMessage("image/x-be-bitmap", &archivedBitmap) == B_OK) 280 { 281 BBitmap *bitmap = new(std::nothrow) BBitmap(&archivedBitmap); 282 if (bitmap) 283 { 284 // Don't delete bitmap, BBitmapStream will. 285 BBitmapStream stream(bitmap); 286 BTranslatorRoster *roster = BTranslatorRoster::Default(); 287 if (roster && bitmap->IsValid()) 288 { 289 BMallocIO bmpStream; 290 if (roster->Translate(&stream, NULL, NULL, &bmpStream, B_BMP_FORMAT) == B_OK) 291 { 292 const void *pDib; 293 size_t cbDibSize; 294 /* Strip out the BM header */ 295 rc = vboxClipboardBmpGetDib(bmpStream.Buffer(), bmpStream.BufferLength(), &pDib, &cbDibSize); 296 if (RT_SUCCESS(rc)) 297 { 298 rc = VbglR3ClipboardWriteData(fClientId, 299 VBOX_SHARED_CLIPBOARD_FMT_BITMAP, (void *)pDib, cbDibSize); 300 } 301 } 302 } 303 } 304 } 305 } 306 307 be_clipboard->Unlock(); 308 break; 309 } 310 311 case B_CLIPBOARD_CHANGED: 312 { 313 printf("B_CLIPBOARD_CHANGED\n"); 314 const void *data; 315 int32 dataLen; 316 if (!be_clipboard->Lock()) 317 break; 318 319 BMessage *clip = be_clipboard->Data(); 320 if (!clip) 321 { 322 be_clipboard->Unlock(); 323 break; 324 } 325 326 bool fromVBox; 327 if (clip->FindBool("FromVirtualBoxHost", &fromVBox) == B_OK && fromVBox) 328 { 329 // It already comes from the host, discard. 330 be_clipboard->Unlock(); 331 break; 332 } 333 334 if (clip->FindData("text/plain", B_MIME_TYPE, &data, &dataLen) == B_OK) 335 formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 336 if (clip->HasMessage("image/bitmap") || clip->HasMessage("image/x-be-bitmap")) 337 formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP; 338 339 be_clipboard->Unlock(); 340 341 VbglR3ClipboardReportFormats(fClientId, formats); 342 break; 343 } 344 345 case B_QUIT_REQUESTED: 346 fExiting = true; 347 break; 348 349 default: 350 BHandler::MessageReceived(message); 351 } 352 } 353 332 354 333 355 status_t VBoxClipboardService::_ServiceThreadNub(void *_this) 334 356 { 335 VBoxClipboardService *service = (VBoxClipboardService *)_this; 336 return service->_ServiceThread(); 337 } 357 VBoxClipboardService *service = (VBoxClipboardService *)_this; 358 return service->_ServiceThread(); 359 } 360 338 361 339 362 status_t VBoxClipboardService::_ServiceThread() … … 347 370 uint32_t u32Formats; 348 371 int rc = VbglR3ClipboardGetHostMsg(fClientId, &u32Msg, &u32Formats); 349 if (RT_SUCCESS(rc)) { 350 switch (u32Msg) { 372 if (RT_SUCCESS(rc)) 373 { 374 switch (u32Msg) 375 { 351 376 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS: 352 377 { … … 374 399 /* The host is terminating. */ 375 400 LogRelFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT\n")); 376 401 fExiting = true; 377 402 return VERR_INTERRUPTED; 378 403 } … … 381 406 Log(("VBoxClipboardService::%s: Unsupported message from host! Message = %u\n", __FUNCTION__, u32Msg)); 382 407 } 383 } else 384 fExiting = true; 408 } 409 else 410 fExiting = true; 385 411 386 412 LogRelFlow(("processed host event rc = %d\n", rc)); 387 413 388 414 if (fExiting) 389 415 break; 390 416 } 391 392 } 393 394 395 void *VBoxClipboardService::_VBoxReadHostClipboard(uint32_t format, uint32_t *pcb)396 { 397 398 399 400 401 402 403 404 405 417 return 0; 418 } 419 420 421 void* VBoxClipboardService::_VBoxReadHostClipboard(uint32_t format, uint32_t *pcb) 422 { 423 uint32_t cb = 1024; 424 void *pv; 425 int rc; 426 427 pv = malloc(cb); 428 if (pv == NULL) 429 return NULL; 430 431 rc = VbglR3ClipboardReadData(fClientId, format, pv, cb, pcb); 406 432 if (RT_SUCCESS(rc) && (rc != VINF_BUFFER_OVERFLOW)) 407 433 return pv; 408 434 if (rc == VINF_BUFFER_OVERFLOW) 409 435 { 410 411 412 413 414 415 416 417 418 419 420 436 free(pv); 437 cb = *pcb; 438 pv = malloc(cb); 439 if (pv == NULL) 440 return NULL; 441 442 rc = VbglR3ClipboardReadData(fClientId, format, pv, cb, pcb); 443 if (RT_SUCCESS(rc) && (rc != VINF_BUFFER_OVERFLOW)) 444 return pv; 445 446 free(pv); 421 447 } 422 448 return NULL; -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxClipboard.h
r43363 r43364 50 50 #include <Handler.h> 51 51 52 class VBoxClipboardService : public BHandler { 53 public: 54 VBoxClipboardService(); 55 virtual ~VBoxClipboardService(); 52 class VBoxClipboardService : public BHandler 53 { 54 public: 55 VBoxClipboardService(); 56 virtual ~VBoxClipboardService(); 56 57 57 58 58 virtual status_t Connect(); 59 virtual status_t Disconnect(); 59 60 60 virtual void MessageReceived(BMessage*message);61 virtual void MessageReceived(BMessage *message); 61 62 62 private:63 private: 63 64 64 static status_t _ServiceThreadNub(void *_this);65 65 static status_t _ServiceThreadNub(void *_this); 66 status_t _ServiceThread(); 66 67 67 void *_VBoxReadHostClipboard(uint32_t format, uint32_t *pcb);68 void* _VBoxReadHostClipboard(uint32_t format, uint32_t *pcb); 68 69 69 70 71 70 uint32_t fClientId; 71 thread_id fServiceThreadID; 72 bool fExiting; 72 73 73 74 }; -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxDisplay.cpp
r43363 r43364 71 71 72 72 VBoxDisplayService::VBoxDisplayService() 73 74 75 76 77 73 : BHandler("VBoxDisplayService"), 74 fClientId(-1), 75 fServiceThreadID(-1), 76 fExiting(false), 77 fScreen(B_MAIN_SCREEN_ID) 78 78 { 79 79 } 80 80 81 81 82 VBoxDisplayService::~VBoxDisplayService() … … 83 84 } 84 85 86 85 87 void VBoxDisplayService::Start() 86 88 { 87 88 89 89 status_t err; 90 err = fServiceThreadID = spawn_thread(_ServiceThreadNub, 91 "VBoxDisplayService", B_NORMAL_PRIORITY, this); 90 92 91 if (err >= B_OK) { 92 93 }else94 93 if (err >= B_OK) 94 resume_thread(fServiceThreadID); 95 else 96 LogRel(("VBoxDisplayService: Error starting service thread: %s\n", strerror(err))); 95 97 96 98 } 97 99 98 void VBoxDisplayService::MessageReceived(BMessage* message) 100 101 void VBoxDisplayService::MessageReceived(BMessage *message) 99 102 { 100 101 102 103 103 if (message->what == B_QUIT_REQUESTED) 104 fExiting = true; 105 else 106 BHandler::MessageReceived(message); 104 107 } 108 105 109 106 110 status_t VBoxDisplayService::_ServiceThreadNub(void *_this) 107 111 { 108 109 112 VBoxDisplayService *service = (VBoxDisplayService *)_this; 113 return service->_ServiceThread(); 110 114 } 115 111 116 112 117 status_t VBoxDisplayService::_ServiceThread() … … 115 120 116 121 VbglR3CtlFilterMask(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0); 117 122 VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0); 118 123 119 for (;;) { 120 uint32_t events; 124 for (;;) 125 { 126 uint32_t events; 121 127 122 123 124 128 int rc = VbglR3WaitEvent(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 5000, &events); 129 if (rc == -6) // timed out? 130 continue; 125 131 126 if (RT_SUCCESS(rc)) { 127 uint32_t cx, cy, cBits, iDisplay; 132 if (RT_SUCCESS(rc)) 133 { 134 uint32_t cx, cy, cBits, iDisplay; 128 135 int rc2 = VbglR3GetDisplayChangeRequest(&cx, &cy, &cBits, &iDisplay, true); 129 136 printf("rc2=%d screen %d size changed (%d, %d, %d)\n", rc2, iDisplay, cx, cy, cBits); 130 137 131 if (RT_SUCCESS(rc2)) { 132 display_mode mode; 133 fScreen.GetMode(&mode); 134 if (cBits == 0) { 135 cBits = get_depth_for_color_space(mode.space); 136 } 137 mode.timing.h_display = cx; 138 mode.timing.v_display = cy; 139 mode.space = get_color_space_for_depth(cBits); 140 mode.virtual_width = cx; 141 mode.virtual_height = cy; 138 if (RT_SUCCESS(rc2)) 139 { 140 display_mode mode; 141 fScreen.GetMode(&mode); 142 if (cBits == 0) 143 { 144 cBits = get_depth_for_color_space(mode.space); 145 } 146 mode.timing.h_display = cx; 147 mode.timing.v_display = cy; 148 mode.space = get_color_space_for_depth(cBits); 149 mode.virtual_width = cx; 150 mode.virtual_height = cy; 142 151 143 144 145 146 147 152 /*= { 153 {0, cx, 0, 0, cBits * cx / 8, cy, 0, 0, cBits * cy / 8, 0}, 154 get_color_space_for_depth(cBits), 155 cx, cy, 0, 0, 0 156 };*/ 148 157 149 150 158 fScreen.SetMode(&mode, false); 159 } 151 160 } 152 161 else 153 162 fExiting = true; 154 163 155 164 LogRelFlow(("processed host event rc = %d\n", rc)); 156 165 157 166 if (fExiting) 158 167 break; 159 168 } 160 169 return 0; 161 170 } 171 -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxDisplay.h
r43363 r43364 51 51 #include <Screen.h> 52 52 53 class VBoxDisplayService : public BHandler { 54 public: 55 VBoxDisplayService(); 56 virtual ~VBoxDisplayService(); 53 class VBoxDisplayService : public BHandler 54 { 55 public: 56 VBoxDisplayService(); 57 virtual ~VBoxDisplayService(); 57 58 58 voidStart();59 void Start(); 59 60 60 virtual void MessageReceived(BMessage*message);61 virtual void MessageReceived(BMessage *message); 61 62 62 private:63 private: 63 64 64 static status_t_ServiceThreadNub(void *_this);65 status_t_ServiceThread();65 static status_t _ServiceThreadNub(void *_this); 66 status_t _ServiceThread(); 66 67 67 uint32_tfClientId;68 thread_idfServiceThreadID;69 volatile boolfExiting;70 BScreenfScreen;68 uint32_t fClientId; 69 thread_id fServiceThreadID; 70 volatile bool fExiting; 71 BScreen fScreen; 71 72 }; 72 73 74 #endif /* __VBOXSERVICESHAREDCLIPLBOARD__H */ 73 75 74 #endif /* __VBOXSERVICESHAREDCLIPLBOARD__H */ -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxGuestApplication.cpp
r43363 r43364 60 60 61 61 VBoxGuestApplication::VBoxGuestApplication() 62 62 : BApplication(VBOX_GUEST_APP_SIG) 63 63 { 64 64 PRINT(("%s()\n", __FUNCTION__)); 65 65 } 66 66 67 67 68 VBoxGuestApplication::~VBoxGuestApplication() 68 69 { 69 70 PRINT(("%s()\n", __FUNCTION__)); 70 71 } 72 71 73 72 74 void VBoxGuestApplication::ReadyToRun() 73 75 { 74 76 status_t err; 75 77 76 77 78 err = VBoxGuestDeskbarView::AddToDeskbar(); 79 PRINT(("%s: VBoxGuestDeskbarView::AddToDeskbar: 0x%08lx\n", __FUNCTION__, err)); 78 80 79 81 exit(0); 80 82 } 83 81 84 82 85 int main(int argc, const char **argv) 83 86 { 84 85 86 87 new VBoxGuestApplication(); 88 be_app->Run(); 89 delete be_app; 87 90 88 91 /* int rc = RTR3Init(); … … 96 99 if (RT_SUCCESS(rc)) 97 100 { 98 101 Log(("VBoxGuestApp: Init successful\n")); 99 102 100 101 102 103 new VBoxGuestApplication(gVBoxDriverFD); 104 be_app->Run(); 105 delete be_app; 103 106 104 107 } 105 108 106 109 if (RT_FAILURE(rc)) 107 110 { 108 111 LogRel(("VBoxGuestApp: Error while starting, rc=%Rrc\n", rc)); … … 110 113 LogRel(("VBoxGuestApp: Ended\n")); 111 114 112 115 vboxCloseBaseDriver(); 113 116 114 117 VbglR3Term();*/ 115 118 116 119 return 0; 117 120 } 121 -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxGuestDeskbarView.cpp
r43363 r43364 69 69 our_image(image_info& image) 70 70 { 71 /** @todo r=ramshankar: find a way to do this without annoying the compiler, probably uintptr_t? */ 72 int32 cookie = 0; 73 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) { 74 if ((char *)our_image >= (char *)image.text 75 && (char *)our_image <= (char *)image.text + image.text_size) 76 return B_OK; 77 } 78 79 return B_ERROR; 71 /** @todo r=ramshankar: find a way to do this without annoying the compiler, probably uintptr_t? */ 72 int32 cookie = 0; 73 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) 74 { 75 if ((char *)our_image >= (char *)image.text 76 && (char *)our_image <= (char *)image.text + image.text_size) 77 return B_OK; 78 } 79 80 return B_ERROR; 80 81 } 81 82 82 83 83 84 VBoxGuestDeskbarView::VBoxGuestDeskbarView() 84 : BView(BRect(0, 0, 15, 15), VIEWNAME, B_FOLLOW_NONE, 85 B_WILL_DRAW | B_NAVIGABLE), 86 fIcon(NULL), fClipboardService(NULL), fDisplayService(NULL) 87 { 88 PRINT(("%s()\n", __FUNCTION__)); 89 _Init(); 90 } 85 : BView(BRect(0, 0, 15, 15), VIEWNAME, B_FOLLOW_NONE, 86 B_WILL_DRAW | B_NAVIGABLE), 87 fIcon(NULL), fClipboardService(NULL), fDisplayService(NULL) 88 { 89 PRINT(("%s()\n", __FUNCTION__)); 90 _Init(); 91 } 92 91 93 92 94 VBoxGuestDeskbarView::VBoxGuestDeskbarView(BMessage *archive) 93 : BView(archive), 94 fIcon(NULL) 95 { 96 PRINT(("%s()\n", __FUNCTION__)); 97 archive->PrintToStream(); 98 99 _Init(archive); 100 } 95 : BView(archive), 96 fIcon(NULL) 97 { 98 PRINT(("%s()\n", __FUNCTION__)); 99 archive->PrintToStream(); 100 101 _Init(archive); 102 } 103 101 104 102 105 VBoxGuestDeskbarView::~VBoxGuestDeskbarView() 103 106 { 104 PRINT(("%s()\n", __FUNCTION__)); 105 delete fIcon; 106 if (fClipboardService) { 107 fClipboardService->Disconnect(); 108 delete fClipboardService; 109 } 110 VbglR3Term(); 111 } 112 113 BArchivable *VBoxGuestDeskbarView::Instantiate(BMessage *data) 114 { 115 PRINT(("%s()\n", __FUNCTION__)); 116 if (!validate_instantiation(data, VIEWNAME)) 117 return NULL; 118 119 return new VBoxGuestDeskbarView(data); 120 } 107 PRINT(("%s()\n", __FUNCTION__)); 108 delete fIcon; 109 if (fClipboardService) 110 { 111 fClipboardService->Disconnect(); 112 delete fClipboardService; 113 } 114 VbglR3Term(); 115 } 116 117 118 BArchivable* VBoxGuestDeskbarView::Instantiate(BMessage *data) 119 { 120 PRINT(("%s()\n", __FUNCTION__)); 121 if (!validate_instantiation(data, VIEWNAME)) 122 return NULL; 123 124 return new VBoxGuestDeskbarView(data); 125 } 126 121 127 122 128 status_t VBoxGuestDeskbarView::Archive(BMessage *data, bool deep) const 123 129 { 124 status_t err; 125 PRINT(("%s()\n", __FUNCTION__)); 126 127 err = BView::Archive(data, false); 128 if (err < B_OK) 129 return err; 130 data->AddString("add_on", VBOX_GUEST_APP_SIG); 131 data->AddString("class", "VBoxGuestDeskbarView"); 132 return B_OK; 133 } 130 status_t err; 131 PRINT(("%s()\n", __FUNCTION__)); 132 133 err = BView::Archive(data, false); 134 if (err < B_OK) 135 return err; 136 data->AddString("add_on", VBOX_GUEST_APP_SIG); 137 data->AddString("class", "VBoxGuestDeskbarView"); 138 return B_OK; 139 } 140 134 141 135 142 void VBoxGuestDeskbarView::Draw(BRect rect) 136 143 { 137 SetDrawingMode(B_OP_ALPHA); 138 DrawBitmap(fIcon); 139 } 144 SetDrawingMode(B_OP_ALPHA); 145 DrawBitmap(fIcon); 146 } 147 140 148 141 149 void VBoxGuestDeskbarView::AttachedToWindow() 142 150 { 143 BView::AttachedToWindow(); 144 if (Parent()) { 145 SetViewColor(Parent()->ViewColor()); 146 SetLowColor(Parent()->LowColor()); 147 } 148 149 if (fClipboardService) { // don't repeatedly crash deskbar if vboxdev not loaded 150 Looper()->AddHandler(fClipboardService); 151 fClipboardService->Connect(); 152 } 153 154 if (fDisplayService) { 155 fDisplayService->Start(); 156 } 157 } 151 BView::AttachedToWindow(); 152 if (Parent()) 153 { 154 SetViewColor(Parent()->ViewColor()); 155 SetLowColor(Parent()->LowColor()); 156 } 157 158 if (fClipboardService) // don't repeatedly crash deskbar if vboxdev not loaded 159 { 160 Looper()->AddHandler(fClipboardService); 161 fClipboardService->Connect(); 162 } 163 164 if (fDisplayService) 165 { 166 fDisplayService->Start(); 167 } 168 } 169 158 170 159 171 void VBoxGuestDeskbarView::DetachedFromWindow() 160 172 { 161 BMessage message(B_QUIT_REQUESTED); 162 fClipboardService->MessageReceived(&message); 163 fDisplayService->MessageReceived(&message); 164 } 173 BMessage message(B_QUIT_REQUESTED); 174 fClipboardService->MessageReceived(&message); 175 fDisplayService->MessageReceived(&message); 176 } 177 165 178 166 179 void VBoxGuestDeskbarView::MouseDown(BPoint point) 167 180 { 168 printf("MouseDown\n"); 169 int32 buttons = B_PRIMARY_MOUSE_BUTTON; 170 if (Looper() != NULL && Looper()->CurrentMessage() != NULL) 171 Looper()->CurrentMessage()->FindInt32("buttons", &buttons); 172 173 BPoint where = ConvertToScreen(point); 174 175 if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) { 176 BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 177 menu->SetAsyncAutoDestruct(true); 178 menu->SetFont(be_plain_font); 179 180 menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED))); 181 menu->SetTargetForItems(this); 182 183 menu->Go(where, true, true, true); 184 } 185 } 186 187 void VBoxGuestDeskbarView::MessageReceived(BMessage* message) 188 { 189 if (message->what == B_QUIT_REQUESTED) 190 RemoveFromDeskbar(); 191 else 192 BHandler::MessageReceived(message); 193 } 181 printf("MouseDown\n"); 182 int32 buttons = B_PRIMARY_MOUSE_BUTTON; 183 if (Looper() != NULL && Looper()->CurrentMessage() != NULL) 184 Looper()->CurrentMessage()->FindInt32("buttons", &buttons); 185 186 BPoint where = ConvertToScreen(point); 187 188 if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) 189 { 190 BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 191 menu->SetAsyncAutoDestruct(true); 192 menu->SetFont(be_plain_font); 193 194 menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED))); 195 menu->SetTargetForItems(this); 196 197 menu->Go(where, true, true, true); 198 } 199 } 200 201 202 void VBoxGuestDeskbarView::MessageReceived(BMessage *message) 203 { 204 if (message->what == B_QUIT_REQUESTED) 205 RemoveFromDeskbar(); 206 else 207 BHandler::MessageReceived(message); 208 } 209 194 210 195 211 status_t VBoxGuestDeskbarView::AddToDeskbar(bool force) 196 212 { 197 BDeskbar deskbar; 198 status_t err; 199 PRINT(("%s()\n", __FUNCTION__)); 200 201 if (force) 202 RemoveFromDeskbar(); 203 else if (deskbar.HasItem(VIEWNAME)) 204 return B_OK; 205 206 app_info info; 207 err = be_app->GetAppInfo(&info); 208 PRINT(("%s: be_app->GetAppInfo: 0x%08lx\n", __FUNCTION__, err)); 209 if (err < B_OK) 210 return err; 211 212 BPath p(&info.ref); 213 PRINT(("%s: app path: '%s'\n", __FUNCTION__, p.Path())); 214 215 return deskbar.AddItem(&info.ref); 216 } 213 BDeskbar deskbar; 214 status_t err; 215 PRINT(("%s()\n", __FUNCTION__)); 216 217 if (force) 218 RemoveFromDeskbar(); 219 else if (deskbar.HasItem(VIEWNAME)) 220 return B_OK; 221 222 app_info info; 223 err = be_app->GetAppInfo(&info); 224 PRINT(("%s: be_app->GetAppInfo: 0x%08lx\n", __FUNCTION__, err)); 225 if (err < B_OK) 226 return err; 227 228 BPath p(&info.ref); 229 PRINT(("%s: app path: '%s'\n", __FUNCTION__, p.Path())); 230 231 return deskbar.AddItem(&info.ref); 232 } 233 217 234 218 235 status_t VBoxGuestDeskbarView::RemoveFromDeskbar() 219 236 { 220 BDeskbar deskbar; 221 PRINT(("%s()\n", __FUNCTION__)); 222 223 return deskbar.RemoveItem(VIEWNAME); 224 } 237 BDeskbar deskbar; 238 PRINT(("%s()\n", __FUNCTION__)); 239 240 return deskbar.RemoveItem(VIEWNAME); 241 } 242 225 243 226 244 status_t VBoxGuestDeskbarView::_Init(BMessage *archive) 227 245 { 228 BString toolTipText; 229 toolTipText << VBOX_PRODUCT << " Guest Additions "; 230 toolTipText << VBOX_VERSION_MAJOR << "." << VBOX_VERSION_MINOR << "." << VBOX_VERSION_BUILD; 231 toolTipText << "r" << VBOX_SVN_REV; 232 233 SetToolTip(toolTipText.String()); 234 235 image_info info; 236 if (our_image(info) != B_OK) 237 return B_ERROR; 238 239 BFile file(info.name, B_READ_ONLY); 240 if (file.InitCheck() < B_OK) 241 return B_ERROR; 242 243 BResources resources(&file); 244 if (resources.InitCheck() < B_OK) 245 return B_ERROR; 246 247 const void* data = NULL; 248 size_t size; 249 //data = resources.LoadResource(B_VECTOR_ICON_TYPE, 250 // kNetworkStatusNoDevice + i, &size); 251 data = resources.LoadResource('data', 400, &size); 252 if (data != NULL) { 253 BMemoryIO mem(data, size); 254 fIcon = BTranslationUtils::GetBitmap(&mem); 255 } 246 BString toolTipText; 247 toolTipText << VBOX_PRODUCT << " Guest Additions "; 248 toolTipText << VBOX_VERSION_MAJOR << "." << VBOX_VERSION_MINOR << "." << VBOX_VERSION_BUILD; 249 toolTipText << "r" << VBOX_SVN_REV; 250 251 SetToolTip(toolTipText.String()); 252 253 image_info info; 254 if (our_image(info) != B_OK) 255 return B_ERROR; 256 257 BFile file(info.name, B_READ_ONLY); 258 if (file.InitCheck() < B_OK) 259 return B_ERROR; 260 261 BResources resources(&file); 262 if (resources.InitCheck() < B_OK) 263 return B_ERROR; 264 265 const void *data = NULL; 266 size_t size; 267 //data = resources.LoadResource(B_VECTOR_ICON_TYPE, 268 // kNetworkStatusNoDevice + i, &size); 269 data = resources.LoadResource('data', 400, &size); 270 if (data != NULL) 271 { 272 BMemoryIO mem(data, size); 273 fIcon = BTranslationUtils::GetBitmap(&mem); 274 } 256 275 257 276 int rc = RTR3InitDll(0); 258 printf("%d\n", rc); 259 if (RT_SUCCESS(rc)) { 277 printf("%d\n", rc); 278 if (RT_SUCCESS(rc)) 279 { 260 280 rc = VbglR3Init(); 261 281 } 262 printf("%d\n", rc); 263 if (RT_SUCCESS(rc)) { 264 fClipboardService = new VBoxClipboardService(); 265 fDisplayService = new VBoxDisplayService(); 266 } 267 268 return RTErrConvertToErrno(rc); 269 } 270 271 extern "C" BView* 272 instantiate_deskbar_item(void) 273 { 274 PRINT(("%s()\n", __FUNCTION__)); 275 return new VBoxGuestDeskbarView(); 276 } 277 282 printf("%d\n", rc); 283 if (RT_SUCCESS(rc)) 284 { 285 fClipboardService = new VBoxClipboardService(); 286 fDisplayService = new VBoxDisplayService(); 287 } 288 289 return RTErrConvertToErrno(rc); 290 } 291 292 293 RTDECL(BView*) instantiate_deskbar_item() 294 { 295 PRINT(("%s()\n", __FUNCTION__)); 296 return new VBoxGuestDeskbarView(); 297 } 298 -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxGuestDeskbarView.h
r43363 r43364 65 65 #define REMOVE_FROM_DESKBAR_MSG 'vbqr' 66 66 67 class VBoxGuestDeskbarView : public BView { 68 public: 69 VBoxGuestDeskbarView(); 70 VBoxGuestDeskbarView(BMessage *archive); 71 virtual ~VBoxGuestDeskbarView(); 72 static BArchivable *Instantiate(BMessage *data); 73 virtual status_t Archive(BMessage *data, bool deep = true) const; 67 class VBoxGuestDeskbarView : public BView 68 { 69 public: 70 VBoxGuestDeskbarView(); 71 VBoxGuestDeskbarView(BMessage *archive); 72 virtual ~VBoxGuestDeskbarView(); 74 73 75 void Draw(BRect rect); 76 void AttachedToWindow(); 77 void DetachedFromWindow(); 74 static BArchivable* Instantiate(BMessage *data); 75 virtual status_t Archive(BMessage *data, bool deep = true) const; 78 76 79 virtual void MouseDown(BPoint point); 80 virtual void MessageReceived(BMessage* message); 77 void Draw(BRect rect); 78 void AttachedToWindow(); 79 void DetachedFromWindow(); 81 80 82 static status_t AddToDeskbar(bool force=true);83 static status_t RemoveFromDeskbar();81 virtual void MouseDown(BPoint point); 82 virtual void MessageReceived(BMessage *message); 84 83 85 private: 86 status_t _Init(BMessage *archive=NULL); 87 BBitmap *fIcon; 84 static status_t AddToDeskbar(bool force = true); 85 static status_t RemoveFromDeskbar(); 88 86 89 VBoxClipboardService *fClipboardService; 90 VBoxDisplayService *fDisplayService; 87 private: 88 status_t _Init(BMessage *archive = NULL); 89 BBitmap *fIcon; 90 91 VBoxClipboardService *fClipboardService; 92 VBoxDisplayService *fDisplayService; 91 93 }; 92 94 93 95 #endif /* __VBOXGUESTTRAYVIEW__H */ 96 -
trunk/src/VBox/Additions/haiku/VBoxVideo/accelerant/accelerant.cpp
r43363 r43364 53 53 #define TRACE(x...) do { FILE* logfile = fopen("/var/log/vboxvideo.accelerant.log", "a"); fprintf(logfile, x); fflush(logfile); fsync(fileno(logfile)); fclose(logfile); sync(); } while(0) 54 54 55 class AreaCloner { 56 public: 57 AreaCloner() : fArea(-1) {} 58 ~AreaCloner() { 59 if (fArea >= B_OK) 60 delete_area(fArea); 61 } 62 63 area_id Clone(const char *name, void **_address, uint32 spec, uint32 protection, area_id sourceArea) { 64 fArea = clone_area(name, _address, spec, protection, sourceArea); 65 return fArea; 66 } 67 68 status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; } 69 void Keep() { fArea = -1; } 70 71 private: 72 area_id fArea; 55 class AreaCloner 56 { 57 public: 58 AreaCloner() : fArea(-1) { } 59 ~AreaCloner() 60 { 61 if (fArea >= B_OK) 62 delete_area(fArea); 63 } 64 65 area_id Clone(const char *name, void **_address, uint32 spec, uint32 protection, area_id sourceArea) 66 { 67 fArea = clone_area(name, _address, spec, protection, sourceArea); 68 return fArea; 69 } 70 71 status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; } 72 void Keep() { fArea = -1; } 73 74 private: 75 area_id fArea; 73 76 }; 74 77 75 78 AccelerantInfo gInfo; 76 79 77 static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL}; 78 79 extern "C" void* get_accelerant_hook(uint32 feature, void* data) { 80 TRACE("%s\n", __FUNCTION__); 81 switch (feature) { 82 /* general */ 83 case B_INIT_ACCELERANT: 84 return (void*)vboxvideo_init_accelerant; 85 case B_UNINIT_ACCELERANT: 86 return (void*)vboxvideo_uninit_accelerant; 87 case B_CLONE_ACCELERANT: 88 return (void*)vboxvideo_clone_accelerant; 89 case B_ACCELERANT_CLONE_INFO_SIZE: 90 return (void*)vboxvideo_accelerant_clone_info_size; 91 case B_GET_ACCELERANT_CLONE_INFO: 92 return (void*)vboxvideo_get_accelerant_clone_info; 93 case B_GET_ACCELERANT_DEVICE_INFO: 94 return (void*)vboxvideo_get_accelerant_device_info; 95 case B_ACCELERANT_RETRACE_SEMAPHORE: 96 return (void*)vboxvideo_accelerant_retrace_semaphore; 97 98 /* mode configuration */ 99 case B_ACCELERANT_MODE_COUNT: 100 return (void*)vboxvideo_accelerant_mode_count; 101 case B_GET_MODE_LIST: 102 return (void*)vboxvideo_get_mode_list; 103 case B_SET_DISPLAY_MODE: 104 return (void*)vboxvideo_set_display_mode; 105 case B_GET_DISPLAY_MODE: 106 return (void*)vboxvideo_get_display_mode; 107 case B_GET_EDID_INFO: 108 return (void*)vboxvideo_get_edid_info; 109 case B_GET_FRAME_BUFFER_CONFIG: 110 return (void*)vboxvideo_get_frame_buffer_config; 111 case B_GET_PIXEL_CLOCK_LIMITS: 112 return (void*)vboxvideo_get_pixel_clock_limits; 113 114 /* cursor managment */ 115 /*case B_SET_CURSOR_SHAPE: 116 return (void*)vboxvideo_set_cursor_shape; 117 case B_MOVE_CURSOR: 118 return (void*)vboxvideo_move_cursor; 119 case B_SHOW_CURSOR: 120 return (void*)vboxvideo_show_cursor;*/ 121 122 /* engine/synchronization */ 123 case B_ACCELERANT_ENGINE_COUNT: 124 return (void*)vboxvideo_accelerant_engine_count; 125 case B_ACQUIRE_ENGINE: 126 return (void*)vboxvideo_acquire_engine; 127 case B_RELEASE_ENGINE: 128 return (void*)vboxvideo_release_engine; 129 case B_WAIT_ENGINE_IDLE: 130 return (void*)vboxvideo_wait_engine_idle; 131 case B_GET_SYNC_TOKEN: 132 return (void*)vboxvideo_get_sync_token; 133 case B_SYNC_TO_TOKEN: 134 return (void*)vboxvideo_sync_to_token; 135 } 136 137 return NULL; 138 } 139 140 status_t vboxvideo_init_common(int fd, bool cloned) { 141 unlink("/var/log/vboxvideo.accelerant.log"); // clear old log - next TRACE() will recreate it 142 TRACE("%s\n", __FUNCTION__); 143 144 gInfo.deviceFD = fd; 145 gInfo.isClone = cloned; 146 gInfo.sharedInfo = NULL; 147 gInfo.sharedInfoArea = -1; 148 149 area_id sharedArea; 150 if (ioctl(gInfo.deviceFD, VBOXVIDEO_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) != 0) { 151 TRACE("ioctl failed\n"); 152 return B_ERROR; 153 } 154 155 AreaCloner sharedCloner; 156 gInfo.sharedInfoArea = sharedCloner.Clone("vboxvideo shared info", 157 (void **)&gInfo.sharedInfo, B_ANY_ADDRESS, 158 B_READ_AREA | B_WRITE_AREA, sharedArea); 159 status_t status = sharedCloner.InitCheck(); 160 if (status < B_OK) { 161 TRACE("InitCheck failed (%s)\n", strerror(status)); 162 return status; 163 } 164 sharedCloner.Keep(); 165 166 return B_OK; 167 } 168 169 status_t vboxvideo_init_accelerant(int fd) { 170 return vboxvideo_init_common(fd, false); 171 } 172 173 ssize_t vboxvideo_accelerant_clone_info_size(void) { 174 TRACE("%s\n", __FUNCTION__); 175 return B_PATH_NAME_LENGTH; 176 } 177 178 void vboxvideo_get_accelerant_clone_info(void *data) { 179 TRACE("%s\n", __FUNCTION__); 180 ioctl(gInfo.deviceFD, VBOXVIDEO_GET_DEVICE_NAME, data, B_PATH_NAME_LENGTH); 181 } 182 183 status_t vboxvideo_clone_accelerant(void *data) { 184 TRACE("%s\n", __FUNCTION__); 185 186 // create full device name 187 char path[MAXPATHLEN]; 188 strcpy(path, "/dev/"); 189 strcat(path, (const char *)data); 190 191 int fd = open(path, B_READ_WRITE); 192 if (fd < 0) 193 return errno; 194 195 return vboxvideo_init_common(fd, true); 196 } 197 198 void vboxvideo_uninit_accelerant(void) { 199 delete_area(gInfo.sharedInfoArea); 200 gInfo.sharedInfo = NULL; 201 gInfo.sharedInfoArea = -1; 202 203 if (gInfo.isClone) 204 close(gInfo.deviceFD); 205 206 TRACE("%s\n", __FUNCTION__); 207 } 208 209 status_t vboxvideo_get_accelerant_device_info(accelerant_device_info *adi) { 210 TRACE("%s\n", __FUNCTION__); 211 adi->version = B_ACCELERANT_VERSION; 212 strcpy(adi->name, "Virtual display"); 213 strcpy(adi->chipset, "VirtualBox Graphics Adapter"); 214 strcpy(adi->serial_no, "9001"); 215 return B_OK; 216 } 217 218 sem_id vboxvideo_accelerant_retrace_semaphore(void) { 219 TRACE("%s\n", __FUNCTION__); 220 return -1; 80 static engine_token sEngineToken = { 1, 0 /*B_2D_ACCELERATION*/, NULL }; 81 82 extern "C" 83 void* get_accelerant_hook(uint32 feature, void *data) 84 { 85 TRACE("%s\n", __FUNCTION__); 86 switch (feature) 87 { 88 /* general */ 89 case B_INIT_ACCELERANT: 90 return (void *)vboxvideo_init_accelerant; 91 case B_UNINIT_ACCELERANT: 92 return (void *)vboxvideo_uninit_accelerant; 93 case B_CLONE_ACCELERANT: 94 return (void *)vboxvideo_clone_accelerant; 95 case B_ACCELERANT_CLONE_INFO_SIZE: 96 return (void *)vboxvideo_accelerant_clone_info_size; 97 case B_GET_ACCELERANT_CLONE_INFO: 98 return (void *)vboxvideo_get_accelerant_clone_info; 99 case B_GET_ACCELERANT_DEVICE_INFO: 100 return (void *)vboxvideo_get_accelerant_device_info; 101 case B_ACCELERANT_RETRACE_SEMAPHORE: 102 return (void *)vboxvideo_accelerant_retrace_semaphore; 103 104 /* mode configuration */ 105 case B_ACCELERANT_MODE_COUNT: 106 return (void *)vboxvideo_accelerant_mode_count; 107 case B_GET_MODE_LIST: 108 return (void *)vboxvideo_get_mode_list; 109 case B_SET_DISPLAY_MODE: 110 return (void *)vboxvideo_set_display_mode; 111 case B_GET_DISPLAY_MODE: 112 return (void *)vboxvideo_get_display_mode; 113 case B_GET_EDID_INFO: 114 return (void *)vboxvideo_get_edid_info; 115 case B_GET_FRAME_BUFFER_CONFIG: 116 return (void *)vboxvideo_get_frame_buffer_config; 117 case B_GET_PIXEL_CLOCK_LIMITS: 118 return (void *)vboxvideo_get_pixel_clock_limits; 119 120 /* cursor managment */ 121 /*case B_SET_CURSOR_SHAPE: 122 return (void*)vboxvideo_set_cursor_shape; 123 case B_MOVE_CURSOR: 124 return (void*)vboxvideo_move_cursor; 125 case B_SHOW_CURSOR: 126 return (void*)vboxvideo_show_cursor;*/ 127 128 /* engine/synchronization */ 129 case B_ACCELERANT_ENGINE_COUNT: 130 return (void *)vboxvideo_accelerant_engine_count; 131 case B_ACQUIRE_ENGINE: 132 return (void *)vboxvideo_acquire_engine; 133 case B_RELEASE_ENGINE: 134 return (void *)vboxvideo_release_engine; 135 case B_WAIT_ENGINE_IDLE: 136 return (void *)vboxvideo_wait_engine_idle; 137 case B_GET_SYNC_TOKEN: 138 return (void *)vboxvideo_get_sync_token; 139 case B_SYNC_TO_TOKEN: 140 return (void *)vboxvideo_sync_to_token; 141 } 142 143 return NULL; 144 } 145 146 status_t vboxvideo_init_common(int fd, bool cloned) 147 { 148 unlink("/var/log/vboxvideo.accelerant.log"); // clear old log - next TRACE() will recreate it 149 TRACE("%s\n", __FUNCTION__); 150 151 gInfo.deviceFD = fd; 152 gInfo.isClone = cloned; 153 gInfo.sharedInfo = NULL; 154 gInfo.sharedInfoArea = -1; 155 156 area_id sharedArea; 157 if (ioctl(gInfo.deviceFD, VBOXVIDEO_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) != 0) 158 { 159 TRACE("ioctl failed\n"); 160 return B_ERROR; 161 } 162 163 AreaCloner sharedCloner; 164 gInfo.sharedInfoArea = sharedCloner.Clone("vboxvideo shared info", 165 (void **)&gInfo.sharedInfo, B_ANY_ADDRESS, 166 B_READ_AREA | B_WRITE_AREA, sharedArea); 167 status_t status = sharedCloner.InitCheck(); 168 if (status < B_OK) 169 { 170 TRACE("InitCheck failed (%s)\n", strerror(status)); 171 return status; 172 } 173 sharedCloner.Keep(); 174 175 return B_OK; 176 } 177 178 status_t vboxvideo_init_accelerant(int fd) 179 { 180 return vboxvideo_init_common(fd, false); 181 } 182 183 ssize_t vboxvideo_accelerant_clone_info_size(void) 184 { 185 TRACE("%s\n", __FUNCTION__); 186 return B_PATH_NAME_LENGTH; 187 } 188 189 void vboxvideo_get_accelerant_clone_info(void *data) 190 { 191 TRACE("%s\n", __FUNCTION__); 192 ioctl(gInfo.deviceFD, VBOXVIDEO_GET_DEVICE_NAME, data, B_PATH_NAME_LENGTH); 193 } 194 195 status_t vboxvideo_clone_accelerant(void *data) 196 { 197 TRACE("%s\n", __FUNCTION__); 198 199 // create full device name 200 char path[MAXPATHLEN]; 201 strcpy(path, "/dev/"); 202 strcat(path, (const char *)data); 203 204 int fd = open(path, B_READ_WRITE); 205 if (fd < 0) 206 return errno; 207 208 return vboxvideo_init_common(fd, true); 209 } 210 211 void vboxvideo_uninit_accelerant(void) 212 { 213 delete_area(gInfo.sharedInfoArea); 214 gInfo.sharedInfo = NULL; 215 gInfo.sharedInfoArea = -1; 216 217 if (gInfo.isClone) 218 close(gInfo.deviceFD); 219 220 TRACE("%s\n", __FUNCTION__); 221 } 222 223 status_t vboxvideo_get_accelerant_device_info(accelerant_device_info *adi) 224 { 225 TRACE("%s\n", __FUNCTION__); 226 adi->version = B_ACCELERANT_VERSION; 227 strcpy(adi->name, "Virtual display"); 228 strcpy(adi->chipset, "VirtualBox Graphics Adapter"); 229 strcpy(adi->serial_no, "9001"); 230 return B_OK; 231 } 232 233 sem_id vboxvideo_accelerant_retrace_semaphore(void) 234 { 235 TRACE("%s\n", __FUNCTION__); 236 return -1; 221 237 } 222 238 223 239 // modes & constraints 224 uint32 vboxvideo_accelerant_mode_count(void) { 225 TRACE("%s\n", __FUNCTION__); 226 return 1; 227 } 228 229 status_t vboxvideo_get_mode_list(display_mode *dm) { 230 // TODO return some standard modes here 231 TRACE("%s\n", __FUNCTION__); 232 return vboxvideo_get_display_mode(dm); 233 } 234 235 status_t vboxvideo_set_display_mode(display_mode *modeToSet) { 236 TRACE("%s\n", __FUNCTION__); 237 TRACE("trying to set mode %dx%d\n", modeToSet->timing.h_display, modeToSet->timing.v_display); 238 return ioctl(gInfo.deviceFD, VBOXVIDEO_SET_DISPLAY_MODE, modeToSet, sizeof(display_mode)); 239 } 240 241 status_t vboxvideo_get_display_mode(display_mode *currentMode) { 242 TRACE("%s\n", __FUNCTION__); 243 *currentMode = gInfo.sharedInfo->currentMode; 244 TRACE("current mode is %dx%d\n", currentMode->timing.h_display, currentMode->timing.v_display); 245 return B_OK; 246 } 247 248 status_t vboxvideo_get_edid_info(void *info, size_t size, uint32 *_version) { 249 TRACE("%s\n", __FUNCTION__); 250 251 // copied from the X11 implementation: 252 static const uint8 edid_data[128] = { 253 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* header */ 254 0x58, 0x58, /* manufacturer (VBX) */ 255 0x00, 0x00, /* product code */ 256 0x00, 0x00, 0x00, 0x00, /* serial number goes here */ 257 0x01, /* week of manufacture */ 258 0x00, /* year of manufacture */ 259 0x01, 0x03, /* EDID version */ 260 0x80, /* capabilities - digital */ 261 0x00, /* horiz. res in cm, zero for projectors */ 262 0x00, /* vert. res in cm */ 263 0x78, /* display gamma (120 == 2.2). Should we ask the host for this? */ 264 0xEE, /* features (standby, suspend, off, RGB, standard colour space, 265 * preferred timing mode) */ 266 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54, 267 /* chromaticity for standard colour space - should we ask the host? */ 268 0x00, 0x00, 0x00, /* no default timings */ 269 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 270 0x01, 0x01, 0x01, 0x01, /* no standard timings */ 271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* descriptor block 1 goes here */ 273 0x00, 0x00, 0x00, 0xFD, 0x00, /* descriptor block 2, monitor ranges */ 274 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 275 0x20, /* 0-200Hz vertical, 0-200KHz horizontal, 1000MHz pixel clock */ 276 0x00, 0x00, 0x00, 0xFC, 0x00, /* descriptor block 3, monitor name */ 277 'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r', '\n', 278 0x00, 0x00, 0x00, 0x10, 0x00, /* descriptor block 4: dummy data */ 279 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 280 0x20, 281 0x00, /* number of extensions */ 282 0x00 /* checksum goes here */ 283 }; 284 285 if (size < 128) 286 return B_BUFFER_OVERFLOW; 287 288 *_version = 1; /*EDID_VERSION_1*/ 289 memcpy(info, edid_data, 128); 290 return B_OK; 291 } 292 293 status_t vboxvideo_get_frame_buffer_config(frame_buffer_config *config) { 294 TRACE("%s\n", __FUNCTION__); 295 config->frame_buffer = gInfo.sharedInfo->framebuffer; 296 config->frame_buffer_dma = NULL; 297 config->bytes_per_row = get_depth_for_color_space(gInfo.sharedInfo->currentMode.space) 298 * gInfo.sharedInfo->currentMode.timing.h_display / 8; 299 return B_OK; 300 } 301 302 status_t vboxvideo_get_pixel_clock_limits(display_mode *dm, uint32 *low, uint32 *high) { 303 TRACE("%s\n", __FUNCTION__); 304 // irrelevant for virtual monitors 305 *low = 0; 306 *high = 9001; 307 return B_OK; 240 uint32 vboxvideo_accelerant_mode_count(void) 241 { 242 TRACE("%s\n", __FUNCTION__); 243 return 1; 244 } 245 246 status_t vboxvideo_get_mode_list(display_mode *dm) 247 { 248 // TODO return some standard modes here 249 TRACE("%s\n", __FUNCTION__); 250 return vboxvideo_get_display_mode(dm); 251 } 252 253 status_t vboxvideo_set_display_mode(display_mode *modeToSet) 254 { 255 TRACE("%s\n", __FUNCTION__); 256 TRACE("trying to set mode %dx%d\n", modeToSet->timing.h_display, modeToSet->timing.v_display); 257 return ioctl(gInfo.deviceFD, VBOXVIDEO_SET_DISPLAY_MODE, modeToSet, sizeof(display_mode)); 258 } 259 260 status_t vboxvideo_get_display_mode(display_mode *currentMode) 261 { 262 TRACE("%s\n", __FUNCTION__); 263 *currentMode = gInfo.sharedInfo->currentMode; 264 TRACE("current mode is %dx%d\n", currentMode->timing.h_display, currentMode->timing.v_display); 265 return B_OK; 266 } 267 268 status_t vboxvideo_get_edid_info(void *info, size_t size, uint32 *_version) 269 { 270 TRACE("%s\n", __FUNCTION__); 271 272 // copied from the X11 implementation: 273 static const uint8 edid_data[128] = { 274 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* header */ 275 0x58, 0x58, /* manufacturer (VBX) */ 276 0x00, 0x00, /* product code */ 277 0x00, 0x00, 0x00, 0x00, /* serial number goes here */ 278 0x01, /* week of manufacture */ 279 0x00, /* year of manufacture */ 280 0x01, 0x03, /* EDID version */ 281 0x80, /* capabilities - digital */ 282 0x00, /* horiz. res in cm, zero for projectors */ 283 0x00, /* vert. res in cm */ 284 0x78, /* display gamma (120 == 2.2). Should we ask the host for this? */ 285 0xEE, /* features (standby, suspend, off, RGB, standard colour space, 286 * preferred timing mode) */ 287 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54, 288 /* chromaticity for standard colour space - should we ask the host? */ 289 0x00, 0x00, 0x00, /* no default timings */ 290 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 291 0x01, 0x01, 0x01, 0x01, /* no standard timings */ 292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* descriptor block 1 goes here */ 294 0x00, 0x00, 0x00, 0xFD, 0x00, /* descriptor block 2, monitor ranges */ 295 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 296 0x20, /* 0-200Hz vertical, 0-200KHz horizontal, 1000MHz pixel clock */ 297 0x00, 0x00, 0x00, 0xFC, 0x00, /* descriptor block 3, monitor name */ 298 'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r', '\n', 299 0x00, 0x00, 0x00, 0x10, 0x00, /* descriptor block 4: dummy data */ 300 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 301 0x20, 302 0x00, /* number of extensions */ 303 0x00 /* checksum goes here */ 304 }; 305 306 if (size < 128) 307 return B_BUFFER_OVERFLOW; 308 309 *_version = 1; /*EDID_VERSION_1*/ 310 memcpy(info, edid_data, 128); 311 return B_OK; 312 } 313 314 status_t vboxvideo_get_frame_buffer_config(frame_buffer_config *config) 315 { 316 TRACE("%s\n", __FUNCTION__); 317 config->frame_buffer = gInfo.sharedInfo->framebuffer; 318 config->frame_buffer_dma = NULL; 319 config->bytes_per_row = get_depth_for_color_space(gInfo.sharedInfo->currentMode.space) 320 * gInfo.sharedInfo->currentMode.timing.h_display / 8; 321 return B_OK; 322 } 323 324 status_t vboxvideo_get_pixel_clock_limits(display_mode *dm, uint32 *low, uint32 *high) 325 { 326 TRACE("%s\n", __FUNCTION__); 327 // irrelevant for virtual monitors 328 *low = 0; 329 *high = 9001; 330 return B_OK; 308 331 } 309 332 310 333 // cursor 311 status_t vboxvideo_set_cursor_shape(uint16 width, uint16 height, uint16 hotX, uint16 hotY, uint8 *andMask, uint8 *xorMask) { 312 TRACE("%s\n", __FUNCTION__); 313 // VBoxHGSMIUpdatePointerShape 314 return B_UNSUPPORTED; 315 } 316 317 void vboxvideo_move_cursor(uint16 x, uint16 y) { 318 TRACE("%s\n", __FUNCTION__); 319 } 320 321 void vboxvideo_show_cursor(bool is_visible) { 322 TRACE("%s\n", __FUNCTION__); 334 status_t vboxvideo_set_cursor_shape(uint16 width, uint16 height, uint16 hotX, uint16 hotY, uint8 *andMask, uint8 *xorMask) 335 { 336 TRACE("%s\n", __FUNCTION__); 337 // VBoxHGSMIUpdatePointerShape 338 return B_UNSUPPORTED; 339 } 340 341 void vboxvideo_move_cursor(uint16 x, uint16 y) 342 { 343 TRACE("%s\n", __FUNCTION__); 344 } 345 346 void vboxvideo_show_cursor(bool is_visible) 347 { 348 TRACE("%s\n", __FUNCTION__); 323 349 } 324 350 325 351 // accelerant engine 326 uint32 vboxvideo_accelerant_engine_count(void) { 327 TRACE("%s\n", __FUNCTION__); 328 return 1; 329 } 330 331 status_t vboxvideo_acquire_engine(uint32 capabilities, uint32 maxWait, sync_token *st, engine_token **et) { 332 TRACE("%s\n", __FUNCTION__); 333 *et = &sEngineToken; 334 return B_OK; 335 } 336 337 status_t vboxvideo_release_engine(engine_token *et, sync_token *st) { 338 TRACE("%s\n", __FUNCTION__); 339 if (st != NULL) 340 st->engine_id = et->engine_id; 341 342 return B_OK; 343 } 344 345 void vboxvideo_wait_engine_idle(void) { 346 TRACE("%s\n", __FUNCTION__); 347 } 348 349 status_t vboxvideo_get_sync_token(engine_token *et, sync_token *st) { 350 TRACE("%s\n", __FUNCTION__); 351 return B_OK; 352 } 353 354 status_t vboxvideo_sync_to_token(sync_token *st) { 355 TRACE("%s\n", __FUNCTION__); 356 return B_OK; 352 uint32 vboxvideo_accelerant_engine_count(void) 353 { 354 TRACE("%s\n", __FUNCTION__); 355 return 1; 356 } 357 358 status_t vboxvideo_acquire_engine(uint32 capabilities, uint32 maxWait, sync_token *st, engine_token **et) 359 { 360 TRACE("%s\n", __FUNCTION__); 361 *et = &sEngineToken; 362 return B_OK; 363 } 364 365 status_t vboxvideo_release_engine(engine_token *et, sync_token *st) 366 { 367 TRACE("%s\n", __FUNCTION__); 368 if (st != NULL) 369 st->engine_id = et->engine_id; 370 371 return B_OK; 372 } 373 374 void vboxvideo_wait_engine_idle(void) 375 { 376 TRACE("%s\n", __FUNCTION__); 377 } 378 379 status_t vboxvideo_get_sync_token(engine_token *et, sync_token *st) 380 { 381 TRACE("%s\n", __FUNCTION__); 382 return B_OK; 383 } 384 385 status_t vboxvideo_sync_to_token(sync_token *st) 386 { 387 TRACE("%s\n", __FUNCTION__); 388 return B_OK; 357 389 } 358 390 359 391 // 2D acceleration 360 void vboxvideo_screen_to_screen_blit(engine_token *et, blit_params *list, uint32 count) { 361 TRACE("%s\n", __FUNCTION__); 362 } 363 364 void vboxvideo_fill_rectangle(engine_token *et, uint32 color, fill_rect_params *list, uint32 count) { 365 TRACE("%s\n", __FUNCTION__); 366 } 367 368 void vboxvideo_invert_rectangle(engine_token *et, fill_rect_params *list, uint32 count) { 369 TRACE("%s\n", __FUNCTION__); 370 } 371 372 void vboxvideo_fill_span(engine_token *et, uint32 color, uint16 *list, uint32 count) { 373 TRACE("%s\n", __FUNCTION__); 374 } 392 void vboxvideo_screen_to_screen_blit(engine_token *et, blit_params *list, uint32 count) 393 { 394 TRACE("%s\n", __FUNCTION__); 395 } 396 397 void vboxvideo_fill_rectangle(engine_token *et, uint32 color, fill_rect_params *list, uint32 count) 398 { 399 TRACE("%s\n", __FUNCTION__); 400 } 401 402 void vboxvideo_invert_rectangle(engine_token *et, fill_rect_params *list, uint32 count) 403 { 404 TRACE("%s\n", __FUNCTION__); 405 } 406 407 void vboxvideo_fill_span(engine_token *et, uint32 color, uint16 *list, uint32 count) 408 { 409 TRACE("%s\n", __FUNCTION__); 410 } -
trunk/src/VBox/Additions/haiku/VBoxVideo/accelerant/accelerant.h
r43363 r43364 51 51 #include "../common/VBoxVideo_common.h" 52 52 53 struct AccelerantInfo { 54 int deviceFD; 55 bool isClone; 53 struct AccelerantInfo 54 { 55 int deviceFD; 56 bool isClone; 56 57 57 SharedInfo*sharedInfo;58 58 SharedInfo *sharedInfo; 59 area_id sharedInfoArea; 59 60 }; 60 61 extern AccelerantInfo gInfo; … … 97 98 void vboxvideo_fill_span(engine_token *et, uint32 color, uint16 *list, uint32 count); 98 99 99 #endif 100 #endif /* _ACCELERANT_PROTOS_H */ -
trunk/src/VBox/Additions/haiku/VBoxVideo/common/VBoxVideo_common.h
r43363 r43364 52 52 #include <PCI.h> 53 53 54 struct SharedInfo {55 display_mode currentMode; 56 57 58 void*framebuffer;54 struct SharedInfo 55 { 56 display_mode currentMode; 57 area_id framebufferArea; 58 void *framebuffer; 59 59 }; 60 60 61 enum { 62 VBOXVIDEO_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, 63 VBOXVIDEO_GET_DEVICE_NAME, 64 VBOXVIDEO_SET_DISPLAY_MODE 61 enum 62 { 63 VBOXVIDEO_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, 64 VBOXVIDEO_GET_DEVICE_NAME, 65 VBOXVIDEO_SET_DISPLAY_MODE 65 66 }; 66 67 67 68 static inline uint32 get_color_space_for_depth(uint32 depth) 68 69 { 69 switch (depth) { 70 case 1: 71 return B_GRAY1; 72 case 4: 73 return B_GRAY8; 74 // the app_server is smart enough to translate this to VGA mode 75 case 8: 76 return B_CMAP8; 77 case 15: 78 return B_RGB15; 79 case 16: 80 return B_RGB16; 81 case 24: 82 return B_RGB24; 83 case 32: 84 return B_RGB32; 85 } 70 switch (depth) 71 { 72 case 1: return B_GRAY1; 73 case 4: return B_GRAY8; 74 // the app_server is smart enough to translate this to VGA mode 75 case 8: return B_CMAP8; 76 case 15: return B_RGB15; 77 case 16: return B_RGB16; 78 case 24: return B_RGB24; 79 case 32: return B_RGB32; 80 } 86 81 87 82 return 0; 88 83 } 89 84 90 85 static inline uint32 get_depth_for_color_space(uint32 depth) 91 86 { 92 switch (depth) { 93 case B_GRAY1: 94 return 1; 95 case B_GRAY8: 96 return 4; 97 case B_CMAP8: 98 return 8; 99 case B_RGB15: 100 return 15; 101 case B_RGB16: 102 return 16; 103 case B_RGB24: 104 return 24; 105 case B_RGB32: 106 return 32; 107 } 108 109 return 0; 87 switch (depth) 88 { 89 case B_GRAY1: return 1; 90 case B_GRAY8: return 4; 91 case B_CMAP8: return 8; 92 case B_RGB15: return 15; 93 case B_RGB16: return 16; 94 case B_RGB24: return 24; 95 case B_RGB32: return 32; 96 } 97 return 0; 110 98 } 111 99 112 #endif 100 #endif /* _VBOXVIDEO_COMMON_H */ 101 -
trunk/src/VBox/Additions/haiku/VBoxVideo/driver/driver.cpp
r43363 r43364 66 66 #undef TRACE 67 67 #ifdef ENABLE_DEBUG_TRACE 68 # 68 #define TRACE(x...) dprintf("VBoxVideo: " x) 69 69 #else 70 # 70 #define TRACE(x...) ; 71 71 #endif 72 72 … … 75 75 extern "C" status_t vm_set_area_memory_type(area_id id, phys_addr_t physicalBase, uint32 type); 76 76 77 struct Benaphore { 78 sem_id sem; 79 int32 count; 80 81 status_t Init(const char* name) 82 { 83 count = 0; 84 sem = create_sem(0, name); 85 return sem < 0 ? sem : B_OK; 86 } 87 88 status_t Acquire() 89 { 90 if (atomic_add(&count, 1) > 0) 91 return acquire_sem(sem); 92 return B_OK; 93 } 94 95 status_t Release() 96 { 97 if (atomic_add(&count, -1) > 1) 98 return release_sem(sem); 99 return B_OK; 100 } 101 102 void Delete() { delete_sem(sem); } 77 struct Benaphore 78 { 79 sem_id sem; 80 int32 count; 81 82 status_t Init(const char *name) 83 { 84 count = 0; 85 sem = create_sem(0, name); 86 return sem < 0 ? sem : B_OK; 87 } 88 89 status_t Acquire() 90 { 91 if (atomic_add(&count, 1) > 0) 92 return acquire_sem(sem); 93 return B_OK; 94 } 95 96 status_t Release() 97 { 98 if (atomic_add(&count, -1) > 1) 99 return release_sem(sem); 100 return B_OK; 101 } 102 103 void Delete() 104 { 105 delete_sem(sem); 106 } 103 107 }; 104 108 105 struct DeviceInfo { 106 uint32 openCount; // count of how many times device has been opened 107 uint32 flags; 108 area_id sharedArea; // area shared between driver and all accelerants 109 SharedInfo* sharedInfo; // pointer to shared info area memory 110 pci_info pciInfo; // copy of pci info for this device 111 char name[B_OS_NAME_LENGTH]; // name of device 109 struct DeviceInfo 110 { 111 uint32 openCount; // count of how many times device has been opened 112 uint32 flags; // device flags 113 area_id sharedArea; // area shared between driver and all accelerants 114 SharedInfo *sharedInfo; // pointer to shared info area memory 115 pci_info pciInfo; // copy of pci info for this device 116 char name[B_OS_NAME_LENGTH]; // name of device 112 117 }; 113 118 114 119 // at most one virtual video card ever appears, no reason for this to be an array 115 120 static DeviceInfo gDeviceInfo; 116 static char * gDeviceNames[2] = {gDeviceInfo.name, NULL};121 static char *gDeviceNames[2] = { gDeviceInfo.name, NULL }; 117 122 static bool gCanHasDevice = false; // is the device present? 118 123 static Benaphore gLock; 119 static pci_module_info *gPCI;120 121 status_t device_open(const char * name, uint32 flags, void**cookie);122 status_t device_close(void *dev);123 status_t device_free(void *dev);124 status_t device_read(void * dev, off_t pos, void* buf, size_t*len);125 status_t device_write(void * dev, off_t pos, const void* buf, size_t*len);126 status_t device_ioctl(void * dev, uint32 msg, void*buf, size_t len);124 static pci_module_info *gPCI; 125 126 status_t device_open(const char *name, uint32 flags, void **cookie); 127 status_t device_close(void *dev); 128 status_t device_free(void *dev); 129 status_t device_read(void *dev, off_t pos, void *buf, size_t *len); 130 status_t device_write(void *dev, off_t pos, const void *buf, size_t *len); 131 status_t device_ioctl(void *dev, uint32 msg, void *buf, size_t len); 127 132 static uint32 get_color_space_for_depth(uint32 depth); 128 133 129 static device_hooks gDeviceHooks = { 130 device_open, // open 131 device_close, // close 132 device_free, // free 133 device_ioctl, // control 134 device_read, // read 135 device_write, // write 136 NULL, // select 137 NULL, // deselect 138 NULL, // read_pages 139 NULL // write_pages 134 static device_hooks gDeviceHooks = 135 { 136 device_open, // open 137 device_close, // close 138 device_free, // free 139 device_ioctl, // control 140 device_read, // read 141 device_write, // write 142 NULL, // select 143 NULL, // deselect 144 NULL, // read_pages 145 NULL // write_pages 140 146 }; 141 147 142 148 status_t init_hardware() 143 149 { 144 TRACE("init_hardware\n"); 145 146 if (get_module(VBOXGUEST_MODULE_NAME, (module_info **)&g_VBoxGuest) != B_OK) { 147 dprintf("get_module(%s) failed\n", VBOXGUEST_MODULE_NAME); 148 return B_ERROR; 149 } 150 151 if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI) != B_OK) { 152 dprintf("get_module(%s) failed\n", B_PCI_MODULE_NAME); 153 return B_ERROR; 154 } 155 156 return B_OK; 150 TRACE("init_hardware\n"); 151 152 if (get_module(VBOXGUEST_MODULE_NAME, (module_info **)&g_VBoxGuest) != B_OK) 153 { 154 dprintf("get_module(%s) failed\n", VBOXGUEST_MODULE_NAME); 155 return B_ERROR; 156 } 157 158 if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI) != B_OK) 159 { 160 dprintf("get_module(%s) failed\n", B_PCI_MODULE_NAME); 161 return B_ERROR; 162 } 163 164 return B_OK; 157 165 } 158 166 159 167 status_t init_driver() 160 168 { 161 TRACE("init_driver\n"); 162 163 gLock.Init("VBoxVideo driver lock"); 164 165 uint32 pciIndex = 0; 166 167 while (gPCI->get_nth_pci_info(pciIndex, &gDeviceInfo.pciInfo) == B_OK) { 168 if (gDeviceInfo.pciInfo.vendor_id == VENDOR_ID && gDeviceInfo.pciInfo.device_id == DEVICE_ID) { 169 sprintf(gDeviceInfo.name, "graphics/" DEVICE_FORMAT, 170 gDeviceInfo.pciInfo.vendor_id, gDeviceInfo.pciInfo.device_id, 171 gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function); 172 TRACE("found device %s\n", gDeviceInfo.name); 173 174 gCanHasDevice = true; 175 gDeviceInfo.openCount = 0; 176 177 size_t sharedSize = (sizeof(SharedInfo) + 7) & ~7; 178 gDeviceInfo.sharedArea = create_area("vboxvideo shared info", 179 (void**)&gDeviceInfo.sharedInfo, B_ANY_KERNEL_ADDRESS, 180 ROUND_TO_PAGE_SIZE(sharedSize), B_FULL_LOCK, 181 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA); 182 183 uint16_t width, height, vwidth, bpp, flags; 184 VBoxVideoGetModeRegisters(&width, &height, &vwidth, &bpp, &flags); 185 186 gDeviceInfo.sharedInfo->currentMode.space = get_color_space_for_depth(bpp); 187 gDeviceInfo.sharedInfo->currentMode.virtual_width = width; 188 gDeviceInfo.sharedInfo->currentMode.virtual_height = height; 189 gDeviceInfo.sharedInfo->currentMode.h_display_start = 0; 190 gDeviceInfo.sharedInfo->currentMode.v_display_start = 0; 191 gDeviceInfo.sharedInfo->currentMode.flags = 0; 192 gDeviceInfo.sharedInfo->currentMode.timing.h_display = width; 193 gDeviceInfo.sharedInfo->currentMode.timing.v_display = height; 194 // not used, but this makes a reasonable-sounding refresh rate show in screen prefs: 195 gDeviceInfo.sharedInfo->currentMode.timing.h_total = 1000; 196 gDeviceInfo.sharedInfo->currentMode.timing.v_total = 1; 197 gDeviceInfo.sharedInfo->currentMode.timing.pixel_clock = 850; 198 199 // map the PCI memory space 200 uint32 command_reg = gPCI->read_pci_config(gDeviceInfo.pciInfo.bus, 201 gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function, PCI_command, 2); 202 command_reg |= PCI_command_io | PCI_command_memory | PCI_command_master; 203 gPCI->write_pci_config(gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device, 204 gDeviceInfo.pciInfo.function, PCI_command, 2, command_reg); 205 206 gDeviceInfo.sharedInfo->framebufferArea = 207 map_physical_memory("vboxvideo framebuffer", (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0], 208 gDeviceInfo.pciInfo.u.h0.base_register_sizes[0], B_ANY_KERNEL_BLOCK_ADDRESS, 209 B_READ_AREA | B_WRITE_AREA, &(gDeviceInfo.sharedInfo->framebuffer)); 210 vm_set_area_memory_type(gDeviceInfo.sharedInfo->framebufferArea, 211 (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0], B_MTR_WC); 212 213 break; 214 } 215 216 pciIndex++; 217 } 218 219 return B_OK; 220 } 169 TRACE("init_driver\n"); 170 171 gLock.Init("VBoxVideo driver lock"); 172 173 uint32 pciIndex = 0; 174 175 while (gPCI->get_nth_pci_info(pciIndex, &gDeviceInfo.pciInfo) == B_OK) 176 { 177 if (gDeviceInfo.pciInfo.vendor_id == VENDOR_ID && gDeviceInfo.pciInfo.device_id == DEVICE_ID) 178 { 179 sprintf(gDeviceInfo.name, "graphics/" DEVICE_FORMAT, 180 gDeviceInfo.pciInfo.vendor_id, gDeviceInfo.pciInfo.device_id, 181 gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function); 182 TRACE("found device %s\n", gDeviceInfo.name); 183 184 gCanHasDevice = true; 185 gDeviceInfo.openCount = 0; 186 187 size_t sharedSize = (sizeof(SharedInfo) + 7) & ~7; 188 gDeviceInfo.sharedArea = create_area("vboxvideo shared info", 189 (void **)&gDeviceInfo.sharedInfo, B_ANY_KERNEL_ADDRESS, 190 ROUND_TO_PAGE_SIZE(sharedSize), B_FULL_LOCK, 191 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA); 192 193 uint16_t width, height, vwidth, bpp, flags; 194 VBoxVideoGetModeRegisters(&width, &height, &vwidth, &bpp, &flags); 195 196 gDeviceInfo.sharedInfo->currentMode.space = get_color_space_for_depth(bpp); 197 gDeviceInfo.sharedInfo->currentMode.virtual_width = width; 198 gDeviceInfo.sharedInfo->currentMode.virtual_height = height; 199 gDeviceInfo.sharedInfo->currentMode.h_display_start = 0; 200 gDeviceInfo.sharedInfo->currentMode.v_display_start = 0; 201 gDeviceInfo.sharedInfo->currentMode.flags = 0; 202 gDeviceInfo.sharedInfo->currentMode.timing.h_display = width; 203 gDeviceInfo.sharedInfo->currentMode.timing.v_display = height; 204 // not used, but this makes a reasonable-sounding refresh rate show in screen prefs: 205 gDeviceInfo.sharedInfo->currentMode.timing.h_total = 1000; 206 gDeviceInfo.sharedInfo->currentMode.timing.v_total = 1; 207 gDeviceInfo.sharedInfo->currentMode.timing.pixel_clock = 850; 208 209 // map the PCI memory space 210 uint32 command_reg = gPCI->read_pci_config(gDeviceInfo.pciInfo.bus, 211 gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function, PCI_command, 2); 212 command_reg |= PCI_command_io | PCI_command_memory | PCI_command_master; 213 gPCI->write_pci_config(gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device, 214 gDeviceInfo.pciInfo.function, PCI_command, 2, command_reg); 215 216 gDeviceInfo.sharedInfo->framebufferArea = map_physical_memory("vboxvideo framebuffer", 217 (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0], 218 gDeviceInfo.pciInfo.u.h0.base_register_sizes[0], B_ANY_KERNEL_BLOCK_ADDRESS, 219 B_READ_AREA | B_WRITE_AREA, &(gDeviceInfo.sharedInfo->framebuffer)); 220 vm_set_area_memory_type(gDeviceInfo.sharedInfo->framebufferArea, 221 (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0], B_MTR_WC); 222 break; 223 } 224 225 pciIndex++; 226 } 227 228 return B_OK; 229 } 230 221 231 222 232 const char** publish_devices() 223 233 { 224 TRACE("publish_devices\n"); 225 if (gCanHasDevice) { 226 return (const char**)gDeviceNames; 227 } 228 else { 229 return NULL; 230 } 231 } 232 233 device_hooks* find_device(const char* name) 234 { 235 TRACE("find_device\n"); 236 if (gCanHasDevice && strcmp(name, gDeviceInfo.name) == 0) { 237 return &gDeviceHooks; 238 } 239 else { 240 return NULL; 241 } 242 } 234 TRACE("publish_devices\n"); 235 if (gCanHasDevice) 236 return (const char **)gDeviceNames; 237 return NULL; 238 } 239 240 241 device_hooks* find_device(const char *name) 242 { 243 TRACE("find_device\n"); 244 if (gCanHasDevice && strcmp(name, gDeviceInfo.name) == 0) 245 return &gDeviceHooks; 246 247 return NULL; 248 } 249 243 250 244 251 void uninit_driver() 245 252 { 246 TRACE("uninit_driver\n"); 247 gLock.Delete(); 248 put_module(VBOXGUEST_MODULE_NAME); 249 } 250 251 status_t device_open(const char* name, uint32 flags, void** cookie) 252 { 253 TRACE("device_open\n"); 254 255 if (!gCanHasDevice || strcmp(name, gDeviceInfo.name) != 0) 256 return B_BAD_VALUE; 257 258 // TODO init device! 259 260 *cookie = (void*)&gDeviceInfo; 261 262 return B_OK; 263 } 264 265 status_t device_close(void* dev) 266 { 267 TRACE("device_close\n"); 268 return B_ERROR; 269 } 270 271 status_t device_free(void* dev) 272 { 273 TRACE("device_free\n"); 274 275 DeviceInfo& di = *(DeviceInfo*)dev; 276 gLock.Acquire(); 277 278 if (di.openCount <= 1) { 279 // TODO deinit device! 280 281 delete_area(di.sharedArea); 282 di.sharedArea = -1; 283 di.sharedInfo = NULL; 284 } 285 286 if (di.openCount > 0) 287 di.openCount--; 288 289 gLock.Release(); 290 291 return B_OK; 292 } 293 294 status_t device_read(void* dev, off_t pos, void* buf, size_t* len) 295 { 296 TRACE("device_read\n"); 297 return B_NOT_ALLOWED; 298 } 299 300 status_t device_write(void* dev, off_t pos, const void* buf, size_t* len) 301 { 302 TRACE("device_write\n"); 303 return B_NOT_ALLOWED; 304 } 305 306 status_t device_ioctl(void* cookie, uint32 msg, void* buf, size_t len) 307 { 308 TRACE("device_ioctl\n"); 309 310 DeviceInfo* dev = (DeviceInfo*)cookie; 311 312 switch (msg) { 313 case B_GET_ACCELERANT_SIGNATURE: 314 strcpy((char*)buf, "vboxvideo.accelerant"); 315 return B_OK; 316 317 case VBOXVIDEO_GET_PRIVATE_DATA: 318 return user_memcpy(buf, &dev->sharedArea, sizeof(area_id)); 319 320 case VBOXVIDEO_GET_DEVICE_NAME: 321 if (user_strlcpy((char*)buf, gDeviceInfo.name, len) < B_OK) 322 return B_BAD_ADDRESS; 323 else 324 return B_OK; 325 326 case VBOXVIDEO_SET_DISPLAY_MODE: { 327 display_mode* mode = (display_mode*)buf; 328 VBoxVideoSetModeRegisters(mode->timing.h_display, mode->timing.v_display, 329 mode->timing.h_display, get_depth_for_color_space(mode->space), 0, 0, 0); 330 gDeviceInfo.sharedInfo->currentMode = *mode; 331 return B_OK; 332 } 333 default: 334 return B_BAD_VALUE; 335 } 336 337 } 253 TRACE("uninit_driver\n"); 254 gLock.Delete(); 255 put_module(VBOXGUEST_MODULE_NAME); 256 } 257 258 status_t device_open(const char *name, uint32 flags, void **cookie) 259 { 260 TRACE("device_open\n"); 261 262 if (!gCanHasDevice || strcmp(name, gDeviceInfo.name) != 0) 263 return B_BAD_VALUE; 264 265 // TODO init device! 266 267 *cookie = (void *)&gDeviceInfo; 268 return B_OK; 269 } 270 271 272 status_t device_close(void *dev) 273 { 274 TRACE("device_close\n"); 275 return B_ERROR; 276 } 277 278 279 status_t device_free(void *dev) 280 { 281 TRACE("device_free\n"); 282 283 DeviceInfo& di = *(DeviceInfo *)dev; 284 gLock.Acquire(); 285 286 if (di.openCount <= 1) 287 { 288 // TODO deinit device! 289 delete_area(di.sharedArea); 290 di.sharedArea = -1; 291 di.sharedInfo = NULL; 292 } 293 294 if (di.openCount > 0) 295 di.openCount--; 296 297 gLock.Release(); 298 299 return B_OK; 300 } 301 302 303 status_t device_read(void *dev, off_t pos, void *buf, size_t *len) 304 { 305 TRACE("device_read\n"); 306 return B_NOT_ALLOWED; 307 } 308 309 310 status_t device_write(void *dev, off_t pos, const void *buf, size_t *len) 311 { 312 TRACE("device_write\n"); 313 return B_NOT_ALLOWED; 314 } 315 316 317 status_t device_ioctl(void *cookie, uint32 msg, void *buf, size_t len) 318 { 319 TRACE("device_ioctl\n"); 320 321 DeviceInfo *dev = (DeviceInfo *)cookie; 322 323 switch (msg) 324 { 325 case B_GET_ACCELERANT_SIGNATURE: 326 strcpy((char *)buf, "vboxvideo.accelerant"); 327 return B_OK; 328 329 case VBOXVIDEO_GET_PRIVATE_DATA: 330 return user_memcpy(buf, &dev->sharedArea, sizeof(area_id)); 331 332 case VBOXVIDEO_GET_DEVICE_NAME: 333 if (user_strlcpy((char *)buf, gDeviceInfo.name, len) < B_OK) 334 return B_BAD_ADDRESS; 335 else 336 return B_OK; 337 338 case VBOXVIDEO_SET_DISPLAY_MODE: 339 { 340 display_mode *mode = (display_mode *)buf; 341 VBoxVideoSetModeRegisters(mode->timing.h_display, mode->timing.v_display, 342 mode->timing.h_display, get_depth_for_color_space(mode->space), 0, 0, 0); 343 gDeviceInfo.sharedInfo->currentMode = *mode; 344 return B_OK; 345 } 346 default: 347 return B_BAD_VALUE; 348 } 349 350 } 351
Note:
See TracChangeset
for help on using the changeset viewer.