If you are like me, when you get your new hardware you don't even bother to boot it into Windows before you go ahead and install your favorite free OS onto it. Actually, if you're really like me, you bought your system from a vendor that doesn't force you to absorb the Microsoft Tax in your purchase. Either way, chances are that you'll try using the nifty DVD drive in it for playing movies at some point and get aggravated because the drive seems to refuse all attempts at interfacing a video dvd.
This is thanks to the movie industry's clever “copy protection” system. The system is so well engineered that it doesn't even really prevent copying of DVDs! It is really a “playback protection” mechanism, meaning that the manufacturer of your DVD drive had to pay them to play their DVDs. Sound fair? That's what I thought. Basically, most DVDs are encrypted with an algorithm called CSS, and your drive manufacturer paid for a key to de-scramble the encrypted content. There is really nothing preventing you from duplicating an encrypted volume by copying it sector-for-encrypted-sector to another disk (except that your drive most likely will prevent you from doing that). However, it's a rather trivial matter for an organization large enough to engineer DVD copying hardware that doesn't prevent them from copying.
Another mechanism that they put into the system is to tie your DVD drive to a specific region. This was an agreement where hardware manufacturers and the movie industry divided up the globe into a number of regions, and agreed that they would only sell their wares to certain regions that the wares are specially marked for. Since this system turned out to become a big headache for the likes of the hardware industry that might sell stock to three regions from a single factory, a compromise was made where your drive typically arrives ”regionless” and you get the convenience of setting the region yourself, manually. In Windows, the Windows Media Player, or your drive's specialized DVD playback software will do this work for you.
So, if you happened to bypass the Windows installation on your system, chances are that your DVD drive is still “regionless”. This results in the drive simply refusing to read any and all region-encoded DVDs.
The following table lists the regions:
| region code | region coverage |
|---|---|
| 1 | Bermuda, Canada, United States, US Territories |
| 2 | European Union, Albania, Andorra, Bahrain, Belarus, Bosnia and Herzegovina, Croatia, Egypt, Faroe Islands, French Guiana, Georgia, Greenland, Guernsey, Iceland, Iran, Iraq, Isle of Man, Israel, Japan, Jersey, Jordan, Kosovo, Kuwait, Lebanon, Lesotho, Liechtenstein, Macedonia, Moldova, Monaco, Montenegro, Norway, Oman, Qatar, San Marino, Saudi Arabia, Serbia, South Africa, Swaziland, Switzerland, Syria, Turkey, United Arab Emirates, Vatican City State, Yemen |
| 3 | Southeast Asia, Hong Kong, Macau, South Korea, Taiwan |
| 4 | Caribbean, Central America, Oceania, South America (except French Guiana), Mexico |
| 5 | African countries not explicitly included in other regions, Indian subcontinent, countries included in the former Soviet Union, Mongolia, North Korea |
| 6 | People's Republic of China (except Macau and Hong Kong) |
| 7 | Reserved for future use (found in use on protected screener copies of MPAA-related DVDs and “media copies” of pre-releases in Asia) |
| 8 | International venues such as aircraft, cruise ships, etc. |
This table was shamelessly pulled from DVD_region_codeon Wikipedia.
Luckily, for FreeBSD, I came across the following two small programs which can be used to interface this logic and provide region-setting and region-getting support from the FreeBSD command-line.
Here is regionget.c:
#include <fcntl.h> #include <stdio.h> #include <string.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/dvdio.h> #include <unistd.h> int main( int argc, char const *argv[] ) { int ret; int region; int fd; struct dvd_authinfo dvd; if( argc < 2 ) { fprintf( stderr, "Usage: %s <dvd device>\n", argv[ 0 ]); return -1; } fd = open( argv[ 1 ], O_RDONLY ); if( fd < 0 ) { fprintf( stderr, "Failed to open %s\n", argv[ 1 ]); return -1; } memset( &dvd, 0, sizeof( struct dvd_authinfo )); dvd.format = DVD_REPORT_RPC; ret = ioctl( fd, DVDIOCREPORTKEY, &dvd ); close( fd ); if( ret < 0 ) { fprintf( stderr, "Failed to retrieve region info. Try with a disc in the drive.\n" ); return -1; } dvd.region ^= 0xff; for( region = 0; dvd.region; dvd.region >>= 1 ) { region++; if( dvd.region == 1 ) break; } printf( "vendor resets left: %u\n", dvd.vend_rsts ); printf( "user changes left: %u\n", dvd.user_rsts ); printf( "drive region: %u\n", region ); printf( "rpc type: %u\n", dvd.rpc_scheme + 1 ); return 0; }
Save the file, cd to its directory and then run make regionget and FreeBSD make will automatically build it for you.
Likewise, here is regionset.c:
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/dvdio.h> #include <unistd.h> int main( int argc, char const *argv[] ) { int ret, fd; uint8_t region; struct dvd_authinfo dvd; if( argc < 3 ) { fprintf( stderr, "Usage: %s <dvd device> <region>\n", argv[ 0 ]); return -1; } ret = ( uint8_t ) strtol( argv[ 2 ], NULL, 10 ); if( ret <= 0 || ret > 8 ) { fprintf( stderr, "Invalid region.\n" ); return -1; } for( region = 0x01; ret > 1; ret-- ) { region <<= 1; } region ^= 0xff; fd = open( argv[ 1 ], O_RDONLY ); if( fd < 0 ) { fprintf( stderr, "Failed to open %s\n", argv[ 1 ]); return -1; } memset( &dvd, 0, sizeof( struct dvd_authinfo )); dvd.format = DVD_SEND_RPC; dvd.region = region; ret = ioctl( fd, DVDIOCSENDKEY, &dvd ); close( fd ); if( ret < 0 ) { fprintf( stderr, "Failed to set region. Try with a disc in the drive.\n" ); return -1; } return 0; }
Both programs will provide a usage statement when called without any arguments. They both utilize the same region codes as provided in the table above.
Beware that most drives only support the region codes being set a finite amount of times, so make sure that you double-check everything you are doing before you reset the region encoding.