// return 1 if OS hdl are identicals // 0 if any of the interface has changed int yyyOShdlCompare( yPrivDeviceSt *dev, DevEnum *newdev) { int i,j, nbifaces; if(dev->infos.nbinbterfaces != newdev->nbifaces){ HALLOG("bad number of inteface for %s (%d:%d)\n",dev->infos.serial,dev->infos.nbinbterfaces, newdev->nbifaces); return 0; } nbifaces=newdev->nbifaces; for (i =0 ; i < nbifaces ;i++) { for (j =0 ; j < nbifaces ;j++) { if(dev->ifaces[i].devref == newdev->ifaces[j]->devref){ break; } } if(j==nbifaces) break; } if( i < nbifaces ) { HALLOG("devref %d has changed for %s (%X)\n",i,dev->infos.serial,dev->ifaces[i].devref); return 0; } return 1; }
static void read_callback(struct libusb_transfer *transfer) { int res; linRdTr *lintr = (linRdTr*)transfer->user_data; yInterfaceSt *iface = lintr->iface; switch(transfer->status){ case LIBUSB_TRANSFER_COMPLETED: //HALLOG("%s:%d pkt_arrived (len=%d)\n",iface->serial,iface->ifaceno,transfer->actual_length); yPktQueuePushD2H(iface,&lintr->tmppkt,NULL); if (iface->flags.yyySetupDone) { res=libusb_submit_transfer(lintr->tr); if(res<0){ HALLOG("%s:%d libusb_submit_transfer errror %X\n",iface->serial,iface->ifaceno,res); } } return; case LIBUSB_TRANSFER_ERROR: HALLOG("%s:%d pkt error\n",iface->serial,iface->ifaceno); res=libusb_submit_transfer(lintr->tr); if(res<0){ HALLOG("%s:%d libusb_submit_transfer errror %X\n",iface->serial,iface->ifaceno,res); } break; case LIBUSB_TRANSFER_TIMED_OUT : HALLOG("%s:%d pkt timeout\n",iface->serial,iface->ifaceno); break; case LIBUSB_TRANSFER_CANCELLED: HALLOG("%s:%d pkt_cancelled (len=%d) \n",iface->serial,iface->ifaceno,transfer->actual_length); if(transfer->actual_length==64){ yPktQueuePushD2H(iface,&lintr->tmppkt,NULL); } break; case LIBUSB_TRANSFER_STALL: HALLOG("%s:%d pkt stall\n",iface->serial,iface->ifaceno); res=libusb_submit_transfer(lintr->tr); if(res<0){ HALLOG("%s:%d libusb_submit_transfer errror %X\n",iface->serial,iface->ifaceno,res); } break; case LIBUSB_TRANSFER_NO_DEVICE: HALLOG("%s:%d pkt_cancelled (len=%d)\n",iface->serial,iface->ifaceno,transfer->actual_length); return; case LIBUSB_TRANSFER_OVERFLOW: HALLOG("%s:%d pkt_overflow (len=%d)\n",iface->serial,iface->ifaceno,transfer->actual_length); break; default: HALLOG("%s:%d unknown state %X\n",iface->serial,iface->ifaceno,transfer->status); break; } }
static int setupHIDManager(yContextSt *ctx, OSX_HID_REF *hid, char *errmsg) { int c_vendorid = YOCTO_VENDORID; CFMutableDictionaryRef dictionary; CFNumberRef Vendorid; IOReturn tIOReturn; yInitializeCriticalSection(&hid->hidMCS); // Initialize HID Manager hid->manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); // create dictionary to match Yocto devices dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,1,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks); Vendorid = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &c_vendorid ); CFDictionarySetValue( dictionary, CFSTR( kIOHIDVendorIDKey ), Vendorid ); CFRelease(Vendorid); // register the dictionary IOHIDManagerSetDeviceMatching(hid->manager, dictionary ); // now we can release the dictionary CFRelease(dictionary); // sechedulle the HID Manager with our global run loop IOHIDManagerScheduleWithRunLoop(hid->manager, ctx->usb_run_loop, kCFRunLoopDefaultMode); // Now open the IO HID Manager reference tIOReturn = IOHIDManagerOpen(hid->manager, kIOHIDOptionsTypeNone ); if(kIOReturnSuccess != tIOReturn ||CFGetTypeID(hid->manager) != IOHIDManagerGetTypeID()){ HALLOG("Unable to Open HID Manager"); return YERRMSG(YAPI_NOT_SUPPORTED,"Unable to Open HID Manager"); } return YAPI_SUCCESS; }
static void *event_thread(void *param) { yContextSt *ctx=param; ctx->usb_run_loop = CFRunLoopGetCurrent(); ctx->usb_thread_state = USB_THREAD_RUNNING; /* Non-blocking. See if the OS has any reports to give. */ HALLOG("Start event_thread run loop\n"); while (ctx->usb_thread_state != USB_THREAD_MUST_STOP) { CFRunLoopRunInMode( kCFRunLoopDefaultMode, 10, FALSE); } HALLOG("event_thread run loop stoped\n"); ctx->usb_thread_state = USB_THREAD_STOPED; return NULL; }
static int yLinSetErrEx(u32 line,char *intro, int err,char *errmsg) { const char *msg; if(errmsg==NULL) return YAPI_IO_ERROR; switch(err){ case LIBUSB_SUCCESS: msg="Success (no error)";break; case LIBUSB_ERROR_IO: msg="Input/output error"; break; case LIBUSB_ERROR_INVALID_PARAM:msg="Invalid parameter"; break; case LIBUSB_ERROR_ACCESS: msg="Access denied (insufficient permissions)"; break; case LIBUSB_ERROR_NO_DEVICE: msg="No such device (it may have been disconnected)"; break; case LIBUSB_ERROR_NOT_FOUND: msg="Entity not found"; break; case LIBUSB_ERROR_BUSY: msg="Resource busy"; break; case LIBUSB_ERROR_TIMEOUT: msg="Operation timed out"; break; case LIBUSB_ERROR_OVERFLOW: msg="Overflow"; break; case LIBUSB_ERROR_PIPE: msg="Pipe error"; break; case LIBUSB_ERROR_INTERRUPTED: msg="System call interrupted (perhaps due to signal)"; break; case LIBUSB_ERROR_NO_MEM: msg="Insufficient memory"; break; case LIBUSB_ERROR_NOT_SUPPORTED:msg="Operation not supported or unimplemented on this platform"; break; default: case LIBUSB_ERROR_OTHER: msg="Other error"; break; } if (intro){ YSPRINTF(errmsg,YOCTO_ERRMSG_LEN,"%s:%s",intro,msg); } else{ YSPRINTF(errmsg,YOCTO_ERRMSG_LEN,"LIN(%d):%s",line,msg); } HALLOG("LIN(%d):%s\n",line,msg); return YAPI_IO_ERROR; };
static int getDevConfig(libusb_device *dev, struct libusb_config_descriptor **config) { int res = libusb_get_active_config_descriptor(dev, config); if(res==LIBUSB_ERROR_NOT_FOUND){ HALLOG("not yet configured\n"); if(libusb_get_config_descriptor(dev, 0, config)!=0){ return -1; } }else if(res!=0){ HALLOG("unable to get active configuration %d\n",res); return -1; } return 0; }
// return 1 if OS hdl are identicals // 0 if any of the interface has changed int yyyOShdlCompare( yPrivDeviceSt *dev, yInterfaceSt *newdev) { if(dev->infos.nbinbterfaces != 1){ HALLOG("bad number of inteface for %s (%d)\n",dev->infos.serial,dev->infos.nbinbterfaces); return 0; } return 1; }
static void *event_thread(void *param) { yContextSt *ctx = (yContextSt*)param; char errmsg[YOCTO_ERRMSG_LEN]; ctx->usb_thread_state = USB_THREAD_RUNNING; /* Non-blocking. See if the OS has any reports to give. */ HALLOG("Start event_thread run loop\n"); while (ctx->usb_thread_state != USB_THREAD_MUST_STOP) { int res; struct timeval tv; memset(&tv,0,sizeof(tv)); tv.tv_sec = 1; res = libusb_handle_events_timeout(ctx->libusb, &tv); if (res < 0) { yLinSetErr("libusb_handle_events_timeout", res,errmsg); break; } } HALLOG("event_thread run loop stoped\n"); ctx->usb_thread_state = USB_THREAD_STOPED; return NULL; }
void yyyPacketShutdown(yInterfaceSt *iface) { int res,j; iface->flags.yyySetupDone = 0; HALLOG("%s:%d cancel all transfer\n",iface->serial,iface->ifaceno); for(j=0;j< NB_LINUX_USB_TR ; j++){ int count=10; int res =libusb_cancel_transfer(iface->rdTr[j].tr); if(res==0){ while(count && iface->rdTr[j].tr->status != LIBUSB_TRANSFER_CANCELLED){ usleep(1000); count--; } } } for(j=0;j< NB_LINUX_USB_TR ; j++){ if (iface->rdTr[j].tr){ HALLOG("%s:%d libusb_TR free %d\n",iface->serial,iface->ifaceno,j); libusb_free_transfer(iface->rdTr[j].tr); iface->rdTr[j].tr=NULL; } } HALLOG("%s:%d libusb relase iface\n",iface->serial,iface->ifaceno); res = libusb_release_interface(iface->hdl,iface->ifaceno); if(res != 0 && res!=LIBUSB_ERROR_NOT_FOUND && res!=LIBUSB_ERROR_NO_DEVICE){ HALLOG("%s:%dlibusb_release_interface error\n",iface->serial,iface->ifaceno); } res = libusb_attach_kernel_driver(iface->hdl,iface->ifaceno); if(res<0 && res!=LIBUSB_ERROR_NO_DEVICE){ HALLOG("%s:%d libusb_attach_kernel_driver error\n",iface->serial,iface->ifaceno); } libusb_close(iface->hdl); yPktQueueFree(&iface->rxQueue); yPktQueueFree(&iface->txQueue); }
int yUSB_init(yContextSt *ctx,char *errmsg) { int c_vendorid = YOCTO_VENDORID; IOReturn tIOReturn; CFMutableDictionaryRef dictionary; CFNumberRef Vendorid; if(!yReserveGlobalAccess(ctx)){ return YERRMSG(YAPI_DOUBLE_ACCES,"Another process is already using yAPI"); } ctx->usb_thread_state = USB_THREAD_NOT_STARTED; pthread_create(&ctx->usb_thread, NULL, event_thread, ctx); yInitializeCriticalSection(&ctx->hidMCS); // Initialize HID Manager ctx->hidM = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); // create dictionary to match Yocto devices dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault,1,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks); Vendorid = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &c_vendorid ); CFDictionarySetValue( dictionary, CFSTR( kIOHIDVendorIDKey ), Vendorid ); // register the dictionary IOHIDManagerSetDeviceMatching( ctx->hidM, dictionary ); // now we can release the dictionary CFRelease(dictionary); IOHIDManagerRegisterDeviceRemovalCallback(ctx->hidM,hid_device_removal_callback,ctx); //register hid into read_thead's RunnLoop while(ctx->usb_thread_state != USB_THREAD_RUNNING){ usleep(50000); } IOHIDManagerScheduleWithRunLoop(ctx->hidM, ctx->usb_run_loop, kCFRunLoopDefaultMode); // Now open the IO HID Manager reference tIOReturn = IOHIDManagerOpen( ctx->hidM, kIOHIDOptionsTypeNone ); CFRelease(Vendorid); if(kIOReturnSuccess != tIOReturn ||CFGetTypeID(ctx->hidM) != IOHIDManagerGetTypeID()){ HALLOG("Unable to Open HID Manager"); return YERRMSG(YAPI_NOT_SUPPORTED,"Unable to Open HID Manager"); } return YAPI_SUCCESS; }
static void hid_device_removal_callback(void *context, IOReturn result, void *sender, IOHIDDeviceRef dev_ref) { yContextSt *ctx =(yContextSt*)context; yPrivDeviceSt *p=ctx->devs; //dbglog("handle device removal correctly\n"); while(p){ int i; for(i =0 ; i< p->infos.nbinbterfaces ;i++){ yInterfaceSt *iface = &p->ifaces[i]; if(iface->devref == dev_ref){ yEnterCriticalSection(&iface->yyyCS); HALLOG("unplug of %s:%d detected\n",iface->serial,iface->ifaceno); iface->devref=NULL; yLeaveCriticalSection(&iface->yyyCS); break; } } p=p->next; } }
// return 1 if we can reserve access to the device 0 if the device // is already reserved static int yReserveGlobalAccess(yContextSt *ctx) { int fd; int chk_val; size_t res; mode_t mode=0666; mode_t oldmode = umask(0000); HALLOG("old mode (%#o)\n",oldmode); HALLOG("create fifo with (%#o)\n",mode); if(mkfifo(YOCTO_LOCK_PIPE,mode)<0) { HALLOG("unable to create lock fifo (%d:%s)\n",errno,strerror(errno)); } umask(oldmode); fd = open(YOCTO_LOCK_PIPE,O_RDWR|O_NONBLOCK); if(fd<0){ HALLOG("unable to open lock fifo (%d)\n",errno); if(errno==EACCES) { HALLOG("we do not have acces to lock fifo\n"); return 0; }else{ // we cannot open lock file so we cannot realy // check double instance so we asume that we are // alone return 1; } } chk_val=0; res = read(fd,&chk_val,sizeof(chk_val)); if(res==sizeof(chk_val)){ //there is allready someone chk_val=1; } res = write(fd,&chk_val,sizeof(chk_val)); if(res!=sizeof(chk_val)) { HALLOG("write to lock fifo failed (%d)",res); return 0; } if(chk_val==1) return 0; return 1; }
int yUSBGetInterfaces(yInterfaceSt **ifaces,int *nbifaceDetect,char *errmsg) { int nbifaceAlloc; int deviceIndex; CFSetRef deviceCFSetRef; CFIndex deviceCount; IOHIDDeviceRef *dev_refs; // allocate buffer for detected interfaces *nbifaceDetect = 0; nbifaceAlloc = 8; *ifaces =yMalloc(nbifaceAlloc * sizeof(yInterfaceSt)); memset(*ifaces, 0 ,nbifaceAlloc * sizeof(yInterfaceSt)); yEnterCriticalSection(&yContext->hidMCS); deviceCFSetRef = IOHIDManagerCopyDevices( yContext->hidM ); yLeaveCriticalSection(&yContext->hidMCS); if(deviceCFSetRef== NULL){ //no device found return 0; } // how many devices in the set? deviceCount = CFSetGetCount( deviceCFSetRef ); HALLOG("%ld usb interfaces detected\n",deviceCount); dev_refs = yMalloc( sizeof(IOHIDDeviceRef) * (u32)deviceCount ); // now extract the device ref's from the set CFSetGetValues( deviceCFSetRef, (const void **) dev_refs ); for(deviceIndex=0 ; deviceIndex < deviceCount ;deviceIndex++){ u16 vendorid; u16 deviceid; IOHIDDeviceRef dev = dev_refs[deviceIndex]; yInterfaceSt *iface; vendorid = get_int_property(dev,CFSTR(kIOHIDVendorIDKey)); deviceid = get_int_property(dev,CFSTR(kIOHIDProductIDKey)); //ensure the buffer of detected interface is big enought if(*nbifaceDetect == nbifaceAlloc){ yInterfaceSt *tmp; tmp = (yInterfaceSt*) yMalloc(nbifaceAlloc*2 * sizeof(yInterfaceSt)); memset(tmp,0,nbifaceAlloc*2 * sizeof(yInterfaceSt)); yMemcpy(tmp,*ifaces, nbifaceAlloc * sizeof(yInterfaceSt) ); yFree(*ifaces); *ifaces = tmp; nbifaceAlloc *=2; } iface = *ifaces + *nbifaceDetect; iface->devref = dev; iface->vendorid = vendorid; iface->deviceid = deviceid; get_txt_property(dev,iface->serial,YOCTO_SERIAL_LEN*2, CFSTR(kIOHIDSerialNumberKey)); HALLOG("work on interface %d (%x:%x:%s)\n",deviceIndex,vendorid,deviceid,iface->serial); (*nbifaceDetect)++; } CFRelease(deviceCFSetRef); yFree(dev_refs); return YAPI_SUCCESS; }
int yyySetup(yInterfaceSt *iface,char *errmsg) { int res,j; int error; struct libusb_config_descriptor *config; const struct libusb_interface_descriptor* ifd; HALLOG("%s:%d yyySetup %X:%X\n",iface->serial,iface->ifaceno,iface->vendorid,iface->deviceid); if(iface->devref==NULL){ return YERR(YAPI_DEVICE_NOT_FOUND); } if((res=libusb_open(iface->devref,&iface->hdl))!=0){ return yLinSetErr("libusb_open", res,errmsg); } if((res=libusb_kernel_driver_active(iface->hdl,iface->ifaceno))<0){ error= yLinSetErr("libusb_kernel_driver_active",res,errmsg); goto error; } if(res){ HALLOG("%s:%d need to detach kernel driver\n",iface->serial,iface->ifaceno); if((res = libusb_detach_kernel_driver(iface->hdl,iface->ifaceno))<0){ error= yLinSetErr("libusb_detach_kernel_driver",res,errmsg); goto error; } } HALLOG("%s:%d Claim interface\n",iface->serial,iface->ifaceno); if((res = libusb_claim_interface(iface->hdl,iface->ifaceno))<0){ error= yLinSetErr("libusb_claim_interface", res,errmsg); goto error; } res=getDevConfig(iface->devref,&config); if(res<0){ error=YERRMSG(YAPI_IO_ERROR,"unable to get configuration descriptor"); goto error; } ifd = &config->interface[iface->ifaceno].altsetting[0]; for (j = 0; j < ifd->bNumEndpoints; j++) { //HALLOG("endpoint %X size=%d \n",ifd->endpoint[j].bEndpointAddress,ifd->endpoint[j].wMaxPacketSize); if((ifd->endpoint[j].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN){ iface->rdendp = ifd->endpoint[j].bEndpointAddress; }else{ iface->wrendp = ifd->endpoint[j].bEndpointAddress; } } yPktQueueInit(&iface->rxQueue); yPktQueueInit(&iface->txQueue); iface->flags.yyySetupDone = 1; for(j=0;j< NB_LINUX_USB_TR ; j++){ iface->rdTr[j].iface = iface; iface->rdTr[j].tr=libusb_alloc_transfer(0); YASSERT(iface->rdTr[j].tr); libusb_fill_interrupt_transfer( iface->rdTr[j].tr, iface->hdl, iface->rdendp, (u8*)&iface->rdTr[j].tmppkt, sizeof(USB_Packet), read_callback, &iface->rdTr[j], 0/*5 sec*/); HALLOG("%s:%d libusb_TR filled (%d)\n",iface->serial,iface->ifaceno,j); } //HALLOG("%s:%d yyyRead\n",iface->serial ,iface->ifaceno); for(j=0;j< NB_LINUX_USB_TR ; j++){ //HALLOG("%s:%d libusb_TR transmit (%d)\n",iface->serial,iface->ifaceno,j); res=libusb_submit_transfer(iface->rdTr[j].tr); if(res<0){ return yLinSetErr("libusb_submit_transfer",res,errmsg); } } HALLOG("%s:%d yyySetup done\n",iface->serial,iface->ifaceno); return YAPI_SUCCESS; error: libusb_close(iface->hdl); return error; }
int yyyUSBGetInterfaces(yInterfaceSt **ifaces,int *nbifaceDetect,char *errmsg) { libusb_device **list; ssize_t nbdev; int returnval=YAPI_SUCCESS; int i,j; int nbifaceAlloc; yInterfaceSt *iface; nbdev=libusb_get_device_list(yContext->libusb,&list); if(nbdev<0) return yLinSetErr("Unable to get device list",nbdev,errmsg); HALLOG("%d devices found\n",nbdev); // allocate buffer for detected interfaces *nbifaceDetect = 0; nbifaceAlloc = nbdev*2; *ifaces = (yInterfaceSt*) yMalloc(nbifaceAlloc * sizeof(yInterfaceSt)); memset(*ifaces,0,nbifaceAlloc * sizeof(yInterfaceSt)); for(i=0; i < nbdev; i++){ int res; struct libusb_device_descriptor desc; struct libusb_config_descriptor *config; libusb_device_handle *hdl; libusb_device *dev=list[i]; if((res=libusb_get_device_descriptor(dev,&desc))!=0){ returnval = yLinSetErr("Unable to get device descriptor",res,errmsg); goto exit; } if(desc.idVendor!=YOCTO_VENDORID ){ continue; } HALLOG("open device %x:%x\n",desc.idVendor,desc.idProduct); if(getDevConfig(dev,&config)<0) continue; for(j=0 ; j < config->bNumInterfaces; j++){ //ensure the buffer of detected interface is big enough if(*nbifaceDetect == nbifaceAlloc){ yInterfaceSt *tmp; u32 newsize = nbifaceAlloc*2 * sizeof(yInterfaceSt); tmp = (yInterfaceSt*) yMalloc(newsize); memset(tmp,0,newsize); yMemcpy(tmp,*ifaces, nbifaceAlloc * sizeof(yInterfaceSt) ); yFree(*ifaces); *ifaces = tmp; nbifaceAlloc *=2; } iface = *ifaces + *nbifaceDetect; iface->vendorid = (u16)desc.idVendor; iface->deviceid = (u16)desc.idProduct; iface->ifaceno = (u16)j; iface->devref = libusb_ref_device(dev); res = libusb_open(dev,&hdl); if(res==LIBUSB_ERROR_ACCESS){ returnval =YERRMSG(YAPI_IO_ERROR,"the user has insufficient permissions to access USB devices"); goto exit; } if(res!=0){ HALLOG("unable to access device %x:%x\n",desc.idVendor,desc.idProduct); continue; } HALLOG("try to get serial for %x:%x:%x (%p)\n",desc.idVendor,desc.idProduct,desc.iSerialNumber,dev); res = getUsbStringASCII(hdl, dev, desc.iSerialNumber, iface->serial, YOCTO_SERIAL_LEN); if(res<0){ HALLOG("unable to get serial for device %x:%x\n",desc.idVendor,desc.idProduct); } libusb_close(hdl); (*nbifaceDetect)++; HALLOG("----Running Dev %x:%x:%d:%s ---\n",iface->vendorid,iface->deviceid,iface->ifaceno,iface->serial); } libusb_free_config_descriptor(config); } exit: libusb_free_device_list(list,1); return returnval; }
int yyySetup(yInterfaceSt *iface,char *errmsg) { char str[32]; int i; CFIndex deviceCount; IOHIDDeviceRef *dev_refs; if (yContext->osx_flags & YCTX_OSX_MULTIPLES_HID) { if (YISERR(setupHIDManager(yContext, &iface->hid,errmsg))) { return YAPI_IO_ERROR; } // get all device detected by the OSX dev_refs = getDevRef(&iface->hid, &deviceCount); } else { dev_refs = getDevRef(&yContext->hid, &deviceCount); } if(dev_refs == NULL) { return YERRMSG(YAPI_IO_ERROR,"Device disapear before yyySetup"); } for(i=0 ; i < deviceCount ;i++){ u16 vendorid; u16 deviceid; IOHIDDeviceRef dev = dev_refs[i]; vendorid = get_int_property(dev,CFSTR(kIOHIDVendorIDKey)); deviceid = get_int_property(dev,CFSTR(kIOHIDProductIDKey)); if (iface->vendorid == vendorid && iface->deviceid == deviceid){ char serial[YOCTO_SERIAL_LEN * 2]; memset(serial, 0, YOCTO_SERIAL_LEN * 2); get_txt_property(dev,serial,YOCTO_SERIAL_LEN * 2, CFSTR(kIOHIDSerialNumberKey)); if (YSTRCMP(serial, iface->serial) == 0){ HALLOG("right Interface detected (%x:%x:%s)\n",vendorid,deviceid,iface->serial); iface->devref = dev; break; } } } yFree(dev_refs); if (i == deviceCount) { return YERRMSG(YAPI_IO_ERROR,"Unable to match device detected"); } IOReturn ret = IOHIDDeviceOpen(iface->devref, kIOHIDOptionsTypeNone); if (ret != kIOReturnSuccess) { YSPRINTF(str,32,"Unable to open device (0x%x)",ret); return YERRMSG(YAPI_IO_ERROR,str); } yPktQueueInit(&iface->rxQueue); yPktQueueInit(&iface->txQueue); /* Create the Run Loop Mode for this device. printing the reference seems to work. */ sprintf(str, "yocto_%p", iface->devref); iface->run_loop_mode = CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); /* Attach the device to a Run Loop */ IOHIDDeviceScheduleWithRunLoop(iface->devref, yContext->usb_run_loop, iface->run_loop_mode); IOHIDDeviceRegisterInputReportCallback( iface->devref, // IOHIDDeviceRef for the HID device (u8*) &iface->tmprxpkt, // pointer to the report data USB_PKT_SIZE, // number of bytes in the report (CFIndex) &Handle_IOHIDDeviceIOHIDReportCallback, // the callback routine iface); // context passed to callback // save setuped iface pointer in context in order // to retreive it durring unplugcallback for (i=0; i< SETUPED_IFACE_CACHE_SIZE ; i++) { if(yContext->setupedIfaceCache[i]==NULL){ yContext->setupedIfaceCache[i] = iface; break; } } if (i==SETUPED_IFACE_CACHE_SIZE) { return YERRMSG(YAPI_IO_ERROR,"Too many setuped USB interfaces"); } iface->flags.yyySetupDone = 1; return 0; }
// on success data point to a null terminated string of max length-1 characters static int getUsbStringASCII(libusb_device_handle *hdl, libusb_device *dev, u8 desc_index, char *data, u32 length) { u8 buffer[512]; u32 l,len; int res,i; stringCacheSt *c = stringCache; stringCacheSt *f = NULL; u64 now = yapiGetTickCount(); yEnterCriticalSection(&yContext->string_cache_cs); for (i = 0; i < STRING_CACHE_SIZE; i++, c++) { if (c->expiration > now) { if(c->dev == dev && c->desc_index == desc_index) { if (c->len > 0 && c->string) { len = c->len; if (c->len >= length) len = length-1; memcpy(data, c->string, len); data[len] = 0; HALLOG("return string from cache (%p:%d->%s)\n",dev,desc_index,c->string); yLeaveCriticalSection(&yContext->string_cache_cs); return c->len; } else { f = c; break; } } } else { if (c->string) { yFree(c->string); c->string =NULL; } if (f == NULL) { f = c; } } } res=libusb_control_transfer(hdl, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc_index, 0, buffer, 512, 10000); if(res<0) return res; len=(buffer[0]-2)/2; if (len >= length) { len = length - 1; } for (l = 0; l < len; l++){ data[l] = (char) buffer[2+(l*2)]; } data[len] = 0; if (f != NULL) { f->dev = dev; f->desc_index = desc_index; f->string = yMalloc(len+1); memcpy(f->string, data, len+1); f->len = len; f->expiration = yapiGetTickCount() + STRING_CACHE_EXPIRATION; HALLOG("add string to cache (%p:%d->%s)\n",dev,desc_index,f->string); } yLeaveCriticalSection(&yContext->string_cache_cs); return len; }