]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/libs4c/usb/pdiusb/pdiusb.c
Merge branch 'master' into can-usb1
[lincan.git] / embedded / libs4c / usb / pdiusb / pdiusb.c
1 /*********************************************************/
2 /***   Module : PDIUSB D11,H11,H11A,D12 - implement.   ***/
3 /***   Author : Roman Bartosinski (C) 03.10.2002       ***/
4 /***   Description : Integrate common functions for    ***/
5 /***                PDIUSBD11,PDIUSBD12,PDIUSBH11(old) ***/
6 /***                PDIUSBH11A in Single/Multiple mode ***/
7 /***                 to one common file.               ***/
8 /***   Modify : 10.10.2002 - add H11                   ***/
9 /***            13.10.2002 - add spec.fnc for 'using'  ***/
10 /*********************************************************/
11
12 #include <system_def.h>
13 #include <endian.h>
14 #if __BYTE_ORDER == __BIG_ENDIAN
15   #include <byteswap.h>
16 #endif
17 #include <usb/pdiusb.h>
18 #include <usb/usb_spec.h>
19
20   #ifdef PDI_CMD_RWD_INTERNAL
21    #ifndef PDIUSBD12
22      #include <periph/i2c.h>
23    #endif
24   #endif
25
26   #ifndef SDCC
27    #define xdata 
28   #endif
29
30
31 /*********************************************************/
32 // Function for read and write from/into chip
33
34  #if defined(PDI_CMD_RWD_INTERNAL)
35   #if defined(PDIUSBD12) // parallel interface
36
37    void pdiSendCommand( unsigned char byCmd) {
38      *((volatile xdata unsigned char *) PDIUSB_COMMAND_ADDR) = byCmd;
39    }
40    unsigned char pdiReadData( unsigned char byCount, void *pbyData) {
41      unsigned char out = byCount;
42      while (byCount) {
43        byCount--;
44        *(unsigned char*)pbyData++ = *((volatile xdata unsigned char *) PDIUSB_READ_DATA_ADDR);
45      }
46      return out;
47    }
48    void pdiWriteData( unsigned char byCount, const void *pbyData) {
49      while (byCount) {
50        byCount--;
51        *((volatile xdata unsigned char *) PDIUSB_WRITE_DATA_ADDR) = *(unsigned char*)pbyData++;
52      }
53    }
54
55    #if defined(PDI_USE_USING)
56      unsigned short pdiIntCmdReadData( unsigned char byCmd, unsigned char byShort) _PDI_USING {
57        unsigned char i[2];
58        *((volatile xdata unsigned char *) PDIUSB_COMMAND_ADDR) = byCmd;
59        i[0] = *((volatile xdata unsigned char *) PDIUSB_READ_DATA_ADDR);
60        if ( !byShort) {
61         i[1] = 0;
62         return i[0];
63        }
64        i[1] = *((volatile xdata unsigned char *) PDIUSB_READ_DATA_ADDR);
65        return (((unsigned short) i[1]) << 8) + i[0];
66      }
67    #endif
68
69   #else // serial interface iic
70    #ifndef D11_REG_CMD
71      #define D11_REG_CMD  PDIUSB_COMMAND_ADDR
72    #endif
73    #ifndef D11_REG_DATA_WRITE
74      #define D11_REG_DATA_WRITE PDIUSB_WRITE_DATA_ADDR
75    #endif
76    #ifndef D11_REG_DATA_READ
77      #define D11_REG_DATA_READ PDIUSB_READ_DATA_ADDR
78    #endif
79      
80    void pdiSendCommand( unsigned char byCmd) {
81      I2C_Write( D11_REG_CMD, &byCmd, 1);
82    }
83    unsigned char pdiReadData( unsigned char byCount, void *pbyData) {
84      I2C_Read( D11_REG_DATA_READ, pbyData, byCount);
85      return byCount;
86    }
87    void pdiWriteData( unsigned char byCount, const void *pbyData) {
88      I2C_Write( D11_REG_DATA_WRITE, pbyData, byCount);
89    }
90    #if defined(PDI_USE_USING)
91     unsigned short pdiIntCmdReadData( unsigned char byCmd, unsigned char byShort) _PDI_USING {
92     }
93    #endif
94
95   #endif
96  #endif
97
98
99 /*********************************************************/
100 /*********************************************************/
101 // PDIUSB common commands
102
103 #if defined(PDIUSBH11) || defined(PDIUSBH11A) || defined(PDIUSBD11)
104
105  /*********************************************************/
106  // pdiSetHUBAddressEnable
107  // enable HUB function and set address (byAddress is 0-0x7F, byEnable is 0 or 1)
108    void pdiSetHUBAddressEnable( unsigned char byAddress, unsigned char byEnable) {
109 // usb_debug_print( DEBUG_LEVEL_HIGH, ("H "));
110      byAddress = (byAddress & 0x7F) | (byEnable << 7);
111      pdiSendCommand( PDI_CMD_HUB_ENB_ADDR);
112      pdiWriteData( 1, &byAddress);
113    }
114
115 #endif
116 #if !defined(PDIUSBH11A_MULTPLE) // D11,D12,H11,H11A_S(emb.fnc)
117
118  /*********************************************************/
119  // pdiSetAddressEnable
120  // Enable function and set address (byAddress is 0-0x7F, byEnable is 0 or 1)
121    void pdiSetAddressEnable( unsigned char byAddr_Enb) {
122 // usb_debug_print( DEBUG_LEVEL_HIGH, ("A "));
123      pdiSendCommand( PDI_CMD_FNC_ENB_ADDR);
124      pdiWriteData( 1, &byAddr_Enb);
125    }
126
127 #else
128
129  /*********************************************************/
130  // pdiSetEmbFncAddressEnable
131  // Enable Embedded function and set address (byAddress is 0-0x7F, byEnable is 0 or 1)
132  // byFnc - function index (zero based) 0-3
133    void pdiSetEmbFncAddressEnable( unsigned char byFnc, unsigned char byAddress, unsigned char byEnable) {
134      byAddress = (byAddress & 0x7F) | (byEnable << 7);
135      pdiSendCommand( PDI_CMD_FNC1_ENB_ADDR + byFnc);
136      pdiWriteData( 1, &byAddress);
137    }
138
139 #endif
140
141
142
143  /*********************************************************/
144  // pdiSetEndpointEnable
145  // enable/disable endpoints (PDI_EPEN_xxx)
146    void pdiSetEndpointEnable( unsigned char byEnable) {
147 // usb_debug_print( DEBUG_LEVEL_HIGH, ("E "));
148      pdiSendCommand( PDI_CMD_EPEN);
149      pdiWriteData( 1, &byEnable);
150    }
151
152
153 #if !defined(PDIUSBH11)  // H11 has not it
154
155  /*********************************************************/
156  // pdiSetMode
157  // set chip mode (PDI_MODE_xxx) and clock division factor (PDI_CLOCK_xxx)
158   void pdiSetMode( unsigned short wMode_Clock) {
159      unsigned char sm[2];
160 // usb_debug_print( DEBUG_LEVEL_HIGH, ("M%04X ",wMode_Clock));
161      sm[0] = (unsigned char) (wMode_Clock & 0xff);
162      sm[1] = (unsigned char) (wMode_Clock >> 8);
163      pdiSendCommand( PDI_CMD_SET_MODE);
164      pdiWriteData( 2, sm);
165    }
166
167 #endif
168
169  #if defined(PDIUSBD12)
170
171  /*********************************************************/
172  // pdiSetDMA
173  // set DMA mode (PDI_DMA_xxx)
174   void pdiSetDMA( unsigned char byDma) {
175     pdiSendCommand( PDI_CMD_SET_DMA);
176     pdiWriteData( 1, &byDma);
177   }
178
179  /*********************************************************/
180  // pdiGetDMA
181  // get current DMA mode
182   unsigned char pdiGetDMA( void) {
183     unsigned char dma;
184     pdiSendCommand( PDI_CMD_GET_DMA);
185     pdiReadData( 1, &dma);
186     return dma;
187   }
188
189  #endif
190
191
192  #if defined(PDIUSBH11)
193
194  /*********************************************************/
195
196  // pdiGetInterrupt - H11 return only one byte
197  // get interrupt register (PDI_INT_xxx)
198   unsigned char pdiGetInterrupt( void) _PDI_USING {
199     unsigned char gin;
200 #if defined(PDI_USE_USING)
201     return pdiIntCmdReadData( PDI_CMD_GET_INT_REG, 0);
202 #else
203     pdiSendCommand( PDI_CMD_GET_INT_REG);
204     pdiReadData( 1, &gin);
205     return gin;
206 #endif
207   }
208
209  #else
210
211  /*********************************************************/
212  // pdiGetInterrupt
213  // get interrupt register (PDI_INT_xxx)
214   unsigned short pdiGetInterrupt( void) _PDI_USING {
215     unsigned short gin;
216 #if defined(PDI_USE_USING)
217     return pdiIntCmdReadData( PDI_CMD_GET_INT_REG, 1);
218 #else
219     pdiSendCommand( PDI_CMD_GET_INT_REG);
220     pdiReadData( 2, &gin);
221    #if __BYTE_ORDER == __BIG_ENDIAN
222     gin=bswap_16(gin);
223    #endif
224     return gin; //pdiData[0] + (((unsigned short)pdiData[1])<<8);
225 #endif
226   }
227
228  #endif
229
230  /*********************************************************/
231  // pdiSelectEp
232  // set internal buffer pointer to selected endpoint (zero based) (PDI_SELEP_xxx)
233   unsigned char pdiSelectEp( unsigned char byEpIdx) {
234     unsigned char sep;
235 // usb_debug_print( DEBUG_LEVEL_HIGH, ("e%1d ",byEpIdx));
236     pdiSendCommand( PDI_CMD_SELECT_EP + byEpIdx);
237     pdiReadData( 1, &sep);
238     return sep;
239   }
240
241  /*********************************************************/
242  // pdiGetLastTransStatus
243  // get Last transaction status (PDI_LTSTAT_xxx and PDI_ERR_xxx)
244   unsigned char pdiGetLastTransStatus( unsigned char byEpIdx) _PDI_USING {
245     unsigned char lts;
246 // usb_debug_print( DEBUG_LEVEL_HIGH, ("L "));
247 #if defined(PDI_USE_USING)
248     return pdiIntCmdReadData( PDI_CMD_GET_LAST_STAT + byEpIdx, 0);
249 #else
250     pdiSendCommand( PDI_CMD_GET_LAST_STAT + byEpIdx);
251     pdiReadData( 1, &lts);
252     return lts;
253 #endif
254   }
255
256
257  #if defined(PDIUSBD11) || defined(PDIUSBH11) || defined(PDIUSBH11A)
258
259  /*********************************************************/
260  // pdiGetEpStatus
261  // get Endpoint Status (PDI_EPSTAT_xxx)
262   unsigned char pdiGetEpStatus( unsigned char byEpIdx) {
263     unsigned char ges;
264 // usb_debug_print( DEBUG_LEVEL_HIGH, ("G "));
265     pdiSendCommand( PDI_CMD_GET_EP_STAT + byEpIdx);
266     pdiReadData( 1, &ges);
267     return ges;
268   }
269
270  #endif
271
272  /*********************************************************/
273  // pdiReadFromEpBuffer - raw reading
274  // read data from selected internal chip buffer
275  // if byLength < length of buffer data, so we read only byLength data)
276   unsigned char pdiReadFromEpBuffer( unsigned char byLength, unsigned char *pToBuff) {
277     unsigned char rdep[2];
278 // usb_debug_print( DEBUG_LEVEL_HIGH, ("R "));
279     pdiSendCommand( PDI_CMD_READ_BUFFER);
280     pdiReadData( 2, rdep);
281     if ( rdep[1]) { // there is some data
282       if ( byLength < rdep[1]) // we need less data then is received
283         rdep[1] = byLength;
284       pdiReadData( rdep[1], pToBuff);
285     }
286     return rdep[1];
287   }
288
289  /*********************************************************/
290  // pdiWriteToEpBuffer - raw writing
291  // write data to selected internal chip buffer
292   void pdiWriteToEpBuffer( unsigned char byLength, const unsigned char *pFromBuff) {
293     unsigned char hd[2];
294 // usb_debug_print( DEBUG_LEVEL_HIGH, ("W "));
295     pdiSendCommand( PDI_CMD_WRITE_BUFFER);
296     hd[0] = 0; hd[1] = byLength;
297     pdiWriteData( 2, hd);
298     if ( byLength) {
299       pdiWriteData( byLength, pFromBuff);
300     }
301   }
302
303  /*********************************************************/
304  // pdiSetEpStatus
305  // set endpoint stall flag
306   void pdiSetEpStatus( unsigned char byEpIdx, unsigned char byStatus) {
307 // usb_debug_print( DEBUG_LEVEL_HIGH, ("T "));
308     pdiSendCommand( PDI_CMD_SET_EP_STAT + byEpIdx);
309     pdiWriteData( 1, &byStatus);
310   }
311
312  /*********************************************************/
313  // pdiAcknowledgeSetup
314  // chip disable fncs Validate and Clear after SETUP packet,
315  // this cmd re-enable these fncs
316   void pdiAcknowledgeSetup( void) {
317 // usb_debug_print( DEBUG_LEVEL_HIGH, ("C "));
318     pdiSendCommand( PDI_CMD_ACK_SETUP);
319   }
320
321  /*********************************************************/
322  // pdiClearBuffer
323  // set endpoint flag 'empty' and next data can be receive
324   void pdiClearBuffer( void) {
325 // usb_debug_print( DEBUG_LEVEL_HIGH, ("B "));
326     pdiSendCommand( PDI_CMD_CLEAR_BUFFER);
327   }
328
329
330  /*********************************************************/
331  // pdiValidateBuffer
332  // set endpoint flag 'full' and data can be send
333   void pdiValidateBuffer( void) {
334 // usb_debug_print( DEBUG_LEVEL_HIGH, ("V "));
335     pdiSendCommand( PDI_CMD_VALID_BUFFER);
336   }
337
338  /*********************************************************/
339  // pdiSendResume
340  // send an upstream resume signal for 10ms
341   void pdiSendResume( void) {
342 // usb_debug_print( DEBUG_LEVEL_HIGH, ("M "));
343     pdiSendCommand( PDI_CMD_SEND_RESUME);
344   }
345
346  /*********************************************************/
347  // pdiGetFrameNumber
348  // return frame number of last successfully received SOF
349   unsigned short pdiGetFrameNumber( void) {
350     unsigned short gfn;
351     pdiSendCommand( PDI_CMD_GET_FRAME);
352     pdiReadData( 2, &gfn);
353    #if __BYTE_ORDER == __BIG_ENDIAN
354     gfn=bswap_16(gfn);
355    #endif
356     return gfn; //pdiData[0] + (((unsigned short)pdiData[1])<<8);
357   }
358   
359  /*********************************************************/
360  // pdiGetChipID  - this function is undocumented
361  // read chip ID (not documented function) ( LSB is maybe type of chip in hex (0x12,0x11))
362   unsigned short pdiGetChipID( void) {
363     unsigned short gid;
364     pdiSendCommand( PDI_CMD_GET_CHIP_ID);
365     pdiReadData( 2, &gid);
366    #if __BYTE_ORDER == __BIG_ENDIAN
367     gid=bswap_16(gid);
368    #endif
369     return gid; //pdiData[0] + (((unsigned short)pdiData[1])<<8);
370   }    
371
372
373  /*********************************************************/
374  /*********************************************************/
375  // HUB command
376 #if defined(PDIUSBH11) || defined(PDIUSBH11A)
377  /*********************************************************/
378  // pdiClearPortFeature
379  // clear feature 'byFeature' in downstream port 2-5 'byEpIdx' (zero based)
380   void pdiClearPortFeature( unsigned char byEpIdx, unsigned char byFeature) {
381     pdiSendCommand( PDI_CMD_P2_CLR_FEATURE + byEpIdx);
382     pdiWriteData( 1, &byFeature);
383   }
384
385  /*********************************************************/
386  // pdiSetPortFeature
387  // set feature 'byFeature' in downstream port 2-5 'byEpIdx' (zero based)
388   void pdiSetPortFeature( unsigned char byEpIdx, unsigned char byFeature) {
389     pdiSendCommand( PDI_CMD_P2_SET_FEATURE + byEpIdx);
390     pdiWriteData( 1, &byFeature);
391   }
392   
393  /*********************************************************/
394  // pdiGetPortFeature
395  // get port status (port status byte and port status change byte)
396   unsigned short pdiGetPortFeature( unsigned char byEpIdx) {
397     unsigned short gpf;
398     pdiSendCommand( PDI_CMD_P2_GET_STATUS + byEpIdx);
399     pdiReadData( 2, &gpf);
400    #if __BYTE_ORDER == __BIG_ENDIAN
401     gpf=bswap_16(gpf);
402    #endif
403     return gpf; //pdiData[0] + (((unsigned short)pdiData[1])<<8);
404   }
405   
406  /*********************************************************/
407  // pdiSetStatusChangeBits
408  // set local power change bits status
409   void pdiSetStatusChangeBits( unsigned char byBits) {
410     pdiSendCommand( PDI_CMD_SET_CHNG_BITS);
411     pdiWriteData( 1, &byBits);
412   }
413   
414 #endif
415
416
417
418 /*********************************************************/
419 /*********************************************************/
420 // PDIUSB other commands
421
422  // complex function for select endpoint, write data and validate data in endpoint buffer
423  void pdiWriteEndpoint( unsigned char byEpIdx, unsigned char byLength, const unsigned char *pbyData) {
424    pdiSelectEp( byEpIdx);
425    pdiWriteToEpBuffer( byLength, pbyData);
426    pdiValidateBuffer();
427  }
428
429  // complex function for select endpoint, read data and clear endpoint buffer
430  // byMaxLength means how many bytes will be maximally read.
431  unsigned char pdiReadEndpoint( unsigned char byEpIdx, unsigned char byMaxLength, unsigned char *pbyData) {
432    unsigned char cnt = 0, sep;
433    sep = pdiSelectEp( byEpIdx);
434    if ( sep & PDI_SELEP_FULL) {
435     cnt = pdiReadFromEpBuffer( byMaxLength, pbyData);
436     pdiClearBuffer();
437    }
438    return cnt;
439  }
440
441  // complex universal function for select command and read/write data to/from PDIUSB
442  unsigned char pdiCmdData( unsigned char byCmd, unsigned char *pbyData,
443                            unsigned char byCount, unsigned char byRead) {
444    pdiSendCommand( byCmd);
445    if ( byCount) {
446      if( byRead) byCount = pdiReadData( byCount, pbyData);  // Read Data
447      else pdiWriteData( byCount, pbyData);                  // Write Data
448    }
449    return byCount;   
450  }
451
452 #if !defined(PDIUSBH11A_MULTIPLE)
453  // complex function for acknowledge control endpoint
454  void pdiAckSetupControl( void) {
455    pdiSendCommand( PDI_CMD_SELECT_EP + PDI_EP0_RX);
456    pdiSendCommand( PDI_CMD_ACK_SETUP);
457    pdiSendCommand( PDI_CMD_CLEAR_BUFFER);
458    pdiSendCommand( PDI_CMD_SELECT_EP + PDI_EP0_TX);
459    pdiSendCommand( PDI_CMD_ACK_SETUP);
460  }
461 #else
462  // complex function for acknowledge control endpoint ( for one emb.fnc. 1,6,7) (zero-based 0,1,2)
463  void pdiAckSetupFncControl( unsigned char Fnc) {
464    unsigned char FncTab[3] = { PDI_F1_EP0_RX, PDI_F6_EP0_RX, PDI_F7_EP0_RX};
465    pdiSendCommand( PDI_CMD_SELECT_EP + FncTab[Fnc]);
466    pdiSendCommand( PDI_CMD_ACK_SETUP);
467    pdiSendCommand( PDI_CMD_CLEAR_BUFFER);
468    pdiSendCommand( PDI_CMD_SELECT_EP + FncTab[Fnc] + 1);
469    pdiSendCommand( PDI_CMD_ACK_SETUP);
470  }
471 #endif
472
473 #if defined(PDIUSBD12) // parallel interface
474  void pdiInit( void) {
475    pdiSetAddressEnable( PDI_ENAD_ENABLE);
476    pdiSetEndpointEnable( PDI_EPEN_ENABLE);
477    pdiSetDMA( PDI_DMA_EP4_INT | PDI_DMA_EP5_INT);
478    pdiSetMode( PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING |
479                PDI_MODE_SOFT_CONNECT | PDI_CLOCK_12M);
480  }
481 #endif
482
483 #if defined(PDIUSBH11A_SINGLE) // serial interface
484  void pdiInit( void) {
485    pdiSetHUBAddressEnable( 0, 0); // disable HUB
486    pdiSetAddressEnable( PDI_ENAD_ENABLE);    // enable emb.function
487    pdiSetEndpointEnable( PDI_EPEN_FNC_ENB);
488    pdiSetMode( PDI_MODE_REMOTE_WAKEUP | PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING |
489                PDI_MODE_SOFT_CONNECT | PDI_MODE_SINGLE_FNC | PDI_CLOCK_12M);
490  }
491 #endif
492
493 /*********************************************************/
494
495  static const unsigned char epin2idx[]={
496    PDI_EP0_IN,
497    PDI_EP1_IN,
498   #if PDI_CNT_EP > 1
499    PDI_EP2_IN,
500   #if PDI_CNT_EP > 2
501    PDI_EP3_IN,
502   #endif
503   #endif
504  };
505
506  static const unsigned char epout2idx[]={
507    PDI_EP0_OUT,
508    PDI_EP1_OUT,
509   #if PDI_CNT_EP > 1
510    PDI_EP2_OUT,
511   #if PDI_CNT_EP > 2
512    PDI_EP3_OUT,
513   #endif
514   #endif
515  };
516
517  // pdiEp2Idx
518  // convert endpoint number to pdi index number
519  unsigned char pdiEp2Idx(unsigned char ep) {
520    if(ep & USB_ENDPOINT_DIRECTION_MASK)
521      return epin2idx[ep & 0xf];
522    else
523      return epout2idx[ep & 0xf];
524  }
525
526  /*********************************************************/
527  /*********************************************************/