#import "JOYSubElement.h" @interface JOYElement () { @public uint16_t _usage; @public uint16_t _usagePage; @public uint32_t _uniqueID; @public int32_t _min; @public int32_t _max; @public int32_t _reportID; @public int32_t _parentID; } @end @implementation JOYSubElement { JOYElement *_parent; size_t _size; // in bits size_t _offset; // in bits } - (instancetype)initWithRealElement:(JOYElement *)element size:(size_t) size // in bits offset:(size_t) offset // in bits usagePage:(uint16_t)usagePage usage:(uint16_t)usage min:(int32_t)min max:(int32_t)max { if ((self = [super init])) { _parent = element; _size = size; _offset = offset; _usage = usage; _usagePage = usagePage; _uniqueID = (uint32_t)((_parent.uniqueID << 16) | offset); _min = min; _max = max; _reportID = _parent.reportID; _parentID = _parent.parentID; } return self; } - (int32_t)value { NSData *parentValue = [_parent dataValue]; if (!parentValue) return 0; if (_size > 32) return 0; if (_size + (_offset % 8) > 32) return 0; size_t parentLength = parentValue.length; if (_size > parentLength * 8) return 0; if (_size + _offset >= parentLength * 8) return 0; const uint8_t *bytes = parentValue.bytes; uint8_t temp[4] = {0,}; memcpy(temp, bytes + _offset / 8, (_offset + _size - 1) / 8 - _offset / 8 + 1); uint32_t ret = (*(uint32_t *)temp) >> (_offset % 8); ret &= (1 << _size) - 1; // if (_min < 0 || _max < 0) { // Uses unsigned values if (ret & (1 << (_size - 1)) ) { // Is negative ret |= ~((1 << _size) - 1); // Fill with 1s } } if (_max < _min) { return _max + _min - ret; } return ret; } - (IOReturn)setValue: (uint32_t) value { NSMutableData *dataValue = [[_parent dataValue] mutableCopy]; if (!dataValue) return -1; if (_size > 32) return -1; if (_size + (_offset % 8) > 32) return -1; size_t parentLength = dataValue.length; if (_size > parentLength * 8) return -1; if (_size + _offset >= parentLength * 8) return -1; uint8_t *bytes = dataValue.mutableBytes; uint8_t temp[4] = {0,}; memcpy(temp, bytes + _offset / 8, (_offset + _size - 1) / 8 - _offset / 8 + 1); (*(uint32_t *)temp) &= ~((1 << (_size - 1)) << (_offset % 8)); (*(uint32_t *)temp) |= (value) << (_offset % 8); memcpy(bytes + _offset / 8, temp, (_offset + _size - 1) / 8 - _offset / 8 + 1); return [_parent setDataValue:dataValue]; } - (NSData *)dataValue { [self doesNotRecognizeSelector:_cmd]; return nil; } - (IOReturn)setDataValue:(NSData *)data { [self doesNotRecognizeSelector:_cmd]; return -1; } @end