📄 usbmouselib.c
字号:
* attached or removed. <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.* Mice generally report their class information at the interface level,* so <configuration> and <interface> will indicate the configuratin/interface* that reports itself as a mouse. Finally, <deviceClass>, <deviceSubClass>,* and <deviceProtocol> will identify a HID/BOOT/KEYBOARD device.** NOTE: The USBD will invoke this function once for each configuration/* interface which reports itself as a mouse. So, it is possible that* a single device insertion/removal may trigger multiple callbacks. We* ignore all callbacks except the first for a given device.** RETURNS: N/A*/LOCAL VOID usbMouseAttachCallback ( USBD_NODE_ID nodeId, UINT16 attachAction, UINT16 configuration, UINT16 interface, UINT16 deviceClass, UINT16 deviceSubClass, UINT16 deviceProtocol ) { pUSB_MSE_SIO_CHAN pSioChan; OSS_MUTEX_TAKE (mseMutex, OSS_BLOCK); /* Depending on the attach code, add a new mouse or disabled one * that's already been created. */ switch (attachAction) { case USBD_DYNA_ATTACH: /* A new device is being attached. Check if we already * have a structure for this device. */ if (findSioChan (nodeId) != NULL) break; /* Create a new structure to manage this device. If there's * an error, there's nothing we can do about it, so skip the * device and return immediately. */ if ((pSioChan = createSioChan (nodeId, configuration, interface)) == NULL) break; /* Notify registered callers that a new mouse has been * added and a new channel created. */ notifyAttach (pSioChan, USB_MSE_ATTACH); break; case USBD_DYNA_REMOVE: /* A device is being detached. Check if we have any * structures to manage this device. */ if ((pSioChan = findSioChan (nodeId)) == NULL) break; /* The device has been disconnected. */ pSioChan->connected = FALSE; /* Notify registered callers that the mouse has been * removed and the channel disabled. * * NOTE: We temporarily increment the channel's lock count * to prevent usbMouseSioChanUnlock() from destroying the * structure while we're still using it. */ pSioChan->lockCount++; notifyAttach (pSioChan, USB_MSE_REMOVE); pSioChan->lockCount--; /* If no callers have the channel structure locked, destroy * it now. If it is locked, it will be destroyed later during * a call to usbMouseUnlock(). */ if (pSioChan->lockCount == 0) destroySioChan (pSioChan); break; } OSS_MUTEX_RELEASE (mseMutex); }/***************************************************************************** doShutdown - shuts down USB mouse SIO driver** <errCode> should be OK or S_usbMouseLib_xxxx. This value will be* passed to ossStatus() and the return value from ossStatus() is the* return value of this function.** RETURNS: OK, or ERROR per value of <errCode> passed by caller*/LOCAL STATUS doShutdown ( int errCode ) { pATTACH_REQUEST pRequest; pUSB_MSE_SIO_CHAN pSioChan; /* Dispose of any outstanding notification requests */ while ((pRequest = usbListFirst (&reqList)) != NULL) destroyAttachRequest (pRequest); /* Dispose of any open mouse connections. */ while ((pSioChan = usbListFirst (&sioList)) != NULL) destroySioChan (pSioChan); /* Release our connection to the USBD. The USBD automatically * releases any outstanding dynamic attach requests when a client * unregisters. */ if (usbdHandle != NULL) { usbdClientUnregister (usbdHandle); usbdHandle = NULL; } /* Release resources. */ if (mseMutex != NULL) { OSS_MUTEX_DESTROY (mseMutex); mseMutex = NULL; } return ossStatus (errCode); }/***************************************************************************** usbMouseDevInit - initialize USB mouse SIO driver** Initializes the USB mouse SIO driver. The USB mouse SIO driver* maintains an initialization count, so calls to this function may be* nested.** RETURNS: OK, or ERROR if unable to initialize.** ERRNO:** S_usbMouseLib_OUT_OF_RESOURCES* S_usbMouseLib_USBD_FAULT*/STATUS usbMouseDevInit (void) { /* If not already initialized, then initialize internal structures * and connection to USBD. */ if (initCount == 0) { /* Initialize lists, structures, resources. */ memset (&sioList, 0, sizeof (sioList)); memset (&reqList, 0, sizeof (reqList)); mseMutex = NULL; usbdHandle = NULL; if (OSS_MUTEX_CREATE (&mseMutex) != OK) return doShutdown (S_usbMouseLib_OUT_OF_RESOURCES); /* Establish connection to USBD */ if (usbdClientRegister (MSE_CLIENT_NAME, &usbdHandle) != OK || usbdDynamicAttachRegister (usbdHandle, USB_CLASS_HID, USB_SUBCLASS_HID_BOOT, USB_PROTOCOL_HID_BOOT_MOUSE, usbMouseAttachCallback) != OK) { return doShutdown (S_usbMouseLib_USBD_FAULT); } } initCount++; return OK; }/***************************************************************************** usbMouseDevShutdown - shuts down mouse SIO driver** RETURNS: OK, or ERROR if unable to shutdown.** ERRNO:* S_usbMouseLib_NOT_INITIALIZED*/STATUS usbMouseDevShutdown (void) { /* Shut down the USB mouse SIO driver if the initCount goes to 0. */ if (initCount == 0) return ossStatus (S_usbMouseLib_NOT_INITIALIZED); if (--initCount == 0) return doShutdown (OK); return OK; }/***************************************************************************** usbMouseDynamicAttachRegister - Register mouse attach callback** <callback> is a caller-supplied function of the form:** .CS* typedef (*USB_MSE_ATTACH_CALLBACK) * (* pVOID arg,* SIO_CHAN *pSioChan,* UINT16 attachCode* );* .CE** usbMouseLib will invoke <callback> each time a USB mouse* is attached to or removed from the system. <arg> is a caller-defined* parameter which will be passed to the <callback> each time it is* invoked. The <callback> will also be passed a pointer to the * SIO_CHAN structure for the channel being created/destroyed and* an attach code of USB_MSE_ATTACH or USB_MSE_REMOVE.** RETURNS: OK, or ERROR if unable to register callback** ERRNO:* S_usbMouseLib_BAD_PARAM* S_usbMouseLib_OUT_OF_MEMORY*/STATUS usbMouseDynamicAttachRegister ( USB_MSE_ATTACH_CALLBACK callback, /* new callback to be registered */ pVOID arg /* user-defined arg to callback */ ) { pATTACH_REQUEST pRequest; pUSB_MSE_SIO_CHAN pSioChan; int status = OK; /* Validate parameters */ if (callback == NULL) return ossStatus (S_usbMouseLib_BAD_PARAM); OSS_MUTEX_TAKE (mseMutex, OSS_BLOCK); /* Create a new request structure to track this callback request. */ if ((pRequest = OSS_CALLOC (sizeof (*pRequest))) == NULL) status = S_usbMouseLib_OUT_OF_MEMORY; else { pRequest->callback = callback; pRequest->callbackArg = arg; usbListLink (&reqList, pRequest, &pRequest->reqLink, LINK_TAIL); /* Perform an initial notification of all currrently attached * mouse devices. */ pSioChan = usbListFirst (&sioList); while (pSioChan != NULL) { if (pSioChan->connected) (*callback) (arg, (SIO_CHAN *) pSioChan, USB_MSE_ATTACH); pSioChan = usbListNext (&pSioChan->sioLink); } } OSS_MUTEX_RELEASE (mseMutex); return ossStatus (status); }/***************************************************************************** usbMouseDynamicAttachUnregister - Unregisters mouse attach callback** This function cancels a previous request to be dynamically notified for* mouse attachment and removal. The <callback> and <arg> paramters must* exactly match those passed in a previous call to * usbMouseDynamicAttachRegister().** RETURNS: OK, or ERROR if unable to unregister callback** ERRNO:* S_usbMouseLib_NOT_REGISTERED*/STATUS usbMouseDynamicAttachUnRegister ( USB_MSE_ATTACH_CALLBACK callback, /* callback to be unregistered */ pVOID arg /* user-defined arg to callback */ ) { pATTACH_REQUEST pRequest; int status = S_usbMouseLib_NOT_REGISTERED; OSS_MUTEX_TAKE (mseMutex, OSS_BLOCK); pRequest = usbListFirst (&reqList); while (pRequest != NULL) { if (callback == pRequest->callback && arg == pRequest->callbackArg) { /* We found a matching notification request. */ destroyAttachRequest (pRequest); status = OK; break; } pRequest = usbListNext (&pRequest->reqLink); } OSS_MUTEX_RELEASE (mseMutex); return ossStatus (status); }/***************************************************************************** usbMouseSioChanLock - Marks SIO_CHAN structure as in use** A caller uses usbMouseSioChanLock() to notify usbMouseLib that* it is using the indicated SIO_CHAN structure. usbMouseLib maintains* a count of callers using a particular SIO_CHAN structure so that it * knows when it is safe to dispose of a structure when the underlying* USB mouse is removed from the system. So long as the "lock count"* is greater than zero, usbMouseLib will not dispose of an SIO_CHAN* structure.** RETURNS: OK, or ERROR if unable to mark SIO_CHAN structure in use.*/STATUS usbMouseSioChanLock ( SIO_CHAN *pChan /* SIO_CHAN to be marked as in use */ ) { pUSB_MSE_SIO_CHAN pSioChan = (pUSB_MSE_SIO_CHAN) pChan; pSioChan->lockCount++; return OK; }/***************************************************************************** usbMouseSioChanUnlock - Marks SIO_CHAN structure as unused** This function releases a lock placed on an SIO_CHAN structure. When a* caller no longer needs an SIO_CHAN structure for which it has previously* called usbMouseSioChanLock(), then it should call this function to* release the lock.** NOTE: If the underlying USB mouse device has already been removed* from the system, then this function will automatically dispose of the* SIO_CHAN structure if this call removes the last lock on the structure.* Therefore, a caller must not reference the SIO_CHAN again structure after* making this call.** RETURNS: OK, or ERROR if unable to mark SIO_CHAN structure unused** ERRNO:* S_usbMouseLib_NOT_LOCKED*/STATUS usbMouseSioChanUnlock ( SIO_CHAN *pChan /* SIO_CHAN to be marked as unused */ ) { pUSB_MSE_SIO_CHAN pSioChan = (pUSB_MSE_SIO_CHAN) pChan; int status = OK; OSS_MUTEX_TAKE (mseMutex, OSS_BLOCK); if (pSioChan->lockCount == 0) status = S_usbMouseLib_NOT_LOCKED; else { /* If this is the last lock and the underlying USB mouse is * no longer connected, then dispose of the mouse. */ if (--pSioChan->lockCount == 0 && !pSioChan->connected) destroySioChan (pSioChan); } OSS_MUTEX_RELEASE (mseMutex); return ossStatus (status); }/* end of file. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -