📄 btusb.c
字号:
* 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; } else { printk("%s (%d): Inside btusb_read(), " "failed to resubmit URB, usb_submit_urb() returned 0x%X.\n", __FILE__, __LINE__, status); }#endif /* 0 */ } }#endif /* MULTIPLE_BULK_IN_URBS */ if ((devStruct->iso_in_urbSubmitted == FALSE) && (devStruct->iso_in_EPMaxPktSize)) { tempUrb = devStruct->iso_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); numOfIsoPkts = (MAX_BT_PKT_SIZE + devStruct->iso_in_EPMaxPktSize - 1) / devStruct->iso_in_EPMaxPktSize; /* Set attributes of ISO frame descriptors */ for(i=0; i < numOfIsoPkts; i++) { tempUrb->iso_frame_desc[i].offset = i * devStruct->iso_in_EPMaxPktSize; tempUrb->iso_frame_desc[i].length = devStruct->iso_in_EPMaxPktSize; tempUrb->iso_frame_desc[i].status = 0; tempUrb->iso_frame_desc[i].actual_length = 0; } } } /* * If transfer buffer exists, submit URB. Set URB submitted flag on * success */ if (tempUrb->transfer_buffer != NULL) {#ifdef BTUSB_DEBUG btusb_display_string("submit sio URB", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ if (BTUSB_SUBMIT_URB(tempUrb) == SUCCESS) { isoInUrbSubmitted = TRUE; } } } } /* if any URBs were submitted, update the btusb_t struct */ if ((intInUrbSubmitted == TRUE) || (bulkInUrbSubmitted == TRUE) || (isoInUrbSubmitted == TRUE)) { /* * Lock the device info struct before updating pending URB count and * URB submitted flags */ BTUSB_RESOURCE_WAIT_FOR_UNLOCK(&devStruct->lock); BTUSB_RESOURCE_LOCK(&devStruct->lock, flags); if (intInUrbSubmitted == TRUE) {#ifdef BTUSB_DEBUG btusb_display_string("submitted interrupt URB", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ devStruct->interrupt_in_urbSubmitted = TRUE; devStruct->pending_inURBs ++; } if (bulkInUrbSubmitted == TRUE) {#ifdef BTUSB_DEBUG btusb_display_string("submitted bulk URB", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ devStruct->bulk_in_urbSubmitted = TRUE; devStruct->pending_inURBs ++; } if (isoInUrbSubmitted == TRUE) {#ifdef BTUSB_DEBUG btusb_display_string("submitted iso URB", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ devStruct->iso_in_urbSubmitted = TRUE; devStruct->pending_inURBs ++; } /* Unlock the device info structure */ BTUSB_RESOURCE_UNLOCK(&devStruct->lock, flags); } return retVal;} /* End of btusb_read *//* * PURPOSE * This function is registered as WRITE file operation function for btusb * device. If device is opened for communication, it sends a packet to the * BT host controller through appropriate USB pipe. * * PARAMETERS TO THE FUNCTION * TYPE VARIABLE DESCRIPTION * file* file_p Valid file structure * char* buf_p user buffer containing data to be sent * size_t count Length of data in buffer * loff_t* pos_p Offset. Always ignored. * * RETURN VALUE * VALUE DESCRIPTION * count If packet was sent successfully. * FLOW_BLOCKED If not able to get or submit URB. * NO_MEM If error in memory allocation. * ERROR If device does not exist. * * GLOBAL PARAMETERS MODIFIED BY THE FUNCTION * None. */static ssize_tbtusb_write(struct file *file_p, const char *buf_p, size_t count, loff_t *pos_p){ btusb_t *devStruct = NULL; uint8 type; uint8 *transferBuf = NULL; int urbPoolIndex = MAX_ISO_OUT_URBS; urb_t *outurb = NULL; unsigned int numOfIsoPkts = 0; unsigned int i; devrequest *btCmdRequest = NULL; unsigned long flags;#ifdef URB_QUEUEING_SUPPORT int urbPoolIndex_forZeroLength = MAX_ISO_OUT_URBS; bool urbSubmitted = TRUE;#endif /* URB_QUEUEING_SUPPORT */ /* 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("write - 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("write - Device error", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } /* Determine type of data. If invalid type, return ERROR */ type = *buf_p; if ((type != ACL_TYPE) && (type != SCO_TYPE) && (type != COMMAND_TYPE)) {#ifdef BTUSB_DEBUG btusb_display_string("write - Device error", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } /* If type of data is SCO and SCO type is not supported, return ERROR */ if ((type == SCO_TYPE) && (devStruct->iso_out_EPMaxPktSize == 0)) {#ifdef BTUSB_DEBUG btusb_display_string("write - Device error, Isochronous not supported", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return ERROR; } /* Allocate transfer buffer. If allocation failed, return NO_MEM */ if ((transferBuf = BTUSB_MEM_ALLOC((count-1))) == NULL) {#ifdef BTUSB_DEBUG btusb_display_string("write - Out of memory", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return NO_MEM; } /* * Find a free URB corresponding to the type, fill it and submit it. * If error in finding free URB or in submission, return FLOW_BLOCKED. */ if (type == SCO_TYPE) { /* Request type is SCO */ /* Check if ISO URB pool can hold one more URB */ urbPoolIndex = MAX_ISO_OUT_URBS; for(i=0;i<MAX_ISO_OUT_URBS;i++) { if (devStruct->iso_out_urb_pool[i] != NULL) { urbPoolIndex = i; break; } } if (urbPoolIndex == MAX_ISO_OUT_URBS) { /* URB pool is full. Release transfer buffer and return FLOW_BLOCKED */ if(transferBuf!=NULL) { BTUSB_MEM_FREE(transferBuf); transferBuf=NULL; }#ifdef BTUSB_DEBUG btusb_display_string("write - No free URBs", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return FLOW_BLOCKED; } /* URB pool can hold one more URB. Allocate URB as per request size */ numOfIsoPkts = (count + devStruct->iso_out_EPMaxPktSize - 1) / devStruct->iso_out_EPMaxPktSize; outurb = BTUSB_ALLOC_URB(numOfIsoPkts); if (outurb == NULL) { /* * URB allocation failed. Release transfer buffer and * return FLOW_BLOCKED */ if(transferBuf!=NULL) { BTUSB_MEM_FREE(transferBuf); transferBuf=NULL; }#ifdef BTUSB_DEBUG btusb_display_string("write - No free URBs", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return FLOW_BLOCKED; } /* Copy data from user memory to the transfer buffer in kernel memory */ copy_from_user(transferBuf, (buf_p+1), (count - 1)); /* Fill URB */ BT_FILL_ISO_OUT_URB(outurb, devStruct, transferBuf, (count - 1), numOfIsoPkts); /* Set attributes of ISO frame descriptors */ for (i = 0; i < numOfIsoPkts; i++) { outurb->iso_frame_desc[i].offset = i * devStruct->iso_in_EPMaxPktSize; outurb->iso_frame_desc[i].length = devStruct->iso_in_EPMaxPktSize; outurb->iso_frame_desc[i].status = 0; outurb->iso_frame_desc[i].actual_length = 0; } } else { /* Request type is not SCO */ /* Check if WRITE URB pool can hold one more URB */ urbPoolIndex = MAX_WRITE_URBS; for (i=0; i < MAX_WRITE_URBS; i++) { if (devStruct->write_urb_pool[i]->context == NULL) { urbPoolIndex = i; break; } }#ifdef URB_QUEUEING_SUPPORT /* * Check whether a zero length packet should be send for a * Bulk OUT Transfer. * * NOTE: The 'count' parameter also includes the packet qualifier which * is not sent on the bus. */ if (type == ACL_TYPE) { if (((count - 1) % devStruct->bulk_out_EPMaxPktSize) == 0) { /* * Check whether an additional URB is available in the pool of * write URBs */ for (i = 0; i < MAX_WRITE_URBS; i++) { if (devStruct->write_urb_pool[i]->context == NULL) { if (i != urbPoolIndex) { urbPoolIndex_forZeroLength = i; break; } } } /* Check whether an additional URB is available */ if (urbPoolIndex_forZeroLength == MAX_WRITE_URBS) { /* Check whether memory was allocated for the transfer buffer */ if (transferBuf != NULL) { /* Free the memory allocated for the transfer buffer */ BTUSB_MEM_FREE(transferBuf); transferBuf = NULL; } /* Return FLOW_BLOCKED, as the URB's cannot be submitted */ return FLOW_BLOCKED; } } }#endif /* URB_QUEUEING_SUPPORT */ /* URB pool is full. Release transfer buffer and return FLOW_BLOCKED */ if ((urbPoolIndex == MAX_WRITE_URBS) && (transferBuf!=NULL)) { BTUSB_MEM_FREE(transferBuf); transferBuf=NULL;#ifdef BTUSB_DEBUG btusb_display_string("write - No free URBs", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return FLOW_BLOCKED; } /* For COMMAND out request, allocate and fill setup packet */ if (type == COMMAND_TYPE) { if ((btCmdRequest = BTUSB_MEM_ALLOC(sizeof(devrequest)))==NULL) { /* * Cannot allocate memory for setup packet. Free transfer buffer * and return NO_MEM */ if(transferBuf!=NULL) { BTUSB_MEM_FREE(transferBuf); transferBuf=NULL; }#ifdef BTUSB_DEBUG btusb_display_string("write - No free URBs", DBG_FILEOPS);#endif /* BTUSB_DEBUG */ return NO_MEM; } /* * Control URB needs setup packet. * Fill setup packet with Bluetooth request */ btCmdRequest->requesttype = BLUETOOTH_CONTROL_REQUEST_TYPE; btCmdRequest->request = 0x00; btCmdRequest->value = 0x00; btCmdRequest->index = (uint16)0x0000; btCmdRequest->length = (uint16)(count - 1); } /* Get urb from WRITE URB pool */ outurb = devStruct->write_urb_pool[urbPoolIndex]; /* Copy data from user memory to the transfer buffer in kernel memory */ copy_from_user(transferBuf, (buf_p+1), (count - 1)); /* Fill URB */ if (type == ACL_TYPE) { BT_FILL_BULK_OUT_URB(outurb, devStruct, transferBuf, (count-1));#ifdef URB_QUEUEING_SUPPORT /* Populate the Zero length Bulk OUT URB, if required */ if (type == ACL_TYPE) { if (((count - 1) % devStruct->bulk_out_EPMaxPktSize) == 0) { BT_FILL_BULK_OUT_URB( devStruct->write_urb_pool[urbPoolIndex_forZeroLength], devStruct, NULL, /* Transfer buffer */ 0 /* Transfer Length */); } }#endif /* URB_QUEUEING_SUPPORT */ } else { BT_FILL_CONTROL_OUT_URB(outurb, (unsigned char *)btCmdRequest, devStruct, transferBuf, (count-1)); } } /* * Submit URB. If URB submission failed, clean up memory and return * FLOW_BLOCKED. If URB submission succeeded, return 'count' to indicate * that data was sent. */ if (BTUSB_SUBMIT_URB(outurb) != 0) { /* URB submission failed. Clean up memory and return FLOW_BLOCKED */ if (type == SCO_TYPE) { BTUSB_MEM_FREE(transferBuf); BTUSB_FREE_URB(outurb); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -