参考:
libusb四种传输方式详细介绍可见http://blog.chinaunix.net/uid-25314474-id-3040231.html
Linux libusb USB开发(三)—— libusb函数库及接口函数介绍(https://blog.csdn.net/jiguangfan/article/details/86546958)
【USB笔记】端点描述符Endpoint Descriptor(https://blog.csdn.net/u012028275/article/details/109689169)
USB_4大描述符(https://blog.csdn.net/daocaokafei/article/details/114380506)
二,usb描述符-设备 配置 接口 端点(https://blog.csdn.net/u011456016/article/details/129464735)
发现初始化设备
// libusb 初始化,这一步必须首先执行。
usb_init();
// 寻找系统上的usb总线,任何usb设备都通过usb总线和计算机总线通信。
// 此函数返回总线数,失败返回负值。
usb_find_busses();
// 寻找总线上的usb设备,这个函数必要在调用usb_find_busses()后使用。
// 此函数成功返回设备数目,失败返回负值。
usb_find_devices();
struct usb_bus *pbus = nullptr;
struct usb_device *pdev;
struct usb_dev_handle *m_usbHandle;
// usb_get_busses返回全局变量 usb_busses,用于遍历总线链表,
// 查找总线 usb 设备。失败返回 NULL。
for (pbus = usb_get_busses();pbus != nullptr;pbus = pbus->next)
{
for (pdev = pbus->devices;pdev != nullptr;pdev = pdev->next)
{
if(dev->descriptor.idVendor==VENDOR_ID&& dev->descriptor.idProduct == PRODUCT_ID) {
// 这里可以添加设备的初始化代码
// 打开 usb 设备,引用的 usb_dev_handle 以及 usb_device 结构体分别为usb设备操作句柄
// 和usb设备描述符,具体定义可见头文件。函数返回 usb 设备的操作句柄,
// 之后的对该 usb 设备的操作都通过该句柄进行。
m_usbHandle = usb_open(m_usbDev);
// 复位指定的endpoint,参数ep 是指bEndpointAddress。这个函数用来替代usb_resetep函数。
usb_clear_halt(m_usbHandle, 0);
usb_clear_halt(m_usbHandle, 1);
usb_clear_halt(m_usbHandle, 2);
// 设置当前设备使用的configuration(配置模式),参数2configuration 是你要使用的
//configurtation descriptoes中bConfigurationValue, 函数返回0成功,<0失败
//(一个设备可能包含多个configuration,比如同时支持高速和低速的设备就有对应的
//两个configuration,详细可查看usb标准和具体的usb设备)
usb_set_configuration(m_usbHandle, 1);
// 注册与操作系统通信的接口,这个函数必须被调用,因为只有注册接口,
// 才能做相应的操作(比如收发数据)。第二个参数Interface 指 bInterfaceNumber.
// (下面介绍的usb_release_interface 与之相对应,也是必须调用的函数)
usb_claim_interface(m_usbHandle, 0);
usb_claim_interface(m_usbHandle, 1);
usb_claim_interface(m_usbHandle, 2);
// 保存&初始化通信端点
// config:配置描述符
// bNumInterfaces:配置所支持的接口个数, 表示有多少个接口描述符
for (int i = 0; i < m_usbDev->config->bNumInterfaces;i++)
{
// usb_interface:接口描述符
const struct usb_interface *interface = &(m_usbDev->config->interface[i]);
// num_altsetting:接口支持的端点数量 可选设置的数量
for (int j = 0; j < interface->num_altsetting; j++)
{
// 每一个端点具体操作
// usb_interface_descriptor :接口描述符
// altsetting包含所有可用于该接口的可选设置的接口结构数组。每个包含一套端点配置。这些接口结构没有特别的顺序。
const struct usb_interface_descriptor *altsetting = &(interface->altsetting[j]);
// bNumEndpoints要使用的端点个数(不包括端点0), 表示有多少个端点描述符,比如鼠标就只有一个端点
for (int k = 0; k < altsetting->bNumEndpoints; k++)
{
//usb_endpoint_descriptor 端点描述符对象
const struct usb_endpoint_descriptor *endpoint = &(altsetting->endpoint[k]);
// bInterfaceProtocol:接口所遵循的协议
//#define CTRL_EP_PROTOCOL 0
//#define EVENT_EP_PROTOCOL 1
//#define STREAM_EP_PROTOCOL 2
if (altsetting->bInterfaceProtocol == CTRL_EP_PROTOCOL)
{
// bInterfaceNumber:接口的编号
m_ctrlInterface = static_cast<int>(altsetting->bInterfaceNumber);
/*获取A的 bit N位的值*/
//#define GET_BIT(A,N) ((A >> N) & 0x1)
// bEndpointAddress端点编号,比如端点1,就是1
// bit0~3表示端点地址,bit8 表示方向,输入还是输出
if (GET_BIT(endpoint->bEndpointAddress, 7))
{
m_ctrlInEp = static_cast<int>(endpoint->bEndpointAddress);
}
else
{
m_ctrlOutEp = static_cast<int>(endpoint->bEndpointAddress);
}
}
else if (altsetting->bInterfaceProtocol == EVENT_EP_PROTOCOL)
{
m_eventInterface = static_cast<int>(altsetting->bInterfaceNumber);
m_eventEp = static_cast<int>(endpoint->bEndpointAddress);
}
else if (altsetting->bInterfaceProtocol == STREAM_EP_PROTOCOL)
{
m_streamInterface = static_cast<int>(altsetting->bInterfaceNumber);
m_streamEp = static_cast<int>(endpoint->bEndpointAddress);
}
}
}
// 记录所有设备id
// vecId.push_back(pdev->devnum);
break;
}
}
}
发送数据
int SendData(char* sendData, unsigned int length)
{
int rtn = 0;
for (int i = 0; i < 2; i++)
{
int rtn = usb_bulk_write(m_usbHandle, m_ctrlOutEp, sendData, length, 100);
if (rtn < 0)
{
usb_clear_halt(m_usbHandle, m_ctrlInterface);
rtn = ERR_TIME_OUT;
continue;
}
break;
}
return rtn;
}
接收数据
int RecvData(char* recvData, unsigned int length)
{
int rtn = 0;
for (int i = 0; i < 2; i++)
{
rtn = usb_bulk_read(m_usbHandle, m_ctrlInEp, recvData, length, 100);
if (rtn < 0)
{
usb_clear_halt(m_usbHandle, m_ctrlInterface);
rtn = ERR_TIME_OUT;
continue;
}
break;
}
return rtn;
}
关闭设备
bool CloseUsb()
{
if (m_usbHandle)
{
int rtn = usb_clear_halt(m_usbHandle, m_ctrlInEp);
rtn = usb_clear_halt(m_usbHandle, m_ctrlOutEp);
rtn = usb_clear_halt(m_usbHandle, m_eventEp);
rtn = usb_clear_halt(m_usbHandle, m_streamEp);
rtn = usb_release_interface(m_usbHandle, 0);
rtn = usb_release_interface(m_usbHandle, 1);
rtn = usb_release_interface(m_usbHandle, 2);
if (rtn < 0)
{
printf("%s:%d usb_release_interface failed with %d\n", __FILE__, __LINE__, rtn);
}
rtn = usb_close(m_usbHandle);
if (rtn < 0)
{
printf("%s:%d usb_close failed with %d\n", __FILE__, __LINE__, rtn);
return false;
}
m_usbHandle = nullptr;
return true;
}
return false;
}