X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/usb-driver/blobdiff_plain/396647368be03bb5398301e67a676b8634827ac3..cbfa0ac6c885015f3ed37ec3931fba812194b0c0:/xpcu.c diff --git a/xpcu.c b/xpcu.c new file mode 100644 index 0000000..a37826b --- /dev/null +++ b/xpcu.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include "xpcu.h" +#include "usb-driver.h" + +int xpcu_deviceinfo(struct xpcu_s *xpcu, unsigned char *buf) { + int i,j,k,l; + int len = 0; + WDU_CONFIGURATION **pConfigs, **pActiveConfig; + WDU_INTERFACE **pActiveInterface; + + if (buf) { + struct usb_device_info *udi = (struct usb_device_info*)(buf+len); + + udi->Descriptor.bLength = sizeof(WDU_DEVICE_DESCRIPTOR); + udi->Descriptor.bDescriptorType = xpcu->dev->descriptor.bDescriptorType; + udi->Descriptor.bcdUSB = xpcu->dev->descriptor.bcdUSB; + udi->Descriptor.bDeviceClass = xpcu->dev->descriptor.bDeviceClass; + udi->Descriptor.bDeviceSubClass = xpcu->dev->descriptor.bDeviceSubClass; + udi->Descriptor.bDeviceProtocol = xpcu->dev->descriptor.bDeviceProtocol; + udi->Descriptor.bMaxPacketSize0 = xpcu->dev->descriptor.bMaxPacketSize0; + udi->Descriptor.idVendor = xpcu->dev->descriptor.idVendor; + udi->Descriptor.idProduct = xpcu->dev->descriptor.idProduct; + udi->Descriptor.bcdDevice = xpcu->dev->descriptor.bcdDevice; + udi->Descriptor.iManufacturer = xpcu->dev->descriptor.iManufacturer; + udi->Descriptor.iProduct = xpcu->dev->descriptor.iProduct; + udi->Descriptor.iSerialNumber = xpcu->dev->descriptor.iSerialNumber; + udi->Descriptor.bNumConfigurations = xpcu->dev->descriptor.bNumConfigurations; + + /* TODO: Fix Pipe0! */ + udi->Pipe0.dwNumber = 0x00; + udi->Pipe0.dwMaximumPacketSize = xpcu->dev->descriptor.bMaxPacketSize0; + udi->Pipe0.type = 0; + udi->Pipe0.direction = WDU_DIR_IN_OUT; + udi->Pipe0.dwInterval = 0; + + pConfigs = &(udi->pConfigs); + pActiveConfig = &(udi->pActiveConfig); + pActiveInterface = &(udi->pActiveInterface[0]); + } + + len = sizeof(struct usb_device_info); + + for (i=0; idev->descriptor.bNumConfigurations; i++) + { + struct usb_config_descriptor *conf_desc = &xpcu->dev->config[i]; + WDU_INTERFACE **pInterfaces; + WDU_ALTERNATE_SETTING **pAlternateSettings[conf_desc->bNumInterfaces]; + WDU_ALTERNATE_SETTING **pActiveAltSetting[conf_desc->bNumInterfaces]; + + if (buf) { + WDU_CONFIGURATION *cfg = (WDU_CONFIGURATION*)(buf+len); + + *pConfigs = cfg; + *pActiveConfig = cfg; + + cfg->Descriptor.bLength = conf_desc->bLength; + cfg->Descriptor.bDescriptorType = conf_desc->bDescriptorType; + cfg->Descriptor.wTotalLength = conf_desc->wTotalLength; + cfg->Descriptor.bNumInterfaces = conf_desc->bNumInterfaces; + cfg->Descriptor.bConfigurationValue = conf_desc->bConfigurationValue; + cfg->Descriptor.iConfiguration = conf_desc->iConfiguration; + cfg->Descriptor.bmAttributes = conf_desc->bmAttributes; + cfg->Descriptor.MaxPower = conf_desc->MaxPower; + + cfg->dwNumInterfaces = conf_desc->bNumInterfaces; + + pInterfaces = &(cfg->pInterfaces); + } + len += sizeof(WDU_CONFIGURATION); + + if (buf) { + *pInterfaces = (WDU_INTERFACE*)(buf+len); + for (j=0; jbNumInterfaces; j++) { + WDU_INTERFACE *iface = (WDU_INTERFACE*)(buf+len); + + pActiveInterface[j] = iface; + + pAlternateSettings[j] = &(iface->pAlternateSettings); + iface->dwNumAltSettings = xpcu->dev->config[i].interface[j].num_altsetting; + pActiveAltSetting[j] = &(iface->pActiveAltSetting); + + len += sizeof(WDU_INTERFACE); + } + } else { + len += sizeof(WDU_INTERFACE) * conf_desc->bNumInterfaces; + } + + for (j=0; jbNumInterfaces; j++) + { + struct usb_interface *interface = &xpcu->dev->config[i].interface[j]; + + if (buf) { + *pAlternateSettings[j] = (WDU_ALTERNATE_SETTING*)(buf+len); + /* FIXME: */ + *pActiveAltSetting[j] = (WDU_ALTERNATE_SETTING*)(buf+len); + } + + for(k=0; knum_altsetting; k++) + { + unsigned char bNumEndpoints = interface->altsetting[k].bNumEndpoints; + WDU_ENDPOINT_DESCRIPTOR **pEndpointDescriptors; + WDU_PIPE_INFO **pPipes; + + if (buf) { + WDU_ALTERNATE_SETTING *altset = (WDU_ALTERNATE_SETTING*)(buf+len); + + altset->Descriptor.bLength = interface->altsetting[k].bLength; + altset->Descriptor.bDescriptorType = interface->altsetting[k].bDescriptorType; + altset->Descriptor.bInterfaceNumber = interface->altsetting[k].bInterfaceNumber; + altset->Descriptor.bAlternateSetting = interface->altsetting[k].bAlternateSetting; + altset->Descriptor.bNumEndpoints = interface->altsetting[k].bNumEndpoints; + altset->Descriptor.bInterfaceClass = interface->altsetting[k].bInterfaceClass; + altset->Descriptor.bInterfaceSubClass = interface->altsetting[k].bInterfaceSubClass; + altset->Descriptor.bInterfaceProtocol = interface->altsetting[k].bInterfaceProtocol; + altset->Descriptor.iInterface = interface->altsetting[k].iInterface; + pEndpointDescriptors = &(altset->pEndpointDescriptors); + pPipes = &(altset->pPipes); + + } + len +=sizeof(WDU_ALTERNATE_SETTING); + + if (buf) { + *pEndpointDescriptors = (WDU_ENDPOINT_DESCRIPTOR*)(buf+len); + for (l = 0; l < bNumEndpoints; l++) { + WDU_ENDPOINT_DESCRIPTOR *ed = (WDU_ENDPOINT_DESCRIPTOR*)(buf+len); + + ed->bLength = interface->altsetting[k].endpoint[l].bLength; + ed->bDescriptorType = interface->altsetting[k].endpoint[l].bDescriptorType; + ed->bEndpointAddress = interface->altsetting[k].endpoint[l].bEndpointAddress; + ed->bmAttributes = interface->altsetting[k].endpoint[l].bmAttributes; + ed->wMaxPacketSize = interface->altsetting[k].endpoint[l].wMaxPacketSize; + ed->bInterval = interface->altsetting[k].endpoint[l].bInterval; + + len += sizeof(WDU_ENDPOINT_DESCRIPTOR); + } + + *pPipes = (WDU_PIPE_INFO*)(buf+len); + for (l = 0; l < bNumEndpoints; l++) { + WDU_PIPE_INFO *pi = (WDU_PIPE_INFO*)(buf+len); + + pi->dwNumber = interface->altsetting[k].endpoint[l].bEndpointAddress; + pi->dwMaximumPacketSize = WDU_GET_MAX_PACKET_SIZE(interface->altsetting[k].endpoint[l].wMaxPacketSize); + pi->type = interface->altsetting[k].endpoint[l].bmAttributes & USB_ENDPOINT_TYPE_MASK; + if (pi->type == PIPE_TYPE_CONTROL) + pi->direction = WDU_DIR_IN_OUT; + else + { + pi->direction = interface->altsetting[k].endpoint[l].bEndpointAddress & USB_ENDPOINT_DIR_MASK ? WDU_DIR_IN : WDU_DIR_OUT; + } + + pi->dwInterval = interface->altsetting[k].endpoint[l].bInterval; + + len += sizeof(WDU_PIPE_INFO); + } + } else { + len +=(sizeof(WDU_ENDPOINT_DESCRIPTOR)+sizeof(WDU_PIPE_INFO))*bNumEndpoints; + } + } + } + } + + return len; +} + +int xpcu_claim(struct xpcu_s *xpcu, int claim) { + int ret = 0; + static int claimed = 0; + + if (xpcu->interface < 0) + return -1; + + if (claim == XPCU_CLAIM) { + if (claimed) + return 0; + + ret = usb_claim_interface(xpcu->handle, xpcu->interface); + if (!ret) { + claimed = 1; + ret = usb_set_altinterface(xpcu->handle, xpcu->alternate); + if (ret) + fprintf(stderr, "usb_set_altinterface: %d\n", ret); + } else { + fprintf(stderr, "usb_claim_interface: %d -> %d (%s)\n", + xpcu->interface, ret, usb_strerror()); + } + } else { + if (!claimed) + return 0; + + ret = usb_release_interface(xpcu->handle, xpcu->interface); + if (!ret) + claimed = 0; + } + + return ret; +} + +struct xpcu_s *xpcu_open(void) { + static struct xpcu_s xpcu; + + bzero(&xpcu, sizeof(xpcu)); + xpcu.interface = -1; + xpcu.alternate = -1; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + xpcu.busses = usb_get_busses(); + + return &xpcu; +}