public void imm_handleTimedNotification(YPktStreamHead data) { uint pos = 0; YDevice ydev = _yctx._yHash.imm_getDevice(SerialNumber); if (ydev == null) { // device has not been registered; return; } while (pos < data.Len) { int funYdx = data.imm_GetByte(pos) & 0xf; bool isAvg = (data.imm_GetByte(pos) & 0x80) != 0; uint len = (uint)(1 + ((data.imm_GetByte(pos) >> 4) & 0x7)); pos++; if (data.Len < pos + len) { _yctx._Log("drop invalid timedNotification"); return; } if (funYdx == 0xf) { byte[] intData = new byte[len]; for (uint i = 0; i < len; i++) { intData[i] = data.imm_GetByte(pos + i); } ydev.imm_setDeviceTime(intData); } else { YPEntry yp = imm_getYPEntryFromYdx(funYdx); if (yp != null) { List <int> report = new List <int>((int)(len + 1)); report.Add(isAvg ? 1 : 0); for (uint i = 0; i < len; i++) { int b = data.imm_GetByte(pos + i) & 0xff; report.Add(b); } _hub.imm_handleTimedNotification(yp.Serial, yp.FuncId, ydev.imm_getDeviceTime(), report); } } pos += len; } }
public void handleTimedNotificationV2(YPktStreamHead data) { uint pos = 0; YDevice ydev = _yctx._yHash.imm_getDevice(SerialNumber); if (ydev == null) { // device has not been registered; return; } while (pos < data.Len) { int funYdx = data.imm_GetByte(pos) & 0xf; uint extralen = (uint)((data.imm_GetByte(pos) >> 4) & 0xf); uint len = extralen + 1; pos++; // consume generic header if (funYdx == 0xf) { byte[] intData = new byte[len]; for (uint i = 0; i < len; i++) { intData[i] = data.imm_GetByte(pos + i); } ydev.imm_setDeviceTime(intData); } else { YPEntry yp = imm_getYPEntryFromYdx(funYdx); if (yp != null) { List <int> report = new List <int>((int)(len + 1)); report.Add(2); for (uint i = 0; i < len; i++) { int b = data.imm_GetByte(pos + i) & 0xff; report.Add(b); } _hub.imm_handleTimedNotification(yp.Serial, yp.FuncId, ydev.imm_getDeviceTime(), report); } } pos += len; } }
private void imm_handleNotifcation(YPktStreamHead ystream) { string functionId; int firstByte = ystream.imm_GetByte(0); bool isV2 = ystream.StreamType == YGenericHub.YSTREAM_NOTICE_V2; if (isV2 || firstByte <= NOTIFY_1STBYTE_MAXTINY || firstByte >= NOTIFY_1STBYTE_MINSMALL) { int funcvalType = (firstByte >> NOTIFY_V2_TYPE_OFS) & NOTIFY_V2_TYPE_MASK; int funydx = firstByte & NOTIFY_V2_FUNYDX_MASK; YPEntry ypEntry = imm_getYPEntryFromYdx(funydx); if (ypEntry != null) { if (ypEntry.Index == funydx) { if (funcvalType == YGenericHub.NOTIFY_V2_FLUSHGROUP) { // not yet used by devices } else { if ((firstByte & NOTIFY_V2_IS_SMALL_FLAG) != 0) { // added on 2015-02-25, remove code below when confirmed dead code throw new YAPI_Exception(YAPI.IO_ERROR, "Hub Should not fwd notification"); } int len = (int)ystream.Len; byte[] data = new byte[len]; ystream.imm_CopyData(data, 0); string funcval = YGenericHub.imm_decodePubVal(funcvalType, data, 1, len - 1); _hub.imm_handleValueNotification(SerialNumber, ypEntry.FuncId, funcval); } } } } else { string serial = ystream.imm_GetString(0, YAPI.YOCTO_SERIAL_LEN); if (SerialNumber == null) { SerialNumber = serial; } uint p = YAPI.YOCTO_SERIAL_LEN; int type = ystream.imm_GetByte(p++); switch (type) { case NOTIFY_PKT_NAME: _logicalname = ystream.imm_GetString(p, YAPI.YOCTO_LOGICAL_LEN); _beacon = ystream.imm_GetByte(p + YAPI.YOCTO_LOGICAL_LEN); break; case NOTIFY_PKT_PRODNAME: _product = ystream.imm_GetString(p, YAPI.YOCTO_PRODUCTNAME_LEN); break; case NOTIFY_PKT_CHILD: break; case NOTIFY_PKT_FIRMWARE: _firmware = ystream.imm_GetString(p, YAPI.YOCTO_FIRMWARE_LEN); p += YAPI.YOCTO_FIRMWARE_LEN; p += 2; _deviceid = (ushort)(ystream.imm_GetByte(p) + (ystream.imm_GetByte(p + 1) << 8)); break; case NOTIFY_PKT_FUNCNAME: functionId = ystream.imm_GetString(p, YAPI.YOCTO_FUNCTION_LEN); p += YAPI.YOCTO_FUNCTION_LEN; string funcname = ystream.imm_GetString(p, YAPI.YOCTO_LOGICAL_LEN); if (!_usbYP.ContainsKey(functionId)) { _usbYP[functionId] = new YPEntry(serial, functionId, YPEntry.BaseClass.Function); } _usbYP[functionId].LogicalName = funcname; break; case NOTIFY_PKT_FUNCVAL: functionId = ystream.imm_GetString(p, YAPI.YOCTO_FUNCTION_LEN); p += YAPI.YOCTO_FUNCTION_LEN; string funcval = ystream.imm_GetString(p, YAPI.YOCTO_PUBVAL_SIZE); _hub.imm_handleValueNotification(serial, functionId, funcval); break; case NOTIFY_PKT_STREAMREADY: _devState = DevState.StreamReadyReceived; _wp = new WPEntry(_logicalname, _product, _deviceid, "", _beacon, SerialNumber); _yctx._Log("Device " + SerialNumber + " ready.\n"); _currentTask.SetResult(true); break; case NOTIFY_PKT_LOG: //FIXME: handle log notification break; case NOTIFY_PKT_FUNCNAMEYDX: functionId = ystream.imm_GetString(p, YAPI.YOCTO_FUNCTION_LEN - 1); p += YAPI.YOCTO_FUNCTION_LEN - 1; byte funclass = ystream.imm_GetByte(p++); funcname = ystream.imm_GetString(p, YAPI.YOCTO_LOGICAL_LEN); p += YAPI.YOCTO_LOGICAL_LEN; byte funydx = ystream.imm_GetByte(p); if (!_usbYP.ContainsKey(functionId)) { _usbYP[functionId] = new YPEntry(serial, functionId, YPEntry.BaseClass.forByte(funclass)); } // update ydx _usbYP[functionId].Index = funydx; _usbYP[functionId].LogicalName = funcname; break; case NOTIFY_PKT_PRODINFO: break; default: //fixme: Find why this happening on my dev computer throw new YAPI_Exception(YAPI.IO_ERROR, "Invalid Notification"); } } }
internal async void OnInputReportEvent(HidDevice sender, HidInputReportReceivedEventArgs args) { if (_devState == DevState.Detected || _devState == DevState.IOError) { // drop all packet until reset has been sent return; } try { byte[] bb = args.Report.Data.ToArray(); long ofs = 1; //skip first byte that is not part of the packet List <YPktStreamHead> streams = new List <YPktStreamHead>(); while (ofs < bb.Length) { YPktStreamHead s = YPktStreamHead.imm_Decode(ofs, bb); if (s == null) { break; } //Debug.WriteLine(s.ToString()); streams.Add(s); ofs += s.Len + 2; } YPktStreamHead streamHead = streams[0]; switch (_devState) { case DevState.ResetSend: if (streamHead.PktType != YUSBPkt.YPKT_CONF || streamHead.StreamType != YUSBPkt.USB_CONF_RESET) { return; } byte low = streamHead.imm_GetByte(0); uint hig = streamHead.imm_GetByte(1); uint devapi = (hig << 8) + low; _devVersion = devapi; if (imm_CheckVersionCompatibility(devapi) < 0) { return; } await Start(_pktAckDelay); break; case DevState.StartSend: if (streamHead.PktType != YUSBPkt.YPKT_CONF || streamHead.StreamType != YUSBPkt.USB_CONF_START) { return; } if (_devVersion >= YUSBPkt.YPKT_USB_VERSION_BCD) { _pktAckDelay = streamHead.imm_GetByte(1); } else { _pktAckDelay = 0; } _lastpktno = streamHead.PktNumber; _devState = DevState.StartReceived; break; case DevState.StreamReadyReceived: case DevState.StartReceived: if (_devState == DevState.StreamReadyReceived || _devState == DevState.StartReceived) { if (_pktAckDelay > 0 && _lastpktno == streamHead.PktNumber) { //late retry : drop it since we already have the packet. return; } uint expectedPktNo = (_lastpktno + 1) & 7; if (streamHead.PktNumber != expectedPktNo) { String message = "Missing packet (look of pkt " + expectedPktNo + " but get " + streamHead.PktNumber + ")"; _yctx._Log(message + "\n"); _yctx._Log("Set YAPI.RESEND_MISSING_PKT on YAPI.InitAPI()\n"); _devState = DevState.IOError; _watcher.imm_removeUsableDevice(this); return; } _lastpktno = streamHead.PktNumber; await streamHandler(streams); await checkMetaUTC(); } break; default: return; } } catch (YAPI_Exception ex) { _yctx._Log(ex.Message + "\n"); _yctx._Log("Set YAPI.RESEND_MISSING_PKT on YAPI.InitAPI()\n"); _devState = DevState.IOError; _watcher.imm_removeUsableDevice(this); if (_currentTask != null) { _currentTask.SetException(ex); } } }