def GenerateHidReport(report_str, name=None): ''' Generate an HID report Container from a HID report string :param report_str: HID report string :param name: name of generated Container (default: None) :raises: KittyException if not enough bytes are left for command :examples: :: Template( name='MyHidReport', fields=GenerateHidReport( '05010906A101050719E029E7150025017501950881029501750881011900296515002565750895018100C0', ) ) ''' fields = [] index = 0 namer = NameGen() while index < len(report_str): opcode = report_str[index] num_args = opcode & 3 if index + num_args >= len(report_str): raise KittyException('Not enough bytes in hid report for last opcode') index += 1 cur_name = namer.gen(opcode) if num_args == 0: fields.append(UInt8(opcode, name=cur_name)) else: args = report_str[index:index + num_args] value = sum(args[i] << (i * 8) for i in range(len(args))) # little endian... fields.append(Container( name=cur_name, fields=[ UInt8(opcode, name='opcode'), BitField(value, 8 * len(args), encoder=ENC_INT_LE, name='value') ] )) index += num_args return OneOf( name=name, fields=[ Container( name='generation', fields=fields ), MutableField( name='mutation', value=report_str ), RandomHidReport( name='random_sequences' ), ])
max_length=250), ]) ]), ]) ]), Container(name='endpoints', fields=[ SubDescriptor(name='endpoint_descriptor', descriptor_type=DescriptorType.endpoint, fields=[ UInt8(name='bEndpointAddress', value=0x83), BitField(name='bmAttributes', value=3, length=8), LE16(name='wMaxPacketSize', value=0x40), UInt8(name='bInterval', value=0x20) ]) ]) ]) cdc_notification = Template( name='cdc_notification', fields=[ OneOf(fields=[ MutableField(name='mutable notification', value=b'\xa1\x00\x01\x00\x01\x00\x01\x00\x00'), ]), ])