From: frits v. <fr...@so...> - 2007-06-18 05:05:04
|
> I should say this API versioin only defines a very basic function set, > which might be far from effective and complete. More needs to be figured > out during the implementation process. So this version is simply a > start. It can be changed whenever necessary. Of course, comments are > always welcome. > since this is not exposed to app writers, the API can be easily changed when necessary > ------------------------------------------------------------------------ > > #ifndef _WRAPPER_H_ > #define _WRAPPER_H_ > LIBUSB_WRAPPER_H what about the emulation layer for 0.1.* > #include "libusb.h" > > /* Prevent namespace pollution */ > #define list_init __usb_list_init > #define list_add __usb_list_add > #define list_del __usb_list_del > please explain > #include "list.h" > > struct usbi_list { > struct list_head head; > pthread_mutex_t lock; > }; > Is it a good idea to have these locks in the API? Do we really want to expose the locking? > struct usbi_backend_ops; > struct usbi_device_ops; > struct usbi_device; > > /* backend specific data structures */ > struct usbi_bus_private; > struct usbi_dev_private; > struct usbi_io_private; > I don't think you need the above declarations Not sure if I like usbi prefix. > struct usbi_backend { > struct list_head list; > void *handle; > char filepath[PATH_MAX + 1]; > struct usbi_backend_ops *ops; > }; > > struct usbi_bus { > struct list_head list; > pthread_mutex_t lock; > libusb_busid_t busid; > unsigned int busnum; /* Only needs to be unique */ > char sys_path[PATH_MAX + 1]; > struct usbi_backend_ops *ops; > struct list_head devices; > struct usbi_device *root; > uint32_t ctrl_max_xfer_size; > uint32_t intr_max_xfer_size; > uint32_t bulk_max_xfer_size; > uint32_t isoc_max_xfer_size; > struct usbi_bus_private *priv; > }; > is this what is behind busid? > struct usbi_device { > struct list_head dev_list; > struct list_head bus_list; > struct list_head match_list; /* for search functions */ > libusb_devid_t devid; > uint8_t bus_addr; > struct usbi_bus *bus; > struct usbi_device *parent;/* NULL for root hub */ > uint8_t pport; /* parent port */ > uint8_t nports; /* number of ports */ > char sys_path[PATH_MAX + 1]; > char bus_path[LIBUSB_BUS_PATH_MAX]; > struct usbi_device **children; > struct usbi_device_ops *ops; > uint8_t cur_config; > struct usbi_dev_private *priv; > }; > is this what is behind devid? > struct usbi_event_callback { > libusb_event_callback_t func; > void *arg; > }; > > struct usbi_handle { > struct list_head list; > libusb_handle_t handle; > pthread_mutex_t lock; > uint32_t debug_level; > uint32_t debug_flags; > libusb_debug_callback_t debug_cb; > struct usbi_event_callback event_cbs[LIBUSB_EVENT_TYPE_COUNT]; > uint32_t ctrl_timeout; > uint32_t intr_timeout; > uint32_t bulk_timeout; > uint32_t isoc_timeout; /* ? do we need this */ > }; > this is behind libusb_handle? > #define USBI_MAXINTERFACES 32 > > struct usbi_dev_handle { > struct list_head list; > struct usbi_handle *lib_hdl; > libusb_dev_handle_t handle; > struct usbi_device *idev; /* device opened */ > libusb_init_flag_t flags; /* init flag */ > int ifc[USBI_MAXINTERFACES]; /* =1 if claimed */ > int alt[USBI_MAXINTERFACES]; > struct usbi_dev_hdl_private *priv; > }; > > struct usbi_io { > struct list_head list; > pthread_mutex_t lock; > struct usbi_dev_handle *dev; > libusb_request_handle_t req; > int inprogress; > struct timeval tvo; > pthread_cond_t cond; /* for waiting on completion */ > struct usbi_io_private *priv; > }; > is this behind the libusb request handle. Please make it more obvious what the justificatin of of each structure? > struct usbi_device_ops { > /* prepare device and make the default endpoint accessible to libusb */ > int32_t (*open)(struct usbi_dev_handle *dev); > > /* close device and return it to original state */ > int32_t (*close)(struct usbi_dev_handle *dev); > > /* configuration selection */ > int32_t (*set_configuration)(struct usbi_dev_handle *hdev, > uint8_t cfg); > int32_t (*get_configuration)(struct usbi_dev_handle *hdev, > uint8_t *cfg); > > /* interface claiming and bandwidth reservation */ > int32_t (*claim_interface)(struct usbi_dev_handle *dev, uint8_t ifc); > int32_t (*release_interface)(struct usbi_dev_handle *dev, uint8_t ifc); > > /* alternate interface selection */ > int32_t (*set_altinterface)(struct usbi_dev_handle *hdev, > uint8_t ifc, uint8_t alt); > int32_t (*get_altinterface)(struct usbi_device *idev, > uint8_t ifc, uint8_t *alt); > it is not entirely obvious to me what the backend has to know about configuration changes, claiming interfaces and setting alternates. Can you add more comments to explain it all > /* reset device by resetting port */ > int32_t (*reset)(struct usbi_dev_handle *dev); > > /* > * synchronous I/O functions, might be NULL if not > * supported by backend > */ > int32_t (*ctrl_xfer_wait)(struct usbi_dev_handle *hdev, > struct usbi_io *io); > int32_t (*intr_xfer_wait)(struct usbi_dev_handle *hdev, > struct usbi_io *io); > int32_t (*bulk_xfer_wait)(struct usbi_dev_handle *hdev, > struct usbi_io *io); > int32_t (*isoc_xfer_wait)(struct usbi_dev_handle *hdev, > struct usbi_io *io); > > /* > * asynchronous I/O functions, might be NULL if not > * supported by backend > */ > int32_t (*ctrl_xfer_aio)(struct usbi_dev_handle *hdev, > struct usbi_io *io); > int32_t (*intr_xfer_aio)(struct usbi_dev_handle *hdev, > struct usbi_io *io); > int32_t (*bulk_xfer_aio)(struct usbi_dev_handle *hdev, > struct usbi_io *io); > int32_t (*isoc_xfer_aio)(struct usbi_dev_handle *hdev, > struct usbi_io *io); > I would have thought that we only need the synchronous I/O functions and libusb frontend will provide the async part. Remember that we want to keep the backend as simple and dumb as possible > /* I/O abort function */ > int32_t (*io_cancel)(struct usbi_io *io); > }; > > /* backend I/O pattern */ > #define PATTERN_ASYNC 1 > #define PATTERN_SYNC 2 > #define PATTERN_BOTH 4 > huh? > struct usbi_backend_ops { > int backend_version; > > /* > * the pattern value indicates if the backend supports only > * asynchronous I/O functions or synchronous I/O functions > * or both > */ > int io_pattern; > > /* > * backend initialization, called in libusb_init() > * flags - inherited from libusb_init(), TBD > */ > int32_t (*init)(uint32_t flags); > > /* backend cleanup, called in libusb_fini() */ > void (*fini)(void); > > /* search USB buses and create a bus list */ > int32_t (*find_buses)(struct list_head *buses); > > /* > * make a new search of the devices on the bus and refresh > * the device list. the device nodes that have been detached > * from the system would be removed from the list > */ > int32_t (*refresh_devices)(struct usbi_bus *bus); > > /* > * cleanup a device structure when the device node is to be > * removed from a device list > */ > void (*free_device)(struct usbi_device *idev); > > /* > * get standard descriptor in its raw form > * type - descriptor type > * descidx - index for config/string desc., zero for others > * langid - language ID for string desc., zero for others > * buffer - backend allocated data buffer for raw desc. > * buflen - backend returned length of raw desc. > */ > int32_t (*get_raw_desc)(struct usbi_device *idev, uint8_t type, > uint8_t descidx, uint16_t langid, > uint8_t **buffer, uint16_t *buflen); > > struct usbi_device_ops dev; > }; > we need more discussion/background here why this is needed or sufficient. > #endif /* _WRAPPER_H_ */ > > good start but I am clueless whether it will do the job :-( fritS |