origin: https://blog.csdn.net/wuyuwei45/article/details/8926858
Linux kernel2.6以上的版本中,USB裝置驅動的介面改為了gadget,在kernel/driver/usb/gadget目錄下主要包含了平台USB UDC驅動和gadget介面驅動。
kernel/driver/usb/gadget目下的serial.c是一個常用的驅動檔案,它可以配置為bulk傳輸驅動或CDC ACM驅動(USB轉串口驅動)。配置的方式有兩種,一可以在編譯前手動更改驅動檔案中的變數“use_acm"的預設值,現在預設值為”true“,對應為CDC ACM驅動,改為”false"後對應為bulk驅動;二可以將驅動編譯成模組,然後在insmod時傳遞一個參數就行了。
運行make menuconfig看一下:
將“USB Gadget Support -->"選擇編譯為模組,方便動態載入驅動。
進行“USB Gadget Support -->"配置子功能表:
配置紅色方框標註的模組。
運行命令: make M=driver/usb/gagdet modules
編譯後在driver/usb/gagdet 下生產g_file_storage.ko和g_serial.ko,分別對應為隨身碟驅動和USB轉串口驅動。
筆者的嵌入式板上有個SD卡,linux驅動後掛載主目錄是/dev/mmcblk0,分區目錄是/dev/mmcblk0p1,/dev/mmcblk0p2,/dev/mmcblk0p3,有三個分區。
執行:
[plain] view plain copy root@rfODNCC:/mnt# insmod g_file_storage.ko file=/dev/mmcblk0 stall=0 removable=1 [ 69.783477] g_file_storage gadget: No serial-number string provided! [ 69.798980] g_file_storage gadget: File-backed Storage Gadget, version: 1 September 2010 [ 69.807495] g_file_storage gadget: Number of LUNs=1 [ 69.812622] g_file_storage gadget-lun0: ro=0, nofua=0, file: /dev/mmcblk0 [ 69.819763] musb-hdrc musb-hdrc.0: MUSB HDRC host driver [ 69.825622] musb-hdrc musb-hdrc.0: new USB bus registered, assigned bus number 2 [ 69.833801] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002 [ 69.840942] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [ 69.848510] usb usb2: Product: MUSB HDRC host driver [ 69.853668] usb usb2: Manufacturer: Linux 2.6.37-05branch musb-hcd [ 69.860137] usb usb2: SerialNumber: musb-hdrc.0 [ 69.872558] hub 2-0:1.0: USB hub found [ 69.876647] hub 2-0:1.0: 1 port detected root@rfODNCC:/mnt# [ 70.169555] g_file_storage gadget: high speed config #1
串連USB到PC,可以看到PC端出現SD卡的分區目錄。
PS:insmod g_file_storage.ko file=/dev/mmcblk0 stall=0 removable=1 和 insmod g_file_storage.ko file=/dev/mmcblk0有點區別,後續可以尋找理解stall 和 removable的具體作用。
接著製作一個嵌入式裝置端fat32檔案分區,然後掛載到PC上:
1.在主機ubuntu上建立fat32檔案映像,大小為2M。
#dd if=/dev/zero of=fat32.img bs=1k count=2048
#mkfs.vfat fat32.img
2.向fat32.img中寫入一些檔案,以用來測試:
#mkdir fat32
#sudo mount -t vfat -o loop fat32.img fat32
#cd fat32
#touch hello.txt
#echo hello,wolrd>hello.txt
#sync
3.把主機ubuntu上的fat32.img 拷貝到嵌入式裝置的根檔案系統中。
4.在嵌入式裝置中載入g_file_storage驅動
insmod g_file_storage.ko file=/opt/fat32.img stall=0 removable=1 //我將fat32.img放在/opt下
5.USB線串連裝置和PC,彈出發現移動磁碟,開啟盤,裡面有個hello.txt檔案。
6.在PC端開啟隨身碟,增加一個檔案系統,如text.txt,然後在裝置端通過命令掛載映像,命令為:
mount -t vfat -o loop /opt/fat32.img /media //掛載到media目錄下
到media目錄,cd /media
看到/media目下有兩個檔案hello.txt和test.txt,且內容和在PC端看到的一致。
注意:如果此時在PC端再次修改了檔案。這裝置端不能立即看到PC修改的結果。即PC和裝置端不能同步。
此時可以在裝置進行umount /media,然後重新mount一次就可以看到PC更改的結果。同樣在裝置端修改的檔案,PC端也不能立即看到修改結果,需重新插拔USB線才能看到更新。至於原因,暫時不知道。
卸載g_file_storage
執行載入USB轉串口命令
[plain] view plain copy root@rfODNCC:/mnt# insmod g_serial.ko [ 239.675933] g_serial gadget: Gadget Serial v2.4 [ 239.680786] g_serial gadget: g_serial ready [ 239.685241] musb-hdrc musb-hdrc.0: MUSB HDRC host driver [ 239.691009] musb-hdrc musb-hdrc.0: new USB bus registered, assigned bus number 2 [ 239.707153] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002 [ 239.714324] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [ 239.721893] usb usb2: Product: MUSB HDRC host driver [ 239.727111] usb usb2: Manufacturer: Linux 2.6.37-05branch musb-hcd [ 239.733581] usb usb2: SerialNumber: musb-hdrc.0 [ 239.747467] hub 2-0:1.0: USB hub found [ 239.751434] hub 2-0:1.0: 1 port detected root@rfODNCC:/mnt# [ 240.044830] g_serial gadget: high speed config #2: CDC ACM config PC端安裝USB轉串口驅動後,可以從PC裝置管理員上看到多出了一個串口。
要使得裝置端能與PC端通過USB轉串口進行通訊,裝置端還需要手動建立裝置檔案節點,參考核心文檔(Documents/usb/gagdet_serial.txt)中的部分內容:
This will also automatically load the underlying gadget peripheral
controller driver. This must be done each time you reboot the gadget
side Linux system. You can add this to the start up scripts, if
desired.
Your system should use mdev (from busybox) or udev to make the
device nodes. After this gadget driver has been set up you should
then see a /dev/ttyGS0 node:
# ls -l /dev/ttyGS0 | cat
crw-rw---- 1 root root 253, 0 May 8 14:10 /dev/ttyGS0
#
Note that the major number (253, above) is system-specific. If
you need to create /dev nodes by hand, the right numbers to use
will be in the /sys/class/tty/ttyGS0/dev file.
作者建立裝置節點為:先cat /sys/class/tty/ttyGS0/dev,得到主裝置號後,mknod /dev/ttyGS0 c major_num 0
然後PC開啟一個串口軟體,開啟對應的串口連接埠。
裝置端執行 echo “hello” > /dev/ttyGS0,PC端串口軟體收到相應資料。
PS:UDC(裝置控制器)驅動主要是與硬體平台相關的,它會實現gadget功能驅動所需要的介面,一般的UDC僅支援註冊一個gadget功能驅動,所以上面是在將g_file_storage驅動卸載後才能重新載入g_serial.ko。否則會出現失敗。
看看UDC驅動代碼中的註冊gadget驅動函數usb_gadget_probe_driver中的部分程式:
[plain] view plain copy spin_lock_irqsave(&udc->lock, flags); if (udc->driver) { spin_unlock_irqrestore(&udc->lock, flags); return -EBUSY; } 可見第一次註冊gadget驅動後udc->driver為true,在不卸載情況下再次註冊gadget時出現無法註冊的錯誤。
【以下為轉載:http://blog.csdn.net/embededswordman/article/details/6689593】
Linux支援串連各種USB從裝置,同時也支援自己作為裝置插入到其他主機當中。最典型的例子就是Android OS的手機,插入電腦可以被識別為隨身碟之類的裝置。
對於SOC來說,這部分直接對應了USB Device部分的操作。
為了避免與作為主機時支援的"裝置驅動 (USB Device Driver)"一詞混淆, Linux給這部分的實現取名為"Gadget",小玩具。核心源碼的目錄為\drivers\usb\gadget,裡麵包含了核心所支援的不同類型的USB Device Controller (UDC)驅動的實現,以及架構和不同gadget的實現。
以AT91 ARM9為例,最底層的驅動為at91_udc.c(對於支援高速USB 2.0的SOC是atmel_usba_udc.c),它實現了gadget.h定義的統一介面,然後上層的各種gadget driver(如serial.c等)調用這一套統一的介面去實現不同類型的功能,如USB串口、隨身碟、USB乙太網路等等。
Atmel USB串口的架構圖:
USB串口的描述和使用方法在核心目錄\Documentation\usb\gadget_serial.txt中有詳細且清晰的描述,就不再這裡重複。一旦載入模組後會自動在/dev/下建立裝置檔案,程式就可以open它並且write,即使USB線沒有串連上。之前一直糾結在為什麼g_serial沒有向上層提供USB cable connect/disconnect的事件,後來想想在使用串口的時候也是一樣的情況,開啟一個即使沒有連接線的串口,也可以發送資料,只是沒有人會收到而已。不過與串口唯一的不同在於,如果通訊進行中中拔掉USB線,那麼再次串連USB線後需要重新open一次ttyGS0裝置檔案才可以重新發送,否則write不能向串口一樣正常工作而返回出錯。
參考部分:
官方Gadget架構的描述:http://www.linux-usb.org/gadget/
基於9263的配置過程:http://www.cublog.cn/u3/111925/showart_2278264.html
華清講師劉洪濤的BLOG:http://blog.csdn.net/hongtao_liu/article/details/4555645