From: Thomas Jarosch Date: Fri, 19 Feb 2010 22:14:04 +0000 (+0100) Subject: Protect against segfault if device is closed or ftdi context is invalid X-Git-Tag: v0.18~15 X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=commitdiff_plain;h=8970ed7e36f5f4aa85dd5c3a47ee5d2e1044a870 Protect against segfault if device is closed or ftdi context is invalid This will help mulithreaded applications which do proper locking around the ftdi_xxx() functions and one thread already closed the USB device -> Zonk! Thanks to Thomas Klose for reporting the issue. --- diff --git a/src/ftdi.c b/src/ftdi.c index 9740fca..6db70f1 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -2,7 +2,7 @@ ftdi.c - description ------------------- begin : Fri Apr 4 2003 - copyright : (C) 2003-2008 by Intra2net AG + copyright : (C) 2003-2010 by Intra2net AG email : opensource@intra2net.com ***************************************************************************/ @@ -64,7 +64,7 @@ static int ftdi_usb_close_internal (struct ftdi_context *ftdi) { int ret = 0; - if (ftdi->usb_dev) + if (ftdi && ftdi->usb_dev) { ret = usb_close (ftdi->usb_dev); ftdi->usb_dev = NULL; @@ -159,9 +159,13 @@ struct ftdi_context *ftdi_new(void) \retval 0: all fine \retval -1: unknown interface + \retval -2: USB device unavailable */ int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + switch (interface) { case INTERFACE_ANY: @@ -199,6 +203,9 @@ int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface) */ void ftdi_deinit(struct ftdi_context *ftdi) { + if (ftdi == NULL) + return; + ftdi_usb_close_internal (ftdi); if (ftdi->async_usb_buffer != NULL) @@ -233,6 +240,9 @@ void ftdi_free(struct ftdi_context *ftdi) */ void ftdi_set_usbdev (struct ftdi_context *ftdi, usb_dev_handle *usb) { + if (ftdi == NULL) + return; + ftdi->usb_dev = usb; } @@ -396,6 +406,10 @@ static unsigned int _ftdi_determine_max_packet_size(struct ftdi_context *ftdi, s { unsigned int packet_size; + // Sanity check + if (ftdi == NULL || dev == NULL) + return 64; + // Determine maximum packet size. Init with default value. // New hi-speed devices from FTDI use a packet size of 512 bytes // but could be connected to a normal speed USB hub -> 64 bytes packet size. @@ -437,11 +451,16 @@ static unsigned int _ftdi_determine_max_packet_size(struct ftdi_context *ftdi, s \retval -5: unable to claim device \retval -6: reset failed \retval -7: set baudrate failed + \retval -8: ftdi context invalid */ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) { int detach_errno = 0; int config_val = 1; + + if (ftdi == NULL) + ftdi_error_return(-8, "ftdi context invalid"); + if (!(ftdi->usb_dev = usb_open(dev))) ftdi_error_return(-4, "usb_open() failed"); @@ -608,6 +627,7 @@ int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, \retval -8: get product description failed \retval -9: get serial number failed \retval -10: unable to close device + \retval -11: ftdi context invalid */ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, const char* description, const char* serial, unsigned int index) @@ -623,6 +643,9 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, if (usb_find_devices() < 0) ftdi_error_return(-2, "usb_find_devices() failed"); + if (ftdi == NULL) + ftdi_error_return(-11, "ftdi context invalid"); + for (bus = usb_get_busses(); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) @@ -705,9 +728,13 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, \retval -9: get serial number failed \retval -10: unable to close device \retval -11: illegal description format + \retval -12: ftdi context invalid */ int ftdi_usb_open_string(struct ftdi_context *ftdi, const char* description) { + if (ftdi == NULL) + ftdi_error_return(-12, "ftdi context invalid"); + if (description[0] == 0 || description[1] != ':') ftdi_error_return(-11, "illegal description format"); @@ -799,9 +826,13 @@ int ftdi_usb_open_string(struct ftdi_context *ftdi, const char* description) \retval 0: all fine \retval -1: FTDI reset failed + \retval -2: USB device unavailable */ int ftdi_usb_reset(struct ftdi_context *ftdi) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, SIO_RESET_SIO, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) @@ -821,9 +852,13 @@ int ftdi_usb_reset(struct ftdi_context *ftdi) \retval 0: all fine \retval -1: read buffer purge failed + \retval -2: USB device unavailable */ int ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, SIO_RESET_PURGE_RX, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) @@ -843,9 +878,13 @@ int ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi) \retval 0: all fine \retval -1: write buffer purge failed + \retval -2: USB device unavailable */ int ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, SIO_RESET_PURGE_TX, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) @@ -862,11 +901,15 @@ int ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi) \retval 0: all fine \retval -1: read buffer purge failed \retval -2: write buffer purge failed + \retval -3: USB device unavailable */ int ftdi_usb_purge_buffers(struct ftdi_context *ftdi) { int result; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-3, "USB device unavailable"); + result = ftdi_usb_purge_rx_buffer(ftdi); if (result < 0) return -1; @@ -888,11 +931,15 @@ int ftdi_usb_purge_buffers(struct ftdi_context *ftdi) \retval 0: all fine \retval -1: usb_release failed \retval -2: usb_close failed + \retval -3: ftdi context invalid */ int ftdi_usb_close(struct ftdi_context *ftdi) { int rtn = 0; + if (ftdi == NULL) + ftdi_error_return(-3, "ftdi context invalid"); + #ifdef LIBFTDI_LINUX_ASYNC_MODE /* try to release some kernel resources */ ftdi_async_complete(ftdi,1); @@ -1043,12 +1090,16 @@ static int ftdi_convert_baudrate(int baudrate, struct ftdi_context *ftdi, \retval 0: all fine \retval -1: invalid baudrate \retval -2: setting baudrate failed + \retval -3: USB device unavailable */ int ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate) { unsigned short value, index; int actual_baudrate; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-3, "USB device unavailable"); + if (ftdi->bitbang_enabled) { baudrate = baudrate*4; @@ -1104,6 +1155,7 @@ int ftdi_set_line_property(struct ftdi_context *ftdi, enum ftdi_bits_type bits, \retval 0: all fine \retval -1: Setting line property failed + \retval -2: USB device unavailable */ int ftdi_set_line_property2(struct ftdi_context *ftdi, enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity, @@ -1111,6 +1163,9 @@ int ftdi_set_line_property2(struct ftdi_context *ftdi, enum ftdi_bits_type bits, { unsigned short value = bits; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + switch (parity) { case NONE: @@ -1168,6 +1223,7 @@ int ftdi_set_line_property2(struct ftdi_context *ftdi, enum ftdi_bits_type bits, \param buf Buffer with the data \param size Size of the buffer + \retval -666: USB device unavailable \retval <0: error code from usb_bulk_write() \retval >0: number of bytes written */ @@ -1177,6 +1233,9 @@ int ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size) int offset = 0; int total_written = 0; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-666, "USB device unavailable"); + while (offset < size) { int write_size = ftdi->writebuffer_chunksize; @@ -1381,6 +1440,7 @@ static int _usb_bulk_write_async(struct ftdi_context *ftdi, int ep, char *bytes, \param buf Buffer with the data \param size Size of the buffer + \retval -666: USB device unavailable \retval <0: error code from usb_bulk_write() \retval >0: number of bytes written */ @@ -1390,6 +1450,9 @@ int ftdi_write_data_async(struct ftdi_context *ftdi, unsigned char *buf, int siz int offset = 0; int total_written = 0; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-666, "USB device unavailable"); + while (offset < size) { int write_size = ftdi->writebuffer_chunksize; @@ -1417,9 +1480,13 @@ int ftdi_write_data_async(struct ftdi_context *ftdi, unsigned char *buf, int siz \param chunksize Chunk size \retval 0: all fine + \retval -1: ftdi context invalid */ int ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize) { + if (ftdi == NULL) + ftdi_error_return(-1, "ftdi context invalid"); + ftdi->writebuffer_chunksize = chunksize; return 0; } @@ -1431,9 +1498,13 @@ int ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunks \param chunksize Pointer to store chunk size in \retval 0: all fine + \retval -1: ftdi context invalid */ int ftdi_write_data_get_chunksize(struct ftdi_context *ftdi, unsigned int *chunksize) { + if (ftdi == NULL) + ftdi_error_return(-1, "ftdi context invalid"); + *chunksize = ftdi->writebuffer_chunksize; return 0; } @@ -1447,6 +1518,7 @@ int ftdi_write_data_get_chunksize(struct ftdi_context *ftdi, unsigned int *chunk \param buf Buffer to store data in \param size Size of the buffer + \retval -666: USB device unavailable \retval <0: error code from usb_bulk_read() \retval 0: no data was available \retval >0: number of bytes read @@ -1455,8 +1527,12 @@ int ftdi_write_data_get_chunksize(struct ftdi_context *ftdi, unsigned int *chunk int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) { int offset = 0, ret = 1, i, num_of_chunks, chunk_remains; - int packet_size = ftdi->max_packet_size; + int packet_size; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-666, "USB device unavailable"); + + packet_size = ftdi->max_packet_size; // Packet size sanity check (avoid division by zero) if (packet_size == 0) ftdi_error_return(-1, "max_packet_size is bogus (zero)"); @@ -1571,11 +1647,15 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) \param chunksize Chunk size \retval 0: all fine + \retval -1: ftdi context invalid */ int ftdi_read_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize) { unsigned char *new_buf; + if (ftdi == NULL) + ftdi_error_return(-1, "ftdi context invalid"); + // Invalidate all remaining data ftdi->readbuffer_offset = 0; ftdi->readbuffer_remaining = 0; @@ -1596,9 +1676,13 @@ int ftdi_read_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksi \param chunksize Pointer to store chunk size in \retval 0: all fine + \retval -1: FTDI context invalid */ int ftdi_read_data_get_chunksize(struct ftdi_context *ftdi, unsigned int *chunksize) { + if (ftdi == NULL) + ftdi_error_return(-1, "FTDI context invalid"); + *chunksize = ftdi->readbuffer_chunksize; return 0; } @@ -1615,11 +1699,15 @@ int ftdi_read_data_get_chunksize(struct ftdi_context *ftdi, unsigned int *chunks \retval 0: all fine \retval -1: can't enable bitbang mode + \retval -2: USB device unavailable */ int ftdi_enable_bitbang(struct ftdi_context *ftdi, unsigned char bitmask) { unsigned short usb_val; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + usb_val = bitmask; // low byte: bitmask /* FT2232C: Set bitbang_mode to 2 to enable SPI */ usb_val |= (ftdi->bitbang_mode << 8); @@ -1640,9 +1728,13 @@ int ftdi_enable_bitbang(struct ftdi_context *ftdi, unsigned char bitmask) \retval 0: all fine \retval -1: can't disable bitbang mode + \retval -2: USB device unavailable */ int ftdi_disable_bitbang(struct ftdi_context *ftdi) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_BITMODE_REQUEST, 0, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "unable to leave bitbang mode. Perhaps not a BM type chip?"); @@ -1660,11 +1752,15 @@ int ftdi_disable_bitbang(struct ftdi_context *ftdi) \retval 0: all fine \retval -1: can't enable bitbang mode + \retval -2: USB device unavailable */ int ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode) { unsigned short usb_val; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + usb_val = bitmask; // low byte: bitmask usb_val |= (mode << 8); if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_BITMODE_REQUEST, usb_val, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) @@ -1683,9 +1779,13 @@ int ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned \retval 0: all fine \retval -1: read pins failed + \retval -2: USB device unavailable */ int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_PINS_REQUEST, 0, ftdi->index, (char *)pins, 1, ftdi->usb_read_timeout) != 1) ftdi_error_return(-1, "read pins failed"); @@ -1705,6 +1805,7 @@ int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins) \retval 0: all fine \retval -1: latency out of range \retval -2: unable to set latency timer + \retval -3: USB device unavailable */ int ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency) { @@ -1713,6 +1814,9 @@ int ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency) if (latency < 1) ftdi_error_return(-1, "latency out of range. Only valid for 1-255"); + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-3, "USB device unavailable"); + usb_val = latency; if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_LATENCY_TIMER_REQUEST, usb_val, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-2, "unable to set latency timer"); @@ -1728,10 +1832,15 @@ int ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency) \retval 0: all fine \retval -1: unable to get latency timer + \retval -2: USB device unavailable */ int ftdi_get_latency_timer(struct ftdi_context *ftdi, unsigned char *latency) { unsigned short usb_val; + + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_GET_LATENCY_TIMER_REQUEST, 0, ftdi->index, (char *)&usb_val, 1, ftdi->usb_read_timeout) != 1) ftdi_error_return(-1, "reading latency timer failed"); @@ -1777,11 +1886,15 @@ int ftdi_get_latency_timer(struct ftdi_context *ftdi, unsigned char *latency) \retval 0: all fine \retval -1: unable to retrieve status information + \retval -2: USB device unavailable */ int ftdi_poll_modem_status(struct ftdi_context *ftdi, unsigned short *status) { char usb_val[2]; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_POLL_MODEM_STATUS_REQUEST, 0, ftdi->index, usb_val, 2, ftdi->usb_read_timeout) != 2) ftdi_error_return(-1, "getting modem status failed"); @@ -1799,9 +1912,13 @@ int ftdi_poll_modem_status(struct ftdi_context *ftdi, unsigned short *status) \retval 0: all fine \retval -1: set flow control failed + \retval -2: USB device unavailable */ int ftdi_setflowctrl(struct ftdi_context *ftdi, int flowctrl) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_FLOW_CTRL_REQUEST, 0, (flowctrl | ftdi->index), NULL, 0, ftdi->usb_write_timeout) != 0) @@ -1818,11 +1935,15 @@ int ftdi_setflowctrl(struct ftdi_context *ftdi, int flowctrl) \retval 0: all fine \retval -1: set dtr failed + \retval -2: USB device unavailable */ int ftdi_setdtr(struct ftdi_context *ftdi, int state) { unsigned short usb_val; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (state) usb_val = SIO_SET_DTR_HIGH; else @@ -1843,12 +1964,16 @@ int ftdi_setdtr(struct ftdi_context *ftdi, int state) \param state state to set line to (1 or 0) \retval 0: all fine - \retval -1 set rts failed + \retval -1: set rts failed + \retval -2: USB device unavailable */ int ftdi_setrts(struct ftdi_context *ftdi, int state) { unsigned short usb_val; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (state) usb_val = SIO_SET_RTS_HIGH; else @@ -1863,19 +1988,23 @@ int ftdi_setrts(struct ftdi_context *ftdi, int state) } /** - Set dtr and rts line in one pass + Set dtr and rts line in one pass - \param ftdi pointer to ftdi_context - \param dtr DTR state to set line to (1 or 0) - \param rts RTS state to set line to (1 or 0) + \param ftdi pointer to ftdi_context + \param dtr DTR state to set line to (1 or 0) + \param rts RTS state to set line to (1 or 0) - \retval 0: all fine - \retval -1 set dtr/rts failed + \retval 0: all fine + \retval -1: set dtr/rts failed + \retval -2: USB device unavailable */ int ftdi_setdtr_rts(struct ftdi_context *ftdi, int dtr, int rts) { unsigned short usb_val; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (dtr) usb_val = SIO_SET_DTR_HIGH; else @@ -1903,12 +2032,16 @@ int ftdi_setdtr_rts(struct ftdi_context *ftdi, int dtr, int rts) \retval 0: all fine \retval -1: unable to set event character + \retval -2: USB device unavailable */ int ftdi_set_event_char(struct ftdi_context *ftdi, unsigned char eventch, unsigned char enable) { unsigned short usb_val; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + usb_val = eventch; if (enable) usb_val |= 1 << 8; @@ -1928,12 +2061,16 @@ int ftdi_set_event_char(struct ftdi_context *ftdi, \retval 0: all fine \retval -1: unable to set error character + \retval -2: USB device unavailable */ int ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch, unsigned char enable) { unsigned short usb_val; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + usb_val = errorch; if (enable) usb_val |= 1 << 8; @@ -1954,6 +2091,9 @@ int ftdi_set_error_char(struct ftdi_context *ftdi, */ void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom *eeprom, int size) { + if (ftdi == NULL) + return; + ftdi->eeprom_size=size; eeprom->size=size; } @@ -1965,6 +2105,9 @@ void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom *eeprom, */ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) { + if (eeprom == NULL) + return; + eeprom->vendor_id = 0x0403; eeprom->product_id = 0x6001; @@ -1989,14 +2132,15 @@ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) } /** - Build binary output from ftdi_eeprom structure. - Output is suitable for ftdi_write_eeprom(). + Build binary output from ftdi_eeprom structure. + Output is suitable for ftdi_write_eeprom(). - \param eeprom Pointer to ftdi_eeprom - \param output Buffer of 128 bytes to store eeprom image to + \param eeprom Pointer to ftdi_eeprom + \param output Buffer of 128 bytes to store eeprom image to - \retval >0: used eeprom size - \retval -1: eeprom size (128 bytes) exceeded by custom strings + \retval >0: used eeprom size + \retval -1: eeprom size (128 bytes) exceeded by custom strings + \retval -2: Invalid eeprom pointer */ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) { @@ -2005,6 +2149,9 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; int size_check; + if (eeprom == NULL) + return -2; + if (eeprom->manufacturer != NULL) manufacturer_size = strlen(eeprom->manufacturer); if (eeprom->product != NULL) @@ -2183,6 +2330,9 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; int size_check; int eeprom_size = 128; + + if (eeprom == NULL) + return -1; #if 0 size_check = eeprom->size; size_check -= 28; // 28 are always in use (fixed) @@ -2338,9 +2488,13 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) \retval 0: all fine \retval -1: read failed + \retval -2: USB device unavailable */ int ftdi_read_eeprom_location (struct ftdi_context *ftdi, int eeprom_addr, unsigned short *eeprom_val) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, eeprom_addr, (char *)eeprom_val, 2, ftdi->usb_read_timeout) != 2) ftdi_error_return(-1, "reading eeprom failed"); @@ -2355,11 +2509,15 @@ int ftdi_read_eeprom_location (struct ftdi_context *ftdi, int eeprom_addr, unsig \retval 0: all fine \retval -1: read failed + \retval -2: USB device unavailable */ int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) { int i; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + for (i = 0; i < ftdi->eeprom_size/2; i++) { if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, i, eeprom+(i*2), 2, ftdi->usb_read_timeout) != 2) @@ -2394,11 +2552,15 @@ static unsigned char ftdi_read_chipid_shift(unsigned char value) \retval 0: all fine \retval -1: read failed + \retval -2: USB device unavailable */ int ftdi_read_chipid(struct ftdi_context *ftdi, unsigned int *chipid) { unsigned int a = 0, b = 0; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, 0x43, (char *)&a, 2, ftdi->usb_read_timeout) == 2) { a = a << 8 | a >> 8; @@ -2417,20 +2579,25 @@ int ftdi_read_chipid(struct ftdi_context *ftdi, unsigned int *chipid) } /** - Guesses size of eeprom by reading eeprom and comparing halves - will not work with blank eeprom - Call this function then do a write then call again to see if size changes, if so write again. + Guesses size of eeprom by reading eeprom and comparing halves - will not work with blank eeprom + Call this function then do a write then call again to see if size changes, if so write again. - \param ftdi pointer to ftdi_context - \param eeprom Pointer to store eeprom into - \param maxsize the size of the buffer to read into + \param ftdi pointer to ftdi_context + \param eeprom Pointer to store eeprom into + \param maxsize the size of the buffer to read into - \retval size of eeprom + \retval -1: eeprom read failed + \retval -2: USB device unavailable + \retval >=0: size of eeprom */ int ftdi_read_eeprom_getsize(struct ftdi_context *ftdi, unsigned char *eeprom, int maxsize) { int i=0,j,minsize=32; int size=minsize; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + do { for (j = 0; i < maxsize/2 && jusb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, i, eeprom+(i*2), 2, ftdi->usb_read_timeout) != 2) - ftdi_error_return(-1, "reading eeprom failed"); + ftdi_error_return(-1, "eeprom read failed"); i++; } size*=2; @@ -2457,9 +2624,13 @@ int ftdi_read_eeprom_getsize(struct ftdi_context *ftdi, unsigned char *eeprom, i \retval 0: all fine \retval -1: read failed + \retval -2: USB device unavailable */ int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr, unsigned short eeprom_val) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_WRITE_EEPROM_REQUEST, eeprom_val, eeprom_addr, NULL, 0, ftdi->usb_write_timeout) != 0) @@ -2476,12 +2647,16 @@ int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr, unsig \retval 0: all fine \retval -1: read failed + \retval -2: USB device unavailable */ int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) { unsigned short usb_val, status; int i, ret; + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + /* These commands were traced while running MProg */ if ((ret = ftdi_usb_reset(ftdi)) != 0) return ret; @@ -2512,9 +2687,13 @@ int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) \retval 0: all fine \retval -1: erase failed + \retval -2: USB device unavailable */ int ftdi_erase_eeprom(struct ftdi_context *ftdi) { + if (ftdi == NULL || ftdi->usb_dev == NULL) + ftdi_error_return(-2, "USB device unavailable"); + if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_ERASE_EEPROM_REQUEST, 0, 0, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "unable to erase eeprom"); @@ -2530,6 +2709,9 @@ int ftdi_erase_eeprom(struct ftdi_context *ftdi) */ char *ftdi_get_error_string (struct ftdi_context *ftdi) { + if (ftdi == NULL) + return ""; + return ftdi->error_str; }