我一直在将自定义供应商类USB驱动程序从WINCE 6.0移植到Linux内核,以用于自定义Android设备 . 此驱动程序具有批量 endpoints ,用于将数据传输到文件 . 请不要向我解释这是一个坏主意 . 我理解这一点 . 在我的bulkout_complete函数中,我将数据复制到写缓冲区,然后调用queue_work来安排工作队列将数据写入文件 . 为了确保主机在写入完成之前不能再次发送数据,我有一个写入状态变量,它被清除为工作队列函数中的最后一个操作 . 主机驱动程序在控制 endpoints 上调用特定于供应商的请求以监视该变量的状态 . 清除变量后,主机会将下一个数据包发送到批量 endpoints . 问题是即使变量已清除,下一次调用queue_work将返回零值,这似乎表明工作已在进行中 .
从我的头文件:
u8 mWriteBuffer[4096];
u32 mWriteLength;
static bool mWriteActive = false;
#define USB_WORKQUEUE_NAME "wqusb"
static struct workqueue_struct *wqUSB;
static struct work_struct writeFile_work;
DECLARE_WORK(writeFile_work,file_write_handler);
创建和清理工作队列
static int __init init(void)
{
wqUSB = create_workqueue(USB_WORKQUEUE_NAME);
// other init stuff
}
static void __exit cleanup(void)
{
flush_workqueue(wqUSB);
destroy_workqueue(wqUSB);
//other cleanup stuff
}
批量 endpoints 代码
static void bulkout_complete(struct usb_ep *ep, struct usb_request *req)
{
struct usb_composite_dev *cdev;
struct f_myusb *ss = ep->driver_data;
int status = req->status;
cdev = ss->function.config->cdev;
switch (status)
{
case 0: /* normal completion? */
mWriteLength = (u32)req->length;
memcpy(mWriteBuffer,(u8*)req->buf,req->length);
mWriteActive = true;
if(queue_work(wqUSB,&writeFile_work)==0)
{
printk(KERN_INFO "[USB DRIVER] - failed to queuework \n");
}
break;
/* this endpoint is normally active while we're configured */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status,
req->actual, req->length);
free_ep_req(ep, req);
return;
case -EOVERFLOW: /* buffer overrun on read means that
* we didn't provide a big enough
* buffer.
*/
default:
#if 1
DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
status, req->actual, req->length);
#endif
case -EREMOTEIO: /* short read */
break;
}
status = usb_ep_queue(ep, req, GFP_ATOMIC);
if (status) {
ERROR(cdev, "kill %s: resubmit %d bytes --> %d\n",
ep->name, req->length, status);
usb_ep_set_halt(ep);
}
}
写入数据的workqueue函数
void file_write_handler(struct work_struct *pwork)
{
write_file(mWriteBuffer,mWriteLength);
mWriteActive = false;
}