g26a345の日記: USB-IO その3
日記 by
g26a345
おもちゃとしてモルフィーのUSBIOで遊んでいるけど、Linux標準のHIDの使い方がよく判らないままだった。
色々調べるとlibusbなるものがあり、それを使うと結構簡単に行けそうな感じ。
で、やってみた。
ハード的には、USB-IOの12本の信号(PortA 8本、PortB 4本)にそれぞれLEDがついてたり、また、その信号をH/Lに固定できたりするハードがあるとして。
大体以下のような感じで行けるようだ。
まずは出力。12個のLEDをON/OFFが出来た。
--- ここから ---
#include <usb.h>
#include <stdio.h>
#include <string.h>
#define USB_VENDOR 0x12ed
#define USB_PRODUCT 0x1003
/* USB初期化 */
struct usb_bus *morphy_init()
{
usb_init();
usb_find_busses();
usb_find_devices();
return( usb_get_busses() );
}
/* Morphy-USBIOを見つける */
struct usb_device *morphy_find(struct usb_bus *busses, struct usb_device *dev)
{
struct usb_bus *bus;
for(bus=busses; bus; bus=bus->next){
for(dev=bus->devices; dev; dev=dev->next) {
if( (dev->descriptor.idVendor==USB_VENDOR) && (dev->descriptor.idProduct==USB_PRODUCT) ){
return( dev );
}
}
}
return( NULL );
}
/* USBIOオープン */
struct usb_dev_handle *morphy_open(struct usb_device *dev)
{
struct usb_dev_handle *udev = NULL;
udev=usb_open(dev);
if( (udev=usb_open(dev))==NULL ){
printf("!!Can not Open USB-Device\n");
exit(0);
}
if( usb_set_configuration(udev,dev->config->bConfigurationValue)<0 ){
printf("!!usb_set_configuration Error.\n");
}
if( usb_claim_interface(udev,dev->config->interface->altsetting->bInterfaceNumber)<0 ){
printf("!!usb_claim_interface Error.\n");
}
return(udev);
}
/* USBIOクローズ */
void morphy_close(struct usb_dev_handle *udev)
{
if( usb_close(udev)<0 ){
printf("Can not Close USB-Device.\n");
}
}
/* ------------ */
/* MAIN */
/* ------------ */
int main(void)
{
int ret;
int c,i,a;
struct usb_bus *bus;
struct usb_device *dev;
usb_dev_handle *udev;
unsigned char ctl[8];
bus = morphy_init();
dev = morphy_find(bus,dev);
if( dev!=NULL ){
udev=morphy_open(dev);
ctl[2]=ctl[3]=ctl[4]=ctl[5]=ctl[6]=ctl[7]=0;
/* Port0 -> Write 00(LED On) */
ctl[0]=0x01; ctl[1]=0x00;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("!!usb_control_msg Error(01-00)\n");
}
sleep(1);
/* Port0 -> Write FF(LED Off) */
ctl[0]=0x01; ctl[1]=0xff;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("!!usb_control_msg Error(01-FF)\n");
}
sleep(1);
/* Port1 -> Write 00(LED On) */
ctl[0]=0x02; ctl[1]=0x00;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("!!usb_control_msg Error(02-00)\n");
}
sleep(1);
/* Port1 -> Write FF(LED Off) */
ctl[0]=0x02; ctl[1]=0xff;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("!!usb_control_msg Error(02-FF)\n");
}
}else{
printf("USBIO not found.\n");
}
morphy_close(udev);
return(0);
}
--- ここまで ---
つまるところ、ベンダーIDとかプロダクトIDから、USBIOであるデバイスを選んでオープン(morphy_open)して、あとはデバイスに対して、usb_control_msgでデータを送ってやればいいみたい。
リクエストタイプ等は、共通で、0x21,0x09あたりがそう。
実際のデータはctlという文字変数に入れてるけど、ctl[0]が0ならPortA、1ならPortBになる。ctl[1]が書き込む値で、回路の都合で、1を書けばLEDが消えて、0を書けばLEDが点く。
今回は、PortA全部点灯/消灯、PortB全部点灯/消灯てな感じで動かしている。
次に入力。
プログラムは出力と共通な部分が多いけど。
--- ここから ---
#include <usb.h>
#include <stdio.h>
#include <string.h>
#define USB_VENDOR 0x12ed
#define USB_PRODUCT 0x1003
/* USB初期化 */
struct usb_bus *morphy_init()
{
usb_init();
usb_find_busses();
usb_find_devices();
return( usb_get_busses() );
}
/* Morphy-USBIOを見つける */
struct usb_device *morphy_find(struct usb_bus *busses, struct usb_device *dev)
{
struct usb_bus *bus;
for(bus=busses; bus; bus=bus->next){
for(dev=bus->devices; dev; dev=dev->next) {
if( (dev->descriptor.idVendor==USB_VENDOR) && (dev->descriptor.idProduct==USB_PRODUCT) ){
return( dev );
}
}
}
return( NULL );
}
/* USBIOオープン */
struct usb_dev_handle *morphy_open(struct usb_device *dev)
{
struct usb_dev_handle *udev = NULL;
udev=usb_open(dev);
if( (udev=usb_open(dev))==NULL ){
printf("Can not Open USB-Device\n");
exit(0);
}
if( usb_set_configuration(udev,dev->config->bConfigurationValue)<0 ){
printf("%s\n",usb_strerror());
}
if( usb_claim_interface(udev,dev->config->interface->altsetting->bInterfaceNumber)<0 ){
printf("%s\n",usb_strerror());
}
return(udev);
}
/* USBIOクローズ */
void morphy_close(struct usb_dev_handle *udev)
{
if( usb_close(udev)<0 ){
printf("Can not Close USB-Device. %s\n",usb_strerror());
}
}
/* ------------ */
/* MAIN */
/* ------------ */
int main(void)
{
int ret;
int c,i,a;
struct usb_bus *bus;
struct usb_device *dev;
usb_dev_handle *udev;
unsigned char ctl[8];
bus = morphy_init();
dev = morphy_find(bus,dev);
if( dev!=NULL ){
udev=morphy_open(dev);
ctl[0]=ctl[1]=ctl[2]=ctl[3]=ctl[4]=ctl[5]=ctl[6]=ctl[7]=0;
/* CMD:Read Port0 */
ctl[0]=0x03;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("P0 Read-CmdError\n");
}
/* Port0 */
ret=usb_interrupt_read(udev,1,ctl,8,5000);
if( ret<0 ){
printf("P0 Int-Read Error\n");
}
for(i=0; i<8; i++){
printf(">ctl[%d]=%d\n",i,ctl[i]);
}
/* CMD:Read Port1 */
ctl[0]=0x04;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("P1 Read-CmdError\n");
}
/* Port1 */
ret=usb_interrupt_read(udev,1,ctl,8,5000);
if( ret<0 ){
printf("P1 Int-Read Error\n");
}
for(i=0; i<8; i++){
printf(">ctl[%d]=%d\n",i,ctl[i]);
}
}
morphy_close(udev);
return(0);
}
--- ここまで ---
MAINを除けば出力側と同じ記述になってるけど。
やり方は、PortA/PortBそれぞれのリードコマンドを発行(usb_control_msgで)し、インタラプト転送でリード(usb_interrupt_read)するだけであった。
PortAとPortBを同時にはリードできない?のかな?
ちなみにリード結果はctl[1]に格納されてる。
もうちょっと遊んでみよう。
色々調べるとlibusbなるものがあり、それを使うと結構簡単に行けそうな感じ。
で、やってみた。
ハード的には、USB-IOの12本の信号(PortA 8本、PortB 4本)にそれぞれLEDがついてたり、また、その信号をH/Lに固定できたりするハードがあるとして。
大体以下のような感じで行けるようだ。
まずは出力。12個のLEDをON/OFFが出来た。
--- ここから ---
#include <usb.h>
#include <stdio.h>
#include <string.h>
#define USB_VENDOR 0x12ed
#define USB_PRODUCT 0x1003
/* USB初期化 */
struct usb_bus *morphy_init()
{
usb_init();
usb_find_busses();
usb_find_devices();
return( usb_get_busses() );
}
/* Morphy-USBIOを見つける */
struct usb_device *morphy_find(struct usb_bus *busses, struct usb_device *dev)
{
struct usb_bus *bus;
for(bus=busses; bus; bus=bus->next){
for(dev=bus->devices; dev; dev=dev->next) {
if( (dev->descriptor.idVendor==USB_VENDOR) && (dev->descriptor.idProduct==USB_PRODUCT) ){
return( dev );
}
}
}
return( NULL );
}
/* USBIOオープン */
struct usb_dev_handle *morphy_open(struct usb_device *dev)
{
struct usb_dev_handle *udev = NULL;
udev=usb_open(dev);
if( (udev=usb_open(dev))==NULL ){
printf("!!Can not Open USB-Device\n");
exit(0);
}
if( usb_set_configuration(udev,dev->config->bConfigurationValue)<0 ){
printf("!!usb_set_configuration Error.\n");
}
if( usb_claim_interface(udev,dev->config->interface->altsetting->bInterfaceNumber)<0 ){
printf("!!usb_claim_interface Error.\n");
}
return(udev);
}
/* USBIOクローズ */
void morphy_close(struct usb_dev_handle *udev)
{
if( usb_close(udev)<0 ){
printf("Can not Close USB-Device.\n");
}
}
/* ------------ */
/* MAIN */
/* ------------ */
int main(void)
{
int ret;
int c,i,a;
struct usb_bus *bus;
struct usb_device *dev;
usb_dev_handle *udev;
unsigned char ctl[8];
bus = morphy_init();
dev = morphy_find(bus,dev);
if( dev!=NULL ){
udev=morphy_open(dev);
ctl[2]=ctl[3]=ctl[4]=ctl[5]=ctl[6]=ctl[7]=0;
/* Port0 -> Write 00(LED On) */
ctl[0]=0x01; ctl[1]=0x00;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("!!usb_control_msg Error(01-00)\n");
}
sleep(1);
/* Port0 -> Write FF(LED Off) */
ctl[0]=0x01; ctl[1]=0xff;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("!!usb_control_msg Error(01-FF)\n");
}
sleep(1);
/* Port1 -> Write 00(LED On) */
ctl[0]=0x02; ctl[1]=0x00;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("!!usb_control_msg Error(02-00)\n");
}
sleep(1);
/* Port1 -> Write FF(LED Off) */
ctl[0]=0x02; ctl[1]=0xff;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("!!usb_control_msg Error(02-FF)\n");
}
}else{
printf("USBIO not found.\n");
}
morphy_close(udev);
return(0);
}
--- ここまで ---
つまるところ、ベンダーIDとかプロダクトIDから、USBIOであるデバイスを選んでオープン(morphy_open)して、あとはデバイスに対して、usb_control_msgでデータを送ってやればいいみたい。
リクエストタイプ等は、共通で、0x21,0x09あたりがそう。
実際のデータはctlという文字変数に入れてるけど、ctl[0]が0ならPortA、1ならPortBになる。ctl[1]が書き込む値で、回路の都合で、1を書けばLEDが消えて、0を書けばLEDが点く。
今回は、PortA全部点灯/消灯、PortB全部点灯/消灯てな感じで動かしている。
次に入力。
プログラムは出力と共通な部分が多いけど。
--- ここから ---
#include <usb.h>
#include <stdio.h>
#include <string.h>
#define USB_VENDOR 0x12ed
#define USB_PRODUCT 0x1003
/* USB初期化 */
struct usb_bus *morphy_init()
{
usb_init();
usb_find_busses();
usb_find_devices();
return( usb_get_busses() );
}
/* Morphy-USBIOを見つける */
struct usb_device *morphy_find(struct usb_bus *busses, struct usb_device *dev)
{
struct usb_bus *bus;
for(bus=busses; bus; bus=bus->next){
for(dev=bus->devices; dev; dev=dev->next) {
if( (dev->descriptor.idVendor==USB_VENDOR) && (dev->descriptor.idProduct==USB_PRODUCT) ){
return( dev );
}
}
}
return( NULL );
}
/* USBIOオープン */
struct usb_dev_handle *morphy_open(struct usb_device *dev)
{
struct usb_dev_handle *udev = NULL;
udev=usb_open(dev);
if( (udev=usb_open(dev))==NULL ){
printf("Can not Open USB-Device\n");
exit(0);
}
if( usb_set_configuration(udev,dev->config->bConfigurationValue)<0 ){
printf("%s\n",usb_strerror());
}
if( usb_claim_interface(udev,dev->config->interface->altsetting->bInterfaceNumber)<0 ){
printf("%s\n",usb_strerror());
}
return(udev);
}
/* USBIOクローズ */
void morphy_close(struct usb_dev_handle *udev)
{
if( usb_close(udev)<0 ){
printf("Can not Close USB-Device. %s\n",usb_strerror());
}
}
/* ------------ */
/* MAIN */
/* ------------ */
int main(void)
{
int ret;
int c,i,a;
struct usb_bus *bus;
struct usb_device *dev;
usb_dev_handle *udev;
unsigned char ctl[8];
bus = morphy_init();
dev = morphy_find(bus,dev);
if( dev!=NULL ){
udev=morphy_open(dev);
ctl[0]=ctl[1]=ctl[2]=ctl[3]=ctl[4]=ctl[5]=ctl[6]=ctl[7]=0;
/* CMD:Read Port0 */
ctl[0]=0x03;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("P0 Read-CmdError\n");
}
/* Port0 */
ret=usb_interrupt_read(udev,1,ctl,8,5000);
if( ret<0 ){
printf("P0 Int-Read Error\n");
}
for(i=0; i<8; i++){
printf(">ctl[%d]=%d\n",i,ctl[i]);
}
/* CMD:Read Port1 */
ctl[0]=0x04;
ret=usb_control_msg(udev,0x21,0x09,0x00,0x00,ctl,8,5000);
if( ret<0 ){
printf("P1 Read-CmdError\n");
}
/* Port1 */
ret=usb_interrupt_read(udev,1,ctl,8,5000);
if( ret<0 ){
printf("P1 Int-Read Error\n");
}
for(i=0; i<8; i++){
printf(">ctl[%d]=%d\n",i,ctl[i]);
}
}
morphy_close(udev);
return(0);
}
--- ここまで ---
MAINを除けば出力側と同じ記述になってるけど。
やり方は、PortA/PortBそれぞれのリードコマンドを発行(usb_control_msgで)し、インタラプト転送でリード(usb_interrupt_read)するだけであった。
PortAとPortBを同時にはリードできない?のかな?
ちなみにリード結果はctl[1]に格納されてる。
もうちょっと遊んでみよう。