works better on windows
[gnuk/gnuk.git] / src / usb_prop.c
1 /*
2  * usb_prop.c - glue/interface code between Gnuk and USB-FS-Device_Lib
3  *
4  * Copyright (C) 2010 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of Gnuk, a GnuPG USB Token implementation.
8  *
9  * Gnuk is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 /* Packet size of USB Bulk transfer for full speed */
25 #define GNUK_MAX_PACKET_SIZE 64
26
27 #include "config.h"
28 #include "usb_lib.h"
29 #include "usb_conf.h"
30 #include "usb_prop.h"
31 #include "usb_desc.h"
32 #include "usb_pwr.h"
33 #include "hw_config.h"
34
35 #ifdef ENABLE_VIRTUAL_COM_PORT
36 #include "usb-cdc-vport.c"
37 #endif
38
39 static void
40 gnuk_device_init (void)
41 {
42   pInformation->Current_Configuration = 0;
43
44   /* Connect the device */
45   PowerOn ();
46
47   /* Perform basic device initialization operations */
48   USB_SIL_Init ();
49
50   bDeviceState = UNCONNECTED;
51 }
52
53 static void
54 gnuk_device_reset (void)
55 {
56   /* Set DEVICE as not configured */
57   pInformation->Current_Configuration = 0;
58
59   /* Current Feature initialization */
60   pInformation->Current_Feature = Config_Descriptor.Descriptor[7];
61
62   /* Set DEVICE with the default Interface*/
63   pInformation->Current_Interface = 0;
64
65   SetBTABLE (BTABLE_ADDRESS);
66
67   /* Initialize Endpoint 0 */
68   SetEPType (ENDP0, EP_CONTROL);
69   SetEPTxStatus (ENDP0, EP_TX_STALL);
70   SetEPRxAddr (ENDP0, ENDP0_RXADDR);
71   SetEPTxAddr (ENDP0, ENDP0_TXADDR);
72   Clear_Status_Out (ENDP0);
73   SetEPRxCount (ENDP0, GNUK_MAX_PACKET_SIZE);
74   SetEPRxValid (ENDP0);
75
76   /* Initialize Endpoint 1 */
77   SetEPType (ENDP1, EP_BULK);
78   SetEPTxAddr (ENDP1, ENDP1_TXADDR);
79   SetEPTxStatus (ENDP1, EP_TX_NAK);
80   SetEPRxStatus (ENDP1, EP_RX_DIS);
81
82   /* Initialize Endpoint 2 */
83   SetEPType (ENDP2, EP_BULK);
84   SetEPRxAddr (ENDP2, ENDP2_RXADDR);
85   SetEPRxCount (ENDP2, GNUK_MAX_PACKET_SIZE);
86   SetEPRxStatus (ENDP2, EP_RX_VALID);
87   SetEPTxStatus (ENDP2, EP_TX_DIS);
88
89 #ifdef ENABLE_VIRTUAL_COM_PORT
90   /* Initialize Endpoint 3 */
91   SetEPType (ENDP3, EP_BULK);
92   SetEPTxAddr (ENDP3, ENDP3_TXADDR);
93   SetEPTxStatus (ENDP3, EP_TX_NAK);
94   SetEPRxStatus (ENDP3, EP_RX_DIS);
95
96   /* Initialize Endpoint 4 */
97   SetEPType (ENDP4, EP_INTERRUPT);
98   SetEPTxAddr (ENDP4, ENDP4_TXADDR);
99   SetEPTxStatus (ENDP4, EP_TX_NAK);
100   SetEPRxStatus (ENDP4, EP_RX_DIS);
101
102   /* Initialize Endpoint 5 */
103   SetEPType (ENDP5, EP_BULK);
104   SetEPRxAddr (ENDP5, ENDP5_RXADDR);
105   SetEPRxCount (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE);
106   SetEPRxStatus (ENDP5, EP_RX_VALID);
107   SetEPTxStatus (ENDP5, EP_TX_DIS);
108 #endif
109
110   /* Set this device to response on default address */
111   SetDeviceAddress (0);
112
113   bDeviceState = ATTACHED;
114 }
115
116 static void
117 gnuk_device_SetConfiguration (void)
118 {
119   DEVICE_INFO *pInfo = &Device_Info;
120
121   if (pInfo->Current_Configuration != 0)
122     /* Device configured */
123     bDeviceState = CONFIGURED;
124 }
125
126 static void
127 gnuk_device_SetDeviceAddress (void)
128 {
129   bDeviceState = ADDRESSED;
130 }
131
132 /* IN from port 0 */
133 static void
134 gnuk_device_Status_In (void)
135 {
136 }
137
138 /* OUT to port 0 */
139 static void
140 gnuk_device_Status_Out (void)
141 {
142 }
143
144 static uint8_t *
145 gnuk_device_GetDeviceDescriptor (uint16_t Length)
146 {
147   return Standard_GetDescriptorData (Length,
148                                      (PONE_DESCRIPTOR)&Device_Descriptor);
149 }
150
151 static uint8_t *
152 gnuk_device_GetConfigDescriptor (uint16_t Length)
153 {
154   return Standard_GetDescriptorData (Length,
155                                      (PONE_DESCRIPTOR)&Config_Descriptor);
156 }
157
158 static uint8_t *
159 gnuk_device_GetStringDescriptor (uint16_t Length)
160 {
161   uint8_t wValue0 = pInformation->USBwValue0;
162
163   if (wValue0 > (sizeof (String_Descriptor) / sizeof (ONE_DESCRIPTOR)))
164     return NULL;
165   else
166     return Standard_GetDescriptorData (Length,
167                                        (PONE_DESCRIPTOR)&String_Descriptor[wValue0]);
168 }
169
170 static RESULT
171 gnuk_device_Get_Interface_Setting (uint8_t Interface, uint8_t AlternateSetting)
172 {
173   if (AlternateSetting > 0)
174     return USB_UNSUPPORT;
175   else if (Interface > 1)
176     return USB_UNSUPPORT;
177
178   return USB_SUCCESS;
179 }
180
181 #define USB_CCID_REQ_ABORT                      0x01
182 #define USB_CCID_REQ_GET_CLOCK_FREQUENCIES      0x02
183 #define USB_CCID_REQ_GET_DATA_RATES             0x03
184
185 static const uint8_t freq_table[] = { 0xf3, 0x0d, 0, 0, }; /* dwDefaultClock */
186 static uint8_t *
187 gnuk_clock_frequencies (uint16_t len)
188 {
189   if (len == 0)
190     {
191       pInformation->Ctrl_Info.Usb_wLength = sizeof (freq_table);
192       return NULL;
193     }
194
195   return (uint8_t *)freq_table;
196 }
197
198 static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */
199 static uint8_t *
200 gnuk_data_rates (uint16_t len)
201 {
202   if (len == 0)
203     {
204       pInformation->Ctrl_Info.Usb_wLength = sizeof (data_rate_table);
205       return NULL;
206     }
207
208   return (uint8_t *)data_rate_table;
209 }
210
211 static RESULT
212 gnuk_setup_with_data (uint8_t RequestNo)
213 {
214   if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
215     if (pInformation->USBwIndex0 == 0) /* Interface */
216       {
217         if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
218           {
219             pInformation->Ctrl_Info.CopyData = gnuk_clock_frequencies;
220             pInformation->Ctrl_Info.Usb_wOffset = 0;
221             gnuk_clock_frequencies (0);
222             return USB_SUCCESS;
223           }
224         else if (RequestNo == USB_CCID_REQ_GET_DATA_RATES)
225           {
226             pInformation->Ctrl_Info.CopyData = gnuk_data_rates;
227             pInformation->Ctrl_Info.Usb_wOffset = 0;
228             gnuk_data_rates (0);
229             return USB_SUCCESS;
230           }
231         else
232           return USB_UNSUPPORT;
233       }
234     else
235       {
236 #if defined(ENABLE_VIRTUAL_COM_PORT)
237         return Virtual_Com_Port_Data_Setup (RequestNo);
238 #else
239         return USB_UNSUPPORT;
240 #endif
241       }
242   else
243     return USB_UNSUPPORT;
244 }
245
246 static RESULT
247 gnuk_setup_with_nodata (uint8_t RequestNo)
248 {
249   if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
250     if (pInformation->USBwIndex0 == 0) /* Interface */
251       {
252         if (RequestNo == USB_CCID_REQ_ABORT)
253           /* wValue: bSeq, bSlot */
254           /* Abortion is not supported in Gnuk */
255           return USB_UNSUPPORT;
256         else
257           return USB_UNSUPPORT;
258       }
259     else
260       {
261 #if defined(ENABLE_VIRTUAL_COM_PORT)
262         return Virtual_Com_Port_NoData_Setup (RequestNo);
263 #else
264         return USB_UNSUPPORT;
265 #endif
266       }
267   else
268     return USB_UNSUPPORT;
269 }
270
271 /*
272  * Interface to USB core
273  */
274
275 const DEVICE_PROP Device_Property = {
276   gnuk_device_init,
277   gnuk_device_reset,
278   gnuk_device_Status_In,
279   gnuk_device_Status_Out,
280   gnuk_setup_with_data,
281   gnuk_setup_with_nodata,
282   gnuk_device_Get_Interface_Setting,
283   gnuk_device_GetDeviceDescriptor,
284   gnuk_device_GetConfigDescriptor,
285   gnuk_device_GetStringDescriptor,
286   0,
287   GNUK_MAX_PACKET_SIZE
288 };
289
290 const DEVICE Device_Table = {
291   EP_NUM,
292   1
293 };
294
295 const USER_STANDARD_REQUESTS User_Standard_Requests = {
296   NOP_Process,                  /* GetConfiguration */ 
297   gnuk_device_SetConfiguration,
298   NOP_Process,                  /* GetInterface */
299   NOP_Process,                  /* SetInterface */
300   NOP_Process,                  /* GetStatus */
301   NOP_Process,                  /* ClearFeature */
302   NOP_Process,                  /* SetEndPointFeature */
303   NOP_Process,                  /* SetDeviceFeature */
304   gnuk_device_SetDeviceAddress
305 };