Android ADK,PC作为USB主机,带libusb,批量传输错误
我正试图使我的电脑成为安卓2.3.4设备的USB主机,以便能够在不需要实际“附件”的情况下开发API。为此,我需要将PC设置为USB主机和“设备”(在我的例子中,是运行2.3.4的NexusOne) 我从作为PC端基础的libusb代码开始,在Android端使用DemoKit代码和Android文档 两者似乎可以很好地协商连接,接口被“声明”,但在批量传输的实际尝试中死亡。在OSX上,错误为-5(未找到LIBUSB_错误),在Ubuntu Linux上(作为root用户),错误为-1(LIBUSB_错误)。(每个版本的最新版本都包含最新的libusb1.0.8) 这是密码。欢迎对问题发表其他评论,尽管这主要是概念证明,所以我只是想寻找批量传输不起作用的原因:Android ADK,PC作为USB主机,带libusb,批量传输错误,android,libusb,adk,Android,Libusb,Adk,我正试图使我的电脑成为安卓2.3.4设备的USB主机,以便能够在不需要实际“附件”的情况下开发API。为此,我需要将PC设置为USB主机和“设备”(在我的例子中,是运行2.3.4的NexusOne) 我从作为PC端基础的libusb代码开始,在Android端使用DemoKit代码和Android文档 两者似乎可以很好地协商连接,接口被“声明”,但在批量传输的实际尝试中死亡。在OSX上,错误为-5(未找到LIBUSB_错误),在Ubuntu Linux上(作为root用户),错误为-1(LIBU
#include <stdio.h>
#include <libusb.h>
#include <string.h>
#define ENDPOINT_BULK_IN 0x83
#define ENDPOINT_BULK_OUT 0x03 // Have tried 0x00, 0x01 and 0x02
#define VID 0x18D1
#define PID 0x4E11
#define ACCESSORY_PID 0x2D00
#define ACCESSORY_ADB_PID 0x2D01 // Can't get this to work, if ADB is active, can't get handle on device
/*
ON OSX
gcc adktest.c -I/usr/local/include -o adktest -lusb-1.0.0 -I/usr/local/include -I/usr/local/include/libusb-1.0
ON UBUNTU
gcc adktest.c -I/usr/include -o adktest -lusb-1.0 -I/usr/include -I/usr/include/libusb-1.0
Testing on Nexus One with Gingerbread 2.3.4
*/
static int transferTest();
static int init(void);
static int shutdown(void);
static void error(int code);
static void status(int code);
static int setupAccessory(
const char* manufacturer,
const char* modelName,
const char* description,
const char* version,
const char* uri,
const char* serialNumber);
//static
static struct libusb_device_handle* handle;
int main (int argc, char *argv[]){
if(init() < 0)
return;
if(setupAccessory(
"PCHost",
"PCHost1",
"Description",
"1.0",
"http://www.mycompany.com",
"SerialNumber") < 0){
fprintf(stdout, "Error setting up accessory\n");
shutdown();
return -1;
};
if(transferTest() < 0){
fprintf(stdout, "Error in transferTest\n");
shutdown();
return -1;
}
shutdown();
fprintf(stdout, "Finished\n");
return 0;
}
static int transferTest(){
// TEST BULK IN/OUT
const static int PACKET_BULK_LEN=64;
const static int TIMEOUT=5000;
int r,i;
int transferred;
char answer[PACKET_BULK_LEN];
char question[PACKET_BULK_LEN];
for (i=0;i<PACKET_BULK_LEN; i++) question[i]=i;
// ***FAILS HERE***
r = libusb_bulk_transfer(handle, ENDPOINT_BULK_OUT, question, PACKET_BULK_LEN,
&transferred,TIMEOUT);
if (r < 0) {
fprintf(stderr, "Bulk write error %d\n", r);
error(r);
return r;
}
fprintf(stdout, "Wrote %d bytes", r);
r = libusb_bulk_transfer(handle, ENDPOINT_BULK_IN, answer,PACKET_BULK_LEN,
&transferred, TIMEOUT);
if (r < 0) {
fprintf(stderr, "Bulk read error %d\n", r);
error(r);
return r;
}
fprintf(stdout, "Read %d bytes", r);
if (transferred < PACKET_BULK_LEN) {
fprintf(stderr, "Bulk transfer short read (%d)\n", r);
error(r);
return -1;
}
printf("Bulk Transfer Loop Test Result:\n");
// for (i=0;i< PACKET_BULK_LEN;i++) printf("%i, %i,\n ",question[i],answer[i]);
for(i = 0;i < PACKET_BULK_LEN; i++) {
if(i%8 == 0)
printf("\n");
printf("%02x, %02x; ",question[i],answer[i]);
}
printf("\n\n");
return 0;
}
static int init(){
libusb_init(NULL);
if((handle = libusb_open_device_with_vid_pid(NULL, VID, PID)) == NULL){
fprintf(stdout, "Problem acquiring handle\n");
return -1;
}
libusb_claim_interface(handle, 0);
return 0;
}
static int shutdown(){
if(handle != NULL)
libusb_release_interface (handle, 0);
libusb_exit(NULL);
return 0;
}
static int setupAccessory(
const char* manufacturer,
const char* modelName,
const char* description,
const char* version,
const char* uri,
const char* serialNumber){
unsigned char ioBuffer[2];
int devVersion;
int response;
response = libusb_control_transfer(
handle, //handle
0xC0, //bmRequestType
51, //bRequest
0, //wValue
0, //wIndex
ioBuffer, //data
2, //wLength
0 //timeout
);
if(response < 0){error(response);return-1;}
devVersion = ioBuffer[1] << 8 | ioBuffer[0];
fprintf(stdout,"Version Code Device: %d\n", devVersion);
usleep(1000);//sometimes hangs on the next transfer :(
response = libusb_control_transfer(handle,0x40,52,0,0,(char*)manufacturer,strlen(manufacturer),0);
if(response < 0){error(response);return -1;}
response = libusb_control_transfer(handle,0x40,52,0,1,(char*)modelName,strlen(modelName)+1,0);
if(response < 0){error(response);return -1;}
response = libusb_control_transfer(handle,0x40,52,0,2,(char*)description,strlen(description)+1,0);
if(response < 0){error(response);return -1;}
response = libusb_control_transfer(handle,0x40,52,0,3,(char*)version,strlen(version)+1,0);
if(response < 0){error(response);return -1;}
response = libusb_control_transfer(handle,0x40,52,0,4,(char*)uri,strlen(uri)+1,0);
if(response < 0){error(response);return -1;}
response = libusb_control_transfer(handle,0x40,52,0,5,(char*)serialNumber,strlen(serialNumber)+1,0);
if(response < 0){error(response);return -1;}
fprintf(stdout,"Accessory Identification sent\n", devVersion);
response = libusb_control_transfer(handle,0x40,53,0,0,NULL,0,0);
if(response < 0){error(response);return -1;}
fprintf(stdout,"Attempted to put device into accessory mode\n", devVersion);
if(handle != NULL)
libusb_release_interface (handle, 0);
int tries = 4;
for(;;){
tries--;
if((handle = libusb_open_device_with_vid_pid(NULL, VID, ACCESSORY_PID)) == NULL){
if(tries < 0){
return -1;
}
}else{
break;
}
sleep(1);
}
libusb_claim_interface(handle, 0);
fprintf(stdout, "Interface claimed, ready to transfer data\n");
return 0;
}
// error reporting function left out for brevity
#包括
#包括
#包括
#在0x83中定义端点_BULK_
#定义端点\u BULK\u OUT 0x03//已尝试0x00、0x01和0x02
#定义视频0x18D1
#定义PID 0x4E11
#定义附件PID 0x2D00
#定义附件\u ADB\u PID 0x2D01//无法使其工作,如果ADB处于活动状态,则无法在设备上获取句柄
/*
关于OSX
gcc adktest.c-I/usr/local/include-o adktest-lusb-1.0.0-I/usr/local/include-I/usr/local/include/libusb-1.0
在UBUNTU上
gcc adktest.c-I/usr/include-o adktest-lusb-1.0-I/usr/include-I/usr/include/libusb-1.0
使用姜饼2.3.4测试Nexus One
*/
静态int transferTest();
静态int init(void);
静态int关闭(无效);
静态无效错误(int代码);
静态无效状态(内部代码);
静态int设置附件(
const char*制造商,
常量字符*modelName,
常量字符*说明,
常量字符*版本,
常量char*uri,
常量字符*序列号);
//静止的
静态结构libusb\u设备\u句柄*句柄;
int main(int argc,char*argv[]){
if(init()<0)
返回;
if(设置附件)(
“PCHost”,
“PCHost1”,
“说明”,
"1.0",
"http://www.mycompany.com",
“序列号”)<0){
fprintf(stdout,“设置附件时出错\n”);
关机();
返回-1;
};
if(transferTest()<0){
fprintf(stdout,“传输测试中的错误”);
关机();
返回-1;
}
关机();
fprintf(标准输出,“完成”\n);
返回0;
}
静态int transferTest(){
//测试批量输入/输出
const static int PACKET\u BULK\u LEN=64;
const static int TIMEOUT=5000;
int r,i;
整数转移;
字符应答[PACKET_BULK_LEN];
字符问题[PACKET_BULK_LEN];
对于(i=0;i最初的问题是,为了告诉设备进入附件模式而与设备的原始连接从未关闭。如果在原始设备仍然打开的情况下重新打开并声明接口,USB子系统和/或libusb不会抛出错误。只有在实际尝试写入时,才会出现IO或not FOUND错误/从端点开始
加入:
libusb_close(handle);
在从初始连接释放初始接口的if语句中,问题的libusb端得到了解决
下一个阻止数据在这种特定软件组合中传递的问题是,Android端在接受读取之前等待更大的字节段,这会导致超时(由于哪一方的原因尚未解决),因此如果您将缓冲区设置为与libusb端相匹配(64),您将获得一组从PC写入Android设备的初始字节。之后,软件仍将中断,因为PC/libusb端尝试读取数据,但Android端没有写入任何数据,但这只是未完成的软件,不在问题的范围内。代码示例非常有用,只需要ome修改使用和通过在Windows上工作
#包括
#包括
#包括
#ifdef_WIN32
#包括
#定义睡眠
#否则
#包括
#恩迪夫
#在0x83中定义端点_BULK_
#定义端点\u BULK\u OUT 0x03//已尝试0x00、0x01和0x02
#定义视频0x18D1
#定义PID 0x4E11
#定义附件PID 0x2D00
#定义附件\u ADB\u PID 0x2D01//无法使其工作,如果ADB处于活动状态,则无法在设备上获取句柄
#定义数据包\u批量\u LEN 64
#定义超时5000
静态测试(无效);
静态int设置附件(
const char*制造商,
常量字符*modelName,
常量字符*说明,
常量字符*版本,
常量char*uri,
常量字符*序列号);
//静止的
静态结构libusb\u设备\u句柄*句柄;
int main(int argc,char*argv[])
{
int r,尝试;
libusb_init(空);
如果((handle=libusb\u open\u device\u with\u vid\u pid(NULL,vid,pid))!=NULL)
{
libusb_声明_接口(句柄,0);
r=设置附件(“PCHost”,
“PCHost1”,
“说明”,
"1.0",
"http://www.mycompany.com",
“序列号”);
libusb_释放_接口(句柄,0);
libu_关闭(手柄);
if(r<0)
{
libu_退出(空);
fprintf(stdout,“设置附件时出错\n”);
返回-1;
}
}
试验次数=4次;
对于(;;)
{
尝试--;
如果((句柄=libusb\u打开\u设备,\u带有\u视频\u pid(NULL,视频,附件\u pid))==NULL)
{
如果(尝试<0)
{
libu_退出(空);
fprintf(stdout,“获取句柄的问题”);
返回-1;
}
}
其他的
{
打破
}
睡眠(1);
}
libusb_声明_接口(句柄,0);
fprintf(stdout,“接口声明,准备传输数据”);
r=传输测试();
libusb_释放_接口(句柄,0);
libu_关闭(手柄);
libu_退出(空);
if(r<0)
{
fprintf(stdout,“传输测试中的错误”);
返回-1;
}
fprintf(标准输出,“完成”\n);
返回0;
}
静态测试(无效)
{
/
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mycompany.android.pchost"
android:versionCode="1"
android:versionName="1.0">
<uses-feature android:name="android.hardware.usb.accessory" />
<uses-sdk android:minSdkVersion="10" />
<application android:label="@string/app_name" android:icon="@drawable/icon">
<uses-library android:name="com.android.future.usb.accessory" />
<activity android:name="MainActivity"
android:label="@string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
</activity>
</application>
</manifest>
libusb_close(handle);
#include <stdio.h>
#include <libusb.h>
#include <string.h>
#ifdef _WIN32
#include <Windows.h>
#define sleep Sleep
#else
#include <unistd.h>
#endif
#define ENDPOINT_BULK_IN 0x83
#define ENDPOINT_BULK_OUT 0x03 // Have tried 0x00, 0x01 and 0x02
#define VID 0x18D1
#define PID 0x4E11
#define ACCESSORY_PID 0x2D00
#define ACCESSORY_ADB_PID 0x2D01 // Can't get this to work, if ADB is active, can't get handle on device
#define PACKET_BULK_LEN 64
#define TIMEOUT 5000
static int transferTest(void);
static int setupAccessory(
const char* manufacturer,
const char* modelName,
const char* description,
const char* version,
const char* uri,
const char* serialNumber);
//static
static struct libusb_device_handle* handle;
int main (int argc, char *argv[])
{
int r, tries;
libusb_init(NULL);
if((handle = libusb_open_device_with_vid_pid(NULL, VID, PID)) != NULL)
{
libusb_claim_interface(handle, 0);
r = setupAccessory("PCHost",
"PCHost1",
"Description",
"1.0",
"http://www.mycompany.com",
"SerialNumber");
libusb_release_interface (handle, 0);
libusb_close(handle);
if (r < 0)
{
libusb_exit(NULL);
fprintf(stdout, "Error setting up accessory\n");
return -1;
}
}
tries = 4;
for(;;)
{
tries--;
if((handle = libusb_open_device_with_vid_pid(NULL, VID, ACCESSORY_PID)) == NULL)
{
if(tries < 0)
{
libusb_exit(NULL);
fprintf(stdout, "Problem acquiring handle\n");
return -1;
}
}
else
{
break;
}
sleep(1);
}
libusb_claim_interface(handle, 0);
fprintf(stdout, "Interface claimed, ready to transfer data\n");
r = transferTest();
libusb_release_interface (handle, 0);
libusb_close(handle);
libusb_exit(NULL);
if (r < 0)
{
fprintf(stdout, "Error in transferTest\n");
return -1;
}
fprintf(stdout, "Finished\n");
return 0;
}
static int transferTest(void)
{
// TEST BULK IN/OUT
int r,i;
int transferred;
unsigned char answer[PACKET_BULK_LEN];
unsigned char question[PACKET_BULK_LEN];
struct libusb_device* device;
struct libusb_config_descriptor* config;
struct libusb_interface_descriptor const* interfaceDesc;
unsigned char epInAddr = ENDPOINT_BULK_IN;
unsigned char epOutAddr = ENDPOINT_BULK_OUT;
unsigned char idx;
for (i=0;i<PACKET_BULK_LEN; i++)
question[i]=(unsigned char)i;
device = libusb_get_device(handle);
r = libusb_get_active_config_descriptor(device, &config);
if (r < 0)
{
fprintf(stderr, "No active descriptor error %d\n", r);
return r;
}
interfaceDesc = config->interface[0].altsetting;
for(idx = 0; idx < interfaceDesc->bNumEndpoints; idx++)
{
if ((interfaceDesc->endpoint[idx].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK)
{
if ((interfaceDesc->endpoint[idx].bEndpointAddress & LIBUSB_ENDPOINT_IN) == LIBUSB_ENDPOINT_IN)
{
epInAddr = interfaceDesc->endpoint[idx].bEndpointAddress;
}
else
{
epOutAddr = interfaceDesc->endpoint[idx].bEndpointAddress;
}
}
}
r = libusb_bulk_transfer(handle, epOutAddr, question, PACKET_BULK_LEN,
&transferred,TIMEOUT);
if (r < 0)
{
fprintf(stderr, "Bulk write error %d\n", r);
return r;
}
fprintf(stdout, "Wrote %d bytes", r);
r = libusb_bulk_transfer(handle, epInAddr, answer,PACKET_BULK_LEN,
&transferred, TIMEOUT);
if (r < 0)
{
fprintf(stderr, "Bulk read error %d\n", r);
return r;
}
fprintf(stdout, "Read %d bytes", r);
if (transferred < PACKET_BULK_LEN)
{
fprintf(stderr, "Bulk transfer short read (%d)\n", r);
return -1;
}
printf("Bulk Transfer Loop Test Result:\n");
for(i = 0; i < PACKET_BULK_LEN; i++)
{
if(i%8 == 0)
printf("\n");
printf("%02x, %02x; ",question[i],answer[i]);
}
printf("\n\n");
return 0;
}
static int setupAccessory(
const char* manufacturer,
const char* modelName,
const char* description,
const char* version,
const char* uri,
const char* serialNumber)
{
unsigned char ioBuffer[2];
int devVersion;
int r;
r = libusb_control_transfer(
handle, //handle
0xC0, //bmRequestType
51, //bRequest
0, //wValue
0, //wIndex
ioBuffer, //data
2, //wLength
0 //timeout
);
if(r < 0)
{
return-1;
}
devVersion = ioBuffer[1] << 8 | ioBuffer[0];
fprintf(stdout,"Version Code Device: %d\n", devVersion);
sleep(1); //sometimes hangs on the next transfer :(
if ((libusb_control_transfer(handle,0x40,52,0,0,(unsigned char*)manufacturer,strlen(manufacturer)+1,0) < 0) ||
(libusb_control_transfer(handle,0x40,52,0,1,(unsigned char*)modelName,strlen(modelName)+1,0) < 0) ||
(libusb_control_transfer(handle,0x40,52,0,2,(unsigned char*)description,strlen(description)+1,0) < 0) ||
(libusb_control_transfer(handle,0x40,52,0,3,(unsigned char*)version,strlen(version)+1,0) < 0) ||
(libusb_control_transfer(handle,0x40,52,0,4,(unsigned char*)uri,strlen(uri)+1,0) < 0) ||
(libusb_control_transfer(handle,0x40,52,0,5,(unsigned char*)serialNumber,strlen(serialNumber)+1,0) < 0))
{
return -1;
}
fprintf(stdout,"Accessory Identification sent\n", devVersion);
r = libusb_control_transfer(handle,0x40,53,0,0,NULL,0,0);
if(r < 0)
{
return -1;
}
fprintf(stdout,"Attempted to put device into accessory mode\n", devVersion);
return 0;
}