How can I detect if CDRom is a DVD on Linux - c++

I'm looking to create a function in C++ running on Linux that returns true if the CDRom media is a DVD and false if its anything else (e.g. Audio CD).
I have been using ioctl with linux/cdrom.h.
I tried using the DVD_READ_STRUCT but it always returns true. Maybe I'm using it incorrectly.
dvd_struct s
if (ioctl(hDEV, DVD_READ_STRUCT, &s)) {
return true;
}

Look at /proc/sys/dev/cdrom/info, it contains something like this:
CD-ROM information, Id: cdrom.c 3.20 2003/12/17
drive name: sr0
drive speed: 125
drive # of slots: 1
Can close tray: 1
Can open tray: 1
Can lock tray: 1
Can change speed: 1
Can select disk: 0
Can read multisession: 1
Can read MCN: 1
Reports media changed: 1
Can play audio: 1
Can write CD-R: 1
Can write CD-RW: 1
Can read DVD: 1
Can write DVD-R: 1
Can write DVD-RAM: 1
Can read MRW: 0
Can write MRW: 0
Can write RAM: 1
(it is updated by the kernel and available in all distros)
You can use this information in addition to the ioctl's from cdrom.h. Also keep in mind that cdrom.h is an attempt to create a standard interface, it does not yet cater for all manufacturers, some still using SCSI-codes or some other proprietary schemes. So to be safe you should also check at least using the SCSI ioctl codes - do #include <scsi/... to have them available.

The official documentation is a bit more helpful. You have to specify the request type and any required inputs before calling ioctl.
// Is it a DVD?
dvd_struct ds;
ds.type = DVD_STRUCT_PHYSICAL;
ds.physical.layer_num=0;
result = ioctl(drive, DVD_READ_STRUCT, &ds);
if (result == -1) {
perror("Probably not a DVD: ");
} else {
printf("Layer 0: %i to %i.\n", ds.physical.layer[0].start_sector, ds.physical.layer[0].end_sector);
}
The really interesting stuff requires issuing SCSI commands like dvd+rw-tools, cdrkit, and cdrdao. Doing this is a bit painful, though, and it's not necessary if you don't need to know if the disc is recordable, rewritable, or pressed.

Related

FFmpeg - RTCP BYE packets

I’m working on some C++ project which depends on Wi-Fi RAK5206 electronic board. I’m using ffmpeg library to obtain video and audio stream and I have issue where I can start and stop stream for four times, but when I want to start for the fifth time I get error. Error description is Invalid data found when processing input and it happens when I call avformat_open_input function and I need to restart the electronic board, reconnect to Wi-Fi etc.
I figured out with Wireshark application that VLC is working and it is sending some BYE packets when TEARDOWN is called. I wonder if error depends to them, because from my application I’m not sending. How I can make setup to force ffmpeg to send BYE packets?
I found some declarations in rtpenc.h file which options to set and tried when I want to connect, but obviously without success.
The code that I used for setting options and opening input:
AVDictionary* stream_opts = 0;
av_dict_set(&stream_opts, "rtpflags", "send_bye", 0);
avformat_open_input(&format_ctx, url.c_str(), NULL, &stream_opts);
Make sure you are calling this av_write_trailer function, from your application.
if not please debug and check it.
/* Write the trailer, if any. The trailer must be written before you
* close the CodecContexts open when you wrote the header; otherwise
* av_write_trailer() may try to use memory that was freed on
* av_codec_close(). */
av_write_trailer(oc);
function Call flow code snippet from ffmpeg source:
av_write_trailer ->
....
ret = s->oformat->write_trailer(s);
} else {
s->oformat->write_trailer(s);
}
...
.write_trailer = rtp_write_trailer ->
...
if (s1->pb && (s->flags & FF_RTP_FLAG_SEND_BYE))
rtcp_send_sr(s1, ff_ntp_time(), 1)
Resolved issue with adding flag 16 (binary: 10000) to AVFormatContext object's flag.
formatCtx->flags = formatCtx->flags | 16;
According to rtpenc.h:
#define FF_RTP_FLAG_SEND_BYE 16

get devices list with c++

I'm on FreeBSD11. I want to get all devices that connect to my system and save their information with c++. for this reason I run camcontrol devlist command. The output is:
<OCZ-VERTEX4 1.4.1.3> at scbus0 target 0 lun 0 (pass0,ada0)
<OCZ-AGILITY3 2.15> at scbus0 target 1 lun 0 (pass1,ada1)
<OCZ-AGILITY3 2.15> at scbus1 target 0 lun 0 (pass2,ada2)
<OCZ-AGILITY3 2.15> at scbus1 target 1 lun 0 (pass3,ada3)
<OCZ-AGILITY3 2.15> at scbus3 target 0 lun 0 (pass4,ada4)
< USB FLASH DRIVE PMAP> at scbus4 target 0 lun 0 (da0,pass5)
I put this output in a file, with getline in c++, only get the line from at scbus0 target 0 lun 0 (pass0,ada0) and ignore first part.
I want to get ada0,ada1,ada2,ada3,ada4,da0 then with /usr/local/sbin/smartctl -i /dev/<device> get it's information and for other like da0,cd0,... that won't have output in this command save their name.
I'm not sure if this is a good way or not. Please give me a better solution if exist, or help me to solve my problem.
If you're only interested in disks, you might consider trying to use libgeom(3) instead. It offers functions to get providers.
Another approach might be to use libcam to pull the device list as camcontrol does and then you can handle formatting as needed. You can look at how the camcontrol program does this in camcontrol.c 's getdevlist function.

New to linux: C++ opening and closing usb port issues

New developer, Linux, C++, USB - Serial Adapter.
I've completed a program where I am able to write to the USB port. However, if I change my code, make, log back in as root, and try to write to the port again, it doesn't go through. It'll only work if I remove the USB cable from the computer and reseat it before attempting sending data again. If you need more info let me know.
I'm on two different computers and have no way of copying and pasting but here is the gist of what I'm doing.
int fd = 0;
int iOut = 0;
char *ComPort = "/dev/ttyUSB0";
fd=open(ComPort, O_CREAT | O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1)
cout << "unable to open" << endl;
// blah blah getting data ready to be sent
// create a block of 50 hex characters to be sent : DB
iOut = write(fd, $DB, sizeof(DB));
// blah blah error checking
close(fd);
return(0);
#Surt #alexfarber I had a talk with a coworker on this and we concluded that this is most likely a hardware issue with my display or usb to serial adapter. I believe the only way this can work with this particular adapter is by turning off the power to it and turning it back on in order to reflect what it would see when being removed and reseated manually. I dont believe this is possible but I'll start another thread with anything I may run into. I appreciate you all taking the time to help with this, I did learn a number of other things I didn't know before hand so this was still very helpful. Thank you once again.
Take at look at chapter 3.2 here http://www.tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html
add some of the error checking first so you can see where if fails. The perror line will help there.
if (fd <0) {perror(ComPort ); exit(-1); } // note the exit which your code doesn't have.
This should now tell you some more info and add
if (errno) {perror(ComPort ); exit(-1); }
after all operations, read, write and set things on the fd.
now add the newtio part of 3.2 to your program in case some handshake failed. You must change it so it conforms with the display.
The final version of your program might be more like 3.3.

V4L2: Get device/input status

Maybe anybody will know the answer to the next question...
I have plugged in usb digital camera (it has one input pin - 0).
I check input status every 5 seconds via structure: v4l2_input (here is the example: http://pastebin.com/FFvNAkQ3), to process situation if one of the flags is set (V4L2_IN_ST_NO_POWER or V4L2_IN_ST_NO_SIGNAL or V4L2_IN_ST_NO_H_LOCK).
The problem is that even i unplug my usb digital camera, the input status is always 0 (0x00). Why the driver does not change input status flag when the device is unplugged?
Maybe it is possible to check device status not only input pin? If yes, then which ioctl request should be set...?

How to read a multi-session DVD disk size in Windows?

Trying to read the sizes of disks that were created in multiple sessions using GetDiskFreeSpaceEx() gives the size of the last session only. How do I read correctly the number and sizes of all sessions in C/C++?
Thanks.
You might want to look at the DeviceIoControl API function. See here for control codes. Here is a code example that retrieves the size of a CD disk. Substitute
CreateFile(TEXT("\\\\.\\PhysicalDrive0")
for e.g.
CreateFile(TEXT("\\\\.\\F:") /* Drive is F: */
if you wish.
Note: The page says that DeviceIoControl can be used to "retrieve information about a floppy disk drive, hard disk drive, tape drive, or CD-ROM drive", but I have also tested it on a DVD, and it seemed to work perfectly. I did not have access to any multisession DVDs to test, so you'll have to test if that works yourself. If it doesn't work, I'd try some of the other control codes, at least IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, IOCTL_DISK_GET_LENGTH_INFO and IOCTL_DISK_GET_PARTITION_INFO_EX.
If all fails with DeviceIoControl, you could possibly make use of the Windows Image Mastering API (IMAPI). You'll need v2 of the API (included with Vista & later, can be added to XP & 2003 too, see here: What's new in IMAPIv2) for DVD support. This API is primarily for CD burning, but does perhaps contain some functionality for retrieving disk size, I'd find it weird if it didn't. Particularly, this example seems to be interesting. I do not know if this one works for multisession disks either, but since it can create them, I guess it's likely.
Here are some resources for IMAPI:
MSDN - IMAPI
MSDN - IMAPI interfaces
MSDN - Creating multisession disks with IMAPI (note: example with VB, not C or C++)
Hey I got at least 2 solutions for you:
1) Download dvd+rw-mediainfo.exe from http://fy.chalmers.se/~appro/linux/DVD+RW/tools/win32/, it's a tool that reads info about your disc. Then just make a system call from your app and parse the results. Here's example output:
D:\Downloads>"dvd+rw-mediainfo.exe" f:
INQUIRY: [HL-DT-ST][DVDRAM GT30N ][1.01]
GET [CURRENT] CONFIGURATION:
Mounted Media: 10h, DVD-ROM
Current Write Speed: 1.0x1385=1385KB/s
Write Speed #0: 8.0x1385=11080KB/s
Write Speed #1: 4.0x1385=5540KB/s
Write Speed #2: 2.0x1385=2770KB/s
Write Speed #3: 1.0x1385=1385KB/s
Speed Descriptor#0: 00/2292991 R#8.0x1385=11080KB/s W#8.0x1385=11080KB/s
READ DVD STRUCTURE[#0h]:
Media Book Type: 01h, DVD-ROM book [revision 1]
Legacy lead-out at: 2292992*2KB=4696047616
READ DISC INFORMATION:
Disc status: complete
Number of Sessions: 1
State of Last Session: complete
Number of Tracks: 1
READ TRACK INFORMATION[#1]:
Track State: complete
Track Start Address: 0*2KB
Free Blocks: 0*2KB
Track Size: 2292992*2KB
Last Recorded Address: 2292991*2KB
FABRICATED TOC:
Track#1 : 17#0
Track#AA : 17#2292992
Multi-session Info: #1#0
READ CAPACITY: 2292992*2048=4696047616
2) Investigate mciSendString from [DllImport("winmm.dll", EntryPoint = "mciSendStringA", CharSet = CharSet.Ansi)], I suspect you can send some command and get the desired results.
PS: of course you may download dvd+rw-mediainfo.exe sources from here and investigate further, I am just giving you ideas to think of.
UPDATE
Link to source code updated, thanks #oystein
There are many way to do this since the DVD drives have several interfaces for this due to legacy and backward-compatibility issues.
You could send an IOCTL_SCSI_PASSTHROUGH_DIRECT command to the DVD-drive ( the physicaldevice handle for it). With it you issue a SCSI commands that will be answered by the drive. You can read session information, disk information disk capcity and more.
I believe that dvd+rw-mediainfo.exe issues these.
Unfortunatly, the interface is a bit tricky and obscure, since it is a command within a command. Th passthrough has a byte buffer you will have to fill in yourself with the command structure.
Or you can call IOCTL_CDROM_READ_TOC_EX:
http://www.osronline.com/ddkx/storage/k306_2cs2.htm
I also believe that the exact set of the IOCTL / commands that will work depends on on the drive and its firmaware.
Older drives will not support the newr interfaces and some of the newer drives will not support legacy interfaces.
Thus, some of the libraries & tools might use one or more of these interfaces.
Accseeing the older sessons is all quite messy, really, since most OS will not care about them, only the most recent ones.