?? libusbi.h
字號:
/* * Internal header for libusb * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org> * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#ifndef __LIBUSBI_H__#define __LIBUSBI_H__#include <config.h>#include <poll.h>#include <pthread.h>#include <stddef.h>#include <time.h>#include <libusb.h>#define DEVICE_DESC_LENGTH 18#define USB_MAXENDPOINTS 32#define USB_MAXINTERFACES 32#define USB_MAXCONFIG 8struct list_head { struct list_head *prev, *next;};/* Get an entry from the list * ptr - the address of this list_head element in "type" * type - the data type that contains "member" * member - the list_head element in "type" */#define list_entry(ptr, type, member) \ ((type *)((char *)(ptr) - (unsigned long)(&((type *)0L)->member)))/* Get each entry from a list * pos - A structure pointer has a "member" element * head - list head * member - the list_head element in "pos" */#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member))#define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member))#define list_empty(entry) ((entry)->next == (entry))static inline void list_init(struct list_head *entry){ entry->prev = entry->next = entry;}static inline void list_add(struct list_head *entry, struct list_head *head){ entry->next = head->next; entry->prev = head; head->next->prev = entry; head->next = entry;}static inline void list_add_tail(struct list_head *entry, struct list_head *head){ entry->next = head; entry->prev = head->prev; head->prev->next = entry; head->prev = entry;}static inline void list_del(struct list_head *entry){ entry->next->prev = entry->prev; entry->prev->next = entry->next;}#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})#define MIN(a, b) ((a) < (b) ? (a) : (b))#define MAX(a, b) ((a) > (b) ? (a) : (b))#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0)enum usbi_log_level { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR,};void usbi_log(struct libusb_context *ctx, enum usbi_log_level, const char *function, const char *format, ...);#ifdef ENABLE_LOGGING#define _usbi_log(ctx, level, fmt...) usbi_log(ctx, level, __FUNCTION__, fmt)#else#define _usbi_log(ctx, level, fmt...)#endif#ifdef ENABLE_DEBUG_LOGGING#define usbi_dbg(fmt...) _usbi_log(NULL, LOG_LEVEL_DEBUG, fmt)#else#define usbi_dbg(fmt...)#endif#define usbi_info(ctx, fmt...) _usbi_log(ctx, LOG_LEVEL_INFO, fmt)#define usbi_warn(ctx, fmt...) _usbi_log(ctx, LOG_LEVEL_WARNING, fmt)#define usbi_err(ctx, fmt...) _usbi_log(ctx, LOG_LEVEL_ERROR, fmt)#define USBI_GET_CONTEXT(ctx) if (!(ctx)) (ctx) = usbi_default_context#define DEVICE_CTX(dev) ((dev)->ctx)#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev))#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle))#define ITRANSFER_CTX(transfer) \ (TRANSFER_CTX(__USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)))extern struct libusb_context *usbi_default_context;struct libusb_context { int debug; int debug_fixed; struct list_head usb_devs; pthread_mutex_t usb_devs_lock; /* A list of open handles. Backends are free to traverse this if required. */ struct list_head open_devs; pthread_mutex_t open_devs_lock; /* this is a list of in-flight transfer handles, sorted by timeout * expiration. URBs to timeout the soonest are placed at the beginning of * the list, URBs that will time out later are placed after, and urbs with * infinite timeout are always placed at the very end. */ struct list_head flying_transfers; pthread_mutex_t flying_transfers_lock; /* list of poll fd's */ struct list_head pollfds; pthread_mutex_t pollfds_lock; /* user callbacks for pollfd changes */ libusb_pollfd_added_cb fd_added_cb; libusb_pollfd_removed_cb fd_removed_cb; void *fd_cb_user_data; /* ensures that only one thread is handling events at any one time */ pthread_mutex_t events_lock; /* used to see if there is an active thread doing event handling */ int event_handler_active; /* used to wait for event completion in threads other than the one that is * event handling */ pthread_mutex_t event_waiters_lock; pthread_cond_t event_waiters_cond;};struct libusb_device { /* lock protects refcnt, everything else is finalized at initialization * time */ pthread_mutex_t lock; int refcnt; struct libusb_context *ctx; uint8_t bus_number; uint8_t device_address; uint8_t num_configurations; struct list_head list; unsigned long session_data; unsigned char os_priv[0];};struct libusb_device_handle { /* lock protects claimed_interfaces */ pthread_mutex_t lock; unsigned long claimed_interfaces; struct list_head list; struct libusb_device *dev; unsigned char os_priv[0];};#define USBI_TRANSFER_TIMED_OUT (1<<0)/* in-memory transfer layout: * * 1. struct usbi_transfer * 2. struct libusb_transfer (which includes iso packets) [variable size] * 3. os private data [variable size] * * from a libusb_transfer, you can get the usbi_transfer by rewinding the * appropriate number of bytes. * the usbi_transfer includes the number of allocated packets, so you can * determine the size of the transfer and hence the start and length of the * OS-private data. */struct usbi_transfer { int num_iso_packets; struct list_head list; struct timeval timeout; int transferred; uint8_t flags;};#define __USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ ((struct libusb_transfer *)(((void *)(transfer)) \ + sizeof(struct usbi_transfer)))#define __LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ ((struct usbi_transfer *)(((void *)(transfer)) \ - sizeof(struct usbi_transfer)))static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer){ return ((void *)transfer) + sizeof(struct usbi_transfer) + sizeof(struct libusb_transfer) + (transfer->num_iso_packets * sizeof(struct libusb_iso_packet_descriptor));}/* bus structures *//* All standard descriptors have these 2 fields in common */struct usb_descriptor_header { uint8_t bLength; uint8_t bDescriptorType;};/* shared data and functions */void usbi_io_init(struct libusb_context *ctx);struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, unsigned long session_id);struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, unsigned long session_id);int usbi_sanitize_device(struct libusb_device *dev);void usbi_handle_disconnect(struct libusb_device_handle *handle);void usbi_handle_transfer_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status);void usbi_handle_transfer_cancellation(struct usbi_transfer *transfer);int usbi_parse_descriptor(unsigned char *source, char *descriptor, void *dest, int host_endian);int usbi_get_config_index_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, int *idx);/* polling */struct usbi_pollfd { /* must come first */ struct libusb_pollfd pollfd; struct list_head list;};int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events);void usbi_remove_pollfd(struct libusb_context *ctx, int fd);/* device discovery *//* we traverse usbfs without knowing how many devices we are going to find. * so we create this discovered_devs model which is similar to a linked-list * which grows when required. it can be freed once discovery has completed, * eliminating the need for a list node in the libusb_device structure * itself. */struct discovered_devs { size_t len; size_t capacity; struct libusb_device *devices[0];};struct discovered_devs *discovered_devs_append( struct discovered_devs *discdevs, struct libusb_device *dev);/* OS abstraction *//* This is the interface that OS backends need to implement. * All fields are mandatory, except ones explicitly noted as optional. */struct usbi_os_backend { /* A human-readable name for your backend, e.g. "Linux usbfs" */ const char *name; /* Perform initialization of your backend. You might use this function * to determine specific capabilities of the system, allocate required * data structures for later, etc. * * This function is called when a libusb user initializes the library * prior to use. * * Return 0 on success, or a LIBUSB_ERROR code on failure. */ int (*init)(struct libusb_context *ctx); /* Deinitialization. Optional. This function should destroy anything * that was set up by init. * * This function is called when the user deinitializes the library. */ void (*exit)(void); /* Enumerate all the USB devices on the system, returning them in a list * of discovered devices. * * Your implementation should enumerate all devices on the system, * regardless of whether they have been seen before or not. * * When you have found a device, compute a session ID for it. The session * ID should uniquely represent that particular device for that particular * connection session since boot (i.e. if you disconnect and reconnect a * device immediately after, it should be assigned a different session ID). * If your OS cannot provide a unique session ID as described above, * presenting a session ID of (bus_number << 8 | device_address) should * be sufficient. Bus numbers and device addresses wrap and get reused, * but that is an unlikely case. * * After computing a session ID for a device, call * usbi_get_device_by_session_id(). This function checks if libusb already * knows about the device, and if so, it provides you with a libusb_device * structure for it. * * If usbi_get_device_by_session_id() returns NULL, it is time to allocate * a new device structure for the device. Call usbi_alloc_device() to * obtain a new libusb_device structure with reference count 1. Populate * the bus_number and device_address attributes of the new device, and * perform any other internal backend initialization you need to do. At * this point, you should be ready to provide device descriptors and so * on through the get_*_descriptor functions. Finally, call * usbi_sanitize_device() to perform some final sanity checks on the * device. Assuming all of the above succeeded, we can now continue. * If any of the above failed, remember to unreference the device that * was returned by usbi_alloc_device(). * * At this stage we have a populated libusb_device structure (either one * that was found earlier, or one that we have just allocated and * populated). This can now be added to the discovered devices list * using discovered_devs_append(). Note that discovered_devs_append() * may reallocate the list, returning a new location for it, and also * note that reallocation can fail. Your backend should handle these * error conditions appropriately. *
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -