USB 장치 중에 vid가 0bda이고 pid가 8176인 장치가 연결되어 있는지 알아 보는 방법입니다.
USB node는 /sys/bus/usb/devices/ 에 생성되고 idVendor와 idProuct를 읽어보면 됩니다.
{
DIR *dir = opendir("/sys/bus/usb/devices/");
struct dirent *dent;
if (dir != NULL) {
while ((dent = readdir(dir)) != NULL) {
char node[50] = {'\0',};
sprintf(node, "/sys/bus/usb/devices/%s/idVendor", dent->d_name);
int vid_fd = open(node, O_RDONLY);
char buf[5];
if (vid_fd > 0) {
read(vid_fd, buf, 4);
ALOGE("node = %s, vid = %s", node, buf);
if (strcmp(buf, "0bda") == 0) {
sprintf(node, "/sys/bus/usb/devices/%s/idProduct", dent->d_name);
int pid_fd = open(node, O_RDONLY);
read(pid_fd, buf, 4);
ALOGE("node = %s, pid = %s", node, buf);
if (pid_fd > 0) {
if (strcmp(buf, "8176") == 0) {
//pid가 8176인 장치가 연결되어 있음
break;
}
close(pid_fd);
}
}
close(vid_fd);
}
}
}
close(dir);
}
2013년 12월 22일 일요일
2013년 7월 4일 목요일
Use USB GPS for ODROID
android에 외장형 USB GPS를 연결하여 보자.
아래 보이는 USB 타입 GPS는 ACM 드라이버로 붙습니다.
http://www.ascenglobal.com/info.asp?id=139
kernel에서 ACM을 추가한다.
*** USB Device Class drivers ***
<*> USB Modem (CDC ACM) support
< > USB Printer support
아래 링크에서 gps 소스를 다운 받는다.
https://www.dropbox.com/s/tp8zp5grnpis51r/libodroid-gps.tar.gz
device/hardkernel/proprietary/libodroid-gps에 압축을 푼다.
device.mk에 gps가 포함이 되도록 수정한다.
# gps
PRODUCT_PACKAGES += \
gps.$(TARGET_PRODUCT)
BoardConfig.mk
# GPS
BOARD_HAVE_ODROID_GPS := true
BOARD_SUPPORT_EXTERNAL_GPS := true
uevent.odroid[X].rc
62 #for gps
63 /dev/ttyACM0 0666 gps gps
64 /dev/ttyUSB0 0666 gps gps
hardware/libhardware/hardware.c
91 /* Check that the id matches */
92 if (strcmp(id, hmi->id) != 0) {
93 ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
94 status = -EINVAL;
95 goto done;
96 }
97
98 //codewalker
99 if(hmi->dso)
100 hmi->dso = handle;
101
102 /* success */
103 status = 0;
아래 보이는 USB 타입 GPS는 ACM 드라이버로 붙습니다.
http://www.ascenglobal.com/info.asp?id=139
kernel에서 ACM을 추가한다.
*** USB Device Class drivers ***
<*> USB Modem (CDC ACM) support
< > USB Printer support
아래 링크에서 gps 소스를 다운 받는다.
https://www.dropbox.com/s/tp8zp5grnpis51r/libodroid-gps.tar.gz
device/hardkernel/proprietary/libodroid-gps에 압축을 푼다.
device.mk에 gps가 포함이 되도록 수정한다.
# gps
PRODUCT_PACKAGES += \
gps.$(TARGET_PRODUCT)
BoardConfig.mk
# GPS
BOARD_HAVE_ODROID_GPS := true
BOARD_SUPPORT_EXTERNAL_GPS := true
62 #for gps
63 /dev/ttyACM0 0666 gps gps
64 /dev/ttyUSB0 0666 gps gps
hardware/libhardware/hardware.c
91 /* Check that the id matches */
92 if (strcmp(id, hmi->id) != 0) {
93 ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
94 status = -EINVAL;
95 goto done;
96 }
97
98 //codewalker
99 if(hmi->dso)
100 hmi->dso = handle;
101
102 /* success */
103 status = 0;
2011년 11월 24일 목요일
android에서 USB Mass Storage 사용하기
ODROID-7/A에 USB Host가 있습니다.
거기에 USB 저장장치를 연결하여 자동으로 mnt/sdcard/external_storage란 폴더에 자동으로 마운트가 되도록 수정해 보려고 합니다.
ODROID-A에는 두개의 mmc가 있어서 galaxy s처럼 추가 외부 저장장치를 지원합니다.
vold와 MountService.java를 수정하였습니다.
vold.fstab에 bus node를 등록하면 UMS까지 지원하려고 했지만 usb mass 장치를 붙일때 마다 bus node의 인덱싱이 host1, host2 처럼 증가합니다.
vold의 구조가 동적 증가하는 장치를 지원하지 않는 구조 입니다.
fstab에 등록되어 있는 노드 객체를 만들고 등록된 Volume이 NetlinkEvent의 DEVPATH와 동일하면 처리합니다. 따라서 USB Host에 연결하는 장치와 같이 bus 이름이 증가하는 구조에는 적용이 안됩니다.
그리서 vold에서 강제로 mount 하도록 해 봤습니다.
kernel에 USB Mass Storage support를 추가 한다.
<*> USB Mass Storage support
그리고 system/vold/VolumeManager.cpp에 handleBlockEvent() 함수를 다음과 같이 수정합니다.
bool usb_storage_mounted = false;
bool second_netlinkevent = false;
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
const char *devpath = evt->findParam("DEVPATH");
/* Lookup a volume to handle this device */
VolumeCollection::iterator it;
bool hit = false;
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
if (!(*it)->handleBlockEvent(evt)) {
#ifdef NETLINK_DEBUG
SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
#endif
hit = true;
break;
}
}
if (!hit) {
#ifdef NETLINK_DEBUG
SLOGW("No volumes handled block event for '%s'", devpath);
#endif
거기에 USB 저장장치를 연결하여 자동으로 mnt/sdcard/external_storage란 폴더에 자동으로 마운트가 되도록 수정해 보려고 합니다.
ODROID-A에는 두개의 mmc가 있어서 galaxy s처럼 추가 외부 저장장치를 지원합니다.
vold와 MountService.java를 수정하였습니다.
vold.fstab에 bus node를 등록하면 UMS까지 지원하려고 했지만 usb mass 장치를 붙일때 마다 bus node의 인덱싱이 host1, host2 처럼 증가합니다.
vold의 구조가 동적 증가하는 장치를 지원하지 않는 구조 입니다.
fstab에 등록되어 있는 노드 객체를 만들고 등록된 Volume이 NetlinkEvent의 DEVPATH와 동일하면 처리합니다. 따라서 USB Host에 연결하는 장치와 같이 bus 이름이 증가하는 구조에는 적용이 안됩니다.
그리서 vold에서 강제로 mount 하도록 해 봤습니다.
kernel에 USB Mass Storage support를 추가 한다.
<*> USB Mass Storage support
그리고 system/vold/VolumeManager.cpp에 handleBlockEvent() 함수를 다음과 같이 수정합니다.
bool usb_storage_mounted = false;
bool second_netlinkevent = false;
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
const char *devpath = evt->findParam("DEVPATH");
/* Lookup a volume to handle this device */
VolumeCollection::iterator it;
bool hit = false;
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
if (!(*it)->handleBlockEvent(evt)) {
#ifdef NETLINK_DEBUG
SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
#endif
hit = true;
break;
}
}
if (!hit) {
#ifdef NETLINK_DEBUG
SLOGW("No volumes handled block event for '%s'", devpath);
#endif
if (second_netlinkevent) {
second_netlinkevent = false;
return;
}
char *usb_mass_node = "/devices/platform/s5p-ehci/usb";
if (usb_storage_mounted) {
umount("/mnt/sdcard/external_storage");
usb_storage_mounted = false;
SLOGE("unmounted USB Mass Storage");
} else {
int len = strlen(usb_mass_node);
if (strncmp(devpath, usb_mass_node, len) == 0) {
usleep(5000);
if (Fat::doMount("/dev/block/sda1", "/mnt/sdcard/external_storage", false, false, false,
1000, 1015, 0702, true)) {
SLOGE("%s failed to mount via VFAT (%s)\n", devpath, strerror(errno));
} else {
SLOGE("mounted USB Mass Storage");
usb_storage_mounted = true;
}
} else {
SLOGE("not USB Mass Storage");
}
}
second_netlinkevent = true;
}
코드를 조금 설명 드리면 USB Mass는 event가 두번 발생하여 second_netlinkevent를 통해 한번만 처리되도록 하였습니다.
usleep은 event가 발생시점에는 node가 없을 수 있기 때문에 대기 하였다 mount 시킵니다.
devpath가 "/devices/platform/s5p-ehci/usb" 까지 동일하고 usb1,2,3... 이렇게 증가 하기 때문에 여기까지 같다면 usb mass storage 장치가 연결된 걸로 처리 합니다.
물론 init.rc에 external_storage 노드를 처리하여야 합니다.
40 # create mountpoints
41 mkdir /mnt 0775 root system
42 mkdir /mnt/sdcard 0000 system system
43 mkdir /mnt/sdcard/external_storage 0000 system system
44
45 # Create cgroup mount point for cpu accounting
46 mkdir /acct
47 mount cgroup none /acct cpuacct
48 mkdir /acct/uid
49
50 # Backwards Compat - XXX: Going away in G*
51 symlink /mnt/sdcard /sdcard
52 symlink /mnt/sdcard/external_storage /sdcard1
그리고 vold에서 external_storage를 만드는 코드를 추가 합니다.
int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
dumpArgs(argc, argv, -1);
if (argc < 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
return 0;
}
VolumeManager *vm = VolumeManager::Instance();
int rc = 0;
if (!strcmp(argv[1], "list")) {
return vm->listVolumes(cli);
} else if (!strcmp(argv[1], "debug")) {
if (argc != 3 || (argc == 3 && (strcmp(argv[2], "off") && strcmp(argv[2], "on")))) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume debug ", false);
return 0;
}
vm->setDebug(!strcmp(argv[2], "on") ? true : false);
} else if (!strcmp(argv[1], "mount")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mount ", false);
return 0;
}
rc = vm->mountVolume(argv[2]);
//codewalker
mkdir("/mnt/sdcard/external_storage", 0777);
} else if (!strcmp(argv[1], "unmount")) {
if (argc < 3 || argc > 4 || (argc == 4 && strcmp(argv[3], "force"))) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount [force]", false);
return 0;
}
bool force = false;
if (argc >= 4 && !strcmp(argv[3], "force")) {
이렇게 하면 Media Scan이 안되는 문제와 UMS가 안되는 문제가 있습니다.
Astro FileManager 같은데서 직접 폴더를 열어서 사용하는 상황에 맞겠죠.
그리고 여럿 예외 처리가 필요할 걸로 판단됩니다.
피드 구독하기:
글 (Atom)