无网不进  
软硬件开发

基于STM32的USB驱动程序设计,PC驱动程序,Android驱动程序源码一锅端

参考路径:http://www.embed-net.com/thread-94-1-1.html

本帖主要内容:
1,单片机为STM32F103,USB配置为Bulk传输,两个IN端点,两个OUT端点;
2,PC端基于libusb实现USB端点数据发送与接收,并封装成dll动态链接库;
3,PC端调用2封装的动态链接库实现USB端点的数据发送与接收;
4,Android端通过调用系统提供的USB函数,并再次封装为jar文件(类似于dll);
5,Android端调用4封装的jar文件实现USB端点的数据发送与接收;
以上内容源码毫无保留,完全奉献出来,若转载请注明出处,谢谢!
本文链接:http://www.embed-net.com/thread-94-1-1.html

1,STM32端的程序就不多说了,具体移植可以参考如下帖子:
http://www.embed-net.com/thread-18-1-1.html
主函数的功能也很简单,就是初始化配置USB和串口(用于打印一些调试信息),然后判断USB是否接收到数据,若接收到数据则将该数据原样返回。
具体代码如下:

[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int main(void)
{
        uint8_t data[256];
        uint32_t i=0;
        Set_System();//系统时钟初始化
        USART_Configuration();//串口1初始化
        printf("\x0c\0");printf("\x0c\0");//超级终端清屏
        printf("\033[1;40;32m");//设置超级终端背景为黑色,字符为绿色
        printf("\r\n*******************************************************************************");
        printf("\r\n************************ Copyright 2009-2012, EmbedNet ************************");
        printf("\r\n*************************** [url=http://www.embed-net.com]http://www.embed-net.com[/url] **************************");
        printf("\r\n***************************** All Rights Reserved *****************************");
        printf("\r\n*******************************************************************************");
        printf("\r\n");
 
        USB_Interrupts_Config();
        Set_USBClock();
        USB_Init();
 
        while(1)
        {
                if(EP1_ReceivedCount > 0){
                        USB_GetData(ENDP1,data,EP1_ReceivedCount);
                        USB_SendData(ENDP1,data,EP1_ReceivedCount);
                        printf("usb EP1 get data %d byte data\n\r",EP1_ReceivedCount);
                        for(i=0;i<EP1_ReceivedCount;i++){
                                printf("0x%02X ",data[i]);
                        }
                        printf("\n\r");
                        EP1_ReceivedCount=0;
                }
                if(EP2_ReceivedCount > 0){
                        USB_GetData(ENDP2,data,EP2_ReceivedCount);
                        USB_SendData(ENDP2,data,EP2_ReceivedCount);
                        printf("usb EP2 get data %d byte data\n\r",EP2_ReceivedCount);
                        for(i=0;i<EP2_ReceivedCount;i++){
                                printf("0x%02X ",data[i]);
                        }
                        printf("\n\r");
                        EP2_ReceivedCount=0;       
                }
        }
}


USB数据接收回调函数在usb_endp.c文件中,两个端点的接收函数如下:

[C] 纯文本查看 复制代码
01
02
03
04
05
06
void EP1_OUT_Callback(void)
{
        EP1_ReceivedCount = GetEPRxCount(ENDP1);
        PMAToUserBufferCopy(USB_Receive_Buffer, ENDP1_RXADDR, EP1_ReceivedCount);
        SetEPRxStatus(ENDP1, EP_RX_VALID);
}

 

[C] 纯文本查看 复制代码
01
02
03
04
05
06
void EP2_OUT_Callback(void)
{
        EP2_ReceivedCount = GetEPRxCount(ENDP2);
        PMAToUserBufferCopy(USB_Receive_Buffer, ENDP2_RXADDR, EP2_ReceivedCount);
        SetEPRxStatus(ENDP2, EP_RX_VALID);
}


运行PC端测试程序后,串口输出如下信息:
<ignore_js_op> 

2,PC端的USB驱动程序设计,主要是调用libusb的函数实现扫描设备,打开设备,端点读写,关闭设备等功能,其相关源码如下:

[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/**
  * @brief  查找指定的USB设备个数
  * @param  pBoard 设备句柄存放地址
  * @retval 识别到的指定设备个数
  */
static int scan_dev(struct usb_device *pBoard[])
{
    struct usb_bus *bus;
    struct usb_device *dev;
        int devnum=0,i=0;
    for (bus = usb_get_busses(); bus; bus = bus->next)
    {
        for (dev = bus->devices; dev; dev = dev->next)
        {
            if (dev->descriptor.idVendor == USB_VID
                    && dev->descriptor.idProduct == USB_PID)
            {
                                pBoard[devnum] = dev;
                                devnum++;
            }
        }
    }
        for(i=devnum;i<100;i++){
                pBoard[i] = NULL;
        }
    return devnum;
}
/**
  * @brief  扫描设备连接数
  * @param  NeedInit 是否需要初始化,第一次调用该函数需要初始化
  * @retval 识别到的指定设备个数
  */
int __stdcall USBScanDev(int NeedInit)
{
        if(NeedInit){
                usb_init(); /* initialize the library */
                usb_find_busses(); /* find all busses */
                usb_find_devices(); /* find all connected devices */
        }
        return scan_dev(pBoard);
}
 
/**
  * @brief  打开指定的USB设备
  * @param  devNum        需要打开的设备号
  * @param        pBoard        设备句柄存放地址
  * @retval 已经打开了的设备句柄
  */
static usb_dev_handle * open_dev(int devNum,struct usb_device *pBoard[])
{
    struct usb_bus *bus;
    struct usb_device *dev;
        int devnum=0;
    for (bus = usb_get_busses(); bus; bus = bus->next)
    {
        for (dev = bus->devices; dev; dev = dev->next)
        {
            if (dev->descriptor.idVendor == USB_VID
                    && dev->descriptor.idProduct == USB_PID)
            {
                if(devnum==devNum){
                                        return usb_open(pBoard[devNum]);
                                }
                                devnum++;
            }
        }
    }
    return NULL;
}
 
/**
  * @brief  打开指定的USB设备
  * @param  devNum        需要打开的设备号
  * @retval 打开状态
  */
int __stdcall USBOpenDev(int DevIndex)
{
        pBoardHandle[DevIndex] = open_dev(DevIndex,pBoard);
        if(pBoardHandle[DevIndex]==NULL){
                return SEVERITY_ERROR;
        }else{
                return SEVERITY_SUCCESS;
        }
}
/**
  * @brief  关闭指定的USB设备
  * @param  devNum        需要关闭的设备号
  * @param  pBoardHandle        开打了的设备句柄
  * @retval 已经打开了的设备句柄
  */
static int close_dev(int devNum,struct usb_dev_handle *pBoardHandle[])
{
    struct usb_bus *bus;
    struct usb_device *dev;
        int devnum=0;
    for (bus = usb_get_busses(); bus; bus = bus->next)
    {
        for (dev = bus->devices; dev; dev = dev->next)
        {
            if (dev->descriptor.idVendor == USB_VID
                    && dev->descriptor.idProduct == USB_PID)
            {
                if(devnum==devNum){
                                        return usb_close(pBoardHandle[devNum]);
                                }
                                devnum++;
            }
        }
    }
    return NULL;
}
 
/**
  * @brief  关闭指定的USB设备
  * @param  devNum        需要关闭的设备号
  * @retval 打开状态
  */
int __stdcall USBCloseDev(int DevIndex)
{
        return close_dev(DevIndex,pBoardHandle);
}
 
/*
* Read/Write using async transfer functions.
*
* NOTE: This function waits for the transfer to complete essentially making
* it a sync transfer function so it only serves as an example of how one might
* implement async transfers into thier own code.
*/
static int transfer_bulk_async(usb_dev_handle *dev,
                               int ep,
                               char *bytes,
                               int size,
                               int timeout)
{
    // Each async transfer requires it's own context. A transfer
    // context can be re-used.  When no longer needed they must be
    // freed with usb_free_async().
    //
    void* async_context = NULL;
    int ret;
 
    // Setup the async transfer.  This only needs to be done once
    // for multiple submit/reaps. (more below)
    //
    ret = usb_bulk_setup_async(dev, &async_context, ep);
    if (ret < 0)
    {
        //printf("error usb_bulk_setup_async:\n%s\n", usb_strerror());
        goto Done;
    }
 
    // Submit this transfer.  This function returns immediately and the
    // transfer is on it's way to the device.
    //
    ret = usb_submit_async(async_context, bytes, size);
    if (ret < 0)
    {
        //printf("error usb_submit_async:\n%s\n", usb_strerror());
        usb_free_async(&async_context);
        goto Done;
    }
 
    // Wait for the transfer to complete.  If it doesn't complete in the
    // specified time it is cancelled.  see also usb_reap_async_nocancel().
    //
    ret = usb_reap_async(async_context, timeout);
 
    // Free the context.
    usb_free_async(&async_context);
 
Done:
    return ret;
}
 
/**
  * @brief  USB Bulk端点写数据
  * @param  nBoardID 设备号
  * @param  pipenum 端点号
  * @param  sendbuffer 发送数据缓冲区
  * @param  len 发送数据字节数
  * @param  waittime 超时时间
  * @retval 成功发送的数据字节数
  */
 
int __stdcall USBBulkWriteData(unsigned int nBoardID,int pipenum,char *sendbuffer,int len,int waittime)
{
        int ret=0;
        if(pBoardHandle[nBoardID] == NULL){
                return SEVERITY_ERROR;
        }
#ifdef TEST_SET_CONFIGURATION
    if (usb_set_configuration(pBoardHandle[nBoardID], MY_CONFIG) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
 
#ifdef TEST_CLAIM_INTERFACE
    if (usb_claim_interface(pBoardHandle[nBoardID], 0) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
 
#if TEST_ASYNC
    // Running an async write test
    ret = transfer_bulk_async(dev, pipenum, sendbuffer, len, waittime);
#else
        ret = usb_bulk_write(pBoardHandle[nBoardID], pipenum, sendbuffer, len, waittime);
        /*if((len%64) == 0){
                usb_bulk_write(pBoardHandle[nBoardID], pipenum, sendbuffer, 0, waittime);
        }*/
#endif
#ifdef TEST_CLAIM_INTERFACE
    usb_release_interface(pBoardHandle[nBoardID], 0);
#endif
    return ret;
}
 
/**
  * @brief  USB interrupt端点写数据
  * @param  nBoardID 设备号
  * @param  pipenum 端点号
  * @param  sendbuffer 发送数据缓冲区
  * @param  len 发送数据字节数
  * @param  waittime 超时时间
  * @retval 成功发送的数据字节数
  */
int __stdcall USBIntWriteData(unsigned int nBoardID,int pipenum,char *sendbuffer,int len,int waittime)
{
        int ret=0;
        if(pBoardHandle[nBoardID] == NULL){
                return SEVERITY_ERROR;
        }
#ifdef TEST_SET_CONFIGURATION
    if (usb_set_configuration(pBoardHandle[nBoardID], MY_CONFIG) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
 
#ifdef TEST_CLAIM_INTERFACE
    if (usb_claim_interface(pBoardHandle[nBoardID], 0) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
        ret = usb_interrupt_write(pBoardHandle[nBoardID], pipenum, sendbuffer, len, waittime);
#ifdef TEST_CLAIM_INTERFACE
    usb_release_interface(pBoardHandle[nBoardID], 0);
#endif
    return ret;
}
 
/**
  * @brief  USB 控制端点写数据
  * @param  nBoardID 设备号
  * @param  pipenum 端点号
  * @param  sendbuffer 发送数据缓冲区
  * @param  len 发送数据字节数
  * @param  waittime 超时时间
  * @retval 成功发送的数据字节数
  */
int __stdcall USBCtrlData(unsigned int nBoardID,int requesttype,int request,int value, int index, char *bytes, int size,int waittime)
{
        int ret=0;
        if(pBoardHandle[nBoardID] == NULL){
                return SEVERITY_ERROR;
        }
#ifdef TEST_SET_CONFIGURATION
    if (usb_set_configuration(pBoardHandle[nBoardID], MY_CONFIG) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
 
#ifdef TEST_CLAIM_INTERFACE
    if (usb_claim_interface(pBoardHandle[nBoardID], 0) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
        ret = usb_control_msg(pBoardHandle[nBoardID], requesttype, request,value, index, bytes, size,waittime);
#ifdef TEST_CLAIM_INTERFACE
    usb_release_interface(pBoardHandle[nBoardID], 0);
#endif
    return ret;
}
 
/**
  * @brief  USB Bulk读数据
  * @param  nBoardID 设备号
  * @param  pipenum 端点号
  * @param  readbuffer 读取数据缓冲区
  * @param  len 读取数据字节数
  * @param  waittime 超时时间
  * @retval 读到的数据字节数
  */
int __stdcall USBBulkReadData(unsigned int nBoardID,int pipenum,char *readbuffer,int len,int waittime)
{
        int ret=0;
        if(pBoardHandle[nBoardID] == NULL){
                return SEVERITY_ERROR;
        }
#ifdef TEST_SET_CONFIGURATION
    if (usb_set_configuration(pBoardHandle[nBoardID], MY_CONFIG) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
 
#ifdef TEST_CLAIM_INTERFACE
    if (usb_claim_interface(pBoardHandle[nBoardID], 0) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
 
#if TEST_ASYNC
    // Running an async read test
    ret = transfer_bulk_async(pGinkgoBoardHandle[nBoardID], pipenum, sendbuffer, len, waittime);
#else
        ret = usb_bulk_read(pBoardHandle[nBoardID], pipenum, readbuffer, len, waittime);
#endif
#ifdef TEST_CLAIM_INTERFACE
    usb_release_interface(pBoardHandle[nBoardID], 0);
#endif
    return ret;
}
 
/**
  * @brief  USB interrupt读数据
  * @param  nBoardID 设备号
  * @param  pipenum 端点号
  * @param  readbuffer 读取数据缓冲区
  * @param  len 读取数据字节数
  * @param  waittime 超时时间
  * @retval 读到的数据字节数
  */
int __stdcall USBIntReadData(unsigned int nBoardID,int pipenum,char *readbuffer,int len,int waittime)
{
        int ret=0;
        if(pBoardHandle[nBoardID] == NULL){
                return SEVERITY_ERROR;
        }
#ifdef TEST_SET_CONFIGURATION
    if (usb_set_configuration(pGinkgoBoardHandle[nBoardID], MY_CONFIG) < 0)
    {
        usb_close(pGinkgoBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
 
#ifdef TEST_CLAIM_INTERFACE
    if (usb_claim_interface(pBoardHandle[nBoardID], 0) < 0)
    {
        usb_close(pBoardHandle[nBoardID]);
        return SEVERITY_ERROR;
    }
#endif
        ret = usb_interrupt_read(pBoardHandle[nBoardID], pipenum, readbuffer, len, waittime);
#ifdef TEST_CLAIM_INTERFACE
    usb_release_interface(pBoardHandle[nBoardID], 0);
#endif
    return ret;
}


以上程序包含了Bulk端点读写,Interrupt端点读写,Control端点读写,几个函数我都亲自测试过,不过也不敢保证没任何问题,大家在调试的时候若发现问题可以在这里反馈。
这套程序最后是生成USB_Driver.dll和USB_Driver.lib文件,测试程序导入这两个文件就可以调用里面封装的函数了,当然还要包含USB_Driver.h头文件。

3,PC端测试程序,这个程序功能相对简单,就是实现查找设备,打开设备,端点数据发送读取这样的功能,其源码如下:

[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#define        EP1_OUT_SIZE        64
#define        EP1_IN_SIZE        64
 
int _tmain(int argc, _TCHAR* argv[])
{
        int DevNum;
        int ret;
        char WriteTestData[256]={1,2,3,4,5,6,7,8,9};
        char ReadTestData[256]={0};
        for(int i=0;i<256;i++){
                WriteTestData[i] = i;
        }
        //扫描设备连接数,需要初始化
        DevNum = USBScanDev(1);
        printf("设备连接数为:%d\n",DevNum);
        //打开设备0
        ret = USBOpenDev(0);
        if(ret == SEVERITY_ERROR){
                printf("打开设备失败!\n");
                return SEVERITY_ERROR;
        }else{
                printf("打开设备成功!\n");
        }
 
        //端点1写数据
        ret = USBBulkWriteData(0,EP1_OUT,WriteTestData,EP1_OUT_SIZE,500);
        if(ret != EP1_OUT_SIZE){
                printf("端点1写数据失败!%d\n",ret);
                return SEVERITY_ERROR;
        }else{
                printf("端点1写数据成功!\n");
        }
        //端点1读数据
        ret = USBBulkReadData(0,EP1_IN,ReadTestData,EP1_IN_SIZE,500);
        if(ret != EP1_IN_SIZE){
                printf("端点1读数据失败!%d\n",ret);
                return SEVERITY_ERROR;
        }else{
                printf("端点1读数据成功!\n");
                for(int i=0;i<EP1_IN_SIZE;i++){
                        printf("%02X ",ReadTestData[i]);
                        if(((i+1)%16)==0){
                                printf("\n");
                        }
                }
                printf("\n");
        }
        Sleep(100);
        //端点2写数据
        ret = USBBulkWriteData(0,EP2_OUT,WriteTestData+64,64,500);
        if(ret != 64){
                printf("端点2写数据失败!%d\n",ret);
                return SEVERITY_ERROR;
        }else{
                printf("端点2写数据成功!\n");
        }
        //端点2读数据
        ret = USBBulkReadData(0,EP2_IN,ReadTestData,64,500);
        if(ret != 64){
                printf("端点2读数据失败!%d\n",ret);
                return SEVERITY_ERROR;
        }else{
                printf("端点2读数据成功!\n");
                for(int i=0;i<64;i++){
                        printf("%02X ",ReadTestData[i]);
                        if(((i+1)%16)==0){
                                printf("\n");
                        }
                }
                printf("\n");
        }
        getchar();
        return 0;
}


以上就是在PC端开发的相关程序,PC端测试程序输出为:
<ignore_js_op> 
下面介绍下在Android端的USB驱动程序开发。

4,和PC端程序开发一样,我们在Android端也先封装成一个库,封装后的文件为usb_driver.jar,开发平台我们采用官方提供的eclipse平台,其版本为adt-bundle-windows-x86-20140702
Android端封装的程序和PC端类似,也是扫描设备,打开设备,端点发送或者接收,其源码如下:

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package com.viewtool.USBDriver;
 
import java.util.HashMap;
import android.app.PendingIntent;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.util.Log;
 
 
public class UsbDriver{
        private UsbManager usbManager;
        private UsbDevice usbDevice;
        private UsbInterface usbInterface;
        private UsbEndpoint[] BulkInEndpoint = new UsbEndpoint[2];
        private UsbEndpoint[] BulkOutEndpoint = new UsbEndpoint[2];
        private UsbDeviceConnection connection;
        private PendingIntent pendingIntent;
        public UsbDriver(UsbManager usbManager,PendingIntent pendingIntent) {
                super();
                this.usbManager = usbManager;
                this.pendingIntent = pendingIntent;
        }
        /**
         * Scan Device
         * @return
         */
        public UsbDevice ScanDevices() {
                HashMap<String, UsbDevice> map = this.usbManager.getDeviceList();
                for(UsbDevice device : map.values()){
                        Log.e("device", "vid:"+device.getVendorId()+"   pid:"+device.getProductId()+"   "+device.getDeviceName());
                        if(0x1483 == device.getVendorId() && 0x5751 == device.getProductId()){
                                usbDevice = device;
                                System.out.println( "Start ScanDevices" ); 
                                usbManager.requestPermission(usbDevice, pendingIntent);
                                return usbDevice;
                        }
                }
                return null;
        }
        /**
         * Open Device
         * @return
         */
        public int OpenDevice(){
                this.usbInterface = usbDevice.getInterface(0);
                int i=0;
                int j=0;
                int k=0;
        for (i = 0; i < usbInterface.getEndpointCount(); i++) { 
            UsbEndpoint ep = usbInterface.getEndpoint(i); 
            // look for bulk endpoint
            if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                if (ep.getDirection() == UsbConstants.USB_DIR_OUT) { 
                        BulkOutEndpoint[j++] = ep;
                } else
                        BulkInEndpoint[k++] = ep; 
                
            }
        }
        if(((BulkOutEndpoint[0]==null)||(BulkInEndpoint[0]==null))&&(usbInterface.getEndpointCount()==1)){
                return ErrorType.ERR_OPEN_DEVICE;
        }
        if(((BulkOutEndpoint[1]==null)||(BulkInEndpoint[1]==null))&&(usbInterface.getEndpointCount()==2)){
                return ErrorType.ERR_OPEN_DEVICE;
        }
                //判断是否有权限
                if(usbManager.hasPermission(usbDevice)){
                        this.connection = usbManager.openDevice(usbDevice);
                        if(this.connection == null){
                                return ErrorType.ERR_OPEN_DEVICE;
                        }else{
                                this.connection.claimInterface(usbInterface, true);
                        }
                }else{
                        return  ErrorType.ERR_NO_PERMISSIONS;
                }
                return ErrorType.ERR_SUCCESS;
        }
        /**
         * Write data to USB
         * @param epNum Endpoint No.
         * @param writebuffer Write Data buffer
         * @param length Write Data Length
         * @param timeout Time Out
         * @return Write Data Length
         */
        public int USBWriteData(int epNum,byte[] writebuffer,int length,int timeout){
                int count = 0;
                if(epNum==BulkOutEndpoint[0].getEndpointNumber()){
                        count = connection.bulkTransfer(BulkOutEndpoint[0], writebuffer, length, timeout);
                        if((length%64)==0){
                                connection.bulkTransfer(BulkOutEndpoint[0], writebuffer, 0, timeout);
                        }
                        return count;
                }
                if(epNum==BulkOutEndpoint[1].getEndpointNumber()){
                        count = connection.bulkTransfer(BulkOutEndpoint[1], writebuffer, length, timeout);
                        if((length%64)==0){
                                connection.bulkTransfer(BulkOutEndpoint[0], writebuffer, 0, timeout);
                        }
                        return count;
                }
                return count;
        }
        /**
         * Read data From USB
         * @param epNum Endpoint No.
         * @param readbuffer Read Data Buffer
         * @param length Read data length
         * @param timeout Time out
         * @return Read data length
         */
        public int USBReadData(int epNum,byte[] readbuffer,int length,int timeout){
                if(epNum==(BulkInEndpoint[0].getEndpointNumber()|0x80)){
                        return connection.bulkTransfer(BulkInEndpoint[0], readbuffer, length, timeout);
                }
                if(epNum==(BulkInEndpoint[1].getEndpointNumber()|0x80)){
                        return connection.bulkTransfer(BulkInEndpoint[1], readbuffer, length, timeout);
                }
                return 0;
        }
}


代码应该容易理解,若有不理解的可以回帖提问,我会尽我所能进行解答。

5,Android端驱动写好后,下面我们来写个简单的测试程序测试下这个驱动,测试程序所做的事情和PC端的测试程序所做的功能一样,也是扫描设备,打开设备,端点数据发送接收,关闭设备。
在这里简单的介绍下几个关键的地方,完整代码在附件中可以下载
首先是new一个USBDriver的类,也就是我们第4步的类,在这里需要获取USB访问权限,具体效果就是在你运行这个软件,准备对USB进行操作的时候会弹出一个授权对话框,你选择允许即可,其源码如下:

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 配置usb
 */
private void config_usb() {
        // TODO Auto-generated method stub
        mUsbManager = (UsbManager) getSystemService(MainActivity.USB_SERVICE);
        pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(
                        ACTION_USB_PERMISSION), 0);
 
        mUsbDriver = new UsbDriver(mUsbManager, pendingIntent);
        mUsbDevice = mUsbDriver.ScanDevices();
 
        if (mUsbDevice != null) {
                mStringBuffer_Console_Text.append("Find device sucessful.\n");
                mTextView_ShowConsole.setText(mStringBuffer_Console_Text);
                run_set();
        } else {
                mStringBuffer_Console_Text.append("No device connected.\n");
                mTextView_ShowConsole.setText(mStringBuffer_Console_Text);
                return;
        }
        // run_set();
}


run_set()函数就是实现打开设备,端点数据发送和读取了,由于代码比较多,这里就不贴出来了,有兴趣的同学可以在附件下载源码。
Android端测试程序输出效果:
<ignore_js_op><ignore_js_op> 

基本介绍就到这里了,下面是源码大放送:
1,STM32F103上的单片机程序: <ignore_js_op> USB_DriverSTM32F103.rar (677.95 KB, 下载次数: 1240) 
2,PC端生成USB_Driver.dll文件的源码工程(vs2010): <ignore_js_op> USB_DriverBulk.rar (16.14 KB, 下载次数: 415, 售价: 10 金币) 
3,PC端测试程序源码下载(vs2010): <ignore_js_op> USB_DriverTestBulk.rar (279.46 KB, 下载次数: 578, 售价: 10 金币) 
4,Android端生成usb_driver.jar的工程及源码下载: <ignore_js_op> USB_DriverAndroid.rar (666.13 KB, 下载次数: 604, 售价: 10 金币) 
5,Android端测试程序源码下载: <ignore_js_op> USB_DriverTestAndroid.rar (1.36 MB, 下载次数: 1509, 售价: 10 金币) 
6,Android端编译生成的APK文件下载: <ignore_js_op> USB_DriverTestAndroidAPK.rar (264.23 KB, 下载次数: 810) 
7,PC端的USB驱动(inf文件,libusb工具生成): <ignore_js_op> USBDriver.rar (266.54 KB, 下载次数: 703) 
8,inf生成工具: <ignore_js_op> inf_tool.rar (778.26 KB, 下载次数: 683) 
9,libusb-win32下载: <ignore_js_op> libusb-win32-bin-1.2.6.0.rar (821.57 KB, 下载次数: 666) 

posted on 2018-01-10 11:14  无网不进  阅读(1072)  评论(0)    收藏  举报