diff options
-rw-r--r-- | firmware/common/timefuncs.c | 39 | ||||
-rw-r--r-- | firmware/include/timefuncs.h | 2 | ||||
-rw-r--r-- | firmware/usbstack/usb_storage.c | 42 |
3 files changed, 81 insertions, 2 deletions
diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c index 6fdc0b7240..f5097c8e52 100644 --- a/firmware/common/timefuncs.c +++ b/firmware/common/timefuncs.c | |||
@@ -193,3 +193,42 @@ time_t mktime(struct tm *t) | |||
193 | return(result); | 193 | return(result); |
194 | } | 194 | } |
195 | #endif | 195 | #endif |
196 | |||
197 | int day_of_week(int m, int d, int y) | ||
198 | { | ||
199 | char mo[12] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; | ||
200 | |||
201 | if(m == 0 || m == 1) y--; | ||
202 | return (d + mo[m] + y + y/4 - y/100 + y/400) % 7; | ||
203 | } | ||
204 | |||
205 | void yearday_to_daymonth(int yd, int y, int *d, int *m) | ||
206 | { | ||
207 | short t[12] = { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; | ||
208 | int i; | ||
209 | |||
210 | if((y%4 == 0 && y%100 != 0) || y%400 == 0) | ||
211 | { | ||
212 | for(i=1;i<12;i++) | ||
213 | t[i]++; | ||
214 | } | ||
215 | |||
216 | yd++; | ||
217 | if(yd <= 31) | ||
218 | { | ||
219 | *d = yd; | ||
220 | *m = 0; | ||
221 | } | ||
222 | else | ||
223 | { | ||
224 | for(i=1;i<12;i++) | ||
225 | { | ||
226 | if(yd <= t[i]) | ||
227 | { | ||
228 | *d = yd - t[i-1]; | ||
229 | *m = i; | ||
230 | break; | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | } | ||
diff --git a/firmware/include/timefuncs.h b/firmware/include/timefuncs.h index 45978f4e2e..52d4608287 100644 --- a/firmware/include/timefuncs.h +++ b/firmware/include/timefuncs.h | |||
@@ -29,6 +29,8 @@ | |||
29 | struct tm *get_time(void); | 29 | struct tm *get_time(void); |
30 | int set_time(const struct tm *tm); | 30 | int set_time(const struct tm *tm); |
31 | bool valid_time(const struct tm *tm); | 31 | bool valid_time(const struct tm *tm); |
32 | int day_of_week(int m, int d, int y); | ||
33 | void yearday_to_daymonth(int yd, int y, int *d, int *m); | ||
32 | #if CONFIG_RTC | 34 | #if CONFIG_RTC |
33 | time_t mktime(struct tm *t); | 35 | time_t mktime(struct tm *t); |
34 | #endif | 36 | #endif |
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index d29e731d5a..a6c960422d 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c | |||
@@ -31,6 +31,7 @@ | |||
31 | /* Needed to get at the audio buffer */ | 31 | /* Needed to get at the audio buffer */ |
32 | #include "audio.h" | 32 | #include "audio.h" |
33 | #include "usb_storage.h" | 33 | #include "usb_storage.h" |
34 | #include "timefuncs.h" | ||
34 | 35 | ||
35 | 36 | ||
36 | /* Enable the following define to export only the SD card slot. This | 37 | /* Enable the following define to export only the SD card slot. This |
@@ -68,8 +69,8 @@ | |||
68 | #define USB_BULK_RESET_REQUEST 0xff | 69 | #define USB_BULK_RESET_REQUEST 0xff |
69 | #define USB_BULK_GET_MAX_LUN 0xfe | 70 | #define USB_BULK_GET_MAX_LUN 0xfe |
70 | 71 | ||
71 | #define DIRECT_ACCESS_DEVICE 0x00 /* disks */ | 72 | #define DIRECT_ACCESS_DEVICE 0x00 /* disks */ |
72 | #define DEVICE_REMOVABLE 0x80 | 73 | #define DEVICE_REMOVABLE 0x80 |
73 | 74 | ||
74 | #define CBW_SIGNATURE 0x43425355 | 75 | #define CBW_SIGNATURE 0x43425355 |
75 | #define CSW_SIGNATURE 0x53425355 | 76 | #define CSW_SIGNATURE 0x53425355 |
@@ -86,6 +87,7 @@ | |||
86 | #define SCSI_WRITE_10 0x2a | 87 | #define SCSI_WRITE_10 0x2a |
87 | #define SCSI_START_STOP_UNIT 0x1b | 88 | #define SCSI_START_STOP_UNIT 0x1b |
88 | #define SCSI_REPORT_LUNS 0xa0 | 89 | #define SCSI_REPORT_LUNS 0xa0 |
90 | #define SCSI_WRITE_BUFFER 0x3b | ||
89 | 91 | ||
90 | #define UMS_STATUS_GOOD 0x00 | 92 | #define UMS_STATUS_GOOD 0x00 |
91 | #define UMS_STATUS_FAIL 0x01 | 93 | #define UMS_STATUS_FAIL 0x01 |
@@ -270,6 +272,7 @@ static void send_command_result(void *data,int size); | |||
270 | static void send_command_failed_result(void); | 272 | static void send_command_failed_result(void); |
271 | static void send_block_data(void *data,int size); | 273 | static void send_block_data(void *data,int size); |
272 | static void receive_block_data(void *data,int size); | 274 | static void receive_block_data(void *data,int size); |
275 | static void receive_time(void); | ||
273 | static void fill_inquiry(IF_MD_NONVOID(int lun)); | 276 | static void fill_inquiry(IF_MD_NONVOID(int lun)); |
274 | static void send_and_read_next(void); | 277 | static void send_and_read_next(void); |
275 | static bool ejected[NUM_DRIVES]; | 278 | static bool ejected[NUM_DRIVES]; |
@@ -288,6 +291,7 @@ static enum { | |||
288 | SENDING_RESULT, | 291 | SENDING_RESULT, |
289 | SENDING_FAILED_RESULT, | 292 | SENDING_FAILED_RESULT, |
290 | RECEIVING_BLOCKS, | 293 | RECEIVING_BLOCKS, |
294 | RECEIVING_TIME, | ||
291 | SENDING_CSW | 295 | SENDING_CSW |
292 | } state = WAITING_FOR_COMMAND; | 296 | } state = WAITING_FOR_COMMAND; |
293 | 297 | ||
@@ -459,6 +463,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length) | |||
459 | { | 463 | { |
460 | (void)ep; | 464 | (void)ep; |
461 | struct command_block_wrapper* cbw = (void*)cbw_buffer; | 465 | struct command_block_wrapper* cbw = (void*)cbw_buffer; |
466 | struct tm tm; | ||
462 | 467 | ||
463 | //logf("transfer result %X %d", status, length); | 468 | //logf("transfer result %X %d", status, length); |
464 | switch(state) { | 469 | switch(state) { |
@@ -602,6 +607,19 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length) | |||
602 | cur_sense_data.ascq=0; | 607 | cur_sense_data.ascq=0; |
603 | } | 608 | } |
604 | break; | 609 | break; |
610 | case RECEIVING_TIME: | ||
611 | tm.tm_year=(tb.transfer_buffer[0]<<8)+tb.transfer_buffer[1]; | ||
612 | tm.tm_yday=(tb.transfer_buffer[2]<<8)+tb.transfer_buffer[3]; | ||
613 | tb.transfer_buffer[8]; | ||
614 | tm.tm_hour=tb.transfer_buffer[5]; | ||
615 | tm.tm_min=tb.transfer_buffer[6]; | ||
616 | tm.tm_sec=tb.transfer_buffer[7]; | ||
617 | yearday_to_daymonth(tm.tm_yday,tm.tm_year,&tm.tm_mday,&tm.tm_mon); | ||
618 | tm.tm_wday=day_of_week(tm.tm_mon,tm.tm_mday,tm.tm_year); | ||
619 | tm.tm_year -= 1900; | ||
620 | set_time(&tm); | ||
621 | send_csw(UMS_STATUS_GOOD); | ||
622 | break; | ||
605 | } | 623 | } |
606 | } | 624 | } |
607 | 625 | ||
@@ -1063,6 +1081,21 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
1063 | } | 1081 | } |
1064 | break; | 1082 | break; |
1065 | 1083 | ||
1084 | case SCSI_WRITE_BUFFER: | ||
1085 | if(cbw->command_block[1]==1 | ||
1086 | && cbw->command_block[2]==0 | ||
1087 | && cbw->command_block[3]==0x0c | ||
1088 | && cbw->command_block[4]==0 | ||
1089 | && cbw->command_block[5]==0 | ||
1090 | && cbw->command_block[6]==0 | ||
1091 | && cbw->command_block[7]==0 | ||
1092 | /* Some versions of itunes set the next byte to 0. Technically | ||
1093 | * it should be 0x0c */ | ||
1094 | && (cbw->command_block[8]==0 || cbw->command_block[8]==0x0c) | ||
1095 | && cbw->command_block[9]==0) | ||
1096 | receive_time(); | ||
1097 | break; | ||
1098 | |||
1066 | default: | 1099 | default: |
1067 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); | 1100 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); |
1068 | send_csw(UMS_STATUS_FAIL); | 1101 | send_csw(UMS_STATUS_FAIL); |
@@ -1091,6 +1124,11 @@ static void send_command_failed_result(void) | |||
1091 | state = SENDING_FAILED_RESULT; | 1124 | state = SENDING_FAILED_RESULT; |
1092 | } | 1125 | } |
1093 | 1126 | ||
1127 | static void receive_time(void) | ||
1128 | { | ||
1129 | usb_drv_recv(ep_out, tb.transfer_buffer, 12); | ||
1130 | state = RECEIVING_TIME; | ||
1131 | } | ||
1094 | static void receive_block_data(void *data,int size) | 1132 | static void receive_block_data(void *data,int size) |
1095 | { | 1133 | { |
1096 | usb_drv_recv(ep_out, data, size); | 1134 | usb_drv_recv(ep_out, data, size); |