Jérôme Vuarand avatar Jérôme Vuarand committed 38d8a62

Removed fill_interrupt and replaced it with setters on the transfer structure (through the addition of a setter system).

Comments (0)

Files changed (5)

 int typeerror(lua_State* L, int narg, const char* tname);
 #define setfuncs luaL_setfuncs
 #define setuservalue lua_setuservalue
+#define getuservalue lua_getuservalue
 
 #elif LUA_VERSION_NUM==501
 
 #define typeerror luaL_typerror
 void setfuncs(lua_State* L, const luaL_Reg* l, int nup);
 #define setuservalue lua_setfenv
+#define getuservalue lua_getfenv
 
 #endif
 
 		{name='bInterval', ctype='uint8_t', luatype='number'},
 		{name='bRefresh', ctype='uint8_t', luatype='number'},
 		{name='bSynchAddress', ctype='uint8_t', luatype='number'},
-		{name='extra', ctype='const unsigned char*', luatype='string', size='extra_length', size_ctype='int'},
+		{name='extra', const=true, ctype='unsigned char*', luatype='string', size='extra_length', size_ctype='int'},
 	},
 })
 
 		{name='bInterfaceSubClass', ctype='uint8_t', luatype='number'},
 		{name='bInterfaceProtocol', ctype='uint8_t', luatype='number'},
 		{name='iInterface', ctype='uint8_t', luatype='number'},
-		{name='endpoint', ctype='struct libusb_endpoint_descriptor*'},
-		{name='extra', ctype='const unsigned char*', luatype='string', size='extra_length', size_ctype='int'},
+		{name='endpoint', ctype='struct libusb_endpoint_descriptor*', setter=false},
+		{name='extra', const=true, ctype='unsigned char*', luatype='string', size='extra_length', size_ctype='int'},
 	},
 })
 
 table.insert(structs, {
 	cname = 'interface',
 	fields = {
-		{name='altsetting', ctype='struct libusb_interface_descriptor*'},
+		{name='altsetting', ctype='struct libusb_interface_descriptor*', setter=false},
 		{name='num_altsetting', ctype='int', luatype='number'},
 	},
 })
 		{name='iConfiguration', ctype='uint8_t', luatype='number'},
 		{name='bmAttributes', ctype='uint8_t', luatype='number'},
 		{name='MaxPower', ctype='uint8_t', luatype='number'},
-		{name='interface', ctype='struct libusb_interface*'},
-		{name='extra', ctype='const unsigned char*', luatype='string', size='extra_length', size_ctype='int'},
+		{name='interface', ctype='struct libusb_interface*', setter=false},
+		{name='extra', const=true, ctype='unsigned char*', luatype='string', size='extra_length', size_ctype='int'},
 	},
 	gc = true,
 })
 table.insert(structs, {
 	cname = 'transfer',
 	gc = true,
+	fields = {
+		{name='dev_handle'},
+		{name='flags', ctype='uint8_t', luatype='number'},
+		{name='endpoint', ctype='unsigned char', luatype='number'},
+		{name='type', ctype='unsigned char', luatype='number'},
+		{name='timeout', ctype='unsigned int', luatype='number'},
+		{name='status', ctype='enum libusb_transfer_status', luatype='number'},
+	--	{name='length'},
+		{name='actual_length', ctype='int', luatype='number'},
+		{name='callback'},
+	--	{name='user_data'},
+		{name='buffer', ctype='unsigned char*', luatype='string', size='length', size_ctype='int', const=false},
+	--	{name='num_iso_packets'},
+--		{name='iso_packet_desc'},
+	},
 })
 
 ------------------------------------------------------------------------------
 	return 1;
 }
 
+static int luausb_generic_newindex(lua_State* L)
+{
+	lua_getmetatable(L, 1);
+	/* get a getter and call it */
+	lua_getfield(L, -1, "setters");
+	lua_pushvalue(L, 2);
+	lua_gettable(L, -2);
+	if (!lua_isnil(L, -1))
+	{
+		lua_pushvalue(L, 1);
+		lua_pushvalue(L, 3);
+		lua_call(L, 2, 1);
+		return 1;
+	}
+	/* throw error */
+	lua_pushliteral(L, "no setter for field ");
+	lua_getglobal(L, "tostring");
+	lua_pushvalue(L, 2);
+	lua_call(L, 1, 1);
+	lua_concat(L, 2);
+	return lua_error(L);
+}
+
 static int luausb_generic_tostring(lua_State* L)
 {
 	lua_getmetatable(L, 1);
 ]])
 	
 	structs_h:write([[
+int luausb_is_]]..cname..[[(lua_State* L, int index);
 struct libusb_]]..cname..[[* luausb_check_]]..cname..[[(lua_State* L, int index);
 ]])
 	structs_c:write([[
+int luausb_is_]]..cname..[[(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_]]..cname..[[");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_]]..cname..[[* luausb_check_]]..cname..[[(lua_State* L, int index)
 {
 	struct libusb_]]..cname..[[* udata;
 	*udata = value;
 	luaL_getmetatable(L, "struct libusb_]]..cname..[[");
 	lua_setmetatable(L, -2);
+]])
+	local refs_needed = false
+	if struct.fields then
+		for _,field in ipairs(struct.fields) do
+			if field.luatype=='string' then
+				refs_needed = true
+				break
+			end
+		end
+	end
+	if refs_needed then
+		structs_c:write([[
+	lua_createtable(L, 1, 0);
+	if (owner != 0)
+	{
+		lua_pushvalue(L, owner);
+		lua_rawseti(L, -2, 1);
+	}
+	setuservalue(L, -2);
+]])
+	else
+		structs_c:write([[
 	if (owner != 0)
 	{
 		lua_createtable(L, 1, 0);
 		lua_rawseti(L, -2, 1);
 		setuservalue(L, -2);
 	}
+]])
+	end
+	structs_c:write([[
 }
 
 ]])
 
-	-- getters
+	-- getters/setters
 	if struct.fields then
 		for _,field in ipairs(struct.fields) do
 			if field.luatype=='number' then
 	return 1;
 }
 
+static int luausb_set_]]..cname..[[_]]..field.name..[[(lua_State* L)
+{
+	struct libusb_]]..cname..[[* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field ]]..field.name..[[ (]]..field.luatype..[[ expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_]]..cname..[[(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->]]..field.name..[[ = (]]..field.ctype..[[)value;
+	return 0;
+}
+
 ]])
 			elseif field.luatype=='string' then
+				local ctype = field.ctype
+				if field.const then
+					ctype = 'const '..ctype
+				end
 				structs_c:write([[
 static int luausb_get_]]..cname..[[_]]..field.name..[[(lua_State* L)
 {
 					structs_c:write([[
 		lua_pushlstring(L, (const char*)udata->]]..field.name..[[, udata->]]..field.size..[[);
 ]])
-				elseif type(field.size)=='number' then
-					structs_c:write([[
-		lua_pushlstring(L, (const char*)udata->]]..field.name..[[, ]]..field.size..[[);
-]])
 				elseif type(field.size)=='nil' then
 					structs_c:write([[
 		lua_pushstring(L, (const char*)udata->]]..field.name..[[);
 }
 
 ]])
+				if field.const and type(field.size)=='string' then
+					structs_c:write([[
+static int luausb_set_]]..cname..[[_]]..field.name..[[(lua_State* L)
+{
+	struct libusb_]]..cname..[[* udata;
+	if (!lua_isstring(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field ]]..field.name..[[ (]]..field.luatype..[[ expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_]]..cname..[[(L, 1);
+	getuservalue(L, 1);
+	lua_pushvalue(L, 2);
+	lua_setfield(L, -2, "]]..field.name..[[");
+	lua_pop(L, 1);
+	{
+		size_t size;
+		udata->]]..field.name..[[ = lua_tolstring(L, 2, &size);
+		udata->]]..field.size..[[ = (]]..field.size_ctype..[[)size;
+	}
+	return 0;
+}
+]])
+				elseif field.const and type(field.size)=='nil' then
+					structs_c:write([[
+static int luausb_set_]]..cname..[[_]]..field.name..[[(lua_State* L)
+{
+	struct libusb_]]..cname..[[* udata;
+	if (!lua_isstring(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field ]]..field.name..[[ (]]..field.luatype..[[ expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_]]..cname..[[(L, 1);
+	getuservalue(L, 1);
+	lua_pushvalue(L, 2);
+	lua_setfield(L, -2, "]]..field.name..[[");
+	lua_pop(L, 1);
+	udata->]]..field.name..[[ = lua_tostring(L, 2);
+	return 0;
+}
+]])
+				elseif not field.const and type(field.size)=='string' then
+					structs_c:write([[
+static int luausb_set_]]..cname..[[_]]..field.name..[[(lua_State* L)
+{
+	struct libusb_]]..cname..[[* udata;
+	udata = luausb_to_]]..cname..[[(L, 1);
+	if (lua_type(L, 2)==LUA_TSTRING)
+	{
+		const char* value;
+		size_t size;
+		char* buffer;
+		value = lua_tolstring(L, 2, &size);
+		getuservalue(L, 1);
+		buffer = lua_newuserdata(L, size);
+		lua_setfield(L, -2, "]]..field.name..[[");
+		lua_pop(L, 1);
+		memcpy(buffer, value, size);
+		udata->]]..field.name..[[ = buffer;
+		udata->]]..field.size..[[ = (]]..field.size_ctype..[[)size;
+	}
+	else if (lua_type(L, 2)==LUA_TNUMBER)
+	{
+		size_t size;
+		char* buffer;
+		size = (size_t)lua_tonumber(L, 2); /* :FIXME: handle overflow */
+		getuservalue(L, 1);
+		buffer = lua_newuserdata(L, size);
+		lua_setfield(L, -2, "]]..field.name..[[");
+		lua_pop(L, 1);
+		memset(buffer, 0, size);
+		udata->]]..field.name..[[ = buffer;
+		udata->]]..field.size..[[ = (]]..field.size_ctype..[[)size;
+	}
+	else
+	{
+		lua_pushliteral(L, "invalid value for field ]]..field.name..[[ (string or number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	return 0;
+}
+]])
+				else
+					error("unsupported field size for "..cname.."."..field.name)
+				end
+				structs_c:write([[
+
+]])
 			else
 				structs_c:write([[
 int luausb_get_]]..cname..[[_]]..field.name..[[(lua_State* L);
+]])
+				if field.setter ~= false then
+					structs_c:write([[
+int luausb_set_]]..cname..[[_]]..field.name..[[(lua_State* L);
+]])
+				end
+				structs_c:write([[
 
 ]])
 			end
 	structs_c:write([[
 	{0, 0},
 };
+
+static struct luaL_Reg libusb_]]..cname..[[__setters[] = {
+]])
+	if struct.fields then
+		for _,field in ipairs(struct.fields) do
+			if field.setter ~= false then
+				structs_c:write([[
+	{"]]..field.name..[[", luausb_set_]]..cname..[[_]]..field.name..[[},
+]])
+			end
+		end
+	end
+	structs_c:write([[
+	{0, 0},
+};
 ]])
 	
 	-- metamethods
 	structs_c:write([[
 static struct luaL_Reg libusb_]]..cname..[[__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 ]])
 	if struct.tostring then
 		structs_c:write([[
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_]]..cname..[[__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_]]..cname..[[__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "]]..cname..[[");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 	return 1;
 }
 
+static int luausb_generic_newindex(lua_State* L)
+{
+	lua_getmetatable(L, 1);
+	/* get a getter and call it */
+	lua_getfield(L, -1, "setters");
+	lua_pushvalue(L, 2);
+	lua_gettable(L, -2);
+	if (!lua_isnil(L, -1))
+	{
+		lua_pushvalue(L, 1);
+		lua_pushvalue(L, 3);
+		lua_call(L, 2, 1);
+		return 1;
+	}
+	/* throw error */
+	lua_pushliteral(L, "no setter for field ");
+	lua_getglobal(L, "tostring");
+	lua_pushvalue(L, 2);
+	lua_call(L, 1, 1);
+	lua_concat(L, 2);
+	return lua_error(L);
+}
+
 static int luausb_generic_tostring(lua_State* L)
 {
 	lua_getmetatable(L, 1);
 	return udata;
 }
 
+int luausb_is_device_descriptor(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_device_descriptor");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_device_descriptor* luausb_check_device_descriptor(lua_State* L, int index)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bLength(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bLength (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bLength = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_bDescriptorType(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bDescriptorType(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bDescriptorType (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bDescriptorType = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_bcdUSB(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bcdUSB(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bcdUSB (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bcdUSB = (uint16_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_bDeviceClass(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bDeviceClass(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bDeviceClass (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bDeviceClass = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_bDeviceSubClass(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bDeviceSubClass(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bDeviceSubClass (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bDeviceSubClass = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_bDeviceProtocol(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bDeviceProtocol(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bDeviceProtocol (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bDeviceProtocol = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_bMaxPacketSize0(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bMaxPacketSize0(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bMaxPacketSize0 (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bMaxPacketSize0 = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_idVendor(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_idVendor(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field idVendor (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->idVendor = (uint16_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_idProduct(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_idProduct(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field idProduct (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->idProduct = (uint16_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_bcdDevice(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bcdDevice(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bcdDevice (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bcdDevice = (uint16_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_iManufacturer(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_iManufacturer(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field iManufacturer (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->iManufacturer = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_iProduct(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_iProduct(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field iProduct (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->iProduct = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_iSerialNumber(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_iSerialNumber(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field iSerialNumber (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->iSerialNumber = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_device_descriptor_bNumConfigurations(lua_State* L)
 {
 	struct libusb_device_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_device_descriptor_bNumConfigurations(lua_State* L)
+{
+	struct libusb_device_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bNumConfigurations (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_device_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bNumConfigurations = (uint8_t)value;
+	return 0;
+}
+
 static struct luaL_Reg libusb_device_descriptor__getters[] = {
 	{"bLength", luausb_get_device_descriptor_bLength},
 	{"bDescriptorType", luausb_get_device_descriptor_bDescriptorType},
 	{"bNumConfigurations", luausb_get_device_descriptor_bNumConfigurations},
 	{0, 0},
 };
+
+static struct luaL_Reg libusb_device_descriptor__setters[] = {
+	{"bLength", luausb_set_device_descriptor_bLength},
+	{"bDescriptorType", luausb_set_device_descriptor_bDescriptorType},
+	{"bcdUSB", luausb_set_device_descriptor_bcdUSB},
+	{"bDeviceClass", luausb_set_device_descriptor_bDeviceClass},
+	{"bDeviceSubClass", luausb_set_device_descriptor_bDeviceSubClass},
+	{"bDeviceProtocol", luausb_set_device_descriptor_bDeviceProtocol},
+	{"bMaxPacketSize0", luausb_set_device_descriptor_bMaxPacketSize0},
+	{"idVendor", luausb_set_device_descriptor_idVendor},
+	{"idProduct", luausb_set_device_descriptor_idProduct},
+	{"bcdDevice", luausb_set_device_descriptor_bcdDevice},
+	{"iManufacturer", luausb_set_device_descriptor_iManufacturer},
+	{"iProduct", luausb_set_device_descriptor_iProduct},
+	{"iSerialNumber", luausb_set_device_descriptor_iSerialNumber},
+	{"bNumConfigurations", luausb_set_device_descriptor_bNumConfigurations},
+	{0, 0},
+};
 static struct luaL_Reg libusb_device_descriptor__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 	{"__tostring", luausb_generic_tostring},
 	{0, 0},
 };
 	return udata;
 }
 
+int luausb_is_endpoint_descriptor(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_endpoint_descriptor");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_endpoint_descriptor* luausb_check_endpoint_descriptor(lua_State* L, int index)
 {
 	struct libusb_endpoint_descriptor* udata;
 	*udata = value;
 	luaL_getmetatable(L, "struct libusb_endpoint_descriptor");
 	lua_setmetatable(L, -2);
+	lua_createtable(L, 1, 0);
 	if (owner != 0)
 	{
-		lua_createtable(L, 1, 0);
 		lua_pushvalue(L, owner);
 		lua_rawseti(L, -2, 1);
-		setuservalue(L, -2);
 	}
+	setuservalue(L, -2);
 }
 
 static int luausb_get_endpoint_descriptor_bLength(lua_State* L)
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_bLength(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bLength (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bLength = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_endpoint_descriptor_bDescriptorType(lua_State* L)
 {
 	struct libusb_endpoint_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_bDescriptorType(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bDescriptorType (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bDescriptorType = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_endpoint_descriptor_bEndpointAddress(lua_State* L)
 {
 	struct libusb_endpoint_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_bEndpointAddress(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bEndpointAddress (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bEndpointAddress = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_endpoint_descriptor_bmAttributes(lua_State* L)
 {
 	struct libusb_endpoint_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_bmAttributes(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bmAttributes (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bmAttributes = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_endpoint_descriptor_wMaxPacketSize(lua_State* L)
 {
 	struct libusb_endpoint_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_wMaxPacketSize(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field wMaxPacketSize (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->wMaxPacketSize = (uint16_t)value;
+	return 0;
+}
+
 static int luausb_get_endpoint_descriptor_bInterval(lua_State* L)
 {
 	struct libusb_endpoint_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_bInterval(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bInterval (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bInterval = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_endpoint_descriptor_bRefresh(lua_State* L)
 {
 	struct libusb_endpoint_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_bRefresh(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bRefresh (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bRefresh = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_endpoint_descriptor_bSynchAddress(lua_State* L)
 {
 	struct libusb_endpoint_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_bSynchAddress(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bSynchAddress (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bSynchAddress = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_endpoint_descriptor_extra(lua_State* L)
 {
 	struct libusb_endpoint_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_endpoint_descriptor_extra(lua_State* L)
+{
+	struct libusb_endpoint_descriptor* udata;
+	if (!lua_isstring(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field extra (string expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_endpoint_descriptor(L, 1);
+	getuservalue(L, 1);
+	lua_pushvalue(L, 2);
+	lua_setfield(L, -2, "extra");
+	lua_pop(L, 1);
+	{
+		size_t size;
+		udata->extra = lua_tolstring(L, 2, &size);
+		udata->extra_length = (int)size;
+	}
+	return 0;
+}
+
 static struct luaL_Reg libusb_endpoint_descriptor__getters[] = {
 	{"bLength", luausb_get_endpoint_descriptor_bLength},
 	{"bDescriptorType", luausb_get_endpoint_descriptor_bDescriptorType},
 	{"extra", luausb_get_endpoint_descriptor_extra},
 	{0, 0},
 };
+
+static struct luaL_Reg libusb_endpoint_descriptor__setters[] = {
+	{"bLength", luausb_set_endpoint_descriptor_bLength},
+	{"bDescriptorType", luausb_set_endpoint_descriptor_bDescriptorType},
+	{"bEndpointAddress", luausb_set_endpoint_descriptor_bEndpointAddress},
+	{"bmAttributes", luausb_set_endpoint_descriptor_bmAttributes},
+	{"wMaxPacketSize", luausb_set_endpoint_descriptor_wMaxPacketSize},
+	{"bInterval", luausb_set_endpoint_descriptor_bInterval},
+	{"bRefresh", luausb_set_endpoint_descriptor_bRefresh},
+	{"bSynchAddress", luausb_set_endpoint_descriptor_bSynchAddress},
+	{"extra", luausb_set_endpoint_descriptor_extra},
+	{0, 0},
+};
 static struct luaL_Reg libusb_endpoint_descriptor__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 	{"__tostring", luausb_generic_tostring},
 	{0, 0},
 };
 	return udata;
 }
 
+int luausb_is_interface_descriptor(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_interface_descriptor");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_interface_descriptor* luausb_check_interface_descriptor(lua_State* L, int index)
 {
 	struct libusb_interface_descriptor* udata;
 	*udata = value;
 	luaL_getmetatable(L, "struct libusb_interface_descriptor");
 	lua_setmetatable(L, -2);
+	lua_createtable(L, 1, 0);
 	if (owner != 0)
 	{
-		lua_createtable(L, 1, 0);
 		lua_pushvalue(L, owner);
 		lua_rawseti(L, -2, 1);
-		setuservalue(L, -2);
 	}
+	setuservalue(L, -2);
 }
 
 static int luausb_get_interface_descriptor_bLength(lua_State* L)
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_bLength(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bLength (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bLength = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_interface_descriptor_bDescriptorType(lua_State* L)
 {
 	struct libusb_interface_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_bDescriptorType(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bDescriptorType (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bDescriptorType = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_interface_descriptor_bInterfaceNumber(lua_State* L)
 {
 	struct libusb_interface_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_bInterfaceNumber(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bInterfaceNumber (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bInterfaceNumber = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_interface_descriptor_bAlternateSetting(lua_State* L)
 {
 	struct libusb_interface_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_bAlternateSetting(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bAlternateSetting (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bAlternateSetting = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_interface_descriptor_bNumEndpoints(lua_State* L)
 {
 	struct libusb_interface_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_bNumEndpoints(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bNumEndpoints (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bNumEndpoints = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_interface_descriptor_bInterfaceClass(lua_State* L)
 {
 	struct libusb_interface_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_bInterfaceClass(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bInterfaceClass (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bInterfaceClass = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_interface_descriptor_bInterfaceSubClass(lua_State* L)
 {
 	struct libusb_interface_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_bInterfaceSubClass(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bInterfaceSubClass (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bInterfaceSubClass = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_interface_descriptor_bInterfaceProtocol(lua_State* L)
 {
 	struct libusb_interface_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_bInterfaceProtocol(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bInterfaceProtocol (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bInterfaceProtocol = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_interface_descriptor_iInterface(lua_State* L)
 {
 	struct libusb_interface_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_iInterface(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field iInterface (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->iInterface = (uint8_t)value;
+	return 0;
+}
+
 int luausb_get_interface_descriptor_endpoint(lua_State* L);
 
 static int luausb_get_interface_descriptor_extra(lua_State* L)
 	return 1;
 }
 
+static int luausb_set_interface_descriptor_extra(lua_State* L)
+{
+	struct libusb_interface_descriptor* udata;
+	if (!lua_isstring(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field extra (string expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface_descriptor(L, 1);
+	getuservalue(L, 1);
+	lua_pushvalue(L, 2);
+	lua_setfield(L, -2, "extra");
+	lua_pop(L, 1);
+	{
+		size_t size;
+		udata->extra = lua_tolstring(L, 2, &size);
+		udata->extra_length = (int)size;
+	}
+	return 0;
+}
+
 static struct luaL_Reg libusb_interface_descriptor__getters[] = {
 	{"bLength", luausb_get_interface_descriptor_bLength},
 	{"bDescriptorType", luausb_get_interface_descriptor_bDescriptorType},
 	{"extra", luausb_get_interface_descriptor_extra},
 	{0, 0},
 };
+
+static struct luaL_Reg libusb_interface_descriptor__setters[] = {
+	{"bLength", luausb_set_interface_descriptor_bLength},
+	{"bDescriptorType", luausb_set_interface_descriptor_bDescriptorType},
+	{"bInterfaceNumber", luausb_set_interface_descriptor_bInterfaceNumber},
+	{"bAlternateSetting", luausb_set_interface_descriptor_bAlternateSetting},
+	{"bNumEndpoints", luausb_set_interface_descriptor_bNumEndpoints},
+	{"bInterfaceClass", luausb_set_interface_descriptor_bInterfaceClass},
+	{"bInterfaceSubClass", luausb_set_interface_descriptor_bInterfaceSubClass},
+	{"bInterfaceProtocol", luausb_set_interface_descriptor_bInterfaceProtocol},
+	{"iInterface", luausb_set_interface_descriptor_iInterface},
+	{"extra", luausb_set_interface_descriptor_extra},
+	{0, 0},
+};
 static struct luaL_Reg libusb_interface_descriptor__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 	{"__tostring", luausb_generic_tostring},
 	{0, 0},
 };
 	return udata;
 }
 
+int luausb_is_interface(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_interface");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_interface* luausb_check_interface(lua_State* L, int index)
 {
 	struct libusb_interface* udata;
 	return 1;
 }
 
+static int luausb_set_interface_num_altsetting(lua_State* L)
+{
+	struct libusb_interface* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field num_altsetting (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_interface(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->num_altsetting = (int)value;
+	return 0;
+}
+
 static struct luaL_Reg libusb_interface__getters[] = {
 	{"altsetting", luausb_get_interface_altsetting},
 	{"num_altsetting", luausb_get_interface_num_altsetting},
 	{0, 0},
 };
+
+static struct luaL_Reg libusb_interface__setters[] = {
+	{"num_altsetting", luausb_set_interface_num_altsetting},
+	{0, 0},
+};
 static struct luaL_Reg libusb_interface__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 	{"__tostring", luausb_generic_tostring},
 	{0, 0},
 };
 	return udata;
 }
 
+int luausb_is_config_descriptor(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_config_descriptor");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_config_descriptor* luausb_check_config_descriptor(lua_State* L, int index)
 {
 	struct libusb_config_descriptor* udata;
 	*udata = value;
 	luaL_getmetatable(L, "struct libusb_config_descriptor");
 	lua_setmetatable(L, -2);
+	lua_createtable(L, 1, 0);
 	if (owner != 0)
 	{
-		lua_createtable(L, 1, 0);
 		lua_pushvalue(L, owner);
 		lua_rawseti(L, -2, 1);
-		setuservalue(L, -2);
 	}
+	setuservalue(L, -2);
 }
 
 static int luausb_get_config_descriptor_bLength(lua_State* L)
 	return 1;
 }
 
+static int luausb_set_config_descriptor_bLength(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bLength (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bLength = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_config_descriptor_bDescriptorType(lua_State* L)
 {
 	struct libusb_config_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_config_descriptor_bDescriptorType(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bDescriptorType (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bDescriptorType = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_config_descriptor_wTotalLength(lua_State* L)
 {
 	struct libusb_config_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_config_descriptor_wTotalLength(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field wTotalLength (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->wTotalLength = (uint16_t)value;
+	return 0;
+}
+
 static int luausb_get_config_descriptor_bNumInterfaces(lua_State* L)
 {
 	struct libusb_config_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_config_descriptor_bNumInterfaces(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bNumInterfaces (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bNumInterfaces = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_config_descriptor_bConfigurationValue(lua_State* L)
 {
 	struct libusb_config_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_config_descriptor_bConfigurationValue(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bConfigurationValue (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bConfigurationValue = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_config_descriptor_iConfiguration(lua_State* L)
 {
 	struct libusb_config_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_config_descriptor_iConfiguration(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field iConfiguration (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->iConfiguration = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_config_descriptor_bmAttributes(lua_State* L)
 {
 	struct libusb_config_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_config_descriptor_bmAttributes(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field bmAttributes (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->bmAttributes = (uint8_t)value;
+	return 0;
+}
+
 static int luausb_get_config_descriptor_MaxPower(lua_State* L)
 {
 	struct libusb_config_descriptor* udata;
 	return 1;
 }
 
+static int luausb_set_config_descriptor_MaxPower(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field MaxPower (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->MaxPower = (uint8_t)value;
+	return 0;
+}
+
 int luausb_get_config_descriptor_interface(lua_State* L);
 
 static int luausb_get_config_descriptor_extra(lua_State* L)
 	return 1;
 }
 
+static int luausb_set_config_descriptor_extra(lua_State* L)
+{
+	struct libusb_config_descriptor* udata;
+	if (!lua_isstring(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field extra (string expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_config_descriptor(L, 1);
+	getuservalue(L, 1);
+	lua_pushvalue(L, 2);
+	lua_setfield(L, -2, "extra");
+	lua_pop(L, 1);
+	{
+		size_t size;
+		udata->extra = lua_tolstring(L, 2, &size);
+		udata->extra_length = (int)size;
+	}
+	return 0;
+}
+
 static struct luaL_Reg libusb_config_descriptor__getters[] = {
 	{"bLength", luausb_get_config_descriptor_bLength},
 	{"bDescriptorType", luausb_get_config_descriptor_bDescriptorType},
 	{"extra", luausb_get_config_descriptor_extra},
 	{0, 0},
 };
+
+static struct luaL_Reg libusb_config_descriptor__setters[] = {
+	{"bLength", luausb_set_config_descriptor_bLength},
+	{"bDescriptorType", luausb_set_config_descriptor_bDescriptorType},
+	{"wTotalLength", luausb_set_config_descriptor_wTotalLength},
+	{"bNumInterfaces", luausb_set_config_descriptor_bNumInterfaces},
+	{"bConfigurationValue", luausb_set_config_descriptor_bConfigurationValue},
+	{"iConfiguration", luausb_set_config_descriptor_iConfiguration},
+	{"bmAttributes", luausb_set_config_descriptor_bmAttributes},
+	{"MaxPower", luausb_set_config_descriptor_MaxPower},
+	{"extra", luausb_set_config_descriptor_extra},
+	{0, 0},
+};
 int luausb_config_descriptor_gc(lua_State* L);
 static struct luaL_Reg libusb_config_descriptor__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 	{"__tostring", luausb_generic_tostring},
 	{"__gc", luausb_config_descriptor_gc},
 	{0, 0},
 	return udata;
 }
 
+int luausb_is_device(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_device");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_device* luausb_check_device(lua_State* L, int index)
 {
 	struct libusb_device* udata;
 static struct luaL_Reg libusb_device__getters[] = {
 	{0, 0},
 };
+
+static struct luaL_Reg libusb_device__setters[] = {
+	{0, 0},
+};
 int luausb_device_gc(lua_State* L);
 static struct luaL_Reg libusb_device__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 	{"__tostring", luausb_generic_tostring},
 	{"__gc", luausb_device_gc},
 	{0, 0},
 	return udata;
 }
 
+int luausb_is_device_handle(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_device_handle");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_device_handle* luausb_check_device_handle(lua_State* L, int index)
 {
 	struct libusb_device_handle* udata;
 static struct luaL_Reg libusb_device_handle__getters[] = {
 	{0, 0},
 };
+
+static struct luaL_Reg libusb_device_handle__setters[] = {
+	{0, 0},
+};
 int luausb_device_handle_gc(lua_State* L);
 static struct luaL_Reg libusb_device_handle__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 	{"__tostring", luausb_generic_tostring},
 	{"__gc", luausb_device_handle_gc},
 	{0, 0},
 	return udata;
 }
 
+int luausb_is_transfer(lua_State* L, int index)
+{
+	int result = 0;
+	void* p = lua_touserdata(L, index);
+	/* value is a userdata? */
+	if (p != NULL)
+	{
+		/* does it have a metatable? */
+		if (lua_getmetatable(L, index))
+		{
+			/* get correct metatable */
+			lua_getfield(L, LUA_REGISTRYINDEX, "struct libusb_transfer");
+			/* does it have the correct mt? */
+			if (lua_rawequal(L, -1, -2))
+			{
+				result = 1;
+			}
+			lua_pop(L, 1); /* remove type metatable */
+		}
+		lua_pop(L, 1); /* remove udata metatable */
+	}
+	return result;
+}
+
 struct libusb_transfer* luausb_check_transfer(lua_State* L, int index)
 {
 	struct libusb_transfer* udata;
 	*udata = value;
 	luaL_getmetatable(L, "struct libusb_transfer");
 	lua_setmetatable(L, -2);
+	lua_createtable(L, 1, 0);
 	if (owner != 0)
 	{
-		lua_createtable(L, 1, 0);
 		lua_pushvalue(L, owner);
 		lua_rawseti(L, -2, 1);
-		setuservalue(L, -2);
 	}
+	setuservalue(L, -2);
+}
+
+int luausb_get_transfer_dev_handle(lua_State* L);
+int luausb_set_transfer_dev_handle(lua_State* L);
+
+static int luausb_get_transfer_flags(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	udata = luausb_to_transfer(L, 1);
+	lua_pushnumber(L, udata->flags);
+	return 1;
+}
+
+static int luausb_set_transfer_flags(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field flags (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_transfer(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->flags = (uint8_t)value;
+	return 0;
+}
+
+static int luausb_get_transfer_endpoint(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	udata = luausb_to_transfer(L, 1);
+	lua_pushnumber(L, udata->endpoint);
+	return 1;
+}
+
+static int luausb_set_transfer_endpoint(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field endpoint (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_transfer(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->endpoint = (unsigned char)value;
+	return 0;
+}
+
+static int luausb_get_transfer_type(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	udata = luausb_to_transfer(L, 1);
+	lua_pushnumber(L, udata->type);
+	return 1;
+}
+
+static int luausb_set_transfer_type(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field type (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_transfer(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->type = (unsigned char)value;
+	return 0;
+}
+
+static int luausb_get_transfer_timeout(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	udata = luausb_to_transfer(L, 1);
+	lua_pushnumber(L, udata->timeout);
+	return 1;
+}
+
+static int luausb_set_transfer_timeout(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field timeout (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_transfer(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->timeout = (unsigned int)value;
+	return 0;
+}
+
+static int luausb_get_transfer_status(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	udata = luausb_to_transfer(L, 1);
+	lua_pushnumber(L, udata->status);
+	return 1;
+}
+
+static int luausb_set_transfer_status(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field status (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_transfer(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->status = (enum libusb_transfer_status)value;
+	return 0;
+}
+
+static int luausb_get_transfer_actual_length(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	udata = luausb_to_transfer(L, 1);
+	lua_pushnumber(L, udata->actual_length);
+	return 1;
+}
+
+static int luausb_set_transfer_actual_length(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	lua_Number value;
+	if (!lua_isnumber(L, 2))
+	{
+		lua_pushliteral(L, "invalid value for field actual_length (number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	udata = luausb_to_transfer(L, 1);
+	value = lua_tonumber(L, 2);
+	udata->actual_length = (int)value;
+	return 0;
+}
+
+int luausb_get_transfer_callback(lua_State* L);
+int luausb_set_transfer_callback(lua_State* L);
+
+static int luausb_get_transfer_buffer(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	udata = luausb_to_transfer(L, 1);
+	if (udata->buffer)
+	{
+		lua_pushlstring(L, (const char*)udata->buffer, udata->length);
+	}
+	else
+		lua_pushnil(L);
+	return 1;
+}
+
+static int luausb_set_transfer_buffer(lua_State* L)
+{
+	struct libusb_transfer* udata;
+	udata = luausb_to_transfer(L, 1);
+	if (lua_type(L, 2)==LUA_TSTRING)
+	{
+		const char* value;
+		size_t size;
+		char* buffer;
+		value = lua_tolstring(L, 2, &size);
+		getuservalue(L, 1);
+		buffer = lua_newuserdata(L, size);
+		lua_setfield(L, -2, "buffer");
+		lua_pop(L, 1);
+		memcpy(buffer, value, size);
+		udata->buffer = buffer;
+		udata->length = (int)size;
+	}
+	else if (lua_type(L, 2)==LUA_TNUMBER)
+	{
+		size_t size;
+		char* buffer;
+		size = (size_t)lua_tonumber(L, 2); /* :FIXME: handle overflow */
+		getuservalue(L, 1);
+		buffer = lua_newuserdata(L, size);
+		lua_setfield(L, -2, "buffer");
+		lua_pop(L, 1);
+		memset(buffer, 0, size);
+		udata->buffer = buffer;
+		udata->length = (int)size;
+	}
+	else
+	{
+		lua_pushliteral(L, "invalid value for field buffer (string or number expected, got ");
+		lua_pushstring(L, luaL_typename(L, 2));
+		lua_pushliteral(L, ")");
+		lua_concat(L, 3);
+		return lua_error(L);
+	}
+	return 0;
 }
 
 static struct luaL_Reg libusb_transfer__getters[] = {
+	{"dev_handle", luausb_get_transfer_dev_handle},
+	{"flags", luausb_get_transfer_flags},
+	{"endpoint", luausb_get_transfer_endpoint},
+	{"type", luausb_get_transfer_type},
+	{"timeout", luausb_get_transfer_timeout},
+	{"status", luausb_get_transfer_status},
+	{"actual_length", luausb_get_transfer_actual_length},
+	{"callback", luausb_get_transfer_callback},
+	{"buffer", luausb_get_transfer_buffer},
+	{0, 0},
+};
+
+static struct luaL_Reg libusb_transfer__setters[] = {
+	{"dev_handle", luausb_set_transfer_dev_handle},
+	{"flags", luausb_set_transfer_flags},
+	{"endpoint", luausb_set_transfer_endpoint},
+	{"type", luausb_set_transfer_type},
+	{"timeout", luausb_set_transfer_timeout},
+	{"status", luausb_set_transfer_status},
+	{"actual_length", luausb_set_transfer_actual_length},
+	{"callback", luausb_set_transfer_callback},
+	{"buffer", luausb_set_transfer_buffer},
 	{0, 0},
 };
 int luausb_transfer_gc(lua_State* L);
 static struct luaL_Reg libusb_transfer__metamethods[] = {
 	{"__index", luausb_generic_index},
+	{"__newindex", luausb_generic_newindex},
 	{"__tostring", luausb_generic_tostring},
 	{"__gc", luausb_transfer_gc},
 	{0, 0},
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_device_descriptor__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_device_descriptor__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "device_descriptor");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_endpoint_descriptor__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_endpoint_descriptor__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "endpoint_descriptor");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_interface_descriptor__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_interface_descriptor__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "interface_descriptor");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_interface__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_interface__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "interface");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_config_descriptor__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_config_descriptor__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "config_descriptor");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_device__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_device__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "device");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_device_handle__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_device_handle__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "device_handle");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 	lua_pushvalue(L, 1);
 	setfuncs(L, libusb_transfer__getters, 1);
 	lua_setfield(L, -2, "getters");
+	lua_newtable(L);
+	lua_pushvalue(L, 1);
+	setfuncs(L, libusb_transfer__setters, 1);
+	lua_setfield(L, -2, "setters");
 	lua_pushliteral(L, "transfer");
 	lua_setfield(L, -2, "typename");
 	lua_pop(L, 1);
 #include <libusb.h>
 
 struct libusb_device_descriptor* luausb_to_device_descriptor(lua_State* L, int index);
+int luausb_is_device_descriptor(lua_State* L, int index);
 struct libusb_device_descriptor* luausb_check_device_descriptor(lua_State* L, int index);
 void luausb_push_device_descriptor(lua_State* L, const struct libusb_device_descriptor* value, int owner);
 struct libusb_endpoint_descriptor* luausb_to_endpoint_descriptor(lua_State* L, int index);
+int luausb_is_endpoint_descriptor(lua_State* L, int index);
 struct libusb_endpoint_descriptor* luausb_check_endpoint_descriptor(lua_State* L, int index);
 void luausb_push_endpoint_descriptor(lua_State* L, const struct libusb_endpoint_descriptor* value, int owner);
 struct libusb_interface_descriptor* luausb_to_interface_descriptor(lua_State* L, int index);
+int luausb_is_interface_descriptor(lua_State* L, int index);
 struct libusb_interface_descriptor* luausb_check_interface_descriptor(lua_State* L, int index);
 void luausb_push_interface_descriptor(lua_State* L, const struct libusb_interface_descriptor* value, int owner);
 struct libusb_interface* luausb_to_interface(lua_State* L, int index);
+int luausb_is_interface(lua_State* L, int index);
 struct libusb_interface* luausb_check_interface(lua_State* L, int index);
 void luausb_push_interface(lua_State* L, const struct libusb_interface* value, int owner);
 struct libusb_config_descriptor* luausb_to_config_descriptor(lua_State* L, int index);
+int luausb_is_config_descriptor(lua_State* L, int index);
 struct libusb_config_descriptor* luausb_check_config_descriptor(lua_State* L, int index);
 void luausb_push_config_descriptor(lua_State* L, const struct libusb_config_descriptor* value, int owner);
 struct libusb_device* luausb_to_device(lua_State* L, int index);
+int luausb_is_device(lua_State* L, int index);
 struct libusb_device* luausb_check_device(lua_State* L, int index);
 void luausb_push_device(lua_State* L, const struct libusb_device* value, int owner);
 struct libusb_device_handle* luausb_to_device_handle(lua_State* L, int index);
+int luausb_is_device_handle(lua_State* L, int index);
 struct libusb_device_handle* luausb_check_device_handle(lua_State* L, int index);
 void luausb_push_device_handle(lua_State* L, const struct libusb_device_handle* value, int owner);
 struct libusb_transfer* luausb_to_transfer(lua_State* L, int index);
+int luausb_is_transfer(lua_State* L, int index);
 struct libusb_transfer* luausb_check_transfer(lua_State* L, int index);
 void luausb_push_transfer(lua_State* L, const struct libusb_transfer* value, int owner);
 void luausb_init_structs(lua_State* L);
 	return luausb_transfer_gc(L);
 }
 
-void luausb_transfer_cb(struct libusb_transfer* transfer)
-{
-	lua_State* L;
-	
-	L = transfer->user_data; /* buffer, callback, transfer */
-	
-	lua_pushvalue(L, -2); /* buffer, callback, transfer, callback */
-	lua_pushvalue(L, -2); /* buffer, callback, transfer, callback, transfer */
-	if (transfer->endpoint & LIBUSB_ENDPOINT_IN)
-		lua_pushlstring(L, (const char*)transfer->buffer, transfer->actual_length);
-	else
-		lua_pushnumber(L, transfer->actual_length);
-	if (lua_pcall(L, 2, 0, 0))
-	{
-		fprintf(stderr, "%s\n", lua_tostring(L, -1));
-		lua_pop(L, 1);
-	}
-}
-
-BINDING(fill_interrupt_transfer)
-{
-	struct libusb_transfer* transfer;
-	libusb_device_handle* dev_handle;
-	unsigned char endpoint;
-	unsigned char* buffer;
-	int length;
-	libusb_transfer_cb_fn callback;
-	void* user_data;
-	unsigned int timeout;
-	lua_State* thread;
-	
-	transfer = luausb_check_transfer(L, 1);
-	dev_handle = luausb_check_device_handle(L, 2);
-	endpoint = (unsigned char)luaL_checknumber(L, 3); /* :FIXME: handle overflow */
-	if (endpoint & LIBUSB_ENDPOINT_IN)
-		luaL_checknumber(L, 4);
-	else
-		luaL_checkstring(L, 4);
-	luaL_checktype(L, 5, LUA_TFUNCTION);
-	timeout = (unsigned int)luaL_optnumber(L, 6, 0); /* :FIXME: handle overflow */
-	
-	thread = lua_newthread(L);
-	lua_pushlightuserdata(L, thread);
-	lua_insert(L, -2);
-	lua_settable(L, LUA_REGISTRYINDEX);
-	
-	/* extract actual arg 4 value into a buffer on the thread stack */
-	if (endpoint & LIBUSB_ENDPOINT_IN)
-	{
-		/* in endpoint */
-		length = (int)lua_tonumber(L, 4); /* :FIXME: handle overflow */
-		buffer = (unsigned char*)lua_newuserdata(thread, length);
-	}
-	else
-	{
-		/* out endpoint */
-		size_t len;
-		const char* str;
-		str = lua_tolstring(L, 4, &len);
-		length = (int)len; /* :FIXME: handle overflow */
-		buffer = (unsigned char*)lua_newuserdata(thread, length);
-		memcpy(buffer, str, len);
-	}
-	
-	/* copy the callback function onto the thread stack */
-	lua_pushvalue(L, 5);
-	lua_xmove(L, thread, 1);
-	
-	/* copy the transfer object onto the thread stack */
-	lua_pushvalue(L, 1);
-	lua_xmove(L, thread, 1);
-	
-	user_data = thread;
-	callback = luausb_transfer_cb;
-	
-	libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, buffer, length, callback, user_data, timeout);
-	
-	return 0;
-}
-
 BINDING(submit_transfer)
 {
 	struct libusb_transfer* transfer;
 
 /****************************************************************************/
 
-int luausb_get_interface_descriptor_endpoint(lua_State* L)
+#define GETTER(c, f) int lu