📄 capi.c
字号:
case CAPI_CONNECT_B3_IND: ncci = CAPIMSG_NCCI(skb->data); BT_DBG("CONNECT_B3_IND ncci 0x%02x", ncci); ctrl->new_ncci(ctrl, appl, ncci, 8); ctrl->handle_capimsg(ctrl, appl, skb); break; case CAPI_DISCONNECT_B3_IND: ncci = CAPIMSG_NCCI(skb->data); BT_DBG("DISCONNECT_B3_IND ncci 0x%02x", ncci); if (ncci == 0xffffffff) BT_ERR("DISCONNECT_B3_IND with ncci 0xffffffff"); ctrl->handle_capimsg(ctrl, appl, skb); ctrl->free_ncci(ctrl, appl, ncci); break; default: ctrl->handle_capimsg(ctrl, appl, skb); break; }}void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb){ struct cmtp_scb *scb = (void *) skb->cb; BT_DBG("session %p skb %p len %d", session, skb, skb->len); scb->id = -1; scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3); skb_queue_tail(&session->transmit, skb); cmtp_schedule(session);}static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data){ BT_DBG("ctrl %p data %p", ctrl, data); return -EIO;}static void cmtp_reset_ctr(struct capi_ctr *ctrl){ BT_DBG("ctrl %p", ctrl); ctrl->reseted(ctrl);}static void cmtp_remove_ctr(struct capi_ctr *ctrl){ struct cmtp_session *session = ctrl->driverdata; BT_DBG("ctrl %p", ctrl); ctrl->suspend_output(ctrl); atomic_inc(&session->terminate); cmtp_schedule(session);}static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp){ DECLARE_WAITQUEUE(wait, current); struct cmtp_session *session = ctrl->driverdata; struct cmtp_application *application; unsigned long timeo = CMTP_INTEROP_TIMEOUT; unsigned char buf[8]; int err = 0, nconn, want = rp->level3cnt; BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d", ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen); application = cmtp_application_add(session, appl); if (!application) { BT_ERR("Can't allocate memory for new application"); ctrl->appl_released(ctrl, appl); return; } if (want < 0) nconn = ctrl->profile.nbchannel * -want; else nconn = want; if (nconn == 0) nconn = ctrl->profile.nbchannel; capimsg_setu16(buf, 0, nconn); capimsg_setu16(buf, 2, rp->datablkcnt); capimsg_setu16(buf, 4, rp->datablklen); application->state = BT_CONFIG; application->msgnum = cmtp_msgnum_get(session); cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum, CAPI_FUNCTION_REGISTER, buf, 6); add_wait_queue(&session->wait, &wait); while (1) { set_current_state(TASK_INTERRUPTIBLE); if (!timeo) { err = -EAGAIN; break; } if (application->state == BT_CLOSED) { err = -application->err; break; } if (application->state == BT_CONNECTED) break; if (signal_pending(current)) { err = -EINTR; break; } timeo = schedule_timeout(timeo); } set_current_state(TASK_RUNNING); remove_wait_queue(&session->wait, &wait); if (err) { ctrl->appl_released(ctrl, appl); cmtp_application_del(session, application); return; } ctrl->appl_registered(ctrl, appl);}static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl){ DECLARE_WAITQUEUE(wait, current); struct cmtp_session *session = ctrl->driverdata; struct cmtp_application *application; unsigned long timeo = CMTP_INTEROP_TIMEOUT; BT_DBG("ctrl %p appl %d", ctrl, appl); application = cmtp_application_get(session, CMTP_APPLID, appl); if (!application) { BT_ERR("Can't find application"); return; } application->msgnum = cmtp_msgnum_get(session); cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum, CAPI_FUNCTION_RELEASE, NULL, 0); add_wait_queue(&session->wait, &wait); while (timeo) { set_current_state(TASK_INTERRUPTIBLE); if (application->state == BT_CLOSED) break; if (signal_pending(current)) break; timeo = schedule_timeout(timeo); } set_current_state(TASK_RUNNING); remove_wait_queue(&session->wait, &wait); cmtp_application_del(session, application); ctrl->appl_released(ctrl, appl);}static void cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb){ struct cmtp_session *session = ctrl->driverdata; struct cmtp_application *application; __u16 appl; __u32 contr; BT_DBG("ctrl %p skb %p", ctrl, skb); appl = CAPIMSG_APPID(skb->data); contr = CAPIMSG_CONTROL(skb->data); application = cmtp_application_get(session, CMTP_APPLID, appl); if ((!application) || (application->state != BT_CONNECTED)) { BT_ERR("Can't find application with id %d", appl); kfree_skb(skb); return; } CAPIMSG_SETAPPID(skb->data, application->mapping); if ((contr & 0x7f) == session->num) { contr = (contr & 0xffffff80) | 0x01; CAPIMSG_SETCONTROL(skb->data, contr); } cmtp_send_capimsg(session, skb);}static char *cmtp_procinfo(struct capi_ctr *ctrl){ return "CAPI Message Transport Protocol";}static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl){ struct cmtp_session *session = ctrl->driverdata; struct cmtp_application *app; struct list_head *p, *n; int len = 0; len += sprintf(page + len, "%s (Revision %s)\n\n", cmtp_procinfo(ctrl), REVISION); len += sprintf(page + len, "addr %s\n", session->name); len += sprintf(page + len, "ctrl %d\n", session->num); list_for_each_safe(p, n, &session->applications) { app = list_entry(p, struct cmtp_application, list); len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping); } if (off + count >= len) *eof = 1; if (len < off) return 0; *start = page + off; return ((count < len - off) ? count : len - off);}static struct capi_driver cmtp_driver = { name: "cmtp", revision: REVISION, load_firmware: cmtp_load_firmware, reset_ctr: cmtp_reset_ctr, remove_ctr: cmtp_remove_ctr, register_appl: cmtp_register_appl, release_appl: cmtp_release_appl, send_message: cmtp_send_message, procinfo: cmtp_procinfo, ctr_read_proc: cmtp_ctr_read_proc, driver_read_proc: 0, add_card: 0,};int cmtp_attach_device(struct cmtp_session *session){ DECLARE_WAITQUEUE(wait, current); unsigned long timeo = CMTP_INTEROP_TIMEOUT; unsigned char buf[4]; BT_DBG("session %p", session); capimsg_setu32(buf, 0, 0); cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM, CAPI_FUNCTION_GET_PROFILE, buf, 4); add_wait_queue(&session->wait, &wait); while (timeo) { set_current_state(TASK_INTERRUPTIBLE); if (session->ncontroller) break; if (signal_pending(current)) break; timeo = schedule_timeout(timeo); } set_current_state(TASK_RUNNING); remove_wait_queue(&session->wait, &wait); BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name); if (!timeo) return -ETIMEDOUT; if (!session->ncontroller) return -ENODEV; if (session->ncontroller > 1) BT_INFO("Setting up only CAPI controller 1"); if (!(session->ctrl = di->attach_ctr(&cmtp_driver, session->name, session))) { BT_ERR("Can't attach new controller"); return -EBUSY; } session->num = session->ctrl->cnr; BT_DBG("session %p ctrl %p num %d", session, session->ctrl, session->num); capimsg_setu32(buf, 0, 1); cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), CAPI_FUNCTION_GET_MANUFACTURER, buf, 4); cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), CAPI_FUNCTION_GET_VERSION, buf, 4); cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4); cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session), CAPI_FUNCTION_GET_PROFILE, buf, 4); return 0;}void cmtp_detach_device(struct cmtp_session *session){ struct capi_ctr *ctrl = session->ctrl; BT_DBG("session %p ctrl %p", session, ctrl); if (!ctrl) return; ctrl->reseted(ctrl); di->detach_ctr(ctrl);}int cmtp_init_capi(void){ if (!(di = attach_capi_driver(&cmtp_driver))) { BT_ERR("Can't attach CAPI driver"); return -EIO; } return 0;}void cmtp_cleanup_capi(void){ detach_capi_driver(&cmtp_driver);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -