Exemplo n.º 1
0
int USPiInitialize (void)
{
	assert (s_pLibrary == 0);
	s_pLibrary = (TUSPiLibrary *) malloc (sizeof (TUSPiLibrary));
	assert (s_pLibrary != 0);

	DeviceNameService (&s_pLibrary->NameService);
	DWHCIDevice (&s_pLibrary->DWHCI);
	s_pLibrary->pEth0 = 0;

	if (!DWHCIDeviceInitialize (&s_pLibrary->DWHCI))
	{
		LogWrite (FromUSPi, LOG_ERROR, "Cannot initialize USB host controller interface");

		_DWHCIDevice (&s_pLibrary->DWHCI);
		_DeviceNameService (&s_pLibrary->NameService);
		free (s_pLibrary);
		s_pLibrary = 0;

		return 0;
	}

	s_pLibrary->pUKBD1 = (TUSBKeyboardDevice *) DeviceNameServiceGetDevice (DeviceNameServiceGet (), "ukbd1", FALSE);

	s_pLibrary->pUMouse1 = (TUSBMouseDevice *) DeviceNameServiceGetDevice (DeviceNameServiceGet (), "umouse1", FALSE);

	s_pLibrary->pMIDI1 = (TUSBMIDIDevice *) DeviceNameServiceGetDevice (DeviceNameServiceGet (), "umidi1", FALSE);

	for (unsigned i = 0; i < MAX_DEVICES; i++)
	{
		TString DeviceName;
		String  (&DeviceName);
		StringFormat (&DeviceName, "umsd%u", i+1);

		s_pLibrary->pUMSD[i] = (TUSBBulkOnlyMassStorageDevice *)
			DeviceNameServiceGetDevice (DeviceNameServiceGet (), StringGet (&DeviceName), TRUE);

		_String  (&DeviceName);
	}

	s_pLibrary->pEth0 = (TSMSC951xDevice *) DeviceNameServiceGetDevice (DeviceNameServiceGet (), "eth0", FALSE);

	for (unsigned i = 0; i < MAX_DEVICES; i++)
	{
		TString DeviceName;
		String  (&DeviceName);
		StringFormat (&DeviceName, "upad%u", i+1);

		s_pLibrary->pUPAD[i] = (TUSBGamePadDevice *)
			DeviceNameServiceGetDevice (DeviceNameServiceGet (), StringGet (&DeviceName), FALSE);

		_String  (&DeviceName);
	}

	LogWrite (FromUSPi, LOG_DEBUG, "USPi library successfully initialized");

	return 1;
}
Exemplo n.º 2
0
TString *USBStandardHubGetDeviceNames (TUSBDevice *pDevice)
{
	assert (pDevice != 0);

	TString *pResult = (TString *) malloc (sizeof (TString));
	assert (pResult != 0);
	String (pResult);

	for (unsigned nSelector = DeviceNameVendor; nSelector < DeviceNameUnknown; nSelector++)
	{
		TString *pName = USBDeviceGetName (pDevice, (TDeviceNameSelector) nSelector);
		assert (pName != 0);

		if (StringCompare (pName, "unknown") != 0)
		{
			if (StringGetLength (pResult) > 0)
			{
				StringAppend (pResult, ", ");
			}

			StringAppend (pResult, StringGet (pName));
		}

		_String (pName);
		free (pName);
	}

	if (StringGetLength (pResult) == 0)
	{
		StringSet (pResult, "unknown");
	}

	return pResult;
}
Exemplo n.º 3
0
static void GamePadStatusHandler (unsigned int nDeviceIndex, const USPiGamePadState *pState)
{
	TString Msg;
	String (&Msg);
	StringFormat (&Msg, "GamePad %u: Buttons 0x%X", nDeviceIndex + 1, pState->buttons);

	TString Value;
	String (&Value);

	if (pState->naxes > 0)
	{
		StringAppend (&Msg, " Axes");

		for (unsigned i = 0; i < pState->naxes; i++)
		{
			StringFormat (&Value, " %d", pState->axes[i].value);
			StringAppend (&Msg, StringGet (&Value));
		}
	}

	if (pState->nhats > 0)
	{
		StringAppend (&Msg, " Hats");

		for (unsigned i = 0; i < pState->nhats; i++)
		{
			StringFormat (&Value, " %d", pState->hats[i]);
			StringAppend (&Msg, StringGet (&Value));
		}
	}

	LogWrite (FromSample, LOG_NOTICE, StringGet (&Msg));
	
	_String (&Value);
	_String (&Msg);
}
Exemplo n.º 4
0
boolean USBKeyboardDeviceConfigure (TUSBDevice *pUSBDevice)
{
	TUSBKeyboardDevice *pThis = (TUSBKeyboardDevice *) pUSBDevice;
	assert (pThis != 0);

	TUSBConfigurationDescriptor *pConfDesc =
		(TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION);
	if (   pConfDesc == 0
	    || pConfDesc->bNumInterfaces <  1)
	{
		USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBKbd);

		return FALSE;
	}

	TUSBInterfaceDescriptor *pInterfaceDesc;
	while ((pInterfaceDesc = (TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE)) != 0)
	{
		if (   pInterfaceDesc->bNumEndpoints	  <  1
		    || pInterfaceDesc->bInterfaceClass	  != 0x03	// HID Class
		    || pInterfaceDesc->bInterfaceSubClass != 0x01	// Boot Interface Subclass
		    || pInterfaceDesc->bInterfaceProtocol != 0x01)	// Keyboard
		{
			continue;
		}

		pThis->m_ucInterfaceNumber  = pInterfaceDesc->bInterfaceNumber;
		pThis->m_ucAlternateSetting = pInterfaceDesc->bAlternateSetting;

		TUSBEndpointDescriptor *pEndpointDesc =
			(TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT);
		if (   pEndpointDesc == 0
		    || (pEndpointDesc->bEndpointAddress & 0x80) != 0x80		// Input EP
		    || (pEndpointDesc->bmAttributes     & 0x3F)	!= 0x03)	// Interrupt EP
		{
			continue;
		}

		assert (pThis->m_pReportEndpoint == 0);
		pThis->m_pReportEndpoint = malloc (sizeof (TUSBEndpoint));
		assert (pThis->m_pReportEndpoint != 0);
		USBEndpoint2 (pThis->m_pReportEndpoint, &pThis->m_USBDevice, pEndpointDesc);

		break;
	}

	if (pThis->m_pReportEndpoint == 0)
	{
		USBDeviceConfigurationError (&pThis->m_USBDevice, FromUSBKbd);

		return FALSE;
	}

	if (!USBDeviceConfigure (&pThis->m_USBDevice))
	{
		LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set configuration");

		return FALSE;
	}

	if (pThis->m_ucAlternateSetting != 0)
	{
		if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice),
					USBDeviceGetEndpoint0 (&pThis->m_USBDevice),
					REQUEST_OUT | REQUEST_TO_INTERFACE, SET_INTERFACE,
					pThis->m_ucAlternateSetting,
					pThis->m_ucInterfaceNumber, 0, 0) < 0)
		{
			LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set interface");

			return FALSE;
		}
	}

	if (DWHCIDeviceControlMessage (USBDeviceGetHost (&pThis->m_USBDevice),
				       USBDeviceGetEndpoint0 (&pThis->m_USBDevice),
				       REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_INTERFACE,
				       SET_PROTOCOL, BOOT_PROTOCOL,
				       pThis->m_ucInterfaceNumber, 0, 0) < 0)
	{
		LogWrite (FromUSBKbd, LOG_ERROR, "Cannot set boot protocol");

		return FALSE;
	}

	TString DeviceName;
	String (&DeviceName);
	StringFormat (&DeviceName, "ukbd%u", s_nDeviceNumber++);
	DeviceNameServiceAddDevice (DeviceNameServiceGet (), StringGet (&DeviceName), pThis, FALSE);

	_String (&DeviceName);

	return USBKeyboardDeviceStartRequest (pThis);
}
Exemplo n.º 5
0
boolean USBStandardHubEnumeratePorts (TUSBStandardHub *pThis)
{
	assert (pThis != 0);

	TUSBHostController *pHost = USBDeviceGetHost (&pThis->m_USBDevice);
	assert (pHost != 0);

	TUSBEndpoint *pEndpoint0 = USBDeviceGetEndpoint0 (&pThis->m_USBDevice);
	assert (pEndpoint0 != 0);

	assert (pThis->m_nPorts > 0);

	// first power on all ports
	for (unsigned nPort = 0; nPort < pThis->m_nPorts; nPort++)
	{
		if (DWHCIDeviceControlMessage (pHost, pEndpoint0,
			REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_OTHER,
			SET_FEATURE, PORT_POWER, nPort+1, 0, 0) < 0)
		{
			LogWrite (FromHub, LOG_ERROR, "Cannot power port %u", nPort+1);

			return FALSE;
		}
	}

	// pThis->m_pHubDesc->bPwrOn2PwrGood delay seems to be not enough
	// for some low speed devices, so we use the maximum here
	MsDelay (510);

	// now detect devices, reset and initialize them
	for (unsigned nPort = 0; nPort < pThis->m_nPorts; nPort++)
	{
		assert (pThis->m_pStatus[nPort] == 0);
		pThis->m_pStatus[nPort] = malloc (sizeof (TUSBPortStatus));
		assert (pThis->m_pStatus[nPort] != 0);

		if (DWHCIDeviceControlMessage (pHost, pEndpoint0,
			REQUEST_IN | REQUEST_CLASS | REQUEST_TO_OTHER,
			GET_STATUS, 0, nPort+1, pThis->m_pStatus[nPort], 4) != 4)
		{
			LogWrite (FromHub, LOG_ERROR, "Cannot get status of port %u", nPort+1);

			continue;
		}

		assert (pThis->m_pStatus[nPort]->wPortStatus & PORT_POWER__MASK);
		if (!(pThis->m_pStatus[nPort]->wPortStatus & PORT_CONNECTION__MASK))
		{
			continue;
		}

		if (DWHCIDeviceControlMessage (pHost, pEndpoint0,
			REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_OTHER,
			SET_FEATURE, PORT_RESET, nPort+1, 0, 0) < 0)
		{
			LogWrite (FromHub, LOG_ERROR, "Cannot reset port %u", nPort+1);

			continue;
		}

		MsDelay (100);

		if (DWHCIDeviceControlMessage (pHost, pEndpoint0,
			REQUEST_IN | REQUEST_CLASS | REQUEST_TO_OTHER,
			GET_STATUS, 0, nPort+1, pThis->m_pStatus[nPort], 4) != 4)
		{
			return FALSE;
		}

		//LogWrite (FromHub, LOG_DEBUG, "Port %u status is 0x%04X", nPort+1, (unsigned) pThis->m_pStatus[nPort]->wPortStatus);

		if (!(pThis->m_pStatus[nPort]->wPortStatus & PORT_ENABLE__MASK))
		{
			LogWrite (FromHub, LOG_ERROR, "Port %u is not enabled", nPort+1);

			continue;
		}

		// check for over-current
		if (pThis->m_pStatus[nPort]->wPortStatus & PORT_OVER_CURRENT__MASK)
		{
			DWHCIDeviceControlMessage (pHost, pEndpoint0,
				REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_OTHER,
				CLEAR_FEATURE, PORT_POWER, nPort+1, 0, 0);

			LogWrite (FromHub, LOG_ERROR, "Over-current condition on port %u", nPort+1);

			return FALSE;
		}

		TUSBSpeed Speed = USBSpeedUnknown;
		if (pThis->m_pStatus[nPort]->wPortStatus & PORT_LOW_SPEED__MASK)
		{
			Speed = USBSpeedLow;
		}
		else if (pThis->m_pStatus[nPort]->wPortStatus & PORT_HIGH_SPEED__MASK)
		{
			Speed = USBSpeedHigh;
		}
		else
		{
			Speed = USBSpeedFull;
		}

		// first create default device
		assert (pThis->m_pDevice[nPort] == 0);
		pThis->m_pDevice[nPort] = malloc (sizeof (TUSBDevice));
		assert (pThis->m_pDevice[nPort] != 0);
		USBDevice (pThis->m_pDevice[nPort], pHost, Speed, USBDeviceGetAddress (&pThis->m_USBDevice), nPort+1);

		if (!USBDeviceInitialize (pThis->m_pDevice[nPort]))
		{
			_USBDevice (pThis->m_pDevice[nPort]);
			free (pThis->m_pDevice[nPort]);
			pThis->m_pDevice[nPort] = 0;

			continue;
		}

		TString *pNames = USBStandardHubGetDeviceNames (pThis->m_pDevice[nPort]);
		assert (pNames != 0);

		LogWrite (FromHub, LOG_NOTICE, "Port %u: Device %s found", nPort+1, StringGet (pNames));

		_String (pNames);
		free (pNames);
	}

	// now configure devices
	for (unsigned nPort = 0; nPort < pThis->m_nPorts; nPort++)
	{
		if (pThis->m_pDevice[nPort] == 0)
		{
			continue;
		}

		// now create specific device from default device
		TUSBDevice *pChild = USBDeviceFactoryGetDevice (pThis->m_pDevice[nPort]);
		if (pChild != 0)
		{
			_USBDevice (pThis->m_pDevice[nPort]);		// delete default device
			free (pThis->m_pDevice[nPort]);
			pThis->m_pDevice[nPort] = pChild;		// assign specific device

			if (!(*pThis->m_pDevice[nPort]->Configure) (pThis->m_pDevice[nPort]))
			{
				LogWrite (FromHub, LOG_ERROR, "Port %u: Cannot configure device", nPort+1);

				continue;
			}

			LogWrite (FromHub, LOG_DEBUG, "Port %u: Device configured", nPort+1);
		}
		else
		{
			LogWrite (FromHub, LOG_NOTICE, "Port %u: Device is not supported", nPort+1);

			_USBDevice (pThis->m_pDevice[nPort]);
			free (pThis->m_pDevice[nPort]);
			pThis->m_pDevice[nPort] = 0;
		}
	}

	// again check for over-current
	TUSBHubStatus *pHubStatus = malloc (sizeof (TUSBHubStatus));
	assert (pHubStatus != 0);

	if (DWHCIDeviceControlMessage (pHost, pEndpoint0,
		REQUEST_IN | REQUEST_CLASS,
		GET_STATUS, 0, 0, pHubStatus, sizeof *pHubStatus) != (int) sizeof *pHubStatus)
	{
		LogWrite (FromHub, LOG_ERROR, "Cannot get hub status");

		free (pHubStatus);

		return FALSE;
	}

	if (pHubStatus->wHubStatus & HUB_OVER_CURRENT__MASK)
	{
		for (unsigned nPort = 0; nPort < pThis->m_nPorts; nPort++)
		{
			DWHCIDeviceControlMessage (pHost, pEndpoint0,
				REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_OTHER,
				CLEAR_FEATURE, PORT_POWER, nPort+1, 0, 0);
		}

		LogWrite (FromHub, LOG_ERROR, "Hub over-current condition");

		free (pHubStatus);

		return FALSE;
	}

	free (pHubStatus);
	pHubStatus = 0;

	boolean bResult = TRUE;

	for (unsigned nPort = 0; nPort < pThis->m_nPorts; nPort++)
	{
		if (DWHCIDeviceControlMessage (pHost, pEndpoint0,
			REQUEST_IN | REQUEST_CLASS | REQUEST_TO_OTHER,
			GET_STATUS, 0, nPort+1, pThis->m_pStatus[nPort], 4) != 4)
		{
			continue;
		}

		if (pThis->m_pStatus[nPort]->wPortStatus & PORT_OVER_CURRENT__MASK)
		{
			DWHCIDeviceControlMessage (pHost, pEndpoint0,
				REQUEST_OUT | REQUEST_CLASS | REQUEST_TO_OTHER,
				CLEAR_FEATURE, PORT_POWER, nPort+1, 0, 0);

			LogWrite (FromHub, LOG_ERROR, "Over-current condition on port %u", nPort+1);

			bResult = FALSE;
		}
	}

	return bResult;
}
Exemplo n.º 6
0
boolean SMSC951xDeviceConfigure (TUSBDevice *pUSBDevice)
{
	TSMSC951xDevice *pThis = (TSMSC951xDevice *) pUSBDevice;
	assert (pThis != 0);

	u8 MACAddress[MAC_ADDRESS_SIZE];
	if (GetMACAddress (MACAddress))
	{
		MACAddressSet (&pThis->m_MACAddress, MACAddress);
	}
	else
	{
		LogWrite (FromSMSC951x, LOG_ERROR, "Cannot get MAC address");

		return FALSE;
	}
	TString MACString;
	String (&MACString);
	MACAddressFormat (&pThis->m_MACAddress, &MACString);
	LogWrite (FromSMSC951x, LOG_DEBUG, "MAC address is %s", StringGet (&MACString));

	const TUSBConfigurationDescriptor *pConfigDesc =
		(TUSBConfigurationDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_CONFIGURATION);
	if (   pConfigDesc == 0
	    || pConfigDesc->bNumInterfaces != 1)
	{
		USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x);

		_String (&MACString);

		return FALSE;
	}

	const TUSBInterfaceDescriptor *pInterfaceDesc =
		(TUSBInterfaceDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_INTERFACE);
	if (   pInterfaceDesc == 0
	    || pInterfaceDesc->bInterfaceNumber	 != 0x00
	    || pInterfaceDesc->bAlternateSetting != 0x00
	    || pInterfaceDesc->bNumEndpoints	 != 3)
	{
		USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x);

		_String (&MACString);

		return FALSE;
	}

	const TUSBEndpointDescriptor *pEndpointDesc;
	while ((pEndpointDesc = (TUSBEndpointDescriptor *) USBDeviceGetDescriptor (&pThis->m_USBDevice, DESCRIPTOR_ENDPOINT)) != 0)
	{
		if ((pEndpointDesc->bmAttributes & 0x3F) == 0x02)		// Bulk
		{
			if ((pEndpointDesc->bEndpointAddress & 0x80) == 0x80)	// Input
			{
				if (pThis->m_pEndpointBulkIn != 0)
				{
					USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x);

					_String (&MACString);

					return FALSE;
				}

				pThis->m_pEndpointBulkIn = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint));
				assert (pThis->m_pEndpointBulkIn);
				USBEndpoint2 (pThis->m_pEndpointBulkIn, &pThis->m_USBDevice, pEndpointDesc);
			}
			else							// Output
			{
				if (pThis->m_pEndpointBulkOut != 0)
				{
					USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x);

					_String (&MACString);

					return FALSE;
				}

				pThis->m_pEndpointBulkOut = (TUSBEndpoint *) malloc (sizeof (TUSBEndpoint));
				assert (pThis->m_pEndpointBulkOut);
				USBEndpoint2 (pThis->m_pEndpointBulkOut, &pThis->m_USBDevice, pEndpointDesc);
			}
		}
	}

	if (   pThis->m_pEndpointBulkIn  == 0
	    || pThis->m_pEndpointBulkOut == 0)
	{
		USBDeviceConfigurationError (&pThis->m_USBDevice, FromSMSC951x);

		_String (&MACString);

		return FALSE;
	}

	if (!USBDeviceConfigure (&pThis->m_USBDevice))
	{
		LogWrite (FromSMSC951x, LOG_ERROR, "Cannot set configuration");

		_String (&MACString);

		return FALSE;
	}

	u8 MACAddressBuffer[MAC_ADDRESS_SIZE];
	MACAddressCopyTo (&pThis->m_MACAddress, MACAddressBuffer);
	u16 usMACAddressHigh = *(u16 *) &MACAddressBuffer[4];
	u32 nMACAddressLow   = *(u32 *) &MACAddressBuffer[0];
	if (   !SMSC951xDeviceWriteReg (pThis, ADDRH, usMACAddressHigh)
	    || !SMSC951xDeviceWriteReg (pThis, ADDRL, nMACAddressLow))
	{
		LogWrite (FromSMSC951x, LOG_ERROR, "Cannot set MAC address");

		_String (&MACString);

		return FALSE;
	}

	if (   !SMSC951xDeviceWriteReg (pThis, LED_GPIO_CFG,   LED_GPIO_CFG_SPD_LED
							     | LED_GPIO_CFG_LNK_LED
							     | LED_GPIO_CFG_FDX_LED)
	    || !SMSC951xDeviceWriteReg (pThis, MAC_CR,  MAC_CR_RCVOWN
						       //| MAC_CR_PRMS		// promiscous mode
						       | MAC_CR_TXEN
						       | MAC_CR_RXEN)
	    || !SMSC951xDeviceWriteReg (pThis, TX_CFG, TX_CFG_ON))
	{
		LogWrite (FromSMSC951x, LOG_ERROR, "Cannot start device");

		_String (&MACString);

		return FALSE;
	}

	// TODO: check if PHY is up (wait for it)

	TString DeviceName;
	String (&DeviceName);
	StringFormat (&DeviceName, "eth%u", s_nDeviceNumber++);
	DeviceNameServiceAddDevice (DeviceNameServiceGet (), StringGet (&DeviceName), pThis, FALSE);

	_String (&DeviceName);
	_String (&MACString);

	return TRUE;
}
Exemplo n.º 7
0
    int Ardb::GetValueByPattern(Context& ctx, const Slice& pattern, Data& subst, Data& value,
            ValueObjectMap* meta_cache)
    {
        const char *p, *f;
        const char* spat;
        /* If the pattern is "#" return the substitution object itself in order
         * to implement the "SORT ... GET #" feature. */
        spat = pattern.data();
        if (spat[0] == '#' && spat[1] == '\0')
        {
            value = subst;
            return 0;
        }

        /* If we can't find '*' in the pattern we return NULL as to GET a
         * fixed key does not make sense. */
        p = strchr(spat, '*');
        if (!p)
        {
            return -1;
        }
        std::string vstr;
        subst.GetDecodeString(vstr);

        f = strstr(spat, "->");
        if (NULL != f && (uint32) (f - spat) == (pattern.size() - 2))
        {
            f = NULL;
        }
        std::string keystr(pattern.data(), pattern.size());
        string_replace(keystr, "*", vstr);

        if (f == NULL)
        {
            /*
             * keystr = "len(...)"
             */
            if (keystr.find("len(") == 0 && keystr.rfind(")") == keystr.size() - 1)
            {
                keystr = keystr.substr(4, keystr.size() - 5);

                KeyType keytype = KEY_END;
                GetType(ctx, keystr, keytype);
                switch (keytype)
                {
                    case SET_META:
                    {
                        SetLen(ctx, keystr);
                        break;
                    }
                    case LIST_META:
                    {
                        ListLen(ctx, keystr);
                        break;
                    }
                    case ZSET_META:
                    {
                        ZSetLen(ctx, keystr);
                        break;
                    }
                    default:
                    {
                        return -1;
                    }
                }
                value.SetInt64(ctx.reply.integer);
                value.ToString();
                return 0;
            }
            ValueObject vv;
            int ret = StringGet(ctx, keystr, vv);
            if (0 == ret)
            {
                value = vv.meta.str_value;
                //value.ToString();
            }
            return ret;
        }
        else
        {
            size_t pos = keystr.find("->");
            std::string field = keystr.substr(pos + 2);
            keystr = keystr.substr(0, pos);
            int ret = 0;
            if (NULL == meta_cache)
            {
                ret = HashGet(ctx, keystr, field, value);
            }
            else
            {
                ValueObjectMap::iterator fit = meta_cache->find(keystr);
                if (fit == meta_cache->end())
                {
                    ValueObject meta;
                    GetMetaValue(ctx, keystr, HASH_META, meta);
                    fit = meta_cache->insert(ValueObjectMap::value_type(keystr, meta)).first;
                }
                Data ff;
                ff.SetString(field, true);
                ret = HashGet(ctx, fit->second, ff, value);
            }
            //value.ToString();
            return ret;
        }
    }