1/* 2 * Copyright (c) 1998-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <sys/errno.h> 25#include <sys/proc.h> 26#include <IOKit/storage/IODVDMediaBSDClient.h> 27 28#define super IOMediaBSDClient 29OSDefineMetaClassAndStructors(IODVDMediaBSDClient, IOMediaBSDClient) 30 31typedef struct 32{ 33 uint8_t format; 34 35 uint8_t reserved0008[3]; 36 37 uint32_t address; 38 uint8_t grantID; 39 uint8_t layer; 40 41 uint16_t bufferLength; 42 user32_addr_t buffer; 43} dk_dvd_read_structure_32_t; 44 45typedef struct 46{ 47 uint8_t format; 48 49 uint8_t reserved0008[3]; 50 51 uint32_t address; 52 uint8_t grantID; 53 uint8_t layer; 54 55 uint8_t reserved0080[4]; 56 57 uint16_t bufferLength; 58 user64_addr_t buffer; 59} dk_dvd_read_structure_64_t; 60 61typedef struct 62{ 63 uint8_t format; 64 uint8_t keyClass; 65 66 uint8_t reserved0016[2]; 67 68 uint32_t address; 69 uint8_t grantID; 70 71 uint8_t reserved0072[1]; 72 73 uint16_t bufferLength; 74 user32_addr_t buffer; 75} dk_dvd_report_key_32_t; 76 77typedef struct 78{ 79 uint8_t format; 80 uint8_t keyClass; 81 82 uint8_t reserved0016[2]; 83 84 uint32_t address; 85 uint8_t grantID; 86 87 uint8_t reserved0072[5]; 88 89 uint16_t bufferLength; 90 user64_addr_t buffer; 91} dk_dvd_report_key_64_t; 92 93typedef struct 94{ 95 uint8_t format; 96 uint8_t keyClass; 97 98 uint8_t reserved0016[6]; 99 100 uint8_t grantID; 101 102 uint8_t reserved0072[1]; 103 104 uint16_t bufferLength; 105 user32_addr_t buffer; 106} dk_dvd_send_key_32_t; 107 108typedef struct 109{ 110 uint8_t format; 111 uint8_t keyClass; 112 113 uint8_t reserved0016[6]; 114 115 uint8_t grantID; 116 117 uint8_t reserved0072[5]; 118 119 uint16_t bufferLength; 120 user64_addr_t buffer; 121} dk_dvd_send_key_64_t; 122 123typedef struct 124{ 125 uint8_t reserved0000[10]; 126 127 uint16_t bufferLength; 128 user32_addr_t buffer; 129} dk_dvd_read_disc_info_32_t; 130 131typedef struct 132{ 133 uint8_t reserved0000[14]; 134 135 uint16_t bufferLength; 136 user64_addr_t buffer; 137} dk_dvd_read_disc_info_64_t; 138 139typedef struct 140{ 141 uint8_t reserved0000[4]; 142 143 uint32_t address; 144 uint8_t addressType; 145 146 uint8_t reserved0072[1]; 147 148 uint16_t bufferLength; 149 user32_addr_t buffer; 150} dk_dvd_read_rzone_info_32_t; 151 152typedef struct 153{ 154 uint8_t reserved0000[4]; 155 156 uint32_t address; 157 uint8_t addressType; 158 159 uint8_t reserved0072[5]; 160 161 uint16_t bufferLength; 162 user64_addr_t buffer; 163} dk_dvd_read_rzone_info_64_t; 164 165#define DKIOCDVDREADSTRUCTURE32 _IOW('d', 128, dk_dvd_read_structure_32_t) 166#define DKIOCDVDREADSTRUCTURE64 _IOW('d', 128, dk_dvd_read_structure_64_t) 167#define DKIOCDVDREPORTKEY32 _IOW('d', 129, dk_dvd_report_key_32_t) 168#define DKIOCDVDREPORTKEY64 _IOW('d', 129, dk_dvd_report_key_64_t) 169#define DKIOCDVDSENDKEY32 _IOW('d', 130, dk_dvd_send_key_32_t) 170#define DKIOCDVDSENDKEY64 _IOW('d', 130, dk_dvd_send_key_64_t) 171 172#define DKIOCDVDREADDISCINFO32 _IOWR('d', 132, dk_dvd_read_disc_info_32_t) 173#define DKIOCDVDREADDISCINFO64 _IOWR('d', 132, dk_dvd_read_disc_info_64_t) 174#define DKIOCDVDREADRZONEINFO32 _IOWR('d', 133, dk_dvd_read_rzone_info_32_t) 175#define DKIOCDVDREADRZONEINFO64 _IOWR('d', 133, dk_dvd_read_rzone_info_64_t) 176 177static bool DKIOC_IS_RESERVED(caddr_t data, uint32_t reserved) 178{ 179 UInt32 index; 180 181 for ( index = 0; index < sizeof(reserved) * 8; index++, reserved >>= 1 ) 182 { 183 if ( (reserved & 1) ) 184 { 185 if ( data[index] ) return true; 186 } 187 } 188 189 return false; 190} 191 192static IOMemoryDescriptor * DKIOC_PREPARE_BUFFER( user_addr_t address, 193 UInt32 length, 194 IODirection direction, 195 proc_t proc ) 196{ 197 IOMemoryDescriptor * buffer = 0; 198 199 if ( address && length ) 200 { 201 buffer = IOMemoryDescriptor::withAddressRange( // (create the buffer) 202 /* address */ address, 203 /* length */ length, 204 /* options */ direction, 205 /* task */ (proc == kernproc) ? kernel_task : current_task() ); 206 } 207 208 if ( buffer ) 209 { 210 if ( buffer->prepare() != kIOReturnSuccess ) // (prepare the buffer) 211 { 212 buffer->release(); 213 buffer = 0; 214 } 215 } 216 217 return buffer; 218} 219 220static void DKIOC_COMPLETE_BUFFER(IOMemoryDescriptor * buffer) 221{ 222 if ( buffer ) 223 { 224 buffer->complete(); // (complete the buffer) 225 buffer->release(); // (release the buffer) 226 } 227} 228 229IODVDMedia * IODVDMediaBSDClient::getProvider() const 230{ 231 // 232 // Obtain this object's provider. We override the superclass's method 233 // to return a more specific subclass of IOService -- IODVDMedia. This 234 // method serves simply as a convenience to subclass developers. 235 // 236 237 return (IODVDMedia *) IOService::getProvider(); 238} 239 240int IODVDMediaBSDClient::ioctl( dev_t dev, 241 u_long cmd, 242 caddr_t data, 243 int flags, 244 proc_t proc ) 245{ 246 // 247 // Process a DVD-specific ioctl. 248 // 249 250 IOMemoryDescriptor * buffer = 0; 251 int error = 0; 252 IOReturn status = kIOReturnSuccess; 253 254 switch ( cmd ) 255 { 256 case DKIOCDVDREADSTRUCTURE32: // (dk_dvd_read_structure_32_t *) 257 { 258 dk_dvd_read_structure_32_t * request; 259 260 request = (dk_dvd_read_structure_32_t *) data; 261 262 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 263 264 if ( DKIOC_IS_RESERVED(data, 0xE) ) { error = EINVAL; break; } 265 266 buffer = DKIOC_PREPARE_BUFFER( 267 /* address */ request->buffer, 268 /* length */ request->bufferLength, 269 /* direction */ kIODirectionIn, 270 /* proc */ proc ); 271 272 status = getProvider()->readStructure( 273 /* buffer */ buffer, 274 /* format */ (DVDStructureFormat) request->format, 275 /* address */ request->address, 276 /* layer */ request->layer, 277 /* grantID */ request->grantID ); 278 279 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 280 281 DKIOC_COMPLETE_BUFFER(buffer); 282 283 } break; 284 285 case DKIOCDVDREADSTRUCTURE64: // (dk_dvd_read_structure_64_t *) 286 { 287 dk_dvd_read_structure_64_t * request; 288 289 request = (dk_dvd_read_structure_64_t *) data; 290 291 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 292 293 if ( DKIOC_IS_RESERVED(data, 0x3C0E) ) { error = EINVAL; break; } 294 295 buffer = DKIOC_PREPARE_BUFFER( 296 /* address */ request->buffer, 297 /* length */ request->bufferLength, 298 /* direction */ kIODirectionIn, 299 /* proc */ proc ); 300 301 status = getProvider()->readStructure( 302 /* buffer */ buffer, 303 /* format */ (DVDStructureFormat) request->format, 304 /* address */ request->address, 305 /* layer */ request->layer, 306 /* grantID */ request->grantID ); 307 308 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 309 310 DKIOC_COMPLETE_BUFFER(buffer); 311 312 } break; 313 314 case DKIOCDVDREPORTKEY32: // (dk_dvd_report_key_32_t *) 315 { 316 dk_dvd_report_key_32_t * request = (dk_dvd_report_key_32_t *) data; 317 318 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 319 320 if ( DKIOC_IS_RESERVED(data, 0x20C) ) { error = EINVAL; break; } 321 322 buffer = DKIOC_PREPARE_BUFFER( 323 /* address */ request->buffer, 324 /* length */ request->bufferLength, 325 /* direction */ kIODirectionIn, 326 /* proc */ proc ); 327 328 status = getProvider()->reportKey( 329 /* buffer */ buffer, 330 /* keyClass */ (DVDKeyClass) request->keyClass, 331 /* address */ request->address, 332 /* grantID */ request->grantID, 333 /* format */ (DVDKeyFormat) request->format ); 334 335 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 336 337 DKIOC_COMPLETE_BUFFER(buffer); 338 339 } break; 340 341 case DKIOCDVDREPORTKEY64: // (dk_dvd_report_key_64_t *) 342 { 343 dk_dvd_report_key_64_t * request = (dk_dvd_report_key_64_t *) data; 344 345 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 346 347 if ( DKIOC_IS_RESERVED(data, 0x3E0C) ) { error = EINVAL; break; } 348 349 buffer = DKIOC_PREPARE_BUFFER( 350 /* address */ request->buffer, 351 /* length */ request->bufferLength, 352 /* direction */ kIODirectionIn, 353 /* proc */ proc ); 354 355 status = getProvider()->reportKey( 356 /* buffer */ buffer, 357 /* keyClass */ (DVDKeyClass) request->keyClass, 358 /* address */ request->address, 359 /* grantID */ request->grantID, 360 /* format */ (DVDKeyFormat) request->format ); 361 362 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 363 364 DKIOC_COMPLETE_BUFFER(buffer); 365 366 } break; 367 368 case DKIOCDVDSENDKEY32: // (dk_dvd_send_key_32_t *) 369 { 370 dk_dvd_send_key_32_t * request = (dk_dvd_send_key_32_t *) data; 371 372 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 373 374 if ( DKIOC_IS_RESERVED(data, 0x2FC) ) { error = EINVAL; break; } 375 376 buffer = DKIOC_PREPARE_BUFFER( 377 /* address */ request->buffer, 378 /* length */ request->bufferLength, 379 /* direction */ kIODirectionOut, 380 /* proc */ proc ); 381 382 status = getProvider()->sendKey( 383 /* buffer */ buffer, 384 /* keyClass */ (DVDKeyClass) request->keyClass, 385 /* grantID */ request->grantID, 386 /* format */ (DVDKeyFormat) request->format ); 387 388 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 389 390 DKIOC_COMPLETE_BUFFER(buffer); 391 392 } break; 393 394 case DKIOCDVDSENDKEY64: // (dk_dvd_send_key_64_t *) 395 { 396 dk_dvd_send_key_64_t * request = (dk_dvd_send_key_64_t *) data; 397 398 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 399 400 if ( DKIOC_IS_RESERVED(data, 0x3EFC) ) { error = EINVAL; break; } 401 402 buffer = DKIOC_PREPARE_BUFFER( 403 /* address */ request->buffer, 404 /* length */ request->bufferLength, 405 /* direction */ kIODirectionOut, 406 /* proc */ proc ); 407 408 status = getProvider()->sendKey( 409 /* buffer */ buffer, 410 /* keyClass */ (DVDKeyClass) request->keyClass, 411 /* grantID */ request->grantID, 412 /* format */ (DVDKeyFormat) request->format ); 413 414 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 415 416 DKIOC_COMPLETE_BUFFER(buffer); 417 418 } break; 419 420 case DKIOCDVDGETSPEED: // (uint16_t *) 421 { 422 status = getProvider()->getSpeed((uint16_t *)data); 423 424 } break; 425 426 case DKIOCDVDSETSPEED: // (uint16_t *) 427 { 428 status = getProvider()->setSpeed(*(uint16_t *)data); 429 430 } break; 431 432 case DKIOCDVDREADDISCINFO32: // (dk_dvd_read_disc_info_32_t *) 433 { 434 dk_dvd_read_disc_info_32_t * request; 435 436 request = (dk_dvd_read_disc_info_32_t *) data; 437 438 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 439 440 if ( DKIOC_IS_RESERVED(data, 0x3FF) ) { error = EINVAL; break; } 441 442 buffer = DKIOC_PREPARE_BUFFER( 443 /* address */ request->buffer, 444 /* length */ request->bufferLength, 445 /* direction */ kIODirectionIn, 446 /* proc */ proc ); 447 448 status = getProvider()->readDiscInfo( 449 /* buffer */ buffer, 450 /* actualByteCount */ &request->bufferLength ); 451 452 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 453 454 DKIOC_COMPLETE_BUFFER(buffer); 455 456 } break; 457 458 case DKIOCDVDREADDISCINFO64: // (dk_dvd_read_disc_info_64_t *) 459 { 460 dk_dvd_read_disc_info_64_t * request; 461 462 request = (dk_dvd_read_disc_info_64_t *) data; 463 464 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 465 466 if ( DKIOC_IS_RESERVED(data, 0x3FFF) ) { error = EINVAL; break; } 467 468 buffer = DKIOC_PREPARE_BUFFER( 469 /* address */ request->buffer, 470 /* length */ request->bufferLength, 471 /* direction */ kIODirectionIn, 472 /* proc */ proc ); 473 474 status = getProvider()->readDiscInfo( 475 /* buffer */ buffer, 476 /* actualByteCount */ &request->bufferLength ); 477 478 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 479 480 DKIOC_COMPLETE_BUFFER(buffer); 481 482 } break; 483 484 case DKIOCDVDREADRZONEINFO32: // (dk_dvd_read_rzone_info_32_t *) 485 { 486 dk_dvd_read_rzone_info_32_t * request; 487 488 request = (dk_dvd_read_rzone_info_32_t *) data; 489 490 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 491 492 if ( DKIOC_IS_RESERVED(data, 0x20F) ) { error = EINVAL; break; } 493 494 buffer = DKIOC_PREPARE_BUFFER( 495 /* address */ request->buffer, 496 /* length */ request->bufferLength, 497 /* direction */ kIODirectionIn, 498 /* proc */ proc ); 499 500 status = getProvider()->readRZoneInfo( 501 /* buffer */ buffer, 502 /* address */ request->address, 503 /* addressType */ request->addressType, 504 /* actualByteCount */ &request->bufferLength ); 505 506 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 507 508 DKIOC_COMPLETE_BUFFER(buffer); 509 510 } break; 511 512 case DKIOCDVDREADRZONEINFO64: // (dk_dvd_read_rzone_info_64_t *) 513 { 514 dk_dvd_read_rzone_info_64_t * request; 515 516 request = (dk_dvd_read_rzone_info_64_t *) data; 517 518 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 519 520 if ( DKIOC_IS_RESERVED(data, 0x3E0F) ) { error = EINVAL; break; } 521 522 buffer = DKIOC_PREPARE_BUFFER( 523 /* address */ request->buffer, 524 /* length */ request->bufferLength, 525 /* direction */ kIODirectionIn, 526 /* proc */ proc ); 527 528 status = getProvider()->readRZoneInfo( 529 /* buffer */ buffer, 530 /* address */ request->address, 531 /* addressType */ request->addressType, 532 /* actualByteCount */ &request->bufferLength ); 533 534 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 535 536 DKIOC_COMPLETE_BUFFER(buffer); 537 538 } break; 539 540 default: 541 { 542 // 543 // A foreign ioctl was received. Ask our superclass' opinion. 544 // 545 546 error = super::ioctl(dev, cmd, data, flags, proc); 547 548 } break; 549 } 550 551 return error ? error : getProvider()->errnoFromReturn(status); 552} 553 554OSMetaClassDefineReservedUnused(IODVDMediaBSDClient, 0); 555OSMetaClassDefineReservedUnused(IODVDMediaBSDClient, 1); 556OSMetaClassDefineReservedUnused(IODVDMediaBSDClient, 2); 557OSMetaClassDefineReservedUnused(IODVDMediaBSDClient, 3); 558OSMetaClassDefineReservedUnused(IODVDMediaBSDClient, 4); 559OSMetaClassDefineReservedUnused(IODVDMediaBSDClient, 5); 560OSMetaClassDefineReservedUnused(IODVDMediaBSDClient, 6); 561OSMetaClassDefineReservedUnused(IODVDMediaBSDClient, 7); 562