IOIKIT callback failure

Discussion in 'Mac Programming' started by E1000, Jul 31, 2011.

  1. E1000 macrumors newbie

    Joined:
    Jul 14, 2011
    #1
    Hi everyone,

    I'm a bit desperate, as I can not seem to get this to work. I'm writing an application that communicates with an PIC 18F over USB. I've got the program running so far that I can send commands. Only receiving data isn't working. I've made an object, USBController, that takes care of all the USB stuff. Here is a part of it's code (full code included at bottom), I think something goes wrong here:

    Code:
    //
    #include <CoreFoundation/CoreFoundation.h>
    #include <Carbon/Carbon.h>
    
    #import "USBController.h"
    
    //The callback function
    static void Handle_IOHIDDeviceIOHIDReportCallback(void *context, IOReturn result, void *sender,
    								IOHIDReportType report_type, uint32_t report_id,
    								uint8_t *report, CFIndex report_length)
    {
    	printf("hello");
    }
    
    @implementation USBController
    
    - (void)ConnectToDevice{	
    
    //...
    
            IOHIDDeviceScheduleWithRunLoop(tIOHIDDeviceRefs[0], CFRunLoopGetCurrent(), runloopmode);//kCFRunLoopDefaultMode);
    		
    	CFIndex reportSize = 128;    // note: this should be greater than or equal to the size of the report
    	uint8_t report = malloc(reportSize);
    	IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize, Handle_IOHIDDeviceIOHIDReportCallback, (void*)self);
    
    //...
    
    }
    @end
    
    
    I get an "exc_bad_access" error when I send the command 0x81 to the PIC, which on that command returns the status of its input ports. I wasn't able to find any objects with Zombies. This was my stack content:

    Code:
    #0	0x7fffffe007c5 in __memcpy
    #1	0x102709d6e in IOHIDDeviceClass::_hidReportHandlerCallback
    #2	0x7fff8839468e in __CFMachPortPerform
    #3	0x7fff8836c6e1 in __CFRunLoopRun
    #4	0x7fff8836adbf in CFRunLoopRunSpecific
    #5	0x7fff8885193a in RunCurrentEventLoopInMode
    #6	0x7fff8885173f in ReceiveNextEventCommon
    #7	0x7fff888515f8 in BlockUntilNextEventMatchingListInMode
    #8	0x7fff861bfe64 in _DPSNextEvent
    #9	0x7fff861bf7a9 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
    #10	0x7fff8618548b in -[NSApplication run]
    #11	0x7fff8617e1a8 in NSApplicationMain
    #12	0x100000c55 in main at main.m:13
    Does somebody know what's wrong? Is there some setting I have to set to enable Callbacks? I think I followed the HID guide pretty closely, and I have the setup working when I run it with hidapi...
    Thanks in advance,
    Emiel

    This is the complete code:

    Code:
    //
    //  USBController.m
    //  usbtest
    //
    //  Created by Emiel van de Ven on 27-07-11.
    //  Copyright 2011 __MyCompanyName__. All rights reserved.
    //
    #include <CoreFoundation/CoreFoundation.h>
    #include <Carbon/Carbon.h>
    
    #import "USBController.h"
    
    //The callback function
    static void Handle_IOHIDDeviceIOHIDReportCallback(void *context, IOReturn result, void *sender,
    								IOHIDReportType report_type, uint32_t report_id,
    								uint8_t *report, CFIndex report_length)
    {
    	printf("hello");
    }
    
    @implementation USBController
    
    - (CFMutableDictionaryRef)CreateMatchingDictionary:(UInt32)VID ProductionID:(UInt32)PID {
    	
        CFMutableDictionaryRef matchingDictionary = NULL;
    	
        // Set up a matching dictionary to search I/O Registry by class name for all HID class devices.
        matchingDictionary = IOServiceMatching (kIOHIDDeviceKey);
    	
        if (matchingDictionary != NULL)
        {
    		CFNumberRef cfValue;
    		
    		cfValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type, &VID );
    		CFDictionaryAddValue( matchingDictionary, CFSTR("VendorID"),
    							 cfValue);
    		
    		cfValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type, &PID );
    		CFDictionaryAddValue( matchingDictionary, CFSTR("ProductID"),
    							 cfValue);
            
        }
        else
            printf ("Failed to get HID CFMutableDictionaryRef via IOServiceMatching.");
    		
    		//printf ("Failed to get HID CFMutableDictionaryRef via IOServiceMatching.");
        return matchingDictionary;
    	
    }
    - (void)ConnectToDevice{	
    	
    	tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone );
    	
    	// Create a device matching dictionary
    	CFDictionaryRef matchingCFDictRef = [self CreateMatchingDictionary:0x04D8 ProductionID:0x0042];
    	
    	// set the HID device matching dictionary
    	IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef );
    	
    	// Now open the IO HID Manager reference
    	IOReturn tIOReturn = IOHIDManagerOpen( tIOHIDManagerRef, kIOHIDOptionsTypeNone );
    	
    	// and copy out its devices
    	CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef );
    
    	// how many devices in the set?
    	CFIndex deviceIndex, deviceCount = CFSetGetCount( deviceCFSetRef );
    	deviceIndex = 0;
    
    	// allocate a block of memory to extact the device ref's from the set into
    	tIOHIDDeviceRefs = calloc(deviceCount, sizeof( IOHIDDeviceRef ) );
    
    	// now extract the device ref's from the set
    	CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs );
    	
    	// open the device
    	IOReturn ret = IOHIDDeviceOpen(tIOHIDDeviceRefs[0], kIOHIDOptionsTypeNone);
    	if (ret == kIOReturnSuccess) {
    		//schedule with runloop
    		IOHIDDeviceScheduleWithRunLoop(tIOHIDDeviceRefs[0], CFRunLoopGetCurrent(), runloopmode);//kCFRunLoopDefaultMode);
    		
    		CFIndex reportSize = 128;    // note: this should be greater than or equal to the size of the report
    		uint8_t report = malloc(reportSize);
    		IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize, Handle_IOHIDDeviceIOHIDReportCallback, (void*)self);
    
    		char data[256];
    		size_t length_to_send;
    		
    		data[0] = 0x81; //ask for data
    		length_to_send = 1;
    		
    		//send to device
    		IOHIDDeviceSetReport(tIOHIDDeviceRefs[0],
    							 kIOHIDReportTypeOutput,
    							 data[0], /* Report ID*/
    							 (const unsigned char*)data, length_to_send);
         }
    }
    @end
    
    
     
  2. Mr. Retrofire macrumors 601

    Mr. Retrofire

    Joined:
    Mar 2, 2010
    Location:
    www.emiliana.cl/en
    #2
    You should check the validity of the values in tIOHIDDeviceRefs

    after
    Code:
    CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs );
    You also do not close the device via IOHIDDeviceClose, in your code. Why?
     
  3. E1000 thread starter macrumors newbie

    Joined:
    Jul 14, 2011
    #3
    The tIOHIDDeviceRefs seems to be valid, I checked it with:

    Code:
    if (CFGetTypeID(tIOHIDDeviceRefs[0]) == IOHIDDeviceGetTypeID()) {
            printf("valid");
    }
    All the closing is done in an other method of USBController. I would first like to get the opening/sending/reading part to work before focussing on closing everything..
     

Share This Page