高通平台开发系列讲解(USB篇)port_bridge转发应用分析
【摘要】
文章目录
一、图解port_bridge作用二、port_bridge入口分析三、usb_to_modem_bridge线程四、/dev/at_mdm0处理AT指令
沉淀、分享、成长...
沉淀、分享、成长,让自己和他人都能有所收获!😄
📢本篇章主要介绍高通平台USB
数据转发给modem
流程。
一、图解port_bridge作用
port_bridge
的功能是将从USB
接受到的数据转发至SMD
,该阶段在linux debug
口上进行排查,通过分析port_bridge
进程的状态及执行log
,定位问题发生位置。
二、port_bridge入口分析
目录:apps_proc/data/port-bridge/port_bridge.c
int main()
{
pthread_t mdm_thread, usb_thread;
thread_info_t mdm_info, usb_info;
/* MDM -> USB info object */
mdm_info.from_fd = &mdm_fd;
mdm_info.to_fd = &usb_fd;
mdm_info.to_file_path = targetinfo.usb_chardev;
mdm_info.from_file_path = targetinfo.mdm_chardev;
mdm_info.to_mutex = &usb_mutex;
mdm_info.from_mutex = &mdm_mutex;
/* USB -> MDM info object */
usb_info.from_fd = &usb_fd;
usb_info.to_fd = &mdm_fd;
usb_info.from_file_path = targetinfo.usb_chardev;
usb_info.to_file_path = targetinfo.mdm_chardev;
usb_info.to_mutex = &mdm_mutex;
usb_info.from_mutex = &usb_mutex;
pthread_create(&mdm_thread, NULL, targetinfo.mdm_handler, &mdm_info);
pthread_create(&usb_thread, NULL, usb_to_modem_bridge, &usb_info);
pthread_join(mdm_thread, NULL);
pthread_join(usb_thread, NULL);
}
三、usb_to_modem_bridge线程
USB -> MDM
这里操作的 glink_pkt
void* usb_to_modem_bridge(void* thread_info)
{
thread_info_t tinfo = *((thread_info_t*)thread_info);
while (1)
{
/* ####### OPEN THE USB FILE ####### */
if (*tinfo.from_fd < 0)
{
temp_fd = open(tinfo.from_file_path, O_RDWR); /* Custom blocking open */
}
while (glink_rx_intent_count < GLINK_RX_INTENT_MIN)
{
unsigned int rx_packet_max_size = MAX_MSG_SIZE;
LOGI("Queuing RX Intent for '%s'\n", tinfo.from_file_path);
PB_PTHREAD_MUTEX_LOCK(tinfo.from_mutex, tinfo.from_file_path);
ret = ioctl(*tinfo.from_fd, GLINK_PKT_IOCTL_QUEUE_RX_INTENT, &rx_packet_max_size);
PB_PTHREAD_MUTEX_UNLOCK(tinfo.from_mutex, tinfo.from_file_path);
if (ret)
{
LOGE("Error queuing RX intent=%d\n", ret);
exit(1);
}
glink_rx_intent_count++;
}
// At this point it's open, so poll for anything we need to do
pollinfo.revents = 0;
LOGI("Attempting to poll '%s'...\n", tinfo.from_file_path);
ret = poll(&pollinfo, 1, -1); // -1 timeout specifies infinite block (default linux behavior)
LOGR(ret, "poll on '%s' returned %i\n", tinfo.from_file_path, ret);
}
四、/dev/at_mdm0处理AT指令
前面分析到port_bridge
进程会将从PC
发过来的数据写入到/dev/at_mdm0
中,那么这个过程又是怎样的呢?/dev/at_mdm0
驱动代码位于drivers/soc/qcom/glink_pkt.c
,写入的时候最终会调用glink_pkt_write
, glink_pkt_write
的流程如下:
ssize_t glink_pkt_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct glink_pkt_device *gpdev = file->private_data;
void *kbuf;
int ret;
gpdev = file->private_data;
if (!gpdev || refcount_read(&gpdev->refcount) == 1) {
GLINK_PKT_ERR("invalid device handle\n");
return -EINVAL;
}
GLINK_PKT_INFO("begin to %s buffer_size %zu\n", gpdev->ch_name, count);
kbuf = memdup_user(buf, count);
if (IS_ERR(kbuf))
return PTR_ERR(kbuf);
if (mutex_lock_interruptible(&gpdev->lock)) {
ret = -ERESTARTSYS;
goto free_kbuf;
}
if (!completion_done(&gpdev->ch_open) || !gpdev->rpdev) {
GLINK_PKT_ERR("%s channel in reset\n", gpdev->ch_name);
ret = -ENETRESET;
goto unlock_ch;
}
if (file->f_flags & O_NONBLOCK)
ret = rpmsg_trysend(gpdev->rpdev->ept, kbuf, count);
else
ret = rpmsg_send(gpdev->rpdev->ept, kbuf, count);
unlock_ch:
mutex_unlock(&gpdev->lock);
free_kbuf:
kfree(kbuf);
GLINK_PKT_INFO("finish to %s ret %d\n", gpdev->ch_name, ret);
return ret < 0 ? ret : count;
}
文章来源: xuesong.blog.csdn.net,作者:内核笔记,版权归原作者所有,如需转载,请联系作者。
原文链接:xuesong.blog.csdn.net/article/details/124892210
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)