新聞中心
Linux如何重新枚舉USB設(shè)備

為新津縣等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及新津縣網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都做網(wǎng)站、網(wǎng)站建設(shè)、新津縣網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
USB(通用串行總線(xiàn))設(shè)備在現(xiàn)代計(jì)算機(jī)中廣泛使用。在Linux系統(tǒng)中,USB設(shè)備會(huì)自動(dòng)識(shí)別并枚舉,以便可以在系統(tǒng)中使用。但是,有時(shí)設(shè)備可能無(wú)法正常枚舉或者需要重新枚舉才能重新識(shí)別,例如USB驅(qū)動(dòng)程序異常、硬件升級(jí)或更換等。在這種情況下,重新枚舉USB設(shè)備是一個(gè)常見(jiàn)的解決方案。
重新枚舉USB設(shè)備可以通過(guò)多種方式完成,包括使用系統(tǒng)命令、使用udev工具和重載USB內(nèi)核模塊。下面我們將詳細(xì)介紹這些方法。
方法1:使用系統(tǒng)命令
您可以使用系統(tǒng)命令來(lái)重新枚舉USB設(shè)備。請(qǐng)按以下步驟操作:
1.打開(kāi)終端并輸入以下命令:
sudo systemctl stop systemd-udevd.service
該命令將停止udev守護(hù)程序。
2.卸載所有掛載的USB存儲(chǔ)設(shè)備,以防止數(shù)據(jù)損壞。使用以下命令彈出所有已掛載的USB存儲(chǔ)驅(qū)動(dòng)器:
sudo eject /dev/sdX
其中“X”是USB存儲(chǔ)設(shè)備的字母。
3.使用以下命令卸載已連接但未掛載的USB存儲(chǔ)設(shè)備:
sudo umount /dev/sdX
4.斷開(kāi)所有的USB設(shè)備連接。
5.重新插入U(xiǎn)SB設(shè)備,您的計(jì)算機(jī)應(yīng)該能夠重新枚舉它們。
6.使用以下命令重啟udev守護(hù)程序:
sudo systemctl start systemd-udevd.service
方法2:使用udev工具
udev工具可以幫助管理和控制Linux系統(tǒng)中的設(shè)備。使用該工具重新枚舉USB設(shè)備,只需要使用以下命令:
sudo udevadm trigger
運(yùn)行此命令將強(qiáng)制udev重新掃描您的系統(tǒng)設(shè)備,包括USB設(shè)備。udev將通過(guò)檢查系統(tǒng)設(shè)備目錄的變化來(lái)更新設(shè)備信息,因此當(dāng)您重新插入U(xiǎn)SB設(shè)備時(shí),udev會(huì)自動(dòng)重新枚舉它們。
方法3:重載USB內(nèi)核模塊
最后一種解決方案是通過(guò)重新加載USB內(nèi)核模塊來(lái)重新枚舉USB設(shè)備。使用以下命令:
sudo rmmod u-storage
sudo modprobe u-storage
之一個(gè)命令將卸載USB存儲(chǔ)內(nèi)核模塊,第二個(gè)命令將重新加載該模塊。在重新加載USB內(nèi)核模塊后,您應(yīng)該能夠重新枚舉USB設(shè)備。
結(jié)論
重新枚舉USB設(shè)備是解決在Linux系統(tǒng)中使用USB設(shè)備問(wèn)題的有效方法。您可以使用系統(tǒng)命令、udev工具和重新加載USB內(nèi)核模塊這三種方法中的任何一種。
不過(guò),在執(zhí)行這些方法之前,請(qǐng)務(wù)必備份您的數(shù)據(jù)并謹(jǐn)慎處理USB設(shè)備,以防止數(shù)據(jù)丟失或設(shè)備損壞。同時(shí),如果您不確定該如何操作,請(qǐng)先咨詢(xún)專(zhuān)業(yè)人士。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!
怎么能將linux下自動(dòng)分配的u0改為u1
你好,方法如下:
寫(xiě)一個(gè)USB的驅(qū)動(dòng)程序最 基本的要做四件事:
驅(qū)動(dòng)程序要支持的設(shè)備、注冊(cè)USB驅(qū)動(dòng)程序、探測(cè)和斷開(kāi)、提交和控制urb(USB請(qǐng)求塊)
驅(qū)動(dòng)程序支持的設(shè)備:有一個(gè)結(jié)構(gòu)體struct u_device_id,這個(gè)結(jié)構(gòu)體提供了一列不同類(lèi)型的該驅(qū)動(dòng)程序支持的USB設(shè)備,對(duì)于一個(gè)只控制一個(gè)特定的USB設(shè)備的驅(qū)動(dòng)程序來(lái)說(shuō),struct u_device_id表被定義為:
/* 驅(qū)動(dòng)程序支持的設(shè)備列表 */
static struct u_device_id skel_table = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* 終止入口 */
};
MODULE_DEVICE_TABLE (u, skel_table);
對(duì) 于PC驅(qū)動(dòng)程序,MODULE_DEVICE_TABLE是必需的,而且u必需為該宏的之一個(gè)值,而USB_SKEL_VENDOR_ID和 USB_SKEL_PRODUCT_ID就是這個(gè)特殊設(shè)備的制造商和產(chǎn)品的ID了,我們?cè)诔绦蛑邪讯x的值改為我們這款USB的,如:
/* 定義制造商和產(chǎn)品的ID號(hào) */
#define USB_SKEL_VENDOR_ID 0x1234
#define USB_SKEL_PRODUCT_ID 0x2345
這兩個(gè)值可以通過(guò)命令lsu,當(dāng)然你得先把USB設(shè)備先插到主機(jī)上了?;蛘卟榭磸S(chǎng)商的USB設(shè)備的手冊(cè)也能得到,在我機(jī)器上運(yùn)行l(wèi)su是這樣的結(jié)果:
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
得到這兩個(gè)值后把它定義到程序李卜迅里就可以了。
注冊(cè)USB驅(qū)動(dòng)程序:所 有的USB驅(qū)動(dòng)程序都必須創(chuàng)建的結(jié)構(gòu)體是struct u_driver。這個(gè)結(jié)構(gòu)體必須由USB驅(qū)動(dòng)程序來(lái)填寫(xiě),包括許多回調(diào)函數(shù)和變量,它們向USB核心代碼描述USB驅(qū)動(dòng)程序。創(chuàng)建一個(gè)有效的 struct u_driver結(jié)構(gòu)體,只須要初始化五個(gè)字段就可以了,在框架程序中是這樣的:
static struct u_driver skel_driver = {
.owner = THIS_MODULE,
.name =”skeleton”,
.probe = skel_probe,
.disconnect = skel_disconnect,
.id_table = skel_table,
};
探測(cè)和斷開(kāi):當(dāng) 一個(gè)設(shè)備被安裝而USB核心認(rèn)為該驅(qū)動(dòng)程序應(yīng)該處理時(shí),探測(cè)函數(shù)被調(diào)用,探測(cè)函數(shù)檢查傳遞給它的設(shè)備信息,確定驅(qū)動(dòng)程序是否真的適合該設(shè)備。當(dāng)驅(qū)動(dòng)程序因 為某種原因不應(yīng)該控制設(shè)備時(shí),斷開(kāi)函數(shù)被調(diào)用,它可以做一些清理工作。探測(cè)回調(diào)函數(shù)中,USB驅(qū)動(dòng)程序初始化任何可能用于控制USB設(shè)備的局部結(jié)構(gòu)體,它 還把所需的任何設(shè)備相關(guān)信息保存到一個(gè)局部結(jié)構(gòu)體弊仔中,
提交和控制urb:當(dāng)驅(qū)動(dòng)程序有數(shù)據(jù)要發(fā)送到USB設(shè)備時(shí)(大多數(shù)情況是在驅(qū)動(dòng)程序的寫(xiě)函數(shù)中),要分配一個(gè)urb來(lái)把數(shù)據(jù)傳輸給設(shè)備:
/* 創(chuàng)建一個(gè)urb,并且給它分配一個(gè)緩存*/
urb = u_alloc_urb(0, GFP_KERNEL);
if (!urb) {
retval = -ENOMEM;
goto error;
}
當(dāng)urb被成功分配后,還要?jiǎng)?chuàng)建一個(gè)DMA緩沖區(qū)來(lái)以高效的方式發(fā)送數(shù)據(jù)到設(shè)備,傳遞給驅(qū)動(dòng)程序的數(shù)據(jù)要復(fù)制到這塊緩沖中去:
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;
}
當(dāng)數(shù)據(jù)從用戶(hù)空間正確復(fù)制到局部哪此緩沖區(qū)后,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核心以傳輸?shù)皆O(shè)備了:
/* 把數(shù)據(jù)從批量OUT端口發(fā)出 */
retval = u_submit_urb(urb, GFP_KERNEL);
if (retval) {
err(“%s – failed submitting write urb, error %d”, __FUNCTION__, retval);
goto error;
}
當(dāng)urb被成功傳輸?shù)経SB設(shè)備之后,urb回調(diào)函數(shù)將被USB核心調(diào)用,在我們的例子中,我們初始化urb,使它指向skel_write_bulk_callback函數(shù),以下就是該函數(shù):
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);
}
/* 釋放已分配的緩沖區(qū) */
u_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
}
有時(shí)候USB驅(qū)動(dòng)程序只是要發(fā)送或者接收一些簡(jiǎn)單的數(shù)據(jù),驅(qū)動(dòng)程序也可以不用urb來(lái)進(jìn)行數(shù)據(jù)的傳輸,這是里涉及到兩個(gè)簡(jiǎn)單的接口函數(shù):u_bulk_msg和u_control_msg ,在這個(gè)USB框架程序里讀操作就是這樣的一個(gè)應(yīng)用:
/* 進(jìn)行阻塞的批量讀以從設(shè)備獲取數(shù)據(jù) */
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);
/*如果讀成功,復(fù)制到用戶(hù)空間 */
if (!retval) {
if (copy_to_user(buffer, dev->bulk_in_buffer, count))
retval = -EFAULT;
else
retval = count;
}
u_bulk_msg接口函數(shù)的定義如下:
int u_bulk_msg(struct u_device *u_dev,unsigned int pipe,
void *data,int len,int *actual_length,int timeout);
其參數(shù)為:
struct u_device *u_dev:指向批量消息所發(fā)送的目標(biāo)USB設(shè)備指針。
unsigned int pipe:批量消息所發(fā)送目標(biāo)USB設(shè)備的特定端點(diǎn),此值是調(diào)用u_sndbulkpipe或者u_rcvbulkpipe來(lái)創(chuàng)建的。
void *data:如果是一個(gè)OUT端點(diǎn),它是指向即將發(fā)送到設(shè)備的數(shù)據(jù)的指針。如果是IN端點(diǎn),它是指向從設(shè)備讀取的數(shù)據(jù)應(yīng)該存放的位置的指針。
int len:data參數(shù)所指緩沖區(qū)的大小。
int *actual_length:指向保存實(shí)際傳輸字節(jié)數(shù)的位置的指針,至于是傳輸?shù)皆O(shè)備還是從設(shè)備接收取決于端點(diǎn)的方向。
int timeout:以Jiffies為單位的等待的超時(shí)時(shí)間,如果該值為0,該函數(shù)一直等待消息的結(jié)束。
如果該接口函數(shù)調(diào)用成功,返回值為0,否則返回一個(gè)負(fù)的錯(cuò)誤值。
u_control_msg接口函數(shù)定義如下:
int u_control_msg(struct u_device *dev,unsigned int pipe,__u8 request,__u8requesttype,__u16 value,__u16 index,void *data,__u16 size,int timeout)
除了允許驅(qū)動(dòng)程序發(fā)送和接收USB控制消息之外,u_control_msg函數(shù)的運(yùn)作和u_bulk_msg函數(shù)類(lèi)似,其參數(shù)和u_bulk_msg的參數(shù)有幾個(gè)重要區(qū)別:
struct u_device *dev:指向控制消息所發(fā)送的目標(biāo)USB設(shè)備的指針。
unsigned int pipe:控制消息所發(fā)送的目標(biāo)USB設(shè)備的特定端點(diǎn),該值是調(diào)用u_sndctrlpipe或u_rcvctrlpipe來(lái)創(chuàng)建的。
__u8 request:控制消息的USB請(qǐng)求值。
__u8 requesttype:控制消息的USB請(qǐng)求類(lèi)型值。
__u16 value:控制消息的USB消息值。
__u16 index:控制消息的USB消息索引值。
void *data:如果是一個(gè)OUT端點(diǎn),它是指身即將發(fā)送到設(shè)備的數(shù)據(jù)的指針。如果是一個(gè)IN端點(diǎn),它是指向從設(shè)備讀取的數(shù)據(jù)應(yīng)該存放的位置的指針。
__u16 size:data參數(shù)所指緩沖區(qū)的大小。
int timeout:以Jiffies為單位的應(yīng)該等待的超時(shí)時(shí)間,如果為0,該函數(shù)將一直等待消息結(jié)束。
如果該接口函數(shù)調(diào)用成功,返回傳輸?shù)皆O(shè)備或者從設(shè)備讀取的字節(jié)數(shù);如果不成功它返回一個(gè)負(fù)的錯(cuò)誤值。
這兩個(gè)接口函數(shù)都不能在一個(gè)中斷上下文中或者持有自旋鎖的情況下調(diào)用,同樣,該函數(shù)也不能被任何其它函數(shù)取消,使用時(shí)要謹(jǐn)慎。
我們要給未知的USB設(shè)備寫(xiě)驅(qū)動(dòng)程序,只需要把這個(gè)框架程序稍做修改就可以用了,前面我們已經(jīng)說(shuō)過(guò)要修改制造商和產(chǎn)品的ID號(hào),把0xfff0這兩個(gè)值改為未知USB的ID號(hào)。
#define USB_SKEL_VENDOR_IDxfff0
#define USB_SKEL_PRODUCT_ID 0xfff0
還 有就是在探測(cè)函數(shù)中把需要探測(cè)的接口端點(diǎn)類(lèi)型寫(xiě)好,在這個(gè)框架程序中只探測(cè)了批量(USB_ENDPOINT_XFER_BULK)IN和OUT端點(diǎn),可 以在此處使用掩碼(USB_ENDPOINT_XFERTYPE_MASK)讓其探測(cè)其它的端點(diǎn)類(lèi)型,驅(qū)動(dòng)程序會(huì)對(duì)USB設(shè)備的每一個(gè)接口進(jìn)行一次探測(cè), 當(dāng)探測(cè)成功后,驅(qū)動(dòng)程序就被綁定到這個(gè)接口上。再有就是urb的初始化問(wèn)題,如果你只寫(xiě)簡(jiǎn)單的USB驅(qū)動(dòng),這塊不用多加考慮,框架程序里的東西已經(jīng)夠用 了,這里我們簡(jiǎn)單介紹三個(gè)初始化urb的輔助函數(shù):
u_fill_int_urb :它的函數(shù)原型是這樣的:
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);
這個(gè)函數(shù)用來(lái)正確的初始化即將被發(fā)送到USB設(shè)備的中斷端點(diǎn)的urb。
u_fill_bulk_urb :它的函數(shù)原型是這樣的:
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)
這個(gè)函數(shù)是用來(lái)正確的初始化批量urb端點(diǎn)的。
u_fill_control_urb :它的函數(shù)原型是這樣的:
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);
這個(gè)函數(shù)是用來(lái)正確初始化控制urb端點(diǎn)的。
還有一個(gè)初始化等時(shí)urb的,它現(xiàn)在還沒(méi)有初始化函數(shù),所以它們?cè)诒惶峤坏経SB核心前,必須在驅(qū)動(dòng)程序中手工地進(jìn)行初始化,可以參考內(nèi)核源代碼樹(shù)下的/usr/src/~/drivers/u/media下的konicawc.c文件。
linux 重新枚舉u設(shè)備的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于linux 重新枚舉u設(shè)備,「Linux如何重新枚舉USB設(shè)備」,怎么能將linux下自動(dòng)分配的u0改為u1的信息別忘了在本站進(jìn)行查找喔。
四川成都云服務(wù)器租用托管【創(chuàng)新互聯(lián)】提供各地服務(wù)器租用,電信服務(wù)器托管、移動(dòng)服務(wù)器托管、聯(lián)通服務(wù)器托管,云服務(wù)器虛擬主機(jī)租用。成都機(jī)房托管咨詢(xún):13518219792
創(chuàng)新互聯(lián)(www.cdcxhl.com)擁有10多年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn)、開(kāi)啟建站+互聯(lián)網(wǎng)銷(xiāo)售服務(wù),與企業(yè)客戶(hù)共同成長(zhǎng),共創(chuàng)價(jià)值。
標(biāo)題名稱(chēng):「Linux如何重新枚舉USB設(shè)備」(linux重新枚舉u設(shè)備)
本文地址:http://www.dlmjj.cn/article/cdojics.html


咨詢(xún)
建站咨詢(xún)
