标签:
1、 控制器:MT7620(A9内核)
1、开发环境:Ubuntu12.04
2、SDK内核包:MT7620 SDK软件开发包(MediaTek_ApSoC_SDK_4320_20150414.tar.bz2)
3、内核版本:linux-2.6.36.x
《MTK_APSoC_SDK_User_Manual.pdf》。
下载链接:http://download.csdn.net/detail/xhoufei2010/9478004
USB Mass Storage是一类USB存储设备,这些设备包括USB磁盘、USB硬盘、USB磁带机、USB光驱、U盘、记忆棒、智能卡和一些USB摄像头等,这类设备由USB协议支持。
对于USB的U盘驱动,已经非常完善,大家只需要简单地配置一下内核,开启U盘的功能即可。
由于Linux 内核包默认会自动挂载,且内核初始化的过程中,挂载出现在创建USB节点之前,经常出现自动挂载导致内核崩溃,故取消内核挂载,自己监听USB的热插拔,然后挂载。
进入到内核开发包目录 cd /home/kernel/source
输入命令 make menuconfig
Kernel/Library/Defaults Selection --->Customize Busybox Settings ,选中该选项,如图5-1所示,设置完成之后,保存退出。
图5-1 设置Busybox
在图5-1保存设置之后,会自动跳转到busybox的设置界面,在界面中,进入Linux System Utilities,取消掉Support command execution at device addition/removal 选项,如图5-2所示。
图5-2 取消USB的自动挂载/卸载
在linux-2.6.36.x中,输入命令make menuconfig,进入配置
Linux Kernel Configuration ---> Device Drivers ---> USB support ,在配置中,选中USB Mass Storage support,如图5-3所示。
图5-3 开启USB U盘支持
对于USB的热插拔,实际就是建立一个socket,采用socket监听USB的插拔信息。
当监听到USB插入信息,且发现在 /dev目录下,存在 sda1或者sdb1分区(有时候分区节点为其他名称,根据实际分区修改分区的名称判断条件)的时候,就挂载USB分区到 /tmp/usb目录下。
当监听到USB拔出信息,则卸载 /tmp/usb目录。
/** * @addtogroup module_genericGateway * @{ */ /** * @file * @brief USB控制器,管理USB插拔及挂载。 * @details * @version 1.0.0 * @author sky.houfei * @date 2016-3-18 */ #ifndef _USB_USBCONTROLLER_H_ #define _USB_USBCONTROLLER_H_ #ifdef __cplusplus extern "C" { #endif //****************************************************************************** #include <stdbool.h> //****************************************************************************** /** * @brief USB控制器初始化,准备USB的监听服务。 * @return ret, int,如果初始化成功,则返回0,否则为-1. */ int UsbController_Init(void); /** * @brief USB设备挂载监听。 * @details 如果USB之前没有挂载且当前可以挂载,则挂载。 * \n 如果USB之前挂载成功,此时设备已经被拔出,则卸载。 */ void UsbController_MountMonitor(void); /** * @brief 是否已经挂载成功。 * @return bool s_isMounted, USB设备挂载成功,则返回 true, 否则返回false。 */ bool UsbController_IsMounted(void); #ifdef __cplusplus } #endif #endif // _USB_USBCONTROLLER_H_ /** @} */
/** * @addtogroup module_genericGateway * @{ */ /** * @file * @brief USB控制器,管理USB插拔及挂载。 * @details * @version 1.0.0 * @author sky.houfei * @date 2016-3-18 */ //****************************************************** #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <sys/un.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <linux/types.h> #include <linux/netlink.h> #include <errno.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include "UsbController.h" #include "GenericGateway.h" //****************************************************** #define UEVENT_BUFFER_SIZE 2048 //****************************************************** static bool isUsbConnected = false; static int s_hotplugSock = 0; static bool s_isMounted = false; //****************************************************** static void* UsbController_HotPlugMonitor(void); // USB监听,监听USB的插拔事件,并进行挂载和卸载USB设备。 //****************************************************** static int UsbController_HotplugSockInit(void) { const int buffersize = 1024; int ret; struct sockaddr_nl snl; bzero(&snl, sizeof(struct sockaddr_nl)); snl.nl_family = AF_NETLINK; snl.nl_pid = getpid(); snl.nl_groups = 1; int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (s == -1) { perror("socket"); return -1; } setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl)); if (ret < 0) { perror("bind"); close(s); return -1; } return s; } /** * @brief USB控制器初始化,准备USB的监听服务。 * @return ret, int,如果初始化成功,则返回0,否则为-1. */ int UsbController_Init(void) { const int buffersize = 1024; int ret; pthread_t id; struct sockaddr_nl snl; bzero(&snl, sizeof(struct sockaddr_nl)); snl.nl_family = AF_NETLINK; snl.nl_pid = getpid(); snl.nl_groups = 1; if (access("/dev/sda1", 0) == 0) { // USB已经连接成功 isUsbConnected = true; } UsbController_MountMonitor(); // 首次检查USB是否挂载 s_hotplugSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (s_hotplugSock == -1) { perror("socket error"); return -1; } setsockopt(s_hotplugSock, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); ret = bind(s_hotplugSock, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl)); if (ret < 0) { perror("bind error"); close(s_hotplugSock); return -1; } ret = pthread_create(&id, NULL, UsbController_HotPlugMonitor, NULL); if (ret != 0) { printf("pthread_create error = %d\n", ret); } return 0; } /** * @brief USB监听热插拔,监听USB的插拔事件,并进行挂载和卸载USB设备。 */ static void* UsbController_HotPlugMonitor(void) { pthread_detach(pthread_self()); char *result = NULL; char buf[UEVENT_BUFFER_SIZE * 2] = {0}; // Netlink message buffer while (1) { recv(s_hotplugSock, &buf, sizeof(buf), 0); // 获取 USB 设备的插拔会出现字符信息, result = strtok(buf, "@"); // 查看 USB的插入还是拔出信息 if (result != NULL) { if ((strcmp(result, "add") == 0)) { if (isUsbConnected == false) { isUsbConnected = true; } } else if ((strcmp(result, "remove") == 0)) { if (isUsbConnected == true) { isUsbConnected = false; } } } memset(buf, 0, UEVENT_BUFFER_SIZE * 2); } } /** * @brief 是否连接成功。 * @return bool isConnnected, USB设备连接成功,则返回 true, 否则返回false。 */ static bool UsbController_IsConnected(void) { return isUsbConnected; } /** * @brief 挂载文件系统。 * @details 创建文件夹 /tmp/usb,将USB设备挂在在该目录下。尝试挂在 sda1和sdb1,如果都挂在失败,则认为挂载失败。 * @return 如果挂载成功,则返回0,否则为-1。 */ static int UsbController_MountFileSystem(void) { const char directory[] = "/tmp/usb"; int ret = 0; printf("Try to mount the usb device\n"); // 检测是否存在文件夹 if (access(directory, 0) == -1) { // 文件夹不存在 if (mkdir(directory, 0777)) // 创建文件夹 { printf("creat directory(%s) failed!!!", directory); return -1; } } if (system("mount -t vfat /dev/sda1 /tmp/usb") < 0) // 挂载USB的文件系统 { if (system("mount -t vfat /dev/sdb1 /tmp/usb") < 0) { return -1; } } return 0; } /** * @brief 卸载文件系统。 * @return 如果挂载成功,则返回0,否则为-1。 */ static int UsbController_UnmountFileSystem(void) { int ret = 0; if (system("umount /tmp/usb") < 0) // 挂载USB的文件系统 { printf("Umount the usb device failed\n"); ret = -1; } printf("Umount the usb device success\n"); return ret; } /** * @brief USB设备是否可以挂载。 * @details 设备处于连接状态,且在/dev/目录下创建了sda1或者sdb1节点,则视为可以挂载。 * @return 如果可以挂在,则返回true,否则为false。 */ static bool UsbController_IsMountable(void) { bool isMountable = false; bool isPartitionExist = false; if (access("/dev/sda1", 0) == 0 || access("/dev/sdb1", 0) == 0) { // 存在分区 /dev/sda1 或者 /dev/sdb1 isPartitionExist = true; } if (isUsbConnected == true && isPartitionExist == true) { isMountable = true; } return isMountable; } /** * @brief USB设备挂载监听。 * @details 如果USB之前没有挂载且当前可以挂载,则挂载。 * \n 如果USB之前挂载成功,此时设备已经被拔出,则卸载。 */ void UsbController_MountMonitor(void) { if (s_isMounted == false && UsbController_IsMountable() == true) { // 之前没有挂载且当前可以挂载,挂载文件系统 if (0 == UsbController_MountFileSystem()) { printf("Mount success\n"); s_isMounted = true; GenericGateway_SetUsbMounted(s_isMounted); } } else if (s_isMounted == true && UsbController_IsConnected() == false) { // 之前挂载成功,此时设备已经被拔出,卸载设备 if (0 == UsbController_UnmountFileSystem()) { s_isMounted = false; GenericGateway_SetUsbMounted(s_isMounted); } } } /** * @brief 是否已经挂载成功。 * @return bool s_isMounted, USB设备挂载成功,则返回 true, 否则返回false。 */ bool UsbController_IsMounted(void) { return s_isMounted; } /** @} */
#include <stdio.h> #include "usb/UsbController.h" int main(int argc, char** argv) { int secondCount = 0; UsbController_Init(); while (1) { sleep(1); secondCount++; if (secondCount >= 5) { secondCount = 0; UsbController_MountMonitor(); } } }
1. 查看USB设备
# ls /dev/sd*
/dev/sda1 /dev/sda
2. 插入设备打印信息
# [ 226.340000] usb 1-1: new high speed USB device using rt3xxx-ehci and address 6
[ 226.490000] scsi4 : usb-storage 1-1:1.0
[ 227.520000] scsi 4:0:0:0: Direct-Access Kingston DataTraveler 2.0 1.00 PQ: 0 ANSI: 4
[ 227.540000] sd 4:0:0:0: [sda] 30310400 512-byte logical blocks: (15.5 GB/14.4 GiB)
[ 227.550000] sd 4:0:0:0: [sda] Write Protect is off
[ 227.560000] sd 4:0:0:0: [sda] Assuming drive cache: write through
[ 227.570000] sd 4:0:0:0: [sda] Assuming drive cache: write through
[ 227.580000] sda: sda1
[ 227.590000] sd 4:0:0:0: [sda] Assuming drive cache: write through
[ 227.590000] sd 4:0:0:0: [sda] Attached SCSI removable disk
Try to mount the usb device
[ 232.110000] FAT: utf8 is not a recommended IO charset for FAT filesystems, filesystem will be case sensitive!
Mount success
3. 查看USB挂载后的文件系统
查看之后,可以正常获取到U盘的内容。
# ls /tmp/usb/
test software computime
1. USB拔出之后,打印信息:
# [ 789.230000] usb 1-1: USB disconnect, address 6
Umount the usb device success
2. 查看文件系统
查看,发现/tmp/usb目录的内容已经被卸载,正常卸载。
# ls /tmp/usb/
#
#
标签:
原文地址:http://blog.csdn.net/xhoufei2010/article/details/50987762