]> cvs.zerfleddert.de Git - proxmark3-svn/blob - armsrc/usb_cdc.c
c3975f1d5832cbfdee3e3cfae309f6bef3bfed8d
[proxmark3-svn] / armsrc / usb_cdc.c
1 /*
2 * at91sam7s USB CDC device implementation
3 *
4 * Copyright (c) 2012, Roel Verdult
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * based on the "Basic USB Example" from ATMEL (doc6123.pdf)
30 *
31 * @file usb_cdc.c
32 * @brief
33 */
34
35 #include "usb_cdc.h"
36
37 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
38 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
39 #define AT91C_EP_IN_SIZE 0x40
40 #define AT91C_EP_OUT 1
41 #define AT91C_EP_OUT_SIZE 0x40
42 #define AT91C_EP_IN 2
43
44 const char devDescriptor[] = {
45 /* Device descriptor */
46 0x12, // bLength
47 0x01, // bDescriptorType
48 0x10,0x01, // Complies with USB Spec. Release (0110h = release 1.10)
49 0x02, // bDeviceClass: CDC class code
50 0x00, // bDeviceSubclass: CDC class sub code
51 0x00, // bDeviceProtocol: CDC Device protocol
52 0x08, // bMaxPacketSize0
53 0xeb,0x03, // Vendor ID (random numbers)
54 0x25,0x61, // Product ID (random numbers)
55 0x01,0x00, // Device release number (0001)
56 0x01, // iManufacturer // 0x01
57 0x00, // iProduct
58 0x00, // SerialNumber
59 0x01 // bNumConfigs
60 };
61
62 const char cfgDescriptor[] = {
63 /* ============== CONFIGURATION 1 =========== */
64 /* Configuration 1 descriptor */
65 0x09, // CbLength
66 0x02, // CbDescriptorType
67 0x43, // CwTotalLength 2 EP + Control
68 0x00,
69 0x02, // CbNumInterfaces
70 0x01, // CbConfigurationValue
71 0x00, // CiConfiguration
72 0xC0, // CbmAttributes 0xA0
73 0x00, // CMaxPower
74
75 /* Communication Class Interface Descriptor Requirement */
76 0x09, // bLength
77 0x04, // bDescriptorType
78 0x00, // bInterfaceNumber
79 0x00, // bAlternateSetting
80 0x01, // bNumEndpoints
81 0x02, // bInterfaceClass
82 0x02, // bInterfaceSubclass
83 0x00, // bInterfaceProtocol
84 0x00, // iInterface
85
86 /* Header Functional Descriptor */
87 0x05, // bFunction Length
88 0x24, // bDescriptor type: CS_INTERFACE
89 0x00, // bDescriptor subtype: Header Func Desc
90 0x10, // bcdCDC:1.1
91 0x01,
92
93 /* ACM Functional Descriptor */
94 0x04, // bFunctionLength
95 0x24, // bDescriptor Type: CS_INTERFACE
96 0x02, // bDescriptor Subtype: ACM Func Desc
97 0x00, // bmCapabilities
98
99 /* Union Functional Descriptor */
100 0x05, // bFunctionLength
101 0x24, // bDescriptorType: CS_INTERFACE
102 0x06, // bDescriptor Subtype: Union Func Desc
103 0x00, // bMasterInterface: Communication Class Interface
104 0x01, // bSlaveInterface0: Data Class Interface
105
106 /* Call Management Functional Descriptor */
107 0x05, // bFunctionLength
108 0x24, // bDescriptor Type: CS_INTERFACE
109 0x01, // bDescriptor Subtype: Call Management Func Desc
110 0x00, // bmCapabilities: D1 + D0
111 0x01, // bDataInterface: Data Class Interface 1
112
113 /* Endpoint 1 descriptor */
114 0x07, // bLength
115 0x05, // bDescriptorType
116 0x83, // bEndpointAddress, Endpoint 03 - IN
117 0x03, // bmAttributes INT
118 0x08, // wMaxPacketSize
119 0x00,
120 0xFF, // bInterval
121
122 /* Data Class Interface Descriptor Requirement */
123 0x09, // bLength
124 0x04, // bDescriptorType
125 0x01, // bInterfaceNumber
126 0x00, // bAlternateSetting
127 0x02, // bNumEndpoints
128 0x0A, // bInterfaceClass
129 0x00, // bInterfaceSubclass
130 0x00, // bInterfaceProtocol
131 0x00, // iInterface
132
133 /* First alternate setting */
134 /* Endpoint 1 descriptor */
135 0x07, // bLength
136 0x05, // bDescriptorType
137 0x01, // bEndpointAddress, Endpoint 01 - OUT
138 0x02, // bmAttributes BULK
139 AT91C_EP_OUT_SIZE, // wMaxPacketSize
140 0x00,
141 0x00, // bInterval
142
143 /* Endpoint 2 descriptor */
144 0x07, // bLength
145 0x05, // bDescriptorType
146 0x82, // bEndpointAddress, Endpoint 02 - IN
147 0x02, // bmAttributes BULK
148 AT91C_EP_IN_SIZE, // wMaxPacketSize
149 0x00,
150 0x00 // bInterval
151 };
152
153 const char strDescriptor[] = {
154 26, // Length
155 0x03, // Type is string
156 'p', 0x00,
157 'r', 0x00,
158 'o', 0x00,
159 'x', 0x00,
160 'm', 0x00,
161 'a', 0x00,
162 'r', 0x00,
163 'k', 0x00,
164 '.', 0x00,
165 'o', 0x00,
166 'r', 0x00,
167 'g', 0x00,
168 };
169
170
171 /* USB standard request code */
172 #define STD_GET_STATUS_ZERO 0x0080
173 #define STD_GET_STATUS_INTERFACE 0x0081
174 #define STD_GET_STATUS_ENDPOINT 0x0082
175
176 #define STD_CLEAR_FEATURE_ZERO 0x0100
177 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
178 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
179
180 #define STD_SET_FEATURE_ZERO 0x0300
181 #define STD_SET_FEATURE_INTERFACE 0x0301
182 #define STD_SET_FEATURE_ENDPOINT 0x0302
183
184 #define STD_SET_ADDRESS 0x0500
185 #define STD_GET_DESCRIPTOR 0x0680
186 #define STD_SET_DESCRIPTOR 0x0700
187 #define STD_GET_CONFIGURATION 0x0880
188 #define STD_SET_CONFIGURATION 0x0900
189 #define STD_GET_INTERFACE 0x0A81
190 #define STD_SET_INTERFACE 0x0B01
191 #define STD_SYNCH_FRAME 0x0C82
192
193 /* CDC Class Specific Request Code */
194 #define GET_LINE_CODING 0x21A1
195 #define SET_LINE_CODING 0x2021
196 #define SET_CONTROL_LINE_STATE 0x2221
197
198 typedef struct {
199 unsigned int dwDTERRate;
200 char bCharFormat;
201 char bParityType;
202 char bDataBits;
203 } AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
204
205 AT91S_CDC_LINE_CODING line = {
206 115200, // baudrate
207 0, // 1 Stop Bit
208 0, // None Parity
209 8}; // 8 Data bits
210
211 void AT91F_CDC_Enumerate();
212
213 AT91PS_UDP pUdp = AT91C_BASE_UDP;
214 byte_t btConfiguration = 0;
215 byte_t btConnection = 0;
216 byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
217
218 //*----------------------------------------------------------------------------
219 //* \fn AT91F_USB_Enable
220 //* \brief This function Activates the USB device
221 //*----------------------------------------------------------------------------
222 void usb_enable()
223 {
224 // Set the PLL USB Divider
225 AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
226
227 // Specific Chip USB Initialisation
228 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
229 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
230 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
231
232 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
233 // Set in PIO mode and Configure in Output
234 AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16; // Set in PIO mode
235 AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16; // Configure as Output
236
237 // Clear for set the Pul up resistor
238 AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16;
239 }
240
241 //*----------------------------------------------------------------------------
242 //* \fn AT91F_UDP_IsConfigured
243 //* \brief Test if the device is configured and handle enumeration
244 //*----------------------------------------------------------------------------
245 bool usb_check()
246 {
247 AT91_REG isr = pUdp->UDP_ISR;
248
249 if (isr & AT91C_UDP_ENDBUSRES) {
250 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
251 // reset all endpoints
252 pUdp->UDP_RSTEP = (unsigned int)-1;
253 pUdp->UDP_RSTEP = 0;
254 // Enable the function
255 pUdp->UDP_FADDR = AT91C_UDP_FEN;
256 // Configure endpoint 0
257 pUdp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
258 }
259 else if (isr & AT91C_UDP_EPINT0) {
260 pUdp->UDP_ICR = AT91C_UDP_EPINT0;
261 AT91F_CDC_Enumerate();
262 }
263 return (btConfiguration) ? true : false;
264 }
265
266
267 bool usb_poll()
268 {
269 if (!usb_check()) return false;
270 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
271 }
272
273 //*----------------------------------------------------------------------------
274 //* \fn AT91F_UDP_Read
275 //* \brief Read available data from Endpoint OUT
276 //*----------------------------------------------------------------------------
277 uint32_t usb_read(byte_t* data, size_t len)
278 {
279 byte_t bank = btReceiveBank;
280 uint32_t packetSize, nbBytesRcv = 0;
281 uint32_t time_out = 0;
282
283 while (len)
284 {
285 if (!usb_check()) break;
286
287 if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {
288 packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);
289 len -= packetSize;
290 while(packetSize--)
291 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
292 pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(bank);
293 if (bank == AT91C_UDP_RX_DATA_BK0)
294 {
295 bank = AT91C_UDP_RX_DATA_BK1;
296 } else {
297 bank = AT91C_UDP_RX_DATA_BK0;
298 }
299 }
300 if (time_out++ == 0x1fff) break;
301 }
302
303 btReceiveBank = bank;
304 return nbBytesRcv;
305 }
306
307 //*----------------------------------------------------------------------------
308 //* \fn AT91F_CDC_Write
309 //* \brief Send through endpoint 2
310 //*----------------------------------------------------------------------------
311 uint32_t usb_write(const byte_t* data, const size_t len)
312 {
313 size_t length = len;
314 uint32_t cpt = 0;
315
316 if (!length) return 0;
317 if (!usb_check()) return 0;
318
319 // Send the first packet
320 cpt = MIN(length, AT91C_EP_IN_SIZE-1);
321 length -= cpt;
322 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
323 pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
324
325 while (length) {
326 // Fill the second bank
327 cpt = MIN(length, AT91C_EP_IN_SIZE-1);
328 length -= cpt;
329 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
330 // Wait for the the first bank to be sent
331 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
332 if (!usb_check()) return length;
333 }
334 pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
335 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
336 pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
337 }
338
339 // Wait for the end of transfer
340 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
341 if (!usb_check()) return length;
342 }
343
344 pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
345 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
346
347 return length;
348 }
349
350 //*----------------------------------------------------------------------------
351 //* \fn AT91F_USB_SendData
352 //* \brief Send Data through the control endpoint
353 //*----------------------------------------------------------------------------
354 unsigned int csrTab[100];
355 unsigned char csrIdx = 0;
356
357 static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length)
358 {
359 uint32_t cpt = 0;
360 AT91_REG csr;
361
362 do {
363 cpt = MIN(length, 8);
364 length -= cpt;
365
366 while (cpt--)
367 pUdp->UDP_FDR[0] = *pData++;
368
369 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
370 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
371 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
372 }
373
374 pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
375 do {
376 csr = pUdp->UDP_CSR[0];
377
378 // Data IN stage has been stopped by a status OUT
379 if (csr & AT91C_UDP_RX_DATA_BK0) {
380 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
381 return;
382 }
383 } while ( !(csr & AT91C_UDP_TXCOMP) );
384
385 } while (length);
386
387 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
388 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
389 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
390 }
391 }
392
393 //*----------------------------------------------------------------------------
394 //* \fn AT91F_USB_SendZlp
395 //* \brief Send zero length packet through the control endpoint
396 //*----------------------------------------------------------------------------
397 void AT91F_USB_SendZlp(AT91PS_UDP pUdp)
398 {
399 pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
400 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) );
401 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
402 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
403 }
404
405 //*----------------------------------------------------------------------------
406 //* \fn AT91F_USB_SendStall
407 //* \brief Stall the control endpoint
408 //*----------------------------------------------------------------------------
409 void AT91F_USB_SendStall(AT91PS_UDP pUdp)
410 {
411 pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;
412 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR) );
413 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
414 while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));
415 }
416
417 //*----------------------------------------------------------------------------
418 //* \fn AT91F_CDC_Enumerate
419 //* \brief This function is a callback invoked when a SETUP packet is received
420 //*----------------------------------------------------------------------------
421 void AT91F_CDC_Enumerate()
422 {
423 byte_t bmRequestType, bRequest;
424 uint16_t wValue, wIndex, wLength, wStatus;
425
426 if ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) )
427 return;
428
429 bmRequestType = pUdp->UDP_FDR[0];
430 bRequest = pUdp->UDP_FDR[0];
431 wValue = (pUdp->UDP_FDR[0] & 0xFF);
432 wValue |= (pUdp->UDP_FDR[0] << 8);
433 wIndex = (pUdp->UDP_FDR[0] & 0xFF);
434 wIndex |= (pUdp->UDP_FDR[0] << 8);
435 wLength = (pUdp->UDP_FDR[0] & 0xFF);
436 wLength |= (pUdp->UDP_FDR[0] << 8);
437
438 if (bmRequestType & 0x80) {
439 pUdp->UDP_CSR[0] |= AT91C_UDP_DIR;
440 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_DIR) );
441 }
442 pUdp->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;
443 while ( (pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) );
444
445 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
446 switch ((bRequest << 8) | bmRequestType) {
447 case STD_GET_DESCRIPTOR:
448 if (wValue == 0x100) // Return Device Descriptor
449 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));
450 else if (wValue == 0x200) // Return Configuration Descriptor
451 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
452 else if ((wValue & 0x300) == 0x300) // Return String Descriptor
453 AT91F_USB_SendData(pUdp, strDescriptor, MIN(sizeof(strDescriptor), wLength));
454 else
455 AT91F_USB_SendStall(pUdp);
456 break;
457 case STD_SET_ADDRESS:
458 AT91F_USB_SendZlp(pUdp);
459 pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);
460 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
461 break;
462 case STD_SET_CONFIGURATION:
463 btConfiguration = wValue;
464 AT91F_USB_SendZlp(pUdp);
465 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
466 pUdp->UDP_CSR[1] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
467 pUdp->UDP_CSR[2] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
468 pUdp->UDP_CSR[3] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
469 break;
470 case STD_GET_CONFIGURATION:
471 AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));
472 break;
473 case STD_GET_STATUS_ZERO:
474 wStatus = 0;
475 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
476 break;
477 case STD_GET_STATUS_INTERFACE:
478 wStatus = 0;
479 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
480 break;
481 case STD_GET_STATUS_ENDPOINT:
482 wStatus = 0;
483 wIndex &= 0x0F;
484 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) {
485 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
486 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
487 }
488 else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == 0)) {
489 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
490 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
491 }
492 else
493 AT91F_USB_SendStall(pUdp);
494 break;
495 case STD_SET_FEATURE_ZERO:
496 AT91F_USB_SendStall(pUdp);
497 break;
498 case STD_SET_FEATURE_INTERFACE:
499 AT91F_USB_SendZlp(pUdp);
500 break;
501 case STD_SET_FEATURE_ENDPOINT:
502 wIndex &= 0x0F;
503 if ((wValue == 0) && wIndex && (wIndex <= 3)) {
504 pUdp->UDP_CSR[wIndex] = 0;
505 AT91F_USB_SendZlp(pUdp);
506 }
507 else
508 AT91F_USB_SendStall(pUdp);
509 break;
510 case STD_CLEAR_FEATURE_ZERO:
511 AT91F_USB_SendStall(pUdp);
512 break;
513 case STD_CLEAR_FEATURE_INTERFACE:
514 AT91F_USB_SendZlp(pUdp);
515 break;
516 case STD_CLEAR_FEATURE_ENDPOINT:
517 wIndex &= 0x0F;
518 if ((wValue == 0) && wIndex && (wIndex <= 3)) {
519 if (wIndex == 1)
520 pUdp->UDP_CSR[1] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
521 else if (wIndex == 2)
522 pUdp->UDP_CSR[2] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
523 else if (wIndex == 3)
524 pUdp->UDP_CSR[3] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_ISO_IN);
525 AT91F_USB_SendZlp(pUdp);
526 }
527 else
528 AT91F_USB_SendStall(pUdp);
529 break;
530
531 // handle CDC class requests
532 case SET_LINE_CODING:
533 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) );
534 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
535 AT91F_USB_SendZlp(pUdp);
536 break;
537 case GET_LINE_CODING:
538 AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));
539 break;
540 case SET_CONTROL_LINE_STATE:
541 btConnection = wValue;
542 AT91F_USB_SendZlp(pUdp);
543 break;
544 default:
545 AT91F_USB_SendStall(pUdp);
546 break;
547 }
548 }
Impressum, Datenschutz