📄 pcan_usb_kernel.c
字号:
return pcan_hw_setcontrol_urb(dev, 1, 2, param0, param1, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy);}int pcan_hw_SetCANOn(struct pcandev *dev){ u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_SetCANOn()\n", DEVICE_NAME); return pcan_hw_setcontrol_urb(dev, 3, 2, 1, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy);}int pcan_hw_SetCANOff(struct pcandev *dev){ int err; u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_SetCANOff()\n", DEVICE_NAME); err = pcan_hw_setcontrol_urb(dev, 3, 2, 0, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy); return err;}static int pcan_hw_SetCANSilentOn(struct pcandev *dev){ u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_SetCANSilentOn()\n", DEVICE_NAME); return pcan_hw_setcontrol_urb(dev, 3, 3, 1, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy);}static int pcan_hw_SetCANSilentOff(struct pcandev *dev){ u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_SetCANSilentOff()\n", DEVICE_NAME); return pcan_hw_setcontrol_urb(dev, 3, 3, 0, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy);}int pcan_hw_getBTR0BTR1(struct pcandev *dev, u16 *pwBTR0BTR1){ int err; u8 dummy = 0; u8 param0 = 0; u8 param1 = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_getBTR0BTR1()\n", DEVICE_NAME); err = pcan_hw_getcontrol_urb(dev, 1, 1, ¶m0, ¶m1, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy); *pwBTR0BTR1 = param1; *pwBTR0BTR1 <<= 8; *pwBTR0BTR1 |= param0; DPRINTK(KERN_DEBUG "%s: BTR0BTR1 = 0x%04x\n", DEVICE_NAME, *pwBTR0BTR1); return err;}int pcan_hw_getQuartz(struct pcandev *dev, u32 *pdwQuartzHz){ int err = 0; u8 dummy = 0; u8 param0 = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_getQuartz()\n", DEVICE_NAME); err = pcan_hw_getcontrol_urb(dev, 2, 1, ¶m0, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy); *pdwQuartzHz = param0; *pdwQuartzHz *= 1000000L; DPRINTK(KERN_DEBUG "%s: Frequenz = %u\n", DEVICE_NAME, *pdwQuartzHz); return err;}int pcan_hw_getAnything(struct pcandev *dev, u8 ucFunction, u8 ucNumber){ int err = 0; u8 dummy[8]; int i; DPRINTK(KERN_DEBUG "%s: pcan_hw_getAnything()\n", DEVICE_NAME); for (i = 0; i < 7; i++) dummy[i] = 0; err = pcan_hw_getcontrol_urb(dev, ucFunction, ucNumber, &dummy[0], &dummy[1], &dummy[2], &dummy[3], &dummy[4], &dummy[5], &dummy[6], &dummy[7]); DPRINTK(KERN_DEBUG "%s: Fun/Num:%d/%d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", DEVICE_NAME, ucFunction, ucNumber, dummy[0], dummy[1], dummy[2], dummy[3], dummy[4], dummy[5], dummy[6], dummy[7]); return err;}int pcan_hw_getDeviceNr(struct pcandev *dev, u8 *pucDeviceNr){ int err; u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_getDeviceNr()\n", DEVICE_NAME); err = pcan_hw_getcontrol_urb(dev, 4, 1, pucDeviceNr, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy); DPRINTK(KERN_DEBUG "%s: DeviceNr = 0x%02x\n", DEVICE_NAME, *pucDeviceNr); return err;}int pcan_hw_SetExtVCCOn(struct pcandev *dev){ u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_SetExtVCCOn()\n", DEVICE_NAME); return pcan_hw_setcontrol_urb(dev, 0xA, 2, 1, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy);}int pcan_hw_SetDeviceNr(struct pcandev *dev, u8 ucDeviceNr){ u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_SetDeviceNr()\n", DEVICE_NAME); return pcan_hw_setcontrol_urb(dev, 4, 2, ucDeviceNr, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy);}int pcan_hw_SetSNR(struct pcandev *dev, u32 dwSNR){ u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_SetSNR()\n", DEVICE_NAME); return pcan_hw_setcontrol_urb(dev, 6, 2, (u8)( dwSNR & 0xff), (u8)((dwSNR >> 8) & 0xff), (u8)((dwSNR >> 16) & 0xff), (u8)((dwSNR >> 24) & 0xff), dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy);}static int pcan_hw_SetExtVCCOff(struct pcandev *dev){ u8 dummy = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_SetExtVCCOff()\n", DEVICE_NAME); return pcan_hw_setcontrol_urb(dev, 0xA, 2, 0, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy, dummy);}int pcan_hw_getSNR(struct pcandev *dev, u32 *pdwSNR){ int err = 0; ULCONV SNR; u8 dummy; int i = 1; DPRINTK(KERN_DEBUG "%s: pcan_hw_getSNR()\n", DEVICE_NAME); memset(&SNR, 0, sizeof(SNR)); // sometimes the hardware won't provide the number - so try twice do err = pcan_hw_getcontrol_urb(dev, 6, 1, &SNR.uc[3], &SNR.uc[2], &SNR.uc[1], &SNR.uc[0], &dummy, &dummy, &dummy, &dummy); while ((i--) && (err == -2)); *pdwSNR = SNR.ul; DPRINTK(KERN_DEBUG "%s: SNR = 0x%08x\n", DEVICE_NAME, *pdwSNR); return err;}//****************************************************************************// init hardware partsint pcan_hw_Init(struct pcandev *dev, u16 btr0btr1, u8 bListenOnly){ int err = 0; DPRINTK(KERN_DEBUG "%s: pcan_hw_Init()\n", DEVICE_NAME); err = pcan_hw_setBTR0BTR1(dev, btr0btr1); if (err) goto fail; if (dev->port.usb.ucRevision > 3) { // set listen only if (bListenOnly) err = pcan_hw_SetCANSilentOn(dev); else err = pcan_hw_SetCANSilentOff(dev); if (err) goto fail; } else { // generate err if one tries to set bListenOnly if (bListenOnly) { err = -EINVAL; goto fail; } } // don't know how to handle - walk the save way err = pcan_hw_SetExtVCCOff(dev); // prepare for new start of timestamp calculation pcan_reset_timestamp(dev); fail: return err;}//****************************************************************************// takes USB-message frames out of ucMsgPtr, decodes and packs them into readFifoint pcan_hw_DecodeMessage(struct pcandev *dev, u8 *ucMsgPtr, int lCurrentLength){ int err = 0; int i, j; u8 ucMsgPrefix; u8 ucMsgLen; // number of frames in one USB packet u8 ucStatusLen = 0; // storage for the status/length entry leading each data frame u8 ucLen; // len in bytes of received (CAN) data UWCONV wTimeStamp; u8 *ucMsgStart = ucMsgPtr; // store start of buffer for overflow compare int rwakeup = 0; u8 *org = ucMsgPtr; u8 dataPacketCounter = 0; //DPRINTK(KERN_DEBUG "%s: pcan_hw_DecodeMessage(%p, %d)\n", DEVICE_NAME, ucMsgPtr, lCurrentLength); // sometimes is nothing to do if (!lCurrentLength) return err; // get prefix of message and step over ucMsgPrefix = *ucMsgPtr++; // get length of message and step over ucMsgLen = *ucMsgPtr++; for (i = 0; (i < ucMsgLen); i++) { ULCONV localID; struct timeval tv; ucStatusLen = *ucMsgPtr++; // TODO: take timestamp from PCAN-USB do_gettimeofday(&tv); // normal CAN message are always with timestamp if (!(ucStatusLen & STLN_INTERNAL_DATA)) { int nRtrFrame; struct can_frame frame; ucLen = ucStatusLen & STLN_DATA_LENGTH; if (ucLen > 8) ucLen = 8; frame.can_dlc = ucLen; nRtrFrame = ucStatusLen & STLN_RTR; if (nRtrFrame) frame.can_id = CAN_RTR_FLAG; // re-set to RTR value else frame.can_id = 0; // re-set to default value if (ucStatusLen & STLN_EXTENDED_ID) { frame.can_id |= CAN_EFF_FLAG; // modify if it was extended #if defined(__LITTLE_ENDIAN) localID.uc[0] = *ucMsgPtr++; localID.uc[1] = *ucMsgPtr++; localID.uc[2] = *ucMsgPtr++; localID.uc[3] = *ucMsgPtr++; #elif defined(__BIG_ENDIAN) localID.uc[3] = *ucMsgPtr++; localID.uc[2] = *ucMsgPtr++; localID.uc[1] = *ucMsgPtr++; localID.uc[0] = *ucMsgPtr++; #else #error "Please fix the endianness defines in <asm/byteorder.h>" #endif localID.ul >>= 3; } else { localID.ul = 0; #if defined(__LITTLE_ENDIAN) localID.uc[0] = *ucMsgPtr++; localID.uc[1] = *ucMsgPtr++; #elif defined(__BIG_ENDIAN) localID.uc[3] = *ucMsgPtr++; localID.uc[2] = *ucMsgPtr++; #else #error "Please fix the endianness defines in <asm/byteorder.h>" #endif localID.ul >>= 5; } frame.can_id |= localID.ul; // read timestamp, first timestamp in packet is 16 bit AND data, following timestamps are 8 bit in length if (!dataPacketCounter) { #if defined(__LITTLE_ENDIAN) wTimeStamp.uc[0] = *ucMsgPtr++; wTimeStamp.uc[1] = *ucMsgPtr++; #elif defined(__BIG_ENDIAN) wTimeStamp.uc[1] = *ucMsgPtr++; wTimeStamp.uc[0] = *ucMsgPtr++; #else #error "Please fix the endianness defines in <asm/byteorder.h>" #endif pcan_updateTimeStampFromWord(dev, wTimeStamp.uw, i); } else pcan_updateTimeStampFromByte(dev, *ucMsgPtr++); // read data j = 0; if (!nRtrFrame) { while (ucLen--) frame.data[j++] = *ucMsgPtr++; } // only for beauty, replace useless telegram content with zeros while (j < 8) frame.data[j++] = 0; if ((err = pcan_xxxdev_rx(dev, &frame, &tv)) < 0) // put into data sink goto fail; if (err > 0) // successfully enqueued into chardev FIFO rwakeup++; dataPacketCounter++; } // Status Daten else { u8 ucFunction; u8 ucNumber; u8 dummy; TPCANRdMsg msg; struct can_frame ef; /* error frame */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -