#include <usb.h>
#include <string.h>
+#include <errno.h>
#include "ftdi.h"
#define ftdi_error_return(code, str) do { \
ftdi->error_str = str; \
return code; \
- } while(0);
+ } while(0);
/* ftdi_init
-2: usb_find_devices() failed
-3: out of memory
*/
-int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devlist, int vendor, int product)
+int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devlist, int vendor, int product)
{
struct ftdi_device_list **curdev;
struct usb_bus *bus;
struct usb_device *dev;
int count = 0;
-
+
usb_init();
if (usb_find_busses() < 0)
ftdi_error_return(-1, "usb_find_busses() failed");
*curdev = (struct ftdi_device_list*)malloc(sizeof(struct ftdi_device_list));
if (!*curdev)
ftdi_error_return(-3, "out of memory");
-
+
(*curdev)->next = NULL;
(*curdev)->dev = dev;
}
}
}
-
+
return count;
}
Frees a created device list.
*/
-void ftdi_list_free(struct ftdi_device_list **devlist)
+void ftdi_list_free(struct ftdi_device_list **devlist)
{
struct ftdi_device_list **curdev;
for (; *devlist == NULL; devlist = curdev) {
devlist = NULL;
}
-/* ftdi_usb_open_dev
+/* ftdi_usb_open_dev
Opens a ftdi device given by a usb_device.
*/
int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev)
{
+ int detach_errno = 0;
if (!(ftdi->usb_dev = usb_open(dev)))
ftdi_error_return(-4, "usb_open() failed");
-
+
+#ifdef LIBUSB_HAS_GET_DRIVER_NP
+ // Try to detach ftdi_sio kernel module
+ // Returns ENODATA if driver is not loaded
+ if (usb_detach_kernel_driver_np(ftdi->usb_dev, ftdi->interface) != 0 && errno != ENODATA)
+ detach_errno = errno;
+#endif
+
if (usb_claim_interface(ftdi->usb_dev, ftdi->interface) != 0) {
usb_close (ftdi->usb_dev);
- ftdi_error_return(-5, "unable to claim usb device. Make sure ftdi_sio is unloaded!");
+ if (detach_errno == EPERM) {
+ ftdi_error_return(-8, "inappropriate permissions on device!");
+ } else {
+ ftdi_error_return(-5, "unable to claim usb device. Make sure ftdi_sio is unloaded!");
+ }
}
if (ftdi_usb_reset (ftdi) != 0) {
if (usb_close (ftdi->usb_dev) != 0)
ftdi_error_return(-10, "unable to close device");
-
+
return ftdi_usb_open_dev(ftdi, dev);
}
}
-1: Setting line property failed
*/
int ftdi_set_line_property(struct ftdi_context *ftdi, enum ftdi_bits_type bits,
- enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
+ enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity)
{
unsigned short value = bits;
value |= (0x04 << 8);
break;
}
-
+
switch(sbit) {
case STOP_BIT_1:
value |= (0x00 << 11);
value |= (0x02 << 11);
break;
}
-
+
if (usb_control_msg(ftdi->usb_dev, 0x40, 0x04, value, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)
ftdi_error_return (-1, "Setting new line property failed");
-
+
return 0;
}
int ftdi_setflowctrl(struct ftdi_context *ftdi, int flowctrl)
{
if (usb_control_msg(ftdi->usb_dev, SIO_SET_FLOW_CTRL_REQUEST_TYPE,
- SIO_SET_FLOW_CTRL_REQUEST, 0, (flowctrl | ftdi->interface),
- NULL, 0, ftdi->usb_write_timeout) != 0)
- ftdi_error_return(-1, "set flow control failed");
+ SIO_SET_FLOW_CTRL_REQUEST, 0, (flowctrl | ftdi->interface),
+ NULL, 0, ftdi->usb_write_timeout) != 0)
+ ftdi_error_return(-1, "set flow control failed");
return 0;
}
{
unsigned short usb_val;
- if (state)
+ if (state)
usb_val = SIO_SET_DTR_HIGH;
else
usb_val = SIO_SET_DTR_LOW;
if (usb_control_msg(ftdi->usb_dev, SIO_SET_MODEM_CTRL_REQUEST_TYPE,
- SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->interface,
- NULL, 0, ftdi->usb_write_timeout) != 0)
- ftdi_error_return(-1, "set dtr failed");
+ SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->interface,
+ NULL, 0, ftdi->usb_write_timeout) != 0)
+ ftdi_error_return(-1, "set dtr failed");
return 0;
}
{
unsigned short usb_val;
- if (state)
+ if (state)
usb_val = SIO_SET_RTS_HIGH;
else
usb_val = SIO_SET_RTS_LOW;
- if (usb_control_msg(ftdi->usb_dev, SIO_SET_MODEM_CTRL_REQUEST_TYPE,
- SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->interface,
- NULL, 0, ftdi->usb_write_timeout) != 0)
- ftdi_error_return(-1, "set of rts failed");
+ if (usb_control_msg(ftdi->usb_dev, SIO_SET_MODEM_CTRL_REQUEST_TYPE,
+ SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->interface,
+ NULL, 0, ftdi->usb_write_timeout) != 0)
+ ftdi_error_return(-1, "set of rts failed");
return 0;
}