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