http://qs321.pair.com?node_id=141059


in reply to ioctl into or from perl structs

First, you seem to not understand how to handle these lines:

__u8 cdte_adr :4; __u8 cdte_ctrl :4;

You are trying to unpack this with C4 which represents 4 one-byte values. The C code says that each of those represents one 4-bit value, thus both those values are probably packed with one-byte. (You'll need to seperate them later, with the various bitshifting operators, therefore. You can probably explore and see what part of the byte each value is stored in.). As for the integer that comes later, you'll probably need to add some bytes of padding (x in the format for unpack) so that it will be aligned propperly. On a 32-bit machine this would probably imply one byte of padding to align on a 32-bit boundry.

I would strongly advise that you avoid trying to unpack structures yourself. How they are packed is not always easy to fiquire out and is often dependent on the architecture being used. In some cases, it may even vary from compiler to compiler on that architecture. Writing a little bit of C to do it is likely to be more portable most of the time.

update: Oops. Forgot to talk about that union. The union can hold either the structure cdrom_addr or an int. Usually this means that it's packed such that storage is only allocated for one. This means you'll probably need to have to two formats one which does CCCx (for the struct, padding to match the size of the integer. You'll need more if your platform has ints larger then 32 bits.) and one with does i (for the integer) depending on which is there. This doesn't really seem ideal, however, given you have to look at the info in the struct to see which to use. One solution would be to have a format where you first unpack that field with the format a4 (update: where 4 may be another number if ints are larger then 32 bits), and then further unpack the results with the aforementioned formats. Or you could unpack it as an integer and use bit operations to extract the __u8 values, too.