/*----------------------------------------------------------------------------*\ Init method for the Pb module Ao \*----------------------------------------------------------------------------*/ static pwr_tStatus IoCardInit ( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp ) { io_sCardLocal *local; pwr_sClass_Pb_Ao *op; io_sChannel *chanp; int i; op = (pwr_sClass_Pb_Ao *) cp->op; local = (io_sCardLocal *) cp->Local; if (rp->Class != pwr_cClass_Pb_DP_Slave) { errh_Info( "Illegal object type %s", cp->Name ); return IO__SUCCESS; } if (op->Status >= PB_MODULE_STATE_OPERATE) { // Calculate polycoeff for (i=0; i<cp->ChanListSize; i++) { chanp = &cp->chanlist[i]; if (!chanp->cop) continue; io_AoRangeToCoef(chanp); } } else errh_Info( "Error initializing Pb module Ao %s", cp->Name ); return IO__SUCCESS; }
static pwr_tStatus IoCardInit( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp) { pwr_sClass_OneWire_AoDevice *op = (pwr_sClass_OneWire_AoDevice *)cp->op; io_sLocalAoDevice *local; pwr_tStatus sts; char name[40]; pwr_tFileName fname, tmp; int name_len; char *s; if ( cp->chanlist[0].cop) { local = (io_sLocalAoDevice *) calloc( 1, sizeof(io_sLocalAoDevice)); cp->Local = local; sprintf( name, "%d-%012x", op->Family, op->Super.Address); name_len = strlen(name); strncpy( fname, op->DataFile, sizeof(fname)); // Replace all '%s' with 'family-serialnumber' s = fname; while ( (s = strstr( s, "%s"))) { strncpy( tmp, s+2, sizeof(tmp)); strcpy( s, name); strncat( fname, tmp, sizeof(fname)); } local->value_fp = fopen( fname, "w"); if (!local->value_fp) { errh_Error( "OneWire_AoDevice Unable op open %s, '%ux'", cp->Name, op->Super.Address); sts = IO__INITFAIL; op->Status = sts; return sts; } io_AoRangeToCoef( &cp->chanlist[0]); errh_Info( "Init of OneWire_AoDevice '%s'", cp->Name); } return IO__SUCCESS; }
/*----------------------------------------------------------------------------*\ Write method for the Pb module Ao \*----------------------------------------------------------------------------*/ static pwr_tStatus IoCardWrite ( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp ) { io_sCardLocal *local; pwr_sClass_Pb_Ao *op; pwr_sClass_Pb_DP_Slave *slave; int i; pwr_tInt8 data8 = 0; pwr_tInt16 data16 = 0; pwr_tInt32 data32 = 0; pwr_tUInt8 udata8 = 0; pwr_tUInt16 udata16 = 0; pwr_tUInt32 udata32 = 0; pwr_sClass_ChanAo *cop; pwr_sClass_Ao *sop; io_sChannel *chanp; int fixout; pwr_tFloat32 value; pwr_tFloat32 rawvalue; local = (io_sCardLocal *) cp->Local; op = (pwr_sClass_Pb_Ao *) cp->op; slave = (pwr_sClass_Pb_DP_Slave *) rp->op; if (op->Status >= PB_MODULE_STATE_OPERATE && slave->DisableSlave != 1) { fixout = ctx->Node->EmergBreakTrue && ctx->Node->EmergBreakSelect == FIXOUT; for (i=0; i<cp->ChanListSize; i++) { chanp = &cp->chanlist[i]; if (!chanp->cop || !chanp->sop) continue; cop = (pwr_sClass_ChanAo *) chanp->cop; sop = (pwr_sClass_Ao *) chanp->sop; // Determine what actual value we actually want! if (fixout) value = cop->FixedOutValue; else if (cop->TestOn) value = cop->TestValue; else { value = *(pwr_tFloat32 *) chanp->vbp; } // Make new coeff.. if necessary if (cop->CalculateNewCoef) io_AoRangeToCoef(chanp); // Convert to rawvalue if (value > cop->ActValRangeHigh) value = cop->ActValRangeHigh; else if ( value < cop->ActValRangeLow) value = cop->ActValRangeLow; rawvalue = cop->OutPolyCoef1 * value + cop->OutPolyCoef0; if ( rawvalue > 0) rawvalue = rawvalue + 0.5; else rawvalue = rawvalue - 0.5; // We don´t use RawValue in Profibus I/O sop->RawValue = 0; // Calculate signal value sop->SigValue = cop->SigValPolyCoef1 * value + cop->SigValPolyCoef0; if (op->BytesPerChannel == 4) { if (op->NumberRepresentation == PB_NUMREP_UNSIGNEDINT) { udata32 = (pwr_tUInt32) rawvalue; if (slave->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) udata32 = swap32(udata32); memcpy(local->output_area + op->OffsetOutputs + 4*i, &udata32, 4); } else if (op->NumberRepresentation == PB_NUMREP_SIGNEDINT) { data32 = (pwr_tInt32) rawvalue; if (slave->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) data32 = swap32(data32); memcpy(local->output_area + op->OffsetOutputs + 4*i, &data32, 4); } } else if (op->BytesPerChannel == 3) { if (op->NumberRepresentation == PB_NUMREP_UNSIGNEDINT) { udata32 = (pwr_tUInt32) rawvalue; if (slave->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) udata32 = swap32(udata32); memcpy(local->output_area + op->OffsetOutputs + 3*i, &udata32, 3); } else if (op->NumberRepresentation == PB_NUMREP_SIGNEDINT) { data32 = (pwr_tInt32) rawvalue; if (slave->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) data32 = swap32(data32); memcpy(local->output_area + op->OffsetOutputs + 3*i, &data32, 3); } } else if (op->BytesPerChannel == 2) { if (op->NumberRepresentation == PB_NUMREP_UNSIGNEDINT) { udata16 = (pwr_tUInt16) rawvalue; if (slave->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) udata16 = swap16(udata16); memcpy(local->output_area + op->OffsetOutputs + 2*i, &udata16, 2); } else if (op->NumberRepresentation == PB_NUMREP_SIGNEDINT) { data16 = (pwr_tInt16) rawvalue; if (slave->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) data16 = swap16(data16); memcpy(local->output_area + op->OffsetOutputs + 2*i, &data16, 2); } } else if (op->BytesPerChannel == 1) { if (op->NumberRepresentation == PB_NUMREP_UNSIGNEDINT) { udata8 = (pwr_tUInt8) rawvalue; memcpy(local->output_area + op->OffsetOutputs + i, &udata8, 1); } else if (op->NumberRepresentation == PB_NUMREP_SIGNEDINT) { data8 = (pwr_tInt8) rawvalue; memcpy(local->output_area + op->OffsetOutputs + i, &data8, 1); } } } } return IO__SUCCESS; }
static pwr_tStatus IoCardInit( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp) { int found = 0; int i; unsigned char port_mask[3] = {255,255,63}; unsigned char port[3] = {0,0,0}; int active; int timeout; io_sLocal *local; io_sLocalUSB *localUSB = (io_sLocalUSB *)rp->Local; pwr_sClass_MotionControl_USBIO *op = (pwr_sClass_MotionControl_USBIO *)cp->op; local = (io_sLocal *) calloc( 1, sizeof(io_sLocal)); cp->Local = local; /* Find the handle in rack local data */ for ( i = 0; i < (int)sizeof(localUSB->USB_Handle); i++) { if ( localUSB->snum[i] == op->Super.Address) { found = 1; local->USB_Handle = localUSB->USB_Handle[i]; break; } } if ( !found) { errh_Error( "Io init error, USBIO card not found '%s'", cp->Name); op->Status = pwr_eMotionControl_StatusEnum_FindDevice; return 0; } op->Status = USBIO_SoftReset( &local->USB_Handle); if ( op->Status) errh_Error( "IO Init Card '%s', Status %d", cp->Name, op->Status); /* Configure port A */ local->portA_hasDi = 0; local->portA_hasDo = 0; local->portA_diMask = 0; local->portA_doMask = 0; for ( i = 0; i < 8; i++) { if ( cp->chanlist[i].cop && cp->chanlist[i].sop && cp->chanlist[i].ChanClass == pwr_cClass_ChanDi) { local->portA_hasDi = 1; local->portA_diMask |= (1 << i); } else if ( cp->chanlist[i].cop && cp->chanlist[i].sop && cp->chanlist[i].ChanClass == pwr_cClass_ChanDo) { local->portA_hasDo = 1; local->portA_doMask |= (1 << i); } } if ( local->portA_hasDi || local->portA_hasDo) { op->Status = USBIO_ConfigDIO( &local->USB_Handle, 1, local->portA_diMask); if ( op->Status) errh_Error( "IO Init Card '%s', Status %d", cp->Name, op->Status); } /* Configure port B */ local->portB_hasDi = 0; local->portB_hasDo = 0; local->portB_hasAi = 0; for ( i = 8; i < 16; i++) { if ( cp->chanlist[i].cop && cp->chanlist[i].sop && cp->chanlist[i].ChanClass == pwr_cClass_ChanDi) { local->portB_hasDi = 1; local->portB_diMask |= (1 << (i - 8)); } else if ( cp->chanlist[i].cop && cp->chanlist[i].sop && cp->chanlist[i].ChanClass == pwr_cClass_ChanDo) { local->portB_hasDo = 1; local->portB_doMask |= (1 << (i - 8)); } if ( cp->chanlist[i].cop && cp->chanlist[i].sop && (cp->chanlist[i].ChanClass == pwr_cClass_ChanAi || cp->chanlist[i].ChanClass == pwr_cClass_ChanAit)) { local->portB_hasAi = 1; local->portB_aiMask |= (1 << (i - 8)); // Calculate conversion coefficients io_AiRangeToCoef( &cp->chanlist[i]); } } if ( local->portB_hasDi || local->portB_hasDo) { op->Status = USBIO_ConfigDIO( &local->USB_Handle, 2, local->portB_diMask); if ( op->Status) errh_Error( "IO Init Card '%s', Status %d", cp->Name, op->Status); } if ( local->portB_hasAi) { int num_ai; for ( i = 0; i < 8; i++) { if ( local->portB_aiMask & (1 << i)) num_ai = i + 1; } op->Status = USBIO_ConfigAI( &local->USB_Handle, num_ai); if ( op->Status) errh_Error( "IO Init Card '%s', Status %d", cp->Name, op->Status); } else op->Status = USBIO_ConfigAI( &local->USB_Handle, 0); /* Configure port C */ local->portC_hasDi = 0; local->portC_hasDo = 0; local->portC_hasAo = 0; for ( i = 16; i < 21; i++) { if ( cp->chanlist[i].cop && cp->chanlist[i].sop && cp->chanlist[i].ChanClass == pwr_cClass_ChanDi) { local->portC_hasDi = 1; local->portC_diMask |= (1 << (i - 16)); } else if ( cp->chanlist[i].cop && cp->chanlist[i].sop && cp->chanlist[i].ChanClass == pwr_cClass_ChanDo) { local->portC_hasDo = 1; local->portC_doMask |= (1 << (i - 16)); } if ( cp->chanlist[i].cop && cp->chanlist[i].sop && cp->chanlist[i].ChanClass == pwr_cClass_ChanAo) { local->portC_hasAo = 1; local->portC_aoMask |= (1 << (i - 16)); // Calculate conversion coefficients io_AoRangeToCoef( &cp->chanlist[i]); } } if ( cp->chanlist[18].cop && cp->chanlist[18].sop && cp->chanlist[18].ChanClass == pwr_cClass_ChanIi) local->portC_hasIi = 1; if ( local->portC_hasDi || local->portC_hasDo) { op->Status = USBIO_ConfigDIO( &local->USB_Handle, 3, local->portC_diMask); if ( op->Status) errh_Error( "IO Init Card '%s', Status %d", cp->Name, op->Status); } if ( local->portC_hasAo) { op->Status = USBIO_ConfigAO( &local->USB_Handle, local->portC_aoMask >> 3); if ( op->Status) errh_Error( "IO Init Card '%s', Status %d", cp->Name, op->Status); }
static pwr_tStatus IoCardWrite( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp) { io_sLocalAoDevice *local = (io_sLocalAoDevice *)cp->Local; pwr_sClass_OneWire_AoDevice *op = (pwr_sClass_OneWire_AoDevice *)cp->op; char str[80]; pwr_tUInt32 error_count = op->Super.ErrorCount; int num; if ( op->ScanInterval > 1) { if ( local->interval_cnt != 0) { local->interval_cnt++; if ( local->interval_cnt >= op->ScanInterval) local->interval_cnt = 0; return IO__SUCCESS; } local->interval_cnt++; } if ( cp->chanlist[0].cop && cp->chanlist[0].sop) { io_sChannel *chanp = &cp->chanlist[0]; pwr_sClass_ChanAo *cop = (pwr_sClass_ChanAo *)chanp->cop; pwr_sClass_Ao *sop = (pwr_sClass_Ao *)chanp->sop; if ( cop->CalculateNewCoef) // Request to calculate new coefficients io_AoRangeToCoef( chanp); switch ( op->ChAo.Representation) { case pwr_eDataRepEnum_Float32: case pwr_eDataRepEnum_Float64: { pwr_tFloat32 fvalue; fvalue = *(pwr_tFloat32 *)cp->chanlist[0].vbp * cop->OutPolyCoef1 + cop->OutPolyCoef0; if ( fvalue > cop->ActValRangeHigh) fvalue = cop->ActValRangeHigh; else if ( fvalue < cop->ActValRangeLow) fvalue = cop->ActValRangeLow; if ( fvalue > 0) sop->RawValue = fvalue + 0.5; else sop->RawValue = fvalue - 0.5; if ( strcmp( op->Format, "") == 0 ) num = snprintf( str, sizeof(str), "%f", fvalue); else num = snprintf( str, sizeof(str), op->Format, fvalue); if ( num == 0) op->Super.ErrorCount++; break; } default: { pwr_tInt32 ivalue; pwr_tFloat32 fvalue; fvalue = *(pwr_tFloat32 *)cp->chanlist[0].vbp * cop->OutPolyCoef1 + cop->OutPolyCoef0; if ( fvalue > cop->ActValRangeHigh) fvalue = cop->ActValRangeHigh; else if ( fvalue < cop->ActValRangeLow) fvalue = cop->ActValRangeLow; if ( fvalue > 0) ivalue = sop->RawValue = fvalue + 0.5; else ivalue = sop->RawValue = fvalue - 0.5; if ( strcmp( op->Format, "") == 0 ) num = snprintf( str, sizeof(str), "%d", ivalue); else num = snprintf( str, sizeof(str), op->Format, ivalue); if ( num == 0) op->Super.ErrorCount++; } } if ( num) { fprintf( local->value_fp, "%s", str); fflush( local->value_fp); rewind( local->value_fp); } } if ( op->Super.ErrorCount >= op->Super.ErrorSoftLimit && error_count < op->Super.ErrorSoftLimit) { errh_Warning( "IO Card ErrorSoftLimit reached, '%s'", cp->Name); } if ( op->Super.ErrorCount >= op->Super.ErrorHardLimit) { errh_Error( "IO Card ErrorHardLimit reached '%s', IO stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } return IO__SUCCESS; }
static pwr_tStatus IoRackInit ( io_tCtx ctx, io_sAgent *ap, io_sRack *rp ) { io_sCardLocal *local_card; io_sCard *cardp; short input_counter; short output_counter; pwr_sClass_Pb_DP_Slave *op; pwr_sClass_Pb_Di *dip; pwr_sClass_Pb_Do *dop; pwr_sClass_Pb_Ai *aip; pwr_sClass_Pb_Ao *aop; pwr_sClass_Pb_Ii *iip; pwr_sClass_Pb_Io *iop; pwr_sClass_Pb_Module *mp; char name[196]; pwr_tStatus sts; pwr_tCid cid; io_sChannel *chanp; int i, latent_input_count, latent_output_count; pwr_tInt32 chan_size; pwr_sClass_ChanDi *chan_di; pwr_sClass_ChanDo *chan_do; pwr_sClass_ChanAi *chan_ai; pwr_sClass_ChanAit *chan_ait; pwr_sClass_ChanIi *chan_ii; pwr_sClass_ChanAo *chan_ao; pwr_sClass_ChanIo *chan_io; sts = gdh_ObjidToName(rp->Objid, (char *) &name, sizeof(name), cdh_mNName); errh_Info( "Init of Profibus DP Slave and Modules %s", name); op = (pwr_sClass_Pb_DP_Slave *) rp->op; // Do configuration check and initialize modules. cardp = rp->cardlist; input_counter = 0; output_counter = 0; op->NumberModules = 0; latent_input_count = 0; latent_output_count = 0; while(cardp) { local_card = calloc(1, sizeof(*local_card)); cardp->Local = local_card; local_card->input_area = (void *) &(op->Inputs); local_card->output_area = (void *) &(op->Outputs); /* From v4.1.3 we can have subclasses, find the super class */ cid = cardp->Class; while ( ODD( gdh_GetSuperClass( cid, &cid, cardp->Objid))) ; switch (cid) { /* Old style configuring with Pb_xx objects. Still here for combatibility reasons. New systems (from v4.1.3) should be build with Pb_Module objects or subclasses */ case pwr_cClass_Pb_Di: dip = (pwr_sClass_Pb_Di *) cardp->op; dip->OffsetInputs = input_counter; dip->BytesOfInput = dip->NumberOfChannels / 8; input_counter += dip->BytesOfInput; dip->Status = PB_MODULE_STATE_OPERATE; break; case pwr_cClass_Pb_Do: dop = (pwr_sClass_Pb_Do *) cardp->op; dop->OffsetOutputs = output_counter; dop->BytesOfOutput = dop->NumberOfChannels / 8; output_counter += dop->BytesOfOutput; dop->Status = PB_MODULE_STATE_OPERATE; break; case pwr_cClass_Pb_Ai: aip = (pwr_sClass_Pb_Ai *) cardp->op; aip->OffsetInputs = input_counter; aip->BytesOfInput = aip->NumberOfChannels * aip->BytesPerChannel; input_counter += aip->BytesOfInput; aip->Status = PB_MODULE_STATE_OPERATE; break; case pwr_cClass_Pb_Ao: aop = (pwr_sClass_Pb_Ao *) cardp->op; aop->OffsetOutputs = output_counter; aop->BytesOfOutput = aop->NumberOfChannels * aop->BytesPerChannel; output_counter += aop->BytesOfOutput; aop->Status = PB_MODULE_STATE_OPERATE; break; case pwr_cClass_Pb_Ii: iip = (pwr_sClass_Pb_Ii *) cardp->op; iip->OffsetInputs = input_counter; iip->BytesOfInput = iip->NumberOfChannels * iip->BytesPerChannel; input_counter += iip->BytesOfInput; iip->Status = PB_MODULE_STATE_OPERATE; break; case pwr_cClass_Pb_Io: iop = (pwr_sClass_Pb_Io *) cardp->op; iop->OffsetOutputs = output_counter; iop->BytesOfOutput = iop->NumberOfChannels * iop->BytesPerChannel; output_counter += iop->BytesOfOutput; iop->Status = PB_MODULE_STATE_OPERATE; break; /* New style configuring (from v4.1.3) with Pb_Module objects or subclass. Loop all channels in the module and set channel size and offset. */ case pwr_cClass_Pb_Module: mp = (pwr_sClass_Pb_Module *) cardp->op; mp->Status = PB__INITFAIL; cardp->offset = 0; for (i=0; i<cardp->ChanListSize; i++) { chanp = &cardp->chanlist[i]; if ( is_diag( &chanp->ChanAref)) { chanp->udata |= PB_UDATA_DIAG; switch (chanp->ChanClass) { case pwr_cClass_ChanIi: chanp->offset = ((pwr_sClass_ChanIi *)chanp->cop)->Number; chanp->size = GetChanSize( ((pwr_sClass_ChanIi *)chanp->cop)->Representation); break; default: errh_Error( "Diagnostic channel class, card %s", cardp->Name); } continue; } if (chanp->ChanClass != pwr_cClass_ChanDi) { input_counter += latent_input_count; latent_input_count = 0; } if (chanp->ChanClass != pwr_cClass_ChanDo) { output_counter += latent_output_count; latent_output_count = 0; } switch (chanp->ChanClass) { case pwr_cClass_ChanDi: chan_di = (pwr_sClass_ChanDi *) chanp->cop; if (chan_di->Number == 0) { input_counter += latent_input_count; latent_input_count = 0; } chanp->offset = input_counter; chanp->mask = 1<<chan_di->Number; if (chan_di->Representation == pwr_eDataRepEnum_Bit16 && op->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) chanp->mask = swap16(chanp->mask); if (chan_di->Representation == pwr_eDataRepEnum_Bit32 && op->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) chanp->mask = swap32((unsigned short) chanp->mask); if (chan_di->Number == 0) latent_input_count = GetChanSize(chan_di->Representation); // printf("Di channel found in %s, Number %d, Offset %d\n", cardp->Name, chan_di->Number, chanp->offset); break; case pwr_cClass_ChanAi: chan_ai = (pwr_sClass_ChanAi *) chanp->cop; chanp->offset = input_counter; chan_size = GetChanSize(chan_ai->Representation); chanp->size = chan_size; chanp->mask = 0; input_counter += chan_size; io_AiRangeToCoef(chanp); // printf("Ai channel found in %s, Number %d, Offset %d\n", cardp->Name, chan_ai->Number, chanp->offset); break; case pwr_cClass_ChanAit: chan_ait = (pwr_sClass_ChanAit *) chanp->cop; chanp->offset = input_counter; chan_size = GetChanSize(chan_ait->Representation); chanp->size = chan_size; chanp->mask = 0; input_counter += chan_size; io_AiRangeToCoef(chanp); break; case pwr_cClass_ChanIi: chan_ii = (pwr_sClass_ChanIi *) chanp->cop; chanp->offset = input_counter; chan_size = GetChanSize(chan_ii->Representation); chanp->size = chan_size; chanp->mask = 0; input_counter += chan_size; // printf("Ii channel found in %s, Number %d, Offset %d\n", cardp->Name, chan_ii->Number, chanp->offset); break; case pwr_cClass_ChanDo: chan_do = (pwr_sClass_ChanDo *) chanp->cop; if (chan_do->Number == 0) { output_counter += latent_output_count; latent_output_count = 0; } chanp->offset = output_counter; chan_size = GetChanSize(chan_do->Representation); chanp->mask = 1<<chan_do->Number; if (chan_do->Representation == pwr_eDataRepEnum_Bit16 && op->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) chanp->mask = swap16(chanp->mask); if (chan_do->Representation == pwr_eDataRepEnum_Bit32 && op->ByteOrdering == pwr_eByteOrderingEnum_BigEndian) chanp->mask = swap32((unsigned short) chanp->mask); if (chan_do->Number == 0) latent_output_count = GetChanSize(chan_do->Representation); // printf("Do channel found in %s, Number %d, Offset %d\n", cardp->Name, chan_do->Number, chanp->offset); break; case pwr_cClass_ChanAo: chan_ao = (pwr_sClass_ChanAo *) chanp->cop; chanp->offset = output_counter; chan_size = GetChanSize(chan_ao->Representation); chanp->size = chan_size; chanp->mask = 0; output_counter += chan_size; io_AoRangeToCoef(chanp); // printf("Ao channel found in %s, Number %d, Offset %d\n", cardp->Name, chan_ao->Number, chanp->offset); break; case pwr_cClass_ChanIo: chan_io = (pwr_sClass_ChanIo *) chanp->cop; chanp->offset = output_counter; chan_size = GetChanSize(chan_io->Representation); chanp->size = chan_size; chanp->mask = 0; output_counter += chan_size; // printf("Io channel found in %s, Number %d, Offset %d\n", cardp->Name, chan_io->Number, chanp->offset); break; } } mp->Status = PB__NOCONN; break; } op->NumberModules++; cardp = cardp->next; } return IO__SUCCESS; }
static pwr_tStatus IoCardInit( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp) { ssize_t devnum; libusb_device **list; libusb_device *device = 0; int found = 0; int i; io_sLocalUSB_Agent *local_agent = (io_sLocalUSB_Agent *)ap->Local; io_sLocal_K8055 *local; pwr_sClass_Velleman_K8055_Board *op = (pwr_sClass_Velleman_K8055_Board *)cp->op; int sts; if ( !local_agent->libusb_ctx) return IO__INITFAIL; devnum = libusb_get_device_list( local_agent->libusb_ctx, &list); if ( devnum > 0) { for ( i = 0; i < devnum; i++) { struct libusb_device_descriptor desc; if ( libusb_get_device_descriptor( list[i], &desc) != 0) continue; if ( desc.idVendor == 0x10cf && desc.idProduct == 0x5500 + op->Super.Address) { device = list[i]; found = 1; break; } } } if ( !found) { errh_Error( "Init Velleman K8055, device not found '%s'", cp->Name); op->Status = IO__NODEVICE; ((pwr_sClass_Velleman_K8055 *)rp->op)->Status = op->Status; return IO__INITFAIL; } local = (io_sLocal_K8055 *) calloc( 1, sizeof(io_sLocal_K8055)); cp->Local = local; sts = libusb_open( device, &local->libusb_device); if ( sts != 0) { if ( sts == io_cLibDummy) op->Status = IO__DUMMYBUILD; else op->Status = IO__INITFAIL; ((pwr_sClass_Velleman_K8055 *)rp->op)->Status = op->Status; local->libusb_device = 0; return op->Status; } if ( libusb_kernel_driver_active( local->libusb_device, 0) != 0) libusb_detach_kernel_driver( local->libusb_device, 0); sts = libusb_claim_interface( local->libusb_device, 0); if ( sts < 0) { errh_Error( "K8055 Claim interface failed, sts %d, '%s'", sts, ap->Name); op->Status = IO__INITFAIL; ((pwr_sClass_Velleman_K8055 *)rp->op)->Status = op->Status; return IO__INITFAIL; } for ( i = 0; i < 2; i++) { if ( cp->chanlist[i].sop) io_AiRangeToCoef( &cp->chanlist[i]); } for ( i = 0; i < 2; i++) { if ( cp->chanlist[i+7].sop) io_AoRangeToCoef( &cp->chanlist[i+7]); } errh_Info( "Init of Velleman K8055 '%s'", cp->Name); op->Status = IO__SUCCESS; // Rack has no methods, set status if ( ((pwr_sClass_Velleman_K8055 *)rp->op)->Status == 0) ((pwr_sClass_Velleman_K8055 *)rp->op)->Status = op->Status; return IO__SUCCESS; }
static pwr_tStatus IoCardWrite( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp) { io_sLocal_K8055 *local = (io_sLocal_K8055 *)cp->Local; pwr_sClass_Velleman_K8055_Board *op = (pwr_sClass_Velleman_K8055_Board *)cp->op; unsigned char data[9]; char endpoint = 0x1; int size = 8; int tsize; unsigned char m; int i; int sts; pwr_tUInt32 error_count = op->Super.ErrorCount; memset( data, 0, sizeof(data)); data[0] = 0x5; // Handle Do m = 1; unsigned char do_value = 0; for ( i = 0; i < 8; i++) { if ( cp->chanlist[i+9].sop) { if ( *(pwr_tBoolean *)cp->chanlist[i+9].vbp) do_value |= m; } m = m << 1; } data[1] = do_value; // Handle Ao for ( i = 0; i < 2; i++) { if ( cp->chanlist[i+7].sop) { io_sChannel *chanp = &cp->chanlist[i+7]; pwr_sClass_ChanAo *cop = (pwr_sClass_ChanAo *)chanp->cop; if ( cop->CalculateNewCoef) // Request to calculate new coefficients io_AoRangeToCoef( chanp); float fvalue = *(pwr_tFloat32 *)chanp->vbp * cop->OutPolyCoef1 + cop->OutPolyCoef0; int ivalue = (int)fvalue; if ( ivalue < 0) ivalue = 0; else if (ivalue > 255) ivalue = 255; data[i+2] = ivalue; } } sts = libusb_interrupt_transfer( local->libusb_device, endpoint, data, size, &tsize, 100); if ( sts != 0 || tsize != size) { op->Super.ErrorCount++; if ( sts != 0 && sts != last_usblib_sts) { errh_Error( "K8055 libusb transfer error %d", sts); last_usblib_sts = sts; } return IO__SUCCESS; } if ( op->Super.ErrorCount >= op->Super.ErrorSoftLimit && error_count < op->Super.ErrorSoftLimit) { errh_Warning( "IO Card ErrorSoftLimit reached, '%s'", cp->Name); } if ( op->Super.ErrorCount >= op->Super.ErrorHardLimit) { errh_Error( "IO Card ErrorHardLimit reached '%s', IO stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } return IO__SUCCESS; }