📄 btusb.c
字号:
/* * Wipro Bluetooth HCI USB Transport Layer. * This file is part of the "Wipro Bluetooth USB Driver for Linux". * Copyright (C) 2001 Wipro Technologies. <www.wipro.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please forward any queries regarding the driver to * Nitant Kulkarni - Nitant.Kulkarni@wipro.com * Kamal K N - kamala.kodi@wipro.com * Burgupalli Chaitanya - Chaitanya.Burgupalli@wipro.com * Sadashivan Manicham - Sadashivan.Manickam@wipro.com * */ /* * NAME : btusb.c * * SYNOPSIS : (Functions exported * * EXPORTED FUNCTIONS : 1. btusb_init * 2. btusb_exit * 3. btusb_probe * 4. btusb_disconnect * 5. btusb_open * 6. btusb_close * 7. btusb_ioctl * 8. btusb_read * 9. btusb_write * * IMPORTED FUNCTIONS : 1. BTUSB_REGISTER_CHRDEV() * 2. BTUSB_UNREGISTER_CHRDEV() * 3. BTUSB_REGISTER_CLASS_DRIVER() * 4. BTUSB_UNREGISTER_CLASS_DRIVER() * 5. BTUSB_ALLOC_URB() * 6. BTUSB_SUBMIT_URB() * 7. BTUSB_UNLINK_URB() * 8. BTUSB_FREE_URB() * 9. BTUSB_MEM_ALLOC() * 10. BTUSB_MEM_FREE() * 11. BTUSB_RESOURCE_INIT_LOCK() * 12. BTUSB_RESOURCE_LOCK() * 13. BTUSB_RESOURCE_UNLOCK() * 14. BTUSB_RESOURCE_WAIT_FOR_UNLOCK() * * DESCRIPTION : This file contains Bluetooth USB transport layer * implementation for Linux OS. Its a kernel level * driver code in form of a lodable module. It * provides a 'file operation system call' based * interface for the Bluetooth host stack. It can * handle up to 16 Bluetooth host controllers * connected to the system. * * CAVEATS : (Known bugs and Unimplemented features) * None * * NOTES : (Notes for future enhancements) * BT USB transport layer can be ported with less * modification for unix flavour OS and which supports * standard file operations system calls. * * DESIGN LIMITATIONS : 1. Present driver support 16 bluetooth devices only. * 2. Data flow between bluetooth host and bluetooth * host controller is limited by the size of the * receive queue buffer. * * SEE ALSO : 1. btusb.h * 2. btusb_driver_dep.h * 3. btusb_os_dep.h * */#include "btusb.h"/* * PURPOSE * This function is called at initialization of class driver. * It registers class driver with USB host driver and * fileoperations with Linux kernel. * * PARAMETERS TO THE FUNCTION * None. * * RETURN VALUE * VALUE DESCRIPTION * SUCCESS if driver initialization was successful. * ERROR if driver initialization failed. * * GLOBAL PARAMETERS MODIFIED BY THE FUNCTION * btusb_devInfo_g */intbtusb_init(void){ int i; int status = 0; /* Intilize all the btusb structures to NULL */ for(i=0; i<MAX_BTDEV; i++) { btusb_devInfo_g[i] = NULL; }#ifdef BTUSB_DEBUG btusb_display_string("Registering file operations for btusb driver", DBG_INIT);#endif /* BTUSB_DEBUG */ /* * Register btusb as a character device driver with linux OS and return * ERROR on failure */ status = BTUSB_REGISTER_CHRDEV(BT_MAJOR, "bluetooth", &btusb_file_ops_g); if (status == ERROR) {#ifdef BTUSB_DEBUG btusb_display_string("Error - Registering file operations failed", DBG_INIT);#endif /* BTUSB_DEBUG */ return ERROR; } /* * Register bluetooth device with USB host driver and return ERROR on * failure */#ifdef BTUSB_DEBUG btusb_display_string("Registering class driver with USB", DBG_INIT);#endif /* BTUSB_DEBUG */ status = BTUSB_REGISTER_CLASS_DRIVER(&btusb_driverInfo_g); if (status == ERROR) {#ifdef BTUSB_DEBUG btusb_display_string("Error - Registring class driver failed", DBG_INIT);#endif /* BTUSB_DEBUG */ /* Unregister btusb as a character device driver with linux OS */ BTUSB_UNREGISTER_CHRDEV(BT_MAJOR, "bluetooth"); return ERROR; }#ifdef BTUSB_DEBUG btusb_display_string("Class driver initialized successfully", DBG_INIT);#endif /* BTUSB_DEBUG */ return SUCCESS;} /* end of btusb_init() *//* * PURPOSE * This function is called at unloading of driver. * It stops communication with all the BT host controllers connected, * claens up memory, releases all the URBs, unregisters class driver * and file operations. * * PARAMETERS TO THE FUNCTION * None. * * RETURN VALUE * VALUE DESCRIPTION * SUCCESS if cleanup was successful. * ERROR if driver cleanup failed. * * GLOBAL PARAMETERS MODIFIED BY THE FUNCTION * btusb_devInfo_g */voidbtusb_exit(void){ btusb_t *devStruct = NULL; int i; int status = 0;#ifdef BTUSB_DEBUG btusb_display_string("Closing all the opened devices", DBG_EXIT);#endif /* BTUSB_DEBUG */ /* * Reset the "device opened" flag in all btusb structures, so driver * standard file operations can't be performed */ for (i=0; i<MAX_BTDEV; i++) { devStruct = btusb_devInfo_g[i]; if (devStruct != NULL) { devStruct->devOpened = FALSE; } }#ifdef BTUSB_DEBUG btusb_display_string("Disconnecting all the connected devices", DBG_EXIT);#endif /* BTUSB_DEBUG */ /* call btusb_disconnect() for all the device connected */ for (i=0; i<MAX_BTDEV; i++) { devStruct = btusb_devInfo_g[i]; if (devStruct != NULL) { btusb_disconnect(devStruct->devDesc, (void *)devStruct); } }#ifdef BTUSB_DEBUG btusb_display_string("Unregistering class driver", DBG_EXIT);#endif /* BTUSB_DEBUG */ /* Unregister Bluetooth device with USB host driver */ BTUSB_UNREGISTER_CLASS_DRIVER(&btusb_driverInfo_g);#ifdef BTUSB_DEBUG btusb_display_string("Unregistering file operations", DBG_EXIT);#endif /* BTUSB_DEBUG */ /* * Unregister btusb as a character device driver with linux OS and on * failure try again unregistring */ /* wait till BTUSB_UNREGISTER_CHRDEV is success */ while ((status = BTUSB_UNREGISTER_CHRDEV(BT_MAJOR, "bluetooth")) != SUCCESS);#ifdef BTUSB_DEBUG btusb_display_string("Exiting btusb driver", DBG_EXIT);#endif /* BTUSB_DEBUG */ return ;} /* end of btusb_exit() *//* * PURPOSE * This function is registered with the USB host driver to be called on * device connection. It validates the device. If a valid BT host * controller is found, it creates a btusb_t struct for that device and * records all the endpoint information. * It allocates the necessary URBs and finally makes an entry of btusb_t * struct in btusb_devInfo_g array. * Note: this function is called for each interface (0 & 1). Interface 0 * supports control, bulk & interrupt endpoint and interface 1 will * support iso endpoint. Only one btusb_t struct is created for a device. * * PARAMETERS TO THE FUNCTION * TYPE VARIABLE DESCRIPTION * usb_device* dev Descriptor of the device that was disconnected. * unsigned int ifnum Interface number to which driver is to be * associated. * usb_device_id* id Bluetooth device class, subclass & protocol * parameters * * NOTE: The last parameter exists only in Linux 2.4.x kernel. * * RETURN VALUE * VALUE DESCRIPTION * Non NULL Pointer to associated btusb_t struct if a valid device * was found. * NULL If device was not a valid BT host controller. * * GLOBAL PARAMETERS MODIFIED BY THE FUNCTION * btusb_devInfo_g */#ifdef LINUX_2_4static void*btusb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)#else /* for Linux 2.2 lernel */static void*btusb_probe(struct usb_device *dev, unsigned int ifnum)#endif /* LINUX_2_4 */{ /* Pointer to bluetooth device interface */ struct usb_interface_descriptor *interface = NULL; /* Pointer to bluetooth device endpoint */ struct usb_endpoint_descriptor *endpoint = NULL; /* pointer to interrupt in endpoint */ struct usb_endpoint_descriptor *interrupt_in_endpoint = NULL; /* pointer to bulk in endpoint */ struct usb_endpoint_descriptor *bulk_in_endpoint = NULL; /* pointer to bulk out endpoint */ struct usb_endpoint_descriptor *bulk_out_endpoint = NULL; /* pointer to iso in endpoint */ struct usb_endpoint_descriptor *iso_in_endpoint = NULL; /* pointer iso out endpoint */ struct usb_endpoint_descriptor *iso_out_endpoint = NULL; /* control out endpoint */ int control_out_endpoint = 0; /* structure of btusb device info */ btusb_t *devStruct = NULL; int minor; int i; int num_interrupt_in = 0; /* counter to count no of interrupt in endpoint */ int num_bulk_in = 0; /* counter to count no of bulk in endpoint */ int num_bulk_out = 0; /* counter to count no of bulk out endpoint */ int num_iso_in = 0; /* counter to count no of iso in endpoint */ int num_iso_out = 0; /* counter to count no of iso out endpoint */ int status;#ifdef BTUSB_DEBUG btusb_display_string("USB device being probed !! ", DBG_PROBE);#endif /* BTUSB_DEBUG */ /* check connected device is valid Bluetooth device, if not return */ if ((dev->descriptor.bDeviceClass != WIRELESS_CLASS_CODE) || (dev->descriptor.bDeviceSubClass != RF_SUBCLASS_CODE)|| (dev->descriptor.bDeviceProtocol != BT_PROGRAMMING_PROTOCOL_CODE)) {#ifdef BTUSB_DEBUG btusb_display_string("Error - Not a valid Bluetooth device", DBG_PROBE);#endif /* BTUSB_DEBUG */ return NULL; }#ifdef BTUSB_DEBUG btusb_display_string("Found a valid Bluetooth device !!", DBG_PROBE);#endif /* BTUSB_DEBUG */ /* * If interface number is 0. find whether control in, bulk in. bulk out * and interrupt in end points are supported */ if (ifnum == 0) { /* assign device get descriptor interface value */ interface = &dev->actconfig->interface[ifnum].altsetting[0]; /* assign control out endpoint number (default 0) */ control_out_endpoint = interface->bInterfaceNumber; /* find the endpoints that we need */ for (i = 0; i < interface->bNumEndpoints; ++i) { endpoint = &interface->endpoint[i]; /* In endpoint == 0x80 & bulk attributes == 0x02 */ if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 0x03) == 0x02)) { /* we found a bulk in endpoint */ bulk_in_endpoint = endpoint; ++num_bulk_in; } /* Out endpoint == 0x00 & bulk attributes == 0x02 */ if (((endpoint->bEndpointAddress & 0x80) == 0x00) && ((endpoint->bmAttributes & 0x03) == 0x02)) { /* we found a bulk out endpoint */ bulk_out_endpoint = endpoint; ++num_bulk_out; } /* In endpoint == 0x80 & interrupt attributes == 0x03 */ if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 0x03) == 0x03)) { /* we found a interrupt in endpoint */ interrupt_in_endpoint = endpoint; ++num_interrupt_in; } } /* * If more then one bulk in, bulk out & interrupt endpoint is found * return ERROR */ if ((num_bulk_in != 1) || (num_bulk_out != 1) || (num_interrupt_in != 1)) {#ifdef BTUSB_DEBUG btusb_display_string("Error - Endpoint requirements are not met", DBG_PROBE);#endif /* BTUSB_DEBUG */ return NULL; } } /* * If interface number is 1. find whether iso in and iso out end points * are supported */ if (ifnum == 1) { interface = &dev->actconfig->interface[ifnum].altsetting[0]; for (i = 0; i < interface->bNumEndpoints; ++i) { endpoint = &interface->endpoint[i]; /* In endpoint == 0x80 & iso attributes == 0x01 */ if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 0x03) == 0x01)) { /* we found a iso in endpoint */ iso_in_endpoint = endpoint; ++num_iso_in; } /* Out endpoint == 0x00 & iso attributes == 0x01 */ if (((endpoint->bEndpointAddress & 0x80) == 0x00) && ((endpoint->bmAttributes & 0x03) == 0x01)) { /* we found a iso out endpoint */ iso_out_endpoint = endpoint; ++num_iso_out; } } /* If more then one iso in & iso out endpoint found return ERROR */ if ((num_iso_in != 1) || (num_iso_out != 1)) {#ifdef BTUSB_DEBUG btusb_display_string("Error - Endpoint requirements are not met", DBG_PROBE);#endif /* BTUSB_DEBUG */ return NULL; } }#ifdef BTUSB_DEBUG btusb_display_string("Endpoint requirements are met !!", DBG_PROBE);#endif /* BTUSB_DEBUG */ MOD_INC_USE_COUNT; /* Kernel maintenance count for modules */ /* check whether btusb struct already exsit or allocate new minor number */ for (minor = 0; minor < MAX_BTDEV; minor++) { if (btusb_devInfo_g[minor] == NULL) { break; } else { if (btusb_devInfo_g[minor]->devDesc == dev)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -