0

I am moderately familiar with Python, but I am a beginner to C, C-extensions and IO Kit. I have read the C-extensions section of "Supporting Python 3", but might still be misunderstanding something fundamental.

I have a C-extension which works in Python 2, and I am trying to migrate it to Python 3. It uses Apple's IO Kit framework to detect some information about a USB device connected to an Apple computer. Here is the code which works in Python 2:

static PyObject * devGetDescriptor(PyObject *self, PyObject *args) {
    storedState_t *ss = NULL;
    PyObject *cobj = NULL;
    byte_t buf[256];
    IOUSBDevRequest request;
    IOReturn err;                    
    byte_t idx = kUSBDeviceDesc;

    if(!PyArg_ParseTuple(args, "O!|b", &PyCObject_Type, &cobj, &idx)) {
        return NULL;
    }
    ss = PyCObject_AsVoidPtr(cobj);

    // populate the request
    request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard,
                                                        kUSBDevice);
    request.bRequest = kUSBRqGetDescriptor;
    request.wValue = (idx << 8) | 0;
    request.wIndex = 0;
    request.wLength = 255;
    request.pData = buf;

    // do it
    err = (*ss->dev)->DeviceRequest(ss->dev, &request);
    if(err) return IOKIT_EXCEPTION(err);

    // copy the result to caller
    return PyString_FromStringAndSize((char*)buf, buf[0]);
}

Here is the definition for storedState_t:

typedef struct
{
    IOUSBDeviceInterface245 **dev;

    // ...

} storedState_t;

Here is my attempt at converting it to code which works in Python 3, it causes a seg fault:

static PyObject * devGetDescriptor(PyObject *self, PyObject *args) {
    storedState_t *ss = NULL;
    PyObject *cobj = NULL;
    byte_t buf[256];
    IOUSBDevRequest request;
    IOReturn err;
    byte_t idx = kUSBDeviceDesc;

    if (!PyArg_ParseTuple(args, "O|b", &cobj, &idx))
    {
        return NULL;
    }
    ss = PyCapsule_New(cobj, NULL, NULL); // changed to PyCapsule

    // populate the request
    request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard,
                                                 kUSBDevice);
    request.bRequest = kUSBRqGetDescriptor;
    request.wValue = (idx << 8) | 0;
    request.wIndex = 0;
    request.wLength = 255;
    request.pData = buf;

    // do it
    err = (*ss->dev)->DeviceRequest(ss->dev, &request); // Causes Seg Fault
    if (err)
        return IOKIT_EXCEPTION(err);

    // copy the result to caller
    return PyUnicode_FromStringAndSize((char *)buf, buf[0]);
}

I believe the problem is with the line err = (*ss->dev)->DeviceRequest(ss->dev, &request);. I know seg fault means one of the memory locations trying to be accessed in invalid, but I don't know which one is invalid nor how to fix it.

79037662
  • 117
  • 5

0 Answers0