// 自定义结构体类型
// 用于保存USB设备相关信息
struct usb_skel {
struct usb_device * udev; /* usb设备对象 */
struct usb_interface * interface; /* usb设备接口对象 */
struct semaphore limit_sem; /* 写信号量 */
unsigned char * bulk_in_buffer; /* 批量传输方式的接收缓存 */
size_t bulk_in_size; /* 接收缓存中的有效字节数 */
__u8 bulk_in_endpointAddr; /* 批量输入端口地址 */
__u8 bulk_out_endpointAddr; /* 批量输出端口地址 */
struct kref kref;
}dev;
// 以production ID和vendor ID组合匹配驱动程序
static struct usb_device_id skel_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* Terminating entry */
};
Static ssize_t skel_write(struct file * filep, const char * buff, size_t count, lof f_t * offp)
{
// 数据的发送方式可以选择urb方式和非urb方式
// urb方式将数据填充到一个urb中,然后发送urb给内核,内核再将数据送上USB总线// 非urb方式直接将数据发送给内核,而不填充urb结构
// 创建通讯管道
unsigned int pipe = usb_sndbulkpipe(dev.udevice, dev.bulk_out_endpointAddr);
/************************** urb 方式 *********************************/
// 创建一个urb(usb request block)
struct urb * usb_alloc_urb(0, // 等时包的数量,如果不是乘载等时包,应该为0
mem_flags);
// 填充urb
void usb_fill_bulk_urb(urb,
dev.udevice, // 目的USB设备指针
pipe, // 与USB设备通讯时使用的管道
buff, // 发送数据缓存
count,// 发送数据的字节数
skel_write_bulk_callback, // 数据发送结束后回调函数指针
void *context); // 由用户定义
// 发送urb,如果成功retval值为0,数据发送结束后可以通过urb->status查询状态retval = usb_submit_urb(urb, GFP_KERNEL);
/*************************** 非urb方式 ***************************/
Usinged int bytes_read;
retval = usb_bulk_msg(dev->udev,
pipe,
buff,
count,
&bytes_read,
10000);
}
// 设备文件操作结构
static struct file_operations skel_fops = {
.owner = THIS_MODULE,
.read = skel_read,
.write = skel_write,
.open = skel_open,
.release = skel_release,
};
static struct usb_class_driver skel_class = {
.name = "skel%d", // 设备驱动程序类名
.fops = &skel_fops, // 设备文件操作结构
.minor_base = USB_SKEL_MINOR_BASE, // 次设备号的基准值
};
skel_probe(usb_interface * interface, struct usb_device_id * device_id)
{
dev->udev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
// 本例程,probe函数查找端口中BULK_IN端点和BULK_OUT端点,
// 并将相关信息保存道dev变量中
iface_desc = interface->cur_altsetting; // 获取接口的当前配置
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
{
endpoint = &iface_desc->endpoint[i].desc;
// 如果这是一个BULK_IN端点
if ( !dev->bulk_in_endpointAddr &&
((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) = = USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) = = USB_ENDPOINT_XF ER_BULK))
{
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
dev->bulk_in_size = buffer_size;
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!dev->bulk_in_buffer) {
err("Could not allocate bulk_in_buffer");
goto error;
}
}
// 如果这是一个BULK_OUT端点
if (!dev->bulk_out_endpointAddr &&
((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)= =USB_DIR_OUT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)= = USB_ENDPOINT_X FER_BULK))
{
/* we found a bulk out endpoint */
dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
}
}
if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
err("Could not find both bulk-in and bulk-out endpoints");
goto error;
}
// 注册usb_class_driver结构,其中包含对USB设备的操作
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
等
retval = usb_register_dev(interface, &skel_class);
}
static struct usb_driver skel_driver = {
.name = "skeleton", //驱动程序名
.probe = skel_probe, // 函数指针,设备与skel_table匹配成功后被调用,
// 完成一些初始化工作
.disconnect = skel_disconnect,
.id_table = skel_table, // usb内核通过设备的production ID和vendor ID的组合
// 或者设备的class、subclass跟protocol的组合来识别设备
// skel_table用于匹配USB内核识别是否将此驱动程序作为已
// 识别设备的驱动程序。
};
static int __init usb_skel_init(void)
{
int result;
/* register this driver with the USB subsystem */
result = usb_register(&skel_driver);
if (result)
err("usb_register failed. Error number %d", result); return result;
}
static void __exit usb_skel_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&skel_driver);
}
module_init (usb_skel_init);
module_exit (usb_skel_exit);
MODULE_LICENSE("GPL");