]> mj.ucw.cz Git - home-hw.git/blob - Src/usb.c
b7604abd7e28162684719c6483cb37e5893b6239
[home-hw.git] / Src / usb.c
1 #include "stm32f1xx.h"
2 #include "stm32f1xx_hal.h"
3
4 #include "usb.h"
5
6 #include <string.h>
7
8 void _Error_Handler(char * file, int line);     // FIXME
9
10 void usb_init(struct usb *usb, PCD_HandleTypeDef *hpcd)
11 {
12   memset(usb, 0, sizeof(*usb));
13   usb->hpcd = hpcd;
14   usb->state = USB_STATE_DEFAULT;
15   usb->ep0_state = USB_EP0_IDLE;
16
17   HAL_PCDEx_PMAConfig(hpcd, 0x00, PCD_SNG_BUF, 0x18);
18   HAL_PCDEx_PMAConfig(hpcd, 0x80, PCD_SNG_BUF, 0x58);
19
20   HAL_PCD_Start(hpcd);
21 }
22
23 static inline uint get_u16(byte *p)
24 {
25   return (p[1] << 8) | p[0];
26 }
27
28 static inline void put_u16(byte *p, u16 x)
29 {
30   p[0] = x;
31   p[1] = x >> 8;
32 }
33
34 #if 0  // FIXME
35 static struct usb_endpoint *ep_by_addr(struct usb *usb, byte ep_addr)
36 {
37   return ((ep_addr & 0x80) ? usb->ep_in : usb->ep_out) + (ep_addr & 0x7f);
38 }
39 #endif
40
41 static void usb_ctl_send_status(struct usb *usb)
42 {
43   usb->ep0_state = USB_EP0_STATUS_IN;
44   usb_ep_transmit(usb, 0x00, NULL, 0);
45 }
46
47 #if 0  // FIXME
48 static void usb_ctl_recv_status(struct usb *usb)
49 {
50   usb->ep0_state = USB_EP0_STATUS_OUT;
51   usb_ep_receive(usb, 0x00, NULL, 0);
52 }
53 #endif
54
55 static void usb_ctl_send_data(struct usb *usb, byte *data, uint len)
56 {
57   usb->ep0_state = USB_EP0_DATA_IN;
58   usb->ep0_total_length = len;
59   usb->ep0_remaining_length = len;
60   usb_ep_transmit(usb, 0x00, data, len);
61 }
62
63 #if 0  // FIXME
64 static void usb_ctl_recv_data(struct usb *usb, byte *data, uint len)
65 {
66   usb->ep0_state = USB_EP0_DATA_OUT;
67   usb->ep0_total_length = len;
68   usb->ep0_remaining_length = len;
69   usb_ep_transmit(usb, 0x00, data, len);
70 }
71 #endif
72
73 static void usb_ctl_send_byte(struct usb *usb, byte data)
74 {
75   usb->status_buf[0] = data;
76   usb_ctl_send_data(usb, usb->status_buf, 1);
77 }
78
79 static void usb_ctl_send_u16(struct usb *usb, u16 data)
80 {
81   put_u16(usb->status_buf, data);
82   usb_ctl_send_data(usb, usb->status_buf, 2);
83 }
84
85 static void usb_ctl_error(struct usb *usb)
86 {
87   usb_ep_stall(usb, 0x00);
88   usb_ep_stall(usb, 0x80);
89 }
90
91 struct setup_request {
92   byte bmRequest;
93   byte bRequest;
94   u16 wValue;
95   u16 wIndex;
96   u16 wLength;
97 };
98
99 static void usb_ctl_setup_error(struct usb *usb, struct setup_request *setup)
100 {
101   usb_ep_stall(usb, setup->bmRequest & USB_REQ_DIRECTION);
102 }
103
104 static void dev_get_status(struct usb *usb, struct setup_request *setup)
105 {
106   if ((usb->state != USB_STATE_ADDRESSED && usb->state != USB_STATE_CONFIGURED) ||
107       setup->wValue || setup->wIndex || setup->wLength != 2)
108     return usb_ctl_error(usb);
109
110   uint stat = 0;
111 #ifdef USB_SELF_POWERED
112   stat |= USB_DEV_STATUS_SELF_POWERED;
113 #endif
114   if (usb->remote_wakeup)
115     stat |= USB_DEV_STATUS_REMOTE_WAKEUP;
116   usb_ctl_send_u16(usb, stat);
117 }
118
119 static void dev_clear_feature(struct usb *usb, struct setup_request *setup)
120 {
121   if (setup->wIndex || setup->wLength)
122     return usb_ctl_error(usb);
123
124   if (setup->wValue == USB_FEATURE_REMOTE_WAKEUP)
125     {
126       usb->remote_wakeup = 0;
127       usb_ctl_send_status(usb);
128     }
129   else
130     usb_ctl_error(usb);
131 }
132
133 static void dev_set_feature(struct usb *usb, struct setup_request *setup)
134 {
135   if (setup->wIndex || setup->wLength)
136     return usb_ctl_error(usb);
137
138   if (setup->wValue == USB_FEATURE_REMOTE_WAKEUP)
139     {
140       usb->remote_wakeup = 1;
141       usb_ctl_send_status(usb);
142     }
143   else
144     usb_ctl_error(usb);
145 }
146
147 static void dev_set_address(struct usb *usb, struct setup_request *setup)
148 {
149   if (setup->wIndex || setup->wLength)
150     return usb_ctl_error(usb);
151
152   uint addr = setup->wValue & 0x7f;
153   if (usb->state == USB_STATE_CONFIGURED)
154     usb_ctl_error(usb);
155   else
156     {
157       usb->address = addr;
158       HAL_PCD_SetAddress(usb->hpcd, addr);
159       usb_ctl_send_status(usb);
160       usb->state = addr ? USB_STATE_ADDRESSED : USB_STATE_DEFAULT;
161     }
162 }
163
164 static void dev_get_descriptor(struct usb *usb, struct setup_request *setup)
165 {
166 }
167
168 static void dev_get_configuration(struct usb *usb, struct setup_request *setup)
169 {
170   if (setup->wValue || setup->wIndex || setup->wLength != 1)
171     return usb_ctl_error(usb);
172
173   switch (usb->state)
174     {
175     case USB_STATE_ADDRESSED:
176       usb_ctl_send_byte(usb, 0);
177       break;
178     case USB_STATE_CONFIGURED:
179       usb_ctl_send_byte(usb, usb->config);
180       break;
181     default:
182       usb_ctl_error(usb);
183     }
184 }
185
186 static void dev_set_configuration(struct usb *usb, struct setup_request *setup)
187 {
188   byte cfg = setup->wValue & 0xff;
189
190   // FIXME: Support more configurations
191   if (cfg > 1 || setup->wIndex || setup->wLength)
192     return usb_ctl_error(usb);
193
194   switch (usb->state)
195     {
196     case USB_STATE_ADDRESSED:
197       if (cfg)
198         {
199           usb->config = cfg;
200           usb->state = USB_STATE_CONFIGURED;
201           // FIXME: Notify that the device was configured
202         }
203       usb_ctl_send_status(usb);
204       break;
205     case USB_STATE_CONFIGURED:
206       if (!cfg)
207         {
208           // Unconfiguring
209           usb->config = 0;
210           usb->state = USB_STATE_ADDRESSED;
211           // FIXME: Notify that the device was unconfigured
212         }
213       else if (cfg != usb->config)
214         {
215           usb->config = cfg;
216           // FIXME: Notify about configuration change
217         }
218       usb_ctl_send_status(usb);
219       break;
220     default:
221       usb_ctl_error(usb);
222     }
223 }
224
225 static void dev_setup(struct usb *usb, struct setup_request *setup)
226 {
227   switch (setup->bRequest)
228     {
229     case USB_REQ_GET_STATUS:
230       return dev_get_status(usb, setup);
231     case USB_REQ_CLEAR_FEATURE:
232       return dev_clear_feature(usb, setup);
233     case USB_REQ_SET_FEATURE:
234       return dev_set_feature(usb, setup);
235     case USB_REQ_SET_ADDRESS:
236       return dev_set_address(usb, setup);
237     case USB_REQ_GET_DESCRIPTOR:
238       return dev_get_descriptor(usb, setup);
239     case USB_REQ_GET_CONFIGURATION:
240       return dev_get_configuration(usb, setup);
241     case USB_REQ_SET_CONFIGURATION:
242       return dev_set_configuration(usb, setup);
243     }
244
245   usb_ctl_setup_error(usb, setup);
246 }
247
248 static void intf_setup(struct usb *usb, struct setup_request *setup)
249 {
250   byte intf = setup->wIndex & 0xff;
251
252   if (!intf)
253     {
254       // FIXME: Support more interfaces
255       usb_ctl_error(usb);
256       return;
257     }
258
259   switch (setup->bRequest)
260     {
261     case USB_REQ_GET_STATUS:
262       if (setup->wValue || setup->wLength != 2 || usb->state != USB_STATE_CONFIGURED)
263         usb_ctl_error(usb);
264       else
265         usb_ctl_send_u16(usb, 0);
266       return;
267
268     case USB_REQ_CLEAR_FEATURE:
269     case USB_REQ_SET_FEATURE:
270       // Interfaces have no standard features
271       return usb_ctl_error(usb);
272     }
273
274   usb_ctl_setup_error(usb, setup);
275 }
276
277 static void ep_setup(struct usb *usb, struct setup_request *setup)
278 {
279   byte ep_addr = setup->wIndex & 0x8f;
280
281   switch (setup->bRequest)
282     {
283     case USB_REQ_GET_STATUS:
284       if (setup->wValue || setup->wLength != 2)
285         return usb_ctl_error(usb);
286       switch (usb->state)
287         {
288         case USB_STATE_ADDRESSED:
289           if (ep_addr & 0x7f)
290             usb_ctl_error(usb);
291           return;
292         case USB_STATE_CONFIGURED:
293           {
294             if (usb_ep_is_stalled(usb, ep_addr))
295               usb_ctl_send_u16(usb, 1);
296             else
297               usb_ctl_send_u16(usb, 0);
298             return;
299           }
300         default:
301           return usb_ctl_error(usb);
302         }
303       break;
304
305     case USB_REQ_SET_FEATURE:
306       if (setup->wLength)
307         return usb_ctl_error(usb);
308       switch (usb->state)
309         {
310         case USB_STATE_ADDRESSED:
311           if (ep_addr & 0x7f)
312             usb_ctl_error(usb);
313           return;
314         case USB_STATE_CONFIGURED:
315           if (setup->wValue == USB_FEATURE_EP_HALT)
316             {
317               if (ep_addr & 0x7f)
318                 usb_ep_stall(usb, ep_addr);
319             }
320           usb_ctl_send_status(usb);
321           return;
322         default:
323           usb_ctl_error(usb);
324         }
325       break;
326
327     case USB_REQ_CLEAR_FEATURE:
328       if (setup->wLength)
329         return usb_ctl_error(usb);
330       switch (usb->state)
331         {
332         case USB_STATE_ADDRESSED:
333           if (ep_addr & 0x7f)
334             usb_ctl_error(usb);
335           return;
336         case USB_STATE_CONFIGURED:
337           if (setup->wValue == USB_FEATURE_EP_HALT)
338             {
339               if (ep_addr & 0x7f)
340                 usb_ep_unstall(usb, ep_addr);
341             }
342           usb_ctl_send_status(usb);
343           return;
344         default:
345           usb_ctl_error(usb);
346         }
347       break;
348     }
349
350   usb_ctl_setup_error(usb, setup);
351 }
352
353 static void usb_handle_setup(struct usb *usb, struct setup_request *setup)
354 {
355   usb->ep0_state = USB_EP0_SETUP;
356   usb->ep0_setup_data_length = setup->wLength;
357
358   if ((setup->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD)
359     {
360       // FIXME: Class-specific and vendor-specific setup packets not supported
361       // FIXME: Check USB_STATE_CONFIGURED here
362       usb_ctl_setup_error(usb, setup);
363     }
364
365   switch (setup->bmRequest & USB_REQ_RECIPIENT_MASK)
366     {
367     case USB_REQ_RECIPIENT_DEVICE:
368       return dev_setup(usb, setup);
369     case USB_REQ_RECIPIENT_INTERFACE:
370       return intf_setup(usb, setup);
371     case USB_REQ_RECIPIENT_ENDPOINT:
372       return ep_setup(usb, setup);
373     }
374
375   usb_ctl_setup_error(usb, setup);
376 }
377
378 void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
379 {
380   struct usb *usb = hpcd->pData;
381   byte *req = (byte *) hpcd->Setup;
382
383   struct setup_request setup = {
384     .bmRequest = req[0],
385     .bRequest = req[1],
386     .wValue = get_u16(req+2),
387     .wIndex = get_u16(req+4),
388     .wLength = get_u16(req+2),
389   };
390   usb_handle_setup(usb, &setup);
391 }
392
393 void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
394 {
395   struct usb *usb = hpcd->pData;
396   PCD_EPTypeDef *ep = &hpcd->IN_ep[epnum];
397
398   if (!epnum)
399     {
400       // HAL/LL handle EP0 transfers in a completely different way, we have to do many things ourselves
401       if (usb->ep0_state != USB_EP0_DATA_OUT)
402         return;
403       if (usb->ep0_remaining_length > ep->maxpacket)
404         {
405           usb->ep0_remaining_length -= ep->maxpacket;
406           usb_ep_receive(usb, 0x00, ep->xfer_buff, MIN(usb->ep0_remaining_length, ep->maxpacket));
407         }
408       else
409         {
410           if (usb->state == USB_STATE_CONFIGURED)
411             {
412               // FIXME: Handle incoming control packet
413             }
414           usb_ctl_send_status(usb);
415         }
416     }
417   else
418     {
419       if (usb->state == USB_STATE_CONFIGURED)
420         {
421           // FIXME: Custom data callback
422         }
423     }
424 }
425
426 void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
427 {
428   struct usb *usb = hpcd->pData;
429   PCD_EPTypeDef *ep = &hpcd->IN_ep[epnum];
430
431   if (!epnum)
432     {
433       // HAL/LL handle EP0 transfers in a completely different way, we have to do many things ourselves
434       if (usb->ep0_state != USB_EP0_DATA_IN)
435         return;
436       if (usb->ep0_remaining_length > ep->maxpacket)
437         {
438           usb->ep0_remaining_length -= ep->maxpacket;
439           usb_ep_transmit(usb, 0x00, ep->xfer_buff, usb->ep0_remaining_length);
440           usb_ep_receive(usb, 0x00, NULL, 0);
441         }
442       else if (usb->ep0_total_length && usb->ep0_total_length % ep->maxpacket == 0 && usb->ep0_total_length < usb->ep0_setup_data_length)
443         {
444           /*
445            *  Each data transfer must be terminated by either a small packet (less than maxpacket)
446            *  or by reaching the answer size requested in the setup packet. Send an empty final packet
447            *  if needed.
448            */
449           usb_ep_transmit(usb, 0x00, NULL, 0);
450           usb->ep0_setup_data_length = 0;
451           usb_ep_receive(usb, 0x00, NULL, 0);
452         }
453       else
454         {
455           if (usb->state == USB_STATE_CONFIGURED)
456             {
457               // FIXME: Custom data callback
458               // All data have been sent
459             }
460         }
461     }
462   else
463     {
464       if (usb->state == USB_STATE_CONFIGURED)
465         {
466           // FIXME: Custom data callback
467           // This gets called when a complete message is sent
468         }
469     }
470 }
471
472 void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
473 {
474   // We are not interested in Start of frame packets
475   // (neither we set hpcd->Init.Sof_enable, so this callback does not get called)
476 }
477
478 void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
479
480   struct usb *usb = hpcd->pData;
481
482   usb->state = USB_STATE_DEFAULT;
483
484   usb_ep_open(usb, 0x00, USB_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
485   usb_ep_open(usb, 0x80, USB_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
486 }
487
488 void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
489 {
490   struct usb *usb = hpcd->pData;
491
492   usb->pre_suspend_state = usb->state;
493   usb->state = USB_STATE_SUSPENDED;
494
495   if (hpcd->Init.low_power_enable)
496     SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
497 }
498
499 void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
500 {
501   struct usb *usb = hpcd->pData;
502   usb->state = usb->pre_suspend_state;
503 }
504
505 void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
506 {
507   // We do not support isochronous mode
508 }
509
510 void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
511 {
512   // We do not support isochronous mode
513 }
514
515 void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
516 {
517 }
518
519 void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
520 {
521   struct usb *usb = hpcd->pData;
522   usb->state = USB_STATE_DEFAULT;
523 }