Re: Packing byte fields and an array object into struct
On Wednesday, November 13, 2013 1:31:49 PM UTC-5, krishna...@gmail.com wrote: Hello, I am trying to build a structure to be passed down to an I2C device driver. The driver expects a struct that has a data array of size 512 bytes among other things. This is my code - rd_wr = 0x0 # Read operation i2c_addr= addr mux = mux_sel multi_len = count cmd = 0x0 i2c_inst_type = CHEL_I2C_AUTO_RD_TYPE_5 flag= CHEL_I2C_AUTO_VALID status = 0x0 data= array.array('B', (0 for x in range(0,512))) os_inst_bytes = (struct.pack('B', rd_wr) + struct.pack('B', i2c_addr) + struct.pack('B', mux)+ struct.pack('B', multi_len) + struct.pack('B', cmd)+ struct.pack('B', i2c_inst_type) + struct.pack('B', flag) + struct.pack('I', status) + struct.pack('512B', data)) #Convert to byte array os_inst = bytearray(os_inst_bytes) ret = fcntl.ioctl(self._dev_fd, self.__IOWR(FXCB_FPGAIO_I2C_AUTO_OS_INST), os_inst, 1) I get an error like this - 591 struct.pack('B', flag) + 592 struct.pack('I', status) + -- 593 struct.pack('512B', data)) error: pack requires exactly 512 arguments In [1]: Even though data is a 512 element array, it is not treat as such in this struct.pack. The data field is used to return data from the driver. I should be able to unpack the struct os_inst and read the data buffer after the IOCTL call. How can I achieve this ? Thanks in advance! To make a 512-byte field in struct, use '512s' with a data value of ''. It will zero-pad the result and give you 512 zero bytes. Also, you can use multiple format specifiers in one struct.pack call: os_inst_bytes = struct.pack('7BI512s', rd_wr, i2c_addr, muc, multi_len, cmd, i2c_inst_type, flag, status, '') Lastly, I suspect the value returned from struct.pack is byte-string enough for the ioctl call, no need to use bytearray. --Ned. -- https://mail.python.org/mailman/listinfo/python-list
Re: Packing byte fields and an array object into struct
Correction in the last input line... In [16]: result = struct.unpack('5p', os_inst[11:16]) --- error Traceback (most recent call last) ipython-input-16-42b59e00d5af in module() 1 result = struct.unpack('5p', os_inst[11:16]) error: unpack requires a bytes object of length 5 In [17]: -- https://mail.python.org/mailman/listinfo/python-list
Re: Packing byte fields and an array object into struct
Thanks for your reply Ned! I tried this your suggestion and this is what it complains... os_inst_bytes = struct.pack('7BI512s', 0, 0x51, 0x10, 5, 0, 0xD, 0x80, 0, '') --- error Traceback (most recent call last) ipython-input-6-d36f45a8d3e6 in module() 1 os_inst_bytes = struct.pack('7BI512s', 0, 0x51, 0x10, 5, 0, 0xD, 0x80, 0, ) error: argument for 's' must be a bytes object In [7]: And about the bytearray() call, I want to pass a mutable object to the IOCTL to be able to get the data back from the driver. Without bytearray(), the ioctl with mutable flag set to 1 would complain. I tried to use the p format specifier with pack after converting the array object to byte stream. Packing seems fine. However, I cant seem to unpack. In [1]: import array In [2]: import struct In [3]: data= array.array('B', (1 for x in range(5))) In [4]: data_bytes = data.tobytes() In [5]: os_inst_bytes = struct.pack('7BIp', 0, 0x51, 0x10, 5, 0, 0xD, 0x80, 0, data_bytes) In [6]: In [6]: os_inst = bytearray(os_inst_bytes) In [7]: result = struct.unpack('7B', os_inst[0:7]) In [8]: print(result) (0, 81, 16, 5, 0, 13, 128) In [9]: result = struct.unpack('I', os_inst[7:11]) In [10]: print(result) (0,) In [11]: result = struct.unpack('5s', os_inst[11:16]) --- error Traceback (most recent call last) ipython-input-11-da14a6693435 in module() 1 result = struct.unpack('5s', os_inst[11:16]) error: unpack requires a bytes object of length 5 In [12]: -- https://mail.python.org/mailman/listinfo/python-list
Re: Packing byte fields and an array object into struct
On Wednesday, November 13, 2013 3:41:03 PM UTC-5, krishna...@gmail.com wrote: Thanks for your reply Ned! I tried this your suggestion and this is what it complains... os_inst_bytes = struct.pack('7BI512s', 0, 0x51, 0x10, 5, 0, 0xD, 0x80, 0, '') --- error Traceback (most recent call last) ipython-input-6-d36f45a8d3e6 in module() 1 os_inst_bytes = struct.pack('7BI512s', 0, 0x51, 0x10, 5, 0, 0xD, 0x80, 0, ) error: argument for 's' must be a bytes object OK, looks like you are using Python 3 (it helps to specify these things up-front). Use b to get an empty byte-string. In [7]: And about the bytearray() call, I want to pass a mutable object to the IOCTL to be able to get the data back from the driver. Without bytearray(), the ioctl with mutable flag set to 1 would complain. OK, keep the bytearray call if it helps. --Ned. -- https://mail.python.org/mailman/listinfo/python-list