61b684a2ee94637ff0c8b0a8d9fb1f93211a4447
[fw/altos] / lib / cp-usb.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ccdbg.h"
20 #include <usb.h>
21
22 #define CP2101_UART     0x00
23 #define UART_ENABLE     0x0001
24 #define UART_DISABLE    0x0000
25 #define REQTYPE_HOST_TO_DEVICE  0x41
26 #define REQTYPE_DEVICE_TO_HOST  0xc1
27
28 static int
29 cp_usb_gpio_get(struct ccdbg *dbg, uint8_t *gpio_get)
30 {
31         return usb_control_msg(dbg->usb_dev,            /* dev */
32                                0xc0,                    /* request */
33                                0xff,                    /* requesttype */
34                                0x00c2,                  /* value */
35                                0,                       /* index */
36                                (char *) gpio_get,       /* bytes */
37                                1,                       /* size */
38                                300);                    /* timeout */
39 }
40
41 static int
42 cp_usb_gpio_set(struct ccdbg *dbg, uint8_t mask, uint8_t value)
43 {
44         uint16_t gpio_set = ((uint16_t) value << 8) | mask;
45
46         return usb_control_msg(dbg->usb_dev,            /* dev */
47                                0x40,                    /* request */
48                                0xff,                    /* requesttype */
49                                0x37e1,                  /* value */
50                                gpio_set,                /* index */
51                                NULL,                    /* bytes */
52                                0,                       /* size */
53                                300);                    /* timeout */
54 }
55
56 static int
57 cp_usb_uart_enable_disable(struct ccdbg *dbg, uint16_t enable)
58 {
59         return usb_control_msg(dbg->usb_dev,
60                                CP2101_UART,
61                                REQTYPE_HOST_TO_DEVICE,
62                                enable,
63                                0,
64                                NULL,
65                                0,
66                                300);
67 }
68
69 void
70 cp_usb_init(struct ccdbg *dbg)
71 {
72         usb_dev_handle *dev_handle;
73         struct usb_device *dev = NULL;
74         struct usb_bus *bus, *busses;
75         int interface;
76         int ret;
77         uint8_t gpio;
78         
79         usb_init();
80         usb_find_busses();
81         usb_find_devices();
82         
83         busses = usb_get_busses();
84         for (bus = busses; bus; bus = bus->next) {
85                 for (dev = bus->devices; dev; dev = dev->next) {
86                         if (dev->descriptor.idVendor == 0x10c4 &&
87                             dev->descriptor.idProduct == 0xea60)
88                                 break;
89                 }
90                 if (dev)
91                         break;
92         }
93         if (!dev){
94                 perror("No CP2103 found");
95                 exit(1);
96         }
97         interface = 0;
98         dev_handle = usb_open(dev);
99         usb_detach_kernel_driver_np(dev_handle, interface);
100         usb_claim_interface(dev_handle, interface);
101         dbg->usb_dev = dev_handle;
102         ret = cp_usb_uart_enable_disable(dbg, UART_DISABLE);
103         dbg->gpio = 0xf;
104         ret = cp_usb_gpio_set(dbg, 0xf, dbg->gpio);
105         ret = cp_usb_gpio_get(dbg, &gpio);
106 }
107
108 void
109 cp_usb_fini(struct ccdbg *dbg)
110 {
111         cp_usb_uart_enable_disable(dbg, UART_DISABLE);
112         usb_close(dbg->usb_dev);
113 }
114
115 void
116 cp_usb_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
117 {
118         uint8_t new_gpio;
119         int ret;
120
121         new_gpio = (dbg->gpio & ~mask) | (value & mask);
122         if (new_gpio != dbg->gpio) {
123                 ret = cp_usb_gpio_set(dbg, new_gpio ^ dbg->gpio, new_gpio);
124                 if (ret < 0)
125                         perror("gpio_set");
126                 dbg->gpio = new_gpio;
127         }
128 }
129
130 uint8_t
131 cp_usb_read(struct ccdbg *dbg)
132 {
133         int ret;
134         uint8_t gpio;
135
136         ret = cp_usb_gpio_get(dbg, &gpio);
137         if (ret < 0)
138                 perror("gpio_set");
139         return gpio;
140 }