「Linux如何重新枚举USB设备」 (linux 重新枚举u设备)

Linux如何重新枚举USB设备

USB(通用串行总线)设备在现代计算机中广泛使用。在Linux系统中,USB设备会自动识别并枚举,以便可以在系统中使用。但是,有时设备可能无法正常枚举或者需要重新枚举才能重新识别,例如USB驱动程序异常、硬件升级或更换等。在这种情况下,重新枚举USB设备是一个常见的解决方案。

重新枚举USB设备可以通过多种方式完成,包括使用系统命令、使用udev工具和重载USB内核模块。下面我们将详细介绍这些方法。

方法1:使用系统命令

您可以使用系统命令来重新枚举USB设备。请按以下步骤操作:

1.打开终端并输入以下命令:

sudo systemctl stop systemd-udevd.service

该命令将停止udev守护程序。

2.卸载所有挂载的USB存储设备,以防止数据损坏。使用以下命令弹出所有已挂载的USB存储驱动器:

sudo eject /dev/sdX

其中“X”是USB存储设备的字母。

3.使用以下命令卸载已连接但未挂载的USB存储设备:

sudo umount /dev/sdX

4.断开所有的USB设备连接。

5.重新插入USB设备,您的计算机应该能够重新枚举它们。

6.使用以下命令重启udev守护程序:

sudo systemctl start systemd-udevd.service

方法2:使用udev工具

udev工具可以帮助管理和控制Linux系统中的设备。使用该工具重新枚举USB设备,只需要使用以下命令:

sudo udevadm trigger

运行此命令将强制udev重新扫描您的系统设备,包括USB设备。udev将通过检查系统设备目录的变化来更新设备信息,因此当您重新插入USB设备时,udev会自动重新枚举它们。

方法3:重载USB内核模块

最后一种解决方案是通过重新加载USB内核模块来重新枚举USB设备。使用以下命令:

sudo rmmod u-storage

sudo modprobe u-storage

之一个命令将卸载USB存储内核模块,第二个命令将重新加载该模块。在重新加载USB内核模块后,您应该能够重新枚举USB设备。

结论

重新枚举USB设备是解决在Linux系统中使用USB设备问题的有效方法。您可以使用系统命令、udev工具和重新加载USB内核模块这三种方法中的任何一种。

不过,在执行这些方法之前,请务必备份您的数据并谨慎处理USB设备,以防止数据丢失或设备损坏。同时,如果您不确定该如何操作,请先咨询专业人士。

相关问题拓展阅读:

  • 怎么能将linux下自动分配的u0改为u1

怎么能将linux下自动分配的u0改为u1

你好,方法如下:

写一个USB的驱动程序最 基本的要做四件事:

驱动程序要支持的设备、注册USB驱动程序、探测和断开、提交和控制urb(USB请求块)

驱动程序支持的设备:有一个结构体struct u_device_id,这个结构体提供了一列不同类型的该驱动程序支持的USB设备,对于一个只控制一个特定的USB设备的驱动程序来说,struct u_device_id表被定义为:

/* 驱动程序支持的设备列表 */

static struct u_device_id skel_table = {

{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },

{ } /* 终止入口 */

};

MODULE_DEVICE_TABLE (u, skel_table);

对 于PC驱动程序,MODULE_DEVICE_TABLE是必需的,而且u必需为该宏的之一个值,而USB_SKEL_VENDOR_ID和 USB_SKEL_PRODUCT_ID就是这个特殊设备的制造商和产品的ID了,我们在程序中把定义的值改为我们这款USB的,如:

/* 定义制造商和产品的ID号 */

#define USB_SKEL_VENDOR_ID 0x1234

#define USB_SKEL_PRODUCT_ID 0x2345

这两个值可以通过命令lsu,当然你得先把USB设备先插到主机上了。或者查看厂商的USB设备的手册也能得到,在我机器上运行lsu是这样的结果:

Bus 004 Device 001: ID 0000:0000

Bus 003 Device 002: ID 1234:2345 Abc Corp.

Bus 002 Device 001: ID 0000:0000

Bus 001 Device 001: ID 0000:0000

得到这两个值后把它定义到程序李卜迅里就可以了。

注册USB驱动程序:所 有的USB驱动程序都必须创建的结构体是struct u_driver。这个结构体必须由USB驱动程序来填写,包括许多回调函数和变量,它们向USB核心代码描述USB驱动程序。创建一个有效的 struct u_driver结构体,只须要初始化五个字段就可以了,在框架程序中是这样的:

static struct u_driver skel_driver = {

.owner = THIS_MODULE,

.name =”skeleton”,

.probe = skel_probe,

.disconnect = skel_disconnect,

.id_table = skel_table,

};

探测和断开:当 一个设备被安装而USB核心认为该驱动程序应该处理时,探测函数被调用,探测函数检查传递给它的设备信息,确定驱动程序是否真的适合该设备。当驱动程序因 为某种原因不应该控制设备时,断开函数被调用,它可以做一些清理工作。探测回调函数中,USB驱动程序初始化任何可能用于控制USB设备的局部结构体,它 还把所需的任何设备相关信息保存到一个局部结构体弊仔中,

提交和控制urb:当驱动程序有数据要发送到USB设备时(大多数情况是在驱动程序的写函数中),要分配一个urb来把数据传输给设备:

/* 创建一个urb,并且给它分配一个缓存*/

urb = u_alloc_urb(0, GFP_KERNEL);

if (!urb) {

retval = -ENOMEM;

goto error;

}

当urb被成功分配后,还要创建一个DMA缓冲区来以高效的方式发送数据到设备,传递给驱动程序的数据要复制到这块缓冲中去:

buf = u_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);

if (!buf) {

retval = -ENOMEM;

goto error;

}

if (copy_from_user(buf, user_buffer, count)) {

retval = -EFAULT;

goto error;

}

当数据从用户空间正确复制到局部哪此缓冲区后,urb必须在可以被提交给USB核心之前被正确初始化:

/* 初始化urb */

u_fill_bulk_urb(urb, dev->udev,

u_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),

buf, count, skel_write_bulk_callback, dev);

urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

然后urb就可以被提交给USB核心以传输到设备了:

/* 把数据从批量OUT端口发出 */

retval = u_submit_urb(urb, GFP_KERNEL);

if (retval) {

err(“%s – failed submitting write urb, error %d”, __FUNCTION__, retval);

goto error;

}

当urb被成功传输到USB设备之后,urb回调函数将被USB核心调用,在我们的例子中,我们初始化urb,使它指向skel_write_bulk_callback函数,以下就是该函数:

static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)

{

struct u_skel *dev;

dev = (struct u_skel *)urb->context;

if (urb->status &&

!(urb->status == -ENOENT ||

urb->status == -ECONNRESET ||

urb->status == -ESHUTDOWN)) {

dbg(“%s – nonzero write bulk status received: %d”,

__FUNCTION__, urb->status);

}

/* 释放已分配的缓冲区 */

u_buffer_free(urb->dev, urb->transfer_buffer_length,

urb->transfer_buffer, urb->transfer_dma);

}

有时候USB驱动程序只是要发送或者接收一些简单的数据,驱动程序也可以不用urb来进行数据的传输,这是里涉及到两个简单的接口函数:u_bulk_msg和u_control_msg ,在这个USB框架程序里读操作就是这样的一个应用:

/* 进行阻塞的批量读以从设备获取数据 */

retval = u_bulk_msg(dev->udev,

u_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),

dev->bulk_in_buffer,

min(dev->bulk_in_size, count),

&count, HZ*10);

/*如果读成功,复制到用户空间 */

if (!retval) {

if (copy_to_user(buffer, dev->bulk_in_buffer, count))

retval = -EFAULT;

else

retval = count;

}

u_bulk_msg接口函数的定义如下:

int u_bulk_msg(struct u_device *u_dev,unsigned int pipe,

void *data,int len,int *actual_length,int timeout);

其参数为:

struct u_device *u_dev:指向批量消息所发送的目标USB设备指针。

unsigned int pipe:批量消息所发送目标USB设备的特定端点,此值是调用u_sndbulkpipe或者u_rcvbulkpipe来创建的。

void *data:如果是一个OUT端点,它是指向即将发送到设备的数据的指针。如果是IN端点,它是指向从设备读取的数据应该存放的位置的指针。

int len:data参数所指缓冲区的大小。

int *actual_length:指向保存实际传输字节数的位置的指针,至于是传输到设备还是从设备接收取决于端点的方向。

int timeout:以Jiffies为单位的等待的超时时间,如果该值为0,该函数一直等待消息的结束。

如果该接口函数调用成功,返回值为0,否则返回一个负的错误值。

u_control_msg接口函数定义如下:

int u_control_msg(struct u_device *dev,unsigned int pipe,__u8 request,__u8requesttype,__u16 value,__u16 index,void *data,__u16 size,int timeout)

除了允许驱动程序发送和接收USB控制消息之外,u_control_msg函数的运作和u_bulk_msg函数类似,其参数和u_bulk_msg的参数有几个重要区别:

struct u_device *dev:指向控制消息所发送的目标USB设备的指针。

unsigned int pipe:控制消息所发送的目标USB设备的特定端点,该值是调用u_sndctrlpipe或u_rcvctrlpipe来创建的。

__u8 request:控制消息的USB请求值。

__u8 requesttype:控制消息的USB请求类型值。

__u16 value:控制消息的USB消息值。

__u16 index:控制消息的USB消息索引值。

void *data:如果是一个OUT端点,它是指身即将发送到设备的数据的指针。如果是一个IN端点,它是指向从设备读取的数据应该存放的位置的指针。

__u16 size:data参数所指缓冲区的大小。

int timeout:以Jiffies为单位的应该等待的超时时间,如果为0,该函数将一直等待消息结束。

如果该接口函数调用成功,返回传输到设备或者从设备读取的字节数;如果不成功它返回一个负的错误值。

这两个接口函数都不能在一个中断上下文中或者持有自旋锁的情况下调用,同样,该函数也不能被任何其它函数取消,使用时要谨慎。

我们要给未知的USB设备写驱动程序,只需要把这个框架程序稍做修改就可以用了,前面我们已经说过要修改制造商和产品的ID号,把0xfff0这两个值改为未知USB的ID号。

#define USB_SKEL_VENDOR_IDxfff0

#define USB_SKEL_PRODUCT_ID 0xfff0

还 有就是在探测函数中把需要探测的接口端点类型写好,在这个框架程序中只探测了批量(USB_ENDPOINT_XFER_BULK)IN和OUT端点,可 以在此处使用掩码(USB_ENDPOINT_XFERTYPE_MASK)让其探测其它的端点类型,驱动程序会对USB设备的每一个接口进行一次探测, 当探测成功后,驱动程序就被绑定到这个接口上。再有就是urb的初始化问题,如果你只写简单的USB驱动,这块不用多加考虑,框架程序里的东西已经够用 了,这里我们简单介绍三个初始化urb的辅助函数:

u_fill_int_urb :它的函数原型是这样的:

void u_fill_int_urb(struct urb *urb,struct u_device *dev,

unsigned int pipe,void *transfer_buff,

int buffer_length,u_complete_t complete,

void *context,int interval);

这个函数用来正确的初始化即将被发送到USB设备的中断端点的urb。

u_fill_bulk_urb :它的函数原型是这样的:

void u_fill_bulk_urb(struct urb *urb,struct u_device *dev,

unsigned int pipe,void *transfer_buffer,

int buffer_length,u_complete_t complete)

这个函数是用来正确的初始化批量urb端点的。

u_fill_control_urb :它的函数原型是这样的:

void u_fill_control_urb(struct urb *urb,struct u_device *dev,unsigned int pipe,unsigned char *setup_packet,void *transfer_buffer,int buffer_length,u_complete_t complete,void *context);

这个函数是用来正确初始化控制urb端点的。

还有一个初始化等时urb的,它现在还没有初始化函数,所以它们在被提交到USB核心前,必须在驱动程序中手工地进行初始化,可以参考内核源代码树下的/usr/src/~/drivers/u/media下的konicawc.c文件。

linux 重新枚举u设备的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux 重新枚举u设备,「Linux如何重新枚举USB设备」,怎么能将linux下自动分配的u0改为u1的信息别忘了在本站进行查找喔。

香港服务器首选树叶云,2H2G首月10元开通。
树叶云(shuyeidc.com)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/171747.html<

(0)
运维的头像运维
上一篇2025-03-23 00:19
下一篇 2025-03-23 00:21

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注