Cleanup work; separating out the cp interface to be more abstract.
authorKeith Packard <keithp@keithp.com>
Sun, 21 Dec 2008 07:30:06 +0000 (23:30 -0800)
committerKeith Packard <keithp@keithp.com>
Sun, 21 Dec 2008 07:30:06 +0000 (23:30 -0800)
Signed-off-by: Keith Packard <keithp@keithp.com>
lib/cccp.c
lib/ccdbg-command.c
lib/ccdbg-flash.c
lib/ccdbg-io.c
lib/ccdbg.h
lib/cp-usb.c

index 99a0d81f1a11a895d470d558d7fdfe6caa8ac585..34e866e89c4cda97c248702a55ad63bb1061b3ac 100644 (file)
@@ -98,3 +98,15 @@ cccp_fini(struct ccdbg *dbg)
        cccp_write(dbg, 0xf, 0xf);
        dbg->clock = 1;
 }
        cccp_write(dbg, 0xf, 0xf);
        dbg->clock = 1;
 }
+
+cccp_open()
+{
+       dbg->fd = open("/dev/ttyUSB0", 2);
+       if (dbg->fd < 0) {
+               perror(file);
+               free(dbg);
+               return NULL;
+       }
+       cccp_init(dbg);
+       cccp_write(dbg, CC_CLOCK, CC_CLOCK);
+}
index 38c006cb99c4ee303493b5baa59f75ad2211ebe0..30f5094dbdfd71bb5110ab59e1afd7324907808d 100644 (file)
@@ -174,9 +174,9 @@ ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image)
        ccdbg_write_hex_image(dbg, image, 0);
        ccdbg_set_pc(dbg, image->address);
        pc = ccdbg_get_pc(dbg);
        ccdbg_write_hex_image(dbg, image, 0);
        ccdbg_set_pc(dbg, image->address);
        pc = ccdbg_get_pc(dbg);
-       printf ("pc starts at 0x%04x\n", pc);
+       ccdbg_debug(CC_DEBUG_EXECUTE, "pc starts at 0x%04x\n", pc);
        status = ccdbg_resume(dbg);
        status = ccdbg_resume(dbg);
-       printf ("resume status: 0x%02x\n", status);
+       ccdbg_debug(CC_DEBUG_EXECUTE, "resume status: 0x%02x\n", status);
        return 0;
 }
 
        return 0;
 }
 
index aa2c5187f917a9d99e75966e07c2362fec4a5f9f..f950dd1b65ee8081f270e1162bf23f2db11cddfb 100644 (file)
@@ -112,16 +112,16 @@ ccdbg_flash_erase_page(struct ccdbg *dbg, uint16_t addr)
        flash_erase_page[ERASE_PAGE_HIGH] = page_addr >> 8;
        flash_erase_page[ERASE_PAGE_LOW] = page_addr & 0xff;
        status = ccdbg_execute(dbg, flash_erase_page);
        flash_erase_page[ERASE_PAGE_HIGH] = page_addr >> 8;
        flash_erase_page[ERASE_PAGE_LOW] = page_addr & 0xff;
        status = ccdbg_execute(dbg, flash_erase_page);
-       printf("erase status 0x%02x\n", status);
+       ccdbg_debug(CC_DEBUG_FLASH, "erase status 0x%02x\n", status);
        do {
                status = ccdbg_execute(dbg, flash_read_control);
        do {
                status = ccdbg_execute(dbg, flash_read_control);
-               printf("fctl 0x%02x\n", status);
+               ccdbg_debug(CC_DEBUG_FLASH, "fctl 0x%02x\n", status);
        } while (status & FCTL_BUSY);
        ccdbg_read_memory(dbg, addr, new, 0x10);
        for (i = 0; i < 0x10; i++)
        } while (status & FCTL_BUSY);
        ccdbg_read_memory(dbg, addr, new, 0x10);
        for (i = 0; i < 0x10; i++)
-               printf("0x%02x -> 0x%02x\n", old[i], new[i]);
+               ccdbg_debug(CC_DEBUG_FLASH, "0x%02x -> 0x%02x\n", old[i], new[i]);
        status = ccdbg_execute(dbg, flash_control_clear);
        status = ccdbg_execute(dbg, flash_control_clear);
-       printf("clear fctl 0x%02x\n", status);
+       ccdbg_debug(CC_DEBUG_FLASH, "clear fctl 0x%02x\n", status);
        return 0;
 }
 #endif
        return 0;
 }
 #endif
@@ -190,22 +190,22 @@ ccdbg_flash_write_word(struct ccdbg *dbg, uint16_t addr, uint8_t data[2])
        flash_write[WRITE_PAGE_LOW] = page_addr & 0xff;
        flash_write[WRITE_BYTE_0] = data[0];
        flash_write[WRITE_BYTE_1] = data[1];
        flash_write[WRITE_PAGE_LOW] = page_addr & 0xff;
        flash_write[WRITE_BYTE_0] = data[0];
        flash_write[WRITE_BYTE_1] = data[1];
-       printf("upload flash write\n");
+       ccdbg_debug(CC_DEBUG_FLASH, "upload flash write\n");
        ccdbg_write_memory(dbg, 0xf000, flash_write, sizeof(flash_write));
        ccdbg_set_pc(dbg, 0xf000);
        ccdbg_resume(dbg);
        for (;;) {
                status = ccdbg_read_status(dbg);
        ccdbg_write_memory(dbg, 0xf000, flash_write, sizeof(flash_write));
        ccdbg_set_pc(dbg, 0xf000);
        ccdbg_resume(dbg);
        for (;;) {
                status = ccdbg_read_status(dbg);
-               printf("waiting for write 0x%02x\n", status);
+               ccdbg_debug(CC_DEBUG_FLASH, "waiting for write 0x%02x\n", status);
                if ((status & CC_STATUS_CPU_HALTED) != 0)
                        break;
                sleep (1);
        }
        status = ccdbg_execute(dbg, flash_control_clear);
                if ((status & CC_STATUS_CPU_HALTED) != 0)
                        break;
                sleep (1);
        }
        status = ccdbg_execute(dbg, flash_control_clear);
-       printf("clear fctl 0x%02x\n", status);
+       ccdbg_debug(CC_DEBUG_FLASH, "clear fctl 0x%02x\n", status);
        ccdbg_read_memory(dbg, addr, check, 2);
        for (i = 0; i < 2; i++)
        ccdbg_read_memory(dbg, addr, check, 2);
        for (i = 0; i < 2; i++)
-               printf("0x%02x : 0x%02x\n", data[i], check[i]);
+               ccdbg_debug(CC_DEBUG_FLASH, "0x%02x : 0x%02x\n", data[i], check[i]);
        return 0;
 }
 #endif
        return 0;
 }
 #endif
@@ -231,7 +231,7 @@ ccdbg_flash_lock(struct ccdbg *dbg, uint8_t lock)
        ccdbg_read_memory(dbg, 0, old, 1);
        ccdbg_flash_write_word(dbg, 0, bytes);
        ccdbg_read_memory(dbg, 0, new, 1);
        ccdbg_read_memory(dbg, 0, old, 1);
        ccdbg_flash_write_word(dbg, 0, bytes);
        ccdbg_read_memory(dbg, 0, new, 1);
-       printf ("flash lock 0x%02x -> 0x%02x\n", old[0], new[0]);
+       ccdbg_debug(CC_DEBUG_FLASH, "flash lock 0x%02x -> 0x%02x\n", old[0], new[0]);
        ccdbg_wr_config(dbg, config & ~SEL_FLASH_INFO_PAGE);
        return 0;
 }
        ccdbg_wr_config(dbg, config & ~SEL_FLASH_INFO_PAGE);
        return 0;
 }
@@ -270,7 +270,7 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)
        fwt = 0x20;
 
        flash_page[FLASH_TIMING] = fwt;
        fwt = 0x20;
 
        flash_page[FLASH_TIMING] = fwt;
-       printf("Upload %d flash program bytes to 0x%04x\n",
+       ccdbg_debug(CC_DEBUG_FLASH, "Upload %d flash program bytes to 0x%04x\n",
               sizeof (flash_page), flash_prog);
        ccdbg_write_memory(dbg, flash_prog, flash_page, sizeof(flash_page));
        
               sizeof (flash_page), flash_prog);
        ccdbg_write_memory(dbg, flash_prog, flash_page, sizeof(flash_page));
        
@@ -283,10 +283,10 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)
 
                offset = ram_addr - (image->address + start);
 
 
                offset = ram_addr - (image->address + start);
 
-               printf("Upload %d bytes at 0x%04x\n", this_time, ram_addr);
+               ccdbg_debug(CC_DEBUG_FLASH, "Upload %d bytes at 0x%04x\n", this_time, ram_addr);
                ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time);
 
                ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time);
 
-               printf("Verify %d bytes\n", image->length);
+               ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes\n", image->length);
                ccdbg_read_memory(dbg, ram_addr, verify, this_time);
                if (memcmp (image->data + start, verify, this_time) != 0) {
                        fprintf(stderr, "image verify failed\n");
                ccdbg_read_memory(dbg, ram_addr, verify, this_time);
                if (memcmp (image->data + start, verify, this_time) != 0) {
                        fprintf(stderr, "image verify failed\n");
@@ -308,12 +308,12 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)
 
                ccdbg_set_pc(dbg, flash_prog);
                pc = ccdbg_get_pc(dbg);
 
                ccdbg_set_pc(dbg, flash_prog);
                pc = ccdbg_get_pc(dbg);
-               printf("Starting flash program at 0x%04x\n", pc);
+               ccdbg_debug(CC_DEBUG_FLASH, "Starting flash program at 0x%04x\n", pc);
                status = ccdbg_resume(dbg);
                status = ccdbg_resume(dbg);
-               printf("resume status is 0x%02x\n", status);
+               ccdbg_debug(CC_DEBUG_FLASH, "resume status is 0x%02x\n", status);
                do {
                        status = ccdbg_read_status(dbg);
                do {
                        status = ccdbg_read_status(dbg);
-                       printf("chip status is 0x%02x\n", status);
+                       ccdbg_debug(CC_DEBUG_FLASH, "chip status is 0x%02x\n", status);
                        sleep(1);
                } while ((status & CC_STATUS_CPU_HALTED) == 0);
                
                        sleep(1);
                } while ((status & CC_STATUS_CPU_HALTED) == 0);
                
@@ -321,14 +321,14 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)
                start += this_time;
        }
 #if 1
                start += this_time;
        }
 #if 1
-       printf("Downloading flash to check\n");
+       ccdbg_debug(CC_DEBUG_FLASH, "Downloading flash to check\n");
        struct hex_image *test_image;
        test_image = ccdbg_read_hex_image(dbg, image->address, image->length);
        if (!ccdbg_hex_image_equal(image, test_image)) {
                int i;
                fprintf(stderr, "Image not loaded\n");
                for (i = 0;i < 0x10; i++)
        struct hex_image *test_image;
        test_image = ccdbg_read_hex_image(dbg, image->address, image->length);
        if (!ccdbg_hex_image_equal(image, test_image)) {
                int i;
                fprintf(stderr, "Image not loaded\n");
                for (i = 0;i < 0x10; i++)
-                       printf ("0x%02x : 0x%02x\n", image->data[i], test_image->data[i]);
+                       ccdbg_debug(CC_DEBUG_FLASH, "0x%02x : 0x%02x\n", image->data[i], test_image->data[i]);
                return 1;
        }
        return 0;
                return 1;
        }
        return 0;
index 2947678561d4ac964e99e988fd52d39efe06cbdb..6999dbecb1503684f77532259488a006660c8c84 100644 (file)
@@ -38,54 +38,32 @@ ccdbg_open(void)
                perror("calloc");
                return NULL;
        }
                perror("calloc");
                return NULL;
        }
-       dbg->clock = 1;
-#ifdef USE_KERNEL
-       dbg->fd = open("/dev/ttyUSB0", 2);
-       if (dbg->fd < 0) {
-               perror(file);
-               free(dbg);
+       dbg->cp = cp_usb_open ();
+       if (!dbg->cp) {
+               free (dbg);
                return NULL;
        }
                return NULL;
        }
-       cccp_init(dbg);
-       cccp_write(dbg, CC_CLOCK, CC_CLOCK);
-#else
-       cp_usb_init(dbg);
-#endif
-       dbg->clock = 1;
        return dbg;
 }
 
 void
 ccdbg_close(struct ccdbg *dbg)
 {
        return dbg;
 }
 
 void
 ccdbg_close(struct ccdbg *dbg)
 {
-#if USE_KERNEL
-       cccp_fini(dbg);
-       close (dbg->fd);
-#else
-       cp_usb_fini(dbg);
-#endif
+       cp_usb_close(dbg->cp);
        free (dbg);
 }
 
 int
 ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
 {
        free (dbg);
 }
 
 int
 ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
 {
-#if USE_KERNEL
-       return cccp_write(dbg, mask, value);
-#else
-       cp_usb_write(dbg, mask, value);
+       cp_usb_write(dbg->cp, mask, value);
        return 0;
        return 0;
-#endif
 }
 
 uint8_t
 ccdbg_read(struct ccdbg *dbg)
 {
 }
 
 uint8_t
 ccdbg_read(struct ccdbg *dbg)
 {
-#if USE_KERNEL
-       return cccp_read_all(dbg);
-#else
-       return cp_usb_read(dbg);
-#endif
+       return cp_usb_read(dbg->cp);
 }
 
 static char
 }
 
 static char
index b74d13ca3495bde9e8c67b6a7a2f41489d949c5b..4d4a648d41ccf61c8d6c0729bf43bb1d21ddf678 100644 (file)
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
-#undef USE_KERNEL
-#ifdef USE_KERNEL
-#include <cp2101.h>
-#define CC_CLOCK       CP2101_GPIO_MASK(0)
-#define CC_DATA                CP2101_GPIO_MASK(1)
-#define CC_RESET_N     CP2101_GPIO_MASK(2)
-#else
+#include "cp-usb.h"
 #define CC_CLOCK       0x1
 #define CC_DATA                0x2
 #define CC_RESET_N     0x4
 #define CC_CLOCK       0x1
 #define CC_DATA                0x2
 #define CC_RESET_N     0x4
-#include <usb.h>
-#endif
-
-
-/* painfully slow for now */
-#define CC_CLOCK_US    (50)
+#define CC_CLOCK_US    (40)
 
 
+/* 8051 instructions
+ */
 #define MOV_direct_data                0x75
 #define LJMP                   0x02
 #define MOV_Rn_data(n)         (0x78 | (n))
 #define MOV_direct_data                0x75
 #define LJMP                   0x02
 #define MOV_Rn_data(n)         (0x78 | (n))
 #define MOV_A_direct           0xe5
 #define MOV_direct_A           0xf5
 #define MOV_DPTR_data16                0x90
 #define MOV_A_direct           0xe5
 #define MOV_direct_A           0xf5
 #define MOV_DPTR_data16                0x90
-#define MOV_A_data     0x74
-#define MOVX_atDPTR_A  0xf0
-#define MOVX_A_atDPTR  0xe0
-#define INC_DPTR       0xa3
-#define TRAP           0xa5
-
-#define SJMP           0x80
-
-#define FWT            0xAB
-#define FADDRL         0xAC
-#define FADDRH         0xAD
-#define FCTL           0xAE
-# define FCTL_BUSY     0x80
-# define FCTL_BUSY_BIT 7
-# define FCTL_SWBSY    0x40
-# define FCTL_SWBSY_BIT        6
-# define FCTL_CONTRD   0x10
-# define FCTL_WRITE    0x02
-# define FCTL_ERASE    0x01
-#define FWDATA         0xAF
-
-#define CLKCON         0xC6
-#define  CLKCON_OSC32K 0x80
-#define  CLKCON_OSC    0x40
-#define  CLKCON_TICKSPD        0x38
-#define  CLKCON_CLKSPD 0x07
-
-#define P0             0x80
-#define P1             0x90
-#define P2             0xA0
-#define P0DIR          0xFD
-#define P1DIR          0xFE
-#define P2DIR          0xFF
-
-#define SLEEP          0xBE
-
-#define JB             0x20
-
-#define ACC(bit)       (0xE0 | (bit))
+#define MOV_A_data             0x74
+#define MOVX_atDPTR_A          0xf0
+#define MOVX_A_atDPTR          0xe0
+#define INC_DPTR               0xa3
+#define TRAP                   0xa5
+#define SJMP                   0x80
+#define JB                     0x20
+
+/* 8051 special function registers
+ */
+
+/* flash controller */
+#define FWT                    0xAB
+#define FADDRL                 0xAC
+#define FADDRH                 0xAD
+#define FCTL                   0xAE
+# define FCTL_BUSY             0x80
+# define FCTL_BUSY_BIT         7
+# define FCTL_SWBSY            0x40
+# define FCTL_SWBSY_BIT                6
+# define FCTL_CONTRD           0x10
+# define FCTL_WRITE            0x02
+# define FCTL_ERASE            0x01
+#define FWDATA                 0xAF
+
+#define SLEEP                  0xBE
+
+/* clock controller */
+#define CLKCON                 0xC6
+#define  CLKCON_OSC32K         0x80
+#define  CLKCON_OSC            0x40
+#define  CLKCON_TICKSPD                0x38
+#define  CLKCON_CLKSPD         0x07
+
+/* I/O pins */
+#define P0                     0x80
+#define P1                     0x90
+#define P2                     0xA0
+#define P0DIR                  0xFD
+#define P1DIR                  0xFE
+#define P2DIR                  0xFF
+
+/* Bit-addressable accumulator */
+#define ACC(bit)               (0xE0 | (bit))
 
 struct ccdbg {
 
 struct ccdbg {
-       usb_dev_handle  *usb_dev;
-       uint8_t gpio;
-#ifdef USE_KERNEL
-       int     fd;
-#endif
-       uint8_t debug_data;
-       int     clock;
+       struct cp_usb *cp;
 };
 
 };
 
+/* Intel hex file format data
+ */
 struct hex_record {
        uint8_t length;
        uint16_t address;
 struct hex_record {
        uint8_t length;
        uint16_t address;
@@ -127,8 +119,8 @@ struct hex_image {
 #define HEX_RECORD_EOF                 0x01
 #define HEX_RECORD_EXTENDED_ADDRESS    0x02
 
 #define HEX_RECORD_EOF                 0x01
 #define HEX_RECORD_EXTENDED_ADDRESS    0x02
 
-#include "cccp.h"
-
+/* CC1111 debug port commands
+ */
 #define CC_CHIP_ERASE          0x14
 
 #define CC_WR_CONFIG           0x1d
 #define CC_CHIP_ERASE          0x14
 
 #define CC_WR_CONFIG           0x1d
@@ -161,9 +153,13 @@ struct hex_image {
 #define CC_STEP_REPLACE(n)     (0x64|(n))
 #define CC_GET_CHIP_ID         0x68
 
 #define CC_STEP_REPLACE(n)     (0x64|(n))
 #define CC_GET_CHIP_ID         0x68
 
+/* Debug levels
+ */
 #define CC_DEBUG_BITBANG       0x00000001
 #define CC_DEBUG_COMMAND       0x00000002
 #define CC_DEBUG_INSTRUCTIONS  0x00000004
 #define CC_DEBUG_BITBANG       0x00000001
 #define CC_DEBUG_COMMAND       0x00000002
 #define CC_DEBUG_INSTRUCTIONS  0x00000004
+#define CC_DEBUG_EXECUTE       0x00000008
+#define CC_DEBUG_FLASH         0x00000010
 
 /* ccdbg-command.c */
 void
 
 /* ccdbg-command.c */
 void
@@ -335,17 +331,4 @@ ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offse
 struct hex_image *
 ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length);
 
 struct hex_image *
 ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length);
 
-/* cp-usb.c */
-void
-cp_usb_init(struct ccdbg *dbg);
-
-void
-cp_usb_fini(struct ccdbg *dbg);
-
-void
-cp_usb_write(struct ccdbg *dbg, uint8_t mask, uint8_t value);
-
-uint8_t
-cp_usb_read(struct ccdbg *dbg);
-
 #endif /* _CCDBG_H_ */
 #endif /* _CCDBG_H_ */
index 61b684a2ee94637ff0c8b0a8d9fb1f93211a4447..6ab9092c1f487926e354aca698f99bfdbb90ccfd 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#include "ccdbg.h"
-#include <usb.h>
+/*
+ * libusb interface to the GPIO pins on a CP2103.
+ *
+ * Various magic constants came from the cp210x driver published by silabs.
+ */
+
+#include "cp-usb.h"
+#include <stdio.h>
+#include <errno.h>
+
+struct cp_usb {
+       usb_dev_handle *usb_dev;
+       uint8_t gpio;
+};
 
 #define CP2101_UART    0x00
 #define UART_ENABLE    0x0001
 
 #define CP2101_UART    0x00
 #define UART_ENABLE    0x0001
@@ -26,9 +38,9 @@
 #define REQTYPE_DEVICE_TO_HOST  0xc1
 
 static int
 #define REQTYPE_DEVICE_TO_HOST  0xc1
 
 static int
-cp_usb_gpio_get(struct ccdbg *dbg, uint8_t *gpio_get)
+cp_usb_gpio_get(struct cp_usb *cp, uint8_t *gpio_get)
 {
 {
-       return usb_control_msg(dbg->usb_dev,            /* dev */
+       return usb_control_msg(cp->usb_dev,             /* dev */
                               0xc0,                    /* request */
                               0xff,                    /* requesttype */
                               0x00c2,                  /* value */
                               0xc0,                    /* request */
                               0xff,                    /* requesttype */
                               0x00c2,                  /* value */
@@ -39,11 +51,11 @@ cp_usb_gpio_get(struct ccdbg *dbg, uint8_t *gpio_get)
 }
 
 static int
 }
 
 static int
-cp_usb_gpio_set(struct ccdbg *dbg, uint8_t mask, uint8_t value)
+cp_usb_gpio_set(struct cp_usb *cp, uint8_t mask, uint8_t value)
 {
        uint16_t gpio_set = ((uint16_t) value << 8) | mask;
 
 {
        uint16_t gpio_set = ((uint16_t) value << 8) | mask;
 
-       return usb_control_msg(dbg->usb_dev,            /* dev */
+       return usb_control_msg(cp->usb_dev,             /* dev */
                               0x40,                    /* request */
                               0xff,                    /* requesttype */
                               0x37e1,                  /* value */
                               0x40,                    /* request */
                               0xff,                    /* requesttype */
                               0x37e1,                  /* value */
@@ -54,9 +66,9 @@ cp_usb_gpio_set(struct ccdbg *dbg, uint8_t mask, uint8_t value)
 }
 
 static int
 }
 
 static int
-cp_usb_uart_enable_disable(struct ccdbg *dbg, uint16_t enable)
+cp_usb_uart_enable_disable(struct cp_usb *cp, uint16_t enable)
 {
 {
-       return usb_control_msg(dbg->usb_dev,
+       return usb_control_msg(cp->usb_dev,
                               CP2101_UART,
                               REQTYPE_HOST_TO_DEVICE,
                               enable,
                               CP2101_UART,
                               REQTYPE_HOST_TO_DEVICE,
                               enable,
@@ -66,9 +78,10 @@ cp_usb_uart_enable_disable(struct ccdbg *dbg, uint16_t enable)
                               300);
 }
 
                               300);
 }
 
-void
-cp_usb_init(struct ccdbg *dbg)
+struct cp_usb *
+cp_usb_open(void)
 {
 {
+       struct cp_usb *cp;
        usb_dev_handle *dev_handle;
        struct usb_device *dev = NULL;
        struct usb_bus *bus, *busses;
        usb_dev_handle *dev_handle;
        struct usb_device *dev = NULL;
        struct usb_bus *bus, *busses;
@@ -92,49 +105,52 @@ cp_usb_init(struct ccdbg *dbg)
        }
        if (!dev){
                perror("No CP2103 found");
        }
        if (!dev){
                perror("No CP2103 found");
-               exit(1);
+               return NULL;
        }
        }
+       cp = calloc(sizeof(struct cp_usb), 1);
        interface = 0;
        dev_handle = usb_open(dev);
        usb_detach_kernel_driver_np(dev_handle, interface);
        usb_claim_interface(dev_handle, interface);
        interface = 0;
        dev_handle = usb_open(dev);
        usb_detach_kernel_driver_np(dev_handle, interface);
        usb_claim_interface(dev_handle, interface);
-       dbg->usb_dev = dev_handle;
-       ret = cp_usb_uart_enable_disable(dbg, UART_DISABLE);
-       dbg->gpio = 0xf;
-       ret = cp_usb_gpio_set(dbg, 0xf, dbg->gpio);
-       ret = cp_usb_gpio_get(dbg, &gpio);
+       cp->usb_dev = dev_handle;
+       ret = cp_usb_uart_enable_disable(cp, UART_DISABLE);
+       cp->gpio = 0xf;
+       ret = cp_usb_gpio_set(cp, 0xf, cp->gpio);
+       ret = cp_usb_gpio_get(cp, &gpio);
+       return cp;
 }
 
 void
 }
 
 void
-cp_usb_fini(struct ccdbg *dbg)
+cp_usb_close(struct cp_usb *cp)
 {
 {
-       cp_usb_uart_enable_disable(dbg, UART_DISABLE);
-       usb_close(dbg->usb_dev);
+       cp_usb_uart_enable_disable(cp, UART_DISABLE);
+       usb_close(cp->usb_dev);
+       free(cp);
 }
 
 void
 }
 
 void
-cp_usb_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
+cp_usb_write(struct cp_usb *cp, uint8_t mask, uint8_t value)
 {
        uint8_t new_gpio;
        int ret;
 
 {
        uint8_t new_gpio;
        int ret;
 
-       new_gpio = (dbg->gpio & ~mask) | (value & mask);
-       if (new_gpio != dbg->gpio) {
-               ret = cp_usb_gpio_set(dbg, new_gpio ^ dbg->gpio, new_gpio);
+       new_gpio = (cp->gpio & ~mask) | (value & mask);
+       if (new_gpio != cp->gpio) {
+               ret = cp_usb_gpio_set(cp, new_gpio ^ cp->gpio, new_gpio);
                if (ret < 0)
                        perror("gpio_set");
                if (ret < 0)
                        perror("gpio_set");
-               dbg->gpio = new_gpio;
+               cp->gpio = new_gpio;
        }
 }
 
 uint8_t
        }
 }
 
 uint8_t
-cp_usb_read(struct ccdbg *dbg)
+cp_usb_read(struct cp_usb *cp)
 {
        int ret;
        uint8_t gpio;
 
 {
        int ret;
        uint8_t gpio;
 
-       ret = cp_usb_gpio_get(dbg, &gpio);
+       ret = cp_usb_gpio_get(cp, &gpio);
        if (ret < 0)
        if (ret < 0)
-               perror("gpio_set");
+               perror("gpio_get");
        return gpio;
 }
        return gpio;
 }