📄 pcan_fops_rt.c
字号:
// push a new transmission trough ioctl() only if interrupt triggered push was stalled mb(); if (atomic_read(&dev->DataSendReady)) { atomic_set(&dev->DataSendReady, 0); mb(); rtdm_lock_get_irqsave(&ctx->sja_lock, lockctx); err = dev->device_write(dev,ctx); rtdm_lock_put_irqrestore(&ctx->sja_lock, lockctx); if (err) atomic_set(&dev->DataSendReady, 1); } else { // DPRINTK(KERN_DEBUG "%s: pushed %d items into Fifo\n", DEVICE_NAME, dev->writeFifo.nStored); } } fail: return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_GET_EXT_STATUS int pcan_ioctl_extended_status_rt(rtdm_user_info_t *user_info, struct pcanctx_rt *ctx, TPEXTENDEDSTATUS *status){ int err = 0; struct pcandev *dev; TPEXTENDEDSTATUS local; DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(PCAN_GET_EXT_STATUS)\n", DEVICE_NAME); dev = ctx->dev; local = pcan_ioctl_extended_status_common(dev); if (copy_to_user_rt(user_info, status, &local, sizeof(local))) { err = -EFAULT; goto fail; } dev->wCANStatus = 0; dev->nLastError = 0; fail: return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_GET_STATUSint pcan_ioctl_status_rt(rtdm_user_info_t *user_info, struct pcanctx_rt *ctx, TPSTATUS *status){ int err = 0; struct pcandev *dev; TPSTATUS local; DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(PCAN_GET_STATUS)\n", DEVICE_NAME); dev = ctx->dev; local = pcan_ioctl_status_common(dev); if (copy_to_user_rt(user_info, status, &local, sizeof(local))) { err = -EFAULT; goto fail; } dev->wCANStatus = 0; dev->nLastError = 0; fail: return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_DIAG int pcan_ioctl_diag_rt(rtdm_user_info_t *user_info, struct pcanctx_rt *ctx, TPDIAG *diag){ int err = 0; struct pcandev *dev; TPDIAG local; DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(PCAN_DIAG)\n", DEVICE_NAME); dev = ctx->dev; local = pcan_ioctl_diag_common(dev); if (copy_to_user_rt(user_info, diag, &local, sizeof(local))) err = -EFAULT; return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_INITint pcan_ioctl_init_rt(rtdm_user_info_t *user_info, struct pcanctx_rt *ctx, TPCANInit *Init){ int err = 0; TPCANInit local; struct pcandev *dev; rtdm_lockctx_t lockctx; DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(PCAN_INIT)\n", DEVICE_NAME); dev = ctx->dev; if (copy_from_user_rt(user_info, &local, Init, sizeof(local))) { err = -EFAULT; goto fail; } // flush fifo contents rtdm_lock_get_irqsave(&ctx->out_lock, lockctx); err = pcan_fifo_reset(&dev->writeFifo); rtdm_lock_put_irqrestore(&ctx->out_lock, lockctx); if (err) goto fail; rtdm_lock_get_irqsave(&ctx->in_lock, lockctx); err = pcan_fifo_reset(&dev->readFifo); rtdm_lock_put_irqrestore(&ctx->in_lock, lockctx); if (err) goto fail; wait_until_fifo_empty(dev, MAX_WAIT_UNTIL_CLOSE, ctx); // release the device dev->device_release(dev); // init again err = dev->device_open(dev, local.wBTR0BTR1, local.ucCANMsgType, local.ucListenOnly); if (!err) { dev->wBTR0BTR1 = local.wBTR0BTR1; dev->ucCANMsgType = local.ucCANMsgType; dev->ucListenOnly = local.ucListenOnly; } fail: return err;}//----------------------------------------------------------------------------// get BTR0BTR1 init valuesint pcan_ioctl_BTR0BTR1_rt(rtdm_user_info_t *user_info, struct pcanctx_rt *ctx, TPBTR0BTR1 *BTR0BTR1){ int err = 0; TPBTR0BTR1 local; DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(PCAN_BTR0BTR1)\n", DEVICE_NAME); if (copy_from_user_rt(user_info, &local, BTR0BTR1, sizeof(local))) { err = -EFAULT; goto fail; } // this does not influence hardware settings, only BTR0BTR1 values are calculated local.wBTR0BTR1 = sja1000_bitrate(local.dwBitRate); if (!local.wBTR0BTR1) { err = -EFAULT; goto fail; } if (copy_to_user_rt(user_info, BTR0BTR1, &local, sizeof(*BTR0BTR1))) err = -EFAULT; fail: return err;}//----------------------------------------------------------------------------// add a message filter_element into the filter chain or delete all filter_elementsint pcan_ioctl_msg_filter_rt(rtdm_user_info_t *user_info, struct pcanctx_rt *ctx, TPMSGFILTER *filter){ TPMSGFILTER local_filter; struct pcandev *dev; DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(PCAN_MSG_FILTER)\n", DEVICE_NAME); dev = ctx->dev; // filter == NULL -> delete the filter_elements in the chain if (!filter) { pcan_delete_filter_all(dev->filter); return 0; } if (copy_from_user_rt(user_info, &local_filter, filter, sizeof(local_filter))) return -EFAULT; return pcan_add_filter(dev->filter, local_filter.FromID, local_filter.ToID, local_filter.MSGTYPE);}//----------------------------------------------------------------------------// is called at user ioctl() callint pcan_ioctl_rt(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, IOCTL_REQUEST_TYPE request, void *arg){ int err; struct pcanctx_rt *ctx; struct pcandev *dev; ctx = (struct pcanctx_rt *)context->dev_private; dev = ctx->dev; // if the device is plugged out if (!dev->ucPhysicallyInstalled) return -ENODEV; switch(request) { case PCAN_READ_MSG: err = pcan_ioctl_read_rt(user_info, ctx, (TPCANRdMsg *)arg); // support blocking and nonblocking IO break; case PCAN_WRITE_MSG: err = pcan_ioctl_write_rt(user_info, ctx, (TPCANMsg *)arg); // support blocking and nonblocking IO break; case PCAN_GET_EXT_STATUS: err = pcan_ioctl_extended_status_rt(user_info, ctx, (TPEXTENDEDSTATUS *)arg); break; case PCAN_GET_STATUS: err = pcan_ioctl_status_rt(user_info, ctx, (TPSTATUS *)arg); break; case PCAN_DIAG: err = pcan_ioctl_diag_rt(user_info, ctx, (TPDIAG *)arg); break; case PCAN_INIT: err = pcan_ioctl_init_rt(user_info, ctx, (TPCANInit *)arg); break; case PCAN_BTR0BTR1: err = pcan_ioctl_BTR0BTR1_rt(user_info, ctx, (TPBTR0BTR1 *)arg); break; case PCAN_MSG_FILTER: err = pcan_ioctl_msg_filter_rt(user_info, ctx, (TPMSGFILTER *)arg); break; default: DPRINTK(KERN_DEBUG "%s: pcan_ioctl_rt(%d)\n", DEVICE_NAME, request); err = -ENOTTY; break; } DPRINTK(KERN_DEBUG "%s: pcan_ioctl()_rt = %d\n", DEVICE_NAME, err); return err;}//****************************************************************************// GLOBALS//----------------------------------------------------------------------------// this structure is used in init_module(void)struct rtdm_device pcandev_rt ={ struct_version: RTDM_DEVICE_STRUCT_VER, device_flags: RTDM_NAMED_DEVICE, context_size: sizeof(struct pcanctx_rt), device_name: "", open_rt: NULL, open_nrt: pcan_open_rt, ops: { close_rt: NULL, close_nrt: pcan_close_rt, ioctl_rt: pcan_ioctl_rt, ioctl_nrt: pcan_ioctl_rt, read_rt: NULL, read_nrt: NULL, write_rt: NULL, write_nrt: NULL, recvmsg_rt: NULL, recvmsg_nrt: NULL, sendmsg_rt: NULL, sendmsg_nrt: NULL, }, device_class: RTDM_CLASS_CAN, driver_name: "pcan_driver", provider_name: "PEAK System-Technik GmbH", proc_name: pcandev_rt.device_name,};// end of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -