📄 btusb.c
字号:
}/* * PURPOSE * Function registered as CLOSE file operation function for btusb device. * It stops all communication witht he device and cleans up * btusb_t structure associated with the device. * * PARAMETERS TO THE FUNCTION * TYPE VARIABLE DESCRIPTION * inode* inode_p Inode struct corresponding to btusb device. * file* file_p Valid file structure of btusb device. * * RETURN VALUE * VALUE DESCRIPTION * SUCCESS If closing the device was successful. * ERROR If error in closing the device. * * GLOBAL PARAMETERS MODIFIED BY THE FUNCTION * None. */static intbtusb_close(struct inode *inode_p, struct file *file_p){ btusb_t *devStruct = NULL; unsigned long flags;#ifdef BTUSB_DEBUG btusb_display_string("close - Closing device file", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ /* if btusb_t struct for minor number is not found, return ERROR */ devStruct = (btusb_t *)file_p->private_data; if (devStruct == NULL) {#ifdef BTUSB_DEBUG btusb_display_string("close - Error! Invalid file descriptor", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } if (btusb_devInfo_g[devStruct->minorNumber] != devStruct) {#ifdef BTUSB_DEBUG btusb_display_string("close - Error! devStruct mismatch", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } /* if device is not opened, return ERROR */ if (devStruct->devOpened == FALSE) {#ifdef BTUSB_DEBUG btusb_display_string("close - Device already closed", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return SUCCESS; }#ifdef BTUSB_DEBUG btusb_display_string("close - DEvice is open. Need to close", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ /* Lock the btusb_t struct, reset devOpened flag and unlock it */ BTUSB_RESOURCE_WAIT_FOR_UNLOCK(&devStruct->lock); BTUSB_RESOURCE_LOCK(&devStruct->lock, flags); devStruct->devOpened = FALSE; devStruct->devFile->private_data = NULL; devStruct->devFile = NULL; BTUSB_RESOURCE_UNLOCK(&devStruct->lock, flags);#ifdef BTUSB_DEBUG btusb_display_string("close - Unlinking submitted URBs", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ /* Unlink all the submitted URBs of this device */ btusb_unlink_urbs(devStruct);#ifdef BTUSB_DEBUG btusb_display_string("close - Cleaning up receive data queue", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ /* Clean up the receive-data_queue and reset its parameters to defaults */ btusb_cleanup_queue(&devStruct->recvQueue);#ifdef BTUSB_DEBUG btusb_display_string("close - Device closed", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return SUCCESS;}/* * PURPOSE * Function registered as IOCTL file operation function for btusb device. * Currently it supports a single command to set max-queue-length of a * receive-data-queue. Command is 0x01. * * PARAMETERS TO THE FUNCTION * TYPE VARIABLE DESCRIPTION * inode* inode_p Inode struct corresponding to btusb device. * file* file_p Valid file structure of btusb device. * unsigned int cmd ioctl command. 0x01 for set max queue length. * unsigned long arg Argument of command. * * RETURN VALUE * VALUE DESCRIPTION * SUCCESS If command was successful. * ERROR If command failed. * * GLOBAL PARAMETERS MODIFIED BY THE FUNCTION * None. */static intbtusb_ioctl(struct inode *inode_p, struct file *file_p, unsigned int cmd, unsigned long arg){ btusb_t *devStruct = NULL; unsigned long flags; int retVal = ERROR; /* Get devStruct from file_p. If NULL, return ERROR */ devStruct = (btusb_t *)file_p->private_data; if (devStruct == NULL) {#ifdef BTUSB_DEBUG btusb_display_string("ioctl - Command failed", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } /* If device is not opened, return ERROR */ if (devStruct->devOpened == FALSE) {#ifdef BTUSB_DEBUG btusb_display_string("ioctl - Command failed", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } switch(cmd) { case 0x01: /* set max queue length command */ /* * Update max-queue-length only if value is within * MAX_PENDING_IN_URBS to 255 */ if ((arg >= MAX_PENDING_IN_URBS) && (arg < 256)) { BTUSB_RESOURCE_WAIT_FOR_UNLOCK(&devStruct->lock); BTUSB_RESOURCE_LOCK(&devStruct->lock, flags); devStruct->recvQueue.maxLength = arg; BTUSB_RESOURCE_UNLOCK(&devStruct->lock, flags); retVal = SUCCESS; } break; default: /* Return error if command is not supported */ retVal = ERROR; break; } if (retVal == ERROR) {#ifdef BTUSB_DEBUG btusb_display_string("ioctl - Command failed", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ } else {#ifdef BTUSB_DEBUG btusb_display_string("ioctl - Command success", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ } return retVal;} /* End of btusb_ioctl *//* * PURPOSE * Function registered as READ file operation function for btusb device. * If device is opened for communication, it returns a data chunk got * from device specific receive-data-queue. * This function also takes care of re-submitting IN URBs where were * not submitted. * * PARAMETERS TO THE FUNCTION * TYPE VARIABLE DESCRIPTION * file* file_p Valid file structure. * char* buf_p user buffer to hold received data. * size_t count Length of data to be read. Always MAX_BT_PKT_SIZE. * loff_t* pos_p Offset. Always ignored. * * RETURN VALUE * VALUE DESCRIPTION * Actual length Length of data chunk including type if data is being * returned. * NO_DATA If device receive-data-queue was empty. * ERROR If device does not exist. * * GLOBAL PARAMETERS MODIFIED BY THE FUNCTION * None. */static ssize_tbtusb_read(struct file *file_p, char *buf_p, size_t count, loff_t *pos_p){ btusb_t *devStruct = NULL; unsigned long flags; node_t *nodeFromQueue = NULL; int16 spaceInQueue = 0; urb_t *tempUrb = NULL; uint8 *transferBuf = NULL; unsigned int numOfIsoPkts = 0; unsigned int i; ssize_t retVal = ERROR; bool bulkInUrbSubmitted = FALSE; bool isoInUrbSubmitted = FALSE; bool intInUrbSubmitted = FALSE; int status; /* Get devStruct from file_p.If NULL, return ERROR*/ devStruct = (btusb_t *)file_p->private_data; if (devStruct == NULL) {#ifdef BTUSB_DEBUG btusb_display_string("read - Device error", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } /* If device is not opened, return ERROR */ if (devStruct->devOpened == FALSE) {#ifdef BTUSB_DEBUG btusb_display_string("read - Device error", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } /* If requested data length is not MAX_BT_PKT_SIZE, return ERROR */ if (count != MAX_BT_PKT_SIZE) {#ifdef BTUSB_DEBUG btusb_display_string("read - Request data length is not MAX_BT_PKT_SIZE", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } /* Lock the btusb_t struct, get a node from its receive-data-queue and unlock it */ BTUSB_RESOURCE_WAIT_FOR_UNLOCK(&devStruct->lock); BTUSB_RESOURCE_LOCK(&devStruct->lock, flags); nodeFromQueue = btusb_getNodeFromQueue(&devStruct->recvQueue); spaceInQueue = devStruct->recvQueue.maxLength - devStruct->recvQueue.currentLength; BTUSB_RESOURCE_UNLOCK(&devStruct->lock, flags); /* If node from queue was not NULL, copy type and data to user buffer */ if (nodeFromQueue != NULL) { switch (nodeFromQueue->type) { case INTERRUPT_TYPE: *buf_p = EVENT_TYPE; break; case BULK_TYPE: *buf_p = ACL_TYPE; break; case ISO_TYPE: *buf_p = SCO_TYPE; break; default: *buf_p = EVENT_TYPE; break; } copy_to_user((buf_p+1),nodeFromQueue->buf,nodeFromQueue->length); /* set return value to length of data along with type being returned */ retVal = nodeFromQueue->length + 1; BTUSB_MEM_FREE(nodeFromQueue); nodeFromQueue=NULL;#ifdef BTUSB_DEBUG btusb_display_string("read - Got data", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ } else { /* set retrun value to NO_DATA */ retVal = NO_DATA;#ifdef BTUSB_DEBUG btusb_display_string("Read - No data", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ } /* * if space in queue >= MAX_PENDING_IN_URBS, submit IN URBs which were * not submitted */ if (spaceInQueue >= MAX_PENDING_IN_URBS) { /* Submit interrupt-in URB if it was not submitted */ if (devStruct->interrupt_in_urbSubmitted == FALSE) { tempUrb = devStruct->interrupt_in_urb; /* Allocate transfer buffer if it was not allocated */ if (tempUrb->transfer_buffer == NULL) { transferBuf = BTUSB_MEM_ALLOC((sizeof(node_t) + MAX_BT_PKT_SIZE)); if (transferBuf != NULL) { tempUrb->transfer_buffer = transferBuf + sizeof(node_t); } } /* * If transfer buffer exists, submit URB. Set URB submitted flag on * success */ if (tempUrb->transfer_buffer != NULL) { if (BTUSB_SUBMIT_URB(tempUrb) == SUCCESS) { intInUrbSubmitted = TRUE; }#ifdef BTUSB_DEBUG btusb_display_string("submit interrupt URB", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ } } /* Submit bulk-in URB if it was not submitted */#ifdef MULTIPLE_BULK_IN_URBS if ((devStruct->bulk_in_urbSubmitted == FALSE) || (devStruct->pending_bulk_in_urbs < MAX_PENDING_BULK_IN_URBS)) { /* To hold the URB available */ int nURBAvailable = MAX_PENDING_BULK_IN_URBS; /* Locate the URB which is available */ for (i = 0; i < MAX_PENDING_BULK_IN_URBS; i++) { if (devStruct->bulk_in_urb_submitted[i] == FALSE) { nURBAvailable = i; } } /* Check whether an URB is avaiable */#ifdef BTUSB_DEBUG if (nURBAvailable == MAX_PENDING_BULK_IN_URBS) { printk("%s (%d): Inside btusb_read(), no BULK IN URB available.\n", __FILE__, __LINE__); return ERROR; }#endif /* BTUSB_DEBUG */ tempUrb = devStruct->bulk_in_urb[nURBAvailable]; /* Allocate transfer buffer if it was not allocated */ if (tempUrb->transfer_buffer == NULL) { transferBuf = BTUSB_MEM_ALLOC((sizeof(node_t) + MAX_BT_PKT_SIZE)); if (transferBuf != NULL) { tempUrb->transfer_buffer = transferBuf + sizeof(node_t); } } /* * If transfer buffer exists, submit URB. Set URB submitted flag on * success */ if (tempUrb->transfer_buffer != NULL) {#ifdef BTUSB_DEBUG btusb_display_string("submit bulk URB", DBG_FILEOPS);#endif /* BTUSB_DEBUG */#if 0 if (BTUSB_SUBMIT_URB(tempUrb) == SUCCESS) { bulkInUrbSubmitted = TRUE; }#else#ifdef LINUX_2_4 BT_FILL_BULK_IN_URB(tempUrb, devStruct, tempUrb->transfer_buffer, MAX_BT_PKT_SIZE);#endif /* LINUX_2_4 */ if ((status = BTUSB_SUBMIT_URB(tempUrb)) == SUCCESS) { bulkInUrbSubmitted = TRUE; /* Increment the number of bulk in urbs pending */ devStruct->pending_bulk_in_urbs++; /* Set the urb flag as submitted */ devStruct->bulk_in_urb_submitted[nURBAvailable] = TRUE; } else { printk("%s (%d): Inside btusb_read(), " "failed to resubmit URB, usb_submit_urb() returned 0x%X.\n", __FILE__, __LINE__, status); }#endif /* 0 */ } }#else /* MULTIPLE_BULK_IN_URBS */ if (devStruct->bulk_in_urbSubmitted == FALSE) { tempUrb = devStruct->bulk_in_urb; /* Allocate transfer buffer if it was not allocated */ if (tempUrb->transfer_buffer == NULL) { transferBuf = BTUSB_MEM_ALLOC((sizeof(node_t) + MAX_BT_PKT_SIZE)); if (transferBuf != NULL) { tempUrb->transfer_buffer = transferBuf + sizeof(node_t); } } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -